* 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 "ChannelInterface.h"
#include "FrameInterface.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;
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);
}
static int
DumpHciConnections(int argc, char** argv)
{
HciConnection* conn;
L2capChannel* chan;
L2capFrame* frame;
DoublyLinkedList<HciConnection>::Iterator iterator
= sConnectionList.GetIterator();
while (iterator.HasNext()) {
conn = iterator.Next();
kprintf("LocalDevice=0x%" B_PRIx32 " Destination=%s handle=%#x type=%d"
"outqueue=%" B_PRId32 " expected=%" B_PRId32 "\n", conn->Hid,
bdaddrUtils::ToString(conn->destination).String(), conn->handle,
conn->type, conn->OutGoingFrames.Count(),
conn->ExpectedResponses.Count());
*/
kprintf("\tChannels\n");
DoublyLinkedList<L2capChannel>::Iterator channelIterator
= conn->ChannelList.GetIterator();
while (channelIterator.HasNext()) {
chan = channelIterator.Next();
kprintf("\t\tscid=%x dcid=%x state=%x cfg=%x\n", chan->scid,
chan->dcid, chan->state, chan->cfgState);
}
kprintf("\n\tOutGoingFrames\n");
DoublyLinkedList<L2capFrame>::Iterator frameIterator
= conn->OutGoingFrames.GetIterator();
while (frameIterator.HasNext()) {
frame = frameIterator.Next();
kprintf("\t\tscid=%x code=%x ident=%x type=%x, buffer=%p\n",
frame->channel->scid, frame->code, frame->ident,
frame->type, frame->buffer);
}
kprintf("\n\tExpectedFrames\n");
DoublyLinkedList<L2capFrame>::Iterator frameExpectedIterator
= conn->ExpectedResponses.GetIterator();
while (frameExpectedIterator.HasNext()) {
frame = frameExpectedIterator.Next();
kprintf("\t\tscid=%x code=%x ident=%x type=%x, buffer=%p\n",
frame->channel->scid, frame->code, frame->ident,
frame->type, frame->buffer);
}
}
return 0;
}
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>;
add_debugger_command("btConnections", &DumpHciConnections,
"Lists Bluetooth Connections with RemoteDevices & channels");
status = get_module(NET_BUFFER_MODULE_NAME,
(module_info **)&gBufferModule);
if (status < B_OK)
return status;
return B_OK;
break;
case B_MODULE_UNINIT:
remove_debugger_command("btConnections", &DumpHciConnections);
put_module(NET_BUFFER_MODULE_NAME);
return B_OK;
break;
}
return B_ERROR;
}
bluetooth_core_data_module_info sBCDModule = {
{
BT_CORE_DATA_MODULE_NAME,
0,
bcd_std_ops
},
PostEvent,
AddConnection,
RemoveConnection,
RouteConnection,
SetAclBuffer,
SetAclExpectedSize,
AclPutting,
AclComplete,
AclOverFlowed,
ConnectionByHandle,
ConnectionByDestination,
AddChannel,
RemoveChannel,
ChannelBySourceID,
ChannelAllocateCid,
ChannelAllocateIdent,
SignalByIdent,
TimeoutSignal,
unTimeoutSignal,
SpawmFrame,
SpawmSignal,
AcknowledgeSignal,
QueueSignal,
};
module_info* modules[] = {
(module_info*)&sBCDModule,
NULL
};