Because of the holidays, TI E2E™ design support forum responses will be delayed from Dec. 25 through Jan. 2. Thank you for your patience.

This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Tiva USB HID Touch

I am attempting to use the Tiva usb_host_mouse project as a starting point to implementing a -- hopefully -- simple touch screen driver.  Of course the project works as expected with an HID mouse attached, and when a touch controller is attached via the same USB port the enumeration process begins.  BUT the end result of an actual touch event is banishment to the FaultISR().

Any suggestions would be much appreciated.

  • Greg Ford said:
    BUT the end result of an actual touch event is banishment to the FaultISR().


    You may analyze the place on which HardFault (FaultISR()) occurs, using calling stack view of the debugger (on Keil). But I believe it is caused because the touch screen should return an input report of more than 3 bytes, expected for boot mouse.

    Anyway, to support the touch screen, you have to write another HID host driver, modifying usbhhidmouse.c.
    C:\ti\TivaWare_C_Series-2.0.1.11577\usblib\host\usbhhidmouse.c

    Before starting modification, the target touch screen should be examined on a PC well, to fix the required feature for modification.

    Using a USB sniffer on a PC, read out descriptors of the touch screen (including report descriptor). These sniffers get the descriptors at enumeration.

    USBlyzer (33days free trial) http://www.usblyzer.com/
    USBTrace (15days free trial) http://www.sysnucleus.com/

    To capture enumeration at plug in,
    - Run USBlyzer, enable "Capture->Capture Hot-plugged" menu, and plug in your device.
    OR
    - After starting USBTrace, click the "Capture Hot Plugged Devices" menu or toolbar button and "start capture". And then, plug in your device.

    These sniffers display Descriptors in readable format. Save the Descriptors into a file.
    Zip and post it, so that we can discuss on the descriptors.

    Tsuneo

  • In addition to the great suggestions already posted, we have an app note that is often useful in diagnosing faults.

    http://www.ti.com/lit/an/spma043/spma043.pdf

    Dexter

  • 7446.USB Input Device.zip

    Tsuneo,

    Thanks for the help.  Attached is the descriptor for the touch panel. 

    Although I use the IAR tool chain, I was able to confirm the cause of the Hard Fault.  The HIDDriverOpen(...) function returns successfully, but a call back function is not registered; therefore any subsequent call to pfnCallback(...) causes the fault.  Which in turn indicates that you are spot on in your assessment of the overall issue; An HID dost driver is required.

    There is a large amount of information where do I begin?

     

  • Umm, the fact didn't go like my above speculation.

    The outline of the mouse detection and initialization of its instance is as follows,

    In usb_host_mouse.c
    (1) When the host detects device connection, USBHCDEvents() callback is called with USB_EVENT_CONNECTED
    (2) USBHCDEvents() checks the interface triad (class, subclass, protocol) fields
    when the triad matches to boot mouse (0x03, 0x01, 0x02),
    (3) STATE_MOUSE_INIT is assigned to g_eUSBState
    (4) main loop catches STATE_MOUSE_INIT,
    (5) USBHMouseInit() initializes the moust device instance (g_psMouseInstance).


    usb_host_mouse.c

    void
    USBHCDEvents(void *pvData)
    {
        ...
        switch(pEventInfo->ui32Event)
        {
            //
            // New mouse detected.
            //
            case USB_EVENT_CONNECTED:       // <------ (1)
            {
                //
                // See if this is a HID Mouse.
                //
                                            // <------ (2)
                if((USBHCDDevClass(pEventInfo->ui32Instance, 0) == USB_CLASS_HID) &&
                   (USBHCDDevProtocol(pEventInfo->ui32Instance, 0) ==
                    USB_HID_PROTOCOL_MOUSE))
                {
                    ...
                    //
                    // Proceed to the STATE_MOUSE_INIT state so that the main loop
                    // can finish initialized the mouse since USBHMouseInit()
                    // cannot be called from within a callback.
                    //
                    g_eUSBState = STATE_MOUSE_INIT;    // <------ (3)
                }
                break;
            }

    int
    main(void)
    {
        ...
        while(1)
        {
            ...
            switch(g_eUSBState)
            {
                //
                // This state is entered when the mouse is first detected.
                //
                case STATE_MOUSE_INIT:                  // <------ (4)
                {
                    //
                    // Initialize the newly connected mouse.
                    //
                    USBHMouseInit(g_psMouseInstance);   // <------ (5)


    Thanking to your post of the descriptors,
    the interface triad of the touch panel is (0x03, 0x00, 0x00)

    Interface Descriptor 0/0 HID, 2 Endpoints
    0 bLength            1 09h  
    1 bDescriptorType    1 04h Interface
    2 bInterfaceNumber   1 00h  
    3 bAlternateSetting  1 00h  
    4 bNumEndpoints      1 02h  
    5 bInterfaceClass    1 03h HID     <-------
    6 bInterfaceSubClass 1 00h         <-------
    7 bInterfaceProtocol 1 00h         <-------
    8 iInterface         1 03h "EndPoint1 Interrupt Pipe"

    It doesn't match to boot mouse.
    And then, the device doesn't pass the check of above (2)
    The sequence, (3) and after, doesn't occur.
    In this way, the device instance isn't initialized.


    If you would like to support this touch panel, you have to write a new driver, based on usbhhidmouse.c
    \TivaWare_C_Series-2.0.1.11577\usblib\host\usbhhidmouse.c
    It won't be so much modification from the original usbhhidmouse.c
    Do you try a custom driver?

    Tsuneo

  • Thanks Tsuneo, That makes more sense. From what I am able to understand I believe I should start by using USBDescGet(...) to get the device descriptor. However I'm not exactly sure where to place the function call or what parameters to include. What function is the initial entry point for the enumeration cycle? Is it necessary to create a custom structure as well?
  • You may modify usb_host_mouse.c and usbhhidmouse.c,
    so that they support both of mouse and the touch panel.
    But I recommend you to modify them just for the touch panel, first.
    When you'll be satisfied of the result, compare the mods and the original, using a "diff" tool (*1),
    And then, you'll get the insight on the way, how to bind them together.

    (*1) for example, WinMerge  http://winmerge.org/

    Here are the mods for the touch panel.

    1) The touch panel is identified by its VID/PID.

    usb_host_mouse.c

    void
    USBHCDEvents(void *pvData)
    {
        ...
        switch(pEventInfo->ui32Event)
        {
            case USB_EVENT_CONNECTED:
            {
         // rewrite this criteria, from boot mouse
    //            if((USBHCDDevClass(pEventInfo->ui32Instance, 0) == USB_CLASS_HID) &&
    //               (USBHCDDevProtocol(pEventInfo->ui32Instance, 0) ==
    //                USB_HID_PROTOCOL_MOUSE))
         // to touch panel
    #define TOUCH_VID 0x14E1
    #define TOUCH_PID 0x6000
                tDeviceDescriptor * pDesc = &g_psMouseInstance->psHIDInstance->psDevice->sDeviceDescriptor;
                if(   (pDesc->idVendor  == TOUCH_VID)
                   && (pDesc->idProduct == TOUCH_PID) )


    The major differences of the touch panel from the boot mouse are twofold,
    2) Boot protocol
    The touch panel doesn't accept boot protocol.
    But USBHMouseInit() puts Set_Protocol( BOOT_PROTOCOL ) request.

    usbhhidmouse.c

    uint32_t
    USBHMouseInit(tUSBHMouse *psMsInstance)
    {
        ...
        //
        // Set the mouse to boot protocol.
        //
    //    USBHHIDSetProtocol(psMsInstance->psHIDInstance, 1);   // <----- comment this line

    3) Input report
    The input report format (3 bytes) of the boot mouse is,

    byte
    offset
    0  buttons (bit 0,1,2)
    1  X - relative, 8-bit signed integer
    2  Y - relative, 8-bit signed integer

    The input report format (5 bytes) of the touch panel is,

    byte
    offset
    0  buttons (bit 6,7)
    1  X - absolute, 16-bit unsigned integer
    3  Y - absolute, 16-bit unsigned integer

    This difference brings a couple of changes on the usbhhidmouse.c

    #define USBHMS_REPORT_SIZE      4    // <---- 5

    UpdateMouseState() function should be utterly rewritten, so that the difference of the input report.
    - button bitmap
    - X,Y: 8bits and 16 bits


    Tsuneo

  • Thank you for your patience Tsuneo. I have attempted to follow your instructions; although they are informative I have hit some technical difficulties. 1. tDeviceDescriptor * pDesc = &g_psMouseInstance->psHIDInstance->psDevice->sDeviceDescriptor; This causes a compiler error "pointer to incomplete class type is not allowed"; although I understand this is related to accessing a structures' data before it has been initialized, I was unable to find a solution. So I used a brute force approach and declared g_eUSBState = STATE_TOUCH_INIT; whenever case: USB_EVENT_CONNECTED is entered. 2. It appears that the critical information for success is found in the device descriptor so I used the debugger to stop in the HIDDriverOpen(...) and the device information appears to be garbage (see attached). Since this is not the case when enumerating the mouse -- which is a low speed device -- is there a problem utilizing Full speed? Or is the speed of the device un-related... I chose to look in HIDDriverOpen(...) because it is called before the event handler and the call to USBHMouseInit(...) so if the information for the device is invalid there it is likely incorrect in subsequent usage as well. What do you think Tsuneo?
    Debug_HIDDriverOpen.doc
  • 1. tDeviceDescriptor * pDesc = &g_psMouseInstance->psHIDInstance->psDevice->sDeviceDescriptor; This causes a compiler error



    Ah, sorry. code analysis wasn't enough.
    We have to modify usbhostenum.c, too.

    Copy usbhostenum.c to your project folder,
    C:\ti\TivaWare_C_Series-2.0.1.11577\usblib\host\usbhostenum.c
    and append this routine,

    usbhostenum.c

    #define UNKNOWN_VIDPID  0x00000000

    unsigned long
    USBHCDDevVIDPID(unsigned long ulInstance)
    {
        unsigned long ulDevIndex;

        ulDevIndex = HCDInstanceToDevIndex(ulInstance);

        //
        // If the instance was not valid return an unknown VID/PID.
        //
        if(ulDevIndex == 0xff)
        {
            return(UNKNOWN_VIDPID);
        }

        return( g_sUSBHCD.USBDevice[ulDevIndex].DeviceDescriptor.idVendor << 16
              | g_sUSBHCD.USBDevice[ulDevIndex].DeviceDescriptor.idProduct );
    }

    To support a vendor-specific class, the host stack should have this routine.
    But as the stack doesn't yet implement vendor-specific, this routine isn't there.


    On the usb_host_mouse.c,

    unsigned long USBHCDDevVIDPID(unsigned long ulInstance);
    #define TOUCH_VIDPID (0x14E1 << 16 | 0x6000)

    void
    USBHCDEvents(void *pvData)
    {
        ...
        switch(pEventInfo->ulEvent)
        {
            //
            // New mouse detected.
            //
            case USB_EVENT_CONNECTED:
            {
                //
                // See if this is a HID Mouse.
                //

          // <---- comment these lines
    //            if((USBHCDDevClass(pEventInfo->ulInstance, 0) == USB_CLASS_HID) &&
    //               (USBHCDDevProtocol(pEventInfo->ulInstance, 0) ==
    //               USB_HID_PROTOCOL_MOUSE))

          // <---- add these lines
                //
                // See if this is the touch panel.
                //
                if( USBHCDDevVIDPID(pEventInfo->ulInstance) == TOUCH_VIDPID )
                {



    2. It appears that the critical information for success is found in the device descriptor so I used the debugger to stop in the HIDDriverOpen(...) and the device information appears to be garbage


    At the timing when USBHCDEvents( USB_EVENT_CONNECTED ) comes,
    the stack has already read out Device descriptor and Config descriptor set.
    Also the stack has issued Set_Configuration to the device.
    On my side, the host stack works well for a full-speed vendor-specific HID device.


    Place a break point in UpdateMouseState() (usbhhidmoouse.c),
    and see a break-point hit when you fiddle the touch panel.

    Tsuneo

  • Fantastic! Thanks for sticking with this Tsuneo... And your patience, both are very much appreciated. I tried your original code suggestions and they worked flawlessly.
  • Aside from the practical code examples one of the keys to the solution seems to be parsing the descriptors. Can you tell me how your new the values hidden within the input descriptor?
  • Can you tell me how your new the values hidden within the input descriptor?



    Just interpret the report descriptor.

    Usage Page (Generic Desktop)     05 01  
    Usage (Mouse)                    09 02  
    Collection (Application)         A1 01  
        Usage (Pointer)              09 01  
        Collection (Physical)        A1 00  

            Usage (Undefined)        09 00    // padding (bit 0-5)
            Logical Minimum (0)      15 00  
            Logical Maximum (1)      25 01  
            Report Count (6)         95 06  
            Report Size (1)          75 01  
            Input (Cnst,Ary,Abs)     81 01

            Usage Page (Button)      05 09    // button (bit 6,7)
            Usage Minimum (Button 1) 19 01  
            Usage Maximum (Button 3) 29 03  
            Logical Minimum (0)      15 00  
            Logical Maximum (1)      25 01  
            Report Count (2)         95 02  
            Report Size (1)          75 01  
            Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02

            Usage Page (Generic Desktop) 05 01  // X, Y axes
            Usage (X)                09 30  
            Usage (Y)                09 31  
            Logical Minimum (0)      15 00  
            Logical Maximum (1023)   26 FF 03  
            Physical Minimum (128)   36 80 00  
            Physical Maximum (32767) 46 FF 7F  
            Report Size (16)         75 10  
            Report Count (2)         95 02  
            Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02  

            Usage (Undefined)        09 00    // Featrue report, (for calibration?)
            Logical Minimum (0)      15 00  
            Logical Maximum (255)    26 FF 00  
            Report Size (8)          75 08  
            Report Count (5)         95 05  
            Feature (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) B1 02  

        End Collection               C0  
    End Collection                   C0  



    This report descriptor defines an 5-bytes input report format,

    byte
    offset
    0  buttons (bit 6,7)
    1  X - absolute, 16-bit unsigned integer, LSB first
    3  Y - absolute, 16-bit unsigned integer, LSB first


    Also, it defines a 5-bytes Feature report, too.
    This Feature report should be applied to exchange calibration.

    Anyway, PC driver may ignore the detailed format on the report descriptor (except for the 5 bytes report size). Install the genuine driver of the panel to a PC, and capture the USB traffic of the touch panel. Confirm that the touch panel sends supposed input report or not, when you fiddle the panel.

    Also, run the calibration utility of the panel on the sniffer.
    how to use the feature report for calibration.

    Any sniffer will do, for example,
    USBlyzer (33days free trial) http://www.usblyzer.com/
    USBTrace (15days free trial) http://www.sysnucleus.com/

    Tsuneo