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