xref: /haiku/src/add-ons/kernel/drivers/bluetooth/h2/h2generic/h2generic.cpp (revision b247f935d133a42c427cad8a759a1bf2f65bc290)
1 /*
2  * Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
3  * Copyright 2008 Mika Lindqvist, monni1995_at_gmail.com
4  * All rights reserved. Distributed under the terms of the MIT License.
5  *
6  */
7 
8 
9 #include "h2generic.h"
10 
11 #include <kernel.h>
12 #include <malloc.h>
13 #include <stdio.h>
14 #include <string.h>
15 
16 #include <KernelExport.h>
17 #include <ByteOrder.h>
18 #include <Drivers.h>
19 
20 #include <btModules.h>
21 
22 #include "snet_buffer.h"
23 #include "h2cfg.h"
24 #include "h2debug.h"
25 #include "h2transactions.h"
26 #include "h2util.h"
27 
28 
29 int32 api_version = B_CUR_DRIVER_API_VERSION;
30 
31 // Modules
32 static const char* usb_name = B_USB_MODULE_NAME;
33 static const char* hci_name = BT_HCI_MODULE_NAME;
34 static const char* btDevices_name = BT_HCI_MODULE_NAME;
35 
36 
37 usb_module_info* usb = NULL;
38 bt_hci_module_info* hci = NULL; // TODO remove / clean
39 struct bt_hci_module_info* btDevices = NULL;
40 struct net_buffer_module_info* nb = NULL;
41 struct bluetooth_core_data_module_info* btCoreData = NULL;
42 
43 // Driver Global data
44 static char* publish_names[MAX_BT_GENERIC_USB_DEVICES];
45 
46 int32 dev_count = 0; // number of connected devices
47 static bt_usb_dev* bt_usb_devices[MAX_BT_GENERIC_USB_DEVICES];
48 sem_id dev_table_sem = -1; // sem to synchronize access to device table
49 
50 status_t submit_nbuffer(hci_id hid, net_buffer* nbuf);
51 
52 usb_support_descriptor supported_devices[] = {
53 	// Generic Bluetooth USB device
54 	// Class, SubClass, and Protocol codes that describe a Bluetooth device
55 	{ UDCLASS_WIRELESS, UDSUBCLASS_RF, UDPROTO_BLUETOOTH , 0 , 0 },
56 
57 	// Broadcom BCM2035
58 	{ 0, 0, 0, 0x0a5c, 0x200a },
59 	{ 0, 0, 0, 0x0a5c, 0x2009 },
60 
61 	// Devices taken from the linux Driver
62 	// AVM BlueFRITZ! USB v2.0
63 	{ 0, 0, 0, 0x057c, 0x3800 },
64 	// Bluetooth Ultraport Module from IBM
65 	{ 0, 0, 0, 0x04bf, 0x030a },
66 	// ALPS Modules with non-standard id
67 	{ 0, 0, 0, 0x044e, 0x3001 },
68 	{ 0, 0, 0, 0x044e, 0x3002 },
69 	// Ericsson with non-standard id
70 	{ 0, 0, 0, 0x0bdb, 0x1002 }
71 };
72 
73 /* add a device to the list of connected devices */
74 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
75 static bt_usb_dev*
76 spawn_device(usb_device usb_dev)
77 #else
78 static bt_usb_dev*
79 spawn_device(usb_device* usb_dev)
80 #endif
81 
82 {
83 	CALLED();
84 
85 	int32 i;
86 	status_t err = B_OK;
87 	bt_usb_dev* new_bt_dev = NULL;
88 
89 	// 16 usb dongles...
90 	if (dev_count >= MAX_BT_GENERIC_USB_DEVICES) {
91 		ERROR("%s: Device table full\n", __func__);
92 		goto exit;
93 	}
94 
95 	// try the allocation
96 	new_bt_dev = (bt_usb_dev*)malloc(sizeof(bt_usb_dev));
97 	if (new_bt_dev == NULL) {
98 		ERROR("%s: Unable to malloc new bt device\n", __func__);
99 		goto exit;
100 	}
101 	memset(new_bt_dev, 0, sizeof(bt_usb_dev));
102 
103 	// We will need this sem for some flow control
104 	new_bt_dev->cmd_complete = create_sem(1,
105 		BLUETOOTH_DEVICE_DEVFS_NAME "cmd_complete");
106 	if (new_bt_dev->cmd_complete < 0) {
107 		err = new_bt_dev->cmd_complete;
108 		goto bail0;
109 	}
110 
111 	// and this for something else
112 	new_bt_dev->lock = create_sem(1, BLUETOOTH_DEVICE_DEVFS_NAME "lock");
113 	if (new_bt_dev->lock < 0) {
114 		err = new_bt_dev->lock;
115 		goto bail1;
116 	}
117 
118 	// find a free slot and fill out the name
119 	acquire_sem(dev_table_sem);
120 	for (i = 0; i < MAX_BT_GENERIC_USB_DEVICES; i++) {
121 		if (bt_usb_devices[i] == NULL) {
122 			bt_usb_devices[i] = new_bt_dev;
123 			sprintf(new_bt_dev->name, "%s/%" B_PRId32,
124 				BLUETOOTH_DEVICE_PATH, i);
125 			new_bt_dev->num = i;
126 			TRACE("%s: added device %p %" B_PRId32 " %s\n", __func__,
127 				bt_usb_devices[i], new_bt_dev->num, new_bt_dev->name);
128 			break;
129 		}
130 	}
131 	release_sem_etc(dev_table_sem, 1, B_DO_NOT_RESCHEDULE);
132 
133 	// In the case we cannot us
134 	if (bt_usb_devices[i] != new_bt_dev) {
135 		ERROR("%s: Device could not be added\n", __func__);
136 		goto bail2;
137 	}
138 
139 	new_bt_dev->dev = usb_dev;
140 	// TODO: currently only server opens
141 	new_bt_dev->open_count = 0;
142 
143 	dev_count++;
144 	return new_bt_dev;
145 
146 bail2:
147 	delete_sem(new_bt_dev->lock);
148 bail1:
149 	delete_sem(new_bt_dev->cmd_complete);
150 bail0:
151 	free(new_bt_dev);
152 	new_bt_dev = NULL;
153 exit:
154 	return new_bt_dev;
155 }
156 
157 
158 // remove a device from the list of connected devices
159 static void
160 kill_device(bt_usb_dev* bdev)
161 {
162 	if (bdev != NULL) {
163 		TRACE("%s: (%p)\n", __func__, bdev);
164 
165 		delete_sem(bdev->lock);
166 		delete_sem(bdev->cmd_complete);
167 
168 		// mark it free
169 		bt_usb_devices[bdev->num] = NULL;
170 
171 		free(bdev);
172 		dev_count--;
173 	}
174 }
175 
176 
177 bt_usb_dev*
178 fetch_device(bt_usb_dev* dev, hci_id hid)
179 {
180 	int i;
181 
182 //	TRACE("%s: (%p) or %d\n", __func__, dev, hid);
183 
184 	acquire_sem(dev_table_sem);
185 	if (dev != NULL) {
186 		for (i = 0; i < MAX_BT_GENERIC_USB_DEVICES; i++) {
187 			if (bt_usb_devices[i] == dev) {
188 				release_sem_etc(dev_table_sem, 1, B_DO_NOT_RESCHEDULE);
189 				return bt_usb_devices[i];
190 			}
191 		}
192 	} else {
193 		for (i = 0; i < MAX_BT_GENERIC_USB_DEVICES; i++) {
194 			if (bt_usb_devices[i] != NULL && bt_usb_devices[i]->hdev == hid) {
195 				release_sem_etc(dev_table_sem, 1, B_DO_NOT_RESCHEDULE);
196 				return bt_usb_devices[i];
197 			}
198 		}
199 	}
200 
201 	release_sem_etc(dev_table_sem, 1, B_DO_NOT_RESCHEDULE);
202 
203 	return NULL;
204 }
205 
206 
207 #if 0
208 #pragma mark -
209 #endif
210 
211 // called by USB Manager when device is added to the USB
212 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
213 static status_t
214 device_added(usb_device dev, void** cookie)
215 #else
216 device_added(usb_device* dev, void** cookie)
217 #endif
218 {
219 	const usb_interface_info* 		interface;
220 	const usb_device_descriptor* 	desc;
221 	const usb_configuration_info*	config;
222 	const usb_interface_info*		uif;
223 	const usb_endpoint_info*		ep;
224 
225 	status_t 	err = B_ERROR;
226 	bt_usb_dev* new_bt_dev = spawn_device(dev);
227 	int e;
228 
229 	TRACE("%s: device_added(%p)\n", __func__, new_bt_dev);
230 
231 	if (new_bt_dev == NULL) {
232 		ERROR("%s: Couldn't allocate device record.\n", __func__);
233 		err = ENOMEM;
234 		goto bail_no_mem;
235 	}
236 
237 	// we only have 1 configuration number 0
238 	config = usb->get_nth_configuration(dev, 0);
239 	// dump_usb_configuration_info(config);
240 	if (config == NULL) {
241 		ERROR("%s: Couldn't get default USB config.\n", __func__);
242 		err = B_ERROR;
243 		goto bail;
244 	}
245 
246 	TRACE("%s: found %" B_PRIuSIZE " alt interfaces.\n", __func__,
247 		config->interface->alt_count);
248 
249 	// set first interface
250 	interface = &config->interface->alt[0];
251 	err = usb->set_alt_interface(new_bt_dev->dev, interface);
252 
253 	if (err != B_OK) {
254 		ERROR("%s: set_alt_interface() error.\n", __func__);
255 		goto bail;
256 	}
257 
258 	// call set_configuration() only after calling set_alt_interface()
259 	err = usb->set_configuration(dev, config);
260 	if (err != B_OK) {
261 		ERROR("%s: set_configuration() error.\n", __func__);
262 		goto bail;
263 	}
264 
265 	// Place to find out whats our concrete device and set up some special
266 	// info to our driver. If this code increases too much reconsider
267 	// this implementation
268 	desc = usb->get_device_descriptor(dev);
269 	if (desc->vendor_id == 0x0a5c
270 		&& (desc->product_id == 0x200a
271 			|| desc->product_id == 0x2009
272 			|| desc->product_id == 0x2035)) {
273 
274 		new_bt_dev->driver_info = BT_WILL_NEED_A_RESET | BT_SCO_NOT_WORKING;
275 
276 	}
277 	/*
278 	else if ( desc->vendor_id == YOUR_VENDOR_HERE
279 		&& desc->product_id == YOUR_PRODUCT_HERE ) {
280 		YOUR_SPECIAL_FLAGS_HERE
281 	}
282 	*/
283 
284 	if (new_bt_dev->driver_info & BT_IGNORE_THIS_DEVICE) {
285 		err = ENODEV;
286 		goto bail;
287 	}
288 
289 	// security check
290 	if (config->interface->active->descr->interface_number > 0) {
291 		ERROR("%s: Strange condition happened %d\n", __func__,
292 			config->interface->active->descr->interface_number);
293 		err = B_ERROR;
294 		goto bail;
295 	}
296 
297 	TRACE("%s: Found %" B_PRIuSIZE " interfaces. Expected 3\n", __func__,
298 		config->interface_count);
299 
300 	// Find endpoints that we need
301 	uif = config->interface->active;
302 	for (e = 0; e < uif->descr->num_endpoints; e++) {
303 
304 		ep = &uif->endpoint[e];
305 		switch (ep->descr->attributes & USB_ENDPOINT_ATTR_MASK) {
306 			case USB_ENDPOINT_ATTR_INTERRUPT:
307 				if (ep->descr->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN)
308 				{
309 					new_bt_dev->intr_in_ep = ep;
310 					new_bt_dev->max_packet_size_intr_in
311 						= ep->descr->max_packet_size;
312 					TRACE("%s: INT in\n", __func__);
313 				} else {
314 					TRACE("%s: INT out\n", __func__);
315 				}
316 			break;
317 
318 			case USB_ENDPOINT_ATTR_BULK:
319 				if (ep->descr->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN)	{
320 					new_bt_dev->bulk_in_ep  = ep;
321 					new_bt_dev->max_packet_size_bulk_in
322 						= ep->descr->max_packet_size;
323 					TRACE("%s: BULK int\n", __func__);
324 				} else	{
325 					new_bt_dev->bulk_out_ep = ep;
326 					new_bt_dev->max_packet_size_bulk_out
327 						= ep->descr->max_packet_size;
328 					TRACE("%s: BULK out\n", __func__);
329 				}
330 			break;
331 		}
332 	}
333 
334 	if (!new_bt_dev->bulk_in_ep || !new_bt_dev->bulk_out_ep
335 		|| !new_bt_dev->intr_in_ep) {
336 		ERROR("%s: Minimal # endpoints for BT not found\n", __func__);
337 		goto bail;
338 	}
339 
340 	// Look into the devices suported to understand this
341 	if (new_bt_dev->driver_info & BT_DIGIANSWER)
342 		new_bt_dev->ctrl_req = USB_TYPE_VENDOR;
343 	else
344 		new_bt_dev->ctrl_req = USB_TYPE_CLASS;
345 
346 	new_bt_dev->connected = true;
347 
348 	// set the cookie that will be passed to other USB
349 	// hook functions (currently device_removed() is the only other)
350 	*cookie = new_bt_dev;
351 	TRACE("%s: Ok %p\n", __func__, new_bt_dev);
352 	return B_OK;
353 
354 bail:
355 	kill_device(new_bt_dev);
356 bail_no_mem:
357 	*cookie = NULL;
358 
359 	return err;
360 }
361 
362 
363 // Called by USB Manager when device is removed from the USB
364 static status_t
365 device_removed(void* cookie)
366 {
367 	bt_usb_dev* bdev = fetch_device((bt_usb_dev*)cookie, 0);
368 
369 	TRACE("%s: device_removed(%p)\n", __func__, bdev);
370 
371 	if (bdev == NULL) {
372 		ERROR("%s: Device not present in driver.\n", __func__);
373 		return B_ERROR;
374 	}
375 
376 	if (!TEST_AND_CLEAR(&bdev->state, RUNNING))
377 		ERROR("%s: wasnt running?\n", __func__);
378 
379 	TRACE("%s: Cancelling queues...\n", __func__);
380 	if (bdev->intr_in_ep != NULL)
381 		usb->cancel_queued_transfers(bdev->intr_in_ep->handle);
382 	if (bdev->bulk_in_ep != NULL)
383 		usb->cancel_queued_transfers(bdev->bulk_in_ep->handle);
384 	if (bdev->bulk_out_ep != NULL)
385 		usb->cancel_queued_transfers(bdev->bulk_out_ep->handle);
386 
387 	bdev->connected = false;
388 
389 	return B_OK;
390 }
391 
392 
393 static bt_hci_transport_hooks bluetooth_hooks = {
394 	NULL,
395 	&submit_nbuffer,
396 	&submit_nbuffer,
397 	NULL,
398 	NULL,
399 	H2
400 };
401 
402 
403 static usb_notify_hooks notify_hooks = {
404 	&device_added,
405 	&device_removed
406 };
407 
408 #if 0
409 #pragma mark -
410 #endif
411 
412 status_t
413 submit_nbuffer(hci_id hid, net_buffer* nbuf)
414 {
415 	bt_usb_dev* bdev = NULL;
416 
417 	bdev = fetch_device(NULL, hid);
418 
419 	TRACE("%s: index=%" B_PRId32 " nbuf=%p bdev=%p\n", __func__, hid,
420 		nbuf, bdev);
421 
422 	if (bdev != NULL) {
423 		switch (nbuf->protocol) {
424 			case BT_COMMAND:
425 				// not issued this way
426 			break;
427 
428 			case BT_ACL:
429 				return submit_tx_acl(bdev, nbuf);
430 			break;
431 
432 			default:
433 				panic("submit_nbuffer: no protocol");
434 			break;
435 
436 		}
437 	}
438 
439 	return B_ERROR;
440 
441 }
442 
443 
444 // implements the POSIX open()
445 static status_t
446 device_open(const char* name, uint32 flags, void **cookie)
447 {
448 	CALLED();
449 
450 	status_t err = ENODEV;
451 	bt_usb_dev* bdev = NULL;
452 	hci_id hdev;
453 	int i;
454 
455 	acquire_sem(dev_table_sem);
456 	for (i = 0; i < MAX_BT_GENERIC_USB_DEVICES; i++) {
457 		if (bt_usb_devices[i] && !strcmp(name, bt_usb_devices[i]->name)) {
458 			bdev = bt_usb_devices[i];
459 			break;
460 		}
461 	}
462 	release_sem_etc(dev_table_sem, 1, B_DO_NOT_RESCHEDULE);
463 
464 	if (bdev == NULL) {
465 		ERROR("%s: Device not found in the open list!", __func__);
466 		*cookie = NULL;
467 		return B_ERROR;
468 	}
469 
470 	// Set RUNNING
471 	if (TEST_AND_SET(&bdev->state, RUNNING)) {
472 		ERROR("%s: dev already running! - reOpened device!\n", __func__);
473 		return B_ERROR;
474 	}
475 
476 	acquire_sem(bdev->lock);
477 	// TX structures
478 	for (i = 0; i < BT_DRIVER_TXCOVERAGE; i++) {
479 		list_init(&bdev->nbuffersTx[i]);
480 		bdev->nbuffersPendingTx[i] = 0;
481 	}
482 
483 	// RX structures
484 	bdev->eventRx = NULL;
485 	for (i = 0; i < BT_DRIVER_RXCOVERAGE; i++) {
486 		bdev->nbufferRx[i] = NULL;
487 	}
488 
489 	// dumping the USB frames
490 	init_room(&bdev->eventRoom);
491 	init_room(&bdev->aclRoom);
492 	// init_room(new_bt_dev->scoRoom);
493 
494 	list_init(&bdev->snetBufferRecycleTrash);
495 
496 	// Allocate set and register the HCI device
497 	if (btDevices != NULL) {
498 		bluetooth_device* ndev;
499 		// TODO: Fill the transport descriptor
500 		err = btDevices->RegisterDriver(&bluetooth_hooks, &ndev);
501 
502 		if (err == B_OK) {
503 			bdev->hdev = hdev = ndev->index; // Get the index
504 			bdev->ndev = ndev;  // Get the net_device
505 
506 		} else {
507 			hdev = bdev->num; // XXX: Lets try to go on
508 		}
509 	} else {
510 		hdev = bdev->num; // XXX: Lets try to go on
511 	}
512 
513 	bdev->hdev = hdev;
514 
515 	*cookie = bdev;
516 	release_sem(bdev->lock);
517 
518 	return B_OK;
519 
520 }
521 
522 
523 /* called when a client calls POSIX close() on the driver, but I/O
524  * requests may still be pending
525  */
526 static status_t
527 device_close(void* cookie)
528 {
529 	CALLED();
530 
531 	int32 i;
532 	void* item;
533 	bt_usb_dev* bdev = (bt_usb_dev*)cookie;
534 
535 	if (bdev == NULL)
536 		panic("bad cookie");
537 
538 	// Clean queues
539 
540 	if (bdev->connected == true) {
541 		TRACE("%s: Cancelling queues...\n", __func__);
542 
543 		if (bdev->intr_in_ep != NULL)
544 			usb->cancel_queued_transfers(bdev->intr_in_ep->handle);
545 
546 		if (bdev->bulk_in_ep!=NULL)
547 			usb->cancel_queued_transfers(bdev->bulk_in_ep->handle);
548 
549 		if (bdev->bulk_out_ep!=NULL)
550 			usb->cancel_queued_transfers(bdev->bulk_out_ep->handle);
551 	}
552 
553 	// TX
554 	for (i = 0; i < BT_DRIVER_TXCOVERAGE; i++) {
555 		if (i == BT_COMMAND) {
556 			while ((item = list_remove_head_item(&bdev->nbuffersTx[i])) != NULL)
557 				snb_free((snet_buffer*)item);
558 		} else {
559 			while ((item = list_remove_head_item(&bdev->nbuffersTx[i])) != NULL)
560 				nb_destroy((net_buffer*)item);
561 		}
562 	}
563 	// RX
564 	for (i = 0; i < BT_DRIVER_RXCOVERAGE; i++) {
565 		nb_destroy(bdev->nbufferRx[i]);
566 	}
567 	snb_free(bdev->eventRx);
568 
569 	purge_room(&bdev->eventRoom);
570 	purge_room(&bdev->aclRoom);
571 
572 	// Device no longer in our Stack
573 	if (btDevices != NULL)
574 		btDevices->UnregisterDriver(bdev->hdev);
575 
576 	// unSet RUNNING
577 	if (TEST_AND_CLEAR(&bdev->state, RUNNING)) {
578 		ERROR("%s: %s not running?\n", __func__, bdev->name);
579 		return B_ERROR;
580 	}
581 
582 	return B_OK;
583 }
584 
585 
586 // Called after device_close(), when all pending I / O requests have returned
587 static status_t
588 device_free(void* cookie)
589 {
590 	CALLED();
591 
592 	status_t err = B_OK;
593 	bt_usb_dev* bdev = (bt_usb_dev*)cookie;
594 
595 	if (!bdev->connected)
596 		kill_device(bdev);
597 
598 	return err;
599 }
600 
601 
602 // implements the POSIX ioctl()
603 static status_t
604 device_control(void* cookie, uint32 msg, void* params, size_t size)
605 {
606 	status_t 	err = B_ERROR;
607 	bt_usb_dev*	bdev = (bt_usb_dev*)cookie;
608 	snet_buffer* snbuf;
609 	#if BT_DRIVER_SUPPORTS_ACL // ACL
610 	int32	i;
611 	#endif
612 
613 	TOUCH(size);
614 	TRACE("%s: ioctl() opcode %" B_PRId32 " size %" B_PRIuSIZE ".\n", __func__,
615 		msg, size);
616 
617 	if (bdev == NULL) {
618 		TRACE("%s: Bad cookie\n", __func__);
619 		return B_BAD_VALUE;
620 	}
621 
622 	if (params == NULL) {
623 		TRACE("%s: Invalid pointer control\n", __func__);
624 		return B_BAD_VALUE;
625 	}
626 
627 	acquire_sem(bdev->lock);
628 
629 	switch (msg) {
630 		case ISSUE_BT_COMMAND:
631 #ifdef BT_IOCTLS_PASS_SIZE
632 			if (size == 0) {
633 				TRACE("%s: Invalid size control\n", __func__);
634 				err = B_BAD_VALUE;
635 				break;
636 			}
637 #else
638 			size = (*((size_t*)params));
639 			(*(size_t**)&params)++;
640 #endif
641 
642 			// TODO: Reuse from some TXcompleted queue
643 			// snbuf = snb_create(size);
644 			snbuf = snb_fetch(&bdev->snetBufferRecycleTrash, size);
645 			snb_put(snbuf, params, size);
646 
647 			err = submit_tx_command(bdev, snbuf);
648 			TRACE("%s: command launched\n", __func__);
649 		break;
650 
651 		case BT_UP:
652 
653 			//  EVENTS
654 			err = submit_rx_event(bdev);
655 			if (err != B_OK) {
656 				bdev->state = CLEAR_BIT(bdev->state, ANCILLYANT);
657 				ERROR("%s: Queuing failed device stops running\n", __func__);
658 				break;
659 			}
660 
661 			#if BT_DRIVER_SUPPORTS_ACL // ACL
662 			for (i = 0; i < MAX_ACL_IN_WINDOW; i++) {
663 				err = submit_rx_acl(bdev);
664 				if (err != B_OK && i == 0) {
665 					bdev->state = CLEAR_BIT(bdev->state, ANCILLYANT);
666 						// Set the flaq in the HCI world
667 					ERROR("%s: Queuing failed device stops running\n",
668 						__func__);
669 					break;
670 				}
671 			}
672 			#endif
673 
674 			bdev->state = SET_BIT(bdev->state, RUNNING);
675 
676 			#if BT_DRIVER_SUPPORTS_SCO
677 				// TODO:  SCO / eSCO
678 			#endif
679 
680 			ERROR("%s: Device online\n", __func__);
681 		break;
682 
683 		case GET_STATS:
684 			memcpy(params, &bdev->stat, sizeof(bt_hci_statistics));
685 			err = B_OK;
686 		break;
687 
688 		case GET_HCI_ID:
689 			*(hci_id*)params = bdev->hdev;
690 			err = B_OK;
691 		break;
692 
693 
694 	default:
695 		ERROR("%s: Invalid opcode.\n", __func__);
696 		err = B_DEV_INVALID_IOCTL;
697 		break;
698 	}
699 
700 	release_sem(bdev->lock);
701 	return err;
702 }
703 
704 
705 // implements the POSIX read()
706 static status_t
707 device_read(void* cookie, off_t pos, void* buffer, size_t* count)
708 {
709 	TRACE("%s: Reading... count = %" B_PRIuSIZE "\n", __func__, *count);
710 
711 	*count = 0;
712 	return B_OK;
713 }
714 
715 
716 // implements the POSIX write()
717 static status_t
718 device_write(void* cookie, off_t pos, const void* buffer, size_t* count)
719 {
720 	CALLED();
721 
722 	return B_ERROR;
723 }
724 
725 
726 #if 0
727 #pragma mark -
728 #endif
729 
730 
731 static int
732 dump_driver(int argc, char** argv)
733 {
734 	int i;
735 	snet_buffer* item = NULL;
736 
737 	for (i = 0; i < MAX_BT_GENERIC_USB_DEVICES; i++) {
738 
739 		if (bt_usb_devices[i] != NULL) {
740 			kprintf("%s : \n", bt_usb_devices[i]->name);
741 			kprintf("\taclroom = %d\teventroom = %d\tcommand & events =%d\n",
742 				snb_packets(&bt_usb_devices[i]->eventRoom),
743 				snb_packets(&bt_usb_devices[i]->aclRoom),
744 				snb_packets(&bt_usb_devices[i]->snetBufferRecycleTrash));
745 
746 			while ((item = (snet_buffer*)list_get_next_item(
747 				&bt_usb_devices[i]->snetBufferRecycleTrash, item)) != NULL)
748 				snb_dump(item);
749 		}
750 	}
751 
752 	return 0;
753 }
754 
755 
756 // called each time the driver is loaded by the kernel
757 status_t
758 init_driver(void)
759 {
760 	CALLED();
761 	int j;
762 
763 	if (get_module(BT_CORE_DATA_MODULE_NAME,
764 		(module_info**)&btCoreData) != B_OK) {
765 		ERROR("%s: cannot get module '%s'\n", __func__,
766 			BT_CORE_DATA_MODULE_NAME);
767 		return B_ERROR;
768 	}
769 
770 	// BT devices MODULE INITS
771 	if (get_module(btDevices_name, (module_info**)&btDevices) != B_OK) {
772 		ERROR("%s: cannot get module '%s'\n", __func__, btDevices_name);
773 		goto err_release3;
774 	}
775 
776 	// HCI MODULE INITS
777 	if (get_module(hci_name, (module_info**)&hci) != B_OK) {
778 		ERROR("%s: cannot get module '%s'\n", __func__, hci_name);
779 #ifndef BT_SURVIVE_WITHOUT_HCI
780 		goto err_release2;
781 #endif
782 	}
783 
784 	// USB MODULE INITS
785 	if (get_module(usb_name, (module_info**)&usb) != B_OK) {
786 		ERROR("%s: cannot get module '%s'\n", __func__, usb_name);
787 		goto err_release1;
788 	}
789 
790 	if (get_module(NET_BUFFER_MODULE_NAME, (module_info**)&nb) != B_OK) {
791 		ERROR("%s: cannot get module '%s'\n", __func__,
792 			NET_BUFFER_MODULE_NAME);
793 #ifndef BT_SURVIVE_WITHOUT_NET_BUFFERS
794 		goto err_release;
795 #endif
796 	}
797 
798 	// GENERAL INITS
799 	dev_table_sem = create_sem(1, BLUETOOTH_DEVICE_DEVFS_NAME "dev_table_lock");
800 	if (dev_table_sem < 0) {
801 		goto err;
802 	}
803 
804 	for (j = 0; j < MAX_BT_GENERIC_USB_DEVICES; j++) {
805 		bt_usb_devices[j] = NULL;
806 	}
807 
808 	// Note: After here device_added and publish devices hooks are called
809 	usb->register_driver(BLUETOOTH_DEVICE_DEVFS_NAME, supported_devices, 1, NULL);
810 	usb->install_notify(BLUETOOTH_DEVICE_DEVFS_NAME, &notify_hooks);
811 
812 	add_debugger_command("bth2generic", &dump_driver,
813 		"Lists H2 Transport device info");
814 
815 	return B_OK;
816 
817 err:	// Releasing
818 	put_module(NET_BUFFER_MODULE_NAME);
819 err_release:
820 	put_module(usb_name);
821 err_release1:
822 	put_module(hci_name);
823 #ifndef BT_SURVIVE_WITHOUT_HCI
824 err_release2:
825 #endif
826 	put_module(btDevices_name);
827 err_release3:
828 	put_module(BT_CORE_DATA_MODULE_NAME);
829 
830 	return B_ERROR;
831 }
832 
833 
834 // called just before the kernel unloads the driver
835 void
836 uninit_driver(void)
837 {
838 	CALLED();
839 
840 	int32 j;
841 
842 	for (j = 0; j < MAX_BT_GENERIC_USB_DEVICES; j++) {
843 
844 		if (publish_names[j] != NULL)
845 			free(publish_names[j]);
846 
847 		if (bt_usb_devices[j] != NULL) {
848 			//	if (connected_dev != NULL) {
849 			//		debugf("Device %p still exists.\n",	connected_dev);
850 			//	}
851 			ERROR("%s: %s still present?\n", __func__, bt_usb_devices[j]->name);
852 			kill_device(bt_usb_devices[j]);
853 		}
854 	}
855 
856 	usb->uninstall_notify(BLUETOOTH_DEVICE_DEVFS_NAME);
857 
858 	remove_debugger_command("bth2generic", &dump_driver);
859 
860 	// Releasing modules
861 	put_module(usb_name);
862 	put_module(hci_name);
863 	// TODO: netbuffers
864 
865 	delete_sem(dev_table_sem);
866 }
867 
868 
869 const char**
870 publish_devices(void)
871 {
872 	CALLED();
873 	int32 j;
874 	int32 i = 0;
875 
876 	char* str;
877 
878 	for (j = 0; j < MAX_BT_GENERIC_USB_DEVICES; j++) {
879 		if (publish_names[j]) {
880 			free(publish_names[j]);
881 			publish_names[j] = NULL;
882 		}
883 	}
884 
885 	acquire_sem(dev_table_sem);
886 	for (j = 0; j < MAX_BT_GENERIC_USB_DEVICES; j++) {
887 		if (bt_usb_devices[j] != NULL && bt_usb_devices[j]->connected) {
888 			str = strdup(bt_usb_devices[j]->name);
889 			if (str) {
890 				publish_names[i++] = str;
891 				TRACE("%s: publishing %s\n", __func__, bt_usb_devices[j]->name);
892 			}
893 		}
894 	}
895 	release_sem_etc(dev_table_sem, 1, B_DO_NOT_RESCHEDULE);
896 
897 	publish_names[i] = NULL;
898 	TRACE("%s: published %" B_PRId32 " devices\n", __func__, i);
899 
900 	// TODO: this method might make better memory use
901 	// dev_names = (char**)malloc(sizeof(char*) * (dev_count + 1));
902 	// if (dev_names) {
903 	// for (i = 0; i < MAX_NUM_DEVS; i++) {
904 	//	if ((dev != NULL) // dev + \n
905 	//	&& (dev_names[i] = (char*)malloc(strlen(DEVICE_PATH) + 2))) {
906 	//	sprintf(dev_names[i], "%s%ld", DEVICE_PATH, dev->num);
907 	//	debugf("publishing \"%s\"\n", dev_names[i]);
908 	//	}
909 	// }
910 
911 	return (const char**)publish_names;
912 }
913 
914 
915 static device_hooks hooks = {
916 	device_open,
917 	device_close,
918 	device_free,
919 	device_control,
920 	device_read,
921 	device_write,
922 	NULL,
923 	NULL,
924 	NULL,
925 	NULL
926 };
927 
928 
929 device_hooks*
930 find_device(const char* name)
931 {
932 	CALLED();
933 
934 	return &hooks;
935 }
936