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