Determining Device Write Type
Once you know your device’s protocol type, you may still need to determine which specific write function to use. HID devices in particular have two different write methods that target different USB transfer mechanisms.
device.write
Section titled “device.write”device.write() sends data using a bulk or interrupt transfer on the device’s currently selected HID endpoint. This is the standard write path and works for the majority of devices.
Use device.write() when:
- The device sends and receives fixed-length reports via interrupt transfer
- The Wireshark capture shows URB_INTERRUPT transfers
- The device does not use a HID Report ID on the selected endpoint (requiring zero padding — see below)
var packet = [];packet[0] = 0xEC;packet[1] = 0x40;packet[2] = channel;packet = packet.concat(RGBData);
device.write(packet, 65);device.send_report
Section titled “device.send_report”device.send_report() sends data using a HID SET_REPORT control transfer. This targets the HID feature report mechanism rather than the interrupt endpoint.
Use device.send_report() when:
- The Wireshark capture shows URB_CONTROL transfers with a SET_REPORT request (request code
0x09) device.write()returns an “incorrect function” error on all endpoints- The device explicitly uses HID Feature reports for its command interface
device.send_report([0x07, 0x03, 0x06, 0x01, 0x00], 65);The companion read function for feature reports is device.get_report(), which issues a GET_REPORT control transfer. Use it when you need to read back configuration via the same feature report mechanism.
Which One to Try First
Section titled “Which One to Try First”If you’re not sure, start with device.write(). It works for the majority of HID devices. If you get an “incorrect function” error, switch to device.send_report(). If both fail, verify you have the correct endpoint selected.
| Symptom | Try |
|---|---|
| Works as expected | You’re done |
| ”Incorrect function” error | Switch to device.send_report() |
| ”Access is denied” error | Wrong endpoint — see Selecting Endpoints |
| No error, but device doesn’t respond | Wrong endpoint, or wrong device type |
Zero Padding
Section titled “Zero Padding”Some HID devices require the first byte of every packet to be 0x00. This happens when the device has no Report ID assigned to the selected endpoint — the HID driver strips byte 0 before passing the data to the device, so you need to push everything over by one position to compensate.
Signs you need zero padding:
- The Wireshark capture shows the first meaningful command byte at offset 1, not offset 0
- Without the zero byte, the device ignores the packet or produces garbage output
How to apply it:
// Without zero padding (packet size 64)packet[0] = 0xEC; // commandpacket[1] = 0x40;device.write(packet, 64);
// With zero padding (packet size 65)packet[0] = 0x00; // padding byte — consumed by HID driverpacket[1] = 0xEC; // command now at offset 1packet[2] = 0x40;device.write(packet, 65);The rule of thumb: if your Wireshark capture shows a 64-byte packet but device.write(packet, 64) doesn’t work, try device.write(packet, 65) with packet[0] = 0x00 and all other bytes shifted up by one.
Reading Data Back
Section titled “Reading Data Back”The read-side equivalents follow the same split:
| Write method | Matching read method | Transfer type |
|---|---|---|
device.write() | device.read() | Bulk / Interrupt |
device.send_report() | device.get_report() | Control (GET_REPORT) |
For reading input reports specifically (not feature reports), use device.input_report(). See Advanced Communication for details.