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