Lines 252-257
static struct ng_type typestruct =
Link Here
|
252 |
****************************************************************************/ |
252 |
****************************************************************************/ |
253 |
|
253 |
|
254 |
/* USB methods */ |
254 |
/* USB methods */ |
|
|
255 |
static usb_callback_t ubt_probe_intr_callback; |
255 |
static usb_callback_t ubt_ctrl_write_callback; |
256 |
static usb_callback_t ubt_ctrl_write_callback; |
256 |
static usb_callback_t ubt_intr_read_callback; |
257 |
static usb_callback_t ubt_intr_read_callback; |
257 |
static usb_callback_t ubt_bulk_read_callback; |
258 |
static usb_callback_t ubt_bulk_read_callback; |
Lines 421-426
static const STRUCT_USB_HOST_ID ubt_ignore_devs[] =
Link Here
|
421 |
/* Atheros AR5BBU12 with sflash firmware */ |
422 |
/* Atheros AR5BBU12 with sflash firmware */ |
422 |
{ USB_VPI(0x0489, 0xe03c, 0), USB_DEV_BCD_LTEQ(1) }, |
423 |
{ USB_VPI(0x0489, 0xe03c, 0), USB_DEV_BCD_LTEQ(1) }, |
423 |
{ USB_VPI(0x0489, 0xe036, 0), USB_DEV_BCD_LTEQ(1) }, |
424 |
{ USB_VPI(0x0489, 0xe036, 0), USB_DEV_BCD_LTEQ(1) }, |
|
|
425 |
|
426 |
/* Intel Wireless 8260/8265 and successors */ |
427 |
{ USB_VPI(USB_VENDOR_INTEL2, 0x0a2b, UBT_INTEL8265) }, |
428 |
{ USB_VPI(USB_VENDOR_INTEL2, 0x0aaa, UBT_INTEL8265) }, |
429 |
{ USB_VPI(USB_VENDOR_INTEL2, 0x0025, UBT_INTEL8265) }, |
430 |
{ USB_VPI(USB_VENDOR_INTEL2, 0x0026, UBT_INTEL8265) }, |
431 |
{ USB_VPI(USB_VENDOR_INTEL2, 0x0029, UBT_INTEL8265) }, |
424 |
}; |
432 |
}; |
425 |
|
433 |
|
426 |
/* List of supported bluetooth devices */ |
434 |
/* List of supported bluetooth devices */ |
Lines 502-507
static const STRUCT_USB_HOST_ID ubt_devs[] =
Link Here
|
502 |
{ USB_VPI(USB_VENDOR_DELL, 0x8197, 0) }, |
510 |
{ USB_VPI(USB_VENDOR_DELL, 0x8197, 0) }, |
503 |
}; |
511 |
}; |
504 |
|
512 |
|
|
|
513 |
/* |
514 |
* Does a synchronous (waits for completion event) execution of HCI command. |
515 |
* Size of both command and response buffers are passed in length field of |
516 |
* corresponding structures in "Parameter Total Length" format i.e. |
517 |
* not including HCI packet headers. |
518 |
* |
519 |
* Must not be used after USB transfers have been configured in attach routine. |
520 |
*/ |
521 |
|
522 |
static usb_error_t |
523 |
ubt_do_hci_request(struct usb_device *udev, struct ubt_hci_cmd *cmd, |
524 |
void *evt, usb_timeout_t timeout) |
525 |
{ |
526 |
static const struct usb_config ubt_probe_config = { |
527 |
.type = UE_INTERRUPT, |
528 |
.endpoint = UE_ADDR_ANY, |
529 |
.direction = UE_DIR_IN, |
530 |
.flags = { .pipe_bof = 1, .short_xfer_ok = 1 }, |
531 |
.bufsize = UBT_INTR_BUFFER_SIZE, |
532 |
.callback = &ubt_probe_intr_callback, |
533 |
}; |
534 |
struct usb_device_request req; |
535 |
struct usb_xfer *xfer[1]; |
536 |
struct mtx mtx; |
537 |
usb_error_t error = USB_ERR_NORMAL_COMPLETION; |
538 |
uint8_t iface_index = 0; |
539 |
|
540 |
/* Initialize a USB control request and then do it */ |
541 |
bzero(&req, sizeof(req)); |
542 |
req.bmRequestType = UBT_HCI_REQUEST; |
543 |
req.wIndex[0] = iface_index; |
544 |
USETW(req.wLength, UBT_HCI_CMD_SIZE(cmd)); |
545 |
|
546 |
error = usbd_do_request(udev, NULL, &req, cmd); |
547 |
if (error != USB_ERR_NORMAL_COMPLETION) { |
548 |
printf("ng_ubt: usbd_do_request error=%s\n", |
549 |
usbd_errstr(error)); |
550 |
return (error); |
551 |
} |
552 |
|
553 |
if (evt == NULL) |
554 |
return (USB_ERR_NORMAL_COMPLETION); |
555 |
|
556 |
/* Initialize INTR endpoint xfer and wait for response */ |
557 |
mtx_init(&mtx, "ubt pb", NULL, MTX_DEF); |
558 |
|
559 |
error = usbd_transfer_setup(udev, &iface_index, xfer, |
560 |
&ubt_probe_config, 1, evt, &mtx); |
561 |
if (error == USB_ERR_NORMAL_COMPLETION) { |
562 |
|
563 |
mtx_lock(&mtx); |
564 |
usbd_transfer_start(*xfer); |
565 |
|
566 |
if (msleep_sbt(evt, &mtx, 0, "ubt pb", SBT_1MS * timeout, |
567 |
0, C_HARDCLOCK) == EWOULDBLOCK) { |
568 |
printf("ng_ubt: HCI command 0x%04x timed out\n", |
569 |
le16toh(cmd->opcode)); |
570 |
error = USB_ERR_TIMEOUT; |
571 |
} |
572 |
|
573 |
usbd_transfer_stop(*xfer); |
574 |
mtx_unlock(&mtx); |
575 |
|
576 |
usbd_transfer_unsetup(xfer, 1); |
577 |
} else |
578 |
printf("ng_ubt: usbd_transfer_setup error=%s\n", |
579 |
usbd_errstr(error)); |
580 |
|
581 |
mtx_destroy(&mtx); |
582 |
|
583 |
return (error); |
584 |
} |
585 |
|
586 |
/* |
587 |
* Find if the Intel Wireless 8260/8265 device is in bootloader mode or is |
588 |
* running operational firmware with checking of 7-th byte "Intel version" |
589 |
* HCI command response. The value 0x23 identifies the operational firmware. |
590 |
* Attempt to initialize bluetooth stack while device is in bootloader mode |
591 |
* (7-th byte is 0x06) locks the adapter hardly and requires power on/off |
592 |
* cycle to restore. |
593 |
*/ |
594 |
|
595 |
static bool |
596 |
ubt_check_intel8265_firmware_state(struct usb_device *udev) |
597 |
{ |
598 |
#define UBT_INTEL_VER_LEN 13 |
599 |
#define UBT_INTEL_HCICMD_TIMEOUT 2000 /* ms */ |
600 |
struct ubt_hci_event_command_compl *evt; |
601 |
uint8_t buf[offsetof(struct ubt_hci_event, data) + UBT_INTEL_VER_LEN]; |
602 |
static struct ubt_hci_cmd cmd = { |
603 |
.opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_VENDOR, 0x05)), |
604 |
.length = 0, |
605 |
}; |
606 |
usb_error_t error; |
607 |
|
608 |
bzero(buf, sizeof(buf)); |
609 |
evt = (struct ubt_hci_event_command_compl *)buf; |
610 |
evt->header.length = UBT_INTEL_VER_LEN; |
611 |
|
612 |
error = ubt_do_hci_request(udev, &cmd, evt, UBT_INTEL_HCICMD_TIMEOUT); |
613 |
if (error != USB_ERR_NORMAL_COMPLETION) |
614 |
return false; |
615 |
|
616 |
return (evt->header.event == NG_HCI_EVENT_COMMAND_COMPL && |
617 |
evt->header.length == UBT_INTEL_VER_LEN && |
618 |
evt->data[4] == 0x23); |
619 |
} |
620 |
|
505 |
/* |
621 |
/* |
506 |
* Probe for a USB Bluetooth device. |
622 |
* Probe for a USB Bluetooth device. |
507 |
* USB context. |
623 |
* USB context. |
Lines 520-527
ubt_probe(device_t dev)
Link Here
|
520 |
return (ENXIO); |
636 |
return (ENXIO); |
521 |
|
637 |
|
522 |
if (usbd_lookup_id_by_uaa(ubt_ignore_devs, |
638 |
if (usbd_lookup_id_by_uaa(ubt_ignore_devs, |
523 |
sizeof(ubt_ignore_devs), uaa) == 0) |
639 |
sizeof(ubt_ignore_devs), uaa) == 0) { |
524 |
return (ENXIO); |
640 |
if ((USB_GET_DRIVER_INFO(uaa) & UBT_INTEL8265) != 0) { |
|
|
641 |
if (!ubt_check_intel8265_firmware_state(uaa->device)) |
642 |
return (ENXIO); |
643 |
} else |
644 |
return (ENXIO); |
645 |
} |
525 |
|
646 |
|
526 |
error = usbd_lookup_id_by_uaa(ubt_devs, sizeof(ubt_devs), uaa); |
647 |
error = usbd_lookup_id_by_uaa(ubt_devs, sizeof(ubt_devs), uaa); |
527 |
if (error == 0) |
648 |
if (error == 0) |
Lines 717-722
ubt_detach(device_t dev)
Link Here
|
717 |
return (0); |
838 |
return (0); |
718 |
} /* ubt_detach */ |
839 |
} /* ubt_detach */ |
719 |
|
840 |
|
|
|
841 |
/* |
842 |
* Called when incoming interrupt transfer (HCI event) has completed, i.e. |
843 |
* HCI event was received from the device during device probe stage. |
844 |
* USB context. |
845 |
*/ |
846 |
|
847 |
static void |
848 |
ubt_probe_intr_callback(struct usb_xfer *xfer, usb_error_t error) |
849 |
{ |
850 |
struct ubt_hci_event *evt = usbd_xfer_softc(xfer); |
851 |
struct usb_page_cache *pc; |
852 |
int actlen; |
853 |
|
854 |
usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); |
855 |
|
856 |
switch (USB_GET_STATE(xfer)) { |
857 |
case USB_ST_TRANSFERRED: |
858 |
if (actlen > UBT_HCI_EVENT_SIZE(evt)) |
859 |
actlen = UBT_HCI_EVENT_SIZE(evt); |
860 |
pc = usbd_xfer_get_frame(xfer, 0); |
861 |
usbd_copy_out(pc, 0, evt, actlen); |
862 |
/* OneShot mode */ |
863 |
wakeup(evt); |
864 |
break; |
865 |
|
866 |
case USB_ST_SETUP: |
867 |
submit_next: |
868 |
usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); |
869 |
usbd_transfer_submit(xfer); |
870 |
break; |
871 |
|
872 |
default: |
873 |
if (error != USB_ERR_CANCELLED) { |
874 |
printf("ng_ubt: interrupt transfer failed: %s\n", |
875 |
usbd_errstr(error)); |
876 |
/* Try clear stall first */ |
877 |
usbd_xfer_set_stall(xfer); |
878 |
goto submit_next; |
879 |
} |
880 |
break; |
881 |
} |
882 |
} /* ubt_probe_intr_callback */ |
883 |
|
720 |
/* |
884 |
/* |
721 |
* Called when outgoing control request (HCI command) has completed, i.e. |
885 |
* Called when outgoing control request (HCI command) has completed, i.e. |
722 |
* HCI command was sent to the device. |
886 |
* HCI command was sent to the device. |