diff options
Diffstat (limited to 'md')
-rw-r--r-- | md/writeup/webusb_example.md | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/md/writeup/webusb_example.md b/md/writeup/webusb_example.md new file mode 100644 index 0000000..a98216b --- /dev/null +++ b/md/writeup/webusb_example.md @@ -0,0 +1,219 @@ +title:WebUSB example +keywords:linux,webusb,usb,usbmon,ch341,pl2101 + +# WebUSB example +## Hardware requirements + +Modern browser have some cool API's like WebUSB that allows from browser +acces USB stack. Here is a steps to try it out. As internet doesnt have +any basic example of stuff how things works, here is all info needed to +make first WebUSB requests running. On most basic devices out there. +USB serail interface is cheap to get on any online shop here is quite +common chip models CH341,PL2303. + +TODO +* describe how request decoded add py example code +* describe initialisation phase +* Describe how to send data on CH341 +* Describe how to recieve data on CH341 +* sniffed usbmon traffic desctiption + +## Gathering info + +Linux provides utilities to list all usb device connections. + +``` +lsusb +``` + +Output will be something like: +``` +Bus 002 Device 027: ID 1bcf:0007 Sunplus Innovation Technology Inc. Optical Mouse +Bus 002 Device 026: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port +Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub +``` + +Our PL2303 device is connected and is on a bus 2.0 + + +When USB device is connected to bus linux logs some information. When USB +device is there in dmesg you can find out some info. +``` +dmesg | tail +``` +Most important part is to find device bus id in our case it is "2-1:1.0" + +``` +[190298.876894] usb 2-1: USB disconnect, device number 26 +[190298.877195] pl2303 ttyUSB0: pl2303 converter now disconnected from ttyUSB0 +[190298.877245] pl2303 2-1:1.0: device disconnected +[190301.871959] usb 2-1: new full-speed USB device number 28 using xhci_hcd +[190302.012793] usb 2-1: New USB device found, idVendor=067b, idProduct=2303, bcdDevice= 3.00 +[190302.012799] usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0 +[190302.012802] usb 2-1: Product: USB-Serial Controller +[190302.012804] usb 2-1: Manufacturer: Prolific Technology Inc. +[190302.013632] pl2303 2-1:1.0: pl2303 converter detected +[190302.014426] usb 2-1: pl2303 converter now attached to ttyUSB0 +``` + +## Setting up udev + +Use usb bus id to unbind driver. If its not done there will be no permission +error, or device busy error. Use one of lines to unbind device driver by usb +bus id. + +``` +echo "2-2:1.0" > /sys/bus/usb/drivers/pl2303/unbind +echo "2-2:1.0" > /sys/bus/usb/drivers/ch341/unbind +``` + + +If you have other errors related to not able to connect to device then or no +permsision. Add file to udev rules in /etc/udev/rules.d directory + + +/etc/udev/rules.d/88-hello-usb.rules + +Here is examples of USB ids for PL2303 and CH341 +``` +SUBSYSTEMS=="usb", ATTR{idVendor}=="067b", ATTR{idProduct}=="2303", MODE:="0666" +SUBSYSTEMS=="usb", ATTR{idVendor}=="1a86", ATTR{idProduct}=="7523", MODE:="0666" +``` + +As rulles is not loaded after file are created or new entries are added. +Need to restart udev daemon so new rulles are added to current running rulles. + +``` +udevadm control --reload-rules && udevadm trigger + +``` + +## Programming + +Most of modern browsers provide javascript API for accesing USB its called +WebUSB API. + +### Get request to access device + +First thing that is needed to do is request devices. Popup windows to select +device will appear. + +```js +serial.requestPort = function() { + const filters = [ + { vendorId:0x067b, productId:0x2303 }, //cp210 + { vendorId:0x1a86, productId:0x7523 }, //ch341 + ]; + return navigator.usb.requestDevice({ 'filters': filters }).then( + device => new serial.Port(device) + ); + } +``` + +### Recieving data + +To recieve date control request need to be created. +Request constructed according to suported protocol that may differ +from device to device. + +PL2303 and CH3421 have totaly different interfeises. Steps to initialise +device also differs. + +```js +serial.Port.prototype.vendorRead = function(value) { + console.log("Read val="+value); + return this.device.controlTransferIn({ + 'requestType': 'vendor', + 'recipient': 'device', + 'request':serial.VENDOR_READ_REQUEST, + 'value':value, + 'index':0, + },1); + }; +``` + +### Sending data + +```js +serial.Port.prototype.vendorWrite = function(value,index) { + console.log("Write idx "+index+" val = "+value) + return this.device.controlTransferOut({ + 'requestType': 'vendor', + 'recipient': 'device', + 'request': serial.VENDOR_WRITE_REQUEST, + 'value': value, + 'index': index, + }); + }; +``` + +### CH341 chip request table + +| | | +| --- | --- | + + +### PL2301 chip request table + +| Request name | value | +| --- | --- | +| CP210_VENDOR_WRITE_REQUEST | | +| CP210_VENDOR_READ_REQUEST | | +| CP210_GET_LINE_REQUEST | | +| CP210_SET_LINE_REQUEST | | +| CP210_SET_CONTROL_REQUEST | | +| CP210_BREAK_REQUEST | | + + +## Sniffing USB traffic + +Linux provides infrastructure to see USB transactions. Its allow to +debug or sniff some USB trafic, so in case if there is some unknown +parts how USB initialisation is working, you have change to figure out +by seeing sequenc of commands sent to USB interface. + +### Setting usbmon + +``` +mount -t debugfs none_debugs /sys/kernel/debug +modprobe usbmon +ls /sys/kernel/debug/usb/usbmon +``` + +``` +T: Bus=01 Lev=04 Prnt=43 Port=03 Cnt=02 Dev#= 45 Spd=12 MxCh= 0 +D: Ver= 1.10 Cls=ff(vend.) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 +P: Vendor=1a86 ProdID=7523 Rev= 2.54 +S: Product=USB2.0-Serial +C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr= 96mA +I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=02 Driver=ch341 +E: Ad=82(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms +E: Ad=02(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms +E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=1ms +``` + +``` +cat /sys/kernel/debug/usb/usbmon/1u > /tmp/1.mon.out +``` + +### Sniffed traffic example + +## Thx + +[daGrevis](https://github.com/daGrevis) - gave tips about using await/async in js +[jurgenzz](https://github.com/jurgenzz) - help solving await/async issues +[#developers.lv](https://developers.lv) - having patiens for listening to js nonsence from js-newbie + +## Source + + + +## Links +[https://www.mankier.com/8/usbmon](https://www.mankier.com/8/usbmon) +[https://www.kernel.org/doc/Documentation/usb/usbmon.txt](https://www.kernel.org/doc/Documentation/usb/usbmon.txt) +[https://elinux.org/images/1/17/USB_Debugging_and_Profiling_Techniques.pdf](https://elinux.org/images/1/17/USB_Debugging_and_Profiling_Techniques.pdf) +[https://developer.mozilla.org/en-US/docs/Web/API/USB](https://developer.mozilla.org/en-US/docs/Web/API/USB) +[https://developer.mozilla.org/en-US/docs/Web/API/USBDevice](https://developer.mozilla.org/en-US/docs/Web/API/USBDevice) +[https://github.com/ultibohub/Core/blob/master/source/rtl/ultibo/drivers/pl2303.pas](https://github.com/ultibohub/Core/blob/master/source/rtl/ultibo/drivers/pl2303.pas) +[https://github.com/torvalds/linux/blob/master/drivers/usb/serial/pl2303.c](https://github.com/torvalds/linux/blob/master/drivers/usb/serial/pl2303.c) +[https://www.beyondlogic.org/usbnutshell/usb1.shtml](https://www.beyondlogic.org/usbnutshell/usb1.shtml) |