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