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