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