dmitrystu / libusb_stm32

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

hid descriptor request lost #32

Closed maor1993 closed 5 years ago

maor1993 commented 5 years ago

Hey, I've been trying to implement an HID demo. used an hid example from lufa as the descriptor values and cross compared the code they we're using with your implantation.

I will note that CDC loopback works well, so does modding it to become a debug print path.

I'm running on the stm32f042 nucleo.

long story short: The computer gets the device descriptor, but gets no reply from HID Report request.

looking at wireshark the computer sends it as GET DESCRIPTOR HID REPORT (0x22) image

but when I place a breakpoint on the point where it should receive it, nothing gets through, meaning the callback is not triggered.

here is a link to the repo: https://github.com/maor1993/StamDevPlayGround/blob/master/stam/Src/usbhid.c

Any tests I should do to find out why? Thanks, Maor.

dmitrystu commented 5 years ago

Well, it happens because it's an request to the interface, not to the device. It can be handled in your hid_control subroutine. So, it this implementation of the usbd core get_descriptor callback works only with requests to the device. Looks like a bug, and code must be revised.

dmitrystu commented 5 years ago

There is no standard GET_DESCRIPTOR request on interface level. It can be added to the core but i'm afraid of the side-effects.

maor1993 commented 5 years ago

Would it be possible to add a callback for interface requests as well? it seems this is the only way to support HID devices.

microwavesafe commented 5 years ago

I use this in the callback for HID devices

usbd_respond
usbd__control(usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback)
{
    // class request
    if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == (USB_REQ_INTERFACE | USB_REQ_CLASS)) {
        switch (req->bRequest) {
            case USB_HID_SETPROTOCOL:
                usbd_hid__.protocol = (uint8_t)(req->wValue);
                return usbd_ack;

            case USB_HID_GETPROTOCOL:
                dev->status.data_ptr = (uint8_t*)&usbd_hid__.protocol;
                dev->status.data_count = sizeof(usbd_hid__.protocol);
                return usbd_ack;

            case USB_HID_SETIDLE:
                usbd_hid__.idle = (uint8_t)(req->wValue >> 8);
                return usbd_ack;

            case USB_HID_GETIDLE:
                dev->status.data_ptr = (uint8_t*)&usbd_hid__.idle;
                dev->status.data_count = sizeof(usbd_hid__.idle);
                return usbd_ack;

            default:
                return usbd_fail;
        }
    }
    // standard request
    else if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) == (USB_REQ_INTERFACE | USB_REQ_STANDARD)) {
        switch (req->wValue >> 8) {
            case USB_DTYPE_HID_REPORT:
               dev->status.data_ptr = (uint8_t*)usb_hid_report_descriptor;
               dev->status.data_count = sizeof(usb_hid_report_descriptor);
               return usbd_ack;;

         default:
             return usbd_fail;
        }
    }

    return usbd_fail;
}
maor1993 commented 5 years ago

Hey, @microwavesafe works perfect. @dmitrystu , I suggest you add an HID example, perhaps using what microwavesafe did.

closing this issue.