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