Skip to content

Commit

Permalink
usb: host-linux: Ignore parsing errors of the device descriptors
Browse files Browse the repository at this point in the history
The Linux is more tolerant here as well: Just stop parsing the device
descriptors when an error is detected but do not reset what was found
so far. This allows to run buggy devices with partially invalid
descriptors.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
  • Loading branch information
jan-kiszka authored and kraxel committed Nov 16, 2012
1 parent c06c68c commit 537e8f1
Showing 1 changed file with 11 additions and 20 deletions.
31 changes: 11 additions & 20 deletions hw/usb/host-linux.c
Expand Up @@ -135,7 +135,7 @@ static int parse_filter(const char *spec, struct USBAutoFilter *f);
static void usb_host_auto_check(void *unused);
static int usb_host_read_file(char *line, size_t line_size,
const char *device_file, const char *device_name);
static int usb_linux_update_endp_table(USBHostDevice *s);
static void usb_linux_update_endp_table(USBHostDevice *s);

static int usb_host_usbfs_type(USBHostDevice *s, USBPacket *p)
{
Expand Down Expand Up @@ -1132,8 +1132,7 @@ static void usb_host_handle_control(USBDevice *dev, USBPacket *p,
p->status = USB_RET_ASYNC;
}

/* returns 1 on problem encountered or 0 for success */
static int usb_linux_update_endp_table(USBHostDevice *s)
static void usb_linux_update_endp_table(USBHostDevice *s)
{
static const char *tname[] = {
[USB_ENDPOINT_XFER_CONTROL] = "control",
Expand All @@ -1159,23 +1158,23 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
if (d->bLength < 2) {
trace_usb_host_parse_error(s->bus_num, s->addr,
"descriptor too short");
goto error;
return;
}
if (i + d->bLength > s->descr_len) {
trace_usb_host_parse_error(s->bus_num, s->addr,
"descriptor too long");
goto error;
return;
}
switch (d->bDescriptorType) {
case 0:
trace_usb_host_parse_error(s->bus_num, s->addr,
"invalid descriptor type");
goto error;
return;
case USB_DT_DEVICE:
if (d->bLength < 0x12) {
trace_usb_host_parse_error(s->bus_num, s->addr,
"device descriptor too short");
goto error;
return;
}
v = (d->u.device.idVendor_hi << 8) | d->u.device.idVendor_lo;
p = (d->u.device.idProduct_hi << 8) | d->u.device.idProduct_lo;
Expand All @@ -1185,7 +1184,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
if (d->bLength < 0x09) {
trace_usb_host_parse_error(s->bus_num, s->addr,
"config descriptor too short");
goto error;
return;
}
configuration = d->u.config.bConfigurationValue;
active = (configuration == s->dev.configuration);
Expand All @@ -1196,7 +1195,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
if (d->bLength < 0x09) {
trace_usb_host_parse_error(s->bus_num, s->addr,
"interface descriptor too short");
goto error;
return;
}
interface = d->u.interface.bInterfaceNumber;
altsetting = d->u.interface.bAlternateSetting;
Expand All @@ -1209,15 +1208,15 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
if (d->bLength < 0x07) {
trace_usb_host_parse_error(s->bus_num, s->addr,
"endpoint descriptor too short");
goto error;
return;
}
devep = d->u.endpoint.bEndpointAddress;
pid = (devep & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT;
ep = devep & 0xf;
if (ep == 0) {
trace_usb_host_parse_error(s->bus_num, s->addr,
"invalid endpoint address");
goto error;
return;
}

type = d->u.endpoint.bmAttributes & 0x3;
Expand Down Expand Up @@ -1250,11 +1249,6 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
break;
}
}
return 0;

error:
usb_ep_reset(&s->dev);
return 1;
}

/*
Expand Down Expand Up @@ -1341,10 +1335,7 @@ static int usb_host_open(USBHostDevice *dev, int bus_num,
}

usb_ep_init(&dev->dev);
ret = usb_linux_update_endp_table(dev);
if (ret) {
goto fail;
}
usb_linux_update_endp_table(dev);

if (speed == -1) {
struct usbdevfs_connectinfo ci;
Expand Down

0 comments on commit 537e8f1

Please sign in to comment.