• AVR Freaks

Host recognize Composite device as two input devices

Author
alexia
New Member
  • Total Posts : 11
  • Reward points : 0
  • Joined: 2011/02/10 02:58:59
  • Location: 0
  • Status: offline
2011/02/21 09:10:28 (permalink)
0

Host recognize Composite device as two input devices

Hi all,
First I want to thank you for reading and helping me out with this issue.
I am new in USB device development. However I have experience in developing Microcontroller FW.

My problem:
I need to develop composite device which has two interfaces (mouse and Vendor defined). My current state is that my device doesn’t work. The enumeration process succeeded. The device’s state is CONFIGURED. I am not sure if the descriptors and the report descriptors are correct (which I assume the cause of the problem).
Windows “Device Manager” shows “USB Composite Device” with two “USB Input Device”. Each “USB Input Device” has “HID-compliant device” and “HID-compliant mouse”.
Why are there two mice while my descriptors include one vendor specific and one Mouse?
My code is based on the mouse sample supplied by Microchip. The project FW works fine if only mouse descriptor is enabled (GPIO is commented out). I see mouse movement in circles on screen. When I add the GPIO, mouse movement stops even though HIDTxPacket() is called.

I am posting my descriptors in case the problem is there:
 
     /* Device Descriptor */      
ROM USB_DEVICE_DESCRIPTOR device_dsc=     
{         
 0x12,            // Size of this descriptor in bytes         
 USB_DESCRIPTOR_DEVICE,  // DEVICE descriptor type         
 0x0200,           // USB Spec Release Number in BCD format         
 0x00,            // Class Code         
 0x00,            // Subclass code         
 0x00,            // Protocol code         
 USB_EP0_BUFF_SIZE,      // Max packet size for EP0, see usb_config.h         
 VID,            // Vendor ID         
 PID,            // Product ID: Mouse in a circle fw demo         
 0x0004,           // Device release number in BCD format         
 0x01,            // Manufacturer string index         
 0x02,            // Product string index         
 0x00,            // Device serial number string index         
 0x01            // Number of possible configurations     
};           /* Configuration Descriptor */     

ROM BYTE configDescriptor1[]=
{                   
 0x09,                                   // Size of this descriptor in bytes         
 USB_DESCRIPTOR_CONFIGURATION,           // CONFIGURATION descriptor type         
 DESC_CONFIG_WORD(0x003b),               // Total length of data for this cfg         
 2,                                      // Number of interfaces in this cfg         
 1,                                      // Index value of this configuration         
 0,                                      // Configuration string index         
 _DEFAULT,                               // Attributes, see usb_device.h         
 50,                                     // Max power consumption (2X mA)            
 
 //////////////////////////// Mouse ////////////////////////////         
 /* Interface Descriptor */         
 0x09,       // Size of this descriptor in bytes         
 USB_DESCRIPTOR_INTERFACE,       // INTERFACE descriptor type         
 0,                                      // Interface Number         
 0,                                      // Alternate Setting Number         
 1,                                      // Number of endpoints in this intf         
 HID_INTF,                               // Class code         
 BOOT_INTF_SUBCLASS,                     // Subclass code         
 HID_PROTOCOL_MOUSE,                     // Protocol code         
 0,                                      // Interface string index          
 
 /* HID Class-Specific Descriptor */         
 0x09,                                   // 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(75),                   // Size of the mouse report descriptor Report ID (1)                  
 
 /* Endpoint Descriptor */         
 0x07,                                   //sizeof(USB_EP_DSC)         
 USB_DESCRIPTOR_ENDPOINT,                //Endpoint Descriptor         
 _EP01_IN,                               //EndpointAddress         
 _INTERRUPT,                             //Attributes         
 DESC_CONFIG_WORD(3),                    //size         
 0x01,                                   //Interval             
 
 //////////////////////////// GPIO ////////////////////////////         
 /* Interface Descriptor */         
 0x09,                                   // Size of this descriptor in bytes         
 USB_DESCRIPTOR_INTERFACE,               // INTERFACE descriptor type         
 1,                                      // Interface Number         
 0,                                      // Alternate Setting Number         
 1,                                      // Number of endpoints in this intf         
 HID_INTF,                               // Class code        
 BOOT_INTF_SUBCLASS,                     // Subclass code         
 HID_PROTOCOL_NONE,                      // Protocol code         
 0,                                      // Interface string index                  
 
 /* HID Class-Specific Descriptor */         
 0x09,                                   // 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(75),                   // Size of the GPIO report descriptor Report ID (2)                  
 
 /* Endpoint Descriptor */         
 0x07,                                   //sizeof(USB_EP_DSC)         
 USB_DESCRIPTOR_ENDPOINT,                //Endpoint Descriptor         
 _EP02_OUT,                              //EndpointAddress         
 _INTERRUPT,                             //Attributes         
 DESC_CONFIG_WORD(8),                    //size         
 0x01                                    //Interval     
};      
     
ROM struct{ BYTE report[HID_RPT01_SIZE]; }hid_rpt01= {     
{              
 //////////////////////////////// Mouse ////////////////////////////////        
 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 (1)        
 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, 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,Var,Rel)        
 0xc0,                          //   END_COLLECTION        
 0xc0,                          // END_COLLECTION      
     
//////////////////////////////// GPIO ////////////////////////////////         
 0x06, 0x00, 0xff,              // USAGE_PAGE (Vendor Defined Page 1)         
 0x09, 0x01,                    // USAGE (Vendor Usage 1)         
 0xa1, 0x01,                    // COLLECTION (Application)         
 0x85, 0x02,                    //   REPORT_ID (2)         
 0x09, 0x01,                    //   USAGE (Vendor Usage 1)         
 0x15, 0x00,                    //   LOGICAL_MINIMUM (0)         
 0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)         
 0x75, 0x08,                    //   REPORT_SIZE (8)         
 0x95, 0x08,                    //   REPORT_COUNT (8)         
 0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)         
 0xc0                           // END_COLLECTION      
}     
};          

 
usb_config.h
 
#define USB_EP0_BUFF_SIZE    8                                                                                             
#define USB_MAX_NUM_INT        2
#define USB_MAX_EP_NUMBER               1  
#define USB_NUM_STRING_DESCRIPTORS      3  
#define USB_USE_HID #define HID_INTF_ID 0x00
#define HID_INTF_ID_1                   0x01
#define HID_EP                          1
#define HID_INT_OUT_EP_SIZE             8
#define HID_INT_IN_EP_SIZE              3
#define HID_NUM_OF_DSC                  1
#define HID_RPT01_SIZE                  0x4b 
 
 
I am obviously doing something wrong. I have no idea if it is in one of the descriptors or if it is in the USB stack.
Thank you gain.
post edited by alexia - 2011/02/21 09:46:25
#1

6 Replies Related Threads

    alexia
    New Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2011/02/10 02:58:59
    • Location: 0
    • Status: offline
    Re:Host recognize Composite device as two input devices 2011/02/21 09:12:24 (permalink)
    0
    Sorry for the bad formating. I had no idea it will look like that...
    #2
    chinzei
    Super Member
    • Total Posts : 2250
    • Reward points : 0
    • Joined: 2003/11/07 12:39:02
    • Location: Tokyo, Japan
    • Status: offline
    Re:Host recognize Composite device as two input devices 2011/02/21 15:06:14 (permalink)
    0

    Windows “Device Manager” shows “USB Composite Device” with two “USB Input Device”.

    Your descriptors are composed exactly like Windows show.
    Do you like a vendor-specific class instead of HID, for the second interface?

    Tsuneo
    #3
    alexia
    New Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2011/02/10 02:58:59
    • Location: 0
    • Status: offline
    Re:Host recognize Composite device as two input devices 2011/02/21 15:06:24 (permalink)
    0
    Hi chinzei.
     
    thank you for your reply. 
     
    Yes I need vendor specific hid.
    It there anything wrong with my descriptors?
     
    Thank you again.
    post edited by alexia - 2011/02/21 15:11:46
    #4
    chinzei
    Super Member
    • Total Posts : 2250
    • Reward points : 0
    • Joined: 2003/11/07 12:39:02
    • Location: Tokyo, Japan
    • Status: offline
    Re:Host recognize Composite device as two input devices 2011/02/21 15:50:04 (permalink)
    0
    Yes I need vendor specific hid.

    I see.

    Split your single report descriptor into two descriptors, one for each interface.
    Each "HID Class-Specific Descriptor" specifies the size of its own report descriptor.

    usb_config.h

         #define USB_MAX_EP_NUMBER               1    // <---- 2
         ...
         #define HID_RPT01_SIZE                  0x4b // <---- 52
         #define HID_RPT02_SIZE                  23   // <---- add this line


    usb_descriptors.c

          //////////////////////////// Mouse ////////////////////////////         
          ...
          /* HID Class-Specific Descriptor */         
          0x09,                                   // 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(75),          // <---- DESC_CONFIG_WORD(HID_RPT01_SIZE),
          ...
          //////////////////////////// GPIO ////////////////////////////         
          …
          /* HID Class-Specific Descriptor */         
          0x09,                                   // 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(75),          // <---- DESC_CONFIG_WORD(HID_RPT02_SIZE),
          ...


         ROM struct{ BYTE report[HID_RPT01_SIZE]; }hid_rpt01= {     
         {              
          //////////////////////////////// Mouse ////////////////////////////////        
          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 (1)        
          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, 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,Var,Rel)        
          0xc0,                          //   END_COLLECTION        
          0xc0                           // END_COLLECTION      
          }
          };

         ROM struct{ BYTE report[HID_RPT02_SIZE]; }hid_rpt02= {     
         {              
         //////////////////////////////// GPIO ////////////////////////////////         
          0x06, 0x00, 0xff,              // USAGE_PAGE (Vendor Defined Page 1)         
          0x09, 0x01,                    // USAGE (Vendor Usage 1)         
          0xa1, 0x01,                    // COLLECTION (Application)         
          0x85, 0x02,                    //   REPORT_ID (2)         
          0x09, 0x01,                    //   USAGE (Vendor Usage 1)         
          0x15, 0x00,                    //   LOGICAL_MINIMUM (0)         
          0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)         
          0x75, 0x08,                    //   REPORT_SIZE (8)         
          0x95, 0x08,                    //   REPORT_COUNT (8)         
          0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)         
          0xc0                           // END_COLLECTION      
         }     
         };                      



    You have to touch to the HID class stack code, too, so that it returns each report descriptor for Get_Descriptor( HID report ) request.

    Copy usb_function_hid.c (under C:\Microchip Solutions v2010-10-19\Microchip\USB\HID Device Driver\) to your project, and replace the compile target on the workspace to the copied one.
    Modify the code in "case DSC_HID" and "case DSC_RPT"

    usb_function_hid.c

    void USBCheckHIDRequest(void)
    {
        if(SetupPkt.Recipient != USB_SETUP_RECIPIENT_INTERFACE_BITFIELD) return;
        if((SetupPkt.bIntfID != HID_INTF_ID) && (SetupPkt.bIntfID != HID_INTF_ID_1)) return;  // <----
        ...   

        if(SetupPkt.bRequest == USB_REQUEST_GET_DESCRIPTOR)
        {
            switch(SetupPkt.bDescriptorType)
            {
                case DSC_HID: //HID Descriptor         
                    if(USBActiveConfiguration == 1)
                    {
                        if (SetupPkt.bIntfID == HID_INTF_ID)
                        {
                            USBEP0SendROMPtr(
                                (ROM BYTE*)&configDescriptor1 + 18,
                                sizeof(USB_HID_DSC)+3,
                                USB_EP0_INCLUDE_ZERO);
                        }
                        if (SetupPkt.bIntfID == HID_INTF_ID_1)
                        {
                            USBEP0SendROMPtr(
                                (ROM BYTE*)&configDescriptor1 + 43,
                                sizeof(USB_HID_DSC)+3,
                                USB_EP0_INCLUDE_ZERO);
                        }
                    }
                    break;

                case DSC_RPT:  //Report Descriptor          
                    if(USBActiveConfiguration == 1)
                    {
                        if (SetupPkt.bIntfID == HID_INTF_ID)
                        {
                            USBEP0SendROMPtr(
                                (ROM BYTE*)&hid_rpt01,
                                HID_RPT01_SIZE,
                                USB_EP0_INCLUDE_ZERO);
                        }
                        if (SetupPkt.bIntfID == HID_INTF_ID_1)
                        {
                        USBEP0SendROMPtr(
                            (ROM BYTE*)&hid_rpt02,
                            HID_RPT02_SIZE,
                            USB_EP0_INCLUDE_ZERO);
                        }
                    }
                    break;


    Tsuneo
    #5
    alexia
    New Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2011/02/10 02:58:59
    • Location: 0
    • Status: offline
    Re:Host recognize Composite device as two input devices 2011/02/22 12:19:14 (permalink)
    0
    Hello chinzei,
     
    Thank you very much for your help. It is working now!!!
    However, I have some questions if I may.
     
    1.   In USBCheckHIDRequest() I saw that only “DSC_RPT” is called while “DSC_HID” never does.
          I put UART trace. When and how does the OS get the HID descriptors if I don't see “DSC_HID” print.
          Note that mouse 
    works great. I haven’t tested the other interface yet.
    2.   Why did you separate the two interfaces into two different report descriptors? Can’t they be on
          same report? Do I still need the report IDs? If I add third HID (Volume) does it need to be on its
          own report descriptor or it can be on the same report with the mouse HID but with different report ID?
     
    Once again, thank you very much for your help.
    post edited by alexia - 2011/02/22 12:22:33
    #6
    chinzei
    Super Member
    • Total Posts : 2250
    • Reward points : 0
    • Joined: 2003/11/07 12:39:02
    • Location: Tokyo, Japan
    • Status: offline
    Re:Host recognize Composite device as two input devices 2011/02/23 15:18:28 (permalink)
    0
    1. In USBCheckHIDRequest() I saw that only “DSC_RPT” is called while “DSC_HID” never does.

    You wouldn't see“DSC_HID”called in any major OS, Windows, Linux and MacOSX.
    The code is there, just for HID spec compliance.

    2.   Why did you separate the two interfaces into two different report descriptors? Can’t they be on same report?

    There are two ways to get two (or more) HID on single USB device.
    a) Composite device
    b) Multiple TLC (Top-Level Collection) <- HID specific

    Composite device is a combination of independent interfaces. Therefore, each HID interface has its own report descriptor.

    Multiple TLC combines HID report descriptor on single HID interface.
    HID functions, defined by each TLC, share the HID interface and endpoint(s) (IN and OUT).

    Your code was an incomplete mixture of both methods. I took composite device approach, following your topic title.

    Do I still need the report IDs?

    Auu, my bad. Report IDs are redundant.

    If I add third HID (Volume) does it need to be on its own report descriptor or it can be on the same report with the mouse HID but with different report ID?

    For composite device approach, you need the third HID interface and report descriptor, but no report ID.

    Tsuneo
    #7
    Jump to:
    © 2019 APG vNext Commercial Version 4.5