usb-host: fix configuration tracking.
It is perfectly fine to leave the usb device in unconfigured state
(USBHostDevice->configuration == 0). Just do that and wait for the
guest to explicitly set a configuration. This is closer to what real
hardware does and it also simplifies the device initialization. There
is no need to figure how the device is configured on the host.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
diff --git a/usb-linux.c b/usb-linux.c
index 36d25d7..a903023 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -407,8 +407,11 @@
int interface, nb_interfaces;
int ret, i;
- if (configuration == 0) /* address state - ignore */
+ if (configuration == 0) { /* address state - ignore */
+ dev->ninterfaces = 0;
+ dev->configuration = 0;
return 1;
+ }
DPRINTF("husb: claiming interfaces. config %d\n", configuration);
@@ -433,7 +436,7 @@
DPRINTF("husb: config #%d need %d\n", dev->descr[i + 5], configuration);
- if (configuration < 0 || configuration == dev->descr[i + 5]) {
+ if (configuration == dev->descr[i + 5]) {
configuration = dev->descr[i + 5];
break;
}
@@ -513,7 +516,7 @@
ioctl(s->fd, USBDEVFS_RESET);
- usb_host_claim_interfaces(s, s->configuration);
+ usb_host_claim_interfaces(s, 0);
usb_linux_update_endp_table(s);
}
@@ -835,6 +838,7 @@
return ctrl_error();
}
usb_host_claim_interfaces(s, config);
+ usb_linux_update_endp_table(s);
return 0;
}
@@ -941,51 +945,6 @@
return USB_RET_ASYNC;
}
-static int usb_linux_get_configuration(USBHostDevice *s)
-{
- uint8_t configuration;
- struct usb_ctrltransfer ct;
- int ret;
-
- if (usb_fs_type == USB_FS_SYS) {
- char device_name[32], line[1024];
- int configuration;
-
- sprintf(device_name, "%d-%s", s->bus_num, s->port);
-
- if (!usb_host_read_file(line, sizeof(line), "bConfigurationValue",
- device_name)) {
- goto usbdevfs;
- }
- if (sscanf(line, "%d", &configuration) != 1) {
- goto usbdevfs;
- }
- return configuration;
- }
-
-usbdevfs:
- ct.bRequestType = USB_DIR_IN;
- ct.bRequest = USB_REQ_GET_CONFIGURATION;
- ct.wValue = 0;
- ct.wIndex = 0;
- ct.wLength = 1;
- ct.data = &configuration;
- ct.timeout = 50;
-
- ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
- if (ret < 0) {
- perror("usb_linux_get_configuration");
- return -1;
- }
-
- /* in address state */
- if (configuration == 0) {
- return -1;
- }
-
- return configuration;
-}
-
static uint8_t usb_linux_get_alt_setting(USBHostDevice *s,
uint8_t configuration, uint8_t interface)
{
@@ -1031,16 +990,16 @@
static int usb_linux_update_endp_table(USBHostDevice *s)
{
uint8_t *descriptors;
- uint8_t devep, type, configuration, alt_interface;
+ uint8_t devep, type, alt_interface;
int interface, length, i;
for (i = 0; i < MAX_ENDPOINTS; i++)
s->endp_table[i].type = INVALID_EP_TYPE;
- i = usb_linux_get_configuration(s);
- if (i < 0)
- return 1;
- configuration = i;
+ if (s->configuration == 0) {
+ /* not configured yet -- leave all endpoints disabled */
+ return 0;
+ }
/* get the desired configuration, interface, and endpoint descriptors
* from device description */
@@ -1049,8 +1008,9 @@
i = 0;
if (descriptors[i + 1] != USB_DT_CONFIG ||
- descriptors[i + 5] != configuration) {
- DPRINTF("invalid descriptor data - configuration\n");
+ descriptors[i + 5] != s->configuration) {
+ fprintf(stderr, "invalid descriptor data - configuration %d\n",
+ s->configuration);
return 1;
}
i += descriptors[i];
@@ -1064,7 +1024,8 @@
}
interface = descriptors[i + 2];
- alt_interface = usb_linux_get_alt_setting(s, configuration, interface);
+ alt_interface = usb_linux_get_alt_setting(s, s->configuration,
+ interface);
/* the current interface descriptor is the active interface
* and has endpoints */
@@ -1204,13 +1165,8 @@
#endif
- /*
- * Initial configuration is -1 which makes us claim first
- * available config. We used to start with 1, which does not
- * always work. I've seen devices where first config starts
- * with 2.
- */
- if (!usb_host_claim_interfaces(dev, -1)) {
+ /* start unconfigured -- we'll wait for the guest to set a configuration */
+ if (!usb_host_claim_interfaces(dev, 0)) {
goto fail;
}