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>
This commit is contained in:
Gerd Hoffmann 2011-08-30 11:11:29 +02:00
parent 097db43848
commit 65360511a2
3 changed files with 38 additions and 20 deletions

View File

@ -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) static void usb_desc_setdefaults(USBDevice *dev)
{ {
const USBDesc *desc = dev->info->usb_desc; const USBDesc *desc = dev->info->usb_desc;
@ -237,7 +260,7 @@ static void usb_desc_setdefaults(USBDevice *dev)
dev->device = desc->high; dev->device = desc->high;
break; break;
} }
dev->config = dev->device->confs; usb_desc_set_config(dev, 0);
} }
void usb_desc_init(USBDevice *dev) 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) int request, int value, int index, int length, uint8_t *data)
{ {
const USBDesc *desc = dev->info->usb_desc; const USBDesc *desc = dev->info->usb_desc;
int i, ret = -1; int ret = -1;
assert(desc != NULL); assert(desc != NULL);
switch(request) { switch(request) {
@ -427,12 +450,7 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
ret = 1; ret = 1;
break; break;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
for (i = 0; i < dev->device->bNumConfigurations; i++) { ret = usb_desc_set_config(dev, value);
if (dev->device->confs[i].bConfigurationValue == value) {
dev->config = dev->device->confs + i;
ret = 0;
}
}
trace_usb_set_config(dev->addr, value, ret); trace_usb_set_config(dev->addr, value, ret);
break; break;

View File

@ -188,6 +188,9 @@ struct USBDevice {
QLIST_HEAD(, USBDescString) strings; QLIST_HEAD(, USBDescString) strings;
const USBDescDevice *device; const USBDescDevice *device;
int configuration;
int ninterfaces;
const USBDescConfig *config; const USBDescConfig *config;
}; };

View File

@ -106,8 +106,6 @@ typedef struct USBHostDevice {
uint8_t descr[8192]; uint8_t descr[8192];
int descr_len; int descr_len;
int configuration;
int ninterfaces;
int closing; int closing;
uint32_t iso_urb_count; uint32_t iso_urb_count;
Notifier exit; Notifier exit;
@ -547,8 +545,8 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
int ret, i; int ret, i;
if (configuration == 0) { /* address state - ignore */ if (configuration == 0) { /* address state - ignore */
dev->ninterfaces = 0; dev->dev.ninterfaces = 0;
dev->configuration = 0; dev->dev.configuration = 0;
return 1; 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, trace_usb_host_claim_interfaces(dev->bus_num, dev->addr,
nb_interfaces, configuration); nb_interfaces, configuration);
dev->ninterfaces = nb_interfaces; dev->dev.ninterfaces = nb_interfaces;
dev->configuration = configuration; dev->dev.configuration = configuration;
return 1; return 1;
fail: fail:
@ -624,7 +622,7 @@ static int usb_host_release_interfaces(USBHostDevice *s)
trace_usb_host_release_interfaces(s->bus_num, s->addr); 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); ret = ioctl(s->fd, USBDEVFS_RELEASEINTERFACE, &i);
if (ret < 0) { if (ret < 0) {
perror("USBDEVFS_RELEASEINTERFACE"); perror("USBDEVFS_RELEASEINTERFACE");
@ -1123,7 +1121,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
s->ep_out[i].type = INVALID_EP_TYPE; s->ep_out[i].type = INVALID_EP_TYPE;
} }
if (s->configuration == 0) { if (s->dev.configuration == 0) {
/* not configured yet -- leave all endpoints disabled */ /* not configured yet -- leave all endpoints disabled */
return 0; return 0;
} }
@ -1138,12 +1136,11 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
if (descriptors[i + 1] != USB_DT_CONFIG) { if (descriptors[i + 1] != USB_DT_CONFIG) {
fprintf(stderr, "invalid descriptor data\n"); fprintf(stderr, "invalid descriptor data\n");
return 1; return 1;
} else if (descriptors[i + 5] != s->configuration) { } else if (descriptors[i + 5] != s->dev.configuration) {
DPRINTF("not requested configuration %d\n", s->configuration); DPRINTF("not requested configuration %d\n", s->dev.configuration);
i += (descriptors[i + 3] << 8) + descriptors[i + 2]; i += (descriptors[i + 3] << 8) + descriptors[i + 2];
continue; continue;
} }
i += descriptors[i]; i += descriptors[i];
if (descriptors[i + 1] != USB_DT_INTERFACE || if (descriptors[i + 1] != USB_DT_INTERFACE ||
@ -1154,7 +1151,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
} }
interface = descriptors[i + 2]; 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); interface);
/* the current interface descriptor is the active interface /* the current interface descriptor is the active interface