Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set Feature Report data last byte corrupted #72

Open
Hal9000Space opened this issue Jul 16, 2021 · 4 comments
Open

Set Feature Report data last byte corrupted #72

Hal9000Space opened this issue Jul 16, 2021 · 4 comments

Comments

@Hal9000Space
Copy link

Hi,

First of all allow me to say thanks for maintaining this repository. It saves me a ton of work!

On Linux I use the usb library (import usb) along with the controlMsg() method for the device to send data, and this works for the particular device. On Windows 10 I'm importing the pywinusb.hid library and trying to send the same type of data. My first attempt was to use the set_raw_data() and send() methods of a feature report to send data to a device, as I did not know if there was a controlMsg() equivalent function in pywinusb. I see the data on the USB bus with my analyzer, but the last byte of the given transaction is always set to zero (0x00). The buffer for this feature report (0xE4) is 263 bytes long, which represents 256 bytes of data plus a 7 byte header.

How can I send the 263 byte data buffer without corruption? Is there another method I should be using?

Thank you.

Here is one transaction worth of data, the last byte should not be zero.

000: E4 00 00 00 00 00 01 59 00 A6 4B 09 BC 16 D3 DB 
016: E4 5D E5 DC E2 36 E3 01 28 42 99 03 43 91 05 D4 
032: C4 BC 1F D3 BC 2D D3 E4 00 E2 40 E3 C0 14 E1 00 
048: 52 72 11 0B 73 28 D2 04 E1 40 14 79 91 EB 28 C8 
064: C2 F0 C8 C1 F0 E0 07 C8 C0 F0 E0 80 C8 C2 F0 E4 
080: 12 BF 73 1D E1 01 79 98 01 B9 E1 50 E8 E0 F0 19 
096: C8 E0 F0 E1 05 E8 E1 F0 19 C8 E1 F0 E8 E0 F0 19 
112: C8 E0 F0 E8 08 FC E1 08 19 C8 08 FC E8 09 FC E1 
128: 00 19 C8 09 FC E8 0A FC C8 0A FC E8 0B FC C8 0B 
144: FC E8 58 FC E1 F9 21 C8 58 FC E8 59 FC E1 FF 21 
160: C8 59 FC E8 5A FC 21 C8 5A FC E8 5B FC 21 C8 5B 
176: FC E8 58 FC C8 58 FC E8 59 FC C8 59 FC E8 5A FC 
192: C8 5A FC E8 5B FC C8 5B FC E0 70 C8 6C FC E0 AD 
208: C8 6D FC 28 C8 6E FC C8 6F FC E1 01 E8 50 FC 19 
224: C8 50 FC E8 51 FC 19 C8 51 FC E0 D0 C8 08 FF E0 
240: 39 C8 09 FF 28 C8 0A FF C8 0B FF E8 F8 FE E1 F9 
256: 21 C8 F8 FE E8 F9 00  // <- this byte is corrupted

Here is a snippet of my Python code. The 'size' parameter from the hid caps does match the buffer size (263) in the case.

import pywinusb.hid as hid

# device open code not shown...

    def SetFeature(self, buffer):
        """Executes a set feature request to the device."""
        assert(self.IsOpen())
        
        size = self._hDevice.hid_caps.feature_report_byte_length
        for i in range(len(buffer), size):
            buffer.append(0)

        success = 0

        for report in self._hDevice.find_feature_reports():
            if report.report_id == buffer[0]:
                # found our feature report
                report.set_raw_data(buffer)
                report.send()
                success += 1
                break

        if success:
            return True
        else:
            return False
@Hal9000Space
Copy link
Author

Well I just answered by own question! I looked through the public methods in this repository and I saw the send_feature_report() method and tried it out. This is doing what I want. Some times we just need to summarize our question in writing and then we can answer our own question. Still curious what was wrong with my set_raw_data() example, but I'm not stuck on this anymore.

@mcuee
Copy link

mcuee commented Aug 12, 2021

Set your buffer to be one bytes more (for the report ID).

https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/hidsdi/nf-hidsdi-hidd_setfeature

BOOLEAN HidD_SetFeature(
  HANDLE HidDeviceObject,
  PVOID  ReportBuffer,
  ULONG  ReportBufferLength
);

ReportBufferLength
[in] Specifies the size, in bytes, of the report buffer. The report buffer must be large 
enough to hold the feature report -- excluding its report ID, if report IDs are used 
-- plus one additional byte that specifies a nonzero report ID or zero.

@rene-aguirre
Copy link
Owner

This is a current design limitation, currently, the HID class doesn't keep an internal feature type so find_feature_reports just returns a generic report, hence, send assumes the default output report.

I think your example code makes sense, it should be supported.

@mcuee
Copy link

mcuee commented Aug 13, 2021

This is a current design limitation, currently, the HID class doesn't keep an internal feature type so find_feature_reports just returns a generic report, hence, send assumes the default output report.

Interesting. Looking at the codes it does seem to differentiate feature report with output report, but maybe I am wrong.
https://github.com/rene-aguirre/pywinusb/blob/master/pywinusb/hid/core.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants