I recently bought a Sitecom CNT-524 Bluetooth 4.0 USB dongle, which seems to be based on a Cambridge Silicon Radio reference design, CSR 8510 A10 aka CSR Nanosira. It comes up in some sort of dummy HID mode which does nothing useful, or I couldn’t find what it would do. So I set out to make it work properly.
I started out by looking at what comes up by default when you plug in the device:
Bus 006 Device 023: ID 0a12:100b Cambridge Silicon Radio, Ltd
[361895.944068] usb 6-2: new full-speed USB device number 23 using uhci_hcd [361896.302190] usb 6-2: New USB device found, idVendor=0a12, idProduct=100b [361896.302203] usb 6-2: New USB device strings: Mfr=0, Product=2, SerialNumber=0 [361896.302211] usb 6-2: Product: CSR8510 A10 [361896.329542] input: CSR8510 A10 as /devices/pci0000:00/0000:00:1d.0/usb6/6-2/6-2:1.0/input/input53 [361896.329986] hid-generic 0003:0A12:100B.0027: input,hiddev0,hidraw0: USB HID v1.11 Keyboard [CSR8510 A10] on usb-0000:00:1d.0-2/input0 [361896.338126] input: CSR8510 A10 as /devices/pci0000:00/0000:00:1d.0/usb6/6-2/6-2:1.1/input/input54 [361896.338597] hid-generic 0003:0A12:100B.0028: input,hidraw1: USB HID v1.11 Mouse [CSR8510 A10] on usb-0000:00:1d.0-2/input1
As said, the device doesn’t seem to do anything useful in this mode. Maybe it would react to some BT-HID or BT-LE-HID devices automagically?
So I started looking at how to get this device to do something sensible. In the end I caved and booted a virtual Windows7 (the virtual machines from http://modern.ie are great for such one-shot exercises), installed the driver (418MByte, sic!) and attached the USB device to the virtual machine. Lo and behold the device disappeared and a new device appeared.
[362349.728136] usb 6-2: USB disconnect, device number 23 [362350.668045] usb 6-2: new full-speed USB device number 24 using uhci_hcd [362350.845137] usb 6-2: New USB device found, idVendor=0a12, idProduct=0001 [362350.845144] usb 6-2: New USB device strings: Mfr=0, Product=2, SerialNumber=0 [362350.845148] usb 6-2: Product: CSR8510 A10
Bus 006 Device 024: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
Just what I was looking for and also that device then does have BT-LE (aka Bluetooth Smart) functionality without requiring further exact steps.
# hcitool -i hci1 lescan LE Scan ... 00:18:33:7A:96:05 (unknown) 00:18:33:7A:96:05 MetaWatch 05 00:17:EA:92:05:E4 (unknown) 00:17:EA:92:05:E4 Biscuit 78:C5:E5:6E:E3:38 (unknown) 78:C5:E5:6E:E3:38 SensorTag
It immediately finds my TI SmartTag, MetaWatch and RedBearLab BLE Mini, all of those are LowEnergy devices.
Having verified that, it’s time to get back to making this work on Linux without the help of a VM. So the next logical step was to find out what exactly happens under Windows, so that I could then reproduce it using the fine usb_modeswitch tool. For that I’ve taken a look at Mark’s blog post and adapted it to my situation.
One of the problems I faced was that the Windows drivers don’t seem to work properly in the Windows XP VM I had. So I resorted to, my anyway preferred tool, Wireshark for sniffing the USB traffic directly on the host Linux machine:
# modprobe usbmon
Then start Wireshark and start listening to the right bus as indicated by e.g. lsusb. In my case that’ bus 6, as you can also see from the previous output. Then attach the USB device to the virtual machine and let the drivers do their work. Verify the device switched. Stop the capture and restart. Rinse, repeat.
Luckily I took a look at the Windows services that were running and found one suspiciously named “CSR Bluetooth Switcher Service” with the telling description of “Allows a Bluetooth device to switch from boot mode to Bluetooth HCI mode“. I then verified, that it does exactly that, by stopping the service and attaching the dongle – It wouldn’t switch to HCI mode until I restarted the service. I still don’t understand why they don’t come up in HCI mode by default…
This allowed to narrow things down to exactly one packet sent from the Laptop to the device:
No. Time Source Destination Protocol Length Info 112 66.328046000 host 14.0 USBHID 73 SET_REPORT Request Frame 112: 73 bytes on wire (584 bits), 73 bytes captured (584 bits) on interface 0 Interface id: 0 Encapsulation type: USB packets with Linux header and padding (115) Arrival Time: Oct 5, 2013 16:43:39.667846000 UTC [Time shift for this packet: 0.000000000 seconds] Epoch Time: 1380991419.667846000 seconds [Time delta from previous captured frame: 26.537027000 seconds] [Time delta from previous displayed frame: 26.537027000 seconds] [Time since reference or first frame: 66.328046000 seconds] Frame Number: 112 Frame Length: 73 bytes (584 bits) Capture Length: 73 bytes (584 bits) [Frame is marked: False] [Frame is ignored: False] [Protocols in frame: usb:usbhid] USB URB URB id: 0xffff88008eafd840 URB type: URB_SUBMIT ('S') URB transfer type: URB_CONTROL (0x02) Endpoint: 0x00, Direction: OUT 0... .... = Direction: OUT (0) .000 0000 = Endpoint value: 0 Device: 14 URB bus id: 6 Device setup request: relevant (0) Data: present (0) URB sec: 1380991419 URB usec: 667846 URB status: Operation now in progress (-EINPROGRESS) (-115) URB length [bytes]: 9 Data length [bytes]: 9 [Response in: 113] [bInterfaceClass: HID (0x03)] URB setup bmRequestType: 0x21 0... .... = Direction: Host-to-device .01. .... = Type: Class (0x01) ...0 0001 = Recipient: Interface (0x01) bRequest: SET_REPORT (0x09) wValue: 0x0301 ReportID: 1 ReportType: Feature (3) wIndex: 0 wLength: 9 0000 40 d8 af 8e 00 88 ff ff 53 02 00 0e 06 00 00 00 @.......S....... 0010 bb 41 50 52 00 00 00 00 c6 30 0a 00 8d ff ff ff .APR.....0...... 0020 09 00 00 00 09 00 00 00 21 09 01 03 00 00 09 00 ........!....... 0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0040 01 05 00 00 00 00 00 00 00 .........
The device then ACKs this message with a status code of 0 (success) and some last messages, of which the last one cuts off and is thus malformed. 60ms later it is gone. Then the ‘right’ device appears and enumerates.
That’s where I’m currently stuck. I’ve tried to send the bolded payload (or some part/permutation of it) to the device using usb_modeswitch, but for some reason it seems it can’t get to the device endpoint 0x00 that windows uses for this message.
# usb_modeswitch -v0a12 -p100b -W -m00 -M "210901030000090000000000000000000000000000000000010500000000000000" […] Accessing device 016 on bus 006 ... Getting the current device configuration ... OK, got current device configuration (1) Using interface number 0 Error: message endpoint not given or found. Aborting.
I’ve emailed the usb_modeswitch author to see if he sees something obvious that I have missed. After all USB hacking is not my every day pastime.
I’ll write a follow-up blog post once I’ve made progress with this. For the moment I have to begrudgingly resort to waking up a Windows VM for switching the device after plugging it in.