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