Hid 2 hci switch on Cambridge Silicon Radio CN-524 (idVendor=0a12, idProduct=100b)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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;

[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux