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 #include <btDebug.h>
26 #include <btCoreData.h>
27 #include <btModules.h>
28 #include <CodeHandler.h>
29 #define KERNEL_LAND
30 #include <PortListener.h>
31 #undef KERNEL_LAND
32
33 #include <bluetooth/HCI/btHCI.h>
34 #include <bluetooth/HCI/btHCI_acl.h>
35 #include <bluetooth/HCI/btHCI_command.h>
36 #include <bluetooth/HCI/btHCI_event.h>
37 #include <bluetooth/HCI/btHCI_transport.h>
38 #include <bluetooth/HCI/btHCI_sco.h>
39 #include <bluetooth/bdaddrUtils.h>
40
41 #include "acl.h"
42
43
44 int32 api_version = B_CUR_DRIVER_API_VERSION;
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*
FindDeviceByID(hci_id hid)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
PostTransportPacket(hci_id hid,bt_packet_t type,void * data,size_t count)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
Assemble(bluetooth_device * bluetoothDevice,bt_packet_t type,void * data,size_t count)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 ERROR("%s: EVENT posted in HCI!!!\n", __func__);
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 TRACE("%s: ACL parsed in ACL!\n", __func__);
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 (type == BT_ACL) {
200 TRACE("%s: ACL Packet not filled size %" B_PRIu32
201 " expected=%" B_PRIuSIZE "\n", __func__, nbuf->size,
202 bluetoothDevice->fExpectedPacketSize[type]);
203 }
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
HciPacketHandler(void * data,int32 code,size_t size)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 TRACE("%s: to assemble %" B_PRIuSIZE " bytes of 0x%" B_PRIx32 "\n",
224 __func__, size, deviceId);
225
226 if (bluetoothDevice != NULL) {
227 return Assemble(bluetoothDevice, Bluetooth::CodeHandler::Protocol(code),
228 data, size);
229 } else {
230 ERROR("%s: Device 0x%" B_PRIx32 " could not be matched\n", __func__,
231 deviceId);
232 }
233
234 return B_ERROR;
235 }
236
237
238 // #pragma mark -
239
240
241 status_t
RegisterDriver(bt_hci_transport_hooks * hooks,bluetooth_device ** _device)242 RegisterDriver(bt_hci_transport_hooks* hooks, bluetooth_device** _device)
243 {
244
245 bluetooth_device* device = new (std::nothrow) bluetooth_device;
246 if (device == NULL)
247 return B_NO_MEMORY;
248
249 for (int index = 0; index < HCI_NUM_PACKET_TYPES; index++) {
250 device->fBuffersRx[index] = NULL;
251 device->fExpectedPacketSize[index] = 0;
252 }
253
254 device->info = NULL; // not yet used
255 device->hooks = hooks;
256 device->supportedPacketTypes = (HCI_DM1 | HCI_DH1 | HCI_HV1);
257 device->linkMode = (HCI_LM_ACCEPT);
258 device->mtu = L2CAP_MTU_MINIMUM; // TODO: ensure specs min value
259
260 MutexLocker _(&sListLock);
261
262 if (sDeviceList.IsEmpty())
263 device->index = HCI_DEVICE_INDEX_OFFSET; // REVIEW: dev index
264 else {
265 device->index = (sDeviceList.Tail())->index + 1; // REVIEW!
266 TRACE("%s: List not empty\n", __func__);
267 }
268
269 sDeviceList.Add(device);
270
271 TRACE("%s: Device %" B_PRIx32 "\n", __func__, device->index);
272
273 *_device = device;
274
275 return B_OK;
276 }
277
278
279 status_t
UnregisterDriver(hci_id id)280 UnregisterDriver(hci_id id)
281 {
282 bluetooth_device* device = FindDeviceByID(id);
283
284 if (device == NULL)
285 return B_ERROR;
286
287 if (device->GetDoublyLinkedListLink()->next != NULL
288 || device->GetDoublyLinkedListLink()->previous != NULL
289 || device == sDeviceList.Head())
290 sDeviceList.Remove(device);
291
292 delete device;
293
294 return B_OK;
295 }
296
297
298 // PostACL
299 status_t
PostACL(hci_id hciId,net_buffer * buffer)300 PostACL(hci_id hciId, net_buffer* buffer)
301 {
302 net_buffer* curr_frame = NULL;
303 net_buffer* next_frame = buffer;
304 uint8 flag = HCI_ACL_PACKET_START;
305
306 if (buffer == NULL)
307 panic("passing null buffer");
308
309 uint16 handle = buffer->type; // TODO: CodeHandler
310
311 bluetooth_device* device = FindDeviceByID(hciId);
312
313 if (device == NULL) {
314 ERROR("%s: No device 0x%" B_PRIx32 "\n", __func__, hciId);
315 return B_ERROR;
316 }
317
318 TRACE("%s: index 0x%" B_PRIx32 " try to send bt packet of %" B_PRIu32
319 " bytes (flags 0x%" B_PRIx32 "):\n", __func__, device->index,
320 buffer->size, buffer->flags);
321
322 // TODO: ATOMIC! any other thread should stop here
323 do {
324 // Divide packet if big enough
325 curr_frame = next_frame;
326
327 if (curr_frame->size > device->mtu) {
328 next_frame = gBufferModule->split(curr_frame, device->mtu);
329 } else {
330 next_frame = NULL;
331 }
332
333 // Attach acl header
334 {
335 NetBufferPrepend<struct hci_acl_header> bufferHeader(curr_frame);
336 status_t status = bufferHeader.Status();
337 if (status < B_OK) {
338 // free the buffer
339 continue;
340 }
341
342 bufferHeader->handle = pack_acl_handle_flags(handle, flag, 0);
343 bufferHeader->alen = curr_frame->size - sizeof(struct hci_acl_header);
344 }
345
346 // Send to driver
347 curr_frame->protocol = BT_ACL;
348
349 TRACE("%s: Tolower nbuf %p!\n", __func__, curr_frame);
350 // We could pass a cookie and avoid the driver fetch the Id
351 device->hooks->SendACL(device->index, curr_frame);
352 flag = HCI_ACL_PACKET_FRAGMENT;
353
354 } while (next_frame != NULL);
355
356 return B_OK;
357 }
358
359
360 status_t
PostSCO(hci_id hciId,net_buffer * buffer)361 PostSCO(hci_id hciId, net_buffer* buffer)
362 {
363 return B_ERROR;
364 }
365
366
367 status_t
PostESCO(hci_id hciId,net_buffer * buffer)368 PostESCO(hci_id hciId, net_buffer* buffer)
369 {
370 return B_ERROR;
371 }
372
373
374 static int
dump_bluetooth_devices(int argc,char ** argv)375 dump_bluetooth_devices(int argc, char** argv)
376 {
377 bluetooth_device* device;
378
379 DoublyLinkedList<bluetooth_device>::Iterator iterator
380 = sDeviceList.GetIterator();
381
382 while (iterator.HasNext()) {
383 device = iterator.Next();
384 kprintf("\tindex=%" B_PRIx32 " @%p hooks=%p\n", device->index,
385 device, device->hooks);
386 }
387
388 return 0;
389 }
390
391
392 static status_t
bluetooth_std_ops(int32 op,...)393 bluetooth_std_ops(int32 op, ...)
394 {
395 switch (op) {
396 case B_MODULE_INIT:
397 {
398 status_t status;
399
400 status = get_module(NET_BUFFER_MODULE_NAME,
401 (module_info**)&gBufferModule);
402
403 if (status < B_OK) {
404 panic("no way Dude we need that!");
405 return status;
406 }
407
408 status = get_module(BT_CORE_DATA_MODULE_NAME,
409 (module_info**)&btCoreData);
410 if (status < B_OK) {
411 ERROR("%s: problem getting bt core data module\n", __func__);
412 return status;
413 }
414
415 new (&sDeviceList) DoublyLinkedList<bluetooth_device>;
416 // static C++ objects are not initialized in the module startup
417
418 BluetoothRXPort = new BluetoothRawDataPort(BT_RX_PORT_NAME,
419 (BluetoothRawDataPort::port_listener_func)&HciPacketHandler);
420
421 if (BluetoothRXPort->Launch() != B_OK) {
422 ERROR("%s: RX thread creation failed!\n", __func__);
423 // we Cannot do much here ... avoid registering
424 } else {
425 TRACE("%s: RX thread launched!\n", __func__);
426 }
427
428 sLinkChangeSemaphore = create_sem(0, "bt sem");
429 if (sLinkChangeSemaphore < B_OK) {
430 put_module(NET_STACK_MODULE_NAME);
431 ERROR("%s: Link change semaphore failed\n", __func__);
432 return sLinkChangeSemaphore;
433 }
434
435 mutex_init(&sListLock, "bluetooth devices");
436
437 // status = InitializeAclConnectionThread();
438 ERROR("%s: Connection Thread error\n", __func__);
439
440 add_debugger_command("btLocalDevices", &dump_bluetooth_devices,
441 "Lists Bluetooth LocalDevices registered in the Stack");
442
443 return B_OK;
444 }
445
446 case B_MODULE_UNINIT:
447 {
448 delete_sem(sLinkChangeSemaphore);
449
450 mutex_destroy(&sListLock);
451 put_module(NET_BUFFER_MODULE_NAME);
452 put_module(NET_STACK_MODULE_NAME);
453 put_module(BT_CORE_DATA_MODULE_NAME);
454 remove_debugger_command("btLocalDevices", &dump_bluetooth_devices);
455 // status_t status = QuitAclConnectionThread();
456
457 return B_OK;
458 }
459
460 default:
461 return B_ERROR;
462 }
463 }
464
465
466 bt_hci_module_info sBluetoothModule = {
467 {
468 BT_HCI_MODULE_NAME,
469 B_KEEP_LOADED,
470 bluetooth_std_ops
471 },
472 RegisterDriver,
473 UnregisterDriver,
474 FindDeviceByID,
475 PostTransportPacket,
476 PostACL,
477 PostSCO,
478 PostESCO
479 };
480
481
482 module_info* modules[] = {
483 (module_info*)&sBluetoothModule,
484 NULL
485 };
486
487