Hi, Since I could not find solution on the net to switch USB bluetooth device Sitecom CN-524 (aka Cambridge Silicon Radio CN-524; idVendor=0a12, idProduct=100b) from HID to HCI mode, I made patch myself after sniffing USB messages that Windows driver sends. Since I'm not expert in programming, nor USB or bluetooth, the code maybe imperfect. I'm sending anyway so someone could review/adapt/improve and maybe even include in newer release. My capture of Windows sending the switch is available on request... debian:/home/user/src/bluez-5.21/tools# diff -u hid2hci.c.orig hid2hci.c --- hid2hci.c.orig 2014-03-11 12:20:34.000000000 +0100 +++ hid2hci.c 2014-08-05 10:45:00.000000000 +0200 @@ -119,6 +119,37 @@ return err; } +static int usb_switch_csr2(int fd, enum mode mode) +{ + char data[] = { 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + struct usbfs_disconnect disconnect; + int err; + + switch (mode) { + case HCI: + //OK. + break; + case HID: + //Not implemented! + printf("Switch to HID not implemented!\r\n"); + return -1; + } + + disconnect.interface = 0; + disconnect.flags = USBFS_DISCONNECT_EXCEPT_DRIVER; + strcpy(disconnect.driver, "usbfs"); + + if (ioctl(fd, USBFS_IOCTL_DISCONNECT, &disconnect) < 0) { + fprintf(stderr, "Can't claim interface: %s (%d)\n", + strerror(errno), errno); + return -1; + } + + err = control_message(fd, USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, USB_REQ_SET_CONFIGURATION, 0x0301, 0, data, sizeof(data), 10000); + + return err; +} + static int hid_logitech_send_report(int fd, const char *buf, size_t size) { struct hiddev_report_info rinfo; @@ -258,7 +289,7 @@ printf("Usage: hid2hci [options]\n" " --mode= mode to switch to [hid|hci] (default hci)\n" " --devpath= sys device path\n" - " --method= method to use to switch [csr|logitech-hid|dell]\n" + " --method= method to use to switch [csr|csr2|logitech-hid|dell]\n" " --help\n\n"); } @@ -274,6 +305,7 @@ enum method { METHOD_UNDEF, METHOD_CSR, + METHOD_CSR2, METHOD_LOGITECH_HID, METHOD_DELL, } method = METHOD_UNDEF; @@ -311,6 +343,9 @@ if (!strcmp(optarg, "csr")) { method = METHOD_CSR; usb_switch = usb_switch_csr; + } else if (!strcmp(optarg, "csr2")) { + method = METHOD_CSR2; + usb_switch = usb_switch_csr2; } else if (!strcmp(optarg, "logitech-hid")) { method = METHOD_LOGITECH_HID; } else if (!strcmp(optarg, "dell")) { @@ -344,6 +379,7 @@ switch (method) { case METHOD_CSR: + case METHOD_CSR2: case METHOD_DELL: { struct udev_device *dev; int handle; debian:/home/user/src/bluez-5.21/tools# diff -u hid2hci.rules.orig hid2hci.rules --- hid2hci.rules.orig 2014-08-05 09:01:22.000000000 +0200 +++ hid2hci.rules 2014-08-05 10:57:16.000000000 +0200 @@ -27,5 +27,6 @@ # CSR devices ATTR{idVendor}=="0a12|0458|05ac", ATTR{idProduct}=="1000", RUN+="hid2hci --method=csr --devpath=%p" +ATTR{idVendor}=="0a12", ATTR{idProduct}=="100b", RUN+="hid2hci --method=csr2 --devpath=%p" LABEL="hid2hci_end" debian:/home/user/src/bluez-5.21/tools# debian:/home/user# dmesg | tail -n8 [1018219.376060] usb 5-1: new full-speed USB device number 5 using uhci_hcd [1018219.710052] usb 5-1: New USB device found, idVendor=0a12, idProduct=100b [1018219.710060] usb 5-1: New USB device strings: Mfr=0, Product=2, SerialNumber=0 [1018219.710064] usb 5-1: Product: CSR8510 A10 [1018219.735632] input: CSR8510 A10 as /devices/pci0000:00/0000:00:1d.3/usb5/5-1/5-1:1.0/0003:0A12:100B.0003/input/input14 [1018219.736726] hid-generic 0003:0A12:100B.0003: input,hiddev0,hidraw0: USB HID v1.11 Keyboard [CSR8510 A10] on usb-0000:00:1d.3-1/input0 [1018219.748715] input: CSR8510 A10 as /devices/pci0000:00/0000:00:1d.3/usb5/5-1/5-1:1.1/0003:0A12:100B.0004/input/input15 [1018219.749184] hid-generic 0003:0A12:100B.0004: input,hidraw1: USB HID v1.11 Mouse [CSR8510 A10] on usb-0000:00:1d.3-1/input1 debian:/home/user# ./src/bluez-5.21/tools/hid2hci --devpath=/devices/pci0000:00/0000:00:1d.3/usb5/5-1/5-1:1.1 --method=csr2 debian:/home/user# dmesg | tail -n8 [1018219.736726] hid-generic 0003:0A12:100B.0003: input,hiddev0,hidraw0: USB HID v1.11 Keyboard [CSR8510 A10] on usb-0000:00:1d.3-1/input0 [1018219.748715] input: CSR8510 A10 as /devices/pci0000:00/0000:00:1d.3/usb5/5-1/5-1:1.1/0003:0A12:100B.0004/input/input15 [1018219.749184] hid-generic 0003:0A12:100B.0004: input,hidraw1: USB HID v1.11 Mouse [CSR8510 A10] on usb-0000:00:1d.3-1/input1 [1018390.592102] usb 5-1: USB disconnect, device number 5 [1018391.544045] usb 5-1: new full-speed USB device number 6 using uhci_hcd [1018391.719048] usb 5-1: New USB device found, idVendor=0a12, idProduct=0001 [1018391.719056] usb 5-1: New USB device strings: Mfr=0, Product=2, SerialNumber=0 [1018391.719060] usb 5-1: Product: CSR8510 A10 debian:/home/user# And after installing new udev rules file and new hid2hci tool; reboot and plugging the usb device: user@debian:~$ dmesg | tail -n 17 [ 68.822503] Bluetooth: SCO socket layer initialized [ 278.248039] usb 4-2: new full-speed USB device number 2 using uhci_hcd [ 278.613049] usb 4-2: New USB device found, idVendor=0a12, idProduct=100b [ 278.613056] usb 4-2: New USB device strings: Mfr=0, Product=2, SerialNumber=0 [ 278.613060] usb 4-2: Product: CSR8510 A10 [ 280.392124] usb 4-2: USB disconnect, device number 2 [ 280.428258] hidraw: raw HID events driver (C) Jiri Kosina [ 280.452772] usbcore: registered new interface driver usbhid [ 280.452780] usbhid: USB HID core driver [ 281.320043] usb 4-2: new full-speed USB device number 3 using uhci_hcd [ 281.507066] usb 4-2: New USB device found, idVendor=0a12, idProduct=0001 [ 281.507073] usb 4-2: New USB device strings: Mfr=0, Product=2, SerialNumber=0 [ 281.507078] usb 4-2: Product: CSR8510 A10 [ 281.551508] usbcore: registered new interface driver btusb [ 282.719805] Bluetooth: BNEP (Ethernet Emulation) ver 1.3 [ 282.719815] Bluetooth: BNEP filters: protocol multicast [ 282.719831] Bluetooth: BNEP socket layer initialized user@debian:~$ hcitool dev Devices: hci0 00:09:DD:42:89:D4 user@debian:~$ So far my contribution... Hope it's useful for the community. Regards, Fred
--- tools/hid2hci.rules.orig 2014-08-05 09:01:22.000000000 +0200 +++ tools/hid2hci.rules 2014-08-05 10:57:16.000000000 +0200 @@ -27,5 +27,6 @@ # CSR devices ATTR{idVendor}=="0a12|0458|05ac", ATTR{idProduct}=="1000", RUN+="hid2hci --method=csr --devpath=%p" +ATTR{idVendor}=="0a12", ATTR{idProduct}=="100b", RUN+="hid2hci --method=csr2 --devpath=%p" LABEL="hid2hci_end"
--- tools/hid2hci.c.orig 2014-03-11 12:20:34.000000000 +0100 +++ tools/hid2hci.c 2014-08-05 10:45:00.000000000 +0200 @@ -119,6 +119,37 @@ return err; } +static int usb_switch_csr2(int fd, enum mode mode) +{ + char data[] = { 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + struct usbfs_disconnect disconnect; + int err; + + switch (mode) { + case HCI: + //OK. + break; + case HID: + //Not implemented! + printf("Switch to HID not implemented!\r\n"); + return -1; + } + + disconnect.interface = 0; + disconnect.flags = USBFS_DISCONNECT_EXCEPT_DRIVER; + strcpy(disconnect.driver, "usbfs"); + + if (ioctl(fd, USBFS_IOCTL_DISCONNECT, &disconnect) < 0) { + fprintf(stderr, "Can't claim interface: %s (%d)\n", + strerror(errno), errno); + return -1; + } + + err = control_message(fd, USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, USB_REQ_SET_CONFIGURATION, 0x0301, 0, data, sizeof(data), 10000); + + return err; +} + static int hid_logitech_send_report(int fd, const char *buf, size_t size) { struct hiddev_report_info rinfo; @@ -258,7 +289,7 @@ printf("Usage: hid2hci [options]\n" " --mode= mode to switch to [hid|hci] (default hci)\n" " --devpath= sys device path\n" - " --method= method to use to switch [csr|logitech-hid|dell]\n" + " --method= method to use to switch [csr|csr2|logitech-hid|dell]\n" " --help\n\n"); } @@ -274,6 +305,7 @@ enum method { METHOD_UNDEF, METHOD_CSR, + METHOD_CSR2, METHOD_LOGITECH_HID, METHOD_DELL, } method = METHOD_UNDEF; @@ -311,6 +343,9 @@ if (!strcmp(optarg, "csr")) { method = METHOD_CSR; usb_switch = usb_switch_csr; + } else if (!strcmp(optarg, "csr2")) { + method = METHOD_CSR2; + usb_switch = usb_switch_csr2; } else if (!strcmp(optarg, "logitech-hid")) { method = METHOD_LOGITECH_HID; } else if (!strcmp(optarg, "dell")) { @@ -344,6 +379,7 @@ switch (method) { case METHOD_CSR: + case METHOD_CSR2: case METHOD_DELL: { struct udev_device *dev; int handle;