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