@@ -91,6 +91,15 @@ int usb_desc_config(const USBDescConfig *conf, uint8_t *dest,
size_t len)
dest[0x08] = conf->bMaxPower;
wTotalLength += bLength;
+ /* handle Interface Association Descriptor, if present */
+ if (conf->niad != 0) {
+ rc = usb_desc_iad(conf->iad, dest + wTotalLength, len -
wTotalLength);
+ if (rc < 0) {
+ return rc;
+ }
+ wTotalLength += rc;
+ }
+
count = conf->nif ? conf->nif : conf->bNumInterfaces;
for (i = 0; i < count; i++) {
rc = usb_desc_iface(conf->ifs + i, dest + wTotalLength, len -
wTotalLength);
@@ -105,6 +114,26 @@ int usb_desc_config(const USBDescConfig *conf, uint8_t
*dest, size_t len)
return wTotalLength;
}
+int usb_desc_iad(const USBDescIfaceAssoc *iad, uint8_t *dest, size_t len)
+{
+ uint8_t bLength = 0x08;
+
+ if (len < bLength) {
+ return -1;
+ }
+
+ dest[0x00] = bLength;
+ dest[0x01] = USB_DT_INTERFACE_ASSOC;
+ dest[0x02] = iad->bFirstInterface;
+ dest[0x03] = iad->bInterfaceCount;
+ dest[0x04] = iad->bFunctionClass;
+ dest[0x05] = iad->bFunctionSubClass;
+ dest[0x06] = iad->bFunctionProtocol;
+ dest[0x07] = iad->iFunction;
+
+ return bLength;
+}
+
int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len)
{
uint8_t bLength = 0x09;
@@ -30,10 +30,22 @@ struct USBDescConfig {
uint8_t bmAttributes;
uint8_t bMaxPower;
+ uint8_t niad; /* 0 or 1 for now */
+ const USBDescIfaceAssoc *iad;
+
uint8_t nif;
const USBDescIface *ifs;
};
+struct USBDescIfaceAssoc {
+ uint8_t bFirstInterface;
+ uint8_t bInterfaceCount;
+ uint8_t bFunctionClass;
+ uint8_t bFunctionSubClass;
+ uint8_t bFunctionProtocol;
+ uint8_t iFunction;
+};
+
struct USBDescIface {
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
@@ -75,6 +87,7 @@ int usb_desc_device(const USBDescID *id, const USBDescDevice
*dev,
int usb_desc_device_qualifier(const USBDescDevice *dev,
uint8_t *dest, size_t len);
int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len);
+int usb_desc_iad(const USBDescIfaceAssoc *iad, uint8_t *dest, size_t len);
int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len);
int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len);
int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len);
@@ -211,6 +211,7 @@ static const USBDescDevice desc_device_mouse = {
.iConfiguration = STR_CONFIG_MOUSE,
.bmAttributes = 0xa0,
.bMaxPower = 50,
+ .niad = 0,
.ifs = &desc_iface_mouse,
},
},
@@ -227,6 +228,7 @@ static const USBDescDevice desc_device_tablet = {
.iConfiguration = STR_CONFIG_TABLET,
.bmAttributes = 0xa0,
.bMaxPower = 50,
+ .niad = 0,
.ifs = &desc_iface_tablet,
},
},
@@ -243,6 +245,7 @@ static const USBDescDevice desc_device_keyboard = {
.iConfiguration = STR_CONFIG_KEYBOARD,
.bmAttributes = 0xa0,
.bMaxPower = 50,
+ .niad = 0,
.ifs = &desc_iface_keyboard,
},
},
@@ -119,6 +119,7 @@ static const USBDescDevice desc_device_hub = {
.bNumInterfaces = 1,
.bConfigurationValue = 1,
.bmAttributes = 0xe0,
+ .niad = 0,
.ifs = &desc_iface_hub,
},
},
@@ -124,6 +124,7 @@
#define USB_DT_ENDPOINT 0x05
#define USB_DT_DEVICE_QUALIFIER 0x06
#define USB_DT_OTHER_SPEED_CONFIG 0x07
+#define USB_DT_INTERFACE_ASSOC 0x0B
#define USB_ENDPOINT_XFER_CONTROL 0
#define USB_ENDPOINT_XFER_ISOC 1
@@ -140,6 +141,7 @@ typedef struct USBDesc USBDesc;
typedef struct USBDescID USBDescID;
typedef struct USBDescDevice USBDescDevice;
typedef struct USBDescConfig USBDescConfig;
+typedef struct USBDescIfaceAssoc USBDescIfaceAssoc;
typedef struct USBDescIface USBDescIface;
typedef struct USBDescEndpoint USBDescEndpoint;
typedef struct USBDescOther USBDescOther;