xref: /haiku/src/add-ons/kernel/bluetooth/hci/bluetooth.cpp (revision e1e291b063dcf7b8614fbe22e8d3a0c101cd2714)
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