dmitrystu / libusb_stm32

Lightweight USB device Stack for STM32 microcontrollers
Apache License 2.0
721 stars 165 forks source link

Get data for USB HID Keyboard's LED via Class Request 0x09 (Set Report)? #95

Closed GrantMTG closed 3 years ago

GrantMTG commented 3 years ago

This is a standard feature of HID Keyboards, they receive the LED information (Caps Lock, etc) via a SETUP then a one-byte EP0 OUT data packet. The setup looks normally like this:

21 09 00 02 00 00 01 00

I can set the usbd_process_eprx() function to receive the data (1 byte) using the following, but I don't know the correct way to direct that byte to my own buffer. Alternatively I would need notification or a callback to get it out of the default(?) one. This code currently resides in cdc_control() in the demo and is similar to https://github.com/dmitrystu/libusb_stm32/issues/32#issuecomment-453434318.

if((req->bmRequestType & (USB_REQ_TYPE|USB_REQ_RECIPIENT)) == (USB_REQ_CLASS|USB_REQ_INTERFACE))
   {
   switch(req->bRequest)
      {
      case USB_HID_SETREPORT:          // 0x09
           ReportType = req->wValue >> 8;         // 2=Output report, 3=Feature report
           ReportID   = req->wValue &0xFF;
           // Configure the data stage:
           dev->status.control_state = usbd_ctl_rxdata;
           dev->status.data_count = 1;
// Not sure how to get the results from the data stage afterward...
//           dev->status.data_buf = &HidKbLEDs;
//           dev->status.data_ptr = &HidKbLEDs; 
           return usbd_ack;                       // We are expecting an OUT data stage with the info...

How can I get the data and/or be notified that is has been received?

GrantMTG commented 3 years ago

image

GrantMTG commented 3 years ago

Curiously the data stage is already handled before

static usbd_respond cdc_control(usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback)

is even called! I did not expect that. So, my code is much simpler even:

if((req->bmRequestType & (USB_REQ_TYPE|USB_REQ_RECIPIENT)) == (USB_REQ_CLASS|USB_REQ_INTERFACE))
   {
   switch(req->bRequest)
      {
      case USB_HID_SETREPORT:          // 0x09
           ReportType = req->wValue >> 8;         // 2=Output report, 3=Feature report
           ReportID   = req->wValue &0xFF;
           // ToDo: check the above two values first...
           HidKbLEDs = ((uint8_t *)dev->status.data_ptr)[0];
           return usbd_ack; 

Let me know if this is indeed correct.

dmitrystu commented 3 years ago

Hi Yes, that's correct. Main logic