LedgerHQ / speculos

Ledger Nano/Blue apps emulator
GNU Lesser General Public License v3.0
151 stars 57 forks source link

HID support #40

Open Ericson2314 opened 4 years ago

Ericson2314 commented 4 years ago

Perhaps this can help https://www.kernel.org/doc/Documentation/hid/uhid.txt and https://github.com/torvalds/linux/blob/master/samples/uhid/uhid-example.c ? No that is different (user space driver), but dummy_hcd and gadgetfs does.

I'll be getting started on this but it would be nice to collaborate with upstream.

greenknot commented 4 years ago

Hello John,

A few months ago, we actually developed a proof-of-concept code relying on dummy_usb to allow usual clients to work with a speculos-like emulator. It isn't super convenient because this kernel module isn't built by default on most Linux distros and there are a few bugs with userland libraries (libusb IIRC).

Anyway, here are a few notes and scripts in the usb branch. Disclaimer: this is highly experimental and probably doesn't work as is, but it might give a few hints.

As a side note, usb wasn't supported at all at the time, it might also be of interest.

Ericson2314 commented 4 years ago

Awesome! Will check it out.

gitmachtl commented 3 years ago

Hi, are there any updates available on this? I would like to use speculos for Testing of the Cardano-App with the cardano-hw-cli, but for that speculos must appear like a normal usb device. Is this possible now?

greenknot commented 3 years ago

Unfortunately no.

I guess you can modify the cardano-hw-cli to communicate with speculos through TCP though.

mullroy commented 1 year ago

Good day, I've managed to build the dummy_hcd kernel module and get it loaded, as per your instructions in the USB branch. I can run the 'setup.sh start' script to create the emulated Ledger USB device. If I run 'lsmod' and 'dmesg' I can see the device:

$ sudo lsmod Bus 003 Device 002: ID 2c97:0001 Ledger Nano S

$ sudo dmesg [] dummy_hcd dummy_hcd.0: USB Host+Gadget Emulator, driver 02 May 2005 [] dummy_hcd dummy_hcd.0: Dummy host controller [] dummy_hcd dummy_hcd.0: new USB bus registered, assigned bus number 3 [] usb usb3: New USB device found, idVendor=1d6b, idProduct=0002, bcdDevice= 5.15 [] usb usb3: New USB device strings: Mfr=3, Product=2, SerialNumber=1 [] usb usb3: Product: Dummy host controller [] usb usb3: Manufacturer: Linux 5.15.0-73-generic dummy_hcd [] usb usb3: SerialNumber: dummy_hcd.0 [] hub 3-0:1.0: USB hub found [] hub 3-0:1.0: 1 port detected

$ sudo cat /sys/kernel/debug/usb/devices Emulated device: T: Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 10 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=2c97 ProdID=0001 Rev= 2.00 S: Manufacturer=Ledger S: Product=Nano S S: SerialNumber=0001 C: #Ifs= 2 Cfg#= 1 Atr=80 MxPwr=100mA I: If#= 0 Alt= 0 #EPs= 2 Cls=03(HID ) Sub=01 Prot=01 Driver=usbfs E: Ad=81(I) Atr=03(Int.) MxPS= 64 Ivl=1ms E: Ad=02(O) Atr=03(Int.) MxPS= 64 Ivl=1ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=03(HID ) Sub=01 Prot=01 Driver=usbhid E: Ad=85(I) Atr=03(Int.) MxPS= 64 Ivl=1ms E: Ad=07(O) Atr=03(Int.) MxPS= 64 Ivl=1ms

Real NanoS T: Bus=01 Lev=01 Prnt=01 Port=09 Cnt=05 Dev#= 51 Spd=12 MxCh= 0 D: Ver= 2.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=2c97 ProdID=1011 Rev= 2.01 S: Manufacturer=Ledger S: Product=Nano S S: SerialNumber=0001 C: #Ifs= 2 Cfg#= 1 Atr=c0 MxPwr=100mA I: If#= 0 Alt= 0 #EPs= 2 Cls=03(HID ) Sub=00 Prot=00 Driver=usbhid E: Ad=82(I) Atr=03(Int.) MxPS= 64 Ivl=1ms E: Ad=02(O) Atr=03(Int.) MxPS= 64 Ivl=1ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=83(I) Atr=03(Int.) MxPS= 64 Ivl=1ms E: Ad=03(O) Atr=03(Int.) MxPS= 64 Ivl=1ms

Differences that I can pick up between the emulated and real device: My real Ledger NanoS has product ID 1011, rev 2.01 The emulated device is set to product ID 0001, rev 2.00

The usb endpoints are also different: On the real device, If#0 Driver=usbhid and If#1 Driver=none On the emulated device: If#0 Driver=usbfs and If#1 Driver=usbhid

While electrum bitcoin wallet tries to scan for a hardware device, it resolves the HID device via the btchip-python project. To pass the scan test, the 'usage_page' must be 0xffa0. See electrum/plugins/ledger/ledger.py, function: can_recognize_device()

The setup script doesn't have a field called 'usage_page' for the usb endpoints. I couldn't find any thing related to gadgetfs or usb_gadget regarding setup of a field called 'usage_page'.

Anybody else like to have a go at the setup.sh script?

After a bit of further digging about the USB HID structure: The utilities usbhid-dump can dump the USB info from the real Ledger hardare. The hidrd utility can help to format the descriptor data in a meaningfull way.

The 'usagePage' is the first 2 fields of the descriptor data. Electrum wallet via btchip-python expect this field to be 0xffa0, where 0xff00 to 0xffff are vendor specifiec fields (https://github.com/DIGImend/usbhid-dump) (https://github.com/DIGImend/hidrd)