summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2011-08-30 11:11:29 +0200
committerGerd Hoffmann <kraxel@redhat.com>2012-01-13 10:25:44 +0100
commit65360511a2eeab8b671722df6634dd674cc4a5d6 (patch)
tree4a38c1dd1b525f2700d9458b40c71e83a1728bf9
parent097db4384860b4363364eb531285296f616d89e5 (diff)
downloadqemu-65360511a2eeab8b671722df6634dd674cc4a5d6.zip
usb: track configuration and interface count in USBDevice.
Move fields from USBHostDevice to USBDevice. Add bits to usb-desc.c to fill them for emulated devices too. Also allow to set configuration 0 (== None) for emulated devices. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-rw-r--r--hw/usb-desc.c34
-rw-r--r--hw/usb.h3
-rw-r--r--usb-linux.c21
3 files changed, 38 insertions, 20 deletions
diff --git a/hw/usb-desc.c b/hw/usb-desc.c
index ae2d384bb3..b52561adf8 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -223,6 +223,29 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
/* ------------------------------------------------------------------ */
+static int usb_desc_set_config(USBDevice *dev, int value)
+{
+ int i;
+
+ if (value == 0) {
+ dev->configuration = 0;
+ dev->ninterfaces = 0;
+ dev->config = NULL;
+ } else {
+ for (i = 0; i < dev->device->bNumConfigurations; i++) {
+ if (dev->device->confs[i].bConfigurationValue == value) {
+ dev->configuration = value;
+ dev->ninterfaces = dev->device->confs[i].bNumInterfaces;
+ dev->config = dev->device->confs + i;
+ }
+ }
+ if (i < dev->device->bNumConfigurations) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
static void usb_desc_setdefaults(USBDevice *dev)
{
const USBDesc *desc = dev->info->usb_desc;
@@ -237,7 +260,7 @@ static void usb_desc_setdefaults(USBDevice *dev)
dev->device = desc->high;
break;
}
- dev->config = dev->device->confs;
+ usb_desc_set_config(dev, 0);
}
void usb_desc_init(USBDevice *dev)
@@ -408,7 +431,7 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
int request, int value, int index, int length, uint8_t *data)
{
const USBDesc *desc = dev->info->usb_desc;
- int i, ret = -1;
+ int ret = -1;
assert(desc != NULL);
switch(request) {
@@ -427,12 +450,7 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
ret = 1;
break;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
- for (i = 0; i < dev->device->bNumConfigurations; i++) {
- if (dev->device->confs[i].bConfigurationValue == value) {
- dev->config = dev->device->confs + i;
- ret = 0;
- }
- }
+ ret = usb_desc_set_config(dev, value);
trace_usb_set_config(dev->addr, value, ret);
break;
diff --git a/hw/usb.h b/hw/usb.h
index c6e1870e59..1ef53a102f 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -188,6 +188,9 @@ struct USBDevice {
QLIST_HEAD(, USBDescString) strings;
const USBDescDevice *device;
+
+ int configuration;
+ int ninterfaces;
const USBDescConfig *config;
};
diff --git a/usb-linux.c b/usb-linux.c
index c68e194053..3aaa93bd86 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -106,8 +106,6 @@ typedef struct USBHostDevice {
uint8_t descr[8192];
int descr_len;
- int configuration;
- int ninterfaces;
int closing;
uint32_t iso_urb_count;
Notifier exit;
@@ -547,8 +545,8 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
int ret, i;
if (configuration == 0) { /* address state - ignore */
- dev->ninterfaces = 0;
- dev->configuration = 0;
+ dev->dev.ninterfaces = 0;
+ dev->dev.configuration = 0;
return 1;
}
@@ -606,8 +604,8 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
trace_usb_host_claim_interfaces(dev->bus_num, dev->addr,
nb_interfaces, configuration);
- dev->ninterfaces = nb_interfaces;
- dev->configuration = configuration;
+ dev->dev.ninterfaces = nb_interfaces;
+ dev->dev.configuration = configuration;
return 1;
fail:
@@ -624,7 +622,7 @@ static int usb_host_release_interfaces(USBHostDevice *s)
trace_usb_host_release_interfaces(s->bus_num, s->addr);
- for (i = 0; i < s->ninterfaces; i++) {
+ for (i = 0; i < s->dev.ninterfaces; i++) {
ret = ioctl(s->fd, USBDEVFS_RELEASEINTERFACE, &i);
if (ret < 0) {
perror("USBDEVFS_RELEASEINTERFACE");
@@ -1123,7 +1121,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
s->ep_out[i].type = INVALID_EP_TYPE;
}
- if (s->configuration == 0) {
+ if (s->dev.configuration == 0) {
/* not configured yet -- leave all endpoints disabled */
return 0;
}
@@ -1138,12 +1136,11 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
if (descriptors[i + 1] != USB_DT_CONFIG) {
fprintf(stderr, "invalid descriptor data\n");
return 1;
- } else if (descriptors[i + 5] != s->configuration) {
- DPRINTF("not requested configuration %d\n", s->configuration);
+ } else if (descriptors[i + 5] != s->dev.configuration) {
+ DPRINTF("not requested configuration %d\n", s->dev.configuration);
i += (descriptors[i + 3] << 8) + descriptors[i + 2];
continue;
}
-
i += descriptors[i];
if (descriptors[i + 1] != USB_DT_INTERFACE ||
@@ -1154,7 +1151,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
}
interface = descriptors[i + 2];
- alt_interface = usb_linux_get_alt_setting(s, s->configuration,
+ alt_interface = usb_linux_get_alt_setting(s, s->dev.configuration,
interface);
/* the current interface descriptor is the active interface