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

How to switch device between MSC and HID?

Hi there!
I'm working on a device that's currently setup as a USB mass storage device. Now I've added HID functionality as per the following descriptor:

/* USB Configuration Descriptor */
/*   All Descriptors (Configuration, Interface, Endpoint, Class, Vendor) */
const U8 USB_ConfigDescriptor[] = {
/* Configuration 1 */
  USB_CONFIGUARTION_DESC_SIZE,       /* bLength */
  USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
  WBVAL(                             /* wTotalLength */
    1*USB_CONFIGUARTION_DESC_SIZE +
    2*USB_INTERFACE_DESC_SIZE     +
      HID_DESC_SIZE               +
    4*USB_ENDPOINT_DESC_SIZE
  ),
  0x02,                              /* bNumInterfaces */
  0x01,                              /* bConfigurationValue: 0x01 is used to select this configuration */
  0x04,                              /* iConfiguration */
  USB_CONFIG_BUS_POWERED             /* bmAttributes */
  USB_CONFIG_POWER_MA(100),          /* bMaxPower, device power consumption is 100 mA */

/* 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 */
  0x05,                              /* 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, EP1 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, EP1 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 */
  0x20,          /* 32ms */          /* bInterval */

/* Interface 1, Alternate Setting 0, MSC Class */
  USB_INTERFACE_DESC_SIZE,           /* bLength */
  USB_INTERFACE_DESCRIPTOR_TYPE,     /* bDescriptorType */
  0x01,                              /* bInterfaceNumber */
  0x00,                              /* bAlternateSetting */
  0x02,                              /* bNumEndpoints */
  USB_DEVICE_CLASS_STORAGE,          /* bInterfaceClass */
  MSC_SUBCLASS_SCSI,                 /* bInterfaceSubClass */
  MSC_PROTOCOL_BULK_ONLY,            /* bInterfaceProtocol */
  0x07,                              /* iInterface */

/* Endpoint, EP2 Bulk IN */
  USB_ENDPOINT_DESC_SIZE,            /* bLength */
  USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
  USB_ENDPOINT_IN(2),                /* bEndpointAddress */
  USB_ENDPOINT_TYPE_BULK,            /* bmAttributes */
  WBVAL(0x0040),                     /* wMaxPacketSize */
  0x00,                              /* bInterval: ignore for Bulk transfer */

/* Endpoint, EP2 Bulk OUT */
  USB_ENDPOINT_DESC_SIZE,            /* bLength */
  USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
  USB_ENDPOINT_OUT(2),               /* bEndpointAddress */
  USB_ENDPOINT_TYPE_BULK,            /* bmAttributes */
  WBVAL(0x0040),                     /* wMaxPacketSize */
  0x00,                              /* bInterval: ignore for Bulk transfer */

/* Terminator */
  0                                  /* bLength */
};

This works fine. However, I'd rather be able to turn the MSC on and off at runtime. Now I don't know what's the best way to do so. Looks two me like my options are: use two configurations or use two alternate interfaces...

<continued in the next post>

Parents
  • SORRY, TYPO ABOVE: in reality, the comma after "USB_CONFIG_BUS_POWERED" is not missing.

    So for the alternate interfaces I'm using the following descriptor:

    const U8 USB_ConfigDescriptor[] = {
    /* Configuration 1 */
      USB_CONFIGUARTION_DESC_SIZE,       /* bLength */
      USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
      WBVAL(                             /* wTotalLength */
        1*USB_CONFIGUARTION_DESC_SIZE +
        2*USB_INTERFACE_DESC_SIZE     +
          HID_DESC_SIZE               +
        4*USB_ENDPOINT_DESC_SIZE
      ),
      0x01,                              /* bNumInterfaces */
      0x01,                              /* bConfigurationValue: 0x01 is used to select this configuration */
      0x04,                              /* iConfiguration */
      USB_CONFIG_BUS_POWERED,            /* bmAttributes */
      USB_CONFIG_POWER_MA(100),          /* bMaxPower, device power consumption is 100 mA */
    
    /* 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 */
      0x05,                              /* 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, EP1 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, EP1 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 */
      0x20,          /* 32ms */          /* bInterval */
    
    /* Interface 0, Alternate Setting 1, MSC Class */
      USB_INTERFACE_DESC_SIZE,           /* bLength */
      USB_INTERFACE_DESCRIPTOR_TYPE,     /* bDescriptorType */
      0x00,                              /* bInterfaceNumber */
      0x01,                              /* bAlternateSetting */
      0x02,                              /* bNumEndpoints */
      USB_DEVICE_CLASS_STORAGE,          /* bInterfaceClass */
      MSC_SUBCLASS_SCSI,                 /* bInterfaceSubClass */
      MSC_PROTOCOL_BULK_ONLY,            /* bInterfaceProtocol */
      0x07,                              /* iInterface */
    
    /* Endpoint, EP2 Bulk IN */
      USB_ENDPOINT_DESC_SIZE,            /* bLength */
      USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
      USB_ENDPOINT_IN(2),                /* bEndpointAddress */
      USB_ENDPOINT_TYPE_BULK,            /* bmAttributes */
      WBVAL(0x0040),                     /* wMaxPacketSize */
      0x00,                              /* bInterval: ignore for Bulk transfer */
    
    /* Endpoint, EP2 Bulk OUT */
      USB_ENDPOINT_DESC_SIZE,            /* bLength */
      USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
      USB_ENDPOINT_OUT(2),               /* bEndpointAddress */
      USB_ENDPOINT_TYPE_BULK,            /* bmAttributes */
      WBVAL(0x0040),                     /* wMaxPacketSize */
      0x00,                              /* bInterval: ignore for Bulk transfer */
    
    /* Terminator */
      0                                  /* bLength */
    };
    


    This doesn't work as in: my PC host application (the famous HIDClient.exe) freezes after selecting the HID - enumeration is fine, though.

    What would be the best way to create a runtime-configurable USB device? In the best case by switching between its modes on the device itself (as opposed to sending some USB command). After all, am I better off using different configurations?

    Best wishes,
    Peter

Reply
  • SORRY, TYPO ABOVE: in reality, the comma after "USB_CONFIG_BUS_POWERED" is not missing.

    So for the alternate interfaces I'm using the following descriptor:

    const U8 USB_ConfigDescriptor[] = {
    /* Configuration 1 */
      USB_CONFIGUARTION_DESC_SIZE,       /* bLength */
      USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
      WBVAL(                             /* wTotalLength */
        1*USB_CONFIGUARTION_DESC_SIZE +
        2*USB_INTERFACE_DESC_SIZE     +
          HID_DESC_SIZE               +
        4*USB_ENDPOINT_DESC_SIZE
      ),
      0x01,                              /* bNumInterfaces */
      0x01,                              /* bConfigurationValue: 0x01 is used to select this configuration */
      0x04,                              /* iConfiguration */
      USB_CONFIG_BUS_POWERED,            /* bmAttributes */
      USB_CONFIG_POWER_MA(100),          /* bMaxPower, device power consumption is 100 mA */
    
    /* 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 */
      0x05,                              /* 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, EP1 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, EP1 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 */
      0x20,          /* 32ms */          /* bInterval */
    
    /* Interface 0, Alternate Setting 1, MSC Class */
      USB_INTERFACE_DESC_SIZE,           /* bLength */
      USB_INTERFACE_DESCRIPTOR_TYPE,     /* bDescriptorType */
      0x00,                              /* bInterfaceNumber */
      0x01,                              /* bAlternateSetting */
      0x02,                              /* bNumEndpoints */
      USB_DEVICE_CLASS_STORAGE,          /* bInterfaceClass */
      MSC_SUBCLASS_SCSI,                 /* bInterfaceSubClass */
      MSC_PROTOCOL_BULK_ONLY,            /* bInterfaceProtocol */
      0x07,                              /* iInterface */
    
    /* Endpoint, EP2 Bulk IN */
      USB_ENDPOINT_DESC_SIZE,            /* bLength */
      USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
      USB_ENDPOINT_IN(2),                /* bEndpointAddress */
      USB_ENDPOINT_TYPE_BULK,            /* bmAttributes */
      WBVAL(0x0040),                     /* wMaxPacketSize */
      0x00,                              /* bInterval: ignore for Bulk transfer */
    
    /* Endpoint, EP2 Bulk OUT */
      USB_ENDPOINT_DESC_SIZE,            /* bLength */
      USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
      USB_ENDPOINT_OUT(2),               /* bEndpointAddress */
      USB_ENDPOINT_TYPE_BULK,            /* bmAttributes */
      WBVAL(0x0040),                     /* wMaxPacketSize */
      0x00,                              /* bInterval: ignore for Bulk transfer */
    
    /* Terminator */
      0                                  /* bLength */
    };
    


    This doesn't work as in: my PC host application (the famous HIDClient.exe) freezes after selecting the HID - enumeration is fine, though.

    What would be the best way to create a runtime-configurable USB device? In the best case by switching between its modes on the device itself (as opposed to sending some USB command). After all, am I better off using different configurations?

    Best wishes,
    Peter

Children