- 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
-35
View File
@@ -1,35 +0,0 @@
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef _BTHCI_MODULE_H_
#define _BTHCI_MODULE_H_
/* includes */
#include <bluetooth/HCI/btHCI.h>
#include <bluetooth/HCI/btHCI_transport.h>
#include <net_buffer.h>
/* defines */
#define BT_HCI_MODULE_NAME "bus_managers/hci/v1"
/* TODO: Possible definition of a bus manager of whatever is gonna be on the top */
typedef struct bt_hci_module_info {
/* registration */
status_t (*RegisterDriver)(bt_hci_transport* desc, hci_id *id /*out*/,
bt_hci_device* cookie /*out*/ );
status_t (*UnregisterDriver)(hci_id id);
/* Transferences to be called from drivers */
status_t (*PostACL)(hci_id id, net_buffer* nbuf);
status_t (*PostSCO)(hci_id id, net_buffer* nbuf);
/* Management */
bt_hci_device* (*GetHciDevice)(hci_id id);
} bt_hci_module_info ;
#endif // _BTHCI_MODULE_H_
+86 -19
View File
@@ -7,16 +7,21 @@
#include <bluetooth/HCI/btHCI.h> #include <bluetooth/HCI/btHCI.h>
#include <util/DoublyLinkedList.h>
#include <net_buffer.h> #include <net_buffer.h>
#include <Drivers.h> #include <Drivers.h>
typedef enum { ANCILLYANT = (1<<0),
typedef enum {
ANCILLYANT = (1<<0),
RUNNING = (1<<1), RUNNING = (1<<1),
LEAVING = (1<<2), LEAVING = (1<<2),
SENDING = (1<<3), SENDING = (1<<3),
PROCESSING = (1<<4) PROCESSING = (1<<4)
} bt_transport_status_t; } bt_transport_status_t;
typedef uint8 bt_stat_t; typedef uint8 bt_stat_t;
typedef struct bt_hci_statistics { typedef struct bt_hci_statistics {
bt_stat_t acceptedTX; bt_stat_t acceptedTX;
@@ -42,18 +47,6 @@ typedef struct bt_hci_statistics {
bt_stat_t bytesTX; bt_stat_t bytesTX;
} bt_hci_statistics; } bt_hci_statistics;
/* TODO: Possible hooks which drivers will have to provide */
typedef struct bt_hci_transport {
status_t (*SendCommand)(hci_id hci_dev, net_buffer *snbuf);
status_t (*SendPacket)(hci_id hci_dev, net_buffer *nbuf );
status_t (*SendSCO)(hci_id hci_dev, net_buffer *nbuf );
status_t (*DeliverStatistics)(bt_hci_statistics *statistics);
transport_type kind;
char name[B_OS_NAME_LENGTH];
} bt_hci_transport;
typedef struct bt_hci_device { typedef struct bt_hci_device {
transport_type kind; transport_type kind;
@@ -61,17 +54,90 @@ typedef struct bt_hci_device {
} bt_hci_device; } bt_hci_device;
/* Here the transport driver have some flags that */ /* Hooks which drivers will have to provide.
/* can be used to inform the upper layer about some */ * The structure is meant to be allocated in driver side and
/* special behaouvior to perform */ * provided to the HCI where it will fill the remaining fields
*/
typedef struct bt_hci_transport_hooks {
// to be filled by driver
status_t (*SendCommand)(hci_id hciId, void* command);
status_t (*SendACL)(hci_id hciId, net_buffer* nbuf );
status_t (*SendSCO)(hci_id hciId, net_buffer* nbuf );
status_t (*SendESCO)(hci_id hciId, net_buffer* nbuf );
status_t (*DeliverStatistics)(hci_id hciId, bt_hci_statistics* statistics);
transport_type kind;
} bt_hci_transport_hooks;
typedef struct bt_hci_device_information {
uint32 flags;
uint16 vendorId;
uint16 deviceId;
char name[B_OS_NAME_LENGTH];
} bt_hci_device_information;
#ifdef __cplusplus
struct bluetooth_device : DoublyLinkedListLinkImpl<bluetooth_device> {
net_buffer* fBuffersRx[HCI_NUM_PACKET_TYPES];
size_t fExpectedPacketSize[HCI_NUM_PACKET_TYPES];
hci_id index;
int fd;
bt_hci_device_information* info;
bt_hci_transport_hooks* hooks;
uint16 mtu;
};
#else
struct bluetooth_device;
#endif
#define BT_HCI_MODULE_NAME "bluetooth/hci/v1"
// Possible definition of a bus manager
typedef struct bt_hci_module_info {
module_info info;
// Registration in Stack
status_t (*RegisterDriver)(bt_hci_transport_hooks* hooks,
bluetooth_device** device);
status_t (*UnregisterDriver)(hci_id id);
bluetooth_device* (*FindDeviceByID)(hci_id id);
// to be called from transport driver
status_t (*PostTransportPacket)(hci_id hid, bt_packet_t type,
void* data, size_t count);
// To be called from upper layers
status_t (*PostACL)(hci_id hciId, net_buffer* buffer);
status_t (*PostSCO)(hci_id hciId, net_buffer* buffer);
status_t (*PostESCO)(hci_id hciId, net_buffer* buffer);
} bt_hci_module_info ;
/* Here the transport driver have some flags that
* can be used to inform the upper layer about some
* special behaouvior to perform */
#define BT_IGNORE_THIS_DEVICE (1 << 0) #define BT_IGNORE_THIS_DEVICE (1 << 0)
#define BT_SCO_NOT_WORKING (1 << 1) #define BT_SCO_NOT_WORKING (1 << 1)
#define BT_WILL_NEED_A_RESET (1 << 2) #define BT_WILL_NEED_A_RESET (1 << 2)
#define BT_DIGIANSWER (1 << 4) #define BT_DIGIANSWER (1 << 4)
/* Mandatory IOCTLS to be */ // Mandatory IOCTLS
#define BT_IOCTLS_OFFSET 3000 #define BT_IOCTLS_OFFSET 3000
enum { enum {
@@ -89,7 +155,8 @@ enum {
/* Port drivers can use to send information (1 for all for /* Port drivers can use to send information (1 for all for
at moment refer to ioctl GET_NOTIFICATION_PORT)*/ at moment refer to ioctl GET_NOTIFICATION_PORT)*/
#define BT_USERLAND_PORT_NAME "Kernel-User Event" #define BT_USERLAND_PORT_NAME "BT Kernel-User Event"
#define BT_RX_PORT_NAME "BT Kernel RX assembly"
#define BLUETOOTH_CONNECTION_PORT "bluetooth connection port" #define BLUETOOTH_CONNECTION_PORT "bluetooth connection port"
#define BLUETOOTH_CONNECTION_SCHED_PORT "bluetooth con sched port" #define BLUETOOTH_CONNECTION_SCHED_PORT "bluetooth con sched port"
+30 -15
View File
@@ -15,6 +15,7 @@
#include <bluetooth/bluetooth.h> #include <bluetooth/bluetooth.h>
#include <bluetooth/HCI/btHCI.h> #include <bluetooth/HCI/btHCI.h>
#include <bluetooth/HCI/btHCI_transport.h>
#include <l2cap.h> #include <l2cap.h>
#define BT_CORE_DATA_MODULE_NAME "bluetooth/btCoreData/v1" #define BT_CORE_DATA_MODULE_NAME "bluetooth/btCoreData/v1"
@@ -35,14 +36,14 @@ struct HciConnection : DoublyLinkedListLinkImpl<HciConnection> {
virtual ~HciConnection(); virtual ~HciConnection();
hci_id Hid; hci_id Hid;
struct net_device* ndevice; bluetooth_device* ndevice;
net_buffer* currentRxPacket; net_buffer* currentRxPacket;
ssize_t currentRxExpectedLength; ssize_t currentRxExpectedLength;
bdaddr_t destination; bdaddr_t destination;
uint16 handle; uint16 handle;
int type; int type;
uint16 mtu; uint16 mtu;
connection_status status; /* ACL connection state */ connection_status status;
uint16 lastCid; uint16 lastCid;
uint8 lastIdent; uint8 lastIdent;
DoublyLinkedList<L2capChannel> ChannelList; DoublyLinkedList<L2capChannel> ChannelList;
@@ -134,39 +135,53 @@ struct L2capFrame : DoublyLinkedListLinkImpl<L2capFrame> {
struct bluetooth_core_data_module_info { struct bluetooth_core_data_module_info {
module_info info; module_info info;
status_t (*PostEvent)(struct net_device* ndev, void* event, size_t size); status_t (*PostEvent)(bluetooth_device* ndev, void* event,
struct HciConnection* (*AddConnection)(uint16 handle, int type, bdaddr_t* dst, hci_id hid); size_t size);
struct HciConnection* (*AddConnection)(uint16 handle, int type,
bdaddr_t* dst, hci_id hid);
/*status_t (*RemoveConnection)(bdaddr_t destination, hci_id hid);*/ // status_t (*RemoveConnection)(bdaddr_t destination, hci_id hid);
status_t (*RemoveConnection)(uint16 handle, hci_id hid); status_t (*RemoveConnection)(uint16 handle, hci_id hid);
hci_id (*RouteConnection)(bdaddr_t* destination); hci_id (*RouteConnection)(bdaddr_t* destination);
void (*SetAclBuffer)(struct HciConnection* conn, net_buffer* nbuf); void (*SetAclBuffer)(struct HciConnection* conn,
void (*SetAclExpectedSize)(struct HciConnection* conn, size_t size); net_buffer* nbuf);
void (*AclPutting)(struct HciConnection* conn, size_t size); void (*SetAclExpectedSize)(struct HciConnection* conn,
size_t size);
void (*AclPutting)(struct HciConnection* conn,
size_t size);
bool (*AclComplete)(struct HciConnection* conn); bool (*AclComplete)(struct HciConnection* conn);
bool (*AclOverFlowed)(struct HciConnection* conn); bool (*AclOverFlowed)(struct HciConnection* conn);
struct HciConnection* (*ConnectionByHandle)(uint16 handle, hci_id hid); struct HciConnection* (*ConnectionByHandle)(uint16 handle, hci_id hid);
struct HciConnection* (*ConnectionByDestination)(bdaddr_t* destination, hci_id hid); struct HciConnection* (*ConnectionByDestination)(bdaddr_t* destination,
hci_id hid);
struct L2capChannel* (*AddChannel)(struct HciConnection* conn, uint16 psm); struct L2capChannel* (*AddChannel)(struct HciConnection* conn,
void (*RemoveChannel)(struct HciConnection* conn, uint16 scid); uint16 psm);
struct L2capChannel* (*ChannelBySourceID)(struct HciConnection* conn, uint16 sid); void (*RemoveChannel)(struct HciConnection* conn,
uint16 scid);
struct L2capChannel* (*ChannelBySourceID)(struct HciConnection* conn,
uint16 sid);
uint16 (*ChannelAllocateCid)(struct HciConnection* conn); uint16 (*ChannelAllocateCid)(struct HciConnection* conn);
uint16 (*ChannelAllocateIdent)(struct HciConnection* conn); uint16 (*ChannelAllocateIdent)(struct HciConnection* conn);
struct L2capFrame* (*SignalByIdent)(struct HciConnection* conn, uint8 ident); struct L2capFrame* (*SignalByIdent)(struct HciConnection* conn,
uint8 ident);
status_t (*TimeoutSignal)(struct L2capFrame* frame, uint32 timeo); status_t (*TimeoutSignal)(struct L2capFrame* frame, uint32 timeo);
status_t (*UnTimeoutSignal)(struct L2capFrame* frame); status_t (*UnTimeoutSignal)(struct L2capFrame* frame);
struct L2capFrame* (*SpawnFrame)(struct HciConnection* conn, struct L2capChannel* channel, net_buffer* buffer, frame_type frame); struct L2capFrame* (*SpawnFrame)(struct HciConnection* conn,
struct L2capFrame* (*SpawnSignal)(struct HciConnection* conn, struct L2capChannel* channel, net_buffer* buffer, uint8 ident, uint8 code); struct L2capChannel* channel, net_buffer* buffer, frame_type frame);
struct L2capFrame* (*SpawnSignal)(struct HciConnection* conn,
struct L2capChannel* channel, net_buffer* buffer,
uint8 ident, uint8 code);
status_t (*AcknowledgeSignal)(struct L2capFrame* frame); status_t (*AcknowledgeSignal)(struct L2capFrame* frame);
status_t (*QueueSignal)(struct L2capFrame* frame); status_t (*QueueSignal)(struct L2capFrame* frame);
}; };
inline bool ExistConnectionByDestination(bdaddr_t* destination, hci_id hid); inline bool ExistConnectionByDestination(bdaddr_t* destination, hci_id hid);
inline bool ExistConnectionByHandle(uint16 handle, hci_id hid); inline bool ExistConnectionByHandle(uint16 handle, hci_id hid);
-1
View File
@@ -6,7 +6,6 @@
#define _BTMODULES_H #define _BTMODULES_H
#define NET_BLUETOOTH_DEVICE_NAME "network/devices/bluetooth/v1"
#define NET_BLUETOOTH_L2CAP_NAME "network/protocols/l2cap/v1" #define NET_BLUETOOTH_L2CAP_NAME "network/protocols/l2cap/v1"
#endif // _BCOREDATA_H #endif // _BCOREDATA_H
+1
View File
@@ -1,3 +1,4 @@
SubDir HAIKU_TOP src add-ons kernel bluetooth ; 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 btCoreData ;
SubInclude HAIKU_TOP src add-ons kernel bluetooth hci ;
@@ -17,6 +17,7 @@
DoublyLinkedList<HciConnection> sConnectionList; DoublyLinkedList<HciConnection> sConnectionList;
net_buffer_module_info* gBufferModule = NULL; net_buffer_module_info* gBufferModule = NULL;
inline bool inline bool
ExistConnectionByDestination(bdaddr_t* destination, hci_id hid = -1) ExistConnectionByDestination(bdaddr_t* destination, hci_id hid = -1)
{ {
@@ -37,17 +38,21 @@ DumpHciConnections(int argc, char** argv)
HciConnection* conn; HciConnection* conn;
L2capChannel* chan; L2capChannel* chan;
L2capFrame* frame; L2capFrame* frame;
DoublyLinkedList<HciConnection>::Iterator iterator = sConnectionList.GetIterator(); DoublyLinkedList<HciConnection>::Iterator iterator
= sConnectionList.GetIterator();
while (iterator.HasNext()) { while (iterator.HasNext()) {
conn = iterator.Next(); conn = iterator.Next();
kprintf("LocalDevice=%lx Destination=%s handle=%#x type=%d outqueue=%ld expected=%ld\n", kprintf("LocalDevice=%lx Destination=%s handle=%#x type=%d"
conn->Hid, bdaddrUtils::ToString(conn->destination), "outqueue=%ld expected=%ld\n", conn->Hid,
conn->handle, conn->type, conn->OutGoingFrames.Count() , conn->ExpectedResponses.Count()); bdaddrUtils::ToString(conn->destination), conn->handle, conn->type,
conn->OutGoingFrames.Count() , conn->ExpectedResponses.Count());
// each channel // each channel
kprintf("\tChannels\n"); kprintf("\tChannels\n");
DoublyLinkedList<L2capChannel>::Iterator channelIterator = conn->ChannelList.GetIterator(); DoublyLinkedList<L2capChannel>::Iterator channelIterator
= conn->ChannelList.GetIterator();
while (channelIterator.HasNext()) { while (channelIterator.HasNext()) {
chan = channelIterator.Next(); chan = channelIterator.Next();
kprintf("\t\tscid=%x dcid=%x state=%x cfg=%x\n", chan->scid, kprintf("\t\tscid=%x dcid=%x state=%x cfg=%x\n", chan->scid,
@@ -56,20 +61,25 @@ DumpHciConnections(int argc, char** argv)
// Each outgoing // Each outgoing
kprintf("\n\tOutGoingFrames\n"); kprintf("\n\tOutGoingFrames\n");
DoublyLinkedList<L2capFrame>::Iterator frameIterator = conn->OutGoingFrames.GetIterator(); DoublyLinkedList<L2capFrame>::Iterator frameIterator
= conn->OutGoingFrames.GetIterator();
while (frameIterator.HasNext()) { while (frameIterator.HasNext()) {
frame = frameIterator.Next(); frame = frameIterator.Next();
kprintf("\t\tscid=%x code=%x ident=%x type=%x, buffer=%p\n", frame->channel->scid, kprintf("\t\tscid=%x code=%x ident=%x type=%x, buffer=%p\n",
frame->code, frame->ident, frame->type, frame->buffer); frame->channel->scid, frame->code, frame->ident,
frame->type, frame->buffer);
} }
// Each expected // Each expected
kprintf("\n\tExpectedFrames\n"); kprintf("\n\tExpectedFrames\n");
DoublyLinkedList<L2capFrame>::Iterator frameExpectedIterator = conn->ExpectedResponses.GetIterator(); DoublyLinkedList<L2capFrame>::Iterator frameExpectedIterator
= conn->ExpectedResponses.GetIterator();
while (frameExpectedIterator.HasNext()) { while (frameExpectedIterator.HasNext()) {
frame = frameExpectedIterator.Next(); frame = frameExpectedIterator.Next();
kprintf("\t\tscid=%x code=%x ident=%x type=%x, buffer=%p\n", frame->channel->scid, kprintf("\t\tscid=%x code=%x ident=%x type=%x, buffer=%p\n",
frame->code, frame->ident, frame->type, frame->buffer); frame->channel->scid, frame->code, frame->ident,
frame->type, frame->buffer);
} }
} }
@@ -77,9 +87,8 @@ DumpHciConnections(int argc, char** argv)
} }
status_t 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; struct hci_event_header* outgoingEvent = (struct hci_event_header*) event;
status_t err; status_t err;
@@ -88,23 +97,32 @@ PostEvent(net_device* ndev, void* event, size_t size)
switch (outgoingEvent->ecode) { switch (outgoingEvent->ecode) {
case HCI_EVENT_CONN_COMPLETE: case HCI_EVENT_CONN_COMPLETE:
{ {
struct hci_ev_conn_complete* data = (struct hci_ev_conn_complete*)(outgoingEvent+1); struct hci_ev_conn_complete* data
= (struct hci_ev_conn_complete*)(outgoingEvent + 1);
// TODO: XXX parse handle field // TODO: XXX parse handle field
HciConnection* conn = AddConnection(data->handle, BT_ACL, &data->bdaddr, ndev->index); HciConnection* conn = AddConnection(data->handle, BT_ACL,
&data->bdaddr, ndev->index);
if (conn == NULL) if (conn == NULL)
panic("no mem for conn desc"); panic("no mem for conn desc");
conn->ndevice = ndev; conn->ndevice = ndev;
debugf("Registered connection handle=%#x\n",data->handle); debugf("Registered connection handle=%#x\n",data->handle);
break;
} break; }
case HCI_EVENT_DISCONNECTION_COMPLETE: case HCI_EVENT_DISCONNECTION_COMPLETE:
{ {
struct hci_ev_disconnection_complete_reply* data = struct hci_ev_disconnection_complete_reply* data;
(struct hci_ev_disconnection_complete_reply*)(outgoingEvent+1);
data = (struct hci_ev_disconnection_complete_reply*)
(outgoingEvent + 1);
RemoveConnection(data->handle, ndev->index); RemoveConnection(data->handle, ndev->index);
debugf("unRegistered connection handle=%#x\n",data->handle); debugf("unRegistered connection handle=%#x\n",data->handle);
} break; break;
}
} }
// forward to bluetooth server // forward to bluetooth server
@@ -122,7 +140,6 @@ PostEvent(net_device* ndev, void* event, size_t size)
err = B_NAME_NOT_FOUND; err = B_NAME_NOT_FOUND;
} }
return err; return err;
} }
@@ -138,10 +155,10 @@ bcd_std_ops(int32 op, ...)
add_debugger_command("btConnections", &DumpHciConnections, 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); status = get_module(NET_BUFFER_MODULE_NAME,
if (status < B_OK) { (module_info **)&gBufferModule);
if (status < B_OK)
return status; return status;
}
return B_OK; return B_OK;
@@ -159,6 +176,7 @@ bcd_std_ops(int32 op, ...)
return B_ERROR; return B_ERROR;
} }
bluetooth_core_data_module_info sBCDModule = { bluetooth_core_data_module_info sBCDModule = {
{ {
BT_CORE_DATA_MODULE_NAME, BT_CORE_DATA_MODULE_NAME,
@@ -167,7 +185,7 @@ bluetooth_core_data_module_info sBCDModule = {
}, },
PostEvent, PostEvent,
AddConnection, AddConnection,
/* RemoveConnection,*/ // RemoveConnection,
RemoveConnection, RemoveConnection,
RouteConnection, RouteConnection,
+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; 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)) { 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); gBufferModule->free(nbuf);
return (EMSGSIZE); return (EMSGSIZE);
} }
/* Strip ACL data packet header */ // Strip ACL data packet header
NetBufferHeaderReader<struct hci_acl_header> aclHeader(nbuf); NetBufferHeaderReader<struct hci_acl_header> aclHeader(nbuf);
status_t status = aclHeader.Status(); status_t status = aclHeader.Status();
if (status < B_OK) { if (status < B_OK) {
@@ -54,7 +54,7 @@ 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); aclHeader->handle = le16toh(aclHeader->handle);
uint16 con_handle = get_acl_handle(aclHeader->handle); uint16 con_handle = get_acl_handle(aclHeader->handle);
@@ -63,17 +63,16 @@ AclAssembly(net_buffer* nbuf, hci_id hid)
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 // a) Ensure there is HCI connection
b) Get connection descriptor // b) Get connection descriptor
c) veryfy the status of the connection // c) veryfy the status of the connection
*/
HciConnection* conn = btCoreData->ConnectionByHandle(con_handle, hid); HciConnection* conn = btCoreData->ConnectionByHandle(con_handle, hid);
if (conn == NULL) { if (conn == NULL) {
//debugf("unexpected ACL!Connection does not exist!schedule! con_handle=%#x\n", con_handle); debugf("Uexpected handle=%#x does not exist!\n", con_handle);
panic("unexpected ACL!Connection does not exist!schedule!\n");
conn = btCoreData->AddConnection(con_handle, BT_ACL, BDADDR_NULL, hid); 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 (pb == HCI_ACL_PACKET_START) {
if (conn->currentRxPacket != NULL) { 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); gBufferModule->free(conn->currentRxPacket);
conn->currentRxPacket = NULL; conn->currentRxPacket = NULL;
conn->currentRxExpectedLength = 0; conn->currentRxExpectedLength = 0;
@@ -96,7 +96,8 @@ AclAssembly(net_buffer* nbuf, hci_id hid)
// Get L2CAP header, ACL header was dimissed // Get L2CAP header, ACL header was dimissed
if (nbuf->size < sizeof(l2cap_hdr_t)) { 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); gBufferModule->free(nbuf);
return (EMSGSIZE); return (EMSGSIZE);
} }
@@ -112,9 +113,10 @@ AclAssembly(net_buffer* nbuf, hci_id hid)
l2capHeader->length = le16toh(l2capHeader->length); l2capHeader->length = le16toh(l2capHeader->length);
l2capHeader->dcid = le16toh(l2capHeader->dcid); 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->currentRxPacket = nbuf;
conn->currentRxExpectedLength = l2capHeader->length + sizeof(l2cap_hdr_t); conn->currentRxExpectedLength = l2capHeader->length + sizeof(l2cap_hdr_t);
@@ -125,7 +127,7 @@ AclAssembly(net_buffer* nbuf, hci_id hid)
return (EINVAL); return (EINVAL);
} }
/* Add fragment to the L2CAP packet */ // Add fragment to the L2CAP packet
gBufferModule->merge(conn->currentRxPacket, nbuf, true); gBufferModule->merge(conn->currentRxPacket, nbuf, true);
} else { } else {
@@ -134,12 +136,14 @@ AclAssembly(net_buffer* nbuf, hci_id hid)
return (EINVAL); 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) { if (conn->currentRxExpectedLength < 0) {
debugf("packet length mismatch. Got %ld bytes, expected %ld bytes\n", conn->currentRxPacket->size, debugf("Mismatch. Got %ld, expected %ld\n",
conn->currentRxExpectedLength); conn->currentRxPacket->size, conn->currentRxExpectedLength);
gBufferModule->free(conn->currentRxPacket); gBufferModule->free(conn->currentRxPacket);
conn->currentRxPacket = NULL; conn->currentRxPacket = NULL;
conn->currentRxExpectedLength = 0; conn->currentRxExpectedLength = 0;
@@ -152,7 +156,8 @@ AclAssembly(net_buffer* nbuf, hci_id hid)
conn->currentRxPacket = NULL; conn->currentRxPacket = NULL;
conn->currentRxExpectedLength = 0; conn->currentRxExpectedLength = 0;
} else { } else {
debugf("Expected %ld current acl apports %d\n", conn->currentRxExpectedLength, length); debugf("Expected %ld current adds %d\n",
conn->currentRxExpectedLength, length);
} }
return error; return error;
@@ -169,6 +174,6 @@ PostToUpper(HciConnection* conn, net_buffer* buf)
return B_ERROR; return B_ERROR;
} // TODO: someone put it } // 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> #include <NetBufferUtilities.h>
#define BT_DEBUG_THIS_MODULE #define BT_DEBUG_THIS_MODULE
#define SUBMODULE_NAME "bluetooth_device" #define SUBMODULE_NAME "hci"
#define SUBMODULE_COLOR 34 #define SUBMODULE_COLOR 34
#include <btDebug.h> #include <btDebug.h>
#include <btCoreData.h> #include <btCoreData.h>
#include <btModules.h> #include <btModules.h>
#include <CodeHandler.h> #include <CodeHandler.h>
#define KERNEL_LAND
#include <PortListener.h>
#undef KERNEL_LAND
#include <bluetooth/HCI/btHCI.h> #include <bluetooth/HCI/btHCI.h>
#include <bluetooth/HCI/btHCI_acl.h> #include <bluetooth/HCI/btHCI_acl.h>
#include <bluetooth/HCI/btHCI_command.h> #include <bluetooth/HCI/btHCI_command.h>
#include <bluetooth/HCI/btHCI_event.h> #include <bluetooth/HCI/btHCI_event.h>
#include <bluetooth/HCI/btHCI_transport.h>
#include <bluetooth/HCI/btHCI_sco.h> #include <bluetooth/HCI/btHCI_sco.h>
#include <bluetooth/bdaddrUtils.h> #include <bluetooth/bdaddrUtils.h>
#include "acl.h" #include "acl.h"
struct bluetooth_device : net_device, DoublyLinkedListLinkImpl<bluetooth_device> { typedef PortListener<void,
HCI_MAX_FRAME_SIZE, // Event Body can hold max 255 + 2 header
net_buffer* fBuffersRx[HCI_NUM_PACKET_TYPES]; 24 // Some devices have sent chunks of 24 events(inquiry result)
size_t fExpectedPacketSize[HCI_NUM_PACKET_TYPES]; > BluetoothRawDataPort;
int fd;
uint16 mtu;
};
/* Modules references */ // Modules references
net_buffer_module_info* gBufferModule = NULL; net_buffer_module_info* gBufferModule = NULL;
static net_stack_module_info* sStackModule = NULL;
struct bluetooth_core_data_module_info* btCoreData = NULL; struct bluetooth_core_data_module_info* btCoreData = NULL;
static mutex sListLock; static mutex sListLock;
static DoublyLinkedList<bluetooth_device> sDeviceList;
static sem_id sLinkChangeSemaphore; static sem_id sLinkChangeSemaphore;
static DoublyLinkedList<bluetooth_device> sDeviceList;
BluetoothRawDataPort* BluetoothRXPort;
// forward declarations // 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* bluetooth_device*
@@ -68,11 +69,12 @@ FindDeviceByID(hci_id hid)
{ {
bluetooth_device* device; bluetooth_device* device;
DoublyLinkedList<bluetooth_device>::Iterator iterator = sDeviceList.GetIterator(); DoublyLinkedList<bluetooth_device>::Iterator iterator
while (iterator.HasNext()) { = sDeviceList.GetIterator();
while (iterator.HasNext()) {
device = iterator.Next(); device = iterator.Next();
if (device->index == (uint32 )hid) if (device->index == hid)
return device; return device;
} }
@@ -81,9 +83,21 @@ FindDeviceByID(hci_id hid)
status_t 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]; net_buffer* nbuf = bluetoothDevice->fBuffersRx[type];
size_t currentPacketLen = 0; size_t currentPacketLen = 0;
@@ -95,15 +109,17 @@ Assemble(net_device* netDevice, bt_packet_t type, void* data, size_t count)
switch (type) { switch (type) {
case BT_EVENT: case BT_EVENT:
if (count >= HCI_EVENT_HDR_SIZE) { if (count >= HCI_EVENT_HDR_SIZE) {
struct hci_event_header* headerPkt struct hci_event_header* headerPacket
= (struct hci_event_header*)data; = (struct hci_event_header*)data;
bluetoothDevice->fExpectedPacketSize[type] 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. // the whole packet is here so it can be already posted.
flowf("EVENT posted in HCI!!!\n");
btCoreData->PostEvent(bluetoothDevice, data, btCoreData->PostEvent(bluetoothDevice, data,
bluetoothDevice->fExpectedPacketSize[type]); bluetoothDevice->fExpectedPacketSize[type]);
} else { } else {
nbuf = gBufferModule->create( nbuf = gBufferModule->create(
bluetoothDevice->fExpectedPacketSize[type]); bluetoothDevice->fExpectedPacketSize[type]);
@@ -113,7 +129,7 @@ Assemble(net_device* netDevice, bt_packet_t type, void* data, size_t count)
} }
} else { } else {
flowf("EVENT frame corrupted\n"); panic("EVENT frame corrupted\n");
return EILSEQ; return EILSEQ;
} }
break; break;
@@ -132,7 +148,7 @@ Assemble(net_device* netDevice, bt_packet_t type, void* data, size_t count)
nbuf->protocol = type; nbuf->protocol = type;
} else { } else {
flowf("ACL frame corrupted\n"); panic("ACL frame corrupted\n");
return EILSEQ; return EILSEQ;
} }
break; break;
@@ -152,9 +168,7 @@ Assemble(net_device* netDevice, bt_packet_t type, void* data, size_t count)
// Continuation of a packet // Continuation of a packet
currentPacketLen = bluetoothDevice->fExpectedPacketSize[type] - nbuf->size; currentPacketLen = bluetoothDevice->fExpectedPacketSize[type] - nbuf->size;
} }
if (nbuf != NULL) { if (nbuf != NULL) {
currentPacketLen = min_c(currentPacketLen, count); currentPacketLen = min_c(currentPacketLen, count);
gBufferModule->append(nbuf, data, currentPacketLen); gBufferModule->append(nbuf, data, currentPacketLen);
@@ -163,11 +177,16 @@ Assemble(net_device* netDevice, bt_packet_t type, void* data, size_t count)
switch (nbuf->protocol) { switch (nbuf->protocol) {
case BT_EVENT: case BT_EVENT:
btCoreData->PostEvent(netDevice, data, panic("need to send full buffer to btdatacore!\n");
btCoreData->PostEvent(bluetoothDevice, data,
bluetoothDevice->fExpectedPacketSize[type]); bluetoothDevice->fExpectedPacketSize[type]);
break; break;
case BT_ACL: 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; break;
default: default:
@@ -197,12 +216,18 @@ Assemble(net_device* netDevice, bt_packet_t type, void* data, size_t count)
status_t status_t
HciPacketHandler(void* data, int32 code, size_t size) HciPacketHandler(void* data, int32 code, size_t size)
{ {
bluetooth_device* bluetoothDevice hci_id deviceId = Bluetooth::CodeHandler::Device(code);
= FindDeviceByID(Bluetooth::CodeHandler::Device(code));
bluetooth_device* bluetoothDevice = FindDeviceByID(deviceId);
debugf("to assemble %ld bytes of %ld\n", size, deviceId);
if (bluetoothDevice != NULL) if (bluetoothDevice != NULL)
return Assemble(bluetoothDevice, Bluetooth::CodeHandler::Protocol(code), return Assemble(bluetoothDevice, Bluetooth::CodeHandler::Protocol(code),
data, size); data, size);
else {
debugf("Device %ld could not be matched\n", deviceId);
}
return B_ERROR; return B_ERROR;
} }
@@ -212,31 +237,22 @@ HciPacketHandler(void* data, int32 code, size_t size)
status_t 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; bluetooth_device* device = new (std::nothrow) bluetooth_device;
if (device == NULL) { if (device == NULL)
put_module(NET_BUFFER_MODULE_NAME);
return B_NO_MEMORY; 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 device->mtu = L2CAP_MTU_MINIMUM; // TODO: ensure specs min value
strcpy(device->name, name);
MutexLocker _(&sListLock); MutexLocker _(&sListLock);
@@ -244,92 +260,58 @@ bluetooth_init(const char* name, net_device** _device)
device->index = HCI_DEVICE_INDEX_OFFSET; // REVIEW: dev index device->index = HCI_DEVICE_INDEX_OFFSET; // REVIEW: dev index
else else
device->index = (sDeviceList.Tail())->index + 1; // REVIEW! 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); sDeviceList.Add(device);
debugf("Device %s %lx\n", device->name, device->index ); debugf("Device %lx\n", device->index );
*_device = device; *_device = device;
return B_OK; return B_OK;
} }
status_t 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 if (device->GetDoublyLinkedListLink()->next != NULL
|| device->GetDoublyLinkedListLink()->previous != NULL || device->GetDoublyLinkedListLink()->previous != NULL
|| device == sDeviceList.Head()) || device == sDeviceList.Head())
sDeviceList.Remove(device); sDeviceList.Remove(device);
put_module(NET_BUFFER_MODULE_NAME);
delete device; delete device;
return B_OK; return B_OK;
} }
// PostACL
status_t 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* curr_frame = NULL;
net_buffer* next_frame = buffer; net_buffer* next_frame = buffer;
uint16 handle = buffer->type; // TODO: CodeHandler
uint8 flag = HCI_ACL_PACKET_START; 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); device->index, buffer->size, buffer->flags);
// TODO: ATOMIC! any other thread should stop here // TODO: ATOMIC! any other thread should stop here
@@ -337,13 +319,14 @@ bluetooth_send_data(net_device* _device, net_buffer* buffer)
// Divide packet if big enough // Divide packet if big enough
curr_frame = next_frame; curr_frame = next_frame;
if (next_frame->size > device->mtu) { if (curr_frame->size > device->mtu) {
next_frame = gBufferModule->split(curr_frame, device->mtu); next_frame = gBufferModule->split(curr_frame, device->mtu);
} else { } else {
next_frame = NULL; next_frame = NULL;
} }
// Attach acl header // Attach acl header
{
NetBufferPrepend<struct hci_acl_header> bufferHeader(curr_frame); NetBufferPrepend<struct hci_acl_header> bufferHeader(curr_frame);
status_t status = bufferHeader.Status(); status_t status = bufferHeader.Status();
if (status < B_OK) { if (status < B_OK) {
@@ -353,100 +336,33 @@ bluetooth_send_data(net_device* _device, net_buffer* buffer)
bufferHeader->handle = pack_acl_handle_flags(handle, flag, 0); bufferHeader->handle = pack_acl_handle_flags(handle, flag, 0);
bufferHeader->alen = curr_frame->size - sizeof(struct hci_acl_header); bufferHeader->alen = curr_frame->size - sizeof(struct hci_acl_header);
}
bufferHeader.Sync(); // Send to driver
// Send to driver XXX: another interlayer trick
debugf("tolower nbuf %p\n",curr_frame);
curr_frame->protocol = BT_ACL; 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; flag = HCI_ACL_PACKET_FRAGMENT;
} while (next_frame == NULL); } while (next_frame != NULL);
return B_OK; return B_OK;
} }
status_t status_t
bluetooth_receive_data(net_device* _device, net_buffer** _buffer) PostSCO(hci_id hciId, net_buffer* buffer)
{ {
bluetooth_device* device = (bluetooth_device*)_device; return B_ERROR;
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;
} }
status_t status_t
bluetooth_set_mtu(net_device* _device, size_t mtu) PostESCO(hci_id hciId, net_buffer* buffer)
{ {
bluetooth_device* device = (bluetooth_device*)_device; return B_ERROR;
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;
} }
@@ -455,11 +371,12 @@ dump_bluetooth_devices(int argc, char** argv)
{ {
bluetooth_device* device; bluetooth_device* device;
DoublyLinkedList<bluetooth_device>::Iterator iterator = sDeviceList.GetIterator(); DoublyLinkedList<bluetooth_device>::Iterator iterator
= sDeviceList.GetIterator();
while (iterator.HasNext()) { while (iterator.HasNext()) {
device = iterator.Next(); 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; return 0;
@@ -477,9 +394,9 @@ bluetooth_std_ops(int32 op, ...)
{ {
status_t status; 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) { if (status < B_OK) {
flowf("problem getting netstack module\n"); panic("no way Dude we need that!");
return status; return status;
} }
@@ -492,6 +409,17 @@ bluetooth_std_ops(int32 op, ...)
new (&sDeviceList) DoublyLinkedList<bluetooth_device>; new (&sDeviceList) DoublyLinkedList<bluetooth_device>;
// static C++ objects are not initialized in the module startup // 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"); sLinkChangeSemaphore = create_sem(0, "bt sem");
if (sLinkChangeSemaphore < B_OK) { if (sLinkChangeSemaphore < B_OK) {
put_module(NET_STACK_MODULE_NAME); put_module(NET_STACK_MODULE_NAME);
@@ -515,6 +443,7 @@ bluetooth_std_ops(int32 op, ...)
delete_sem(sLinkChangeSemaphore); delete_sem(sLinkChangeSemaphore);
mutex_destroy(&sListLock); mutex_destroy(&sListLock);
put_module(NET_BUFFER_MODULE_NAME);
put_module(NET_STACK_MODULE_NAME); put_module(NET_STACK_MODULE_NAME);
put_module(BT_CORE_DATA_MODULE_NAME); put_module(BT_CORE_DATA_MODULE_NAME);
remove_debugger_command("btLocalDevices", &dump_bluetooth_devices); 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, B_KEEP_LOADED,
bluetooth_std_ops bluetooth_std_ops
}, },
bluetooth_init, RegisterDriver,
bluetooth_uninit, UnregisterDriver,
bluetooth_up, FindDeviceByID,
bluetooth_down, PostTransportPacket,
bluetooth_control, PostACL,
bluetooth_send_data, PostSCO,
bluetooth_receive_data, PostESCO
bluetooth_set_mtu,
bluetooth_set_promiscuous,
bluetooth_set_media,
bluetooth_add_multicast,
bluetooth_remove_multicast,
}; };
@@ -18,11 +18,11 @@ if ! $(TARGET_PLATFORM_HAIKU_COMPATIBLE) {
} }
KernelAddon h2generic : KernelAddon h2generic :
h2generic.c h2generic.cpp
h2transactions.c h2transactions.cpp
h2upper.c h2upper.cpp
h2util.c h2util.cpp
snet_buffer.c snet_buffer.cpp
$(r5_src) $(r5_src)
; ;
@@ -1,10 +1,7 @@
/* /*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com * Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*
*/ */
#ifndef _H2CFG_H_ #ifndef _H2CFG_H_
#define _H2CFG_H_ #define _H2CFG_H_
@@ -16,10 +13,11 @@
#define BT_DRIVER_SUPPORTS_ESCO 0 #define BT_DRIVER_SUPPORTS_ESCO 0
// TODO: move exclusive header for drivers
/* TODO: move exclusive header for drivers*/ #define BT_DRIVER_RXCOVERAGE (BT_DRIVER_SUPPORTS_EVT + BT_DRIVER_SUPPORTS_ACL \
#define BT_DRIVER_RXCOVERAGE (BT_DRIVER_SUPPORTS_EVT+BT_DRIVER_SUPPORTS_ACL+BT_DRIVER_SUPPORTS_SCO+BT_DRIVER_SUPPORTS_ESCO) + 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) #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 #error incomplete Bluetooth driver Commands and Events should be implemented
@@ -28,8 +26,6 @@
#define BT_SURVIVE_WITHOUT_HCI #define BT_SURVIVE_WITHOUT_HCI
//#define BT_SURVIVE_WITHOUT_NET_BUFFERS //#define BT_SURVIVE_WITHOUT_NET_BUFFERS
////////////////////////////////////
#ifndef BLUETOOTH_DEVICE_TRANSPORT #ifndef BLUETOOTH_DEVICE_TRANSPORT
#error BLUETOOTH_DEVICE_TRANSPORT must be defined to build the publishing path #error BLUETOOTH_DEVICE_TRANSPORT must be defined to build the publishing path
#endif #endif
@@ -38,8 +34,11 @@
#error BLUETOOTH_DEVICE_NAME must be defined to build the publishing path #error BLUETOOTH_DEVICE_NAME must be defined to build the publishing path
#endif #endif
#define BLUETOOTH_DEVICE_DEVFS_NAME BLUETOOTH_DEVICE_TRANSPORT BLUETOOTH_DEVICE_NAME #define BLUETOOTH_DEVICE_DEVFS_NAME BLUETOOTH_DEVICE_TRANSPORT \
#define BLUETOOTH_DEVICE_PATH "bluetooth/" BLUETOOTH_DEVICE_TRANSPORT "/" BLUETOOTH_DEVICE_DEVFS_NAME BLUETOOTH_DEVICE_NAME
#define BLUETOOTH_DEVICE_PATH "bluetooth/" BLUETOOTH_DEVICE_TRANSPORT "/" \
BLUETOOTH_DEVICE_DEVFS_NAME
#endif #endif
@@ -17,8 +17,6 @@
#include "snet_buffer.h" #include "snet_buffer.h"
#include <bluetooth/bluetooth_util.h> #include <bluetooth/bluetooth_util.h>
#include <bluetooth/HCI/btHCI.h>
#include <bluetooth/HCI/btHCI_module.h>
#define BT_DEBUG_THIS_MODULE #define BT_DEBUG_THIS_MODULE
#define SUBMODULE_NAME BLUETOOTH_DEVICE_DEVFS_NAME #define SUBMODULE_NAME BLUETOOTH_DEVICE_DEVFS_NAME
@@ -34,15 +32,15 @@
int32 api_version = B_CUR_DRIVER_API_VERSION; int32 api_version = B_CUR_DRIVER_API_VERSION;
/* Modules */ // Modules
static char* usb_name = B_USB_MODULE_NAME; static char* usb_name = B_USB_MODULE_NAME;
static char* hci_name = BT_HCI_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; usb_module_info* usb = NULL;
bt_hci_module_info* hci = NULL; bt_hci_module_info* hci = NULL; // TODO remove / clean
struct net_device_module_info* btDevices = NULL; struct bt_hci_module_info* btDevices = NULL;
struct net_buffer_module_info* nb = NULL; struct net_buffer_module_info* nb = NULL;
struct bluetooth_core_data_module_info* btCoreData = NULL; struct bluetooth_core_data_module_info* btCoreData = NULL;
@@ -55,8 +53,7 @@ sem_id dev_table_sem = -1; // sem to synchronize access to device table
status_t submit_nbuffer(hci_id hid, net_buffer* nbuf); status_t submit_nbuffer(hci_id hid, net_buffer* nbuf);
usb_support_descriptor supported_devices[] = usb_support_descriptor supported_devices[] = {
{
// Generic Bluetooth USB device // Generic Bluetooth USB device
// Class, SubClass, and Protocol codes that describe a Bluetooth device // Class, SubClass, and Protocol codes that describe a Bluetooth device
{ UDCLASS_WIRELESS, UDSUBCLASS_RF, UDPROTO_BLUETOOTH , 0 , 0 }, { UDCLASS_WIRELESS, UDSUBCLASS_RF, UDPROTO_BLUETOOTH , 0 , 0 },
@@ -99,7 +96,7 @@ spawn_device(usb_device* usb_dev)
goto exit; goto exit;
} }
/* try the allocation */ // try the allocation
new_bt_dev = (bt_usb_dev*)malloc(sizeof(bt_usb_dev)); new_bt_dev = (bt_usb_dev*)malloc(sizeof(bt_usb_dev));
if (new_bt_dev == NULL) { if (new_bt_dev == NULL) {
flowf("no memory\n"); flowf("no memory\n");
@@ -107,41 +104,43 @@ spawn_device(usb_device* usb_dev)
} }
memset(new_bt_dev, 0, sizeof(bt_usb_dev)); memset(new_bt_dev, 0, sizeof(bt_usb_dev));
/* We will need this sem for some flow control */ // We will need this sem for some flow control
new_bt_dev->cmd_complete = create_sem(1, BLUETOOTH_DEVICE_DEVFS_NAME "cmd_complete"); new_bt_dev->cmd_complete = create_sem(1,
BLUETOOTH_DEVICE_DEVFS_NAME "cmd_complete");
if (new_bt_dev->cmd_complete < 0) { if (new_bt_dev->cmd_complete < 0) {
err = new_bt_dev->cmd_complete; err = new_bt_dev->cmd_complete;
goto bail0; goto bail0;
} }
/* and this for something else */ // and this for something else
new_bt_dev->lock = create_sem(1, BLUETOOTH_DEVICE_DEVFS_NAME "lock"); new_bt_dev->lock = create_sem(1, BLUETOOTH_DEVICE_DEVFS_NAME "lock");
if (new_bt_dev->lock < 0) { if (new_bt_dev->lock < 0) {
err = new_bt_dev->lock; err = new_bt_dev->lock;
goto bail1; 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); acquire_sem(dev_table_sem);
for (i = 0; i < MAX_BT_GENERIC_USB_DEVICES; i++) { for (i = 0; i < MAX_BT_GENERIC_USB_DEVICES; i++) {
if (bt_usb_devices[i] == NULL) { if (bt_usb_devices[i] == NULL) {
bt_usb_devices[i] = new_bt_dev; bt_usb_devices[i] = new_bt_dev;
sprintf(new_bt_dev->name, "%s/%ld", BLUETOOTH_DEVICE_PATH, i); sprintf(new_bt_dev->name, "%s/%ld", BLUETOOTH_DEVICE_PATH, i);
new_bt_dev->num = 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; break;
} }
} }
release_sem_etc(dev_table_sem, 1, B_DO_NOT_RESCHEDULE); 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) { if (bt_usb_devices[i] != new_bt_dev) {
flowf("Device could not be added\n"); flowf("Device could not be added\n");
goto bail2; goto bail2;
} }
new_bt_dev->dev = usb_dev; new_bt_dev->dev = usb_dev;
/* TODO am i actually gonna use this? */ // TODO: currently only server opens
new_bt_dev->open_count = 0; new_bt_dev->open_count = 0;
dev_count++; 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 static void
kill_device(bt_usb_dev* bdev) kill_device(bt_usb_dev* bdev)
{ {
@@ -187,7 +186,6 @@ fetch_device(bt_usb_dev* dev, hci_id hid)
acquire_sem(dev_table_sem); acquire_sem(dev_table_sem);
if (dev != NULL) if (dev != NULL)
for (i = 0; i < MAX_BT_GENERIC_USB_DEVICES; i++) { for (i = 0; i < MAX_BT_GENERIC_USB_DEVICES; i++) {
/* somehow the device is still around */
if (bt_usb_devices[i] == dev) { if (bt_usb_devices[i] == dev) {
release_sem_etc(dev_table_sem, 1, B_DO_NOT_RESCHEDULE); release_sem_etc(dev_table_sem, 1, B_DO_NOT_RESCHEDULE);
return bt_usb_devices[i]; return bt_usb_devices[i];
@@ -195,7 +193,6 @@ fetch_device(bt_usb_dev* dev, hci_id hid)
} }
else else
for (i = 0; i < MAX_BT_GENERIC_USB_DEVICES; i++) { 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) { if (bt_usb_devices[i] != NULL && bt_usb_devices[i]->hdev == hid) {
release_sem_etc(dev_table_sem, 1, B_DO_NOT_RESCHEDULE); release_sem_etc(dev_table_sem, 1, B_DO_NOT_RESCHEDULE);
return bt_usb_devices[i]; return bt_usb_devices[i];
@@ -208,12 +205,12 @@ fetch_device(bt_usb_dev* dev, hci_id hid)
return NULL; return NULL;
} }
#if 0 #if 0
#pragma mark - #pragma mark -
#endif #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 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
static status_t static status_t
device_added(usb_device dev, void** cookie) device_added(usb_device dev, void** cookie)
@@ -239,7 +236,7 @@ device_added(usb_device* dev, void** cookie)
goto bail_no_mem; 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); config = usb->get_nth_configuration(dev, 0);
// dump_usb_configuration_info(config); // dump_usb_configuration_info(config);
if (config == NULL) { if (config == NULL) {
@@ -250,7 +247,7 @@ device_added(usb_device* dev, void** cookie)
debugf("found %ld alt interfaces.\n", config->interface->alt_count); debugf("found %ld alt interfaces.\n", config->interface->alt_count);
/* set first interface */ // set first interface
interface = &config->interface->alt[0]; interface = &config->interface->alt[0];
err = usb->set_alt_interface(new_bt_dev->dev, interface); err = usb->set_alt_interface(new_bt_dev->dev, interface);
@@ -259,15 +256,16 @@ device_added(usb_device* dev, void** cookie)
goto bail; 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); err = usb->set_configuration(dev, config);
if (err != B_OK) { if (err != B_OK) {
debugf("set_configuration() returned %ld.\n", err); debugf("set_configuration() returned %ld.\n", err);
goto bail; goto bail;
} }
/* Place to find out whats our concrete device and set up some special info to our driver */ // Place to find out whats our concrete device and set up some special
/* TODO: if this code increases too much reconsider this implementation*/ // info to our driver. If this code increases too much reconsider
// this implementation
desc = usb->get_device_descriptor(dev); desc = usb->get_device_descriptor(dev);
if (desc->vendor_id == 0x0a5c if (desc->vendor_id == 0x0a5c
&& (desc->product_id == 0x200a && (desc->product_id == 0x200a
@@ -278,7 +276,8 @@ 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 YOUR_SPECIAL_FLAGS_HERE
} }
*/ */
@@ -297,7 +296,7 @@ device_added(usb_device* dev, void** cookie)
} }
debugf("Found %ld interfaces. Expected 3\n", config->interface_count); debugf("Found %ld interfaces. Expected 3\n", config->interface_count);
/* Find endpoints that we need */ // Find endpoints that we need
uif = config->interface->active; uif = config->interface->active;
for (e = 0; e < uif->descr->num_endpoints; e++) { for (e = 0; e < uif->descr->num_endpoints; e++) {
@@ -328,7 +327,8 @@ 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"); flowf("Minimal # endpoints for BT not found\n");
goto bail; goto bail;
} }
@@ -341,8 +341,8 @@ device_added(usb_device* dev, void** cookie)
new_bt_dev->connected = true; new_bt_dev->connected = true;
/* set the cookie that will be passed to other USB // set the cookie that will be passed to other USB
hook functions (currently device_removed() is the only other) */ // hook functions (currently device_removed() is the only other)
*cookie = new_bt_dev; *cookie = new_bt_dev;
debugf("Ok %p\n", new_bt_dev); debugf("Ok %p\n", new_bt_dev);
return B_OK; return B_OK;
@@ -356,11 +356,11 @@ 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 static status_t
device_removed(void* cookie) 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); debugf("device_removed(%p)\n", bdev);
@@ -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_added,
&device_removed &device_removed
}; };
@@ -435,7 +444,7 @@ submit_nbuffer(hci_id hid, net_buffer* nbuf)
} }
/* implements the POSIX open() */ // implements the POSIX open()
static status_t static status_t
device_open(const char* name, uint32 flags, void **cookie) device_open(const char* name, uint32 flags, void **cookie)
{ {
@@ -489,21 +498,19 @@ device_open(const char *name, uint32 flags, void **cookie)
// Allocate set and register the HCI device // Allocate set and register the HCI device
if (btDevices != NULL) { if (btDevices != NULL) {
struct net_device* ndev; bluetooth_device* ndev;
// TODO: Fill the transport descriptor // TODO: Fill the transport descriptor
err = btDevices->init_device(bdev->name, &ndev); err = btDevices->RegisterDriver(&bluetooth_hooks, &ndev);
if (err == B_OK) { if (err == B_OK) {
bdev->hdev = hdev = ndev->index; // get the index bdev->hdev = hdev = ndev->index; // Get the index
bdev->ndev = ndev; // get the net_device bdev->ndev = ndev; // Get the net_device
ndev->media = (uint32)submit_nbuffer; //XXX: interlayer-Hack
} else { } else {
hdev = bdev->num; /* XXX: Lets try to go on*/ hdev = bdev->num; // XXX: Lets try to go on
} }
} else { } else {
hdev = bdev->num; /* XXX: Lets try to go on*/ hdev = bdev->num; // XXX: Lets try to go on
} }
bdev->hdev = hdev; bdev->hdev = hdev;
@@ -518,7 +525,8 @@ device_open(const char *name, uint32 flags, void **cookie)
/* called when a client calls POSIX close() on the driver, but I/O /* 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 static status_t
device_close(void* cookie) device_close(void* cookie)
{ {
@@ -555,11 +563,11 @@ device_close(void *cookie)
for (i = 0; i < BT_DRIVER_TXCOVERAGE; i++) { for (i = 0; i < BT_DRIVER_TXCOVERAGE; i++) {
if (i == BT_COMMAND) if (i == BT_COMMAND)
while ((item = list_remove_head_item(&bdev->nbuffersTx[i])) != NULL) { while ((item = list_remove_head_item(&bdev->nbuffersTx[i])) != NULL) {
snb_free(item); snb_free((snet_buffer*)item);
} }
else else
while ((item = list_remove_head_item(&bdev->nbuffersTx[i])) != NULL) { while ((item = list_remove_head_item(&bdev->nbuffersTx[i])) != NULL) {
nb_destroy(item); nb_destroy((net_buffer*)item);
} }
} }
@@ -572,9 +580,9 @@ device_close(void *cookie)
purge_room(&bdev->eventRoom); purge_room(&bdev->eventRoom);
purge_room(&bdev->aclRoom); purge_room(&bdev->aclRoom);
/* Device no longer in our Stack*/ // Device no longer in our Stack
if (btDevices != NULL) if (btDevices != NULL)
btDevices->uninit_device(bdev->ndev); btDevices->UnregisterDriver(bdev->hdev);
// unSet RUNNING // unSet RUNNING
if (TEST_AND_CLEAR(&bdev->state, RUNNING)) { if (TEST_AND_CLEAR(&bdev->state, RUNNING)) {
@@ -586,8 +594,7 @@ device_close(void *cookie)
} }
/* called after device_close(), when all pending I/O requests have // Called after device_close(), when all pending I / O requests have returned
* returned */
static status_t static status_t
device_free (void* cookie) device_free (void* cookie)
{ {
@@ -605,7 +612,7 @@ device_free (void *cookie)
} }
/* implements the POSIX ioctl() */ // implements the POSIX ioctl()
static status_t 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)
{ {
@@ -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 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); 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 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"); flowf("device_write()\n");
return B_ERROR; return B_ERROR;
} }
#if 0 #if 0
#pragma mark - #pragma mark -
#endif #endif
@@ -739,11 +747,13 @@ dump_driver(int argc, char** argv)
if (bt_usb_devices[i] != NULL) { if (bt_usb_devices[i] != NULL) {
kprintf("%s : \n", bt_usb_devices[i]->name); kprintf("%s : \n", bt_usb_devices[i]->name);
kprintf("\taclroom = %d\teventroom = %d\tcommand & events =%d\n", snb_packets(&bt_usb_devices[i]->eventRoom) kprintf("\taclroom = %d\teventroom = %d\tcommand & events =%d\n",
, snb_packets(&bt_usb_devices[i]->aclRoom) snb_packets(&bt_usb_devices[i]->eventRoom),
, snb_packets(&bt_usb_devices[i]->snetBufferRecycleTrash) ); 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) while ((item = (snet_buffer*)list_get_next_item(
&bt_usb_devices[i]->snetBufferRecycleTrash, item)) != NULL)
snb_dump(item); snb_dump(item);
} }
} }
@@ -752,7 +762,7 @@ dump_driver(int argc, char** argv)
} }
/* called each time the driver is loaded by the kernel */ // called each time the driver is loaded by the kernel
status_t status_t
init_driver(void) init_driver(void)
{ {
@@ -809,12 +819,12 @@ init_driver(void)
bt_usb_devices[j] = NULL; bt_usb_devices[j] = NULL;
} }
/* After here device_added and publish devices hooks are called // Note: After here device_added and publish devices hooks are called
be carefull USB devs */
usb->register_driver(BLUETOOTH_DEVICE_DEVFS_NAME, supported_devices, 1, NULL); usb->register_driver(BLUETOOTH_DEVICE_DEVFS_NAME, supported_devices, 1, NULL);
usb->install_notify(BLUETOOTH_DEVICE_DEVFS_NAME, &notify_hooks); 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; return B_OK;
@@ -835,7 +845,7 @@ err_release3:
} }
/* called just before the kernel unloads the driver */ // called just before the kernel unloads the driver
void void
uninit_driver(void) uninit_driver(void)
{ {
@@ -861,7 +871,7 @@ uninit_driver(void)
remove_debugger_command("bth2generic", &dump_driver); remove_debugger_command("bth2generic", &dump_driver);
/* Releasing modules */ // Releasing modules
put_module(usb_name); put_module(usb_name);
put_module(hci_name); put_module(hci_name);
// TODO: netbuffers // TODO: netbuffers
@@ -906,8 +916,8 @@ publish_devices(void)
// dev_names = (char**)malloc(sizeof(char*) * (dev_count + 1)); // dev_names = (char**)malloc(sizeof(char*) * (dev_count + 1));
// if (dev_names) { // if (dev_names) {
// for (i = 0; i < MAX_NUM_DEVS; i++) { // for (i = 0; i < MAX_NUM_DEVS; i++) {
// if ((dev != NULL) && // if ((dev != NULL) // dev + \n
// (dev_names[i] = (char*)malloc(strlen(DEVICE_PATH)+2/* num + \n */))) { // && (dev_names[i] = (char*)malloc(strlen(DEVICE_PATH) + 2))) {
// sprintf(dev_names[i], "%s%ld", DEVICE_PATH, dev->num); // sprintf(dev_names[i], "%s%ld", DEVICE_PATH, dev->num);
// debugf("publishing \"%s\"\n", dev_names[i]); // debugf("publishing \"%s\"\n", dev_names[i]);
// } // }
@@ -21,13 +21,13 @@
#include <util/list.h> #include <util/list.h>
#include <bluetooth/HCI/btHCI.h> #include <bluetooth/HCI/btHCI.h>
#include <bluetooth/HCI/btHCI_module.h> #include <bluetooth/HCI/btHCI_transport.h>
#include <btCoreData.h> #include <btCoreData.h>
#include "snet_buffer.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 UDCLASS_WIRELESS 0xe0
#define UDSUBCLASS_RF 0x01 #define UDSUBCLASS_RF 0x01
#define UDPROTO_BLUETOOTH 0x01 #define UDPROTO_BLUETOOTH 0x01
@@ -45,7 +45,7 @@
extern usb_module_info* usb; extern usb_module_info* usb;
extern bt_hci_module_info* hci; 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 net_buffer_module_info* nb;
extern struct bluetooth_core_data_module_info* btCoreData; extern struct bluetooth_core_data_module_info* btCoreData;
@@ -65,7 +65,7 @@ struct bt_usb_dev {
usb_device* dev; /* opaque handle */ usb_device* dev; /* opaque handle */
#endif #endif
hci_id hdev; /* HCI device id*/ hci_id hdev; /* HCI device id*/
struct net_device* ndev; bluetooth_device* ndev;
char name[B_OS_NAME_LENGTH]; char name[B_OS_NAME_LENGTH];
bool connected; /* is the device plugged into the USB? */ bool connected; /* is the device plugged into the USB? */
@@ -97,7 +97,8 @@ struct bt_usb_dev {
#endif #endif
/* This so called rooms, are for dumping the USB RX frames /* 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 eventRoom;
struct list aclRoom; struct list aclRoom;
@@ -107,8 +108,8 @@ struct bt_usb_dev {
uint32 nbuffersPendingTx[BT_DRIVER_TXCOVERAGE]; uint32 nbuffersPendingTx[BT_DRIVER_TXCOVERAGE];
// Rx buffer // Rx buffer
net_buffer* nbufferRx[BT_DRIVER_RXCOVERAGE]; /* Wasting 1 pointer for BT_EVENT */ net_buffer* nbufferRx[BT_DRIVER_RXCOVERAGE];
snet_buffer* eventRx; /* <- which we hold here */ snet_buffer* eventRx;
// for who ever needs preallocated buffers // 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 static status_t
assembly_rx(bt_usb_dev* bdev, bt_packet_t type, void* data, int count) 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; bdev->stat.bytesRX += count;
if (type == BT_EVENT) return btDevices->PostTransportPacket(bdev->hdev, type, data, count);
snbuf = bdev->eventRx;
else
nbuf = bdev->nbufferRx[type];
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 --- #pragma mark --- RX Complete ---
#endif #endif
void void
#ifndef HAIKU_TARGET_PLATFORM_HAIKU #ifndef HAIKU_TARGET_PLATFORM_HAIKU
event_complete(void* cookie, uint32 status, void* data, uint32 actual_len) event_complete(void* cookie, uint32 status, void* data, uint32 actual_len)
@@ -168,7 +58,7 @@ event_complete(void* cookie, uint32 status, void* data, uint32 actual_len)
event_complete(void* cookie, status_t status, void* data, size_t actual_len) event_complete(void* cookie, status_t status, void* data, size_t actual_len)
#endif #endif
{ {
bt_usb_dev* bdev = cookie; bt_usb_dev* bdev = (bt_usb_dev*)cookie;
// bt_usb_dev* bdev = fetch_device(cookie, 0); -> safer / slower option // bt_usb_dev* bdev = fetch_device(cookie, 0); -> safer / slower option
status_t error; status_t error;
@@ -177,13 +67,13 @@ event_complete(void* cookie, status_t status, void* data, size_t actual_len)
if (bdev == NULL) if (bdev == NULL)
return; return;
if (status == B_CANCELED || status == B_DEV_CRC_ERROR) // or not running anymore... if (status == B_CANCELED || status == B_DEV_CRC_ERROR)
return; return; // or not running anymore...
if (status != B_OK || actual_len == 0) if (status != B_OK || actual_len == 0)
goto resubmit; 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++; bdev->stat.successfulTX++;
} else { } else {
bdev->stat.errorRX++; bdev->stat.errorRX++;
@@ -192,7 +82,7 @@ event_complete(void* cookie, status_t status, void* data, size_t actual_len)
resubmit: resubmit:
error = usb->queue_interrupt(bdev->intr_in_ep->handle, data, error = usb->queue_interrupt(bdev->intr_in_ep->handle, data,
max(HCI_MAX_EVENT_SIZE, bdev->max_packet_size_intr_in), event_complete, bdev); max_c(HCI_MAX_EVENT_SIZE, bdev->max_packet_size_intr_in), event_complete, bdev);
if (error != B_OK) { if (error != B_OK) {
reuse_room(&bdev->eventRoom, data); 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) acl_rx_complete(void* cookie, status_t status, void* data, size_t actual_len)
#endif #endif
{ {
bt_usb_dev* bdev = cookie; bt_usb_dev* bdev = (bt_usb_dev*)cookie;
// bt_usb_dev* bdev = fetch_device(cookie, 0); -> safer / slower option // bt_usb_dev* bdev = fetch_device(cookie, 0); -> safer / slower option
status_t error; status_t error;
if (bdev == NULL) if (bdev == NULL)
return; return;
if (status == B_CANCELED || status == B_DEV_CRC_ERROR) // or not running anymore... if (status == B_CANCELED || status == B_DEV_CRC_ERROR)
return; return; // or not running anymore...
if (status != B_OK || actual_len == 0) if (status != B_OK || actual_len == 0)
goto resubmit; 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++; bdev->stat.successfulRX++;
} else { } else {
bdev->stat.errorRX++; bdev->stat.errorRX++;
@@ -233,7 +123,7 @@ acl_rx_complete(void* cookie, status_t status, void* data, size_t actual_len)
resubmit: resubmit:
error = usb->queue_bulk(bdev->bulk_in_ep->handle, data, 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); acl_rx_complete, (void*) bdev);
if (error != B_OK) { if (error != B_OK) {
@@ -245,6 +135,7 @@ resubmit:
} }
} }
#if 0 #if 0
#pragma mark --- RX --- #pragma mark --- RX ---
#endif #endif
@@ -252,7 +143,7 @@ resubmit:
status_t status_t
submit_rx_event(bt_usb_dev* bdev) 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); void* buf = alloc_room(&bdev->eventRoom, size);
status_t status; status_t status;
@@ -277,7 +168,7 @@ submit_rx_event(bt_usb_dev* bdev)
status_t status_t
submit_rx_acl(bt_usb_dev* bdev) 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); void* buf = alloc_room(&bdev->aclRoom, size);
status_t status; status_t status;
@@ -301,10 +192,11 @@ submit_rx_acl(bt_usb_dev* bdev)
status_t status_t
submit_rx_sco(bt_usb_dev* bdev) submit_rx_sco(bt_usb_dev* bdev)
{ {
/* not yet implemented */ // not yet implemented
return B_ERROR; return B_ERROR;
} }
#if 0 #if 0
#pragma mark --- TX Complete --- #pragma mark --- TX Complete ---
#endif #endif
@@ -317,7 +209,7 @@ command_complete(void* cookie, status_t status, void* data, size_t actual_len)
#endif #endif
{ {
snet_buffer* snbuf = (snet_buffer*)cookie; 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); 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; bdev->stat.bytesTX += actual_len;
} else { } else {
bdev->stat.errorTX++; 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); snb_park(&bdev->snetBufferRecycleTrash, snbuf);
#ifdef BT_RESCHEDULING_AFTER_COMPLETITIONS #ifdef BT_RESCHEDULING_AFTER_COMPLETITIONS
// TODO: check just the empty queues? // TODO: check just the empty queues
schedTxProcessing(bdev); schedTxProcessing(bdev);
#endif #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; net_buffer* nbuf = (net_buffer*)cookie;
bt_usb_dev* bdev = GET_DEVICE(nbuf); 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) { if (status == B_OK) {
bdev->stat.successfulTX++; bdev->stat.successfulTX++;
bdev->stat.bytesTX += actual_len; bdev->stat.bytesTX += actual_len;
} else { } else {
bdev->stat.errorTX++; 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); nb_destroy(nbuf);
#ifdef BT_RESCHEDULING_AFTER_COMPLETITIONS #ifdef BT_RESCHEDULING_AFTER_COMPLETITIONS
schedTxProcessing(bdev); schedTxProcessing(bdev);
#endif #endif
} }
#if 0 #if 0
#pragma mark --- TX --- #pragma mark --- TX ---
#endif #endif
@@ -382,7 +276,7 @@ submit_tx_command(bt_usb_dev* bdev, snet_buffer* snbuf)
return B_DEV_NOT_READY; return B_DEV_NOT_READY;
} }
/* set cookie */ // set cookie
snb_set_cookie(snbuf, bdev); snb_set_cookie(snbuf, bdev);
debugf("@%p\n", snb_get(snbuf)); debugf("@%p\n", snb_get(snbuf));
@@ -390,7 +284,7 @@ submit_tx_command(bt_usb_dev* bdev, snet_buffer* snbuf)
error = usb->queue_request(bdev->dev, bRequestType, bRequest, error = usb->queue_request(bdev->dev, bRequestType, bRequest,
value, wIndex, wLength, snb_get(snbuf), value, wIndex, wLength, snb_get(snbuf),
#ifndef HAIKU_TARGET_PLATFORM_HAIKU #ifndef HAIKU_TARGET_PLATFORM_HAIKU
wLength, //??? wLength,
#endif #endif
command_complete, (void*) snbuf); command_complete, (void*) snbuf);
@@ -407,21 +301,20 @@ submit_tx_command(bt_usb_dev* bdev, snet_buffer* snbuf)
status_t status_t
submit_tx_acl(bt_usb_dev* bdev, net_buffer* nbuf) submit_tx_acl(bt_usb_dev* bdev, net_buffer* nbuf)
{ {
int32 index;
status_t error; status_t error;
/* set cookie */ // set cookie
SET_DEVICE(nbuf, bdev->hdev); SET_DEVICE(nbuf, bdev->hdev);
if (!GET_BIT(bdev->state, RUNNING)) { if (!GET_BIT(bdev->state, RUNNING)) {
return B_DEV_NOT_READY; return B_DEV_NOT_READY;
} }
/*
debugf("### Outgoing ACL: len = %ld\n", nbuf->size); 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]); 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), error = usb->queue_bulk(bdev->bulk_out_ep->handle, nb_get_whole_buffer(nbuf),
nbuf->size, acl_tx_complete, (void*)nbuf); nbuf->size, acl_tx_complete, (void*)nbuf);
@@ -444,6 +337,6 @@ submit_tx_sco(bt_usb_dev* bdev)
return B_DEV_NOT_READY; return B_DEV_NOT_READY;
} }
/* not yet implemented */ // not yet implemented
return B_ERROR; return B_ERROR;
} }
@@ -1,8 +1,6 @@
/* /*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com * Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*
*/ */
#ifndef _H2TRANSACTION_H_ #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 * Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*
*/ */
#ifndef _H2UPPER_H_ #ifndef _H2UPPER_H_
#define _H2UPPER_H_ #define _H2UPPER_H_
@@ -25,7 +25,7 @@ nb_get_whole_buffer(net_buffer* nbuf)
void* conPointer; void* conPointer;
status_t err; status_t err;
#if 0 #if 0
/* the job could be already done */ // the job could be already done
// !!! it could be trash from other upper protocols... // !!! it could be trash from other upper protocols...
if (nbuf->COOKIEFIELD != NULL) if (nbuf->COOKIEFIELD != NULL)
return (void*)nbuf->COOKIEFIELD; return (void*)nbuf->COOKIEFIELD;
@@ -33,10 +33,9 @@ nb_get_whole_buffer(net_buffer* nbuf)
err = nb->direct_access(nbuf, 0, nbuf->size, &conPointer); err = nb->direct_access(nbuf, 0, nbuf->size, &conPointer);
if (err != B_OK) { if (err != B_OK) {
snooze(3*1000*1000);
panic("expected to be contiguous"); panic("expected to be contiguous");
#if 0 #if 0
/* pity, we are gonna need a realocation */ // We are gonna need a realocation
nbuf->COOKIEFIELD = (uint32) malloc(nbuf->size); nbuf->COOKIEFIELD = (uint32) malloc(nbuf->size);
if (nbuf->COOKIEFIELD == NULL) if (nbuf->COOKIEFIELD == NULL)
goto fail; goto fail;
@@ -65,7 +64,7 @@ nb_destroy(net_buffer* nbuf)
if (nbuf == NULL) if (nbuf == NULL)
return; return;
#if 0 #if 0
/* Free possible allocated */ // Free possible allocated
if (nbuf->COOKIEFIELD != NULL) if (nbuf->COOKIEFIELD != NULL)
free((void*)nbuf->COOKIEFIELD); free((void*)nbuf->COOKIEFIELD);
#endif #endif
@@ -77,10 +76,10 @@ nb_destroy(net_buffer* nbuf)
// Extract the expected size of the packet // Extract the expected size of the packet
// TODO: This might be inefficient as at the moment of the creation of the net_buffer // TODO: This might be inefficient as at the moment of the creation
// this information is known and it could be stored in any of the net_buffer fields // of the net_buffer this information is known and it could be stored
// but I still dont know how many of those am i gonna have free.... #if 0
size_t ssize_t
get_expected_size(net_buffer* nbuf) get_expected_size(net_buffer* nbuf)
{ {
@@ -114,14 +113,17 @@ get_expected_size(net_buffer* nbuf)
break; break;
} }
return B_ERROR; return -1;
} }
#endif
#if 0 #if 0
#pragma mark - room util - #pragma mark - room util -
#endif #endif
inline void
void
init_room(struct list* l) init_room(struct list* l)
{ {
list_init(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) reuse_room(struct list* l, void* room)
{ {
list_add_item(l, room); list_add_item(l, room);
@@ -1,10 +1,7 @@
/* /*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com * Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*
*/ */
#ifndef _H2UTIL_H_ #ifndef _H2UTIL_H_
#define _H2UTIL_H_ #define _H2UTIL_H_
@@ -14,7 +11,8 @@
/* net buffer utils for ACL, to be reviewed */ /* net buffer utils for ACL, to be reviewed */
#define DEVICEFIELD type #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 GET_DEVICE(nbuf) fetch_device(NULL,(nbuf->DEVICEFIELD&0xFF))
#define COOKIEFIELD flags #define COOKIEFIELD flags
@@ -23,9 +21,9 @@ void nb_destroy(net_buffer* nbuf);
size_t get_expected_size(net_buffer* nbuf); size_t get_expected_size(net_buffer* nbuf);
/* Room utils */ /* Room utils */
inline void init_room(struct list* l); void init_room(struct list* l);
void* alloc_room(struct list* l, size_t size); void* alloc_room(struct list* l, size_t size);
inline void reuse_room(struct list* l, void* room); void reuse_room(struct list* l, void* room);
void purge_room(struct list* l); void purge_room(struct list* l);
/* list utils */ /* list utils */
@@ -29,10 +29,10 @@ struct snet_buffer {
snet_buffer* snet_buffer*
snb_create(uint16 size) snb_create(uint16 size)
{ {
/* TODO: pointer checking */ // TODO: pointer checking
#ifdef SNB_BUFFER_ATTACHED #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); snet_buffer* snb = (snet_buffer*) malloc(sizeof(snet_buffer) + size);
snb->buffer = ((uint8*)snb) + sizeof(snet_buffer); snb->buffer = ((uint8*)snb) + sizeof(snet_buffer);
#else #else
@@ -50,7 +50,7 @@ snb_create(uint16 size)
void void
snb_put(snet_buffer* snb, void* data, uint16 size) snb_put(snet_buffer* snb, void* data, uint16 size)
{ {
/* TODO: check overflow */ // TODO: check overflow
memcpy( &snb->buffer[snb->puttingSize], data, size); memcpy( &snb->buffer[snb->puttingSize], data, size);
snb->puttingSize+=size; snb->puttingSize+=size;
} }
@@ -59,14 +59,14 @@ snb_put(snet_buffer* snb, void* data, uint16 size)
void* void*
snb_pull(snet_buffer* snb, uint16 size) snb_pull(snet_buffer* snb, uint16 size)
{ {
/* TODO: check overflow */ // TODO: check overflow
snb->pullingSize+=size; snb->pullingSize+=size;
return &snb->buffer[snb->pullingSize - size]; return &snb->buffer[snb->pullingSize - size];
} }
inline void void
snb_reset(snet_buffer* snb) snb_reset(snet_buffer* snb)
{ {
snb->puttingSize = snb->pullingSize = 0; snb->puttingSize = snb->pullingSize = 0;
@@ -89,65 +89,69 @@ snb_free(snet_buffer* snb)
} }
inline void* void*
snb_get(snet_buffer* snb) snb_get(snet_buffer* snb)
{ {
/* TODO: pointer checking */ // TODO: pointer checking
return snb->buffer; return snb->buffer;
} }
inline uint16 uint16
snb_size(snet_buffer* snb) snb_size(snet_buffer* snb)
{ {
/* TODO: pointer checking */ // TODO: pointer checking
return snb->expectedSize; return snb->expectedSize;
} }
inline void* void*
snb_cookie(snet_buffer* snb) snb_cookie(snet_buffer* snb)
{ {
/* TODO: pointer checking */ // TODO: pointer checking
return snb->cookie; return snb->cookie;
} }
inline void void
snb_set_cookie(snet_buffer* snb, void* cookie) snb_set_cookie(snet_buffer* snb, void* cookie)
{ {
/* TODO: pointer checking */ // TODO: pointer checking
snb->cookie = cookie; snb->cookie = cookie;
} }
/* Return true if we canot "put" more data in the buffer */ // Return true if we canot "put" more data in the buffer
inline bool snb_completed(snet_buffer* snb) bool
snb_completed(snet_buffer* snb)
{ {
return (snb->expectedSize == snb->puttingSize); return (snb->expectedSize == snb->puttingSize);
} }
/* Return true if we cannot pull more more data from the buffer */ // Return true if we cannot pull more more data from the buffer
inline bool snb_finished(snet_buffer* snb) bool
snb_finished(snet_buffer* snb)
{ {
return (snb->expectedSize == snb->pullingSize); 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); 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); return (snb->expectedSize - snb->pullingSize);
} }
/*
/* ISSUE1: Number of packets in the worst case(we always need a bigger ISSUE1: Number of packets in the worst case(we always need a bigger
buffer than before) increases, never decreases: buffer than before) increases, never decreases:
SOL1: Delete the smallest when the queue is bigger than X elements SOL1: Delete the smallest when the queue is bigger than X elements
@@ -158,14 +162,15 @@ inline uint16 snb_remaining_to_pull(snet_buffer* snb)
SOL1: Provide purge func. SOL1: Provide purge func.
SOL2: ? SOL2: ?
*/ */
static snet_buffer* static snet_buffer*
snb_attempt_reuse(snet_buffer* snb, uint16 size) 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); snb_free(snb);
return snb_create(size); return snb_create(size);
@@ -183,15 +188,15 @@ snb_park(struct list* l, snet_buffer* snb)
{ {
snet_buffer* item = NULL; snet_buffer* item = NULL;
/* insert it by order */ // insert it by order
while ((item = list_get_next_item(l, item)) != NULL) { while ((item = (snet_buffer*)list_get_next_item(l, item)) != NULL) {
/* This one has allocated more than us place us back*/ // This one has allocated more than us place us back
if (item->allocatedSize > snb->allocatedSize) { if (item->allocatedSize > snb->allocatedSize) {
list_insert_item_before(l, item, snb); list_insert_item_before(l, item, snb);
return; 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); list_add_item(l, snb);
} }
@@ -203,16 +208,18 @@ snb_fetch(struct list* l, uint16 size)
snet_buffer* newitem = NULL; snet_buffer* newitem = NULL;
if (!list_is_empty(l)) 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) { if (item->allocatedSize >= size) {
/* This one is for us*/ // This one is for us
break; break;
} }
} }
newitem = snb_attempt_reuse(item, size); 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) { if (item == newitem) {
list_remove_item(l, item); list_remove_item(l, item);
} }
@@ -227,7 +234,7 @@ snb_packets(struct list* l)
uint16 count = 0; uint16 count = 0;
snet_buffer* item = NULL; 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++; count++;
return count; return count;
@@ -237,5 +244,6 @@ snb_packets(struct list* l)
void void
snb_dump(snet_buffer* snb) 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);
} }
@@ -65,9 +65,9 @@ uint16 snb_remaining_to_pull(snet_buffer* snb);
* Thypical scenario would be * Thypical scenario would be
* that you create a snb_buffer to send data, once you send you free it, * 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 * 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 * that buffer, to snb_park the buffer, and whenever you need to allocate
* one snb_fetch it. That funcion will reuse most appropiated previous used one * another one snb_fetch it. That funcion will reuse most appropiated
* snb_buff by its memory use. * previous used one snb_buff by its memory use.
*/ */
void snb_park(struct list* l, snet_buffer* snb); void snb_park(struct list* l, snet_buffer* snb);
snet_buffer* snb_fetch(struct list* l, uint16 size); 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 ethernet ;
SubInclude HAIKU_TOP src add-ons kernel network devices loopback ; 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 ;
@@ -43,7 +43,7 @@ l2cap_receive(HciConnection* conn, net_buffer* buffer)
uint16 dcid; uint16 dcid;
uint16 length; uint16 length;
/* Check packet */ // Check packet
if (buffer->size < sizeof(l2cap_hdr_t)) { if (buffer->size < sizeof(l2cap_hdr_t)) {
debugf("invalid L2CAP packet. Packet too small, len=%ld\n", buffer->size); debugf("invalid L2CAP packet. Packet too small, len=%ld\n", buffer->size);
gBufferModule->free(buffer); 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); NetBufferHeaderReader<l2cap_hdr_t> bufferHeader(buffer);
status_t status = bufferHeader.Status(); status_t status = bufferHeader.Status();
if (status < B_OK) { if (status < B_OK) {
@@ -61,28 +61,28 @@ l2cap_receive(HciConnection* conn, net_buffer* buffer)
length = bufferHeader->length = le16toh(bufferHeader->length); length = bufferHeader->length = le16toh(bufferHeader->length);
dcid = bufferHeader->dcid = le16toh(bufferHeader->dcid); dcid = bufferHeader->dcid = le16toh(bufferHeader->dcid);
bufferHeader.Remove(); /* pulling */ bufferHeader.Remove(); // pulling
/* Check payload size */ // Check payload size
if (length != buffer->size ) { if (length != buffer->size ) {
debugf("invalid L2CAP packet. Payload length mismatch, packetlen=%d, nebufferlen=%ld\n", debugf("Payload length mismatch, packetlen=%d, bufferlen=%ld\n",
length, buffer->size); length, buffer->size);
gBufferModule->free(buffer); gBufferModule->free(buffer);
return EMSGSIZE; return EMSGSIZE;
} }
/* Process packet */ // Process packet
switch (dcid) { switch (dcid) {
case L2CAP_SIGNAL_CID: /* L2CAP command */ case L2CAP_SIGNAL_CID: // L2CAP command
error = l2cap_process_signal_cmd(conn, buffer); error = l2cap_process_signal_cmd(conn, buffer);
break; break;
case L2CAP_CLT_CID: /* Connectionless packet case L2CAP_CLT_CID: // Connectionless packet
error = l2cap_cl_receive(buffer);*/ // error = l2cap_cl_receive(buffer);
flowf("CL FRAME!!\n"); flowf("CL FRAME!!\n");
break; break;
default: /* Data packet */ default: // Data packet
error = l2cap_co_receive(conn, buffer, dcid); error = l2cap_co_receive(conn, buffer, dcid);
break; 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 #if 0
#pragma mark - thread conn sched - #pragma mark - thread conn sched -
@@ -105,6 +105,7 @@ void
purge_connection(HciConnection* conn) purge_connection(HciConnection* conn)
{ {
L2capFrame* frame; L2capFrame* frame;
bool containerCanBeDestroyed;
debugf("handle=%d\n", conn->handle); debugf("handle=%d\n", conn->handle);
@@ -118,19 +119,22 @@ purge_connection(HciConnection* conn)
// Here is the place to decide how many l2cap signals we want to have // Here is the place to decide how many l2cap signals we want to have
// per l2cap packet. 1 ATM // 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->TimeoutSignal(frame, bluetooth_l2cap_rtx_timeout);
btCoreData->QueueSignal(frame); btCoreData->QueueSignal(frame);
} containerCanBeDestroyed = false;
} else
containerCanBeDestroyed = true;
// Add the l2cap header // Add the l2cap header
if (frame->buffer == NULL) if (frame->buffer == NULL)
panic("Malformed frame in ongoing queue"); panic("Malformed frame in ongoing queue");
{
NetBufferPrepend<l2cap_hdr_t> bufferHeader(frame->buffer); NetBufferPrepend<l2cap_hdr_t> bufferHeader(frame->buffer);
status_t status = bufferHeader.Status(); status_t status = bufferHeader.Status();
if (status < B_OK) { if (status < B_OK) {
debugf("l2cap header could not be prepended!! frame code=%d\n", frame->code); debugf("header could not be prepended! code=%d\n", frame->code);
return; return;
} }
@@ -149,11 +153,10 @@ purge_connection(HciConnection* conn)
break; break;
} }
}
bufferHeader.Sync();
if (btDevices == NULL) 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"); panic("l2cap: cannot get dev module");
} // TODO: someone put it } // TODO: someone put it
@@ -161,7 +164,13 @@ purge_connection(HciConnection* conn)
debugf("dev %p frame %p tolower\n", conn->ndevice, frame->buffer); debugf("dev %p frame %p tolower\n", conn->ndevice, frame->buffer);
frame->buffer->type = conn->handle; 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(); // frame = conn->OutGoingFrames.RemoveHead();
// } // }
@@ -263,8 +272,6 @@ SchedConnectionPurgeThread(HciConnection* conn)
status_t error = write_port(port, (uint32) conn, &temp, sizeof(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) if (error != B_OK)
panic("BT Connection sched failed"); panic("BT Connection sched failed");