1 /* 2 * Copyright 2008, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com 7 */ 8 9 #include <new> 10 #include <errno.h> 11 #include <stdlib.h> 12 #include <string.h> 13 14 #include <KernelExport.h> 15 #include <lock.h> 16 #include <SupportDefs.h> 17 #include <util/AutoLock.h> 18 #include <util/DoublyLinkedList.h> 19 20 #include <net_buffer.h> 21 #include <net_device.h> 22 #include <net_stack.h> 23 #include <NetBufferUtilities.h> 24 25 #define BT_DEBUG_THIS_MODULE 26 #define SUBMODULE_NAME "hci" 27 #define SUBMODULE_COLOR 34 28 #include <btDebug.h> 29 #include <btCoreData.h> 30 #include <btModules.h> 31 #include <CodeHandler.h> 32 #define KERNEL_LAND 33 #include <PortListener.h> 34 #undef KERNEL_LAND 35 36 #include <bluetooth/HCI/btHCI.h> 37 #include <bluetooth/HCI/btHCI_acl.h> 38 #include <bluetooth/HCI/btHCI_command.h> 39 #include <bluetooth/HCI/btHCI_event.h> 40 #include <bluetooth/HCI/btHCI_transport.h> 41 #include <bluetooth/HCI/btHCI_sco.h> 42 #include <bluetooth/bdaddrUtils.h> 43 44 #include "acl.h" 45 46 47 typedef PortListener<void, 48 HCI_MAX_FRAME_SIZE, // Event Body can hold max 255 + 2 header 49 24 // Some devices have sent chunks of 24 events(inquiry result) 50 > BluetoothRawDataPort; 51 52 53 // Modules references 54 net_buffer_module_info* gBufferModule = NULL; 55 struct bluetooth_core_data_module_info* btCoreData = NULL; 56 57 static mutex sListLock; 58 static sem_id sLinkChangeSemaphore; 59 static DoublyLinkedList<bluetooth_device> sDeviceList; 60 61 BluetoothRawDataPort* BluetoothRXPort; 62 63 // forward declarations 64 status_t HciPacketHandler(void* data, int32 code, size_t size); 65 66 67 bluetooth_device* 68 FindDeviceByID(hci_id hid) 69 { 70 bluetooth_device* device; 71 72 DoublyLinkedList<bluetooth_device>::Iterator iterator 73 = sDeviceList.GetIterator(); 74 75 while (iterator.HasNext()) { 76 device = iterator.Next(); 77 if (device->index == hid) 78 return device; 79 } 80 81 return NULL; 82 } 83 84 85 status_t 86 PostTransportPacket(hci_id hid, bt_packet_t type, void* data, size_t count) 87 { 88 uint32 code = 0; 89 90 Bluetooth::CodeHandler::SetDevice(&code, hid); 91 Bluetooth::CodeHandler::SetProtocol(&code, type); 92 93 return BluetoothRXPort->Trigger(code, data, count); 94 } 95 96 97 status_t 98 Assemble(bluetooth_device* bluetoothDevice, bt_packet_t type, void* data, 99 size_t count) 100 { 101 net_buffer* nbuf = bluetoothDevice->fBuffersRx[type]; 102 103 size_t currentPacketLen = 0; 104 105 while (count) { 106 107 if (nbuf == NULL) { 108 // new buffer incoming 109 switch (type) { 110 case BT_EVENT: 111 if (count >= HCI_EVENT_HDR_SIZE) { 112 struct hci_event_header* headerPacket 113 = (struct hci_event_header*)data; 114 bluetoothDevice->fExpectedPacketSize[type] 115 = HCI_EVENT_HDR_SIZE + headerPacket->elen; 116 117 if (count >= bluetoothDevice->fExpectedPacketSize[type]) { 118 // the whole packet is here so it can be already posted. 119 flowf("EVENT posted in HCI!!!\n"); 120 btCoreData->PostEvent(bluetoothDevice, data, 121 bluetoothDevice->fExpectedPacketSize[type]); 122 123 } else { 124 nbuf = gBufferModule->create( 125 bluetoothDevice->fExpectedPacketSize[type]); 126 bluetoothDevice->fBuffersRx[type] = nbuf; 127 128 nbuf->protocol = type; 129 } 130 131 } else { 132 panic("EVENT frame corrupted\n"); 133 return EILSEQ; 134 } 135 break; 136 137 case BT_ACL: 138 if (count >= HCI_ACL_HDR_SIZE) { 139 struct hci_acl_header* headerPkt = (struct hci_acl_header*)data; 140 141 bluetoothDevice->fExpectedPacketSize[type] = HCI_ACL_HDR_SIZE 142 + B_LENDIAN_TO_HOST_INT16(headerPkt->alen); 143 144 // Create the buffer -> TODO: this allocation can fail 145 nbuf = gBufferModule->create( 146 bluetoothDevice->fExpectedPacketSize[type]); 147 bluetoothDevice->fBuffersRx[type] = nbuf; 148 149 nbuf->protocol = type; 150 } else { 151 panic("ACL frame corrupted\n"); 152 return EILSEQ; 153 } 154 break; 155 156 case BT_SCO: 157 158 break; 159 160 default: 161 panic("unknown packet type in assembly"); 162 break; 163 } 164 165 currentPacketLen = bluetoothDevice->fExpectedPacketSize[type]; 166 167 } else { 168 // Continuation of a packet 169 currentPacketLen = bluetoothDevice->fExpectedPacketSize[type] - nbuf->size; 170 } 171 if (nbuf != NULL) { 172 currentPacketLen = min_c(currentPacketLen, count); 173 174 gBufferModule->append(nbuf, data, currentPacketLen); 175 176 if ((bluetoothDevice->fExpectedPacketSize[type] - nbuf->size) == 0) { 177 178 switch (nbuf->protocol) { 179 case BT_EVENT: 180 panic("need to send full buffer to btdatacore!\n"); 181 btCoreData->PostEvent(bluetoothDevice, data, 182 bluetoothDevice->fExpectedPacketSize[type]); 183 184 break; 185 case BT_ACL: 186 // TODO: device descriptor has been fetched better not 187 // pass id again 188 flowf("ACL parsed in ACL!\n"); 189 AclAssembly(nbuf, bluetoothDevice->index); 190 break; 191 default: 192 193 break; 194 } 195 196 bluetoothDevice->fBuffersRx[type] = nbuf = NULL; 197 bluetoothDevice->fExpectedPacketSize[type] = 0; 198 } else { 199 #if DEBUG_ACL 200 if (type == BT_ACL) 201 debugf("ACL Packet not filled size=%ld expected=%ld\n", 202 nbuf->size, bluetoothDevice->fExpectedPacketSize[type]); 203 #endif 204 } 205 206 } 207 // in case in the pipe there is info about the next buffer 208 count -= currentPacketLen; 209 data = (void*)((uint8*)data + currentPacketLen); 210 } 211 212 return B_OK; 213 } 214 215 216 status_t 217 HciPacketHandler(void* data, int32 code, size_t size) 218 { 219 hci_id deviceId = Bluetooth::CodeHandler::Device(code); 220 221 bluetooth_device* bluetoothDevice = FindDeviceByID(deviceId); 222 223 debugf("to assemble %ld bytes of %ld\n", size, deviceId); 224 225 if (bluetoothDevice != NULL) 226 return Assemble(bluetoothDevice, Bluetooth::CodeHandler::Protocol(code), 227 data, size); 228 else { 229 debugf("Device %ld could not be matched\n", deviceId); 230 } 231 232 return B_ERROR; 233 } 234 235 236 // #pragma mark - 237 238 239 status_t 240 RegisterDriver(bt_hci_transport_hooks* hooks, bluetooth_device** _device) 241 { 242 243 bluetooth_device* device = new (std::nothrow) bluetooth_device; 244 if (device == NULL) 245 return B_NO_MEMORY; 246 247 for (int index = 0; index < HCI_NUM_PACKET_TYPES; index++) { 248 device->fBuffersRx[index] = NULL; 249 device->fExpectedPacketSize[index] = 0; 250 } 251 252 device->info = NULL; // not yet used 253 device->hooks = hooks; 254 device->supportedPacketTypes = (HCI_DM1 | HCI_DH1 | HCI_HV1); 255 device->linkMode = (HCI_LM_ACCEPT); 256 device->mtu = L2CAP_MTU_MINIMUM; // TODO: ensure specs min value 257 258 MutexLocker _(&sListLock); 259 260 if (sDeviceList.IsEmpty()) 261 device->index = HCI_DEVICE_INDEX_OFFSET; // REVIEW: dev index 262 else { 263 device->index = (sDeviceList.Tail())->index + 1; // REVIEW! 264 flowf("List not empty\n"); 265 } 266 267 sDeviceList.Add(device); 268 269 debugf("Device %lx\n", device->index ); 270 271 *_device = device; 272 273 return B_OK; 274 } 275 276 277 status_t 278 UnregisterDriver(hci_id id) 279 { 280 bluetooth_device* device = FindDeviceByID(id); 281 282 if (device == NULL) 283 return B_ERROR; 284 285 if (device->GetDoublyLinkedListLink()->next != NULL 286 || device->GetDoublyLinkedListLink()->previous != NULL 287 || device == sDeviceList.Head()) 288 sDeviceList.Remove(device); 289 290 delete device; 291 292 return B_OK; 293 } 294 295 296 // PostACL 297 status_t 298 PostACL(hci_id hciId, net_buffer* buffer) 299 { 300 net_buffer* curr_frame = NULL; 301 net_buffer* next_frame = buffer; 302 uint8 flag = HCI_ACL_PACKET_START; 303 304 if (buffer == NULL) 305 panic("passing null buffer"); 306 307 uint16 handle = buffer->type; // TODO: CodeHandler 308 309 bluetooth_device* device = FindDeviceByID(hciId); 310 311 if (device == NULL) { 312 debugf("No device %lx", hciId); 313 return B_ERROR; 314 } 315 316 debugf("index %lx try to send bt packet of %lu bytes (flags %ld):\n", 317 device->index, buffer->size, buffer->flags); 318 319 // TODO: ATOMIC! any other thread should stop here 320 do { 321 // Divide packet if big enough 322 curr_frame = next_frame; 323 324 if (curr_frame->size > device->mtu) { 325 next_frame = gBufferModule->split(curr_frame, device->mtu); 326 } else { 327 next_frame = NULL; 328 } 329 330 // Attach acl header 331 { 332 NetBufferPrepend<struct hci_acl_header> bufferHeader(curr_frame); 333 status_t status = bufferHeader.Status(); 334 if (status < B_OK) { 335 // free the buffer 336 continue; 337 } 338 339 bufferHeader->handle = pack_acl_handle_flags(handle, flag, 0); 340 bufferHeader->alen = curr_frame->size - sizeof(struct hci_acl_header); 341 } 342 343 // Send to driver 344 curr_frame->protocol = BT_ACL; 345 346 debugf("Tolower nbuf %p!\n", curr_frame); 347 // We could pass a cookie and avoid the driver fetch the Id 348 device->hooks->SendACL(device->index, curr_frame); 349 flag = HCI_ACL_PACKET_FRAGMENT; 350 351 } while (next_frame != NULL); 352 353 return B_OK; 354 } 355 356 357 status_t 358 PostSCO(hci_id hciId, net_buffer* buffer) 359 { 360 return B_ERROR; 361 } 362 363 364 status_t 365 PostESCO(hci_id hciId, net_buffer* buffer) 366 { 367 return B_ERROR; 368 } 369 370 371 static int 372 dump_bluetooth_devices(int argc, char** argv) 373 { 374 bluetooth_device* device; 375 376 DoublyLinkedList<bluetooth_device>::Iterator iterator 377 = sDeviceList.GetIterator(); 378 379 while (iterator.HasNext()) { 380 device = iterator.Next(); 381 kprintf("\tindex=%#lx @%p hooks=%p\n",device->index, device, device->hooks); 382 } 383 384 return 0; 385 } 386 387 388 static status_t 389 bluetooth_std_ops(int32 op, ...) 390 { 391 392 flowf("\n"); 393 394 switch (op) { 395 case B_MODULE_INIT: 396 { 397 status_t status; 398 399 status = get_module(NET_BUFFER_MODULE_NAME, (module_info**)&gBufferModule); 400 if (status < B_OK) { 401 panic("no way Dude we need that!"); 402 return status; 403 } 404 405 status = get_module(BT_CORE_DATA_MODULE_NAME,(module_info**)&btCoreData); 406 if (status < B_OK) { 407 flowf("problem getting datacore\n"); 408 return status; 409 } 410 411 new (&sDeviceList) DoublyLinkedList<bluetooth_device>; 412 // static C++ objects are not initialized in the module startup 413 414 BluetoothRXPort = new BluetoothRawDataPort(BT_RX_PORT_NAME, 415 (BluetoothRawDataPort::port_listener_func)&HciPacketHandler); 416 417 if (BluetoothRXPort->Launch() != B_OK) { 418 flowf("RX thread creation failed!\n"); 419 // we Cannot do much here ... avoid registering 420 } else { 421 flowf("RX thread launched!\n"); 422 } 423 424 sLinkChangeSemaphore = create_sem(0, "bt sem"); 425 if (sLinkChangeSemaphore < B_OK) { 426 put_module(NET_STACK_MODULE_NAME); 427 flowf("sem failed\n"); 428 return sLinkChangeSemaphore; 429 } 430 431 mutex_init(&sListLock, "bluetooth devices"); 432 433 // status = InitializeAclConnectionThread(); 434 debugf("Connection Thread error=%lx\n", status); 435 436 add_debugger_command("btLocalDevices", &dump_bluetooth_devices, 437 "Lists Bluetooth LocalDevices registered in the Stack"); 438 439 return B_OK; 440 } 441 442 case B_MODULE_UNINIT: 443 { 444 delete_sem(sLinkChangeSemaphore); 445 446 mutex_destroy(&sListLock); 447 put_module(NET_BUFFER_MODULE_NAME); 448 put_module(NET_STACK_MODULE_NAME); 449 put_module(BT_CORE_DATA_MODULE_NAME); 450 remove_debugger_command("btLocalDevices", &dump_bluetooth_devices); 451 // status_t status = QuitAclConnectionThread(); 452 453 return B_OK; 454 } 455 456 default: 457 return B_ERROR; 458 } 459 } 460 461 462 bt_hci_module_info sBluetoothModule = { 463 { 464 BT_HCI_MODULE_NAME, 465 B_KEEP_LOADED, 466 bluetooth_std_ops 467 }, 468 RegisterDriver, 469 UnregisterDriver, 470 FindDeviceByID, 471 PostTransportPacket, 472 PostACL, 473 PostSCO, 474 PostESCO 475 }; 476 477 478 module_info* modules[] = { 479 (module_info*)&sBluetoothModule, 480 NULL 481 }; 482 483