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