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

LPC2148 usb controller

I use usb controller in Lpc2148. I get example code from keil website in HID class. I need adapt InReport up to 64 byte( InReport[0],InReport[1]....,InReport[64]) for send more data but I donn't good enough in C programming. How can I do? pleas give code. How can I develop application software in the host side. I need Visual Basic 6
thanks you

Parents
  • Class specific request
    In this example, the Output report is supported through EP0 (default EP) using SetReport request. Now we define the dedicated endpoint for OUT. Then, this SetReport( Output ) handler is not used.

    hiduser.c
    
    BOOL HID_SetReport (void) {
      /* ReportID = SetupPacket.wValue.WB.L; */
      switch (SetupPacket.wValue.WB.H) {
        case HID_REPORT_INPUT:
          return (FALSE);          /* Not Supported */
        case HID_REPORT_OUTPUT:
    
    //      OutReport = EP0Buf[0];        // delete three lines
    //      SetOutReport();
    //      break;
          return (FALSE);          /* Not Supported */
    
        case HID_REPORT_FEATURE:
          return (FALSE);          /* Not Supported */
      }
      return (TRUE);
    }
    


    On the host application, WriteFile() is used to send Output report, instead of HidD_SetOutputReport(). See the examples on Axelson's HID page
    http://www.lvr.com/hidpage.htm

    Endpoint handling
    To the EP1 interrupt handler, add the OUT EP1 handler.
    Read out the OUT packet from the USB engine, and store it to OutReport.
    Then, call SetOutReport().
    That is, the Output procedure in HID_SetReport() moves to here.
    Modify SetOutReport() as you like.

    usbuser.c
    
    void USB_EndPoint1 (DWORD event) {
      switch (event) {
        case USB_EVT_IN:
          GetInReport();
          USB_WriteEP(0x81, &InReport, sizeof(InReport));
          break;
    
        case USB_EVT_OUT:
          USB_ReadEP(0x01, &OutReport);
          SetOutReport();
          break;
    
      }
    }
    

    That's all.
    Now, you have symmetric IN and OUT endpoints.

    USB endpoint handling is like to UART.
    The interrupt of IN EP means that the packet is sent to the host and the EP is empty; TX empty.
    The interrupt of OUT EP means that a packet is received from the host on the EP; RX loaded.

    In this modification, I showed a method to read or write the EPs in interrupt. However, you don't always need to handle the EPs in interrupt. It's also like to UART TX and RX; UART is handled either in interrupt or polling. The host determines the timing of the endpoint interrupt. However, you may have to follow another timing given by the device side. For example, USB mouse and keyboard send Input report just when the device detects user's action. In this case, handle the endpoint in polling method.

    int InEP_empty = TRUE;
    int OutEP_loaded = FALSE;
    
    void USB_EndPoint1 (DWORD event) {
      switch (event) {
        case USB_EVT_IN:
          InEP_empty = TRUE;
          break;
        case USB_EVT_OUT:
          OutEP_loaded = TRUE;
          break;
      }
    }
    
    void Handle_user_action( void ) {
      if ( InEP_empty ) {
          //
          // fill an input report to InReport here
          //
          USB_WriteEP(0x81, &InReport, sizeof(InReport));
      }
    }
    
    void Handle_next_command( void ) {
      if ( OutEP_loaded ) {
          USB_ReadEP(0x01, &OutReport);
          //
          // handle the command on output report here
          //
      }
    }
    

    You don't need to read out OUT EPs immediately on interrupt. The host retries transfer while the OUT EP is occupied. Then, the device can make the host wait until the device unloads the OUT EP. No data loss. This is the flow control mechanism built-in to USB protocol (NAKing).

    Tsuneo

Reply
  • Class specific request
    In this example, the Output report is supported through EP0 (default EP) using SetReport request. Now we define the dedicated endpoint for OUT. Then, this SetReport( Output ) handler is not used.

    hiduser.c
    
    BOOL HID_SetReport (void) {
      /* ReportID = SetupPacket.wValue.WB.L; */
      switch (SetupPacket.wValue.WB.H) {
        case HID_REPORT_INPUT:
          return (FALSE);          /* Not Supported */
        case HID_REPORT_OUTPUT:
    
    //      OutReport = EP0Buf[0];        // delete three lines
    //      SetOutReport();
    //      break;
          return (FALSE);          /* Not Supported */
    
        case HID_REPORT_FEATURE:
          return (FALSE);          /* Not Supported */
      }
      return (TRUE);
    }
    


    On the host application, WriteFile() is used to send Output report, instead of HidD_SetOutputReport(). See the examples on Axelson's HID page
    http://www.lvr.com/hidpage.htm

    Endpoint handling
    To the EP1 interrupt handler, add the OUT EP1 handler.
    Read out the OUT packet from the USB engine, and store it to OutReport.
    Then, call SetOutReport().
    That is, the Output procedure in HID_SetReport() moves to here.
    Modify SetOutReport() as you like.

    usbuser.c
    
    void USB_EndPoint1 (DWORD event) {
      switch (event) {
        case USB_EVT_IN:
          GetInReport();
          USB_WriteEP(0x81, &InReport, sizeof(InReport));
          break;
    
        case USB_EVT_OUT:
          USB_ReadEP(0x01, &OutReport);
          SetOutReport();
          break;
    
      }
    }
    

    That's all.
    Now, you have symmetric IN and OUT endpoints.

    USB endpoint handling is like to UART.
    The interrupt of IN EP means that the packet is sent to the host and the EP is empty; TX empty.
    The interrupt of OUT EP means that a packet is received from the host on the EP; RX loaded.

    In this modification, I showed a method to read or write the EPs in interrupt. However, you don't always need to handle the EPs in interrupt. It's also like to UART TX and RX; UART is handled either in interrupt or polling. The host determines the timing of the endpoint interrupt. However, you may have to follow another timing given by the device side. For example, USB mouse and keyboard send Input report just when the device detects user's action. In this case, handle the endpoint in polling method.

    int InEP_empty = TRUE;
    int OutEP_loaded = FALSE;
    
    void USB_EndPoint1 (DWORD event) {
      switch (event) {
        case USB_EVT_IN:
          InEP_empty = TRUE;
          break;
        case USB_EVT_OUT:
          OutEP_loaded = TRUE;
          break;
      }
    }
    
    void Handle_user_action( void ) {
      if ( InEP_empty ) {
          //
          // fill an input report to InReport here
          //
          USB_WriteEP(0x81, &InReport, sizeof(InReport));
      }
    }
    
    void Handle_next_command( void ) {
      if ( OutEP_loaded ) {
          USB_ReadEP(0x01, &OutReport);
          //
          // handle the command on output report here
          //
      }
    }
    

    You don't need to read out OUT EPs immediately on interrupt. The host retries transfer while the OUT EP is occupied. Then, the device can make the host wait until the device unloads the OUT EP. No data loss. This is the flow control mechanism built-in to USB protocol (NAKing).

    Tsuneo

Children
  • Aha, I missed to show the modification of interface descriptor.

    /* Interface 0, Alternate Setting 0, HID Class */
      USB_INTERFACE_DESC_SIZE,           /* bLength */
      USB_INTERFACE_DESCRIPTOR_TYPE,     /* bDescriptorType */
      0x00,                              /* bInterfaceNumber */
      0x00,                              /* bAlternateSetting */
      0x02,                              /* bNumEndpoints */
      USB_DEVICE_CLASS_HUMAN_INTERFACE,  /* bInterfaceClass */
      HID_SUBCLASS_NONE,                 /* bInterfaceSubClass */
      HID_PROTOCOL_NONE,                 /* bInterfaceProtocol */
      0x5C,                              /* iInterface */
    

    Tsuneo

  • Okay, according to your directions I now have both in and out 64byte transfer. So far it looks fine. I'm going to involve it in one of my projects.

    I just wonder if I did the DESCRIPTOR WORK as expected:

    /* HID Report Descriptor */
    const BYTE HID_ReportDescriptor[] = { HID_UsagePageVendor(0x00),

    HID_Usage(0x01),

    HID_Collection(HID_Application),

    HID_UsagePage(HID_USAGE_PAGE_BUTTON),

    HID_UsageMin(1),

    HID_UsageMax(3),

    HID_LogicalMin(0),

    HID_LogicalMax(1),

    HID_ReportCount(INREPORT_SIZE),

    HID_ReportSize(8),

    HID_Input(HID_Data | HID_Variable | HID_Absolute),

    HID_UsagePage(HID_USAGE_PAGE_LED),

    HID_Usage(HID_USAGE_LED_GENERIC_INDICATOR),

    HID_LogicalMin(0),

    HID_LogicalMax(1),

    HID_ReportCount(INREPORT_SIZE),

    HID_ReportSize(8),

    // HID_ReportCount(8),

    // HID_ReportSize(1),

    HID_Output(HID_Data | HID_Variable | HID_Absolute),

    HID_EndCollection,
    };

    Thank you for helping.

    Aqua

  • I recommend you this simplified report descriptor (same as the report desc in my above (21-Nov-2007 17:02) post))

    const BYTE HID_ReportDescriptor[] = {
      HID_UsagePageVendor( 0x00                                   ),
      HID_Usage(           0x01                                   ),
      HID_Collection(      HID_Application                        ),
        HID_LogicalMin(    0                                      ),
        HID_LogicalMaxS(   0xFF                                   ),
        HID_ReportSize(    8                                      ),  // bits
        HID_ReportCount(   INREPORT_SIZE                          ),  // bytes
        HID_Usage(         0x01                                   ),
        HID_Input(         HID_Data | HID_Variable | HID_Absolute ),
        HID_ReportCount(   OUTREPORT_SIZE                         ),  // bytes
        HID_Usage(         0x01                                   ),
        HID_Output(        HID_Data | HID_Variable | HID_Absolute ),
      HID_EndCollection,
    };
    

    You'll find the detailed (maybe too detailed :-) ) definition of the report descriptor here.
    "Device Class Definition for HID 1.11" - HID spec
    www.usb.org/.../HID1_11.pdf
    6.2.2 Report Descriptor (HID1_11.pdf ver1.11 p23)

    You can confirm your report descriptor using this tool.
    "HID Descriptor Tool" on USB.org
    www.usb.org/.../dt2_4.zip

    If you aren't implementing a specific HID device like mouse and keyboard, however, above simplified report descriptor is enough.



    Ummm.. In above posts, I didn't write about USB_Configure_Event() (usbuser.c) as the initialization of USB routines. But I won't write elaborate long post in this forum any more, because of the weird SPAM filter. You'll find me in these fora. See you in these fora again. Bye!!

    LPC2000
    tech.groups.yahoo.com/.../

    USB-IF Developers
    " href= "http://www.cygnal.org/scripts/Ultimate.cgi?action=intro">www.cygnal.org/.../Ultimate.cgi

    8052.com
    "
    http://www.keil.com/forum/docs/thread11241.asp

    Tsuneo

  • why did you put both handlers in the same endpoint if endpoints are unidiretional? I mean endpoint 1 will only be called if there's an event IN. Wouldn't you need to chance the EVENT OUT to antoher endpoint?

  • Hello Doug,

    It's because KEIL implementation joins the handler for IN and OUT endpoints into single one. See following excerpt.

    Tsuneo

    usbhw.c
    USB_ISR()
    {
      ...
      /* Endpoint's Slow Interrupt */
      if (disr & EP_SLOW_INT) {
    
        while (EP_INT_STAT) {                   /* Endpoint Interrupt Status */
    
          for (n = 0; n < USB_EP_NUM; n++) {    /* Check All Endpoints */
            if (EP_INT_STAT & (1 << n)) {
              m = n >> 1;   // convert physical endpoint number to logical one
    
              EP_INT_CLR = 1 << n;
              while ((DEV_INT_STAT & CDFULL_INT) == 0);
              val = CMD_DATA;
    
              if ((n & 1) == 0) {               /* OUT Endpoint */
                if (n == 0) {                   /* Control OUT Endpoint */
                  if (val & EP_SEL_STP) {       /* Setup Packet */
                    if (USB_P_EP[0]) {
                      USB_P_EP[0](USB_EVT_SETUP);
                      continue;
                    }
                  }
                }
                if (USB_P_EP[m]) {
                  USB_P_EP[m](USB_EVT_OUT); // the same handler is called for IN and OUT
                }
              } else {                          /* IN Endpoint */
                if (USB_P_EP[m]) {
                  USB_P_EP[m](USB_EVT_IN);
                }
              }
            }
          }
        }
      }
    
    Endpoint handler function table - just 16 for 32 endpoints
    usbuser.c
    #define P_EP(n) ((USB_EP_EVENT & (1 << (n))) ? USB_EndPoint##n : NULL)
    
    /* USB Endpoint Events Callback Pointers */
    void (* const USB_P_EP[16]) (DWORD event) = {
      P_EP(0),
      P_EP(1),
      P_EP(2),
      P_EP(3),
      P_EP(4),
      P_EP(5),
      P_EP(6),
      P_EP(7),
      P_EP(8),
      P_EP(9),
      P_EP(10),
      P_EP(11),
      P_EP(12),
      P_EP(13),
      P_EP(14),
      P_EP(15),
    };
    

  • Thanks, do you know any software I can use to debug the usb? I've followed the steps you've posted but haven't got any luck yet, I'm not sure what could be the cause of this.. if you could give me a hand that would be nice :)
    thanks in advance

  • Check the enumeration step on the USB bus.
    Do you have a hardware USB bus analyzer?
    If you don't have any one, download this software sniffer and 'evaluate' it :-)

    Commercial, 1-month eval:
    SourceUSB http://www.sourcequest.com/

    What is the last request on the bus?
    - If the last request fails (usually, followed by bus reset), the problem lies on the request handler on the firmware.
    - If the last request succeeds, and it is one of Get_Descriptor, the problem lies on the descriptor.

    In this way, narrow down the problem, first.

    To check the integrity of the HID report descriptor, this tool is helpful.

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

    Tsuneo

  • This post to SiLabs forum shows a typical enumeration process of vendor-specific HID.

    "Difference on HID enumeration on Win, Linux and Mac"
    www.cygnal.org/.../001325.html

    Tsuneo

  • Hi Tsuneo
    I've downloaded the software and the last thing on the bus was a "GET DESCRIPTOR FROM INTERFACE" after that it turns to "BULK OR INTERRUPT TRANSFER" but it always appear one "Sucess" and the next report is "Not Supported". I've also checked your post on how winxp sp2 enumeration process should go and mine isnt really like that it has some similarities. Now in your last post you said that if the last thing on bus was "GET DESCRIPTOR FROM INTERFACE" the problem should be on the descriptor however I'm not so sure what to look for since I've followed your instructions.
    Doug.

  • "GET DESCRIPTOR FROM INTERFACE"

    I suppose you mean Get_Descriptor( Configuration ).
    Interface descriptor is not directly accessed by Get_Descriptor request.

    When USB device receives Get_Descriptor( Configuration ), it returns full configuration set, ie. configuration / interface / HID / endpoints descriptors.

    Can you post the configuration descriptor set?

    Tsuneo

  • Hi, sure here it is :)
    const BYTE USB_ConfigDescriptor[] = {
    /* Configuration 1 */ USB_CONFIGUARTION_DESC_SIZE, /* bLength */

    USB_CONFIGURATION_DESCRIPTOR_TYPE, /*bDescriptorType */ WBVAL( /* wTotalLength */ USB_CONFIGUARTION_DESC_SIZE + USB_INTERFACE_DESC_SIZE + HID_DESC_SIZE + USB_ENDPOINT_DESC_SIZE + USB_ENDPOINT_DESC_SIZE ), 0x01, /* bNumInterfaces */ 0x01, /* bConfigurationValue */ 0x00, /* iConfiguration */ USB_CONFIG_BUS_POWERED /*|*/ /* bmAttributes */
    /*USB_CONFIG_REMOTE_WAKEUP*/, USB_CONFIG_POWER_MA(100), /* bMaxPower */
    /* Interface 0, Alternate Setting 0, HID Class */ USB_INTERFACE_DESC_SIZE, /* bLength */ USB_INTERFACE_DESCRIPTOR_TYPE,/* bDescriptorType */ 0x00, /* bInterfaceNumber */ 0x00, /* bAlternateSetting */ 0x02, /* bNumEndpoints */ USB_DEVICE_CLASS_HUMAN_INTERFACE,/* bInterfaceClass */ HID_SUBCLASS_NONE, /* bInterfaceSubClass */ HID_PROTOCOL_NONE, /* bInterfaceProtocol */ 0x5C, /* iInterface */
    /* HID Class Descriptor */
    /* HID_DESC_OFFSET = 0x0012 */ HID_DESC_SIZE, /* bLength */ HID_HID_DESCRIPTOR_TYPE, /* bDescriptorType */ WBVAL(0x0100), /* 1.00 */ /* bcdHID */ 0x00, /* bCountryCode */ 0x01, /* bNumDescriptors */ HID_REPORT_DESCRIPTOR_TYPE, /* bDescriptorType */ WBVAL(HID_REPORT_DESC_SIZE), /* wDescriptorLength */
    /* Endpoint, HID Interrupt In */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_IN(1), /* bEndpointAddress */ USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ WBVAL(0x0040), /* wMaxPacketSize */ 0x20, /* 32ms */ /* bInterval */
    /* Endpoint, HID Interrupt Out */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_OUT(1), /* bEndpointAddress */ USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ WBVAL(0x0040), /*wMaxPacketSize // = 64 0x20, /* 32ms */ /* bInterval */
    /* Terminator */ 0 /* bLength */
    };

  • Ok, I think this looks better

    const BYTE USB_ConfigDescriptor[] = {

    /* Configuration 1 */

    USB_CONFIGUARTION_DESC_SIZE, /* bLength */

    USB_CONFIGURATION_DESCRIPTOR_TYPE, /*DescriptorType */

    WBVAL( /* wTotalLength */

    USB_CONFIGUARTION_DESC_SIZE +

    USB_INTERFACE_DESC_SIZE +

    HID_DESC_SIZE +

    USB_ENDPOINT_DESC_SIZE +

    USB_ENDPOINT_DESC_SIZE ), 0x01, /* bNumInterfaces */

    0x01, /* bConfigurationValue */

    0x00, /* iConfiguration */

    USB_CONFIG_BUS_POWERED /*|*/ /* bmAttributes */

    /*USB_CONFIG_REMOTE_WAKEUP*/, USB_CONFIG_POWER_MA(100), /* bMaxPower */

    /* Interface 0, Alternate Setting 0, HID Class */

    USB_INTERFACE_DESC_SIZE, /* bLength */

    USB_INTERFACE_DESCRIPTOR_TYPE, /*bDescriptorType */

    0x00, /* bInterfaceNumber */

    0x00, /* bAlternateSetting */

    0x02, /* bNumEndpoints */

    USB_DEVICE_CLASS_HUMAN_INTERFACE,/* bInterfaceClass */

    HID_SUBCLASS_NONE, /* bInterfaceSubClass */

    HID_PROTOCOL_NONE, /* bInterfaceProtocol */ 0x5C, /* iInterface */
    /* HID Class Descriptor */

    /* HID_DESC_OFFSET = 0x0012 */

    HID_DESC_SIZE, /* bLength */

    HID_HID_DESCRIPTOR_TYPE, /* bDescriptorType */

    WBVAL(0x0100), /* 1.00 */ /* bcdHID */

    0x00, /* bCountryCode */

    0x01, /* bNumDescriptors */

    HID_REPORT_DESCRIPTOR_TYPE, /* bDescriptorType */

    WBVAL(HID_REPORT_DESC_SIZE),/* wDescriptorLength */

    /* Endpoint, HID Interrupt In */ USB_ENDPOINT_DESC_SIZE, /* bLength */

    USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */

    USB_ENDPOINT_IN(1), /* bEndpointAddress */

    USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */

    WBVAL(0x0040), /* wMaxPacketSize */

    0x20, /* 32ms */ /* bInterval */

    /* Endpoint, HID Interrupt Out */

    USB_ENDPOINT_DESC_SIZE, /* bLength */

    USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */

    USB_ENDPOINT_OUT(1), /* bEndpointAddress */

    USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */

    WBVAL(0x0040), /* wMaxPacketSize */ // = 64

    0x20, /* 32ms */ /* bInterval */

    /* Terminator */

    0 /* bLength */
    };
    Doug

  • How about using approporiate code formatting, as per the instructions above the text input window ?

    const BYTE USB_ConfigDescriptor[] = {
    
    /* Configuration 1 */
    
    USB_CONFIGUARTION_DESC_SIZE, /* bLength */
    
    USB_CONFIGURATION_DESCRIPTOR_TYPE, /*DescriptorType */
    
    WBVAL( /* wTotalLength */
    
    USB_CONFIGUARTION_DESC_SIZE +
    
    USB_INTERFACE_DESC_SIZE +
    
    HID_DESC_SIZE +
    
    USB_ENDPOINT_DESC_SIZE +
    
    USB_ENDPOINT_DESC_SIZE ), 0x01, /* bNumInterfaces */
    
    0x01, /* bConfigurationValue */
    
    0x00, /* iConfiguration */
    
    USB_CONFIG_BUS_POWERED /*|*/ /* bmAttributes */
    
    /*USB_CONFIG_REMOTE_WAKEUP*/, USB_CONFIG_POWER_MA(100), /* bMaxPower */
    
    /* Interface 0, Alternate Setting 0, HID Class */
    
    USB_INTERFACE_DESC_SIZE, /* bLength */
    
    USB_INTERFACE_DESCRIPTOR_TYPE, /*bDescriptorType */
    
    0x00, /* bInterfaceNumber */
    
    0x00, /* bAlternateSetting */
    
    0x02, /* bNumEndpoints */
    
    USB_DEVICE_CLASS_HUMAN_INTERFACE,/* bInterfaceClass */
    
    HID_SUBCLASS_NONE, /* bInterfaceSubClass */
    
    HID_PROTOCOL_NONE, /* bInterfaceProtocol */ 0x5C, /* iInterface */
    /* HID Class Descriptor */
    
    /* HID_DESC_OFFSET = 0x0012 */
    
    HID_DESC_SIZE, /* bLength */
    
    HID_HID_DESCRIPTOR_TYPE, /* bDescriptorType */
    
    WBVAL(0x0100), /* 1.00 */ /* bcdHID */
    
    0x00, /* bCountryCode */
    
    0x01, /* bNumDescriptors */
    
    HID_REPORT_DESCRIPTOR_TYPE, /* bDescriptorType */
    
    WBVAL(HID_REPORT_DESC_SIZE),/* wDescriptorLength */
    
    /* Endpoint, HID Interrupt In */ USB_ENDPOINT_DESC_SIZE, /* bLength */
    
    USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
    
    USB_ENDPOINT_IN(1), /* bEndpointAddress */
    
    USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */
    
    WBVAL(0x0040), /* wMaxPacketSize */
    
    0x20, /* 32ms */ /* bInterval */
    
    /* Endpoint, HID Interrupt Out */
    
    USB_ENDPOINT_DESC_SIZE, /* bLength */
    
    USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
    
    USB_ENDPOINT_OUT(1), /* bEndpointAddress */
    
    USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */
    
    WBVAL(0x0040), /* wMaxPacketSize */ // = 64
    
    0x20, /* 32ms */ /* bInterval */
    
    /* Terminator */
    
    0 /* bLength */
    };
    

  • Yeah I suppose thats better I didnt noticed that :) thanks

  • Your Configuration descriptor set is fine.
    I had jumped to wrong conclusion...
    OK, I reconsider on your previous post.

    "the last thing on the bus was a "GET DESCRIPTOR FROM INTERFACE"

    Humm.. then isn't it Get_Descriptor( HID_REPORT )?

    bmRequestType: 0x81   (IN from interface)
    bRequest     : 0x06   (GetDescriptor)
    wValue       : 0x2200 (HID REport, report ID = 0)
    wIndex       : 0x0000 (interface 0)
    

    "after that it turns to "BULK OR INTERRUPT TRANSFER" but it always appear one "Sucess" and the next report is "Not Supported".

    Is it the first Input report? What is the direction of the transfer?
    If so, the enumeration finishes successfully.

    What do you mean "Not Supported"?

    Tsuneo