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

windows debug help #719

Closed
ladmanj opened this issue Feb 25, 2025 · 12 comments
Closed

windows debug help #719

ladmanj opened this issue Feb 25, 2025 · 12 comments
Labels
question Information is requested

Comments

@ladmanj
Copy link

ladmanj commented Feb 25, 2025

Hi,
I have super simple program, which is basically nothing but hidapitester with 99% of things removed.
When I run it on Linux

$ ./shoop 
Opening device, vid/pid: 0x0483/0x5750
Writing output report of 5-bytes...wrote 5 bytes:
 73 65 6E 64 00
Closing device

The connected device responds.

When compiled the same way in msys2 and run on Win11 (in qemu/kvm, usb device redirected), unfortunately

$ ./shoop.exe 
Opening device, vid/pid: 0x0483/0x5750
Writing output report of 5-bytes...wrote -1 bytes:
 73 65 6E 64 00
Closing device

and the hardware device doesn't respond ...

I tried run it in gdb but no useful info found, it calls some api and then -1 is returned. I don't know whether the data was sent, but the device did not blink it's LED and the response not come back.

The device behaves like HID keyboard and does the typing when asked for.
https://github.com/ladmanj/shooplera

Thanks for any advice.

@mcuee mcuee added the question Information is requested label Feb 26, 2025
@mcuee
Copy link
Member

mcuee commented Feb 26, 2025

What if you use a real Windows machine and not a VM? All VMs seem to have USB related issues from time to time.

@ladmanj
Copy link
Author

ladmanj commented Feb 26, 2025

Windows10 computer with no VM:

shoop.exe
Opening device, vid/pid: 0x0483/0x5750
Writing output report of 5-bytes...wrote -1 bytes:
 73 65 6E 64 00
Closing device

No luck

@ladmanj
Copy link
Author

ladmanj commented Feb 26, 2025

The same with binary distributed hidapitester

hidapitester.exe --vidpid 0483/5750 --open --len 5 --send-output  0x73,0x65,0x6E,0x64,0x00
Opening device, vid/pid: 0x0483/0x5750
Writing output report of 5-bytes...wrote -1 bytes:
 73 65 6E 64 00
Closing device

@Youw
Copy link
Member

Youw commented Feb 26, 2025

How many devices does hid_enumerate gives you with vid/pid: 0x0483/0x5750 ?
My guess that on Windows you will get more than one, with different usage_page/usage.

@ladmanj
Copy link
Author

ladmanj commented Feb 26, 2025

hidapitester.exe --vidpid 0483/5750 --list-detail
0483/5750: kluhtrust.cz - ShoopLERA
  vendorId:      0x0483
  productId:     0x5750
  usagePage:     0x0001
  usage:         0x0006
  serial_number: 6D7130884971
  interface:     0
  path: \\?\HID#VID_0483&PID_5750#6&11c6a2fc&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}\KBD

@ladmanj
Copy link
Author

ladmanj commented Feb 26, 2025

hid_open (vendor_id=vendor_id@entry=1155, product_id=product_id@entry=22352, serial_number=serial_number@entry=0x0)
    at ../../hidapi/windows/hid.c:939
939             devs = hid_enumerate(vendor_id, product_id);
(gdb) next
940             if (!devs) {
(gdb) print devs
$1 = (struct hid_device_info *) 0x6fdd20
(gdb) print *devs
$2 = {path = 0x6fd2c0 "\\\\?\\HID#VID_0483&PID_5750#6&11c6a2fc&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}\\KBD",
  vendor_id = 1155, product_id = 22352, serial_number = 0x6fe0c0 L"6D7130884971", release_number = 512,
  manufacturer_string = 0x6fd350 L"kluhtrust.cz", product_string = 0x6fd3a0 L"ShoopLERA", usage_page = 1, usage = 6,
  interface_number = 0, next = 0x0, bus_type = HID_API_BUS_USB}
(gdb)

@ladmanj
Copy link
Author

ladmanj commented Feb 26, 2025

hid_write (dev=dev@entry=0x701460, data=data@entry=0x5ffa80 "send", length=length@entry=5) at ../../hidapi/windows/hid.c:1087
1087            if (length >= dev->output_report_length) {
(gdb) print dev->output_report_length
$7 = 2
(gdb) print length
$8 = 5
(gdb) list
1082               expects the number of bytes which are in the _longest_ report (plus
1083               one for the report number) bytes even if the data is a report
1084               which is shorter than that. Windows gives us this value in
1085               caps.OutputReportByteLength. If a user passes in fewer bytes than this,
1086               use cached temporary buffer which is the proper size. */
1087            if (length >= dev->output_report_length) {
1088                    /* The user passed the right number of bytes. Use the buffer as-is. */
1089                    buf = (unsigned char *) data;
1090            } else {
1091                    if (dev->write_buf == NULL) {
(gdb) next
1106            res = WriteFile(dev->device_handle, buf, (DWORD) length, &bytes_written, &dev->write_ol);
(gdb) print dev->device_handle
$9 = (HANDLE) 0xb8
(gdb) print *dev->device_handle
Attempt to dereference a generic pointer.
(gdb) next
1108            if (!res) {
(gdb) print bytes_written
$10 = 0
(gdb) print dev->
blocking               feature_buf            last_error_str         read_buf               write_ol
device_handle          feature_report_length  ol                     read_pending           write_timeout_ms
device_info            input_report_length    output_report_length   write_buf
(gdb) print dev->write_ol
$11 = {Internal = 259, InternalHigh = 0, {{Offset = 0, OffsetHigh = 0}, Pointer = 0x0}, hEvent = 0xc0}
(gdb) print length
$12 = 5
(gdb) print buf
$13 = (unsigned char *) 0x5ffa80 "send"
(gdb) print res
$14 = 0
(gdb) next
1109                    if (GetLastError() != ERROR_IO_PENDING) {
(gdb)
1111                            register_winapi_error(dev, L"WriteFile");
(gdb)
1112                            goto end_of_function;
(gdb)
1120            if (overlapped) {
(gdb) list
1115            } else {
1116                    /* WriteFile() succeeded synchronously. */
1117                    function_result = bytes_written;
1118            }
1119
1120            if (overlapped) {
1121                    /* Wait for the transaction to complete. This makes
1122                       hid_write() synchronous. */
1123                    res = WaitForSingleObject(dev->write_ol.hEvent, dev->write_timeout_ms);
1124                    if (res != WAIT_OBJECT_0) {
(gdb) next
main (argc=<optimized out>, argv=0x6f7ed0) at D:/msys64/home/ladmanj/shooplera/shoop/shoop.c:114
114                     msg("wrote %d bytes:\n", res);
(gdb) print res
$15 = -1

@ladmanj
Copy link
Author

ladmanj commented Feb 26, 2025

I found this note:
"Windows protects keyboards (and mice) so user applications cannot access them like other HID devices.
Keyboard LEDs can be set via the SetKeyboardState API, but this will affect all attached keyboards."

If this is true, my attempt to make it Windows-compatible is doomed to fail.

@Youw
Copy link
Member

Youw commented Feb 26, 2025

Yeah, Keyboards and Mouses are to be accessed only by native OS API on Windows and macOS.
That's a part of general security, otherwisse any app would be able to sniff what you type (passwords, messages, etc.).

@Youw Youw closed this as not planned Won't fix, can't repro, duplicate, stale Feb 26, 2025
@ladmanj
Copy link
Author

ladmanj commented Feb 26, 2025

How to do it if the keyboard is my own keyboard that I've built myself and want to use it personaly on my own pc?

Any workaround worth of recommendation?

J.

@Youw
Copy link
Member

Youw commented Feb 26, 2025

It is impossible to do both: use it as a Keyboard (to be recognized by Windows as a keyboard) and access with HIDAPI - not if it is the same device.

You may have a few logical devices (at least different usage_page/usage with its own custom set of reports, or even different USB endpoints), and one of them is a Keyboard and accessible by the OS, and the other one is for your custom logic.

@ladmanj
Copy link
Author

ladmanj commented Feb 27, 2025

I tried yesterday to add a second usage-page/usage and bricked my device :-) It is no longer accepted by Linux, and I prepared no other way to switch it to a bootloader than with an HID report packet.
I must open it again and connect the debug probe.
Unfortunately, I don't know how to add the second usage page properly; these problems only exist because Windows does what it does.

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

No branches or pull requests

3 participants