[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 04/18] usb: add support for "grouped" interfaces and
From: |
Gerd Hoffmann |
Subject: |
[Qemu-devel] [PATCH 04/18] usb: add support for "grouped" interfaces and the Interface Association Descriptor |
Date: |
Mon, 23 May 2011 11:43:25 +0200 |
From: Brad Hards <address@hidden>
This is used for some devices that have multiple interfaces that form a logic
device. An example is Video Class, which has a Control interface and a
Streaming interface. There can be additional interfaces on the same (physical)
devices (e.g. a microphone), and Interface Association Descriptor handles this
case.
Signed-off-by: Brad Hards <address@hidden>
Signed-off-by: Gerd Hoffmann <address@hidden>
---
hw/usb-desc.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
hw/usb-desc.h | 20 ++++++++++++++++++++
hw/usb.h | 1 +
3 files changed, 68 insertions(+), 0 deletions(-)
diff --git a/hw/usb-desc.c b/hw/usb-desc.c
index a784155..8367c45 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -91,6 +91,18 @@ int usb_desc_config(const USBDescConfig *conf, uint8_t
*dest, size_t len)
dest[0x08] = conf->bMaxPower;
wTotalLength += bLength;
+ /* handle grouped interfaces if any*/
+ for (i = 0; i < conf->nif_groups; i++) {
+ rc = usb_desc_iface_group(&(conf->if_groups[i]),
+ dest + wTotalLength,
+ len - wTotalLength);
+ if (rc < 0) {
+ return rc;
+ }
+ wTotalLength += rc;
+ }
+
+ /* handle normal (ungrouped / no IAD) interfaces if any */
for (i = 0; i < conf->nif; i++) {
rc = usb_desc_iface(conf->ifs + i, dest + wTotalLength, len -
wTotalLength);
if (rc < 0) {
@@ -104,6 +116,41 @@ int usb_desc_config(const USBDescConfig *conf, uint8_t
*dest, size_t len)
return wTotalLength;
}
+int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest,
+ size_t len)
+{
+ int pos = 0;
+ int i = 0;
+
+ /* handle interface association descriptor */
+ 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;
+ pos += bLength;
+
+ /* handle associated interfaces in this group */
+ for (i = 0; i < iad->nif; i++) {
+ int rc = usb_desc_iface(&(iad->ifs[i]), dest + pos, len - pos);
+ if (rc < 0) {
+ return rc;
+ }
+ pos += rc;
+ }
+
+ return pos;
+}
+
int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len)
{
uint8_t bLength = 0x09;
diff --git a/hw/usb-desc.h b/hw/usb-desc.h
index ac734ab..a612515 100644
--- a/hw/usb-desc.h
+++ b/hw/usb-desc.h
@@ -30,6 +30,24 @@ struct USBDescConfig {
uint8_t bmAttributes;
uint8_t bMaxPower;
+ /* grouped interfaces */
+ uint8_t nif_groups;
+ const USBDescIfaceAssoc *if_groups;
+
+ /* "normal" interfaces */
+ uint8_t nif;
+ const USBDescIface *ifs;
+};
+
+/* conceptually an Interface Association Descriptor, and releated interfaces */
+struct USBDescIfaceAssoc {
+ uint8_t bFirstInterface;
+ uint8_t bInterfaceCount;
+ uint8_t bFunctionClass;
+ uint8_t bFunctionSubClass;
+ uint8_t bFunctionProtocol;
+ uint8_t iFunction;
+
uint8_t nif;
const USBDescIface *ifs;
};
@@ -75,6 +93,8 @@ 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_iface_group(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);
diff --git a/hw/usb.h b/hw/usb.h
index ca06bf8..e0961ac 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -141,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;
--
1.7.1
- [Qemu-devel] [PATCH 02/18] usb: update config descriptors to identify number of interfaces, (continued)
- [Qemu-devel] [PATCH 02/18] usb: update config descriptors to identify number of interfaces, Gerd Hoffmann, 2011/05/23
- [Qemu-devel] [PATCH 06/18] usb: Pass the packet to the device's handle_control callback, Gerd Hoffmann, 2011/05/23
- [Qemu-devel] [PATCH 14/18] usb-storage: don't call usb_packet_complete twice, Gerd Hoffmann, 2011/05/23
- [Qemu-devel] [PATCH 01/18] usb: Add Interface Association Descriptor descriptor type, Gerd Hoffmann, 2011/05/23
- [Qemu-devel] [PATCH 03/18] usb: remove fallback to bNumInterfaces if no .nif, Gerd Hoffmann, 2011/05/23
- [Qemu-devel] [PATCH 07/18] usb-linux: use usb_generic_handle_packet(), Gerd Hoffmann, 2011/05/23
- [Qemu-devel] [PATCH 08/18] usb-linux: fix device path aka physical port handling, Gerd Hoffmann, 2011/05/23
- [Qemu-devel] [PATCH 15/18] usb: add usb_handle_packet, Gerd Hoffmann, 2011/05/23
- [Qemu-devel] [PATCH 12/18] usb-linux: split large xfers, Gerd Hoffmann, 2011/05/23
- [Qemu-devel] [PATCH 16/18] usb: keep track of packet owner., Gerd Hoffmann, 2011/05/23
- [Qemu-devel] [PATCH 04/18] usb: add support for "grouped" interfaces and the Interface Association Descriptor,
Gerd Hoffmann <=
- [Qemu-devel] [PATCH 17/18] usb: move cancel callback to USBDeviceInfo, Gerd Hoffmann, 2011/05/23
[Qemu-devel] [PATCH 18/18] usb: add ehci adapter, Gerd Hoffmann, 2011/05/23
Re: [Qemu-devel] [PULL] usb patch queue: initial usb 2.0 support., Gerd Hoffmann, 2011/05/26