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