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