-
Trying Rust
09/20/2021 at 04:02 • 0 commentsextern crate hidapi; use hidapi::HidApi; fn main() { let mut found = false; match HidApi::new() { Ok(api) => { for device in api.device_list() { if device.vendor_id() == 0x1a86 && device.product_id() == 0xe041 { found = true; println!( "{:04x}:{:04x}, {:?}", device.vendor_id(), device.product_id(), device.serial_number() ); match device.open_device(&api){ Ok(hid_device) => { let data = [0x00, 0x55, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; match hid_device.write(&data) { Ok(result) => { eprintln!("write: {}", result); }, Err(e) => { eprintln!("write Error: {}", e); } } }, Err(e) => { eprintln!("Open Error: {}", e); } } } } }, Err(e) => { eprintln!("HIDApi Error: {}", e); }, } if !found { println!("No device found"); } }
PS C:\Users\Stephen\Documents\GitHub\USBSwitch\Rust> cargo build Finished dev [unoptimized + debuginfo] target(s) in 0.02s PS C:\Users\Stephen\Documents\GitHub\USBSwitch\Rust> .\target\debug\usbshare.exe No device found PS C:\Users\Stephen\Documents\GitHub\USBSwitch\Rust> .\target\debug\usbshare.exe 1a86:e041, None write: 9
That was surprisingly not hard. Sometimes the write fails, but it still switches, I think it switches before/while sending the ACK.
Trying linux.stephen@AO751h:~/Documents/usbshare/usbshare$ cargo build Compiling usbshare v0.1.0 (/home/stephen/Documents/usbshare/usbshare) Finished dev [unoptimized + debuginfo] target(s) in 3.07s stephen@AO751h:~/Documents/usbshare/usbshare$ ./target/debug/usbshare 1a86:e041, None Open Error: Failed opening hid device stephen@AO751h:~/Documents/usbshare/usbshare$ ls -alh /dev/hidraw0 crw-rw-r-- 1 root plugdev 243, 0 Sep 19 21:17 /dev/hidraw0 stephen@AO751h:~/Documents/usbshare/usbshare$ sudo ./target/debug/usbshare [sudo] password for stephen: 1a86:e041, None write Error: hidapi error: hid_error is not implemented yet
Sudo works.
Oh, udev again, Rust HID is using "0002:0003:00" instead of "/dev/hidraw#". New udev rules:
#works for pyusb control access, and rust hid SUBSYSTEM=="usb", ATTR{idVendor}=="1a86", ATTR{idProduct}=="e041", MODE="0664", GROUP="plugdev" #works or chrome WebHID KERNEL=="hidraw*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="e041", MODE="0664", GROUP="plugdev"
stephen@AO751h:~/Documents/usbshare/usbshare$ sudo nano /etc/udev/rules.d/99-hid.rules stephen@AO751h:~/Documents/usbshare/usbshare$ ./target/debug/usbshare 1a86:e041, None, "0002:0007:00" Open Error: Failed opening hid device stephen@AO751h:~/Documents/usbshare/usbshare$ sudo udevadm control --reload-rules stephen@AO751h:~/Documents/usbshare/usbshare$ sudo udevadm trigger stephen@AO751h:~/Documents/usbshare/usbshare$ ./target/debug/usbshare 1a86:e041, None, "0002:0007:00" write Error: hidapi error: hid_error is not implemented yet
Success.
-
UDEV for linux
09/18/2021 at 17:48 • 2 commentsDoesn't work on linux. Udev strikes again. udev helper things:
sudo udevadm control --reload-rules sudo udevadm trigger journalctl -f udevadm monitor --environment udevadm info -q all -a /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-2 udevadm info -q all -a /dev/hidraw1 sudo udevadm control --log-priority=dubug
run
udevadm monitor --environment
and re-plug:stephen@AO751h:~$ udevadm info -q all -a /dev/hidraw1 Udevadm info starts with the device specified by the devpath and then walks up the chain of parent devices. It prints for every device found, all possible attributes in the udev rules key format. A rule to match, can be composed by the attributes of the device and the attributes from one single parent device. looking at device '/devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/0003:1A86:E041.000E/hidraw/hidraw1': KERNEL=="hidraw1" SUBSYSTEM=="hidraw" DRIVER=="" looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/0003:1A86:E041.000E': KERNELS=="0003:1A86:E041.000E" SUBSYSTEMS=="hid" DRIVERS=="hid-generic" ATTRS{country}=="00" looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0': KERNELS=="2-2:1.0" SUBSYSTEMS=="usb" DRIVERS=="usbhid" ATTRS{authorized}=="1" ATTRS{bAlternateSetting}==" 0" ATTRS{bInterfaceClass}=="03" ATTRS{bInterfaceNumber}=="00" ATTRS{bInterfaceProtocol}=="00" ATTRS{bInterfaceSubClass}=="00" ATTRS{bNumEndpoints}=="01" ATTRS{supports_autosuspend}=="1" looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2/2-2': KERNELS=="2-2" SUBSYSTEMS=="usb" DRIVERS=="usb" ATTRS{authorized}=="1" ATTRS{avoid_reset_quirk}=="0" ATTRS{bConfigurationValue}=="1" ATTRS{bDeviceClass}=="00" ATTRS{bDeviceProtocol}=="00" ATTRS{bDeviceSubClass}=="00" ATTRS{bMaxPacketSize0}=="8" ATTRS{bMaxPower}=="100mA" ATTRS{bNumConfigurations}=="1" ATTRS{bNumInterfaces}==" 1" ATTRS{bcdDevice}=="1000" ATTRS{bmAttributes}=="80" ATTRS{busnum}=="2" ATTRS{configuration}=="" ATTRS{devnum}=="12" ATTRS{devpath}=="2" ATTRS{idProduct}=="e041" ATTRS{idVendor}=="1a86" ATTRS{ltm_capable}=="no" ATTRS{maxchild}=="0" ATTRS{quirks}=="0x0" ATTRS{removable}=="unknown" ATTRS{rx_lanes}=="1" ATTRS{speed}=="12" ATTRS{tx_lanes}=="1" ATTRS{urbnum}=="14" ATTRS{version}==" 1.10" looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2': KERNELS=="usb2" SUBSYSTEMS=="usb" DRIVERS=="usb" ATTRS{authorized}=="1" ATTRS{authorized_default}=="1" ATTRS{avoid_reset_quirk}=="0" ATTRS{bConfigurationValue}=="1" ATTRS{bDeviceClass}=="09" ATTRS{bDeviceProtocol}=="00" ATTRS{bDeviceSubClass}=="00" ATTRS{bMaxPacketSize0}=="64" ATTRS{bMaxPower}=="0mA" ATTRS{bNumConfigurations}=="1" ATTRS{bNumInterfaces}==" 1" ATTRS{bcdDevice}=="0504" ATTRS{bmAttributes}=="e0" ATTRS{busnum}=="2" ATTRS{configuration}=="" ATTRS{devnum}=="1" ATTRS{devpath}=="0" ATTRS{idProduct}=="0001" ATTRS{idVendor}=="1d6b" ATTRS{interface_authorized_default}=="1" ATTRS{ltm_capable}=="no" ATTRS{manufacturer}=="Linux 5.4.0-77-generic uhci_hcd" ATTRS{maxchild}=="2" ATTRS{product}=="UHCI Host Controller" ATTRS{quirks}=="0x0" ATTRS{removable}=="unknown" ATTRS{rx_lanes}=="1" ATTRS{serial}=="0000:00:1d.0" ATTRS{speed}=="12" ATTRS{tx_lanes}=="1" ATTRS{urbnum}=="207" ATTRS{version}==" 1.10" looking at parent device '/devices/pci0000:00/0000:00:1d.0': KERNELS=="0000:00:1d.0" SUBSYSTEMS=="pci" DRIVERS=="uhci_hcd" ATTRS{ari_enabled}=="0" ATTRS{broken_parity_status}=="0" ATTRS{class}=="0x0c0300" ATTRS{consistent_dma_mask_bits}=="32" ATTRS{d3cold_allowed}=="0" ATTRS{device}=="0x8114" ATTRS{dma_mask_bits}=="32" ATTRS{driver_override}=="(null)" ATTRS{enable}=="1" ATTRS{irq}=="23" ATTRS{local_cpulist}=="0-1" ATTRS{local_cpus}=="3" ATTRS{msi_bus}=="1" ATTRS{revision}=="0x07" ATTRS{subsystem_device}=="0x0244" ATTRS{subsystem_vendor}=="0x1025" ATTRS{vendor}=="0x8086" looking at parent device '/devices/pci0000:00': KERNELS=="pci0000:00" SUBSYSTEMS=="" DRIVERS==""
udevadm info -q all -a /dev/hidraw1
Seems that the rule
KERNEL=="hidraw*", ATTR{idVendor}=="1a86", ATTR{idProduct}=="e041", MODE="0666"
doesn't catch vendor/product parameters. I guess I'll stick with
KERNEL=="hidraw*", MODE="0666", GROUP="plugdev"
-
Back to JS with webHID
09/18/2021 at 06:44 • 0 commentsdocument.addEventListener('DOMContentLoaded', async () => { let permissionsRequestButton = document.getElementById("switch"); permissionsRequestButton.addEventListener("click", () => { navigator.hid.requestDevice({ filters: [{ vendorId: 0x1a86, productId: 0xe041 }] }).then((devices) =>{ devices[0].open().then(() => { const wValue = new Uint8Array([ 0x55, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]); devices[0].sendReport(0, wValue).then(() => { console.log("Sent output report: "+ wValue); }).catch(err => { console.log(err + " " + wValue) }) }) }); }); });
I guess I only really need the one USBHID SET_REPORT
-
Trying python
09/17/2021 at 23:46 • 0 commentsimport usb.core import usb.util import usb.control # find our device dev = usb.core.find(idVendor=0x1a86, idProduct=0xe041) # was it found? if dev is None: raise ValueError('Device not found') # usb.control.set_configuration(dev, 0) bmRequestType = usb.util.build_request_type(usb.util.CTRL_OUT, usb.util.CTRL_TYPE_STANDARD, usb.util.CTRL_RECIPIENT_DEVICE) #// should be 0x00 bRequest = 0x09 bConfigurationValue = 1 wIndex = 0 wLength = 0 dev.ctrl_transfer(bmRequestType, bRequest, bConfigurationValue) dev.ctrl_transfer(bmRequestType, bRequest, bConfigurationValue)
Doesn't work though. PyUSB sent out a message that was 64 long instead of the 36.
Unless that is libusb doing the padding, IDK.
I don't know if the device keys off the length, or if it is missing the other hid messages first.The mystery exe runs in wine and puts the icon in the panel, but doesn't send off any usb communication though.
I noticed that the last SET_REPORT differed from the previous pile of SET_REPORT
55 01 00 00 00 00 00 00
Then
55 02 00 00 00 00 00 00
Switching to hid I guess.
libhidapi-hidraw0 won't open the device, and libhidapi-libusb.so.0 won't accept the buffer "ctypes.ArgumentError: argument 2: <type 'exceptions.TypeError'>: wrong type"
import hid hid.lib # libhidapi-hidraw0 # hid.HIDException: unable to open device h = hid.Device(vid, pid) h.open(vid, pid) buf = [0]*8 buf[0] = 0x55 buf[1] = 0x01 #libhidapi-libusb.so.0 #ctypes.ArgumentError: argument 2: <type 'exceptions.TypeError'>: wrong type h.send_feature_report([0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) h.send_feature_report([0x55, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
-
Trying WebUSB
09/14/2021 at 16:53 • 0 commentsTrying to find a quick way to test writing out a single usb message, I didn't find any test programs.
Nirsoft USBDeview, and microsoft usbview.exe helped see the devices, but that was it.
HIDPyToy didn't help, because I needed to send a non-hid message.Now I'm looking at webusb, https://wicg.github.io/webusb/#enumdef-usbrequesttype
It won't be useful, but it might be an easy test, and easy to port...? Should look something like:
device = await navigator.usb.requestDevice({ filters: [{ vendorId: device.vendorId, productId: device.productId }] }); await device.open(); await device.controlTransferOut({ requestType: 'standard', recipient: 'device', request: 0x09, value: 0x01, index: 0x00 })
Device.open -> DOMException: Access denied. Looks like a windows problem.
Ok, trying linux. ... no chrome installed. installing chromium. navigator.usb doesn't exist on chromium 92. Should be in since chrome 61. Maybe it is just stripped out of chromium. Downloading to be a local file worked, oh HTTPS only. DOMException: Access denied. Added udev rule. not fixed. maybe udev didn't work
Maybe I should have checked usb-internals first. It looks like the "Testing Tool Panel" is what I wanted. I'm guessing the error is the same permissions error.
-
Hardware/Software investigation
09/14/2021 at 16:02 • 0 commentsThe usb hub has 2 un-connected ports. the 4 CH440G look to be the actual switches. CH9884 doesn't seem to have any data sheets online.
When the port is selected, it connects a generic usb hub. same Vendor/Product as a Monoprice "aquamini".
When the main hub is disconnected, it connects a device to the bus instead:
idVendor: 0x1A86 = Nanjing Qinherg Electronics Co., Ltd.
idProduct: 0xE041Which I'm guessing is CH9884
The "Drivers" cd was a burned cd rom with USBShare.exe, and an installer, that I assume puts it somewhere and adds it to startup. I didn't run the installer. Running strings on the exe showed some usb.
VID_1A86&PID_E041
VID_1A86&PID_E040
VID_5131&PID_2007I ran the exe through ghidra, to see if I could find anything, but I didn't find much. the USB identifiers, and some other strings. \(〇_o)/ I don't have the patience for this. I just decided to run the exe, and wireshark it.
version 1.0.0
Build: May 14 2011
Maybe it still worksWell, it puts a it turns green when connected to the usb hub, and ... well it turns green when not connected too. Turns red, then yellow when switching away.
In yellow state, the program continuously asks (I think it is just connected checks?):
Frame 31356: 44 bytes on wire (352 bits), 44 bytes captured (352 bits) on interface wireshark_extcap2440, id 0 USB URB [Source: host] [Destination: 2.4.0] USBPcap pseudoheader length: 28 IRP ID: 0xffff898c72c27010 IRP USBD_STATUS: USBD_STATUS_SUCCESS (0x00000000) URB Function: URB_FUNCTION_CLASS_INTERFACE (0x001b) IRP information: 0x00, Direction: FDO -> PDO 0000 000. = Reserved: 0x00 .... ...0 = Direction: FDO -> PDO (0x0) URB bus id: 2 Device address: 4 Endpoint: 0x00, Direction: OUT 0... .... = Direction: OUT (0) .... 0000 = Endpoint number: 0 URB transfer type: URB_CONTROL (0x02) Packet Data Length: 16 [Response in: 31357] Control transfer stage: Setup (0) [bInterfaceClass: HID (0x03)] Setup Data bmRequestType: 0x21 0... .... = Direction: Host-to-device .01. .... = Type: Class (0x1) ...0 0001 = Recipient: Interface (0x01) bRequest: SET_REPORT (0x09) wValue: 0x0200 ReportID: 0 ReportType: Output (2) wIndex: 0 wLength: 8 bRequest: 9 wValue: 0x0200 wIndex: 0 (0x0000) wLength: 8 Data Fragment: 5501000000000000
In yellow state, "Switch" gets enabled,
and Upon clicking "switch", it fires off:
Frame 31702: 36 bytes on wire (288 bits), 36 bytes captured (288 bits) on interface wireshark_extcap2440, id 0 USB URB [Source: host] [Destination: 2.4.0] USBPcap pseudoheader length: 28 IRP ID: 0xffff898c81fc6970 IRP USBD_STATUS: USBD_STATUS_SUCCESS (0x00000000) URB Function: URB_FUNCTION_SELECT_CONFIGURATION (0x0000) IRP information: 0x00, Direction: FDO -> PDO 0000 000. = Reserved: 0x00 .... ...0 = Direction: FDO -> PDO (0x0) URB bus id: 2 Device address: 4 Endpoint: 0x00, Direction: OUT 0... .... = Direction: OUT (0) .... 0000 = Endpoint number: 0 URB transfer type: URB_CONTROL (0x02) Packet Data Length: 8 [Response in: 31705] Control transfer stage: Setup (0) Setup Data bmRequestType: 0x00 0... .... = Direction: Host-to-device .00. .... = Type: Standard (0x0) ...0 0000 = Recipient: Device (0x00) bRequest: SET CONFIGURATION (9) bConfigurationValue: 1 wIndex: 0 (0x0000) wLength: 0
So, I guess that is it.