git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26229 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Oliver Ruiz Dorantes 2008-07-02 20:59:57 +00:00
parent c8bc2d8897
commit 848c65ab3e
10 changed files with 2063 additions and 2063 deletions

View File

@ -1,43 +1,43 @@
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
#ifndef _H2CFG_H_
#define _H2CFG_H_
#define BT_DRIVER_SUPPORTS_CMD 1
#define BT_DRIVER_SUPPORTS_EVT 1
#define BT_DRIVER_SUPPORTS_ESCO 0
#define BT_DRIVER_SUPPORTS_SCO 0
#define BT_DRIVER_SUPPORTS_ACL 0
/* TODO: move exclusive header for drivers*/
#define BT_DRIVER_RXCOVERAGE (BT_DRIVER_SUPPORTS_EVT+BT_DRIVER_SUPPORTS_ACL+BT_DRIVER_SUPPORTS_SCO+BT_DRIVER_SUPPORTS_ESCO)
#define BT_DRIVER_TXCOVERAGE (BT_DRIVER_SUPPORTS_CMD+BT_DRIVER_SUPPORTS_ACL+BT_DRIVER_SUPPORTS_SCO+BT_DRIVER_SUPPORTS_ESCO)
#if BT_DRIVER_RXCOVERAGE<1 || BT_DRIVER_TXCOVERAGE<1
#error incomplete Bluetooth driver Commands and Events should be implemented
#endif
#define BT_SURVIVE_WITHOUT_HCI
#define BT_SURVIVE_WITHOUT_NET_BUFFERS
////////////////////////////////////
#ifndef BLUETOOTH_DEVICE_TRANSPORT
#error BLUETOOTH_DEVICE_TRANSPORT must be defined to build the publishing path
#endif
#ifndef BLUETOOTH_DEVICE_NAME
#error BLUETOOTH_DEVICE_NAME must be defined to build the publishing path
#endif
#define BLUETOOTH_DEVICE_DEVFS_NAME BLUETOOTH_DEVICE_TRANSPORT BLUETOOTH_DEVICE_NAME
#define BLUETOOTH_DEVICE_PATH "bluetooth/" BLUETOOTH_DEVICE_DEVFS_NAME
#endif
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
#ifndef _H2CFG_H_
#define _H2CFG_H_
#define BT_DRIVER_SUPPORTS_CMD 1
#define BT_DRIVER_SUPPORTS_EVT 1
#define BT_DRIVER_SUPPORTS_ESCO 0
#define BT_DRIVER_SUPPORTS_SCO 0
#define BT_DRIVER_SUPPORTS_ACL 0
/* TODO: move exclusive header for drivers*/
#define BT_DRIVER_RXCOVERAGE (BT_DRIVER_SUPPORTS_EVT+BT_DRIVER_SUPPORTS_ACL+BT_DRIVER_SUPPORTS_SCO+BT_DRIVER_SUPPORTS_ESCO)
#define BT_DRIVER_TXCOVERAGE (BT_DRIVER_SUPPORTS_CMD+BT_DRIVER_SUPPORTS_ACL+BT_DRIVER_SUPPORTS_SCO+BT_DRIVER_SUPPORTS_ESCO)
#if BT_DRIVER_RXCOVERAGE<1 || BT_DRIVER_TXCOVERAGE<1
#error incomplete Bluetooth driver Commands and Events should be implemented
#endif
#define BT_SURVIVE_WITHOUT_HCI
#define BT_SURVIVE_WITHOUT_NET_BUFFERS
////////////////////////////////////
#ifndef BLUETOOTH_DEVICE_TRANSPORT
#error BLUETOOTH_DEVICE_TRANSPORT must be defined to build the publishing path
#endif
#ifndef BLUETOOTH_DEVICE_NAME
#error BLUETOOTH_DEVICE_NAME must be defined to build the publishing path
#endif
#define BLUETOOTH_DEVICE_DEVFS_NAME BLUETOOTH_DEVICE_TRANSPORT BLUETOOTH_DEVICE_NAME
#define BLUETOOTH_DEVICE_PATH "bluetooth/" BLUETOOTH_DEVICE_DEVFS_NAME
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,458 +1,458 @@
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
#include "h2generic.h"
#include "h2transactions.h"
#include "h2upper.h"
#include "h2util.h"
#include <bluetooth/HCI/btHCI.h>
#include <bluetooth/HCI/btHCI_event.h>
#include <bluetooth/HCI/btHCI_acl.h>
#include <ByteOrder.h>
#include <string.h>
#define BT_DEBUG_THIS_MODULE
#include <btDebug.h>
/* Forward declaration */
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
void acl_tx_complete(void* cookie, uint32 status, void* data, uint32 actual_len);
void acl_rx_complete(void* cookie, uint32 status, void* data, uint32 actual_len);
void command_complete(void* cookie, uint32 status, void* data, uint32 actual_len);
void event_complete(void* cookie, uint32 status, void* data, uint32 actual_len);
#else
void acl_tx_complete(void* cookie, status_t status, void* data, size_t actual_len);
void acl_rx_complete(void* cookie, status_t status, void* data, size_t actual_len);
void command_complete(void* cookie, status_t status, void* data, size_t actual_len);
void event_complete(void* cookie, status_t status, void* data, size_t actual_len);
#endif
static status_t
assembly_rx(bt_usb_dev* bdev, bt_packet_t type, void *data, int count)
{
net_buffer* nbuf = NULL;
snet_buffer* snbuf = NULL;
size_t currentPacketLen = 0;
size_t expectedPacketLen = 0;
bdev->stat.bytesRX += count;
if (type == BT_EVENT)
snbuf = bdev->eventRx;
else
nbuf = bdev->nbufferRx[type];
while (count) {
debugf("count %d %p %p\n",count, nbuf, nb);
if ( (type != BT_EVENT && nbuf == NULL) ||
(type == BT_EVENT && (snbuf == NULL || snb_completed(snbuf))) ) {
/* new buffer incoming */
switch (type) {
case BT_EVENT:
if (count >= HCI_EVENT_HDR_SIZE) {
struct hci_event_header* headerPkt = data;
expectedPacketLen = HCI_EVENT_HDR_SIZE + headerPkt->elen;
snbuf = bdev->eventRx = snb_fetch(&bdev->snetBufferRecycleTrash, expectedPacketLen);
} else {
flowf("EVENT frame corrupted\n");
return -EILSEQ;
}
break;
case BT_ACL:
if (count >= HCI_ACL_HDR_SIZE) {
struct hci_acl_header* headerPkt = data;
expectedPacketLen = HCI_ACL_HDR_SIZE + B_LENDIAN_TO_HOST_INT16(headerPkt->alen);
/* Create the buffer */
bdev->nbufferRx[type] = nbuf = nb->create(expectedPacketLen);
nbuf->protocol = type;
} else {
flowf("ACL frame corrupted\n");
return -EILSEQ;
}
break;
case BT_SCO:
break;
default:
panic("unkown packet type in assembly");
break;
}
#if 0
if (nb == NULL) {
port_id port;
/* Coded for test purpose only we should panic here */
debugf("net_buffers are not ready post manually %d/%d\n",count,expectedPacketLen);
port = find_port(BT_USERLAND_PORT_NAME);
if (port != B_NAME_NOT_FOUND) {
(void)write_port(port, PACK_HEADER_PORT(bdev->num,type), data, count);
return B_OK;
}
panic("Algorithm just ready to arrive here");
return B_ERROR;
}
#endif
currentPacketLen = expectedPacketLen;
}
else {
/* Continuation */
if (type != BT_EVENT)
currentPacketLen = get_expected_size(nbuf) - nbuf->size;
else
currentPacketLen = snb_remaining_to_put(snbuf);
}
currentPacketLen = min(currentPacketLen, count);
if (type == BT_EVENT)
snb_put(snbuf, data, currentPacketLen);
else
nb->append(nbuf, data, currentPacketLen);
/* Complete frame? */
if (type == BT_EVENT && snb_completed(snbuf)) {
flowf("Frame goes up!\n");
post_packet_up(bdev, type, snbuf);
snbuf = bdev->eventRx = NULL;
}
if (type != BT_EVENT && (get_expected_size(nbuf) - nbuf->size) == 0 ) {
flowf("Frame goes up!\n");
post_packet_up(bdev, type, nbuf);
bdev->nbufferRx[type] = nbuf = NULL;
}
/* in case in the pipe there is info about the next buffer ... */
count -= currentPacketLen;
data += currentPacketLen;
}
return B_OK;
}
#if 0
#pragma mark --- RX Complete ---
#endif
void
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
event_complete(void* cookie, uint32 status, void* data, uint32 actual_len)
#else
event_complete(void* cookie, status_t status, void* data, size_t actual_len)
#endif
{
bt_usb_dev* bdev = cookie;
status_t err;
/* TODO: or not running anymore */
if (status == B_CANCELED)
return;
if (status != B_OK || actual_len == 0)
goto resubmit;
if ( assembly_rx(cookie, BT_EVENT, data, actual_len) == B_OK ) {
bdev->stat.successfulTX++;
} else {
bdev->stat.errorRX++;
}
resubmit:
err = usb->queue_interrupt(bdev->intr_in_ep->handle,
data, bdev->max_packet_size_intr_in ,
event_complete, bdev);
if (err != B_OK ) {
reuse_room(&bdev->eventRoom, data);
bdev->stat.rejectedRX++;
debugf("RX event resubmittion failed %s\n",strerror(err));
}
else {
bdev->stat.acceptedRX++;
}
}
void
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
acl_rx_complete(void* cookie, uint32 status, void* data, uint32 actual_len)
#else
acl_rx_complete(void* cookie, status_t status, void* data, size_t actual_len)
#endif
{
bt_usb_dev* bdev = cookie;
status_t err;
/* TODO: or not running anymore? */
if (status == B_CANCELED)
return;
if (status != B_OK || actual_len == 0)
goto resubmit;
if ( assembly_rx(cookie, BT_ACL, data, actual_len) == B_OK ) {
bdev->stat.successfulRX++;
} else {
bdev->stat.errorRX++;
}
resubmit:
err = usb->queue_bulk(bdev->bulk_in_ep->handle, data,
max(HCI_MAX_FRAME_SIZE,bdev->max_packet_size_bulk_in),
acl_rx_complete, (void*) bdev);
if (err != B_OK ) {
reuse_room(&bdev->aclRoom, data);
bdev->stat.rejectedRX++;
debugf("RX acl resubmittion failed %s\n", strerror(err));
}
else {
bdev->stat.acceptedRX++;
}
}
#if 0
#pragma mark --- RX ---
#endif
status_t
submit_rx_event(bt_usb_dev* bdev)
{
status_t err;
size_t size = bdev->max_packet_size_intr_in;
void* buf = alloc_room(&bdev->eventRoom, size);
if (buf == NULL)
return ENOMEM;
err = usb->queue_interrupt(bdev->intr_in_ep->handle,
buf, size ,
event_complete, (void*) bdev);
if (err != B_OK ) {
reuse_room(&bdev->eventRoom, buf);
bdev->stat.rejectedRX++;
}
else {
bdev->stat.acceptedRX++;
debugf("Accepted RX Event %d\n", bdev->stat.acceptedRX);
}
return err;
}
status_t
submit_rx_acl(bt_usb_dev* bdev)
{
status_t err;
size_t size = max(HCI_MAX_FRAME_SIZE,bdev->max_packet_size_bulk_in);
void* buf = alloc_room(&bdev->aclRoom, size);
if (buf == NULL)
return ENOMEM;
err = usb->queue_bulk(bdev->bulk_in_ep->handle, buf, size ,
acl_rx_complete, bdev);
if (err != B_OK ) {
reuse_room(&bdev->aclRoom, buf);
bdev->stat.rejectedRX++;
}
else {
bdev->stat.acceptedRX++;
}
return B_ERROR;
}
status_t
submit_rx_sco(bt_usb_dev* bdev)
{
/* not yet implemented */
return B_ERROR;
}
#if 0
#pragma mark --- TX Complete ---
#endif
void
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
command_complete(void* cookie, uint32 status, void* data, uint32 actual_len)
#else
command_complete(void* cookie, status_t status, void* data, size_t actual_len)
#endif
{
snet_buffer* snbuf = (snet_buffer*) cookie;
bt_usb_dev* bdev = snb_cookie(snbuf);
debugf("%ld %02x:%02x:%02x:\n", actual_len, ((uint8*)data)[0],((uint8*)data)[1],((uint8*)data)[2]);
if (status != B_OK) {
bdev->stat.successfulTX++;
bdev->stat.bytesTX += actual_len;
}
else {
bdev->stat.errorTX++;
/* the packet has been lost */
/* too late to requeue it? */
}
snb_park(&bdev->snetBufferRecycleTrash, snbuf);
#ifdef BT_RESCHEDULING_AFTER_COMPLETITIONS
// TODO: check just the empty queues?
schedTxProcessing(bdev);
#endif
}
void
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
acl_tx_complete(void* cookie, uint32 status, void* data, uint32 actual_len)
#else
acl_tx_complete(void* cookie, status_t status, void* data, size_t actual_len)
#endif
{
net_buffer* nbuf = (net_buffer*) cookie;
bt_usb_dev* bdev = GET_DEVICE(nbuf);
if (status != B_OK) {
bdev->stat.successfulTX++;
bdev->stat.bytesTX += actual_len;
}
else {
bdev->stat.errorTX++;
/* the packet has been lost */
/* too late to requeue it? */
}
nb_destroy(nbuf);
#ifdef BT_RESCHEDULING_AFTER_COMPLETITIONS
schedTxProcessing(bdev);
#endif
}
#if 0
#pragma mark --- TX ---
#endif
status_t
submit_tx_command(bt_usb_dev* bdev, snet_buffer* snbuf)
{
status_t err;
uint8 bRequestType = bdev->ctrl_req;
uint8 bRequest = 0;
uint16 wIndex = 0;
uint16 value = 0;
uint16 wLength = B_HOST_TO_LENDIAN_INT16(snb_size(snbuf));
if (!GET_BIT(bdev->state, RUNNING) ) {
return B_DEV_NOT_READY;
}
/* set cookie */
snb_set_cookie(snbuf, bdev);
err = usb->queue_request(bdev->dev, bRequestType, bRequest,
value, wIndex, wLength,
snb_get(snbuf), wLength //???
,command_complete, (void*) snbuf);
if (err != B_OK ) {
bdev->stat.rejectedTX++;
}
else {
bdev->stat.acceptedTX++;
}
return err;
}
status_t
submit_tx_acl(bt_usb_dev* bdev, net_buffer* nbuf)
{
status_t err;
/* set cookie */
SET_DEVICE(nbuf,bdev->hdev);
if (!GET_BIT(bdev->state, RUNNING) ) {
return B_DEV_NOT_READY;
}
err = usb->queue_bulk(bdev->bulk_out_ep->handle,
nb_get_whole_buffer(nbuf), nbuf->size,
acl_tx_complete, (void*) nbuf);
if (err != B_OK ) {
bdev->stat.rejectedTX++;
}
else {
bdev->stat.acceptedTX++;
}
return err;
}
status_t
submit_tx_sco(bt_usb_dev* bdev)
{
if (!GET_BIT(bdev->state, RUNNING) ) {
return B_DEV_NOT_READY;
}
/* not yet implemented */
return B_ERROR;
}
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
#include "h2generic.h"
#include "h2transactions.h"
#include "h2upper.h"
#include "h2util.h"
#include <bluetooth/HCI/btHCI.h>
#include <bluetooth/HCI/btHCI_event.h>
#include <bluetooth/HCI/btHCI_acl.h>
#include <ByteOrder.h>
#include <string.h>
#define BT_DEBUG_THIS_MODULE
#include <btDebug.h>
/* Forward declaration */
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
void acl_tx_complete(void* cookie, uint32 status, void* data, uint32 actual_len);
void acl_rx_complete(void* cookie, uint32 status, void* data, uint32 actual_len);
void command_complete(void* cookie, uint32 status, void* data, uint32 actual_len);
void event_complete(void* cookie, uint32 status, void* data, uint32 actual_len);
#else
void acl_tx_complete(void* cookie, status_t status, void* data, size_t actual_len);
void acl_rx_complete(void* cookie, status_t status, void* data, size_t actual_len);
void command_complete(void* cookie, status_t status, void* data, size_t actual_len);
void event_complete(void* cookie, status_t status, void* data, size_t actual_len);
#endif
static status_t
assembly_rx(bt_usb_dev* bdev, bt_packet_t type, void *data, int count)
{
net_buffer* nbuf = NULL;
snet_buffer* snbuf = NULL;
size_t currentPacketLen = 0;
size_t expectedPacketLen = 0;
bdev->stat.bytesRX += count;
if (type == BT_EVENT)
snbuf = bdev->eventRx;
else
nbuf = bdev->nbufferRx[type];
while (count) {
debugf("count %d %p %p\n",count, nbuf, nb);
if ( (type != BT_EVENT && nbuf == NULL) ||
(type == BT_EVENT && (snbuf == NULL || snb_completed(snbuf))) ) {
/* new buffer incoming */
switch (type) {
case BT_EVENT:
if (count >= HCI_EVENT_HDR_SIZE) {
struct hci_event_header* headerPkt = data;
expectedPacketLen = HCI_EVENT_HDR_SIZE + headerPkt->elen;
snbuf = bdev->eventRx = snb_fetch(&bdev->snetBufferRecycleTrash, expectedPacketLen);
} else {
flowf("EVENT frame corrupted\n");
return -EILSEQ;
}
break;
case BT_ACL:
if (count >= HCI_ACL_HDR_SIZE) {
struct hci_acl_header* headerPkt = data;
expectedPacketLen = HCI_ACL_HDR_SIZE + B_LENDIAN_TO_HOST_INT16(headerPkt->alen);
/* Create the buffer */
bdev->nbufferRx[type] = nbuf = nb->create(expectedPacketLen);
nbuf->protocol = type;
} else {
flowf("ACL frame corrupted\n");
return -EILSEQ;
}
break;
case BT_SCO:
break;
default:
panic("unkown packet type in assembly");
break;
}
#if 0
if (nb == NULL) {
port_id port;
/* Coded for test purpose only we should panic here */
debugf("net_buffers are not ready post manually %d/%d\n",count,expectedPacketLen);
port = find_port(BT_USERLAND_PORT_NAME);
if (port != B_NAME_NOT_FOUND) {
(void)write_port(port, PACK_HEADER_PORT(bdev->num,type), data, count);
return B_OK;
}
panic("Algorithm just ready to arrive here");
return B_ERROR;
}
#endif
currentPacketLen = expectedPacketLen;
}
else {
/* Continuation */
if (type != BT_EVENT)
currentPacketLen = get_expected_size(nbuf) - nbuf->size;
else
currentPacketLen = snb_remaining_to_put(snbuf);
}
currentPacketLen = min(currentPacketLen, count);
if (type == BT_EVENT)
snb_put(snbuf, data, currentPacketLen);
else
nb->append(nbuf, data, currentPacketLen);
/* Complete frame? */
if (type == BT_EVENT && snb_completed(snbuf)) {
flowf("Frame goes up!\n");
post_packet_up(bdev, type, snbuf);
snbuf = bdev->eventRx = NULL;
}
if (type != BT_EVENT && (get_expected_size(nbuf) - nbuf->size) == 0 ) {
flowf("Frame goes up!\n");
post_packet_up(bdev, type, nbuf);
bdev->nbufferRx[type] = nbuf = NULL;
}
/* in case in the pipe there is info about the next buffer ... */
count -= currentPacketLen;
data += currentPacketLen;
}
return B_OK;
}
#if 0
#pragma mark --- RX Complete ---
#endif
void
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
event_complete(void* cookie, uint32 status, void* data, uint32 actual_len)
#else
event_complete(void* cookie, status_t status, void* data, size_t actual_len)
#endif
{
bt_usb_dev* bdev = cookie;
status_t err;
/* TODO: or not running anymore */
if (status == B_CANCELED)
return;
if (status != B_OK || actual_len == 0)
goto resubmit;
if ( assembly_rx(cookie, BT_EVENT, data, actual_len) == B_OK ) {
bdev->stat.successfulTX++;
} else {
bdev->stat.errorRX++;
}
resubmit:
err = usb->queue_interrupt(bdev->intr_in_ep->handle,
data, bdev->max_packet_size_intr_in ,
event_complete, bdev);
if (err != B_OK ) {
reuse_room(&bdev->eventRoom, data);
bdev->stat.rejectedRX++;
debugf("RX event resubmittion failed %s\n",strerror(err));
}
else {
bdev->stat.acceptedRX++;
}
}
void
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
acl_rx_complete(void* cookie, uint32 status, void* data, uint32 actual_len)
#else
acl_rx_complete(void* cookie, status_t status, void* data, size_t actual_len)
#endif
{
bt_usb_dev* bdev = cookie;
status_t err;
/* TODO: or not running anymore? */
if (status == B_CANCELED)
return;
if (status != B_OK || actual_len == 0)
goto resubmit;
if ( assembly_rx(cookie, BT_ACL, data, actual_len) == B_OK ) {
bdev->stat.successfulRX++;
} else {
bdev->stat.errorRX++;
}
resubmit:
err = usb->queue_bulk(bdev->bulk_in_ep->handle, data,
max(HCI_MAX_FRAME_SIZE,bdev->max_packet_size_bulk_in),
acl_rx_complete, (void*) bdev);
if (err != B_OK ) {
reuse_room(&bdev->aclRoom, data);
bdev->stat.rejectedRX++;
debugf("RX acl resubmittion failed %s\n", strerror(err));
}
else {
bdev->stat.acceptedRX++;
}
}
#if 0
#pragma mark --- RX ---
#endif
status_t
submit_rx_event(bt_usb_dev* bdev)
{
status_t err;
size_t size = bdev->max_packet_size_intr_in;
void* buf = alloc_room(&bdev->eventRoom, size);
if (buf == NULL)
return ENOMEM;
err = usb->queue_interrupt(bdev->intr_in_ep->handle,
buf, size ,
event_complete, (void*) bdev);
if (err != B_OK ) {
reuse_room(&bdev->eventRoom, buf);
bdev->stat.rejectedRX++;
}
else {
bdev->stat.acceptedRX++;
debugf("Accepted RX Event %d\n", bdev->stat.acceptedRX);
}
return err;
}
status_t
submit_rx_acl(bt_usb_dev* bdev)
{
status_t err;
size_t size = max(HCI_MAX_FRAME_SIZE,bdev->max_packet_size_bulk_in);
void* buf = alloc_room(&bdev->aclRoom, size);
if (buf == NULL)
return ENOMEM;
err = usb->queue_bulk(bdev->bulk_in_ep->handle, buf, size ,
acl_rx_complete, bdev);
if (err != B_OK ) {
reuse_room(&bdev->aclRoom, buf);
bdev->stat.rejectedRX++;
}
else {
bdev->stat.acceptedRX++;
}
return B_ERROR;
}
status_t
submit_rx_sco(bt_usb_dev* bdev)
{
/* not yet implemented */
return B_ERROR;
}
#if 0
#pragma mark --- TX Complete ---
#endif
void
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
command_complete(void* cookie, uint32 status, void* data, uint32 actual_len)
#else
command_complete(void* cookie, status_t status, void* data, size_t actual_len)
#endif
{
snet_buffer* snbuf = (snet_buffer*) cookie;
bt_usb_dev* bdev = snb_cookie(snbuf);
debugf("%ld %02x:%02x:%02x:\n", actual_len, ((uint8*)data)[0],((uint8*)data)[1],((uint8*)data)[2]);
if (status != B_OK) {
bdev->stat.successfulTX++;
bdev->stat.bytesTX += actual_len;
}
else {
bdev->stat.errorTX++;
/* the packet has been lost */
/* too late to requeue it? */
}
snb_park(&bdev->snetBufferRecycleTrash, snbuf);
#ifdef BT_RESCHEDULING_AFTER_COMPLETITIONS
// TODO: check just the empty queues?
schedTxProcessing(bdev);
#endif
}
void
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
acl_tx_complete(void* cookie, uint32 status, void* data, uint32 actual_len)
#else
acl_tx_complete(void* cookie, status_t status, void* data, size_t actual_len)
#endif
{
net_buffer* nbuf = (net_buffer*) cookie;
bt_usb_dev* bdev = GET_DEVICE(nbuf);
if (status != B_OK) {
bdev->stat.successfulTX++;
bdev->stat.bytesTX += actual_len;
}
else {
bdev->stat.errorTX++;
/* the packet has been lost */
/* too late to requeue it? */
}
nb_destroy(nbuf);
#ifdef BT_RESCHEDULING_AFTER_COMPLETITIONS
schedTxProcessing(bdev);
#endif
}
#if 0
#pragma mark --- TX ---
#endif
status_t
submit_tx_command(bt_usb_dev* bdev, snet_buffer* snbuf)
{
status_t err;
uint8 bRequestType = bdev->ctrl_req;
uint8 bRequest = 0;
uint16 wIndex = 0;
uint16 value = 0;
uint16 wLength = B_HOST_TO_LENDIAN_INT16(snb_size(snbuf));
if (!GET_BIT(bdev->state, RUNNING) ) {
return B_DEV_NOT_READY;
}
/* set cookie */
snb_set_cookie(snbuf, bdev);
err = usb->queue_request(bdev->dev, bRequestType, bRequest,
value, wIndex, wLength,
snb_get(snbuf), wLength //???
,command_complete, (void*) snbuf);
if (err != B_OK ) {
bdev->stat.rejectedTX++;
}
else {
bdev->stat.acceptedTX++;
}
return err;
}
status_t
submit_tx_acl(bt_usb_dev* bdev, net_buffer* nbuf)
{
status_t err;
/* set cookie */
SET_DEVICE(nbuf,bdev->hdev);
if (!GET_BIT(bdev->state, RUNNING) ) {
return B_DEV_NOT_READY;
}
err = usb->queue_bulk(bdev->bulk_out_ep->handle,
nb_get_whole_buffer(nbuf), nbuf->size,
acl_tx_complete, (void*) nbuf);
if (err != B_OK ) {
bdev->stat.rejectedTX++;
}
else {
bdev->stat.acceptedTX++;
}
return err;
}
status_t
submit_tx_sco(bt_usb_dev* bdev)
{
if (!GET_BIT(bdev->state, RUNNING) ) {
return B_DEV_NOT_READY;
}
/* not yet implemented */
return B_ERROR;
}

View File

@ -1,21 +1,21 @@
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
#ifndef _H2TRANSACTION_H_
#define _H2TRANSACTION_H_
#include "h2generic.h"
status_t submit_rx_event(bt_usb_dev* bdev);
status_t submit_rx_acl(bt_usb_dev* bdev);
status_t submit_rx_sco(bt_usb_dev* bdev);
status_t submit_tx_command(bt_usb_dev* bdev, snet_buffer* snbuf);
status_t submit_tx_acl(bt_usb_dev* bdev, net_buffer* nbuf);
status_t submit_tx_sco(bt_usb_dev* bdev);
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
#ifndef _H2TRANSACTION_H_
#define _H2TRANSACTION_H_
#include "h2generic.h"
status_t submit_rx_event(bt_usb_dev* bdev);
status_t submit_rx_acl(bt_usb_dev* bdev);
status_t submit_rx_sco(bt_usb_dev* bdev);
status_t submit_tx_command(bt_usb_dev* bdev, snet_buffer* snbuf);
status_t submit_tx_acl(bt_usb_dev* bdev, net_buffer* nbuf);
status_t submit_tx_sco(bt_usb_dev* bdev);
#endif

View File

@ -1,203 +1,203 @@
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
#include <string.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/HCI/btHCI_transport.h>
#include "h2upper.h"
#include "h2transactions.h"
#include "snet_buffer.h"
#define BT_DEBUG_THIS_MODULE
#include <btDebug.h>
/* TODO: split for commands and comunication(ACL&SCO) */
void
sched_tx_processing(bt_usb_dev* bdev)
{
net_buffer* nbuf;
snet_buffer* snbuf;
status_t err;
flowf("sched\n")
if (!TEST_AND_SET(&bdev->state, PROCESSING)) {
/* We are not processing in another thread so... START!! */
do {
/* Do while this bit is on... so someone should set it before we stop the iterations*/
CLEAR_BIT(bdev->state, SENDING);
/* check Commands*/
#ifdef EMPTY_COMMAND_QUEUE
while (!list_is_empty(&bdev->nbuffersTx[BT_COMMAND]) ) {
#else
if (!list_is_empty(&bdev->nbuffersTx[BT_COMMAND]) ) {
#endif
snbuf = list_remove_head_item(&bdev->nbuffersTx[BT_COMMAND]);
err = submit_tx_command(bdev, snbuf);
if (err != B_OK) {
/* re-head it*/
list_insert_item_before(&bdev->nbuffersTx[BT_COMMAND],
list_get_first_item(&bdev->nbuffersTx[BT_COMMAND]), snbuf);
}
}
/* check Acl */
#define EMPTY_ACL_QUEUE
#ifdef EMPTY_ACL_QUEUE
while (!list_is_empty(&bdev->nbuffersTx[BT_ACL]) ) {
#else
if (!list_is_empty(&bdev->nbuffersTx[BT_ACL]) ) {
#endif
nbuf = list_remove_head_item(&bdev->nbuffersTx[BT_ACL]);
err = submit_tx_acl(bdev, nbuf);
if (err != B_OK) {
/* re-head it*/
list_insert_item_before(&bdev->nbuffersTx[BT_ACL],
list_get_first_item(&bdev->nbuffersTx[BT_ACL]), nbuf);
}
}
if (!list_is_empty(&bdev->nbuffersTx[BT_SCO]) ) {
/* TODO to be implemented */
}
} while (GET_BIT(bdev->state, SENDING));
CLEAR_BIT(bdev->state, PROCESSING);
} else {
/* We are processing so MARK that we need to still go on with that ... */
SET_BIT(bdev->state, SENDING);
}
}
status_t
post_packet_up(bt_usb_dev* bdev, bt_packet_t type, void* buf)
{
status_t err = B_OK;
port_id port;
if (hci == NULL) {
err = B_ERROR;
// ERROR but we will try to send if its a event!
if (type == BT_EVENT) {
snet_buffer* snbuf = (snet_buffer*) buf;
flowf("HCI not present, Posting to userland\n");
port = find_port(BT_USERLAND_PORT_NAME);
if (port != B_NAME_NOT_FOUND) {
err = write_port_etc(port, PACK_PORTCODE(type,bdev->hdev, -1),
snb_get(snbuf), snb_size(snbuf), B_TIMEOUT, 1*1000*1000);
if (err != B_OK)
debugf("Error posting userland %s\n", strerror(err));
}
else {
flowf("ERROR:bluetooth_server not found for posting\n");
err = B_NAME_NOT_FOUND;
}
/* No need to free the buffer at allocation is gonna be reused */
}
}
else {
// TODO: Upper layer comunication
/* Not freeing because is being used by upper layers*/
}
return err;
}
status_t
send_packet(hci_id hid, bt_packet_t type, net_buffer* nbuf)
{
bt_usb_dev* bdev = fetch_device(NULL, hid);
status_t err = B_OK;
if (bdev == NULL)
return B_ERROR;
// TODO: check if device is actually ready for this
// TODO: Lock Device
if (nbuf != NULL) {
if (type != nbuf->protocol) // a bit strict maybe?
panic("Upper layer has not filled correctly a packet");
switch (type) {
case BT_COMMAND:
case BT_ACL:
case BT_SCO:
list_add_item(&bdev->nbuffersTx[type],nbuf);
bdev->nbuffersPendingTx[type]++;
break;
default:
debugf("Unkown packet type for sending %d\n",type);
// TODO: free the net_buffer -> no, allow upper layer
// handle it with the given error
err = B_BAD_VALUE;
break;
}
} else {
flowf("tx sched provoked");
}
// TODO: check if device is actually ready for this
// TODO: unLock device
/* sched in All cases even if nbuf is null (hidden way to provoke re-scheduling)*/
sched_tx_processing(bdev);
return err;
}
status_t
send_command(hci_id hid, snet_buffer* snbuf)
{
bt_usb_dev* bdev = fetch_device(NULL, hid);
status_t err = B_OK;
if (bdev == NULL)
return B_ERROR;
// TODO: check if device is actually ready for this
// TODO: mutex?
if (snbuf != NULL) {
list_add_item(&bdev->nbuffersTx[BT_COMMAND],snbuf);
bdev->nbuffersPendingTx[BT_COMMAND]++;
} else {
err = B_BAD_VALUE;
flowf("tx sched provoked");
}
// TODO: check if device is actually ready for this
// TODO: mutex?
/* sched in All cases even if nbuf is null (hidden way to provoke re-scheduling)*/
sched_tx_processing(bdev);
return err;
}
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
#include <string.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/HCI/btHCI_transport.h>
#include "h2upper.h"
#include "h2transactions.h"
#include "snet_buffer.h"
#define BT_DEBUG_THIS_MODULE
#include <btDebug.h>
/* TODO: split for commands and comunication(ACL&SCO) */
void
sched_tx_processing(bt_usb_dev* bdev)
{
net_buffer* nbuf;
snet_buffer* snbuf;
status_t err;
flowf("sched\n")
if (!TEST_AND_SET(&bdev->state, PROCESSING)) {
/* We are not processing in another thread so... START!! */
do {
/* Do while this bit is on... so someone should set it before we stop the iterations*/
CLEAR_BIT(bdev->state, SENDING);
/* check Commands*/
#ifdef EMPTY_COMMAND_QUEUE
while (!list_is_empty(&bdev->nbuffersTx[BT_COMMAND]) ) {
#else
if (!list_is_empty(&bdev->nbuffersTx[BT_COMMAND]) ) {
#endif
snbuf = list_remove_head_item(&bdev->nbuffersTx[BT_COMMAND]);
err = submit_tx_command(bdev, snbuf);
if (err != B_OK) {
/* re-head it*/
list_insert_item_before(&bdev->nbuffersTx[BT_COMMAND],
list_get_first_item(&bdev->nbuffersTx[BT_COMMAND]), snbuf);
}
}
/* check Acl */
#define EMPTY_ACL_QUEUE
#ifdef EMPTY_ACL_QUEUE
while (!list_is_empty(&bdev->nbuffersTx[BT_ACL]) ) {
#else
if (!list_is_empty(&bdev->nbuffersTx[BT_ACL]) ) {
#endif
nbuf = list_remove_head_item(&bdev->nbuffersTx[BT_ACL]);
err = submit_tx_acl(bdev, nbuf);
if (err != B_OK) {
/* re-head it*/
list_insert_item_before(&bdev->nbuffersTx[BT_ACL],
list_get_first_item(&bdev->nbuffersTx[BT_ACL]), nbuf);
}
}
if (!list_is_empty(&bdev->nbuffersTx[BT_SCO]) ) {
/* TODO to be implemented */
}
} while (GET_BIT(bdev->state, SENDING));
CLEAR_BIT(bdev->state, PROCESSING);
} else {
/* We are processing so MARK that we need to still go on with that ... */
SET_BIT(bdev->state, SENDING);
}
}
status_t
post_packet_up(bt_usb_dev* bdev, bt_packet_t type, void* buf)
{
status_t err = B_OK;
port_id port;
if (hci == NULL) {
err = B_ERROR;
// ERROR but we will try to send if its a event!
if (type == BT_EVENT) {
snet_buffer* snbuf = (snet_buffer*) buf;
flowf("HCI not present, Posting to userland\n");
port = find_port(BT_USERLAND_PORT_NAME);
if (port != B_NAME_NOT_FOUND) {
err = write_port_etc(port, PACK_PORTCODE(type,bdev->hdev, -1),
snb_get(snbuf), snb_size(snbuf), B_TIMEOUT, 1*1000*1000);
if (err != B_OK)
debugf("Error posting userland %s\n", strerror(err));
}
else {
flowf("ERROR:bluetooth_server not found for posting\n");
err = B_NAME_NOT_FOUND;
}
/* No need to free the buffer at allocation is gonna be reused */
}
}
else {
// TODO: Upper layer comunication
/* Not freeing because is being used by upper layers*/
}
return err;
}
status_t
send_packet(hci_id hid, bt_packet_t type, net_buffer* nbuf)
{
bt_usb_dev* bdev = fetch_device(NULL, hid);
status_t err = B_OK;
if (bdev == NULL)
return B_ERROR;
// TODO: check if device is actually ready for this
// TODO: Lock Device
if (nbuf != NULL) {
if (type != nbuf->protocol) // a bit strict maybe?
panic("Upper layer has not filled correctly a packet");
switch (type) {
case BT_COMMAND:
case BT_ACL:
case BT_SCO:
list_add_item(&bdev->nbuffersTx[type],nbuf);
bdev->nbuffersPendingTx[type]++;
break;
default:
debugf("Unkown packet type for sending %d\n",type);
// TODO: free the net_buffer -> no, allow upper layer
// handle it with the given error
err = B_BAD_VALUE;
break;
}
} else {
flowf("tx sched provoked");
}
// TODO: check if device is actually ready for this
// TODO: unLock device
/* sched in All cases even if nbuf is null (hidden way to provoke re-scheduling)*/
sched_tx_processing(bdev);
return err;
}
status_t
send_command(hci_id hid, snet_buffer* snbuf)
{
bt_usb_dev* bdev = fetch_device(NULL, hid);
status_t err = B_OK;
if (bdev == NULL)
return B_ERROR;
// TODO: check if device is actually ready for this
// TODO: mutex?
if (snbuf != NULL) {
list_add_item(&bdev->nbuffersTx[BT_COMMAND],snbuf);
bdev->nbuffersPendingTx[BT_COMMAND]++;
} else {
err = B_BAD_VALUE;
flowf("tx sched provoked");
}
// TODO: check if device is actually ready for this
// TODO: mutex?
/* sched in All cases even if nbuf is null (hidden way to provoke re-scheduling)*/
sched_tx_processing(bdev);
return err;
}

View File

@ -1,21 +1,21 @@
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
#ifndef _H2UPPER_H_
#define _H2UPPER_H_
#include <util/list.h>
#include "h2generic.h"
status_t post_packet_up(bt_usb_dev* bdev, bt_packet_t type, void* buf);
status_t send_packet(hci_id hid, bt_packet_t type, net_buffer* nbuf);
status_t send_command(hci_id hid, snet_buffer* snbuf);
void sched_tx_processing(bt_usb_dev* bdev);
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
#ifndef _H2UPPER_H_
#define _H2UPPER_H_
#include <util/list.h>
#include "h2generic.h"
status_t post_packet_up(bt_usb_dev* bdev, bt_packet_t type, void* buf);
status_t send_packet(hci_id hid, bt_packet_t type, net_buffer* nbuf);
status_t send_command(hci_id hid, snet_buffer* snbuf);
void sched_tx_processing(bt_usb_dev* bdev);
#endif

View File

@ -1,150 +1,150 @@
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
#include <malloc.h>
#include "h2upper.h"
#include "h2util.h"
#include "h2transactions.h"
#include <bluetooth/HCI/btHCI_acl.h>
#include <bluetooth/HCI/btHCI_command.h>
#include <bluetooth/HCI/btHCI_event.h>
#define BT_DEBUG_THIS_MODULE
#include <btDebug.h>
void*
nb_get_whole_buffer(net_buffer* nbuf)
{
void* conPointer;
status_t err;
/* the job could be already done */
// !!! it could be trash from other upper protocols...
if (nbuf->COOKIEFIELD != NULL)
return (void*)nbuf->COOKIEFIELD;
if (nb == NULL)
goto fail;
err = nb->direct_access(nbuf, 0, nbuf->size, &conPointer);
if (err != B_OK) {
/* pity, we are gonna need a realocation */
nbuf->COOKIEFIELD = (uint32) malloc(nbuf->size);
if (nbuf->COOKIEFIELD == NULL)
goto fail;
err = nb->write(nbuf, 0, (void*) nbuf->COOKIEFIELD, nbuf->size);
if (err != B_OK)
goto free;
conPointer = (void*)nbuf->COOKIEFIELD;
}
return conPointer;
free:
free((void*) nbuf->COOKIEFIELD);
fail:
return NULL;
}
void
nb_destroy(net_buffer* nbuf)
{
/* Free possible allocated */
if (nbuf->COOKIEFIELD != NULL)
free((void*)nbuf->COOKIEFIELD);
// TODO check for survivers...
if (nb != NULL)
nb->free(nbuf);
}
/* Check from the completition if the queue is empty */
size_t
get_expected_size(net_buffer* nbuf)
{
if (nbuf == NULL)
panic("Analizing NULL packet");
switch (nbuf->protocol) {
case BT_ACL: {
struct hci_acl_header* header = nb_get_whole_buffer(nbuf);
return header->alen;
}
case BT_COMMAND: {
struct hci_command_header* header = nb_get_whole_buffer(nbuf);
return header->clen;
}
case BT_EVENT: {
struct hci_event_header* header = nb_get_whole_buffer(nbuf);
return header->elen;
}
default:
break;
}
return B_ERROR;
}
#if 0
#pragma mark - room util -
#endif
inline void
init_room(struct list* l)
{
list_init(l);
}
void*
alloc_room(struct list* l, size_t size)
{
void* item = list_get_first_item(l);
if (item == NULL)
item = (void*) malloc(size);
return item;
}
inline void
reuse_room(struct list* l, void* room)
{
list_add_item(l, room);
}
void
purge_room(struct list* l)
{
void* item;
while ((item = list_remove_head_item(l)) != NULL) {
free(item);
}
}
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
#include <malloc.h>
#include "h2upper.h"
#include "h2util.h"
#include "h2transactions.h"
#include <bluetooth/HCI/btHCI_acl.h>
#include <bluetooth/HCI/btHCI_command.h>
#include <bluetooth/HCI/btHCI_event.h>
#define BT_DEBUG_THIS_MODULE
#include <btDebug.h>
void*
nb_get_whole_buffer(net_buffer* nbuf)
{
void* conPointer;
status_t err;
/* the job could be already done */
// !!! it could be trash from other upper protocols...
if (nbuf->COOKIEFIELD != NULL)
return (void*)nbuf->COOKIEFIELD;
if (nb == NULL)
goto fail;
err = nb->direct_access(nbuf, 0, nbuf->size, &conPointer);
if (err != B_OK) {
/* pity, we are gonna need a realocation */
nbuf->COOKIEFIELD = (uint32) malloc(nbuf->size);
if (nbuf->COOKIEFIELD == NULL)
goto fail;
err = nb->write(nbuf, 0, (void*) nbuf->COOKIEFIELD, nbuf->size);
if (err != B_OK)
goto free;
conPointer = (void*)nbuf->COOKIEFIELD;
}
return conPointer;
free:
free((void*) nbuf->COOKIEFIELD);
fail:
return NULL;
}
void
nb_destroy(net_buffer* nbuf)
{
/* Free possible allocated */
if (nbuf->COOKIEFIELD != NULL)
free((void*)nbuf->COOKIEFIELD);
// TODO check for survivers...
if (nb != NULL)
nb->free(nbuf);
}
/* Check from the completition if the queue is empty */
size_t
get_expected_size(net_buffer* nbuf)
{
if (nbuf == NULL)
panic("Analizing NULL packet");
switch (nbuf->protocol) {
case BT_ACL: {
struct hci_acl_header* header = nb_get_whole_buffer(nbuf);
return header->alen;
}
case BT_COMMAND: {
struct hci_command_header* header = nb_get_whole_buffer(nbuf);
return header->clen;
}
case BT_EVENT: {
struct hci_event_header* header = nb_get_whole_buffer(nbuf);
return header->elen;
}
default:
break;
}
return B_ERROR;
}
#if 0
#pragma mark - room util -
#endif
inline void
init_room(struct list* l)
{
list_init(l);
}
void*
alloc_room(struct list* l, size_t size)
{
void* item = list_get_first_item(l);
if (item == NULL)
item = (void*) malloc(size);
return item;
}
inline void
reuse_room(struct list* l, void* room)
{
list_add_item(l, room);
}
void
purge_room(struct list* l)
{
void* item;
while ((item = list_remove_head_item(l)) != NULL) {
free(item);
}
}

View File

@ -1,34 +1,34 @@
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
#ifndef _H2UTIL_H_
#define _H2UTIL_H_
#include <util/list.h>
#include "h2generic.h"
/* net buffer utils for ACL, to be reviewed */
#define DEVICEFIELD type
#define SET_DEVICE(nbuf,hid) (nbuf->DEVICEFIELD=(nbuf->DEVICEFIELD&0xFFF0)|(hid&0xF))
#define GET_DEVICE(nbuf) fetch_device(NULL,(nbuf->DEVICEFIELD&0x0F))
#define COOKIEFIELD flags
void* nb_get_whole_buffer(net_buffer* nbuf);
void nb_destroy(net_buffer* nbuf);
size_t get_expected_size(net_buffer* nbuf);
/* Room utils */
inline void init_room(struct list* l);
void* alloc_room(struct list* l, size_t size);
inline void reuse_room(struct list* l, void* room);
void purge_room(struct list* l);
/* list utils */
#define list_purge(x) purge_room(x)
#endif
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
#ifndef _H2UTIL_H_
#define _H2UTIL_H_
#include <util/list.h>
#include "h2generic.h"
/* net buffer utils for ACL, to be reviewed */
#define DEVICEFIELD type
#define SET_DEVICE(nbuf,hid) (nbuf->DEVICEFIELD=(nbuf->DEVICEFIELD&0xFFF0)|(hid&0xF))
#define GET_DEVICE(nbuf) fetch_device(NULL,(nbuf->DEVICEFIELD&0x0F))
#define COOKIEFIELD flags
void* nb_get_whole_buffer(net_buffer* nbuf);
void nb_destroy(net_buffer* nbuf);
size_t get_expected_size(net_buffer* nbuf);
/* Room utils */
inline void init_room(struct list* l);
void* alloc_room(struct list* l, size_t size);
inline void reuse_room(struct list* l, void* room);
void purge_room(struct list* l);
/* list utils */
#define list_purge(x) purge_room(x)
#endif

View File

@ -1,225 +1,225 @@
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
#include "snet_buffer.h"
#include <malloc.h>
#include <string.h>
struct snet_buffer {
struct list_link link;
uint8* buffer;
uint16 allocatedSize;
uint16 expectedSize;
uint16 puttingSize;
uint16 pullingSize;
void* cookie;
};
snet_buffer*
snb_create(uint16 size)
{
/* TODO: pointer checking */
#ifdef SNB_BUFFER_ATTACHED
/* Allocating these 2 buffers together might prevent memory fragmentation? */
snet_buffer* snb = (snet_buffer*) malloc(sizeof(snet_buffer) + size);
snb->buffer = ((uint8*)snb) + sizeof(snet_buffer);
#else
snet_buffer* snb = malloc(sizeof (snet_buffer));
snb->buffer = malloc(size);
#endif
snb->pullingSize = snb->puttingSize = 0;
snb->expectedSize = snb->allocatedSize = size;
return snb;
}
void
snb_put(snet_buffer* snb, void* data, uint16 size)
{
/* TODO: check overflow */
memcpy( &snb->buffer[snb->puttingSize], data, size);
snb->puttingSize+=size;
}
void*
snb_pull(snet_buffer* snb, uint16 size)
{
/* TODO: check overflow */
snb->pullingSize+=size;
return &snb->buffer[snb->pullingSize-size];
}
inline void
snb_reset(snet_buffer* snb)
{
snb->puttingSize = snb->pullingSize = 0;
}
void
snb_free(snet_buffer* snb)
{
if (snb == NULL)
return;
#ifdef SNB_BUFFER_ATTACHED
free(snb);
#else
free(snb->buffer);
free(snb);
#endif
}
inline void*
snb_get(snet_buffer* snb)
{
/* TODO: pointer checking */
return snb->buffer;
}
inline uint16
snb_size(snet_buffer* snb)
{
/* TODO: pointer checking */
return snb->expectedSize;
}
inline void*
snb_cookie(snet_buffer* snb)
{
/* TODO: pointer checking */
return snb->cookie;
}
inline void
snb_set_cookie(snet_buffer* snb, void* cookie)
{
/* TODO: pointer checking */
snb->cookie = cookie;
}
/* Return true if we canot "put" more data in the buffer */
inline bool snb_completed(snet_buffer* snb)
{
return (snb->expectedSize == snb->puttingSize);
}
/* Return true if we cannot pull more more data from the buffer */
inline bool snb_finished(snet_buffer* snb)
{
return (snb->expectedSize == snb->pullingSize);
}
inline uint16 snb_remaining_to_put(snet_buffer* snb)
{
return (snb->expectedSize - snb->puttingSize);
}
inline uint16 snb_remaining_to_pull(snet_buffer* snb)
{
return (snb->expectedSize - snb->pullingSize);
}
/* ISSUE1: Number of packets in the worst case(we always need a bigger
buffer than before) increases, never decreases:
SOL1: Delete the smallest when the queue is bigger than X elements
SOL2: ?
ISSUE2: If the queue is not gonna be used for long time. Memory c
ould be freed
SOL1: Provide purge func.
SOL2: ?
*/
static snet_buffer*
snb_attempt_reuse(snet_buffer* snb, uint16 size)
{
if ( snb == NULL ||
((int16)snb->allocatedSize - (int16)size) < 0 ) {
/* Impossible or not worth, Creating a new one */
snb_free(snb);
return snb_create(size);
}
else {
snb_reset(snb);
snb->expectedSize = size;
return snb;
}
}
void
snb_park(struct list* l, snet_buffer* snb)
{
snet_buffer* item = NULL;
/* insert it by order */
while ((item = list_get_next_item(l, item)) != NULL) {
if (item->allocatedSize > snb->allocatedSize)
list_insert_item_before(l, item, snb);
}
}
snet_buffer*
snb_fetch(struct list* l, uint16 size)
{
snet_buffer* item = NULL;
snet_buffer* previous = NULL;
if (!list_is_empty(l))
while ((item = list_get_next_item(l, item)) != NULL) {
if (item->allocatedSize == size) {
/* This one is for us*/
break;
}
else if (item->allocatedSize > size) {
/* get the previous*/
item = previous;
break;
}
previous = item;
}
// reusing previous pointer for another proposit
previous = snb_attempt_reuse(item, size);
/* the resulting reused one is the same as we fetched? => remove it from list*/
if (item == previous) {
list_remove_item(l, item);
}
return previous;
}
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
#include "snet_buffer.h"
#include <malloc.h>
#include <string.h>
struct snet_buffer {
struct list_link link;
uint8* buffer;
uint16 allocatedSize;
uint16 expectedSize;
uint16 puttingSize;
uint16 pullingSize;
void* cookie;
};
snet_buffer*
snb_create(uint16 size)
{
/* TODO: pointer checking */
#ifdef SNB_BUFFER_ATTACHED
/* Allocating these 2 buffers together might prevent memory fragmentation? */
snet_buffer* snb = (snet_buffer*) malloc(sizeof(snet_buffer) + size);
snb->buffer = ((uint8*)snb) + sizeof(snet_buffer);
#else
snet_buffer* snb = malloc(sizeof (snet_buffer));
snb->buffer = malloc(size);
#endif
snb->pullingSize = snb->puttingSize = 0;
snb->expectedSize = snb->allocatedSize = size;
return snb;
}
void
snb_put(snet_buffer* snb, void* data, uint16 size)
{
/* TODO: check overflow */
memcpy( &snb->buffer[snb->puttingSize], data, size);
snb->puttingSize+=size;
}
void*
snb_pull(snet_buffer* snb, uint16 size)
{
/* TODO: check overflow */
snb->pullingSize+=size;
return &snb->buffer[snb->pullingSize-size];
}
inline void
snb_reset(snet_buffer* snb)
{
snb->puttingSize = snb->pullingSize = 0;
}
void
snb_free(snet_buffer* snb)
{
if (snb == NULL)
return;
#ifdef SNB_BUFFER_ATTACHED
free(snb);
#else
free(snb->buffer);
free(snb);
#endif
}
inline void*
snb_get(snet_buffer* snb)
{
/* TODO: pointer checking */
return snb->buffer;
}
inline uint16
snb_size(snet_buffer* snb)
{
/* TODO: pointer checking */
return snb->expectedSize;
}
inline void*
snb_cookie(snet_buffer* snb)
{
/* TODO: pointer checking */
return snb->cookie;
}
inline void
snb_set_cookie(snet_buffer* snb, void* cookie)
{
/* TODO: pointer checking */
snb->cookie = cookie;
}
/* Return true if we canot "put" more data in the buffer */
inline bool snb_completed(snet_buffer* snb)
{
return (snb->expectedSize == snb->puttingSize);
}
/* Return true if we cannot pull more more data from the buffer */
inline bool snb_finished(snet_buffer* snb)
{
return (snb->expectedSize == snb->pullingSize);
}
inline uint16 snb_remaining_to_put(snet_buffer* snb)
{
return (snb->expectedSize - snb->puttingSize);
}
inline uint16 snb_remaining_to_pull(snet_buffer* snb)
{
return (snb->expectedSize - snb->pullingSize);
}
/* ISSUE1: Number of packets in the worst case(we always need a bigger
buffer than before) increases, never decreases:
SOL1: Delete the smallest when the queue is bigger than X elements
SOL2: ?
ISSUE2: If the queue is not gonna be used for long time. Memory c
ould be freed
SOL1: Provide purge func.
SOL2: ?
*/
static snet_buffer*
snb_attempt_reuse(snet_buffer* snb, uint16 size)
{
if ( snb == NULL ||
((int16)snb->allocatedSize - (int16)size) < 0 ) {
/* Impossible or not worth, Creating a new one */
snb_free(snb);
return snb_create(size);
}
else {
snb_reset(snb);
snb->expectedSize = size;
return snb;
}
}
void
snb_park(struct list* l, snet_buffer* snb)
{
snet_buffer* item = NULL;
/* insert it by order */
while ((item = list_get_next_item(l, item)) != NULL) {
if (item->allocatedSize > snb->allocatedSize)
list_insert_item_before(l, item, snb);
}
}
snet_buffer*
snb_fetch(struct list* l, uint16 size)
{
snet_buffer* item = NULL;
snet_buffer* previous = NULL;
if (!list_is_empty(l))
while ((item = list_get_next_item(l, item)) != NULL) {
if (item->allocatedSize == size) {
/* This one is for us*/
break;
}
else if (item->allocatedSize > size) {
/* get the previous*/
item = previous;
break;
}
previous = item;
}
// reusing previous pointer for another proposit
previous = snb_attempt_reuse(item, size);
/* the resulting reused one is the same as we fetched? => remove it from list*/
if (item == previous) {
list_remove_item(l, item);
}
return previous;
}

View File

@ -1,81 +1,81 @@
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
#ifndef _SNET_BUFFER_H_
#define _SNET_BUFFER_H_
#include <util/list.h>
/*
* This is a simple data structure to hold network buffers.
* It drops many functionality that the Haiku net_buffer provides.
*
* - Inspired by linux sk_buff/bsd mbuf (put/pull)
* - Contiguoussafe (no push operation)
*
* So snet_buffers are ONLY meant to be used when:
* 1) You know exactily the maximun/final size of the frame
* before allocating it, and you will never exceed it.
* 2) You are not supposed to prepend data, only append.
*
*/
/* Configuration parameters */
#define SNB_BUFFER_ATTACHED
//#define SNB_PERFORMS_OVERFLOW_CHECKS
//#define SNB_PERFORMS_POINTER_CHECKS
struct snet_buffer;
typedef struct snet_buffer snet_buffer;
/* Creates a snb_buffer allocating size space for its full content */
snet_buffer* snb_create(uint16 size);
/* Free the snb_buffer*/
void snb_free(snet_buffer* snb);
/* Free the snb_buffer*/
void* snb_get(snet_buffer* snb);
/* Size of the snb_buffer*/
uint16 snb_size(snet_buffer* snb);
/* Cookie of the snb_buffer*/
void* snb_cookie(snet_buffer* snb);
/* Get Cookie of the snb_buffer*/
void snb_set_cookie(snet_buffer* snb, void* cookie);
/* Place the memory given by data to the "tail" of the snb */
void snb_put(snet_buffer* snb, void* data, uint16 size);
/* Returns a header chunk of size data */
void* snb_pull(snet_buffer* snb, uint16 size);
/* Discards all data put or pulled from the buffer */
void snb_reset(snet_buffer* snb);
/* Return true if we canot "put" more data in the buffer */
bool snb_completed(snet_buffer* snb);
/* Return true if we cannot pull more more data from the buffer */
bool snb_finished(snet_buffer* snb);
/* Return the amount of data we can still put in the buffer */
uint16 snb_remaining_to_put(snet_buffer* snb);
/* Return the amount of data we can still pull in the buffer */
uint16 snb_remaining_to_pull(snet_buffer* snb);
/* These to functions are provided to avoid memory fragmentation
* allocating and freeing many snb_buffers and its possible overhead.
* Thypical scenario would be
* that you create a snb_buffer to send data, once you send you free it,
* and need another one to hold the response. The idea would be once you send
* that buffer, to snb_park the buffer, and whenever you need to allocate another
* one snb_fetch it. That funcion will reuse most appropiated previous used one
* snb_buff by its memory use.
*/
void snb_park(struct list* l, snet_buffer* snb);
snet_buffer* snb_fetch(struct list* l, uint16 size);
#endif
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
#ifndef _SNET_BUFFER_H_
#define _SNET_BUFFER_H_
#include <util/list.h>
/*
* This is a simple data structure to hold network buffers.
* It drops many functionality that the Haiku net_buffer provides.
*
* - Inspired by linux sk_buff/bsd mbuf (put/pull)
* - Contiguoussafe (no push operation)
*
* So snet_buffers are ONLY meant to be used when:
* 1) You know exactily the maximun/final size of the frame
* before allocating it, and you will never exceed it.
* 2) You are not supposed to prepend data, only append.
*
*/
/* Configuration parameters */
#define SNB_BUFFER_ATTACHED
//#define SNB_PERFORMS_OVERFLOW_CHECKS
//#define SNB_PERFORMS_POINTER_CHECKS
struct snet_buffer;
typedef struct snet_buffer snet_buffer;
/* Creates a snb_buffer allocating size space for its full content */
snet_buffer* snb_create(uint16 size);
/* Free the snb_buffer*/
void snb_free(snet_buffer* snb);
/* Free the snb_buffer*/
void* snb_get(snet_buffer* snb);
/* Size of the snb_buffer*/
uint16 snb_size(snet_buffer* snb);
/* Cookie of the snb_buffer*/
void* snb_cookie(snet_buffer* snb);
/* Get Cookie of the snb_buffer*/
void snb_set_cookie(snet_buffer* snb, void* cookie);
/* Place the memory given by data to the "tail" of the snb */
void snb_put(snet_buffer* snb, void* data, uint16 size);
/* Returns a header chunk of size data */
void* snb_pull(snet_buffer* snb, uint16 size);
/* Discards all data put or pulled from the buffer */
void snb_reset(snet_buffer* snb);
/* Return true if we canot "put" more data in the buffer */
bool snb_completed(snet_buffer* snb);
/* Return true if we cannot pull more more data from the buffer */
bool snb_finished(snet_buffer* snb);
/* Return the amount of data we can still put in the buffer */
uint16 snb_remaining_to_put(snet_buffer* snb);
/* Return the amount of data we can still pull in the buffer */
uint16 snb_remaining_to_pull(snet_buffer* snb);
/* These to functions are provided to avoid memory fragmentation
* allocating and freeing many snb_buffers and its possible overhead.
* Thypical scenario would be
* that you create a snb_buffer to send data, once you send you free it,
* and need another one to hold the response. The idea would be once you send
* that buffer, to snb_park the buffer, and whenever you need to allocate another
* one snb_fetch it. That funcion will reuse most appropiated previous used one
* snb_buff by its memory use.
*/
void snb_park(struct list* l, snet_buffer* snb);
snet_buffer* snb_fetch(struct list* l, uint16 size);
#endif