* Copyright 2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "ConnectionInterface.h"
#include <bluetooth/bdaddrUtils.h>
#include <bluetooth/HCI/btHCI_transport.h>
#include <bluetooth/HCI/btHCI_event.h>
#define BT_DEBUG_THIS_MODULE
#include <btDebug.h>
int32 api_version = B_CUR_DRIVER_API_VERSION;
mutex sConnectionListLock = MUTEX_INITIALIZER("bt connection list");
DoublyLinkedList<HciConnection> sConnectionList;
net_buffer_module_info* gBufferModule = NULL;
inline bool
ExistConnectionByDestination(const bdaddr_t& destination, hci_id hid = -1)
{
return ConnectionByDestination(destination, hid) != NULL;
}
inline bool
ExistConnectionByHandle(uint16 handle, hci_id hid)
{
return ConnectionByHandle(handle, hid);
}
status_t
PostEvent(bluetooth_device* ndev, void* event, size_t size)
{
struct hci_event_header* outgoingEvent = (struct hci_event_header*) event;
status_t err;
switch (outgoingEvent->ecode) {
case HCI_EVENT_CONN_COMPLETE:
{
struct hci_ev_conn_complete* data
= (struct hci_ev_conn_complete*)(outgoingEvent + 1);
HciConnection* conn = AddConnection(data->handle, BT_ACL,
data->bdaddr, ndev->index);
if (conn == NULL)
panic("no mem for conn desc");
conn->ndevice = ndev;
TRACE("%s: Registered connection handle=%#x\n", __func__,
data->handle);
break;
}
case HCI_EVENT_DISCONNECTION_COMPLETE:
{
struct hci_ev_disconnection_complete_reply* data;
data = (struct hci_ev_disconnection_complete_reply*)
(outgoingEvent + 1);
RemoveConnection(data->handle, ndev->index);
TRACE("%s: unRegistered connection handle=%#x\n", __func__,
data->handle);
break;
}
}
port_id port = find_port(BT_USERLAND_PORT_NAME);
if (port != B_NAME_NOT_FOUND) {
err = write_port_etc(port, PACK_PORTCODE(BT_EVENT, ndev->index, -1),
event, size, B_TIMEOUT, 1 * 1000 * 1000);
if (err != B_OK)
ERROR("%s: Error posting userland %s\n", __func__, strerror(err));
} else {
ERROR("%s: bluetooth_server not found for posting!\n", __func__);
err = B_NAME_NOT_FOUND;
}
return err;
}
static status_t
bcd_std_ops(int32 op, ...)
{
status_t status;
switch (op) {
case B_MODULE_INIT:
new (&sConnectionList) DoublyLinkedList<HciConnection>;
status = get_module(NET_BUFFER_MODULE_NAME,
(module_info **)&gBufferModule);
if (status != B_OK)
return status;
return B_OK;
case B_MODULE_UNINIT:
put_module(NET_BUFFER_MODULE_NAME);
return B_OK;
}
return B_ERROR;
}
bluetooth_core_data_module_info sBCDModule = {
{
BT_CORE_DATA_MODULE_NAME,
0,
bcd_std_ops
},
PostEvent,
AddConnection,
RemoveConnection,
RouteConnection,
ConnectionByHandle,
ConnectionByDestination,
allocate_command_ident,
lookup_command_ident,
free_command_ident,
};
module_info* modules[] = {
(module_info*)&sBCDModule,
NULL
};