usb_write fails to write to endpoint buffer in old device stack #104538
Replies: 6 comments 1 reply
-
|
Hi @temportalflux! We appreciate you submitting your first issue for our open-source project. 🌟 Even though I'm a bot, I can assure you that the whole community is genuinely grateful for your time and effort. 🤖💙 |
Beta Was this translation helpful? Give feedback.
-
|
This is also reported as a bug to zmk_raw_hid, but I suspect zephyr folks will be more knowledgable on how to diagnose and fix this issue, even if its a configuration issue / implementation issue in zmk. zzeneg/zmk-raw-hid#3 |
Beta Was this translation helpful? Give feedback.
-
In USB, a device cannot just write to the host. The function name usb_write() is just wrong. Simplified, usb_write() calls usb_dc_ep_write(), which writes to an endpoint FIFO or sets up some endpoint hardware magic to use the buffer. All the communication is ruled by the host. A host application needs to request a transfer. The host controller will issue an IN token, and if an endpoint is ready, it will send a data packet to the host. It looks like your host application does not read anything, and because the previous write is not finished, you see EAGAIN. Also, something like https://github.com/zzeneg/zmk-raw-hid/blob/a01b1317e7c800ed879b1015702dcb1f6870ff8a/src/usb_hid.c#L49-L50 static void send_report(const uint8_t *data, uint8_t len) {
k_sem_take(&hid_sem, K_MSEC(30));
LOG_INF("USB - Sending Raw HID report of length %i", len);
uint8_t report[CONFIG_RAW_HID_REPORT_SIZE] = {0};is not really helpful and actually is a bug. When the host application does not start any transfers, or for example the polling period of the endpoint is high enough, No idea what is your host application, you can use something like pyusb to quickly check how your firmware behaves. It is not a Zephyr bug. I will move it to a discussion. Not sure I will find time to answer there, then you can try to ping me from discord about this topic. Good luck. |
Beta Was this translation helpful? Give feedback.
-
|
I suppose then the place to start will be to try and identify the vendor and product id of my firmware usb device and then tinker with pyusb log for personal reference |
Beta Was this translation helpful? Give feedback.
-
|
Some findings/tinkerings from today: Trying out pyusb, I've managed to identify my device, but am having trouble requesting a report from it. pyusb script import usb
device = usb.core.find(idVendor=0x1d50, idProduct=0x615e)
if device is None:
raise ValueError('Device not found')
print(device)
print(f"Found product \"{device.product}\" manufactured by \"{device.manufacturer}\". SerialNum={device.serial_number} Vendor=0x{device.idVendor:02X} Product=0x{device.idProduct:02X}")
def find_endpoint(dev, attr, dir):
for cfg in dev:
for interface in cfg:
for endpoint in interface:
if endpoint.bmAttributes != attr:
continue
if usb.util.endpoint_direction(endpoint.bEndpointAddress) != dir:
continue
return endpoint
return None
def hid_get_report(dev):
""" Implements HID GetReport via USB control transfer """
# https://stackoverflow.com/a/52368526
# https://drive.google.com/file/d/1UNdKyFdqy40eBSC_B22MlU2DdZ_kE6bG/view
return dev.ctrl_transfer(
usb.util.CTRL_TYPE_CLASS | usb.util.CTRL_RECIPIENT_INTERFACE | usb.util.CTRL_IN,
1, # GET_REPORT
# GET_REPORT:Value = Report Type & Report ID
0x200,
0, # GET_REPORT:Index = the interface
64 # GET_REPORT:Length = number of bytes / max reply size
)
endpoint = find_endpoint(device, usb.util.ENDPOINT_TYPE_BULK, usb.util.ENDPOINT_IN)
if endpoint is None:
raise ValueError('Failed to find BULK IN endpoint')
#print(endpoint)
result = hid_get_report(device)
print(result)Device Log |
Beta Was this translation helpful? Give feedback.
-
|
meanwhile, some comments online point to the python library hidapi script import hidapi
vendor_id = 0x1d50
product_id = 0x615e
for info in hidapi.enumerate(vendor_id, product_id):
print(f"Path:{info.path} Id:0x{info.vendor_id:02X}:0x{info.product_id:02X} Product:{info.product_string} Manufacturer:{info.manufacturer_string} Serial:{info.serial_number} Interface:{info.interface_number}")
device = hidapi.Device(vendor_id=vendor_id, product_id=product_id)
report = device.read(64, 0, True)
print(report)
device.close()log |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Describe the bug
I'm using a nice!nano aurora sweep keyboard, and using ZMK to compile the firmware for it. I'm trying to send some custom HID data from my firmware to the USB device interface on my computer, so I can write a custom software to listen to that data and update state. This data will describe the physical switches on my keyboard and the layers which are active, instead of trying to infer which switches are pressed from standard keyboard scancodes.
To achieve this, I'm using zmk-raw-hid to send some data via zephyr call
hid_int_ep_write. ZMK is currently constrained to the old device stack (not device_next). I've traced the stack via github repos + search.zmk_raw_hid calls
hid_int_ep_writeinsend_report->
hid_int_ep_write->
usb_device.cusb_writemy custom module code:
the output (as described below) repeatedly tries to write to the endpoint buffer, and fails. Its unclear to me why its failing, the error message simply returns with an error code of 11, which seems to be driven by the error defined for
EAGAIN. Its unclear why its failing to write to the endpoint buffer, or what can be done to fix that behavior.Various CDC_ACM config flags have been tried, including
CONFIG_USB_CDC_ACM=y,CONFIG_USBD_CDC_ACM=y, andCONFIG_USBD_CDC_ACM_CLASS=y.Regression
Steps to reproduce
No response
Relevant log output
Impact
Functional Limitation – Some features not working as expected, but system usable.
Environment
Additional Context
ZMK folks have communicated that ZMK will be unable to upgrade to zephyr's new device stack for a little while yet (until sometime after v0.4 release). So upgrading to the new device stack is not available to me in the immediate future.
I'd love assistance understanding this bug and if there is any way to debug or fix this to a reasonable degree. Zephyr support via discord has expressed strong advice to not bother debugging the old stack, but thats not a reasonable option for me at this time.
Beta Was this translation helpful? Give feedback.
All reactions