• AVR Freaks

Helpful ReplyHID keyboard + mouse using 1 HID report with 2 IDs - It's killing me

Author
lawrence_jeff
New Member
  • Total Posts : 2
  • Reward points : 0
  • Joined: 2012/07/22 19:44:26
  • Location: 0
  • Status: offline
2012/07/22 20:22:57 (permalink)
0

HID keyboard + mouse using 1 HID report with 2 IDs - It's killing me

Hi all, hopefully I can get some help as I can't figure out whats going on with my code - I have read through USB complete - downloaded countless examples and have had no luck.
Here is what I am doing.

Starting with 4-03-2012 - Device - HID - Keyboard Example (Using a PIC18F4550 PICDEM FSUSB board). I am attempting to add mouse functionality. Starting from working keyboard code here is what I did:
 
1) Changed the descriptor to add HID mouse info (including ReportIDs) - New length 115 bytes

ROM struct{BYTE report[HID_RPT01_SIZE];}hid_rpt01=
{  
    0x05, 0x01, /* Usage Page (Generic Desktop)             */
    0x09, 0x02, /* Usage (Mouse)                            */
    0xA1, 0x01, /* Collection (Application)                 */
    0x09, 0x01, /*  Usage (Pointer)                         */
    0xA1, 0x00, /*  Collection (Physical)                   */
    0x85, 0x01,  /*   Report ID  */
    0x05, 0x09, /*      Usage Page (Buttons)                */
    0x19, 0x01, /*      Usage Minimum (01)                  */
    0x29, 0x03, /*      Usage Maximum (03)                  */
    0x15, 0x00, /*      Logical Minimum (0)                 */
    0x25, 0x01, /*      Logical Maximum (0)                 */
    0x95, 0x03, /*      Report Count (3)                    */
    0x75, 0x01, /*      Report Size (1)                     */
    0x81, 0x02, /*      Input (Data, Variable, Absolute)    */
    0x95, 0x01, /*      Report Count (1)                    */
    0x75, 0x05, /*      Report Size (5)                     */
    0x81, 0x01, /*      Input (Constant)    ;5 bit padding  */
    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, Variable, Relative)    */
    0xC0, 0xC0,/* End Collection,End Collection            */
    0x09, 0x06, /*  Usage (Keyboard)                    */
    0xA1, 0x01, /*  Collection (Application)            */
    0x85, 0x02,  /*   Report ID  */
    0x05, 0x07, /*   Usage (Key codes)                   */
    0x19, 0xE0, /*      Usage Minimum (224)                 */
    0x29, 0xE7, /*      Usage Maximum (231)                 */
    0x15, 0x00, /*      Logical Minimum (0)                 */
    0x25, 0x01, /*      Logical Maximum (1)                 */
    0x75, 0x01, /*      Report Size (1)                     */
    0x95, 0x08, /*      Report Count (8)                    */
    0x81, 0x02, /*      Input (Data, Variable, Absolute)    */
    0x95, 0x01, /*      Report Count (1)                    */
    0x75, 0x08, /*      Report Size (8)                     */
    0x81, 0x01, /*      Input (Constant)    ;5 bit padding  */
    0x95, 0x05, /*      Report Count (5)                    */
    0x75, 0x01, /*      Report Size (1)                     */
    0x05, 0x08, /*      Usage Page (Page# for LEDs)         */
    0x19, 0x01, /*      Usage Minimum (01)                  */
    0x29, 0x05, /*      Usage Maximum (05)                  */
    0x91, 0x02, /*      Output (Data, Variable, Absolute)   */
    0x95, 0x01, /*      Report Count (1)                    */
    0x75, 0x03, /*      Report Size (3)                     */
    0x91, 0x01, /*      Output (Constant)                   */
    0x95, 0x06, /*      Report Count (6)                    */
    0x75, 0x08, /*      Report Size (8)                     */
    0x15, 0x00, /*      Logical Minimum (0)                 */
    0x25, 0x65, /*      Logical Maximum (101)               */
    0x05, 0x07, /*   Usage (Key codes)                   */
    0x19, 0x00, /*      Usage Minimum (00)                  */
    0x29, 0x65, /*      Usage Maximum (101)                 */
    0x81, 0x00, /*      Input (Data, Array)                 */
    0xC0
};      /*   End Collection,End Collection       */

2) Updated HID_RPT01_SIZE to 115
 #define HID_RPT01_SIZE 115 

3) Updated HID Descriptor size field to 115 

    /* HID Class-Specific Descriptor */
    0x09,//sizeof(USB_HID_DSC)+3,    // Size of this descriptor in bytes RRoj hack
    DSC_HID,                // HID descriptor type
    DESC_CONFIG_WORD(0x0111),                 // HID Spec Release Number in BCD format (1.11)
    0x00,                   // Country Code (0x00 for Not supported)
    HID_NUM_OF_DSC,         // Number of class descriptors, see usbcfg.h
    DSC_RPT,                // Report descriptor type
    DESC_CONFIG_WORD(115),   //sizeof(hid_rpt01),    

4) Changed the IN and OUT Endpoint descriptor size from 8 to 9 bytes (To reflect the ReportID addition)
 

    /* Endpoint Descriptor */
    0x07,/*sizeof(USB_EP_DSC)*/
    USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
    HID_EP | _EP_IN,            //EndpointAddress
    _INTERRUPT,                       //Attributes
    DESC_CONFIG_WORD(9),        //size
    0x50,                        //Interval //
    /* Endpoint Descriptor */
    0x07,/*sizeof(USB_EP_DSC)*/
    USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
    HID_EP | _EP_OUT,            //EndpointAddress
    _INTERRUPT,                       //Attributes
    DESC_CONFIG_WORD(9),        //size
    0x50

5) Changed the HID_INT_IN_EP_SIZE and HID_INT_OUT_EP_SIZE to 9

#define HID_INT_OUT_EP_SIZE 9
#define HID_INT_IN_EP_SIZE 9

6) Added a byte to hid_report, set the first byte in hid_report_in equal to the reportID of the keyboard and changed HIDTxPacket from 8 to 9 bytes to reflect the new size

hid_report_in[0] = 2; //REPORTID
hid_report_in[1] = 0; //MODIFIER
hid_report_in[2] = 0; //RESERVED
hid_report_in[3] = 4; //KEY1 LETTER A
hid_report_in[4] = 0;
hid_report_in[5] = 0;
hid_report_in[6] = 0;      
hid_report_in[7] = 0;
hid_report_in[8] = 0;
lastINTransmission = HIDTxPacket(HID_EP, (BYTE*)hid_report_in, 0x09);

7) Changed the PID
 
 
The device enumerates as a keyboard and mouse but the functions to send data don't work - code that would successfully send keystrokes or mouse movements do nothing.
I'm at a complete loss, I think I understand all the parts involved but can't get it to work. I searched through the forums and did find a key+mouse example that does based on an older version of the USB code but can't make the same components work using the updated functions in 2.x. Any help would be greatly appreciated as I feel my eyes will begin to bleed if I look at this any longer!
 
 
#1
DarioG
Allmächtig.
  • Total Posts : 54081
  • Reward points : 0
  • Joined: 2006/02/25 08:58:22
  • Location: Oesterreich
  • Status: offline
Re:HID keyboard + mouse using 1 HID report with 2 IDs - It's killing me 2012/07/23 00:22:04 (permalink)
0
Hmm the above sounds good enough, but Tsuneo may know better!
Personally, I'd have used 2 interfaces rather than pre-prending the report ID to the packets etc. , since PC may not like that...

GENOVA :D :D ! GODO
#2
chinzei
Super Member
  • Total Posts : 2250
  • Reward points : 0
  • Joined: 2003/11/07 12:39:02
  • Location: Tokyo, Japan
  • Status: offline
Re:HID keyboard + mouse using 1 HID report with 2 IDs - It's killing me 2012/07/23 13:28:52 (permalink) ☄ Helpful
+2 (1)
In addition to your modification, increase HIDRxPacket() size argument by one for the report ID, at USBCBInitEP()


C:\Microchip Solutions v2012-04-03\USB\zTest Device - HID - Keyboard\Firmware\Keyboard.c

void USBCBInitEP(void)
{
    //enable the HID endpoint
    USBEnableEndpoint(HID_EP,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);

//  lastOUTTransmission = HIDRxPacket(HID_EP,(BYTE*)&hid_report_out,1);
    lastOUTTransmission = HIDRxPacket(HID_EP,(BYTE*)&hid_report_out,2);  // <----

}


Also, on Keyboard() routine,

void Keyboard(void)
{
    ...
    if(!HIDRxHandleBusy(lastOUTTransmission))
    {
        //Do something useful with the data now.  Data is in the OutBuffer[0].
        //Num Lock LED state is in Bit0.
//      if(hid_report_out[0] & 0x01) //Make LED1 and LED2 match Num Lock state.
        if(hid_report_out[1] & 0x01) //Make LED1 and LED2 match Num Lock state. // <----
        {
            mLED_1_On();
            mLED_2_On();
        }
        else
        {
            mLED_1_Off();
            mLED_2_Off();           
        }

        //Stop toggling the LEDs, so you can temporily see the Num lock LED state instead.
        //Once the CountdownTimerToShowUSBStatusOnLEDs reaches 0, the LEDs will go back to showing USB state instead.
        BlinkStatusValid = FALSE;
        CountdownTimerToShowUSBStatusOnLEDs = 140000;

//      lastOUTTransmission = HIDRxPacket(HID_EP,(BYTE*)&hid_report_out,1);
        lastOUTTransmission = HIDRxPacket(HID_EP,(BYTE*)&hid_report_out,2);     // <----


Tsuneo
post edited by chinzei - 2012/07/23 13:36:26
#3
lawrence_jeff
New Member
  • Total Posts : 2
  • Reward points : 0
  • Joined: 2012/07/22 19:44:26
  • Location: 0
  • Status: offline
Re:HID keyboard + mouse using 1 HID report with 2 IDs - It's killing me 2012/07/23 19:39:55 (permalink)
0
Chinzei - you are the man!! - I had commented out some of the respose stuff so it was this line you identified that was the problem

lastOUTTransmission = HIDRxPacket(HID_EP,(BYTE*)&hid_report_out,2);

I tried to follow the maze of code without much luck, but am I understanding correctly that the response packet also has a byte prepended with the report ID so you need to look at the second byte (indicating the endpoint is not busy)?
#4
Jump to:
© 2019 APG vNext Commercial Version 4.5