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>
This commit is contained in:
parent
3ee886c5ba
commit
eb7700bb99
82
usb-linux.c
82
usb-linux.c
@ -407,8 +407,11 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
|
|||||||
int interface, nb_interfaces;
|
int interface, nb_interfaces;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
if (configuration == 0) /* address state - ignore */
|
if (configuration == 0) { /* address state - ignore */
|
||||||
|
dev->ninterfaces = 0;
|
||||||
|
dev->configuration = 0;
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
DPRINTF("husb: claiming interfaces. config %d\n", configuration);
|
DPRINTF("husb: claiming interfaces. config %d\n", configuration);
|
||||||
|
|
||||||
@ -433,7 +436,7 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
|
|||||||
|
|
||||||
DPRINTF("husb: config #%d need %d\n", dev->descr[i + 5], configuration);
|
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];
|
configuration = dev->descr[i + 5];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -513,7 +516,7 @@ static void usb_host_handle_reset(USBDevice *dev)
|
|||||||
|
|
||||||
ioctl(s->fd, USBDEVFS_RESET);
|
ioctl(s->fd, USBDEVFS_RESET);
|
||||||
|
|
||||||
usb_host_claim_interfaces(s, s->configuration);
|
usb_host_claim_interfaces(s, 0);
|
||||||
usb_linux_update_endp_table(s);
|
usb_linux_update_endp_table(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -835,6 +838,7 @@ static int usb_host_set_config(USBHostDevice *s, int config)
|
|||||||
return ctrl_error();
|
return ctrl_error();
|
||||||
}
|
}
|
||||||
usb_host_claim_interfaces(s, config);
|
usb_host_claim_interfaces(s, config);
|
||||||
|
usb_linux_update_endp_table(s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -941,51 +945,6 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
|
|||||||
return USB_RET_ASYNC;
|
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,
|
static uint8_t usb_linux_get_alt_setting(USBHostDevice *s,
|
||||||
uint8_t configuration, uint8_t interface)
|
uint8_t configuration, uint8_t interface)
|
||||||
{
|
{
|
||||||
@ -1031,16 +990,16 @@ usbdevfs:
|
|||||||
static int usb_linux_update_endp_table(USBHostDevice *s)
|
static int usb_linux_update_endp_table(USBHostDevice *s)
|
||||||
{
|
{
|
||||||
uint8_t *descriptors;
|
uint8_t *descriptors;
|
||||||
uint8_t devep, type, configuration, alt_interface;
|
uint8_t devep, type, alt_interface;
|
||||||
int interface, length, i;
|
int interface, length, i;
|
||||||
|
|
||||||
for (i = 0; i < MAX_ENDPOINTS; i++)
|
for (i = 0; i < MAX_ENDPOINTS; i++)
|
||||||
s->endp_table[i].type = INVALID_EP_TYPE;
|
s->endp_table[i].type = INVALID_EP_TYPE;
|
||||||
|
|
||||||
i = usb_linux_get_configuration(s);
|
if (s->configuration == 0) {
|
||||||
if (i < 0)
|
/* not configured yet -- leave all endpoints disabled */
|
||||||
return 1;
|
return 0;
|
||||||
configuration = i;
|
}
|
||||||
|
|
||||||
/* get the desired configuration, interface, and endpoint descriptors
|
/* get the desired configuration, interface, and endpoint descriptors
|
||||||
* from device description */
|
* from device description */
|
||||||
@ -1049,8 +1008,9 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
|
|||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
if (descriptors[i + 1] != USB_DT_CONFIG ||
|
if (descriptors[i + 1] != USB_DT_CONFIG ||
|
||||||
descriptors[i + 5] != configuration) {
|
descriptors[i + 5] != s->configuration) {
|
||||||
DPRINTF("invalid descriptor data - configuration\n");
|
fprintf(stderr, "invalid descriptor data - configuration %d\n",
|
||||||
|
s->configuration);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
i += descriptors[i];
|
i += descriptors[i];
|
||||||
@ -1064,7 +1024,8 @@ 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, configuration, interface);
|
alt_interface = usb_linux_get_alt_setting(s, s->configuration,
|
||||||
|
interface);
|
||||||
|
|
||||||
/* the current interface descriptor is the active interface
|
/* the current interface descriptor is the active interface
|
||||||
* and has endpoints */
|
* and has endpoints */
|
||||||
@ -1204,13 +1165,8 @@ static int usb_host_open(USBHostDevice *dev, int bus_num,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/* start unconfigured -- we'll wait for the guest to set a configuration */
|
||||||
* Initial configuration is -1 which makes us claim first
|
if (!usb_host_claim_interfaces(dev, 0)) {
|
||||||
* 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)) {
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user