dmitrystu / libusb_stm32

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

What's USBD_DP_PORT and USBD_DP_PIN for? #15

Closed cnnblike closed 6 years ago

cnnblike commented 6 years ago

I was going through the whole project with Doxygen. A few questions:

  1. What's USBD_DP_PORT and USBD_DP_PIN for? find it somewhere, but the comment is kinda confusing. Is it used to enable the external pull up resistor?
  2. If I'm not making mistake. usbd_poll() is used to process all event from USB, right? usbd_reg_config to register the config & deconfig process; usbd_reg_control to register the control part of USB device; usbd_reg_descr to register all the descriptor may be used. So if I'm going to implement an user-defined HID device, then I need to a. write a config process (which may just be just like modifying some lines in cdc_setconf, adding all endpoints I need, all callback for each endpoint) b. write all the descriptor I may need and register them. c. implement all request SET PROTOCOL, GET PROTOCOL, GET IDLE, SET IDLE, SET REPORT, GET REPORTin the callback registered in the usbd_reg_control. (ref: https://www.keil.com/pack/doc/mw/USB/html/_h_i_d.html) My problem is, what should we do in SET REPORT and GET REPORT? In the custom hid of stm32 HAL USB, they need to call hhid-> IsReportAvailable =1 and USBD_CtlPrepareRx, do libusb_stm32 need to do some similar thing like that?
dmitrystu commented 6 years ago

Hi

  1. USBD_DP_PORT and USBD_DP_PIN defines GPIO port and pin for USB DP pullup resistor for F103/F303 devices that does not have internal controlled 1k5 pullup resistor for soft connect/disconnect. These parameters have effect only for F103/F303. If you using fixed DP pullup (like in bluepill boards) just don't define these parameters.
  2. usbd_poll() subroutine is a main entry point for usb core. You can put this call both into main loop or into USB interrupt. This subroutine produces events callbacks to user code and do some service stuff like bus reset handling. The usbd_reg_control() registers callback for all control requests, Core will process standard device requests if no callback registered or usbd_fail code returned from callback. The usbd_reg_config registers callback for SET_CONFIG/GET_CONFIG control requests. The usbd_reg_descr registers callback for GET_DESCRIPTOR control request.

There is no class helpers implemented. So, if you want to handle cllass specifiic SET_REPORT and GET_REPORT control requests you must write control callback that handle these requests.

/* UNTESTED !!! Just a sample !!!*/
usbd_respond hid_control(usbd_device *dev, usbd_ctlreq *req, usbd_rqc_callback *callback) {
    /* checking if this is a interface and class request */
    /* for complex devices you can also check req->wIndex and req->wValue */
    if (((USB_REQ_RECIPIENT | USB_REQ_TYPE) & req->bmRequestType) != (USB_REQ_INTERFACE | USB_REQ_CLASS)) return usbd_fail;
    switch (req->bRequest) {
    case USB_HID_GETREPORT:
        /* handle GET_GEPORT control request here.
         * dev->status.dataptr points to data buffer for data (req->data by default). You can set this pointer to your data or copy your data to this buffer.
         * dev->status.datacount contains maximum data length in bytes. Adjust this value to your data size */
        return usbd_ack; /* if request accepted and you have a data to transmit, usbd_fail otherwise */
    case USB_HID_SETREPORT:
       /* handle SET_REPORT control request here
        * req->data points to request's data passed from host (w/o request header)
        * req->wLength contains data size */
        return usbd_ack; /* if request accepted, usbd_fail otherwise */
    /* You can add more class specific requests here */
    default:
        return usbd_fail;
    }
}

Check the cdc_loop demo for workflow with class specific requests.

cnnblike commented 6 years ago

Thank you for your detailed explanation, I will try to build a hid device accordingly.

cnnblike commented 6 years ago

@dmitrystu

It seems like that the HID Report Descriptor seems can never fill in a pre-defined type, so I simply make my own type definition for that, but what's usb_hid_report_descriptor designed for?

~And why is INTSERIALNO_DESCRIPTOR defined as 0xFE? Do you actually mean the INTSERIALNO_DESCRIPTOR should be a string descriptor generated from the uuid of STM32?~ update just figure it out, it's inside usbd_stm32f103_devfs.c

cnnblike commented 6 years ago

update: just found the request to interface doesn't have a callback in the library- which should be handled in usbd_process_intrq and will help a lot for a composite usb device. Do you need a pull request for that? or maybe we should just handle that inside control_callback?