1 /* 2 * Copyright 2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com 3 * All rights reserved. Distributed under the terms of the MIT License. 4 */ 5 #include "ConnectionInterface.h" 6 #include "ChannelInterface.h" 7 #include "FrameInterface.h" 8 9 10 #include <bluetooth/bdaddrUtils.h> 11 #include <bluetooth/HCI/btHCI_transport.h> 12 #include <bluetooth/HCI/btHCI_event.h> 13 14 #define BT_DEBUG_THIS_MODULE 15 #include <btDebug.h> 16 17 DoublyLinkedList<HciConnection> sConnectionList; 18 net_buffer_module_info* gBufferModule = NULL; 19 20 21 inline bool 22 ExistConnectionByDestination(const bdaddr_t& destination, hci_id hid = -1) 23 { 24 return ConnectionByDestination(destination, hid) != NULL; 25 } 26 27 28 inline bool 29 ExistConnectionByHandle(uint16 handle, hci_id hid) 30 { 31 return ConnectionByHandle(handle, hid); 32 } 33 34 35 static int 36 DumpHciConnections(int argc, char** argv) 37 { 38 HciConnection* conn; 39 L2capChannel* chan; 40 L2capFrame* frame; 41 DoublyLinkedList<HciConnection>::Iterator iterator 42 = sConnectionList.GetIterator(); 43 44 while (iterator.HasNext()) { 45 conn = iterator.Next(); 46 kprintf("LocalDevice=%lx Destination=%s handle=%#x type=%d" 47 "outqueue=%ld expected=%ld\n", conn->Hid, 48 bdaddrUtils::ToString(conn->destination), conn->handle, conn->type, 49 conn->OutGoingFrames.Count() , conn->ExpectedResponses.Count()); 50 51 // each channel 52 kprintf("\tChannels\n"); 53 DoublyLinkedList<L2capChannel>::Iterator channelIterator 54 = conn->ChannelList.GetIterator(); 55 56 while (channelIterator.HasNext()) { 57 chan = channelIterator.Next(); 58 kprintf("\t\tscid=%x dcid=%x state=%x cfg=%x\n", chan->scid, 59 chan->dcid, chan->state, chan->cfgState); 60 } 61 62 // Each outgoing 63 kprintf("\n\tOutGoingFrames\n"); 64 DoublyLinkedList<L2capFrame>::Iterator frameIterator 65 = conn->OutGoingFrames.GetIterator(); 66 while (frameIterator.HasNext()) { 67 frame = frameIterator.Next(); 68 kprintf("\t\tscid=%x code=%x ident=%x type=%x, buffer=%p\n", 69 frame->channel->scid, frame->code, frame->ident, 70 frame->type, frame->buffer); 71 } 72 73 // Each expected 74 kprintf("\n\tExpectedFrames\n"); 75 DoublyLinkedList<L2capFrame>::Iterator frameExpectedIterator 76 = conn->ExpectedResponses.GetIterator(); 77 78 while (frameExpectedIterator.HasNext()) { 79 frame = frameExpectedIterator.Next(); 80 kprintf("\t\tscid=%x code=%x ident=%x type=%x, buffer=%p\n", 81 frame->channel->scid, frame->code, frame->ident, 82 frame->type, frame->buffer); 83 } 84 } 85 86 return 0; 87 } 88 89 90 status_t 91 PostEvent(bluetooth_device* ndev, void* event, size_t size) 92 { 93 struct hci_event_header* outgoingEvent = (struct hci_event_header*) event; 94 status_t err; 95 96 // Take actions on certain type of events. 97 switch (outgoingEvent->ecode) { 98 case HCI_EVENT_CONN_COMPLETE: 99 { 100 struct hci_ev_conn_complete* data 101 = (struct hci_ev_conn_complete*)(outgoingEvent + 1); 102 103 // TODO: XXX parse handle field 104 HciConnection* conn = AddConnection(data->handle, BT_ACL, 105 data->bdaddr, ndev->index); 106 107 if (conn == NULL) 108 panic("no mem for conn desc"); 109 conn->ndevice = ndev; 110 debugf("Registered connection handle=%#x\n",data->handle); 111 break; 112 } 113 114 case HCI_EVENT_DISCONNECTION_COMPLETE: 115 { 116 struct hci_ev_disconnection_complete_reply* data; 117 118 data = (struct hci_ev_disconnection_complete_reply*) 119 (outgoingEvent + 1); 120 121 RemoveConnection(data->handle, ndev->index); 122 debugf("unRegistered connection handle=%#x\n",data->handle); 123 break; 124 } 125 126 } 127 128 // forward to bluetooth server 129 port_id port = find_port(BT_USERLAND_PORT_NAME); 130 if (port != B_NAME_NOT_FOUND) { 131 132 err = write_port_etc(port, PACK_PORTCODE(BT_EVENT, ndev->index, -1), 133 event, size, B_TIMEOUT, 1 * 1000 * 1000); 134 135 if (err != B_OK) 136 debugf("Error posting userland %s\n", strerror(err)); 137 138 } else { 139 flowf("ERROR:bluetooth_server not found for posting\n"); 140 err = B_NAME_NOT_FOUND; 141 } 142 143 return err; 144 } 145 146 147 static status_t 148 bcd_std_ops(int32 op, ...) 149 { 150 status_t status; 151 152 switch (op) { 153 case B_MODULE_INIT: 154 new (&sConnectionList) DoublyLinkedList<HciConnection>; 155 add_debugger_command("btConnections", &DumpHciConnections, 156 "Lists Bluetooth Connections with RemoteDevices & channels"); 157 158 status = get_module(NET_BUFFER_MODULE_NAME, 159 (module_info **)&gBufferModule); 160 if (status < B_OK) 161 return status; 162 163 return B_OK; 164 165 break; 166 167 case B_MODULE_UNINIT: 168 169 remove_debugger_command("btConnections", &DumpHciConnections); 170 put_module(NET_BUFFER_MODULE_NAME); 171 172 return B_OK; 173 break; 174 } 175 176 return B_ERROR; 177 } 178 179 180 bluetooth_core_data_module_info sBCDModule = { 181 { 182 BT_CORE_DATA_MODULE_NAME, 183 0, 184 bcd_std_ops 185 }, 186 PostEvent, 187 AddConnection, 188 // RemoveConnection, 189 RemoveConnection, 190 191 RouteConnection, 192 193 SetAclBuffer, 194 SetAclExpectedSize, 195 AclPutting, 196 AclComplete, 197 AclOverFlowed, 198 199 ConnectionByHandle, 200 ConnectionByDestination, 201 202 AddChannel, 203 RemoveChannel, 204 ChannelBySourceID, 205 ChannelAllocateCid, 206 ChannelAllocateIdent, 207 208 SignalByIdent, 209 TimeoutSignal, 210 unTimeoutSignal, 211 SpawmFrame, 212 SpawmSignal, 213 AcknowledgeSignal, 214 QueueSignal, 215 216 }; 217 218 219 module_info* modules[] = { 220 (module_info*)&sBCDModule, 221 NULL 222 }; 223