← index #6953Issue #1217
Related · high · value 0.591
QUERY · ISSUE

stm32 HID class USB crash explained

openby doc-hexopened 2021-02-23updated 2024-09-13

Problem: If you call pyb.USB_HID().recv(...) before the USB device is enumerated by the host, a null pointer is dereferenced and hard fault results immediately.

This happens because the HID interface object is not initialized: usb_device.usbd_cdc_msc_hid_state.hid and in particular usb_device.usbd_cdc_msc_hid_state.hid.usbd are zeros.

The init should happen:

  • when the device is enumerated (SetConfig chapter 9 code) in USBD_SetClassConfig
  • calls USBD_CDC_MSC_HID_Init which calls usbd_cdc_state_init
  • I could not find any other paths that might initialize the usbd field in particular; the other fields are also wrong, such as defaulting to dev_speed == USBD_SPEED_HIGH even on my board which can't do high speed, because USBD_SPEED_HIGH is zero.

The null de-ref happens inside USBD_HID_ReceivePacket(&hid->base...) when called by usbd_hid_rx() and it only gets that far (thinking that zero bytes have been received already) because it looks at the un-initialized usbd_hid_itf_t *hid and sees zero for hid->report_in_len rather than USBD_HID_REPORT_INVALID which would be more appropriate in this state.

My workaround, on ports/stm32/usbd_hid_interface.c:

--- a/ports/stm32/usbd_hid_interface.c
+++ b/ports/stm32/usbd_hid_interface.c
@@ -49,7 +49,7 @@ int8_t usbd_hid_receive(usbd_hid_state_t *hid_in, size_t len) {
 int usbd_hid_rx(usbd_hid_itf_t *hid, size_t len, uint8_t *buf, uint32_t timeout_ms) {
     // Wait for an incoming report
     uint32_t t0 = mp_hal_ticks_ms();
-    while (hid->report_in_len == USBD_HID_REPORT_INVALID) {
+    while (hid->report_in_len == USBD_HID_REPORT_INVALID || !hid->base.usbd) {
         if (mp_hal_ticks_ms() - t0 >= timeout_ms || query_irq() == IRQ_STATE_DISABLED) {
             return -MP_ETIMEDOUT;
         }
@@ -62,6 +62,7 @@ int usbd_hid_rx(usbd_hid_itf_t *hid, size_t len, uint8_t *buf, uint32_t timeout_
 
     // Schedule to receive next incoming report
     hid->report_in_len = USBD_HID_REPORT_INVALID;
+    assert(hid->base.usbd);
     USBD_HID_ReceivePacket(&hid->base, &hid->report_in_buf[0]);

I can't explain why this bug isn't seen more often, but I think what was covering it for me was that pyb_usb_dev_init() gets called after the end of boot.py and so was defaulting to VCP+HID+MSC but I've recently changed things so that USB doesn't get enabled until sometime much later in main.py (ie. I called pyb.usb_mode(None) in boot.py) and that initialized the composite USB device as "VCP+HID". I suspect something in the code path for the MSC setup initializes the HID interface state before enumeration, but I can't confirm that.

CANDIDATE · ISSUE

USB HID Receive on Micro Python

closedby 452opened 2015-05-04updated 2016-10-04
port-stm32

How to receive HID data in my stm32F4Discovery board with Micro Python?
please can you provide some Docs link or example with receiving and callback (onReceive)?

pyb.usb_mode("VCP+HID", pid=0x1234, hid=(0, 0, report_len, 50, hid_desc))

when I double pressed tab button I have only one function:

pyb.USB_HID.send

receiving data from host device like PC or tablet not implemented yet on stm32F4Discovery board?

#work good
i=0
while True:
    pyb.USB_HID.send(0,"{} Yet another long text".format(i))
    pyb.delay(100)
    i+=1

I develop https://play.google.com/store/apps/details?id=com.appspot.usbhidterminal

about board and Micro Python version info, how to get it(with sudo screen /dev/ttyACM0 I have no info, only blank screen, after hit enter, I see:

AT

Traceback (most recent call last):
  File "<stdin>", line 1
SyntaxError: invalid syntax
>>> 
>>> 9+8
17
>>> 
PYB: sync filesystems #PRESSED CRTL+D
PYB: soft reboot
Traceback (most recent call last):
  File "main.py", line 9, in <module>
KeyboardInterrupt: #PRESSED CRTL+C
Micro Python v1.4.2-55-g2378be4 on 2015-05-03; F4DISC with STM32F407
Type "help()" for more information.
>>> 
ihor@ihor-M50Vc:~$ sudo picocom /dev/ttyACM0
picocom v1.7

port is        : /dev/ttyACM0
flowcontrol    : none
baudrate is    : 9600
parity is      : none
databits are   : 8
escape is      : C-a
local echo is  : no
noinit is      : no
noreset is     : no
nolock is      : no
send_cmd is    : sz -vv
receive_cmd is : rz -vv
imap is        : 
omap is        : 
emap is        : crcrlf,delbs,

Terminal ready
~x~ # PRESSED Enter
Traceback (most recent call last):
  File "<stdin>", line 1
SyntaxError: invalid syntax
>>> 

, and then command prompt >>>)?
please add pyb.version(), and help() support with:
(about version, number of version integer value, full info - text)

Micro Python v1.4.2-55-g2378be4 on 2015-05-03; F4DISC with STM32F407
Type "help()" for more information.

and Thank you, Micro Python is awesome, good one =), I did not like Python, but now my view is changing =)

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied