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