xref: /haiku/src/add-ons/kernel/drivers/bluetooth/h2/h2generic/h2generic.cpp (revision 7749d0bb0c358a3279b1b9cc76d8376e900130a5)
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 
31 int32 api_version = B_CUR_DRIVER_API_VERSION;
32 
33 // Modules
34 static const char* usb_name = B_USB_MODULE_NAME;
35 static const char* hci_name = BT_HCI_MODULE_NAME;
36 static const char* btDevices_name = BT_HCI_MODULE_NAME;
37 
38 
39 usb_module_info* usb = NULL;
40 bt_hci_module_info* hci = NULL; // TODO remove / clean
41 struct bt_hci_module_info* btDevices = NULL;
42 struct net_buffer_module_info* nb = NULL;
43 struct bluetooth_core_data_module_info* btCoreData = NULL;
44 
45 // Driver Global data
46 static char* publish_names[MAX_BT_GENERIC_USB_DEVICES];
47 
48 int32 dev_count = 0; // number of connected devices
49 static bt_usb_dev* bt_usb_devices[MAX_BT_GENERIC_USB_DEVICES];
50 sem_id dev_table_sem = -1; // sem to synchronize access to device table
51 
52 status_t submit_nbuffer(hci_id hid, net_buffer* nbuf);
53 
54 usb_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
77 static bt_usb_dev*
78 spawn_device(usb_device usb_dev)
79 #else
80 static bt_usb_dev*
81 spawn_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 
147 bail2:
148 	delete_sem(new_bt_dev->lock);
149 bail1:
150 	delete_sem(new_bt_dev->cmd_complete);
151 bail0:
152 	free(new_bt_dev);
153 exit:
154 	return new_bt_dev;
155 }
156 
157 
158 // remove a device from the list of connected devices
159 static void
160 kill_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 
177 bt_usb_dev*
178 fetch_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
213 static status_t
214 device_added(usb_device dev, void** cookie)
215 #else
216 device_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 
348 bail:
349 	kill_device(new_bt_dev);
350 bail_no_mem:
351 	*cookie = NULL;
352 
353 	return err;
354 }
355 
356 
357 // Called by USB Manager when device is removed from the USB
358 static status_t
359 device_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 
395 static bt_hci_transport_hooks bluetooth_hooks = {
396 	NULL,
397 	&submit_nbuffer,
398 	&submit_nbuffer,
399 	NULL,
400 	NULL,
401 	H2
402 };
403 
404 
405 static usb_notify_hooks notify_hooks = {
406 	&device_added,
407 	&device_removed
408 };
409 
410 #if 0
411 #pragma mark -
412 #endif
413 
414 status_t
415 submit_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()
446 static status_t
447 device_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  */
528 static status_t
529 device_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
596 static status_t
597 device_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()
614 static status_t
615 device_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()
713 static status_t
714 device_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()
724 static status_t
725 device_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 
738 static int
739 dump_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
764 status_t
765 init_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 
829 err:	// Releasing
830 	put_module(NET_BUFFER_MODULE_NAME);
831 err_release:
832 	put_module(usb_name);
833 err_release1:
834 	put_module(hci_name);
835 #ifndef BT_SURVIVE_WITHOUT_HCI
836 err_release2:
837 #endif
838 	put_module(btDevices_name);
839 err_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
847 void
848 uninit_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 
881 const char**
882 publish_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 
928 static 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 
942 device_hooks*
943 find_device(const char* name)
944 {
945 	debugf("find_device(%s)\n", name);
946 
947 	return &hooks;
948 }
949