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