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

Emulate USB Keyboard with MCBSTM32Exl

Hi,

I use the board MCBSTM32Exl (http://www.keil.com/arm/mcbstm32exl/) and i wanna that my Board emulate a USB HID Keyboard (When i use the push-button User, the char 'Q' is send to my PC Host). For this, i studied the STMicroelectronics' library "USB full-speed device library" (www.st.com/.../um0424.zip) and adapted interruptions/GPIOs to use this Flibrary with my Board. Also, my PC recognize the device and i successed send data (I watched with a sniffer).

But, it's not like a keyboard, i tried to change the descriptor but it does'nt work (for exemple, my PC don't recognize the device)...

Have you any idea to help me ?

Regards,
ealary.

  • 1) Run Custom_HID project on uVision IDE, select "STM3210E-EVAL" at the target pulldown on the tool bar.
    ST's STM3210E-EVAL board is closer to MCBSTM32Exl
    - STM32F103ZG
    - Both boards mount 8MHz crystal
    - PB15 pin connects to "USB Disconnect" circuitry

    2) Replace report descriptor to a keyboard one.
    You may take it from keybrd.hid example of HID Descriptor Tool

    HID Descriptor Tool on USB.org
    www.usb.org/.../dt2_4.zip

    \STM32_USB-FS-Device_Lib_V3.3.0\Project\Custom_HID\src\usb_desc.h
    
    #define CUSTOMHID_SIZ_REPORT_DESC               63
    
    \STM32_USB-FS-Device_Lib_V3.3.0\Project\Custom_HID\src\usb_desc.c
    
    const uint8_t CustomHID_ReportDescriptor[CUSTOMHID_SIZ_REPORT_DESC] =
    {
      // drag in from keybrd.hid example
        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
    };
    

    3) Put 8-bytes input report of keyboard over the interrupt IN endpoint, when a key makes and when the key breaks.

    I explained on the contents of this input report in this topic on SiLabs forum,
    USB HID KEYBOARD
    www.cygnal.org/.../001381.html

    On the ST's example, the report is sent to host using USB_SIL_Write().
    You'll see a typical code in EXTI9_5_IRQHandler() (\STM32_USB-FS-Device_Lib_V3.3.0\Project\Custom_HID\src\stm32f10x_it.c)

    In this file, DMA1_Channel1_IRQHandler() and EXTI15_10_IRQHandler() also put input reports using USB_SIL_Write(). You have to disable these IRQs, so that any spurious report doesn't come out.

    4) Optionally, implement Set_Report( Output ) process.
    Host puts output reports for keyboard LED over Set_Report( Output ) request.
    In this post to ST forum, I showed Set_Report( Feature ) implementation.

    my.st.com/.../Flat.aspx

    In CustomHID_Data_Setup() routine, copy the lines on case SET_REPORT/case HID_FEATURE into case SET_REPORT/case HID_OUTPUT

    4) Optionally, remove interrupt OUT endpoint from the config descriptor set
    Also delete routines relates to the interrupt OUT endpoint
    The interrupt OUT endpoint is not used on keyboard implementation.

    Tsuneo

  • Hi, thank for your answer.

    Into the usb_desc.c, should i change anything with the Report Descriptor ? (Like, wMaxPacketSize into the Endpoint Descriptor ?)

    3) Put 8-bytes input report of keyboard over the interrupt IN endpoint, when a key makes and when the key breaks.
    Here, should i have change the buffer size in

    \Custom_HID\src\stm32f10x_it.c
    __IO uint8_t Send_Buffer[2];
    

    for

    __IO uint8_t Send_Buffer[8];
    

    or keep the Buffer[2] and use :

    USB_SIL_Write(EP1_IN, (uint8_t*) Send_Buffer, 8);
    

    inside EXTI9_5_IRQHandler(void)

    Also, in the interrupt (EXTI9_5_IRQHandler), which type of data should i insert into the buffer to send the char 'Q' for exemple ?

    Regards,
    ealary

  • > Into the usb_desc.c, should i change anything with the Report Descriptor ? (Like, wMaxPacketSize into the Endpoint Descriptor ?)

    Ah yes, good catch.
    wMaxPacketSize of the interrupt IN endpoint descriptor increases to 8 bytes,
    to put the input report in single transaction.

    Also, the buffer size for the input report increases into 8 bytes.

    > which type of data should i insert into the buffer to send the char 'Q' for exemple ?

    As explained on SiLabs forum ( www.cygnal.org/.../001381.html ),

    At key push:
    input_report[8] = {
       0x00,   // modifier keys - nothing
       0x00,   // reserved
       0x14,   // keycode array[0] - key code of "Q"
       0x00,   // keycode array[1]
       0x00,   // keycode array[2]
       0x00,   // keycode array[3]
       0x00,   // keycode array[4]
       0x00,   // keycode array[5]
    }
    
    At key release: - all zeros:
    input_report[8] = {
       0x00,   // modifier keys - nothing
       0x00,   // reserved
       0x00,   // keycode array[0]
       0x00,   // keycode array[1]
       0x00,   // keycode array[2]
       0x00,   // keycode array[3]
       0x00,   // keycode array[4]
       0x00,   // keycode array[5]
    }
    

    Tsuneo

  • Oops,
    Increase the endpoint buffer size on the USB engine, too.

    \STM32_USB-FS-Device_Lib_V3.3.0\Project\Custom_HID\src\usb_prop.c
    
    void CustomHID_Reset(void)
    {
      ...
      ...
      SetEPTxCount(ENDP1, 2);   // <-- SetEPTxCount(ENDP1, 8)
    

    Tsuneo

  • Thank for your quick answer !

    I applied the modifications (Report, Interrupt etc...) but now, when i watch my USB sniffer (USBlyzer), nothing is transmit...

    Do you know why and how fixe that ?

    Regards
    Ealary

  • 1) Clean up wrong device instance(s) on registry
    On the PC Device Manager, do you see an extra keyboard, made by your device?
    If you wouldn't, unplug your device.
    a) And uninstall all the device instance(s) of VID/PID = 0x0483/0x5750, using USBDeview

    USBDeview
    www.nirsoft.net/.../usb_devices_view.html

    OR
    b) Assign another VID/PID on the device descriptor

    2) Key interrupt
    ST's example sees the User Button on STM3210E-EVAL board which connects to PG8.
    Fortunately, Keil MCBSTM32Exl also has a User Button at PG8.

    To enable interrupt on both edge,

    \STM32_USB-FS-Device_Lib_V3.3.0\Utilities\STM32_EVAL\STM3210E_EVAL\stm3210e_eval.c
    
    void STM_EVAL_PBInit(Button_TypeDef Button, ButtonMode_TypeDef Button_Mode)
    {
      ...
      ...
        if(Button != BUTTON_WAKEUP)
        {
          EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    
          if (Button == BUTTON_KEY)                                  // <---  add these two lines
            EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
    
        }
    

    OR

    You may poll this User Button in main loop, instead of interrupt
    And put above input reports at the state transition

    Tsuneo

  • Hi

    Clean the wrong instance has successed. Now my board is recognizes like a Keyboard, thank you.

    But now,when i push the button the char is alway send (Like when you keep push a key).

    Do you know why ?

    Regards,
    Ealary

  • Do you generate any key-up event?

  • Hi,

    My keyboard with the MCBSTM32Exl board work perfectly. But now, i need to emulate the Keyboard with a single microcontroller (STM32F103RC) into a protoboard to keep just the USB feature and can add more button. I have adapted the code of MCBSTM32 to the STM32F103RC. I modified the buttons placement with the EXTIs Line and the USB_DISCONNECT pin.

    But when i connect the USB line, nothing is happen. My PC don't recognize the "device" and provide just the power into the protoboard. When i look the base board schematics of MCBSTM32, i see that the D+ and D- lines are PA11 and PA12 but i see nothing in the code about this lines...

    How can i do to emulate my keyboard with the protoboard ?

    Regards,
    Ealary

  • Check the pin connections.
    Connection requirements for your custom USB board are,
    1) PA12 for D+ on USB connector (pin 3), PA11 for D- (pin 2)
    2) PB14 for "USB Disconnect" circuitry (*1)
    3) 8MHz crystal

    (*1) I wrote it's PB15 in my first post, but it was wrong.
    On both boards (MCBSTM32Exl and STM3210E-EVAL), PB14 is the "USB Disconnect" pin.

    Tsuneo

  • My pins connections is correct. That why i don't understand why my PC don't recognize the protoboard :/

  • How about other pins?
    1) BOOT0 (pin 60) - GND
    2) NRST (pin 7) - JTAG TRST

    Tsuneo

  • BOOT0 at GND
    NRST at JtagTRST...

    It's not a firmware issue rather that hardware connection ?

    Ealary.

  • > It's not a firmware issue rather that hardware connection ?

    The difference of STM32F103RC from STM32F103ZG, related to your project, is just FLASH memory size.
    The binary of MCBSTM32Exl project should work on STM32F103RC.

    Tsuneo