• AVR Freaks

2 HIDs in one Composite device

Author
MDreamer
New Member
  • Total Posts : 7
  • Reward points : 0
  • Joined: 2011/01/05 07:00:47
  • Location: 0
  • Status: offline
2011/01/05 07:22:04 (permalink)
0

2 HIDs in one Composite device

Hi,

I am new to USB-PIC programing and i am trying to a Composite Device that contains 2 HIDs.
I am working with the Microchip USB framework, PIC18F87J50 and MPLAB 8.63v

My OS recognize only one HID device with problem and doesn;t recognize the Comopsite nor the other HID.
Where should i start?

Here are the descriptors:

/* 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
    0x04D8,                 // Vendor ID
    0x003F,                 // Product ID: Custom HID demo
    0x0002,                 // 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 1 Descriptor */
ROM BYTE configDescriptor1[]={
    /* Configuration Descriptor */
    0x09,//sizeof(USB_CFG_DSC),    // Size of this descriptor in bytes
    USB_DESCRIPTOR_CONFIGURATION,                // CONFIGURATION descriptor type
    73,0,            // 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 | _SELF,               // Attributes, see usb_device.h
    50,                     // Max power consumption (2X mA)
                           
    /* Interface Descriptor */
    0x09,//sizeof(USB_INTF_DSC),   // Size of this descriptor in bytes
    USB_DESCRIPTOR_INTERFACE,               // INTERFACE descriptor type
    0,                      // Interface Number
    0,                      // Alternate Setting Number
    2,                      // Number of endpoints in this intf
    HID_INTF,               // Class code
    0,     // Subclass code
    0,     // Protocol code
    0,                      // Interface string index

    /* HID Class-Specific Descriptor */
    0x09,//sizeof(USB_HID_DSC)+3,    // Size of this descriptor in bytes
    DSC_HID,                // HID descriptor type
    0x11,0x01,                 // 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
    HID_RPT01_SIZE,0x00,//sizeof(hid_rpt01),      // Size of the report descriptor
   
    /* Endpoint Descriptor */
    0x07,/*sizeof(USB_EP_DSC)*/
    USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
    _EP01_IN,                   //EndpointAddress
    _INTERRUPT,                       //Attributes
    0x40,0x00,                  //size
    0x01,                        //Interval

    /* Endpoint Descriptor */
    0x07,/*sizeof(USB_EP_DSC)*/
    USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
    _EP01_OUT,                   //EndpointAddress
    _INTERRUPT,                       //Attributes
    0x40,0x00,                  //size
    0x01,                       //Interval

    /* ----------------- second HID interface ------------------ */

    /* Interface Descriptor */
    0x09,//sizeof(USB_INTF_DSC),   // Size of this descriptor in bytes
    USB_DESCRIPTOR_INTERFACE,               // INTERFACE descriptor type
    1,                      // Interface Number
    0,                      // Alternate Setting Number
    2,                      // Number of endpoints in this intf
    HID_INTF,               // Class code
    0,     // Subclass code
    0,     // Protocol code
    0,                      // Interface string index

    /* HID Class-Specific Descriptor */
    0x09,//sizeof(USB_HID_DSC)+3,    // Size of this descriptor in bytes
    DSC_HID,                // HID descriptor type
    0x11,0x01,                 // 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
    HID_RPT01_SIZE,0x00,//sizeof(hid_rpt01),      // Size of the report descriptor
 
    /* Endpoint Descriptor */
    0x07,/*sizeof(USB_EP_DSC)*/
    USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
    _EP02_IN,                   //EndpointAddress
    _INTERRUPT,                       //Attributes
    0x40,0x00,                  //size
    0x01,                        //Interval

    /* Endpoint Descriptor */
    0x07,/*sizeof(USB_EP_DSC)*/
    USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
    _EP02_OUT,                   //EndpointAddress
    _INTERRUPT,                       //Attributes
    0x40,0x00,                  //size
    0x01                        //Interval
};

//Class specific descriptor - HID
ROM struct{BYTE report[HID_RPT01_SIZE];}hid_rpt01={
{
    0x06, 0x00, 0xFF,       // Usage Page = 0xFF00 (Vendor Defined Page 1)
    0x09, 0x01,             // Usage (Vendor Usage 1)
    0xA1, 0x01,             // Collection (Application)
    0x19, 0x01,             //      Usage Minimum
    0x29, 0x40,             //      Usage Maximum     //64 input usages total (0x01 to 0x40)
    0x15, 0x01,             //      Logical Minimum (data bytes in the report may have minimum value = 0x00)
    0x25, 0x40,                //      Logical Maximum (data bytes in the report may have maximum value = 0x00FF = unsigned 255)
    0x75, 0x08,             //      Report Size: 8-bit field size
    0x95, 0x40,             //      Report Count: Make sixty-four 8-bit fields (the next time the parser hits an "Input", "Output", or "Feature" item)
    0x81, 0x00,             //      Input (Data, Array, Abs): Instantiates input packet fields based on the above report size, count, logical min/max, and usage.
    0x19, 0x01,             //      Usage Minimum
    0x29, 0x40,             //      Usage Maximum     //64 output usages total (0x01 to 0x40)
    0x91, 0x00,             //      Output (Data, Array, Abs): Instantiates output packet fields.  Uses same report size and count as "Input" fields, since nothing new/different was specified to the parser since the "Input" item.
    0xC0}                   // End Collection
};               
#1

15 Replies Related Threads

    chinzei
    Super Member
    • Total Posts : 2250
    • Reward points : 0
    • Joined: 2003/11/07 12:39:02
    • Location: Tokyo, Japan
    • Status: offline
    Re:2 HIDs in one Composite device 2011/01/05 15:09:14 (permalink)
    0
    I have a doubt on the report descriptor at this part,

    ROM struct{BYTE report[HID_RPT01_SIZE];}hid_rpt01={
    {
        ...
        0x15, 0x01,             //      Logical Minimum (data bytes in the report may have minimum value = 0x00)
        0x25, 0x40,             //      Logical Maximum (data bytes in the report may have maximum value = 0x00FF = unsigned 255)

    This is a problem on the original Microchip "USB Device - HID - Custom Demos" (v2010-10-19)
    There is no need to limit the Logical Min/Max to [1..64], unlike Usage Min/Max
    Logical min/max describes the value range of the report field(s), [0..255] is usual for HID custom demo

        0x15, 0x00,             //      LOGICAL_MINIMUM(0)
        0x26, 0xFF, 0x00,       //      LOGICAL_MAXIMUM(255)


    HID_RPT01_SIZE should increse by one for this fix

    C:\Microchip Solutions v2010-10-19\USB Device - HID - Custom Demos\Generic HID - Firmware\usb_config.h

    #define HID_RPT01_SIZE          28   // <------ 29


    The other descriptors seem fine.


    How about mods for other files?

    USBCheckHIDRequest() (usb_function_hid.c) - modify this routine, so that it accepts both of HID interfaces

    C:\Microchip Solutions v2010-10-19\USB Device - HID - Custom Demos\Generic HID - Firmware\usb_config.h

    /* HID */
    #define HID_INTF_ID             0x00
    #define HID_INTF_ID1            0x01       // interface number for the second HID IF <--- add this line



    C:\Microchip Solutions v2010-10-19\Microchip\USB\HID Device Driver\usb_function_hid.c
    // copy this file to your project folder before mods,
    // and replace the file entry on the workspace to the copied one

    void USBCheckHIDRequest(void)
    {
        if(SetupPkt.Recipient != USB_SETUP_RECIPIENT_INTERFACE_BITFIELD) return;
    //  if(SetupPkt.bIntfID != HID_INTF_ID) return;     // <---- modify this line, as follows
        if( (SetupPkt.bIntfID != HID_INTF_ID)           // accepts both of HID interfaces
          &&(SetupPkt.bIntfID != HID_INTF_ID1) ) return;

    Actually, it's better to modify USBCheckHIDRequest() at switch-case DSC_HID and DSC_RPT, too.
    But you are using the same (contents) of the HID descriptor and the Report descriptor.
    Then, this *dirty* mods work wink


    To enable the endpoints for the second HID IF,

    C:\Microchip Solutions v2010-10-19\USB Device - HID - Custom Demos\Generic HID - Firmware\usb_config.h

    /* HID */
    #define HID_EP       1
    #define HID_EP2      2       // endpoint address for the second HID IF <--- add this line



    C:\Microchip Solutions v2010-10-19\USB Device - HID - Custom Demos\Generic HID - Firmware\main.c

    /** VARIABLES ******************************************************/

    unsigned char ReceivedDataBuffer[64];
    unsigned char ToSendDataBuffer[64];

    USB_HANDLE USBOutHandle = 0;
    USB_HANDLE USBInHandle = 0;
                                            // assign new buffers and handles for the second HID IF
                                            // For PIC18F87J50, it's easy because of wide USB RAM
    unsigned char ReceivedDataBuffer2[64];
    unsigned char ToSendDataBuffer2[64];

    USB_HANDLE USBOutHandle2 = 0;
    USB_HANDLE USBInHandle2 = 0;

    ...
    ...

    void USBCBInitEP(void)
    {
        //enable the HID endpoint
        USBEnableEndpoint(HID_EP,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
        //Re-arm the OUT endpoint for the next packet
        USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)&ReceivedDataBuffer,64);

        //enable the HID endpoint                       // <--------- add these lines
        USBEnableEndpoint(HID_EP2,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
        //Re-arm the OUT endpoint for the next packet
        USBOutHandle2 = HIDRxPacket(HID_EP2,(BYTE*)&ReceivedDataBuffer2,64);
    }


    Of course, you'll write code to run these endpoints in ProcessIO()


    PC application needs to be modified, too
    The example folder has three PC app variabions.
    Which one are you working on?

    Tsuneo
    #2
    chinzei
    Super Member
    • Total Posts : 2250
    • Reward points : 0
    • Joined: 2003/11/07 12:39:02
    • Location: Tokyo, Japan
    • Status: offline
    Re:2 HIDs in one Composite device 2011/01/06 16:18:25 (permalink)
    0
    Ah, I remember.
    In addition to above mods, these macros on usb_config.h should be touched, for the extra interface and endpoints.


    C:\Microchip Solutions v2010-10-19\USB Device - HID - Custom Demos\Generic HID - Firmware\usb_config.h

    /** DEFINITIONS ****************************************************/
    ...
    #define USB_MAX_NUM_INT         1   // <---- 2
    #define USB_MAX_EP_NUMBER       1   // <---- 2


    Tsuneo
    #3
    MDreamer
    New Member
    • Total Posts : 7
    • Reward points : 0
    • Joined: 2011/01/05 07:00:47
    • Location: 0
    • Status: offline
    Re:2 HIDs in one Composite device 2011/01/09 04:02:01 (permalink)
    0
    Hi,

    Thank you very much for the detailed response Smile
    I am planning to adapt the 'Generic HID - Simple Demo - PC Software' to that use.
    I did everything that you said and it seems that it compiles but now i have another problem.. i think i run out of space in the PIC.
    I am getting an error:

     MPLINK 4.38, Linker
    Copyright (c) 1998-2010 Microchip Technology Inc.
    Error - section '.udata_main.o' can not fit the section. Section '.udata_main.o' length=0x00000102


    i thinks its because of the two 64 bytes buffers.. actually i don't need 64 bytes. i need only 8 or so. how can solve the problem?

    Again thanks. I really appreciate it!
    #4
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Re:2 HIDs in one Composite device 2011/01/09 04:42:20 (permalink)
    0
    You can probably use #pragmas to move variables into another bank.

    GENOVA :D :D ! GODO
    #5
    MDreamer
    New Member
    • Total Posts : 7
    • Reward points : 0
    • Joined: 2011/01/05 07:00:47
    • Location: 0
    • Status: offline
    Re:2 HIDs in one Composite device 2011/01/09 04:55:57 (permalink)
    0
    ^ Dario,

    I didn't understand what you are saying? how can i move is to anothe bank?
    #6
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Re:2 HIDs in one Composite device 2011/01/09 10:01:15 (permalink)
    0
    Hmm, using
    #pragma udata gpr1
    and such, you can move your RAM variables into another bank: this helps since PIC18 can't have, by default, blocks of contiguous RAM larger than 256 bytes


    GENOVA :D :D ! GODO
    #7
    MDreamer
    New Member
    • Total Posts : 7
    • Reward points : 0
    • Joined: 2011/01/05 07:00:47
    • Location: 0
    • Status: offline
    Re:2 HIDs in one Composite device 2011/01/10 01:02:25 (permalink)
    0
    its working! thank you very much guys!
    #8
    DarioG
    Allmächtig.
    • Total Posts : 54081
    • Reward points : 0
    • Joined: 2006/02/25 08:58:22
    • Location: Oesterreich
    • Status: offline
    Re:2 HIDs in one Composite device 2011/01/10 02:44:30 (permalink)
    0
    ok! Smile good

    GENOVA :D :D ! GODO
    #9
    alexia
    New Member
    • Total Posts : 11
    • Reward points : 0
    • Joined: 2011/02/10 02:58:59
    • Location: 0
    • Status: offline
    Re:2 HIDs in one Composite device 2011/02/14 05:27:39 (permalink)
    0
    Hello all,
     
    First I want to say that English is not my first language.
    I am very new in the USB programming. I read the pdf files from USB.org and got confused. So forgive me for my questions.
     
    I am also using PIC Microcontroller (PIC18F47J53). I have few questions on how to bind between report descriptors and hid descriptors.
     
    I saw MDreamer's question and answers and I have more questions if I may.
     
    I need to develop a composite USB device which contains the following interfaces: mouse (HID-in), audio (HID-out), LEDs (Vendor specific-out) and keys (Vendor specific-in). Each interface has HID descriptor.
     
    So in my understanding I need my report descriptor to contain reports IDs for each interface
    My questions: 
    1. Why in the sample provided by "MDreamer" there is only one HID descriptor? When do you use more than one?
    2. How do I bind HID descriptor to report ID? How does the host know which report ID belong to which interface? Do all the HID descriptors have the same value?
    In the wDescriptorLength field of the HID descriptor, do I write the total length of the report descriptor or only the length of the specific report?
    3. In what situation bNumDescriptors field in the HID descriptor is larger than one?
    4. All my HID descriptors are the same. Do I need to have more than one HID descriptor or one is enough?
     
    Thank you for your help, time and effort.
    #10
    chinzei
    Super Member
    • Total Posts : 2250
    • Reward points : 0
    • Joined: 2003/11/07 12:39:02
    • Location: Tokyo, Japan
    • Status: offline
    Re:2 HIDs in one Composite device 2011/02/14 07:55:19 (permalink)
    0

    mouse (HID-in), audio (HID-out)???, LEDs (Vendor specific-out) and keys (Vendor specific-in). Each interface has HID descriptor.

    USB audio interface is different from HID interface.
    Of course, you can exchange audio data over HID, like other data. But in this case, you have to write a custom PC application which connects audio resources on the PC to the HID endpoint. When you apply audio interface on the device, OS takes care of the process.

    Audio interface can take HID interface with or without IAD (Interface Association Descriptor). But I recommend you to use IAD.

    Config descriptor
    - IAD
    - Audio Control Interface
    - Audio Straming Interface
    - HID mouse Interface
    - HID vendor-specific Interface

    So in my understanding I need my report descriptor to contain reports IDs for each interface

    Not always.

    Report ID is required when you define more than two input (or output or feature) reports in single report descriptor, to identify the report format. In a single report descriptor, you can have one or zero input /and/ one or zero output /and/ one or zero feature report without report ID.

    For HID + HID composite device, each HID interface can have independent report descriptor. You don't need to sum up all report descriptors, to count the report formats.

    1. Why in the sample provided by "MDreamer" there is only one HID descriptor? When do you use more than one?

    Usually, each HID interface has its own report descriptor, for different device type or report format. But in above example, both HID interface happens to have the same device type, the same report format. Therefore, it assigns the same report descriptor to both, to save code space.

    Host queries Get_Descriptor(HID report) with interface number, for each interface. And then, device returns a report descriptor, specific to the interface.

    2. How do I bind HID descriptor to report ID? How does the host know which report ID belong to which interface? Do all the HID descriptors have the same value?

    Report IDs are defined in a report descriptor. These report IDs are effective just for the HID interface and its endpoints, which returns this report descriptor.

    In the wDescriptorLength field of the HID descriptor, do I write the total length of the report descriptor or only the length of the specific report?

    Just the size of single report descriptor, specific to the interface.

    3. In what situation bNumDescriptors field in the HID descriptor is larger than one?

    The HID interface has optional Physical descriptor(s) other than a Report descriptor

    See chapter "3. Management Overview" on the HID spec.

    [qupte]4. All my HID descriptors are the same. Do I need to have more than one HID descriptor or one is enough?
    You should have one HID (class) descriptor for each HID interface. Not one for config.
    And I believe they are different at the wItemLength field, for the report descriptor specific to the HID interface.

    Tsuneo
    post edited by chinzei - 2011/02/14 08:03:49
    #11
    kittu
    Starting Member
    • Total Posts : 37
    • Reward points : 0
    • Joined: 2009/11/24 02:14:32
    • Location: INDIA
    • Status: offline
    Re:2 HIDs in one Composite device 2011/03/09 03:16:01 (permalink)
    0
    reply to, 
    post no #2  PC application needs to be modified, too 
    The example folder has three PC app variabions. 
    Which one are you working on? 


    hi..


    i am also working with multiple hid devices with one host


    so let me know what changes can be made in pc application


    so i can work with multiple hid devices


    & if i have my own find hid function so (from jan axelsons refrence code)


    so how can i modify that code to work with multiple hid devices.


    thank you.


     





    #12
    masterhendor
    New Member
    • Total Posts : 3
    • Reward points : 0
    • Joined: 2011/12/04 19:26:07
    • Location: 0
    • Status: offline
    Re:2 HIDs in one Composite device 2012/02/10 16:56:43 (permalink)
    0
    I am trying to modify the current "Device - HID - Joystick" example to offer 2 (later 3?) Joysticks based on this and the other relevant threads ("boot keyboard & mouse" for example).
    So far I wasn't too sucessful, but at least the first joystick still works with its demo funcionality ;)


    I'll keep trying (hints very welcome!).


    [Working with the Ethernet Starter Kit and MPLABX]
    [I was more sucessful on the Descriptor side of things, this was easy enough for a hacking mechanical engineer (1x19bit, 3x14bit and 2x12bit axis, working like a charm]
    post edited by masterhendor - 2012/02/10 17:33:38
    #13
    masterhendor
    New Member
    • Total Posts : 3
    • Reward points : 0
    • Joined: 2011/12/04 19:26:07
    • Location: 0
    • Status: offline
    Re:2 HIDs in one Composite device 2012/02/24 17:53:12 (permalink)
    0
    Got it working in the meantime, three joysticks are showing up*. So far I am still only sending info to the first one, so I might be missing something ;)

    Little problems: 
    • -USBLyzer doesn't like "09" for each HID descriptors bLength. I was assuming I had to go with 0C instead, but I was wrong...
    • -I want to use USB_INTERRUPT, but SimpleHIDWrite suggests that I must be doing something wrong (data is still "rollling" through).
    • -I have to look into how to assign individual names to each joystick (in the registry iirc from my single HID experiments).





    *3x6axes to not break DXTweak2 atm.

    post edited by masterhendor - 2012/02/24 18:10:24
    #14
    tlkuester
    New Member
    • Total Posts : 2
    • Reward points : 0
    • Joined: 2012/05/16 12:14:14
    • Location: 0
    • Status: offline
    Re:2 HIDs in one Composite device 2012/06/29 15:08:36 (permalink)
    0
    I am working on my first USB device using PIC32.  It needs to emulate keyboard output to host (so I assume this means it needs to have a Generic Desktop/Keyboard interface) and at same time have a vendor-specific HID interface.  I basically want the "Device - HID - Custom Demos" functionality with the addition of keyboard output.  I think this means I need a composite device with 2 interfaces.  I have tried adding a second output report (modeled after the keyboard demo) to the custom demo, but Windows won't let me have read access to it.  When it was just the custom demo, I could get read access to it.
     
    Do I need to edit the Microchip solutions code to support 2 interfaces as described by chinzei or are there any known working examples available that have already done this?
     
    Is it general practice to include the Microchip solutions code in each project if you need to customize it for individual projects?
    #15
    chinzei
    Super Member
    • Total Posts : 2250
    • Reward points : 0
    • Joined: 2003/11/07 12:39:02
    • Location: Tokyo, Japan
    • Status: offline
    Re:2 HIDs in one Composite device 2012/06/29 21:15:44 (permalink)
    0
    tlkuester:
    It needs to emulate keyboard output to host (so I assume this means it needs to have a Generic Desktop/Keyboard interface) and at same time have a vendor-specific HID interface. I think this means I need a composite device with 2 interfaces.  I have tried adding a second output report (modeled after the keyboard demo) to the custom demo,


    HID + HID composite device is one of the way. But there are a couple of another ways.

    1) Feature report
    Windows recognize HID Keyboard/Mouse/Joystick as System Devices. It means PC application can't communicate with System Device directly over Input/Output reports. But Feature report is still available for this purpose. Add Feature report format to the keyboard report descriptor. And then, your PC application can communicate with the keyboard using Feature report in both directions.
    http://www.microchip.com/forums/m215836.aspx

    When the HID device is one of system devices,
    CreateFile() should be called with these parameters, to use Feature report.
    - dwDesiredAccess = 0
    - dwShareMode = (FILE_SHARE_READ | FILE_SHARE_WRITE)

    2) Multiple TLCs (Top Level Collections)
    Instead of composite device, more HID devices are implemented to single HID interface just changing the report descriptor. Append another report descriptor (TLC) after the keyboard report descriptor. Assign report ID to each TLC, keyboard and appended HID device. Each report is preceded by a report ID, which identify HID device on the interface.
    http://www.microchip.com/forums/m567505.aspx


    tlkuester:
    Is it general practice to include the Microchip solutions code in each project if you need to customize it for individual projects?


    It depends on the way how you modify the stack.
    Above two methods don't need to touch to stack code files at all. They are within the supposed extent of the stack. But HID + HID composite device is not supposed by the stack. In such cases, you would drag in a stack file to your project, to apply modification of one-step further.

    Tsuneo
    post edited by chinzei - 2012/06/29 22:15:32
    #16
    Jump to:
    © 2019 APG vNext Commercial Version 4.5