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