This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

USB with RL-USB

Hy, i'm starting to program on stm32f407 and I have some problem using USB.

I manage to make simple application with wizard.
But now, i want to make for example an HID Application with more than one endpoint.
For example, i want ARM to send data to PC as a keyboard and mouse.

How can i make multiple endpoint and more complex HID report descriptor.

I use keil 4.54 and rl-arm library.

Thanks for your help.
I found help and manual not clear on this point.

Parents
  • You can override USB all of the USB descriptors, the ones that are created automatically are enabling users to simply create all of the necessary descriptors without knowing details on how they have to look and how they are assembled but all can be overridden from user side you simply need to provide arrays with same name as ones that are automatically created by the usb_lib.c file.

    usb_lib.c file can be found in ..\ARM\RV31\INC folder and at the end of the file there are all of these arrays assembled, you can see the names that you need to override (for example for overriding the Device Descriptor you need to provide custom array "const U8
    USBD_DeviceDescriptor[]" and USB stack will use that array instead of the one assembled by usb_lib.c

    Bigger problem is that you have to handle all of data on the endpoints manually, otherwise Keil's USB stack has class handling routines for supported classes handling which enable users easier usage of supported classes without having to analyze all communication on the endpoints manually.

Reply
  • You can override USB all of the USB descriptors, the ones that are created automatically are enabling users to simply create all of the necessary descriptors without knowing details on how they have to look and how they are assembled but all can be overridden from user side you simply need to provide arrays with same name as ones that are automatically created by the usb_lib.c file.

    usb_lib.c file can be found in ..\ARM\RV31\INC folder and at the end of the file there are all of these arrays assembled, you can see the names that you need to override (for example for overriding the Device Descriptor you need to provide custom array "const U8
    USBD_DeviceDescriptor[]" and USB stack will use that array instead of the one assembled by usb_lib.c

    Bigger problem is that you have to handle all of data on the endpoints manually, otherwise Keil's USB stack has class handling routines for supported classes handling which enable users easier usage of supported classes without having to analyze all communication on the endpoints manually.

Children
  • Ah, thanks.
    I wasn't aware that usb_config.c includes usb_lib.c

    As of override of standard/class request handlers, maybe these routines are callbacks for this purpose.

    \Keil\ARM\RV31\INC\usb_lib.c
    
    #if    (USBD_HID_ENABLE)
      ...
    #else
      BOOL USBD_ReqGetDescriptor_HID          (U8 **pD, U32 *len) { return (__FALSE); }
      BOOL USBD_EndPoint0_Setup_HID_ReqToIF   (void)              { return (__FALSE); }
      BOOL USBD_EndPoint0_Out_HID_ReqToIF     (void)              { return (__FALSE); }
    #endif  /* (USBD_HID_ENABLE) */
    

    To write custom handlers using these callbacks, this SETUP data should be required.

    \Keil\ARM\RL\USB\INC\usb_def.h
    
    /* USB Default Control Pipe Setup Packet */
    typedef __packed struct _USB_SETUP_PACKET {
      REQUEST_TYPE bmRequestType;           /* bmRequestType */
      U8  bRequest;                         /* bRequest */
      __packed union {
        U16        wValue;                  /* wValue */
        __packed struct {
          U8         wValueL;
          U8         wValueH;
        };
      };
      __packed union {
        U16        wIndex;                  /* wIndex */
        __packed struct {
          U8         wIndexL;
          U8         wIndexH;
        };
      };
      U16          wLength;                 /* wLength */
    } USB_SETUP_PACKET;
    
    \Keil\ARM\RL\USB\INC\usbd_core.h
    
    extern USB_SETUP_PACKET USBD_SetupPacket;
    

    Tsuneo

  • Thanks for this answer.

    So I create a nex .h file to declare my own descriptor.
    Where do i include this file ?

    Maybe, you have a link for example ?

    Thank you in advance.

  • You should specify these arrays in a .c file that you should add to your project and it should automatically replace other arrays as they are defined as __weak

  • To make keyboard + mouse HID device,
    multi-TLC (Top-Level Collection) is much easier than HID + HID composite device.
    Just replacing the report descriptor to this one, you'll get keyboard + mouse HID device

    You may apply RL-USB APIs without any change.
    For example, usbd_hid_get_report() is called with rid (Report ID) = 1 for keyboard, rid = 2 for mouse.

    const U8 USBD_HID_ReportDescriptor[] = {
    
        // Keyboard Top-Level Collection (TLC)
        0x85, 0x01,                    // REPORT_ID (1)
    
        0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
        0x09, 0x06,                    // USAGE (Keyboard)
        0xa1, 0x01,                    // COLLECTION (Application)
        0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
        0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)
        0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)
        0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
        0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
        0x75, 0x01,                    //   REPORT_SIZE (1)
        0x95, 0x08,                    //   REPORT_COUNT (8)
        0x81, 0x02,                    //   INPUT (Data,Var,Abs)
        0x95, 0x01,                    //   REPORT_COUNT (1)
        0x75, 0x08,                    //   REPORT_SIZE (8)
        0x81, 0x03,                    //   INPUT (Cnst,Var,Abs)
        0x95, 0x05,                    //   REPORT_COUNT (5)
        0x75, 0x01,                    //   REPORT_SIZE (1)
        0x05, 0x08,                    //   USAGE_PAGE (LEDs)
        0x19, 0x01,                    //   USAGE_MINIMUM (Num Lock)
        0x29, 0x05,                    //   USAGE_MAXIMUM (Kana)
        0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)
        0x95, 0x01,                    //   REPORT_COUNT (1)
        0x75, 0x03,                    //   REPORT_SIZE (3)
        0x91, 0x03,                    //   OUTPUT (Cnst,Var,Abs)
        0x95, 0x06,                    //   REPORT_COUNT (6)
        0x75, 0x08,                    //   REPORT_SIZE (8)
        0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
        0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)
        0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
        0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))
        0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)
        0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
        0xc0,                          // END_COLLECTION
    
        // Mouse TLC
        0x85, 0x02,                    // REPORT_ID (2)
    
        0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
        0x09, 0x02,                    // USAGE (Mouse)
        0xa1, 0x01,                    // COLLECTION (Application)
        0x09, 0x01,                    //   USAGE (Pointer)
        0xa1, 0x00,                    //   COLLECTION (Physical)
        0x05, 0x09,                    //     USAGE_PAGE (Button)
        0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
        0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3)
        0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
        0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
        0x95, 0x03,                    //     REPORT_COUNT (3)
        0x75, 0x01,                    //     REPORT_SIZE (1)
        0x81, 0x02,                    //     INPUT (Data,Var,Abs)
        0x95, 0x01,                    //     REPORT_COUNT (1)
        0x75, 0x05,                    //     REPORT_SIZE (5)
        0x81, 0x03,                    //     INPUT (Cnst,Var,Abs)
        0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
        0x09, 0x30,                    //     USAGE (X)
        0x09, 0x31,                    //     USAGE (Y)
        0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
        0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
        0x75, 0x08,                    //     REPORT_SIZE (8)
        0x95, 0x02,                    //     REPORT_COUNT (2)
        0x81, 0x06,                    //     INPUT (Data,Var,Rel)
        0xc0,                          //   END_COLLECTION
        0xc0                           // END_COLLECTION
    };
    

    These macros are tuned for this change.

    usb_config.c
    
    #define USBD_HID_INREPORT_NUM       2
    #define USBD_HID_OUTREPORT_NUM      1
    #define USBD_HID_INREPORT_MAX_SZ    9
    #define USBD_HID_OUTREPORT_MAX_SZ   2
    

    Tsuneo

  • Thanks for your advice,

    As soon as i put Report Id inside my descriptor, in a software as USBlyser, the HID report descriptor was not recognized and the device can not start.

    Have you an idea about the problem.

  • Now your problem is probably that Windows host does not have appropriate driver for the device that you created it automatically loads drivers for devices with single in or out descriptor but your descriptor does not apply to no standard HID device so Windows do not have driver for it in that case you have to provide Windows driver for your custom device.

  • If you would run the example once on your PC, the USB configuration of the example should be recorded on Windows registry. When you modify descriptors, Windows could be confused by seeing different USB configuration on your device. Windows try to assign previous device driver and fail.

    Windows manages devices using their Vendor/Product ID (VID/PID). When you change device configuration,
    a) Assign another VID/PID to your device
    OR
    b) Uninstall the device instance from Windows.

    This utility gives easy way to find / uninstall target device instace of the VID/PID
    USBDeview
    www.nirsoft.net/.../usb_devices_view.html

    Tsuneo