- Move bluetooth net_device module to a independent module HCI, remake API interfaces

- Move functionality for assembling ACL/events packets of the driver to this module
- Move h2generic driver to c++ (not style)
- Pass checkstyle.py to all commited files.
Fixes:
- Wrong condition for finishing l2cap packet segmentation.
- Place NetBuffersPrependers in a inner scope to avoid Sycing twice in destructor.
- Avoid keeping trace of l2cap responses of any other kind of thread.
- Do not free net_buffers of for Frame containers.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35117 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Oliver Ruiz Dorantes
2010-01-17 15:46:36 +00:00
parent 9b178bf778
commit 9760dcae20
26 changed files with 1157 additions and 1259 deletions
+1
View File
@@ -1,3 +1,4 @@
SubDir HAIKU_TOP src add-ons kernel bluetooth ;
SubInclude HAIKU_TOP src add-ons kernel bluetooth btCoreData ;
SubInclude HAIKU_TOP src add-ons kernel bluetooth hci ;
@@ -15,10 +15,11 @@
#include <btDebug.h>
DoublyLinkedList<HciConnection> sConnectionList;
net_buffer_module_info *gBufferModule = NULL;
net_buffer_module_info* gBufferModule = NULL;
inline bool
ExistConnectionByDestination(bdaddr_t *destination, hci_id hid = -1)
ExistConnectionByDestination(bdaddr_t* destination, hci_id hid = -1)
{
return (ConnectionByDestination(destination, hid) != NULL);
}
@@ -27,7 +28,7 @@ ExistConnectionByDestination(bdaddr_t *destination, hci_id hid = -1)
inline bool
ExistConnectionByHandle(uint16 handle, hci_id hid)
{
return (ConnectionByHandle(handle,hid));
return (ConnectionByHandle(handle, hid));
}
@@ -37,39 +38,48 @@ DumpHciConnections(int argc, char** argv)
HciConnection* conn;
L2capChannel* chan;
L2capFrame* frame;
DoublyLinkedList<HciConnection>::Iterator iterator = sConnectionList.GetIterator();
DoublyLinkedList<HciConnection>::Iterator iterator
= sConnectionList.GetIterator();
while (iterator.HasNext()) {
conn = iterator.Next();
kprintf("LocalDevice=%lx Destination=%s handle=%#x type=%d outqueue=%ld expected=%ld\n",
conn->Hid, bdaddrUtils::ToString(conn->destination),
conn->handle, conn->type, conn->OutGoingFrames.Count() , conn->ExpectedResponses.Count());
kprintf("LocalDevice=%lx Destination=%s handle=%#x type=%d"
"outqueue=%ld expected=%ld\n", conn->Hid,
bdaddrUtils::ToString(conn->destination), conn->handle, conn->type,
conn->OutGoingFrames.Count() , conn->ExpectedResponses.Count());
// each channel
kprintf("\tChannels\n");
DoublyLinkedList<L2capChannel>::Iterator channelIterator = conn->ChannelList.GetIterator();
DoublyLinkedList<L2capChannel>::Iterator channelIterator
= conn->ChannelList.GetIterator();
while (channelIterator.HasNext()) {
chan = channelIterator.Next();
kprintf("\t\tscid=%x dcid=%x state=%x cfg=%x\n", chan->scid,
chan->dcid, chan->state, chan->cfgState);
chan->dcid, chan->state, chan->cfgState);
}
// Each outgoing
kprintf("\n\tOutGoingFrames\n");
DoublyLinkedList<L2capFrame>::Iterator frameIterator = conn->OutGoingFrames.GetIterator();
DoublyLinkedList<L2capFrame>::Iterator frameIterator
= conn->OutGoingFrames.GetIterator();
while (frameIterator.HasNext()) {
frame = frameIterator.Next();
kprintf("\t\tscid=%x code=%x ident=%x type=%x, buffer=%p\n", frame->channel->scid,
frame->code, frame->ident, frame->type, frame->buffer);
kprintf("\t\tscid=%x code=%x ident=%x type=%x, buffer=%p\n",
frame->channel->scid, frame->code, frame->ident,
frame->type, frame->buffer);
}
// Each expected
kprintf("\n\tExpectedFrames\n");
DoublyLinkedList<L2capFrame>::Iterator frameExpectedIterator = conn->ExpectedResponses.GetIterator();
DoublyLinkedList<L2capFrame>::Iterator frameExpectedIterator
= conn->ExpectedResponses.GetIterator();
while (frameExpectedIterator.HasNext()) {
frame = frameExpectedIterator.Next();
kprintf("\t\tscid=%x code=%x ident=%x type=%x, buffer=%p\n", frame->channel->scid,
frame->code, frame->ident, frame->type, frame->buffer);
kprintf("\t\tscid=%x code=%x ident=%x type=%x, buffer=%p\n",
frame->channel->scid, frame->code, frame->ident,
frame->type, frame->buffer);
}
}
@@ -77,9 +87,8 @@ DumpHciConnections(int argc, char** argv)
}
status_t
PostEvent(net_device* ndev, void* event, size_t size)
PostEvent(bluetooth_device* ndev, void* event, size_t size)
{
struct hci_event_header* outgoingEvent = (struct hci_event_header*) event;
status_t err;
@@ -88,41 +97,49 @@ PostEvent(net_device* ndev, void* event, size_t size)
switch (outgoingEvent->ecode) {
case HCI_EVENT_CONN_COMPLETE:
{
struct hci_ev_conn_complete* data = (struct hci_ev_conn_complete*)(outgoingEvent+1);
//TODO: XXX parse handle field
HciConnection* conn = AddConnection(data->handle, BT_ACL, &data->bdaddr, ndev->index);
struct hci_ev_conn_complete* data
= (struct hci_ev_conn_complete*)(outgoingEvent + 1);
// TODO: XXX parse handle field
HciConnection* conn = AddConnection(data->handle, BT_ACL,
&data->bdaddr, ndev->index);
if (conn == NULL)
panic("no mem for conn desc");
conn->ndevice = ndev;
debugf("Registered connection handle=%#x\n",data->handle);
} break;
break;
}
case HCI_EVENT_DISCONNECTION_COMPLETE:
{
struct hci_ev_disconnection_complete_reply* data =
(struct hci_ev_disconnection_complete_reply*)(outgoingEvent+1);
struct hci_ev_disconnection_complete_reply* data;
data = (struct hci_ev_disconnection_complete_reply*)
(outgoingEvent + 1);
RemoveConnection(data->handle, ndev->index);
debugf("unRegistered connection handle=%#x\n",data->handle);
} break;
break;
}
}
// forward to bluetooth server
port_id port = find_port(BT_USERLAND_PORT_NAME);
if (port != B_NAME_NOT_FOUND) {
if (port != B_NAME_NOT_FOUND) {
err = write_port_etc(port, PACK_PORTCODE(BT_EVENT, ndev->index, -1),
event, size, B_TIMEOUT, 1*1000*1000);
event, size, 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;
} else {
flowf("ERROR:bluetooth_server not found for posting\n");
err = B_NAME_NOT_FOUND;
}
return err;
}
@@ -136,12 +153,12 @@ bcd_std_ops(int32 op, ...)
case B_MODULE_INIT:
new (&sConnectionList) DoublyLinkedList<HciConnection>;
add_debugger_command("btConnections", &DumpHciConnections,
"Lists Bluetooth Connections with RemoteDevices & channels");
"Lists Bluetooth Connections with RemoteDevices & channels");
status = get_module(NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule);
if (status < B_OK) {
status = get_module(NET_BUFFER_MODULE_NAME,
(module_info **)&gBufferModule);
if (status < B_OK)
return status;
}
return B_OK;
@@ -159,6 +176,7 @@ bcd_std_ops(int32 op, ...)
return B_ERROR;
}
bluetooth_core_data_module_info sBCDModule = {
{
BT_CORE_DATA_MODULE_NAME,
@@ -167,7 +185,7 @@ bluetooth_core_data_module_info sBCDModule = {
},
PostEvent,
AddConnection,
/* RemoveConnection,*/
// RemoveConnection,
RemoveConnection,
RouteConnection,
@@ -198,7 +216,7 @@ bluetooth_core_data_module_info sBCDModule = {
};
module_info *modules[] = {
(module_info *)&sBCDModule,
module_info* modules[] = {
(module_info*)&sBCDModule,
NULL
};
+16
View File
@@ -0,0 +1,16 @@
SubDir HAIKU_TOP src add-ons kernel bluetooth hci ;
UsePrivateKernelHeaders ;
UsePrivateHeaders net bluetooth ;
UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) ] ;
UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ;
# disable debug output, if debugging is disabled
if $(DEBUG) = 0 {
SubDirCcFlags [ FDefines DEBUG_MAX_LEVEL_FLOW=0 DEBUG_MAX_LEVEL_INFO=0 ] ;
}
KernelAddon hci :
bluetooth.cpp
acl.cpp
;
@@ -38,14 +38,14 @@ AclAssembly(net_buffer* nbuf, hci_id hid)
{
status_t error = B_OK;
/* Check ACL data packet. Driver should ensure report complete ACL packets */
// Check ACL data packet. Driver should ensure report complete ACL packets
if (nbuf->size < sizeof(struct hci_acl_header)) {
debugf("Transport driver has reported invalid ACL data packet, too small, length=%ld\n", nbuf->size);
debugf("Invalid ACL data packet, small length=%ld\n", nbuf->size);
gBufferModule->free(nbuf);
return (EMSGSIZE);
}
/* Strip ACL data packet header */
// Strip ACL data packet header
NetBufferHeaderReader<struct hci_acl_header> aclHeader(nbuf);
status_t status = aclHeader.Status();
if (status < B_OK) {
@@ -54,26 +54,25 @@ AclAssembly(net_buffer* nbuf, hci_id hid)
}
/* Get ACL connection handle, PB flag and payload length */
// Get ACL connection handle, PB flag and payload length
aclHeader->handle = le16toh(aclHeader->handle);
uint16 con_handle = get_acl_handle(aclHeader->handle);
uint16 pb = get_acl_pb_flag(aclHeader->handle);
uint16 length = le16toh(aclHeader->alen);
aclHeader.Remove();
aclHeader.Remove();
debugf("got ACL data packet, con_handle=%#x, PB=%#x, length=%d\n", con_handle, pb, length);
debugf("ACL data packet, handle=%#x, PB=%#x, length=%d\n",
con_handle, pb, length);
/* a) Ensure there is HCI connection
b) Get connection descriptor
c) veryfy the status of the connection
*/
// a) Ensure there is HCI connection
// b) Get connection descriptor
// c) veryfy the status of the connection
HciConnection* conn = btCoreData->ConnectionByHandle(con_handle, hid);
HciConnection* conn = btCoreData->ConnectionByHandle(con_handle, hid);
if (conn == NULL) {
//debugf("unexpected ACL!Connection does not exist!schedule! con_handle=%#x\n", con_handle);
panic("unexpected ACL!Connection does not exist!schedule!\n");
debugf("Uexpected handle=%#x does not exist!\n", con_handle);
conn = btCoreData->AddConnection(con_handle, BT_ACL, BDADDR_NULL, hid);
}
@@ -85,10 +84,11 @@ AclAssembly(net_buffer* nbuf, hci_id hid)
}
/* Process packet */
// Process packet
if (pb == HCI_ACL_PACKET_START) {
if (conn->currentRxPacket != NULL) {
debugf("dropping incomplete L2CAP packet, got %ld bytes, want %d bytes\n", conn->currentRxPacket->size, length );
debugf("Dropping incomplete L2CAP packet, got %ld want %d \n",
conn->currentRxPacket->size, length );
gBufferModule->free(conn->currentRxPacket);
conn->currentRxPacket = NULL;
conn->currentRxExpectedLength = 0;
@@ -96,7 +96,8 @@ AclAssembly(net_buffer* nbuf, hci_id hid)
// Get L2CAP header, ACL header was dimissed
if (nbuf->size < sizeof(l2cap_hdr_t)) {
debugf("invalid L2CAP packet start fragment. Packet too small, length=%ld\n", nbuf->size);
debugf("Invalid L2CAP start fragment, small, length=%ld\n",
nbuf->size);
gBufferModule->free(nbuf);
return (EMSGSIZE);
}
@@ -112,9 +113,10 @@ AclAssembly(net_buffer* nbuf, hci_id hid)
l2capHeader->length = le16toh(l2capHeader->length);
l2capHeader->dcid = le16toh(l2capHeader->dcid);
debugf("staring new L2CAP packet, con_handle=%#x, length=%d\n", con_handle, le16toh(l2capHeader->length));
debugf("New L2CAP, handle=%#x length=%d\n", con_handle,
le16toh(l2capHeader->length));
/* Start new L2CAP packet */
// Start new L2CAP packet
conn->currentRxPacket = nbuf;
conn->currentRxExpectedLength = l2capHeader->length + sizeof(l2cap_hdr_t);
@@ -125,7 +127,7 @@ AclAssembly(net_buffer* nbuf, hci_id hid)
return (EINVAL);
}
/* Add fragment to the L2CAP packet */
// Add fragment to the L2CAP packet
gBufferModule->merge(conn->currentRxPacket, nbuf, true);
} else {
@@ -134,12 +136,14 @@ AclAssembly(net_buffer* nbuf, hci_id hid)
return (EINVAL);
}
conn->currentRxExpectedLength -= length; /* substract the length of content of the ACL packet*/
// substract the length of content of the ACL packet
conn->currentRxExpectedLength -= length;
if (conn->currentRxExpectedLength < 0) {
debugf("packet length mismatch. Got %ld bytes, expected %ld bytes\n", conn->currentRxPacket->size,
conn->currentRxExpectedLength);
debugf("Mismatch. Got %ld, expected %ld\n",
conn->currentRxPacket->size, conn->currentRxExpectedLength);
gBufferModule->free(conn->currentRxPacket);
conn->currentRxPacket = NULL;
conn->currentRxExpectedLength = 0;
@@ -152,7 +156,8 @@ AclAssembly(net_buffer* nbuf, hci_id hid)
conn->currentRxPacket = NULL;
conn->currentRxExpectedLength = 0;
} else {
debugf("Expected %ld current acl apports %d\n", conn->currentRxExpectedLength, length);
debugf("Expected %ld current adds %d\n",
conn->currentRxExpectedLength, length);
}
return error;
@@ -163,12 +168,12 @@ status_t
PostToUpper(HciConnection* conn, net_buffer* buf)
{
if (L2cap == NULL)
if (get_module(NET_BLUETOOTH_L2CAP_NAME,(module_info**)&L2cap) != B_OK) {
debugf("cannot get module \"%s\"\n", NET_BLUETOOTH_L2CAP_NAME);
return B_ERROR;
} // TODO: someone put it
return L2cap->receive_data((net_buffer*)conn);// XXX:HACK -> pass handle in type
return L2cap->receive_data((net_buffer*)conn);// XXX pass handle in type
}
@@ -23,44 +23,45 @@
#include <NetBufferUtilities.h>
#define BT_DEBUG_THIS_MODULE
#define SUBMODULE_NAME "bluetooth_device"
#define SUBMODULE_NAME "hci"
#define SUBMODULE_COLOR 34
#include <btDebug.h>
#include <btCoreData.h>
#include <btModules.h>
#include <CodeHandler.h>
#define KERNEL_LAND
#include <PortListener.h>
#undef KERNEL_LAND
#include <bluetooth/HCI/btHCI.h>
#include <bluetooth/HCI/btHCI_acl.h>
#include <bluetooth/HCI/btHCI_command.h>
#include <bluetooth/HCI/btHCI_event.h>
#include <bluetooth/HCI/btHCI_transport.h>
#include <bluetooth/HCI/btHCI_sco.h>
#include <bluetooth/bdaddrUtils.h>
#include "acl.h"
struct bluetooth_device : net_device, DoublyLinkedListLinkImpl<bluetooth_device> {
net_buffer* fBuffersRx[HCI_NUM_PACKET_TYPES];
size_t fExpectedPacketSize[HCI_NUM_PACKET_TYPES];
int fd;
uint16 mtu;
};
typedef PortListener<void,
HCI_MAX_FRAME_SIZE, // Event Body can hold max 255 + 2 header
24 // Some devices have sent chunks of 24 events(inquiry result)
> BluetoothRawDataPort;
/* Modules references */
// Modules references
net_buffer_module_info* gBufferModule = NULL;
static net_stack_module_info* sStackModule = NULL;
struct bluetooth_core_data_module_info* btCoreData = NULL;
static mutex sListLock;
static DoublyLinkedList<bluetooth_device> sDeviceList;
static sem_id sLinkChangeSemaphore;
static DoublyLinkedList<bluetooth_device> sDeviceList;
BluetoothRawDataPort* BluetoothRXPort;
// forward declarations
status_t bluetooth_receive_data(net_device* _device, net_buffer** _buffer);
status_t HciPacketHandler(void* data, int32 code, size_t size);
bluetooth_device*
@@ -68,11 +69,12 @@ FindDeviceByID(hci_id hid)
{
bluetooth_device* device;
DoublyLinkedList<bluetooth_device>::Iterator iterator = sDeviceList.GetIterator();
while (iterator.HasNext()) {
DoublyLinkedList<bluetooth_device>::Iterator iterator
= sDeviceList.GetIterator();
while (iterator.HasNext()) {
device = iterator.Next();
if (device->index == (uint32 )hid)
if (device->index == hid)
return device;
}
@@ -81,9 +83,21 @@ FindDeviceByID(hci_id hid)
status_t
Assemble(net_device* netDevice, bt_packet_t type, void* data, size_t count)
PostTransportPacket(hci_id hid, bt_packet_t type, void* data, size_t count)
{
uint32 code = 0;
Bluetooth::CodeHandler::SetDevice(&code, hid);
Bluetooth::CodeHandler::SetProtocol(&code, type);
return BluetoothRXPort->Trigger(code, data, count);
}
status_t
Assemble(bluetooth_device* bluetoothDevice, bt_packet_t type, void* data,
size_t count)
{
bluetooth_device* bluetoothDevice = (bluetooth_device*)netDevice;
net_buffer* nbuf = bluetoothDevice->fBuffersRx[type];
size_t currentPacketLen = 0;
@@ -95,15 +109,17 @@ Assemble(net_device* netDevice, bt_packet_t type, void* data, size_t count)
switch (type) {
case BT_EVENT:
if (count >= HCI_EVENT_HDR_SIZE) {
struct hci_event_header* headerPkt
struct hci_event_header* headerPacket
= (struct hci_event_header*)data;
bluetoothDevice->fExpectedPacketSize[type]
= HCI_EVENT_HDR_SIZE + headerPkt->elen;
= HCI_EVENT_HDR_SIZE + headerPacket->elen;
if (count > bluetoothDevice->fExpectedPacketSize[type]) {
if (count >= bluetoothDevice->fExpectedPacketSize[type]) {
// the whole packet is here so it can be already posted.
flowf("EVENT posted in HCI!!!\n");
btCoreData->PostEvent(bluetoothDevice, data,
bluetoothDevice->fExpectedPacketSize[type]);
} else {
nbuf = gBufferModule->create(
bluetoothDevice->fExpectedPacketSize[type]);
@@ -113,7 +129,7 @@ Assemble(net_device* netDevice, bt_packet_t type, void* data, size_t count)
}
} else {
flowf("EVENT frame corrupted\n");
panic("EVENT frame corrupted\n");
return EILSEQ;
}
break;
@@ -132,7 +148,7 @@ Assemble(net_device* netDevice, bt_packet_t type, void* data, size_t count)
nbuf->protocol = type;
} else {
flowf("ACL frame corrupted\n");
panic("ACL frame corrupted\n");
return EILSEQ;
}
break;
@@ -152,22 +168,25 @@ Assemble(net_device* netDevice, bt_packet_t type, void* data, size_t count)
// Continuation of a packet
currentPacketLen = bluetoothDevice->fExpectedPacketSize[type] - nbuf->size;
}
if (nbuf != NULL) {
currentPacketLen = min_c(currentPacketLen, count);
gBufferModule->append(nbuf, data, currentPacketLen);
if ((bluetoothDevice->fExpectedPacketSize[type] - nbuf->size) == 0 ) {
if ((bluetoothDevice->fExpectedPacketSize[type] - nbuf->size) == 0) {
switch (nbuf->protocol) {
case BT_EVENT:
btCoreData->PostEvent(netDevice, data,
panic("need to send full buffer to btdatacore!\n");
btCoreData->PostEvent(bluetoothDevice, data,
bluetoothDevice->fExpectedPacketSize[type]);
break;
case BT_ACL:
bluetooth_receive_data(netDevice, &nbuf);
// TODO: device descriptor has been fetched better not
// pass id again
flowf("ACL parsed in ACL!\n");
AclAssembly(nbuf, bluetoothDevice->index);
break;
default:
@@ -197,12 +216,18 @@ Assemble(net_device* netDevice, bt_packet_t type, void* data, size_t count)
status_t
HciPacketHandler(void* data, int32 code, size_t size)
{
bluetooth_device* bluetoothDevice
= FindDeviceByID(Bluetooth::CodeHandler::Device(code));
hci_id deviceId = Bluetooth::CodeHandler::Device(code);
bluetooth_device* bluetoothDevice = FindDeviceByID(deviceId);
debugf("to assemble %ld bytes of %ld\n", size, deviceId);
if (bluetoothDevice != NULL)
return Assemble(bluetoothDevice, Bluetooth::CodeHandler::Protocol(code),
data, size);
else {
debugf("Device %ld could not be matched\n", deviceId);
}
return B_ERROR;
}
@@ -212,31 +237,22 @@ HciPacketHandler(void* data, int32 code, size_t size)
status_t
bluetooth_init(const char* name, net_device** _device)
RegisterDriver(bt_hci_transport_hooks* hooks, bluetooth_device** _device)
{
debugf("Initializing bluetooth device %s\n",name);
// TODO: make sure this is a device in /dev/bluetooth
if (strncmp(name, "bluetooth/h", 11))
return B_BAD_VALUE;
if (gBufferModule == NULL) { // lazy allocation
status_t status = get_module(NET_BUFFER_MODULE_NAME,
(module_info**)&gBufferModule);
if (status < B_OK)
return status;
}
bluetooth_device* device = new (std::nothrow) bluetooth_device;
if (device == NULL) {
put_module(NET_BUFFER_MODULE_NAME);
if (device == NULL)
return B_NO_MEMORY;
for (int index = 0; index < HCI_NUM_PACKET_TYPES; index++) {
device->fBuffersRx[index] = NULL;
device->fExpectedPacketSize[index] = 0;
}
memset(device, 0, sizeof(bluetooth_device));
device->info = NULL; // not yet used
device->hooks = hooks;
// Fill
strcpy(device->name, name);
device->mtu = L2CAP_MTU_MINIMUM; // TODO: ensure specs min value
MutexLocker _(&sListLock);
@@ -244,92 +260,58 @@ bluetooth_init(const char* name, net_device** _device)
device->index = HCI_DEVICE_INDEX_OFFSET; // REVIEW: dev index
else
device->index = (sDeviceList.Tail())->index + 1; // REVIEW!
flowf("List not empty\n");
// TODO: add to list whould be done in up hook
sDeviceList.Add(device);
debugf("Device %s %lx\n", device->name, device->index );
debugf("Device %lx\n", device->index );
*_device = device;
return B_OK;
}
status_t
bluetooth_uninit(net_device* _device)
UnregisterDriver(hci_id id)
{
bluetooth_device* device = (bluetooth_device*)_device;
bluetooth_device* device = FindDeviceByID(id);
debugf("index %lx\n",device->index);
if (device == NULL)
return B_ERROR;
// if the device is still part of the list, remove it
if (device->GetDoublyLinkedListLink()->next != NULL
|| device->GetDoublyLinkedListLink()->previous != NULL
|| device == sDeviceList.Head())
sDeviceList.Remove(device);
put_module(NET_BUFFER_MODULE_NAME);
delete device;
return B_OK;
}
// PostACL
status_t
bluetooth_up(net_device* _device)
PostACL(hci_id hciId, net_buffer* buffer)
{
bluetooth_device* device = (bluetooth_device*)_device;
debugf("index %ld\n",device->index);
device->fd = open(device->name, O_RDWR);
if (device->fd < 0)
goto err;
return B_OK;
err:
close(device->fd);
device->fd = -1;
return errno;
}
void
bluetooth_down(net_device* _device)
{
bluetooth_device* device = (bluetooth_device*)_device;
debugf("index %ld\n",device->index);
close(device->fd);
device->fd = -1;
}
status_t
bluetooth_control(net_device* _device, int32 op, void* argument,
size_t length)
{
bluetooth_device* device = (bluetooth_device*)_device;
debugf("index %ld\n",device->index);
// Forward the call to the driver
return ioctl(device->fd, op, argument, length);
}
status_t
bluetooth_send_data(net_device* _device, net_buffer* buffer)
{
bluetooth_device* device = (bluetooth_device*)_device;
net_buffer* curr_frame = NULL;
net_buffer* next_frame = buffer;
uint16 handle = buffer->type; // TODO: CodeHandler
uint8 flag = HCI_ACL_PACKET_START;
debugf("index %ld try to send bt packet of %lu bytes (flags %ld):\n",
if (buffer == NULL)
panic("passing null buffer");
uint16 handle = buffer->type; // TODO: CodeHandler
bluetooth_device* device = FindDeviceByID(hciId);
if (device == NULL) {
debugf("No device %lx", hciId);
return B_ERROR;
}
debugf("index %lx try to send bt packet of %lu bytes (flags %ld):\n",
device->index, buffer->size, buffer->flags);
// TODO: ATOMIC! any other thread should stop here
@@ -337,116 +319,50 @@ bluetooth_send_data(net_device* _device, net_buffer* buffer)
// Divide packet if big enough
curr_frame = next_frame;
if (next_frame->size > device->mtu) {
if (curr_frame->size > device->mtu) {
next_frame = gBufferModule->split(curr_frame, device->mtu);
} else {
next_frame = NULL;
}
// Attach acl header
NetBufferPrepend<struct hci_acl_header> bufferHeader(curr_frame);
status_t status = bufferHeader.Status();
if (status < B_OK) {
// free the buffer
continue;
{
NetBufferPrepend<struct hci_acl_header> bufferHeader(curr_frame);
status_t status = bufferHeader.Status();
if (status < B_OK) {
// free the buffer
continue;
}
bufferHeader->handle = pack_acl_handle_flags(handle, flag, 0);
bufferHeader->alen = curr_frame->size - sizeof(struct hci_acl_header);
}
bufferHeader->handle = pack_acl_handle_flags(handle, flag, 0);
bufferHeader->alen = curr_frame->size - sizeof(struct hci_acl_header);
bufferHeader.Sync();
// Send to driver XXX: another interlayer trick
debugf("tolower nbuf %p\n",curr_frame);
// Send to driver
curr_frame->protocol = BT_ACL;
((status_t(*)(hci_id id, net_buffer* nbuf))device->media)(device->index,
curr_frame);
debugf("Tolower nbuf %p!\n", curr_frame);
// We could pass a cookie and avoid the driver fetch the Id
device->hooks->SendACL(device->index, curr_frame);
flag = HCI_ACL_PACKET_FRAGMENT;
} while (next_frame == NULL);
} while (next_frame != NULL);
return B_OK;
}
status_t
bluetooth_receive_data(net_device* _device, net_buffer** _buffer)
PostSCO(hci_id hciId, net_buffer* buffer)
{
bluetooth_device* device = (bluetooth_device*)_device;
status_t status = B_OK;
debugf("index %ld packet of %lu bytes (flags %ld):\n",
device->index, (*_buffer)->size, (*_buffer)->flags);
if (device->fd == -1)
return B_FILE_ERROR;
switch ((*_buffer)->protocol) {
case BT_ACL:
status = AclAssembly(*_buffer, device->index);
break;
default:
panic("Protocol not supported");
break;
}
return status;
return B_ERROR;
}
status_t
bluetooth_set_mtu(net_device* _device, size_t mtu)
PostESCO(hci_id hciId, net_buffer* buffer)
{
bluetooth_device* device = (bluetooth_device*)_device;
debugf("index %ld mtu %ld\n",device->index, mtu);
device->mtu = mtu;
return B_OK;
}
status_t
bluetooth_set_promiscuous(net_device* _device, bool promiscuous)
{
bluetooth_device* device = (bluetooth_device*)_device;
debugf("index %ld promiscuous %d\n",device->index, promiscuous);
return EOPNOTSUPP;
}
status_t
bluetooth_set_media(net_device* device, uint32 media)
{
debugf("index %ld media %ld\n",device->index, media);
return EOPNOTSUPP;
}
status_t
bluetooth_add_multicast(struct net_device* _device, const sockaddr* _address)
{
bluetooth_device* device = (bluetooth_device*)_device;
debugf("index %ld\n",device->index);
return EOPNOTSUPP;
}
status_t
bluetooth_remove_multicast(struct net_device* _device, const sockaddr* _address)
{
bluetooth_device* device = (bluetooth_device*)_device;
debugf("index %ld\n",device->index);
return EOPNOTSUPP;
return B_ERROR;
}
@@ -455,11 +371,12 @@ dump_bluetooth_devices(int argc, char** argv)
{
bluetooth_device* device;
DoublyLinkedList<bluetooth_device>::Iterator iterator = sDeviceList.GetIterator();
DoublyLinkedList<bluetooth_device>::Iterator iterator
= sDeviceList.GetIterator();
while (iterator.HasNext()) {
device = iterator.Next();
kprintf("\tname=%s index=%#lx @%p\n", device->name, device->index, device);
kprintf("\tindex=%#lx @%p hooks=%p\n",device->index, device, device->hooks);
}
return 0;
@@ -477,9 +394,9 @@ bluetooth_std_ops(int32 op, ...)
{
status_t status;
status = get_module(NET_STACK_MODULE_NAME,(module_info**)&sStackModule);
status = get_module(NET_BUFFER_MODULE_NAME, (module_info**)&gBufferModule);
if (status < B_OK) {
flowf("problem getting netstack module\n");
panic("no way Dude we need that!");
return status;
}
@@ -492,6 +409,17 @@ bluetooth_std_ops(int32 op, ...)
new (&sDeviceList) DoublyLinkedList<bluetooth_device>;
// static C++ objects are not initialized in the module startup
BluetoothRXPort = new BluetoothRawDataPort(BT_RX_PORT_NAME,
(BluetoothRawDataPort::port_listener_func)&HciPacketHandler);
if (BluetoothRXPort->Launch() != B_OK) {
flowf("RX thread creation failed!\n");
// we Cannot do much here ... avoid registering
} else {
flowf("RX thread launched!\n");
}
sLinkChangeSemaphore = create_sem(0, "bt sem");
if (sLinkChangeSemaphore < B_OK) {
put_module(NET_STACK_MODULE_NAME);
@@ -515,6 +443,7 @@ bluetooth_std_ops(int32 op, ...)
delete_sem(sLinkChangeSemaphore);
mutex_destroy(&sListLock);
put_module(NET_BUFFER_MODULE_NAME);
put_module(NET_STACK_MODULE_NAME);
put_module(BT_CORE_DATA_MODULE_NAME);
remove_debugger_command("btLocalDevices", &dump_bluetooth_devices);
@@ -529,24 +458,19 @@ bluetooth_std_ops(int32 op, ...)
}
net_device_module_info sBluetoothModule = {
bt_hci_module_info sBluetoothModule = {
{
NET_BLUETOOTH_DEVICE_NAME,
BT_HCI_MODULE_NAME,
B_KEEP_LOADED,
bluetooth_std_ops
},
bluetooth_init,
bluetooth_uninit,
bluetooth_up,
bluetooth_down,
bluetooth_control,
bluetooth_send_data,
bluetooth_receive_data,
bluetooth_set_mtu,
bluetooth_set_promiscuous,
bluetooth_set_media,
bluetooth_add_multicast,
bluetooth_remove_multicast,
RegisterDriver,
UnregisterDriver,
FindDeviceByID,
PostTransportPacket,
PostACL,
PostSCO,
PostESCO
};
@@ -18,11 +18,11 @@ if ! $(TARGET_PLATFORM_HAIKU_COMPATIBLE) {
}
KernelAddon h2generic :
h2generic.c
h2transactions.c
h2upper.c
h2util.c
snet_buffer.c
h2generic.cpp
h2transactions.cpp
h2upper.cpp
h2util.cpp
snet_buffer.cpp
$(r5_src)
;
@@ -1,10 +1,7 @@
/*
* 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_
@@ -16,20 +13,19 @@
#define BT_DRIVER_SUPPORTS_ESCO 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)
/* 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
#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
@@ -38,8 +34,11 @@
#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_TRANSPORT "/" BLUETOOTH_DEVICE_DEVFS_NAME
#define BLUETOOTH_DEVICE_DEVFS_NAME BLUETOOTH_DEVICE_TRANSPORT \
BLUETOOTH_DEVICE_NAME
#define BLUETOOTH_DEVICE_PATH "bluetooth/" BLUETOOTH_DEVICE_TRANSPORT "/" \
BLUETOOTH_DEVICE_DEVFS_NAME
#endif
@@ -17,8 +17,6 @@
#include "snet_buffer.h"
#include <bluetooth/bluetooth_util.h>
#include <bluetooth/HCI/btHCI.h>
#include <bluetooth/HCI/btHCI_module.h>
#define BT_DEBUG_THIS_MODULE
#define SUBMODULE_NAME BLUETOOTH_DEVICE_DEVFS_NAME
@@ -34,20 +32,20 @@
int32 api_version = B_CUR_DRIVER_API_VERSION;
/* Modules */
// Modules
static char* usb_name = B_USB_MODULE_NAME;
static char* hci_name = BT_HCI_MODULE_NAME;
static char* btDevices_name = NET_BLUETOOTH_DEVICE_NAME;
static char* btDevices_name = BT_HCI_MODULE_NAME;
usb_module_info* usb = NULL;
bt_hci_module_info* hci = NULL;
struct net_device_module_info* btDevices = NULL;
bt_hci_module_info* hci = NULL; // TODO remove / clean
struct bt_hci_module_info* btDevices = NULL;
struct net_buffer_module_info* nb = NULL;
struct bluetooth_core_data_module_info* btCoreData = NULL;
// Driver Global data
static char *publish_names[MAX_BT_GENERIC_USB_DEVICES];
static char* publish_names[MAX_BT_GENERIC_USB_DEVICES];
int32 dev_count = 0; // number of connected devices
static bt_usb_dev* bt_usb_devices[MAX_BT_GENERIC_USB_DEVICES];
@@ -55,10 +53,9 @@ sem_id dev_table_sem = -1; // sem to synchronize access to device table
status_t submit_nbuffer(hci_id hid, net_buffer* nbuf);
usb_support_descriptor supported_devices[] =
{
// Generic Bluetooth USB device
// Class, SubClass, and Protocol codes that describe a Bluetooth device
usb_support_descriptor supported_devices[] = {
// Generic Bluetooth USB device
// Class, SubClass, and Protocol codes that describe a Bluetooth device
{ UDCLASS_WIRELESS, UDSUBCLASS_RF, UDPROTO_BLUETOOTH , 0 , 0 },
// Broadcom BCM2035
@@ -67,14 +64,14 @@ usb_support_descriptor supported_devices[] =
// Devices taken from the linux Driver
// AVM BlueFRITZ! USB v2.0
{ 0, 0, 0, 0x057c , 0x3800 },
{ 0, 0, 0, 0x057c, 0x3800 },
// Bluetooth Ultraport Module from IBM
{ 0, 0, 0, 0x04bf , 0x030a },
{ 0, 0, 0, 0x04bf, 0x030a },
// ALPS Modules with non-standard id
{ 0, 0, 0, 0x044e , 0x3001 },
{ 0, 0, 0, 0x044e , 0x3002 },
{ 0, 0, 0, 0x044e, 0x3001 },
{ 0, 0, 0, 0x044e, 0x3002 },
// Ericsson with non-standard id
{ 0, 0, 0, 0x0bdb , 0x1002 }
{ 0, 0, 0, 0x0bdb, 0x1002 }
};
/* add a device to the list of connected devices */
@@ -93,13 +90,13 @@ spawn_device(usb_device* usb_dev)
flowf("add_device()\n");
// 16 usb dongles...
// 16 usb dongles...
if (dev_count >= MAX_BT_GENERIC_USB_DEVICES) {
flowf("device table full\n");
goto exit;
}
/* try the allocation */
// try the allocation
new_bt_dev = (bt_usb_dev*)malloc(sizeof(bt_usb_dev));
if (new_bt_dev == NULL) {
flowf("no memory\n");
@@ -107,41 +104,43 @@ spawn_device(usb_device* usb_dev)
}
memset(new_bt_dev, 0, sizeof(bt_usb_dev));
/* We will need this sem for some flow control */
new_bt_dev->cmd_complete = create_sem(1, BLUETOOTH_DEVICE_DEVFS_NAME "cmd_complete");
// We will need this sem for some flow control
new_bt_dev->cmd_complete = create_sem(1,
BLUETOOTH_DEVICE_DEVFS_NAME "cmd_complete");
if (new_bt_dev->cmd_complete < 0) {
err = new_bt_dev->cmd_complete;
goto bail0;
}
/* and this for something else */
// and this for something else
new_bt_dev->lock = create_sem(1, BLUETOOTH_DEVICE_DEVFS_NAME "lock");
if (new_bt_dev->lock < 0) {
err = new_bt_dev->lock;
goto bail1;
}
/* find a free slot and fill out the name */
// find a free slot and fill out the name
acquire_sem(dev_table_sem);
for (i = 0; i < MAX_BT_GENERIC_USB_DEVICES; i++) {
if (bt_usb_devices[i] == NULL) {
bt_usb_devices[i] = new_bt_dev;
sprintf(new_bt_dev->name, "%s/%ld", BLUETOOTH_DEVICE_PATH, i);
new_bt_dev->num = i;
debugf("added device %p %ld %s\n", bt_usb_devices[i] ,new_bt_dev->num,new_bt_dev->name);
debugf("added device %p %ld %s\n", bt_usb_devices[i],
new_bt_dev->num, new_bt_dev->name);
break;
}
}
release_sem_etc(dev_table_sem, 1, B_DO_NOT_RESCHEDULE);
/* In the case we cannot us */
// In the case we cannot us
if (bt_usb_devices[i] != new_bt_dev) {
flowf("Device could not be added\n");
flowf("Device could not be added\n");
goto bail2;
}
new_bt_dev->dev = usb_dev;
/* TODO am i actually gonna use this? */
// TODO: currently only server opens
new_bt_dev->open_count = 0;
dev_count++;
@@ -158,7 +157,7 @@ exit:
}
/* remove a device from the list of connected devices */
// remove a device from the list of connected devices
static void
kill_device(bt_usb_dev* bdev)
{
@@ -180,40 +179,38 @@ kill_device(bt_usb_dev* bdev)
bt_usb_dev*
fetch_device(bt_usb_dev* dev, hci_id hid)
{
int i;
int i;
// debugf("(%p) or %d\n", dev, hid);
acquire_sem(dev_table_sem);
if (dev != NULL)
for (i = 0; i < MAX_BT_GENERIC_USB_DEVICES; i++) {
/* somehow the device is still around */
if (bt_usb_devices[i] == dev) {
release_sem_etc(dev_table_sem, 1, B_DO_NOT_RESCHEDULE);
return bt_usb_devices[i];
}
if (dev != NULL)
for (i = 0; i < MAX_BT_GENERIC_USB_DEVICES; i++) {
if (bt_usb_devices[i] == dev) {
release_sem_etc(dev_table_sem, 1, B_DO_NOT_RESCHEDULE);
return bt_usb_devices[i];
}
}
else
for (i = 0; i < MAX_BT_GENERIC_USB_DEVICES; i++) {
/* somehow the device is still around */
if (bt_usb_devices[i] != NULL && bt_usb_devices[i]->hdev == hid) {
release_sem_etc(dev_table_sem, 1, B_DO_NOT_RESCHEDULE);
return bt_usb_devices[i];
}
for (i = 0; i < MAX_BT_GENERIC_USB_DEVICES; i++) {
if (bt_usb_devices[i] != NULL && bt_usb_devices[i]->hdev == hid) {
release_sem_etc(dev_table_sem, 1, B_DO_NOT_RESCHEDULE);
return bt_usb_devices[i];
}
}
release_sem_etc(dev_table_sem, 1, B_DO_NOT_RESCHEDULE);
return NULL;
return NULL;
}
#if 0
#pragma mark -
#endif
/* called by USB Manager when device is added to the USB */
// called by USB Manager when device is added to the USB
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
static status_t
device_added(usb_device dev, void** cookie)
@@ -227,9 +224,9 @@ device_added(usb_device* dev, void** cookie)
const usb_interface_info* uif;
const usb_endpoint_info* ep;
status_t err = B_ERROR;
status_t err = B_ERROR;
bt_usb_dev* new_bt_dev = spawn_device(dev);
int e;
int e;
debugf("device_added(%ld, %p)\n", dev, new_bt_dev);
@@ -239,9 +236,9 @@ device_added(usb_device* dev, void** cookie)
goto bail_no_mem;
}
/* we only have 1 configuration number 0 */
// we only have 1 configuration number 0
config = usb->get_nth_configuration(dev, 0);
//dump_usb_configuration_info(config);
// dump_usb_configuration_info(config);
if (config == NULL) {
flowf("couldn't get default config.\n");
err = B_ERROR;
@@ -250,7 +247,7 @@ device_added(usb_device* dev, void** cookie)
debugf("found %ld alt interfaces.\n", config->interface->alt_count);
/* set first interface */
// set first interface
interface = &config->interface->alt[0];
err = usb->set_alt_interface(new_bt_dev->dev, interface);
@@ -259,17 +256,18 @@ device_added(usb_device* dev, void** cookie)
goto bail;
}
/* call set_configuration() only after calling set_alt_interface()*/
// call set_configuration() only after calling set_alt_interface()
err = usb->set_configuration(dev, config);
if (err != B_OK) {
debugf("set_configuration() returned %ld.\n", err);
goto bail;
}
/* Place to find out whats our concrete device and set up some special info to our driver */
/* TODO: if this code increases too much reconsider this implementation*/
// Place to find out whats our concrete device and set up some special
// info to our driver. If this code increases too much reconsider
// this implementation
desc = usb->get_device_descriptor(dev);
if (desc->vendor_id == 0x0a5c
if (desc->vendor_id == 0x0a5c
&& (desc->product_id == 0x200a
|| desc->product_id == 0x2009
|| desc->product_id == 0x2035)) {
@@ -278,18 +276,19 @@ device_added(usb_device* dev, void** cookie)
}
/*
else if ( desc->vendor_id == YOUR_VENDOR_HERE && desc->product_id == YOUR_PRODUCT_HERE ) {
else if ( desc->vendor_id == YOUR_VENDOR_HERE
&& desc->product_id == YOUR_PRODUCT_HERE ) {
YOUR_SPECIAL_FLAGS_HERE
}
*/
if (new_bt_dev->driver_info & BT_IGNORE_THIS_DEVICE){
if (new_bt_dev->driver_info & BT_IGNORE_THIS_DEVICE) {
err = ENODEV;
goto bail;
}
// security check
if (config->interface->active->descr->interface_number > 0){
if (config->interface->active->descr->interface_number > 0) {
debugf("Strange condition happened %d\n",
config->interface->active->descr->interface_number);
err = B_ERROR;
@@ -297,7 +296,7 @@ device_added(usb_device* dev, void** cookie)
}
debugf("Found %ld interfaces. Expected 3\n", config->interface_count);
/* Find endpoints that we need */
// Find endpoints that we need
uif = config->interface->active;
for (e = 0; e < uif->descr->num_endpoints; e++) {
@@ -328,21 +327,22 @@ device_added(usb_device* dev, void** cookie)
}
}
if (!new_bt_dev->bulk_in_ep || !new_bt_dev->bulk_out_ep || !new_bt_dev->intr_in_ep) {
if (!new_bt_dev->bulk_in_ep || !new_bt_dev->bulk_out_ep
|| !new_bt_dev->intr_in_ep) {
flowf("Minimal # endpoints for BT not found\n");
goto bail;
}
// Look into the devices suported to understand this
if (new_bt_dev->driver_info & BT_DIGIANSWER)
if (new_bt_dev->driver_info & BT_DIGIANSWER)
new_bt_dev->ctrl_req = USB_TYPE_VENDOR;
else
new_bt_dev->ctrl_req = USB_TYPE_CLASS;
new_bt_dev->connected = true;
new_bt_dev->connected = true;
/* set the cookie that will be passed to other USB
hook functions (currently device_removed() is the only other) */
// set the cookie that will be passed to other USB
// hook functions (currently device_removed() is the only other)
*cookie = new_bt_dev;
debugf("Ok %p\n", new_bt_dev);
return B_OK;
@@ -356,20 +356,20 @@ bail_no_mem:
}
/* called by USB Manager when device is removed from the USB */
// Called by USB Manager when device is removed from the USB
static status_t
device_removed(void* cookie)
{
bt_usb_dev* bdev = (bt_usb_dev*) fetch_device(cookie, 0);
bt_usb_dev* bdev = fetch_device((bt_usb_dev*)cookie, 0);
debugf("device_removed(%p)\n", bdev);
if (bdev == NULL) {
flowf(" not present in driver?\n");
return B_ERROR;
}
if (bdev == NULL) {
flowf(" not present in driver?\n");
return B_ERROR;
}
if (!TEST_AND_CLEAR(&bdev->state, RUNNING))
if (!TEST_AND_CLEAR(&bdev->state, RUNNING))
flowf("wasnt running?\n");
flowf("Cancelling queues...\n");
@@ -394,8 +394,17 @@ device_removed(void* cookie)
}
static usb_notify_hooks notify_hooks =
{
static bt_hci_transport_hooks bluetooth_hooks = {
NULL,
&submit_nbuffer,
&submit_nbuffer,
NULL,
NULL,
H2
};
static usb_notify_hooks notify_hooks = {
&device_added,
&device_removed
};
@@ -412,21 +421,21 @@ submit_nbuffer(hci_id hid, net_buffer* nbuf)
bdev = fetch_device(NULL, hid);
debugf("index=%lx nbuf=%p bdev=%p\n",hid, nbuf, bdev);
if (bdev != NULL) {
switch (nbuf->protocol) {
case BT_COMMAND:
// not issued this way
break;
case BT_ACL:
return submit_tx_acl(bdev, nbuf);
return submit_tx_acl(bdev, nbuf);
break;
default:
panic("submit_nbuffer: no protocol");
break;
}
}
@@ -435,9 +444,9 @@ submit_nbuffer(hci_id hid, net_buffer* nbuf)
}
/* implements the POSIX open() */
// implements the POSIX open()
static status_t
device_open(const char *name, uint32 flags, void **cookie)
device_open(const char* name, uint32 flags, void **cookie)
{
status_t err = ENODEV;
bt_usb_dev* bdev = NULL;
@@ -463,8 +472,8 @@ device_open(const char *name, uint32 flags, void **cookie)
// Set RUNNING
if (TEST_AND_SET(&bdev->state, RUNNING)) {
flowf("dev already running! - reOpened device!\n");
return B_ERROR;
flowf("dev already running! - reOpened device!\n");
return B_ERROR;
}
acquire_sem(bdev->lock);
@@ -481,30 +490,28 @@ device_open(const char *name, uint32 flags, void **cookie)
}
// dumping the USB frames
init_room(&bdev->eventRoom);
init_room(&bdev->aclRoom);
//init_room(new_bt_dev->scoRoom);
init_room(&bdev->eventRoom);
init_room(&bdev->aclRoom);
// init_room(new_bt_dev->scoRoom);
list_init(&bdev->snetBufferRecycleTrash);
list_init(&bdev->snetBufferRecycleTrash);
// Allocate set and register the HCI device
if (btDevices != NULL) {
struct net_device* ndev;
// TODO: Fill the transport descriptor
err = btDevices->init_device(bdev->name, &ndev);
if (err == B_OK) {
bdev->hdev = hdev = ndev->index; // get the index
bdev->ndev = ndev; // get the net_device
bluetooth_device* ndev;
// TODO: Fill the transport descriptor
err = btDevices->RegisterDriver(&bluetooth_hooks, &ndev);
ndev->media = (uint32)submit_nbuffer; //XXX: interlayer-Hack
if (err == B_OK) {
bdev->hdev = hdev = ndev->index; // Get the index
bdev->ndev = ndev; // Get the net_device
} else {
hdev = bdev->num; /* XXX: Lets try to go on*/
hdev = bdev->num; // XXX: Lets try to go on
}
} else {
hdev = bdev->num; /* XXX: Lets try to go on*/
}
} else {
hdev = bdev->num; // XXX: Lets try to go on
}
bdev->hdev = hdev;
@@ -518,9 +525,10 @@ device_open(const char *name, uint32 flags, void **cookie)
/* called when a client calls POSIX close() on the driver, but I/O
** requests may still be pending */
* requests may still be pending
*/
static status_t
device_close(void *cookie)
device_close(void* cookie)
{
int32 i;
void* item;
@@ -539,57 +547,56 @@ device_close(void *cookie)
usb->cancel_queued_transfers(bdev->intr_in_ep->handle);
flowf("Cancelling possible EVENTS\n");
}
if (bdev->bulk_in_ep!=NULL) {
usb->cancel_queued_transfers(bdev->bulk_in_ep->handle);
flowf("Cancelling possible ACL in\n");
}
if (bdev->bulk_out_ep!=NULL) {
usb->cancel_queued_transfers(bdev->bulk_out_ep->handle);
flowf("Cancelling possible ACL out\n");
}
}
// TX
for (i = 0; i < BT_DRIVER_TXCOVERAGE; i++) {
if (i == BT_COMMAND)
while ((item = list_remove_head_item(&bdev->nbuffersTx[i])) != NULL) {
snb_free(item);
snb_free((snet_buffer*)item);
}
else
while ((item = list_remove_head_item(&bdev->nbuffersTx[i])) != NULL) {
nb_destroy(item);
nb_destroy((net_buffer*)item);
}
}
// RX
for (i = 0; i < BT_DRIVER_RXCOVERAGE; i++) {
nb_destroy(bdev->nbufferRx[i]);
nb_destroy(bdev->nbufferRx[i]);
}
snb_free(bdev->eventRx);
purge_room(&bdev->eventRoom);
purge_room(&bdev->aclRoom);
purge_room(&bdev->eventRoom);
purge_room(&bdev->aclRoom);
/* Device no longer in our Stack*/
if (btDevices != NULL)
btDevices->uninit_device(bdev->ndev);
// Device no longer in our Stack
if (btDevices != NULL)
btDevices->UnregisterDriver(bdev->hdev);
// unSet RUNNING
if (TEST_AND_CLEAR(&bdev->state, RUNNING)) {
debugf(" %s not running?\n",bdev->name);
return B_ERROR;
debugf(" %s not running?\n",bdev->name);
return B_ERROR;
}
return B_OK;
}
/* called after device_close(), when all pending I/O requests have
* returned */
// Called after device_close(), when all pending I / O requests have returned
static status_t
device_free (void *cookie)
device_free (void* cookie)
{
status_t err = B_OK;
bt_usb_dev* bdev = (bt_usb_dev*)cookie;
@@ -605,9 +612,9 @@ device_free (void *cookie)
}
/* implements the POSIX ioctl() */
// implements the POSIX ioctl()
static status_t
device_control(void *cookie, uint32 msg, void *params, size_t size)
device_control(void* cookie, uint32 msg, void* params, size_t size)
{
status_t err = B_ERROR;
bt_usb_dev* bdev = (bt_usb_dev*)cookie;
@@ -634,7 +641,7 @@ device_control(void *cookie, uint32 msg, void *params, size_t size)
switch (msg) {
case ISSUE_BT_COMMAND:
#ifdef BT_IOCTLS_PASS_SIZE
if (size == 0) {
if (size == 0) {
flowf("Invalid size control\n");
err = B_BAD_VALUE;
break;
@@ -644,10 +651,10 @@ device_control(void *cookie, uint32 msg, void *params, size_t size)
(*(size_t**)&params)++;
#endif
// TODO: Reuse from some TXcompleted queue
//snbuf = snb_create(size);
snbuf = snb_fetch(&bdev->snetBufferRecycleTrash, size);
snb_put(snbuf, params, size);
// TODO: Reuse from some TXcompleted queue
// snbuf = snb_create(size);
snbuf = snb_fetch(&bdev->snetBufferRecycleTrash, size);
snb_put(snbuf, params, size);
err = submit_tx_command(bdev, snbuf);
debugf("command launched %ld\n", err);
@@ -655,10 +662,10 @@ device_control(void *cookie, uint32 msg, void *params, size_t size)
case BT_UP:
// EVENTS
// EVENTS
err = submit_rx_event(bdev);
if (err != B_OK) {
CLEAR_BIT(bdev->state, ANCILLYANT);
CLEAR_BIT(bdev->state, ANCILLYANT);
flowf("Queuing failed device stops running\n");
break;
}
@@ -667,10 +674,10 @@ device_control(void *cookie, uint32 msg, void *params, size_t size)
for (i = 0; i < MAX_ACL_IN_WINDOW; i++) {
err = submit_rx_acl(bdev);
if (err != B_OK && i == 0) {
CLEAR_BIT(bdev->state, ANCILLYANT); // Set the flaq in the HCI world
CLEAR_BIT(bdev->state, ANCILLYANT); // Set the flaq in the HCI world
flowf("Queuing failed device stops running\n");
break;
}
}
}
#endif
@@ -683,13 +690,13 @@ device_control(void *cookie, uint32 msg, void *params, size_t size)
break;
case GET_STATS:
memcpy(params, &bdev->stat, sizeof(bt_hci_statistics));
err = B_OK;
memcpy(params, &bdev->stat, sizeof(bt_hci_statistics));
err = B_OK;
break;
case GET_HCI_ID:
*(hci_id*)params = bdev->hdev;
err = B_OK;
*(hci_id*)params = bdev->hdev;
err = B_OK;
break;
@@ -704,9 +711,9 @@ device_control(void *cookie, uint32 msg, void *params, size_t size)
}
/* implements the POSIX read() */
// implements the POSIX read()
static status_t
device_read(void *cookie, off_t pos, void *buf, size_t *count)
device_read(void* cookie, off_t pos, void* buffer, size_t* count)
{
debugf("Reading... count = %ld\n", *count);
@@ -715,15 +722,16 @@ device_read(void *cookie, off_t pos, void *buf, size_t *count)
}
/* implements the POSIX write() */
// implements the POSIX write()
static status_t
device_write(void *cookie, off_t pos, const void *buf, size_t *count)
device_write(void* cookie, off_t pos, const void* buffer, size_t* count)
{
flowf("device_write()\n");
return B_ERROR;
}
#if 0
#pragma mark -
#endif
@@ -734,25 +742,27 @@ dump_driver(int argc, char** argv)
{
int i;
snet_buffer* item = NULL;
for (i = 0; i < MAX_BT_GENERIC_USB_DEVICES; i++) {
if (bt_usb_devices[i] != NULL) {
kprintf("%s : \n", bt_usb_devices[i]->name);
kprintf("\taclroom = %d\teventroom = %d\tcommand & events =%d\n", snb_packets(&bt_usb_devices[i]->eventRoom)
, snb_packets(&bt_usb_devices[i]->aclRoom)
, snb_packets(&bt_usb_devices[i]->snetBufferRecycleTrash) );
while ((item = list_get_next_item(&bt_usb_devices[i]->snetBufferRecycleTrash, item)) != NULL)
kprintf("\taclroom = %d\teventroom = %d\tcommand & events =%d\n",
snb_packets(&bt_usb_devices[i]->eventRoom),
snb_packets(&bt_usb_devices[i]->aclRoom),
snb_packets(&bt_usb_devices[i]->snetBufferRecycleTrash));
while ((item = (snet_buffer*)list_get_next_item(
&bt_usb_devices[i]->snetBufferRecycleTrash, item)) != NULL)
snb_dump(item);
}
}
}
return 0;
}
/* called each time the driver is loaded by the kernel */
// called each time the driver is loaded by the kernel
status_t
init_driver(void)
{
@@ -806,15 +816,15 @@ init_driver(void)
}
for (j = 0; j < MAX_BT_GENERIC_USB_DEVICES; j++) {
bt_usb_devices[j] = NULL;
bt_usb_devices[j] = NULL;
}
/* After here device_added and publish devices hooks are called
be carefull USB devs */
// Note: After here device_added and publish devices hooks are called
usb->register_driver(BLUETOOTH_DEVICE_DEVFS_NAME, supported_devices, 1, NULL);
usb->install_notify(BLUETOOTH_DEVICE_DEVFS_NAME, &notify_hooks);
add_debugger_command("bth2generic", &dump_driver, "Lists H2 Transport device info");
add_debugger_command("bth2generic", &dump_driver,
"Lists H2 Transport device info");
return B_OK;
@@ -830,12 +840,12 @@ err_release2:
put_module(btDevices_name);
err_release3:
put_module(BT_CORE_DATA_MODULE_NAME);
return B_ERROR;
}
/* called just before the kernel unloads the driver */
// called just before the kernel unloads the driver
void
uninit_driver(void)
{
@@ -849,10 +859,10 @@ uninit_driver(void)
free(publish_names[j]);
if (bt_usb_devices[j] != NULL) {
// if (connected_dev != NULL) {
// debugf("Device %p still exists.\n", connected_dev);
// }
debugf("%s still present?\n",bt_usb_devices[j]->name);
// if (connected_dev != NULL) {
// debugf("Device %p still exists.\n", connected_dev);
// }
debugf("%s still present?\n",bt_usb_devices[j]->name);
kill_device(bt_usb_devices[j]);
}
}
@@ -861,7 +871,7 @@ uninit_driver(void)
remove_debugger_command("bth2generic", &dump_driver);
/* Releasing modules */
// Releasing modules
put_module(usb_name);
put_module(hci_name);
// TODO: netbuffers
@@ -900,18 +910,18 @@ publish_devices(void)
release_sem_etc(dev_table_sem, 1, B_DO_NOT_RESCHEDULE);
publish_names[i] = NULL;
debugf("published %ld devices\n", i);
debugf("published %ld devices\n", i);
// TODO: this method might make better memory use
// dev_names = (char**)malloc(sizeof (char*) * (dev_count+1));
// if (dev_names) {
// for (i = 0; i < MAX_NUM_DEVS; i++) {
// if ((dev != NULL) &&
// (dev_names[i] = (char*)malloc(strlen(DEVICE_PATH)+2/* num + \n */))) {
// sprintf(dev_names[i], "%s%ld", DEVICE_PATH, dev->num);
// debugf("publishing \"%s\"\n", dev_names[i]);
// }
// }
// TODO: this method might make better memory use
// dev_names = (char**)malloc(sizeof(char*) * (dev_count + 1));
// if (dev_names) {
// for (i = 0; i < MAX_NUM_DEVS; i++) {
// if ((dev != NULL) // dev + \n
// && (dev_names[i] = (char*)malloc(strlen(DEVICE_PATH) + 2))) {
// sprintf(dev_names[i], "%s%ld", DEVICE_PATH, dev->num);
// debugf("publishing \"%s\"\n", dev_names[i]);
// }
// }
return (const char**)publish_names;
}
@@ -21,13 +21,13 @@
#include <util/list.h>
#include <bluetooth/HCI/btHCI.h>
#include <bluetooth/HCI/btHCI_module.h>
#include <bluetooth/HCI/btHCI_transport.h>
#include <btCoreData.h>
#include "snet_buffer.h"
/* USB definitions for the generic device*/
// USB definitions for the generic device move to h2cfg
#define UDCLASS_WIRELESS 0xe0
#define UDSUBCLASS_RF 0x01
#define UDPROTO_BLUETOOTH 0x01
@@ -45,7 +45,7 @@
extern usb_module_info* usb;
extern bt_hci_module_info* hci;
extern struct net_device_module_info* btDevices;
extern struct bt_hci_module_info* btDevices;
extern struct net_buffer_module_info* nb;
extern struct bluetooth_core_data_module_info* btCoreData;
@@ -64,9 +64,9 @@ struct bt_usb_dev {
#else
usb_device* dev; /* opaque handle */
#endif
hci_id hdev; /* HCI device id*/
struct net_device* ndev;
hci_id hdev; /* HCI device id*/
bluetooth_device* ndev;
char name[B_OS_NAME_LENGTH];
bool connected; /* is the device plugged into the USB? */
int32 open_count; /* number of clients of the device */
@@ -83,35 +83,36 @@ struct bt_usb_dev {
uint32 state;
bt_hci_statistics stat;
const usb_endpoint_info *bulk_in_ep;
uint16 max_packet_size_bulk_in;
const usb_endpoint_info *bulk_out_ep;
uint16 max_packet_size_bulk_out;
const usb_endpoint_info *intr_in_ep;
uint16 max_packet_size_intr_in;
const usb_endpoint_info* bulk_in_ep;
uint16 max_packet_size_bulk_in;
const usb_endpoint_info* bulk_out_ep;
uint16 max_packet_size_bulk_out;
const usb_endpoint_info* intr_in_ep;
uint16 max_packet_size_intr_in;
#ifdef BLUETOOTH_SUPPORTS_SCO
const usb_endpoint_info *iso_in_ep;
const usb_endpoint_info *iso_out_ep;
#endif
/* This so called rooms, are for dumping the USB RX frames
and try to reuse the allocations. see util submodule */
* and try to reuse the allocations. see util submodule
*/
struct list eventRoom;
struct list aclRoom;
struct list aclRoom;
// Tx buffers: net_buffers for BT_ACL and snet_buffers for BT_COMMAND
// in the same array
struct list nbuffersTx[BT_DRIVER_TXCOVERAGE];
// in the same array
struct list nbuffersTx[BT_DRIVER_TXCOVERAGE];
uint32 nbuffersPendingTx[BT_DRIVER_TXCOVERAGE];
// Rx buffer
net_buffer* nbufferRx[BT_DRIVER_RXCOVERAGE]; /* Wasting 1 pointer for BT_EVENT */
snet_buffer* eventRx; /* <- which we hold here */
net_buffer* nbufferRx[BT_DRIVER_RXCOVERAGE];
snet_buffer* eventRx;
// for who ever needs preallocated buffers
struct list snetBufferRecycleTrash;
struct list snetBufferRecycleTrash;
};
@@ -40,119 +40,10 @@ void event_complete(void* cookie, status_t status, void* data, size_t actual_len
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;
#ifdef DUMP_BUFFERS
int16 index;
#endif
bdev->stat.bytesRX += count;
if (type == BT_EVENT)
snbuf = bdev->eventRx;
else
nbuf = bdev->nbufferRx[type];
return btDevices->PostTransportPacket(bdev->hdev, type, data, count);
while (count) {
//debugf("count %d nb=%p sb=%p type=%d\n", count, nbuf, snbuf, type);
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);
#ifdef DUMP_BUFFERS
debugf("## Incoming EVENT frame %p len = %d ", snbuf, count);
for (index = 0 ; index < count; index++)
dprintf("%x:",((uint8*)data)[index]);
dprintf(" ## \n");
#endif
} 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 -> TODO: this allocation can fail
bdev->nbufferRx[type] = nbuf = nb->create(expectedPacketLen);
nbuf->protocol = type;
#ifdef DUMP_BUFFERS
debugf("## Incoming ACL frame %p len = %d ", nbuf, count);
for (index = 0 ; index < count; index++)
dprintf("%x:",((uint8*)data)[index]);
dprintf(" ## \n");
#endif
} else {
flowf("ACL frame corrupted\n");
return EILSEQ;
}
break;
case BT_SCO:
break;
default:
panic("unknown packet type in assembly");
break;
}
currentPacketLen = expectedPacketLen;
} else {
// Continuation of a packet
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)) {
post_packet_up(bdev, type, snbuf);
snbuf = bdev->eventRx = NULL;
}
if (type != BT_EVENT && (get_expected_size(nbuf) - nbuf->size) == 0 ) {
post_packet_up(bdev, type, nbuf);
bdev->nbufferRx[type] = nbuf = NULL;
} else {
#if DEBUG_ACL
if (type == BT_ACL)
debugf("ACL Packet not filled size=%ld expected=%ld\n",
nbuf->size, get_expected_size(nbuf));
#endif
}
/* in case in the pipe there is info about the next buffer ... */
count -= currentPacketLen;
data += currentPacketLen;
}
return B_OK;
}
@@ -160,7 +51,6 @@ assembly_rx(bt_usb_dev* bdev, bt_packet_t type, void* data, int count)
#pragma mark --- RX Complete ---
#endif
void
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
event_complete(void* cookie, uint32 status, void* data, uint32 actual_len)
@@ -168,8 +58,8 @@ event_complete(void* cookie, uint32 status, void* data, uint32 actual_len)
event_complete(void* cookie, status_t status, void* data, size_t actual_len)
#endif
{
bt_usb_dev* bdev = cookie;
//bt_usb_dev* bdev = fetch_device(cookie, 0); -> safer/slower option
bt_usb_dev* bdev = (bt_usb_dev*)cookie;
// bt_usb_dev* bdev = fetch_device(cookie, 0); -> safer / slower option
status_t error;
debugf("cookie@%p status=%s len=%ld\n", cookie, strerror(status), actual_len);
@@ -177,13 +67,13 @@ event_complete(void* cookie, status_t status, void* data, size_t actual_len)
if (bdev == NULL)
return;
if (status == B_CANCELED || status == B_DEV_CRC_ERROR) // or not running anymore...
return;
if (status == B_CANCELED || status == B_DEV_CRC_ERROR)
return; // or not running anymore...
if (status != B_OK || actual_len == 0)
goto resubmit;
if (assembly_rx(cookie, BT_EVENT, data, actual_len) == B_OK) {
if (assembly_rx(bdev, BT_EVENT, data, actual_len) == B_OK) {
bdev->stat.successfulTX++;
} else {
bdev->stat.errorRX++;
@@ -191,8 +81,8 @@ event_complete(void* cookie, status_t status, void* data, size_t actual_len)
resubmit:
error = usb->queue_interrupt(bdev->intr_in_ep->handle, data,
max(HCI_MAX_EVENT_SIZE, bdev->max_packet_size_intr_in), event_complete, bdev);
error = usb->queue_interrupt(bdev->intr_in_ep->handle, data,
max_c(HCI_MAX_EVENT_SIZE, bdev->max_packet_size_intr_in), event_complete, bdev);
if (error != B_OK) {
reuse_room(&bdev->eventRoom, data);
@@ -211,20 +101,20 @@ acl_rx_complete(void* cookie, uint32 status, void* data, uint32 actual_len)
acl_rx_complete(void* cookie, status_t status, void* data, size_t actual_len)
#endif
{
bt_usb_dev* bdev = cookie;
//bt_usb_dev* bdev = fetch_device(cookie, 0); -> safer/slower option
bt_usb_dev* bdev = (bt_usb_dev*)cookie;
// bt_usb_dev* bdev = fetch_device(cookie, 0); -> safer / slower option
status_t error;
if (bdev == NULL)
return;
if (status == B_CANCELED || status == B_DEV_CRC_ERROR) // or not running anymore...
return;
if (status == B_CANCELED || status == B_DEV_CRC_ERROR)
return; // or not running anymore...
if (status != B_OK || actual_len == 0)
goto resubmit;
if (assembly_rx(cookie, BT_ACL, data, actual_len) == B_OK) {
if (assembly_rx(bdev, BT_ACL, data, actual_len) == B_OK) {
bdev->stat.successfulRX++;
} else {
bdev->stat.errorRX++;
@@ -233,10 +123,10 @@ acl_rx_complete(void* cookie, status_t status, void* data, size_t actual_len)
resubmit:
error = usb->queue_bulk(bdev->bulk_in_ep->handle, data,
max(HCI_MAX_FRAME_SIZE, bdev->max_packet_size_bulk_in),
max_c(HCI_MAX_FRAME_SIZE, bdev->max_packet_size_bulk_in),
acl_rx_complete, (void*) bdev);
if (error != B_OK) {
if (error != B_OK) {
reuse_room(&bdev->aclRoom, data);
bdev->stat.rejectedRX++;
debugf("RX acl resubmittion failed %s\n", strerror(error));
@@ -245,6 +135,7 @@ resubmit:
}
}
#if 0
#pragma mark --- RX ---
#endif
@@ -252,7 +143,7 @@ resubmit:
status_t
submit_rx_event(bt_usb_dev* bdev)
{
size_t size = max(HCI_MAX_EVENT_SIZE, bdev->max_packet_size_intr_in);
size_t size = max_c(HCI_MAX_EVENT_SIZE, bdev->max_packet_size_intr_in);
void* buf = alloc_room(&bdev->eventRoom, size);
status_t status;
@@ -276,8 +167,8 @@ submit_rx_event(bt_usb_dev* bdev)
status_t
submit_rx_acl(bt_usb_dev* bdev)
{
size_t size = max(HCI_MAX_FRAME_SIZE, bdev->max_packet_size_bulk_in);
{
size_t size = max_c(HCI_MAX_FRAME_SIZE, bdev->max_packet_size_bulk_in);
void* buf = alloc_room(&bdev->aclRoom, size);
status_t status;
@@ -301,10 +192,11 @@ submit_rx_acl(bt_usb_dev* bdev)
status_t
submit_rx_sco(bt_usb_dev* bdev)
{
/* not yet implemented */
// not yet implemented
return B_ERROR;
}
#if 0
#pragma mark --- TX Complete ---
#endif
@@ -317,7 +209,7 @@ 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);
bt_usb_dev* bdev = (bt_usb_dev*)snb_cookie(snbuf);
debugf("status = %ld len = %ld @%p\n", status, actual_len, data);
@@ -326,13 +218,13 @@ command_complete(void* cookie, status_t status, void* data, size_t actual_len)
bdev->stat.bytesTX += actual_len;
} else {
bdev->stat.errorTX++;
// the packet has been lost,too late to requeue it?
// 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?
// TODO: check just the empty queues
schedTxProcessing(bdev);
#endif
}
@@ -348,22 +240,24 @@ acl_tx_complete(void* cookie, status_t status, void* data, size_t actual_len)
net_buffer* nbuf = (net_buffer*)cookie;
bt_usb_dev* bdev = GET_DEVICE(nbuf);
debugf("fetched=%p status=%ld nbuftype %lx B%p\n", bdev, status, nbuf->type, data);
debugf("fetched=%p status=%ld type %lx %p\n", bdev, status, nbuf->type, data);
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?
// 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
@@ -376,23 +270,23 @@ submit_tx_command(bt_usb_dev* bdev, snet_buffer* snbuf)
uint16 wIndex = 0;
uint16 value = 0;
uint16 wLength = B_HOST_TO_LENDIAN_INT16(snb_size(snbuf));
status_t error;
status_t error;
if (!GET_BIT(bdev->state, RUNNING)) {
return B_DEV_NOT_READY;
}
/* set cookie */
// set cookie
snb_set_cookie(snbuf, bdev);
debugf("@%p\n", snb_get(snbuf));
error = usb->queue_request(bdev->dev, bRequestType, bRequest,
value, wIndex, wLength, snb_get(snbuf),
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
wLength, //???
#endif
command_complete, (void*) snbuf);
value, wIndex, wLength, snb_get(snbuf),
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
wLength,
#endif
command_complete, (void*) snbuf);
if (error != B_OK) {
bdev->stat.rejectedTX++;
@@ -407,21 +301,20 @@ submit_tx_command(bt_usb_dev* bdev, snet_buffer* snbuf)
status_t
submit_tx_acl(bt_usb_dev* bdev, net_buffer* nbuf)
{
int32 index;
status_t error;
/* set cookie */
// set cookie
SET_DEVICE(nbuf, bdev->hdev);
if (!GET_BIT(bdev->state, RUNNING)) {
return B_DEV_NOT_READY;
}
/*
debugf("### Outgoing ACL: len = %ld\n", nbuf->size);
for (index = 0 ; index < nbuf->size; index++ ) {
for (uint32 index = 0 ; index < nbuf->size; index++ ) {
dprintf("%x:",((uint8*)nb_get_whole_buffer(nbuf))[index]);
}
flowf("### \n");
*/
error = usb->queue_bulk(bdev->bulk_out_ep->handle, nb_get_whole_buffer(nbuf),
nbuf->size, acl_tx_complete, (void*)nbuf);
@@ -444,6 +337,6 @@ submit_tx_sco(bt_usb_dev* bdev)
return B_DEV_NOT_READY;
}
/* not yet implemented */
// not yet implemented
return B_ERROR;
}
@@ -1,8 +1,6 @@
/*
* 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_
@@ -1,187 +0,0 @@
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
* Copyright 2008 Mika Lindqvist, monni1995_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 "h2generic.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;
debugf("(%p)\n", bdev)
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_ERROR;
debugf("Frame up type=%d\n", type);
if (type == BT_EVENT) {
snet_buffer* snbuf = (snet_buffer*)buf;
btCoreData->PostEvent(bdev->ndev, snb_get(snbuf), (size_t)snb_size(snbuf));
snb_park(&bdev->snetBufferRecycleTrash, snbuf);
debugf("to btDataCore len=%d\n", snb_size(snbuf));
} else {
net_buffer* nbuf = (net_buffer*) buf;
/* No need to free the buffer at allocation is gonna be reused */
btDevices->receive_data(bdev->ndev, &nbuf);
flowf("to net_device\n");
}
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("Unknown 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;
}
@@ -0,0 +1,189 @@
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
* Copyright 2008 Mika Lindqvist, monni1995_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 "h2generic.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;
debugf("(%p)\n", bdev)
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 = (snet_buffer*)
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 = (net_buffer*)
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);
}
}
#if 0
// DEPRECATED
status_t
post_packet_up(bt_usb_dev* bdev, bt_packet_t type, void* buf)
{
status_t err = B_ERROR;
debugf("Frame up type=%d\n", type);
if (type == BT_EVENT) {
snet_buffer* snbuf = (snet_buffer*)buf;
btCoreData->PostEvent(bdev->ndev, snb_get(snbuf),
(size_t)snb_size(snbuf));
snb_park(&bdev->snetBufferRecycleTrash, snbuf);
debugf("to btDataCore len=%d\n", snb_size(snbuf));
} else {
net_buffer* nbuf = (net_buffer*) buf;
// No need to free the buffer at allocation is gonna be reused
btDevices->receive_data(bdev->ndev, &nbuf);
flowf("to net_device\n");
}
return err;
}
#endif
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("Unknown 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 any case even if nbuf is null (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;
}
@@ -1,10 +1,7 @@
/*
* 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_
@@ -12,10 +9,10 @@
#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);
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);
void sched_tx_processing(bt_usb_dev* bdev);
#endif
#endif
@@ -22,21 +22,20 @@
void*
nb_get_whole_buffer(net_buffer* nbuf)
{
void* conPointer;
status_t err;
void* conPointer;
status_t err;
#if 0
/* the job could be already done */
// the job could be already done
// !!! it could be trash from other upper protocols...
if (nbuf->COOKIEFIELD != NULL)
return (void*)nbuf->COOKIEFIELD;
#endif
err = nb->direct_access(nbuf, 0, nbuf->size, &conPointer);
err = nb->direct_access(nbuf, 0, nbuf->size, &conPointer);
if (err != B_OK) {
snooze(3*1000*1000);
if (err != B_OK) {
panic("expected to be contiguous");
#if 0
/* pity, we are gonna need a realocation */
// We are gonna need a realocation
nbuf->COOKIEFIELD = (uint32) malloc(nbuf->size);
if (nbuf->COOKIEFIELD == NULL)
goto fail;
@@ -65,7 +64,7 @@ nb_destroy(net_buffer* nbuf)
if (nbuf == NULL)
return;
#if 0
/* Free possible allocated */
// Free possible allocated
if (nbuf->COOKIEFIELD != NULL)
free((void*)nbuf->COOKIEFIELD);
#endif
@@ -77,10 +76,10 @@ nb_destroy(net_buffer* nbuf)
// Extract the expected size of the packet
// TODO: This might be inefficient as at the moment of the creation of the net_buffer
// this information is known and it could be stored in any of the net_buffer fields
// but I still dont know how many of those am i gonna have free....
size_t
// TODO: This might be inefficient as at the moment of the creation
// of the net_buffer this information is known and it could be stored
#if 0
ssize_t
get_expected_size(net_buffer* nbuf)
{
@@ -114,14 +113,17 @@ get_expected_size(net_buffer* nbuf)
break;
}
return B_ERROR;
return -1;
}
#endif
#if 0
#pragma mark - room util -
#endif
inline void
void
init_room(struct list* l)
{
list_init(l);
@@ -142,7 +144,7 @@ alloc_room(struct list* l, size_t size)
}
inline void
void
reuse_room(struct list* l, void* room)
{
list_add_item(l, room);
@@ -1,10 +1,7 @@
/*
* 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_
@@ -14,7 +11,8 @@
/* net buffer utils for ACL, to be reviewed */
#define DEVICEFIELD type
#define SET_DEVICE(nbuf,hid) (nbuf->DEVICEFIELD=(nbuf->DEVICEFIELD&0xFFFFFF00)|(hid&0xFF))
#define SET_DEVICE(nbuf, hid) \
(nbuf->DEVICEFIELD=(nbuf->DEVICEFIELD & 0xFFFFFF00) | (hid & 0xFF))
#define GET_DEVICE(nbuf) fetch_device(NULL,(nbuf->DEVICEFIELD&0xFF))
#define COOKIEFIELD flags
@@ -23,10 +21,10 @@ 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);
void init_room(struct list* l);
void* alloc_room(struct list* l, size_t size);
void reuse_room(struct list* l, void* room);
void purge_room(struct list* l);
/* list utils */
#define list_purge(x) purge_room(x)
@@ -12,16 +12,16 @@
#include <KernelExport.h>
struct snet_buffer {
struct list_link link;
struct list_link link;
uint8* buffer;
uint8* buffer;
uint16 allocatedSize;
uint16 expectedSize;
uint16 puttingSize;
uint16 pullingSize;
uint16 allocatedSize;
uint16 expectedSize;
uint16 puttingSize;
uint16 pullingSize;
void* cookie;
void* cookie;
};
@@ -29,10 +29,10 @@ struct snet_buffer {
snet_buffer*
snb_create(uint16 size)
{
/* TODO: pointer checking */
// TODO: pointer checking
#ifdef SNB_BUFFER_ATTACHED
/* Allocating these 2 buffers together might prevent memory fragmentation? */
// 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
@@ -50,7 +50,7 @@ snb_create(uint16 size)
void
snb_put(snet_buffer* snb, void* data, uint16 size)
{
/* TODO: check overflow */
// TODO: check overflow
memcpy( &snb->buffer[snb->puttingSize], data, size);
snb->puttingSize+=size;
}
@@ -59,14 +59,14 @@ snb_put(snet_buffer* snb, void* data, uint16 size)
void*
snb_pull(snet_buffer* snb, uint16 size)
{
/* TODO: check overflow */
// TODO: check overflow
snb->pullingSize+=size;
return &snb->buffer[snb->pullingSize-size];
return &snb->buffer[snb->pullingSize - size];
}
inline void
void
snb_reset(snet_buffer* snb)
{
snb->puttingSize = snb->pullingSize = 0;
@@ -89,83 +89,88 @@ snb_free(snet_buffer* snb)
}
inline void*
void*
snb_get(snet_buffer* snb)
{
/* TODO: pointer checking */
// TODO: pointer checking
return snb->buffer;
}
inline uint16
uint16
snb_size(snet_buffer* snb)
{
/* TODO: pointer checking */
// TODO: pointer checking
return snb->expectedSize;
}
inline void*
void*
snb_cookie(snet_buffer* snb)
{
/* TODO: pointer checking */
// TODO: pointer checking
return snb->cookie;
}
inline void
void
snb_set_cookie(snet_buffer* snb, void* cookie)
{
/* TODO: pointer checking */
// 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 true if we canot "put" more data in the buffer
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 true if we cannot pull more more data from the buffer
bool
snb_finished(snet_buffer* snb)
{
return (snb->expectedSize == snb->pullingSize);
}
inline uint16 snb_remaining_to_put(snet_buffer* snb)
uint16
snb_remaining_to_put(snet_buffer* snb)
{
return (snb->expectedSize - snb->puttingSize);
}
inline uint16 snb_remaining_to_pull(snet_buffer* snb)
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:
/* 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: ?
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
ISSUE2: If the queue is not gonna be used for long time. Memory c
ould be freed
SOL1: Provide purge func.
SOL2: ?
*/
SOL1: Provide purge func.
SOL2: ?
*/
static snet_buffer*
snb_attempt_reuse(snet_buffer* snb, uint16 size)
{
if ( snb == NULL || (snb->allocatedSize < size) ) {
if (snb == NULL || (snb->allocatedSize < size)) {
/* Impossible or not worth, Creating a new one */
// Impossible or not worth, Creating a new one
snb_free(snb);
return snb_create(size);
@@ -183,15 +188,15 @@ 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) {
/* This one has allocated more than us place us back*/
// insert it by order
while ((item = (snet_buffer*)list_get_next_item(l, item)) != NULL) {
// This one has allocated more than us place us back
if (item->allocatedSize > snb->allocatedSize) {
list_insert_item_before(l, item, snb);
return;
}
}
/* no buffer bigger than us(or empty).. then at the end*/
// no buffer bigger than us(or empty).. then at the end
list_add_item(l, snb);
}
@@ -203,16 +208,18 @@ snb_fetch(struct list* l, uint16 size)
snet_buffer* newitem = NULL;
if (!list_is_empty(l))
while ((item = list_get_next_item(l, item)) != NULL) {
while ((item = (snet_buffer*)list_get_next_item(l, item)) != NULL) {
if (item->allocatedSize >= size) {
/* This one is for us*/
// This one is for us
break;
}
}
newitem = snb_attempt_reuse(item, size);
/* the resulting reused one is the same as we fetched? => remove it from list*/
/* the resulting reused one is the same
* as we fetched? => remove it from list
*/
if (item == newitem) {
list_remove_item(l, item);
}
@@ -227,7 +234,7 @@ snb_packets(struct list* l)
uint16 count = 0;
snet_buffer* item = NULL;
while ((item = list_get_next_item(l, item)) != NULL)
while ((item = (snet_buffer*)list_get_next_item(l, item)) != NULL)
count++;
return count;
@@ -237,5 +244,6 @@ snb_packets(struct list* l)
void
snb_dump(snet_buffer* snb)
{
kprintf("item=%p\tprev=%p\tnext=%p\tallocated=%d\n", snb, snb->link.prev, snb->link.next, snb->allocatedSize);
kprintf("item=%p\tprev=%p\tnext=%p\tallocated=%d\n", snb, snb->link.prev,
snb->link.next, snb->allocatedSize);
}
@@ -16,7 +16,7 @@
*
* 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.
* before allocating it, and you will never exceed it.
* 2) You are not supposed to prepend data, only append.
*
*/
@@ -31,43 +31,43 @@ 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);
snet_buffer* snb_create(uint16 size);
/* Free the snb_buffer*/
void snb_free(snet_buffer* snb);
void snb_free(snet_buffer* snb);
/* Free the snb_buffer*/
void* snb_get(snet_buffer* snb);
void* snb_get(snet_buffer* snb);
/* Size of the snb_buffer*/
uint16 snb_size(snet_buffer* snb);
uint16 snb_size(snet_buffer* snb);
/* Cookie of the snb_buffer*/
void* snb_cookie(snet_buffer* snb);
void* snb_cookie(snet_buffer* snb);
/* Get Cookie of the snb_buffer*/
void snb_set_cookie(snet_buffer* snb, void* cookie);
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);
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);
void* snb_pull(snet_buffer* snb, uint16 size);
/* Discards all data put or pulled from the buffer */
void snb_reset(snet_buffer* snb);
void snb_reset(snet_buffer* snb);
/* Return true if we canot "put" more data in the buffer */
bool snb_completed(snet_buffer* snb);
bool snb_completed(snet_buffer* snb);
/* Return true if we cannot pull more more data from the buffer */
bool snb_finished(snet_buffer* snb);
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);
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);
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.
* 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);
+1 -1
View File
@@ -2,4 +2,4 @@ SubDir HAIKU_TOP src add-ons kernel network devices ;
SubInclude HAIKU_TOP src add-ons kernel network devices ethernet ;
SubInclude HAIKU_TOP src add-ons kernel network devices loopback ;
SubInclude HAIKU_TOP src add-ons kernel network devices bluetooth ;
@@ -1,27 +0,0 @@
SubDir HAIKU_TOP src add-ons kernel network devices bluetooth ;
SetSubDirSupportedPlatformsBeOSCompatible ;
if $(TARGET_PLATFORM) != haiku {
UseHeaders [ FStandardOSHeaders ] : true ;
# Needed for <support/Errors.h> and maybe other stuff.
UseHeaders [ FDirName $(HAIKU_TOP) headers posix ] : true ;
# We need the public network headers also when not compiling for Haiku.
# Unfortunately we get more than we want, namely all POSIX headers.
}
UsePrivateKernelHeaders ;
UsePrivateHeaders net bluetooth ;
KernelAddon bluetooth :
bluetooth.cpp
acl.cpp
;
# Installation
#HaikuInstall install-networking : /boot/home/config/add-ons/kernel/haiku_network/devices
# : bluetooth ;
#Package haiku-networkingkit-cvs :
# haiku :
# boot home config add-ons kernel haiku_network protocols ;
@@ -39,11 +39,11 @@
status_t
l2cap_receive(HciConnection* conn, net_buffer* buffer)
{
status_t error = B_OK;
uint16 dcid;
uint16 length;
status_t error = B_OK;
uint16 dcid;
uint16 length;
/* Check packet */
// Check packet
if (buffer->size < sizeof(l2cap_hdr_t)) {
debugf("invalid L2CAP packet. Packet too small, len=%ld\n", buffer->size);
gBufferModule->free(buffer);
@@ -51,7 +51,7 @@ l2cap_receive(HciConnection* conn, net_buffer* buffer)
}
/* Get L2CAP header */
// Get L2CAP header
NetBufferHeaderReader<l2cap_hdr_t> bufferHeader(buffer);
status_t status = bufferHeader.Status();
if (status < B_OK) {
@@ -61,28 +61,28 @@ l2cap_receive(HciConnection* conn, net_buffer* buffer)
length = bufferHeader->length = le16toh(bufferHeader->length);
dcid = bufferHeader->dcid = le16toh(bufferHeader->dcid);
bufferHeader.Remove(); /* pulling */
bufferHeader.Remove(); // pulling
/* Check payload size */
// Check payload size
if (length != buffer->size ) {
debugf("invalid L2CAP packet. Payload length mismatch, packetlen=%d, nebufferlen=%ld\n",
length, buffer->size);
debugf("Payload length mismatch, packetlen=%d, bufferlen=%ld\n",
length, buffer->size);
gBufferModule->free(buffer);
return EMSGSIZE;
}
/* Process packet */
// Process packet
switch (dcid) {
case L2CAP_SIGNAL_CID: /* L2CAP command */
case L2CAP_SIGNAL_CID: // L2CAP command
error = l2cap_process_signal_cmd(conn, buffer);
break;
case L2CAP_CLT_CID: /* Connectionless packet
error = l2cap_cl_receive(buffer);*/
case L2CAP_CLT_CID: // Connectionless packet
// error = l2cap_cl_receive(buffer);
flowf("CL FRAME!!\n");
break;
default: /* Data packet */
default: // Data packet
error = l2cap_co_receive(conn, buffer, dcid);
break;
}
@@ -92,7 +92,7 @@ l2cap_receive(HciConnection* conn, net_buffer* buffer)
}
struct net_device_module_info* btDevices = NULL;
struct bt_hci_module_info* btDevices = NULL;
#if 0
#pragma mark - thread conn sched -
@@ -105,6 +105,7 @@ void
purge_connection(HciConnection* conn)
{
L2capFrame* frame;
bool containerCanBeDestroyed;
debugf("handle=%d\n", conn->handle);
@@ -118,42 +119,44 @@ purge_connection(HciConnection* conn)
// Here is the place to decide how many l2cap signals we want to have
// per l2cap packet. 1 ATM
if (frame->type == L2CAP_C_FRAME) {
if (frame->type == L2CAP_C_FRAME && IS_SIGNAL_REQ(frame->code)) {
btCoreData->TimeoutSignal(frame, bluetooth_l2cap_rtx_timeout);
btCoreData->QueueSignal(frame);
}
containerCanBeDestroyed = false;
} else
containerCanBeDestroyed = true;
// Add the l2cap header
if (frame->buffer == NULL)
panic("Malformed frame in ongoing queue");
NetBufferPrepend<l2cap_hdr_t> bufferHeader(frame->buffer);
status_t status = bufferHeader.Status();
if (status < B_OK) {
debugf("l2cap header could not be prepended!! frame code=%d\n", frame->code);
return;
{
NetBufferPrepend<l2cap_hdr_t> bufferHeader(frame->buffer);
status_t status = bufferHeader.Status();
if (status < B_OK) {
debugf("header could not be prepended! code=%d\n", frame->code);
return;
}
// fill
bufferHeader->length = htole16(frame->buffer->size - sizeof(l2cap_hdr_t));
switch (frame->type) {
case L2CAP_C_FRAME:
bufferHeader->dcid = L2CAP_SIGNAL_CID;
break;
case L2CAP_G_FRAME:
bufferHeader->dcid = L2CAP_CLT_CID;
break;
default:
bufferHeader->dcid = frame->channel->dcid;
break;
}
}
// fill
bufferHeader->length = htole16(frame->buffer->size - sizeof(l2cap_hdr_t));
switch (frame->type) {
case L2CAP_C_FRAME:
bufferHeader->dcid = L2CAP_SIGNAL_CID;
break;
case L2CAP_G_FRAME:
bufferHeader->dcid = L2CAP_CLT_CID;
break;
default:
bufferHeader->dcid = frame->channel->dcid;
break;
}
bufferHeader.Sync();
if (btDevices == NULL)
if (get_module(NET_BLUETOOTH_DEVICE_NAME, (module_info**)&btDevices) != B_OK) {
if (get_module(BT_HCI_MODULE_NAME, (module_info**)&btDevices) != B_OK) {
panic("l2cap: cannot get dev module");
} // TODO: someone put it
@@ -161,7 +164,13 @@ purge_connection(HciConnection* conn)
debugf("dev %p frame %p tolower\n", conn->ndevice, frame->buffer);
frame->buffer->type = conn->handle;
btDevices->send_data(conn->ndevice, frame->buffer);
btDevices->PostACL(conn->ndevice->index, frame->buffer);
// Only in the case that we need a response the frame container needs
// to be kept: Request C-Frames
if (containerCanBeDestroyed) {
delete frame;
}
// frame = conn->OutGoingFrames.RemoveHead();
// }
@@ -170,7 +179,7 @@ purge_connection(HciConnection* conn)
static status_t
connection_thread(void *)
connection_thread(void*)
{
int32 code;
ssize_t ssizePort;
@@ -187,24 +196,24 @@ connection_thread(void *)
while ((ssizePort = port_buffer_size(fPort)) != B_BAD_PORT_ID) {
if (ssizePort <= 0) {
debugf("Error %s\n", strerror(ssizePort));
snooze(500*1000);
continue;
}
if (ssizePort <= 0) {
debugf("Error %s\n", strerror(ssizePort));
snooze(500 * 1000);
continue;
}
if (ssizePort > (ssize_t) sizeof(conn)) {
debugf("Message too big %ld\n", ssizePort);
snooze(500*1000);
debugf("Message too big %ld\n", ssizePort);
snooze(500 * 1000);
continue;
}
ssizeRead = read_port(fPort, &code, &conn, ssizePort);
if (ssizeRead != ssizePort) {
debugf("Missmatch size port=%ld read=%ld\n", ssizePort, ssizeRead);
snooze(500*1000);
continue;
debugf("Missmatch size port=%ld read=%ld\n", ssizePort, ssizeRead);
snooze(500 * 1000);
continue;
}
purge_connection(conn);
@@ -263,8 +272,6 @@ SchedConnectionPurgeThread(HciConnection* conn)
status_t error = write_port(port, (uint32) conn, &temp, sizeof(conn));
//debugf("error post %s port=%ld size=%ld\n", strerror(error), port, sizeof(conn));
if (error != B_OK)
panic("BT Connection sched failed");