diff options
author | Andrew Kephart <akephart@akephart.org> | 2011-08-21 16:34:13 -0400 |
---|---|---|
committer | Florian Tobias Schandinat <FlorianSchandinat@gmx.de> | 2011-08-24 06:08:49 -0400 |
commit | f2e1fc9d5d12fbc06590ac4987dce6f79d86f1c7 (patch) | |
tree | 07182ddaa42e9daaa3dacb5b7c19728c74768e5f /drivers/video/udlfb.c | |
parent | 58e7c3b00114c48e0879e9fbafd37e0e0c2402cb (diff) |
udlfb: Search config descriptor if not at device level
For at least one DisplayLink device, the vendor-specific information can
be found in the config descriptor instead of as a separate, device-level
descriptor. This patch searches the current interface (of the current
config descriptor) for the DL vendor-specific descriptor.
Signed-off-by: Andrew Kephart <akephart@akephart.org>
Signed-off-by: Bernie Thompson <bernie@plugable.com>
Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Diffstat (limited to 'drivers/video/udlfb.c')
-rw-r--r-- | drivers/video/udlfb.c | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c index fecd2d3543bd..0b77af7bdf1b 100644 --- a/drivers/video/udlfb.c +++ b/drivers/video/udlfb.c | |||
@@ -1479,21 +1479,30 @@ static int dlfb_select_std_channel(struct dlfb_data *dev) | |||
1479 | } | 1479 | } |
1480 | 1480 | ||
1481 | static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev, | 1481 | static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev, |
1482 | struct usb_device *usbdev) | 1482 | struct usb_interface *interface) |
1483 | { | 1483 | { |
1484 | char *desc; | 1484 | char *desc; |
1485 | char *buf; | 1485 | char *buf; |
1486 | char *desc_end; | 1486 | char *desc_end; |
1487 | 1487 | ||
1488 | u8 total_len = 0; | 1488 | int total_len = 0; |
1489 | 1489 | ||
1490 | buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL); | 1490 | buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL); |
1491 | if (!buf) | 1491 | if (!buf) |
1492 | return false; | 1492 | return false; |
1493 | desc = buf; | 1493 | desc = buf; |
1494 | 1494 | ||
1495 | total_len = usb_get_descriptor(usbdev, 0x5f, /* vendor specific */ | 1495 | total_len = usb_get_descriptor(interface_to_usbdev(interface), |
1496 | 0, desc, MAX_VENDOR_DESCRIPTOR_SIZE); | 1496 | 0x5f, /* vendor specific */ |
1497 | 0, desc, MAX_VENDOR_DESCRIPTOR_SIZE); | ||
1498 | |||
1499 | /* if not found, look in configuration descriptor */ | ||
1500 | if (total_len < 0) { | ||
1501 | if (0 == usb_get_extra_descriptor(interface->cur_altsetting, | ||
1502 | 0x5f, &desc)) | ||
1503 | total_len = (int) desc[0]; | ||
1504 | } | ||
1505 | |||
1497 | if (total_len > 5) { | 1506 | if (total_len > 5) { |
1498 | pr_info("vendor descriptor length:%x data:%02x %02x %02x %02x" \ | 1507 | pr_info("vendor descriptor length:%x data:%02x %02x %02x %02x" \ |
1499 | "%02x %02x %02x %02x %02x %02x %02x\n", | 1508 | "%02x %02x %02x %02x %02x %02x %02x\n", |
@@ -1534,6 +1543,8 @@ static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev, | |||
1534 | } | 1543 | } |
1535 | desc += length; | 1544 | desc += length; |
1536 | } | 1545 | } |
1546 | } else { | ||
1547 | pr_info("vendor descriptor not available (%d)\n", total_len); | ||
1537 | } | 1548 | } |
1538 | 1549 | ||
1539 | goto success; | 1550 | goto success; |
@@ -1583,7 +1594,7 @@ static int dlfb_usb_probe(struct usb_interface *interface, | |||
1583 | 1594 | ||
1584 | dev->sku_pixel_limit = 2048 * 1152; /* default to maximum */ | 1595 | dev->sku_pixel_limit = 2048 * 1152; /* default to maximum */ |
1585 | 1596 | ||
1586 | if (!dlfb_parse_vendor_descriptor(dev, usbdev)) { | 1597 | if (!dlfb_parse_vendor_descriptor(dev, interface)) { |
1587 | pr_err("firmware not recognized. Assume incompatible device\n"); | 1598 | pr_err("firmware not recognized. Assume incompatible device\n"); |
1588 | goto error; | 1599 | goto error; |
1589 | } | 1600 | } |