sanei_usb: Linux USB3/xhci workarounds

add calls to sanei_usb_set_altinterface in sanei_usb_close and
sanei_usb_clear_halt- hopefully work around USB3/xhci problems
in Linux. Also, remove some unused code, and fix debug messages.
merge-requests/1/head
m. allan noah 2014-12-16 10:23:55 -05:00
rodzic 67417622cb
commit 014b45d920
2 zmienionych plików z 38 dodań i 23 usunięć

Wyświetl plik

@ -1,3 +1,8 @@
2014-12-16 m. allan noah <kitno455 at gmail dot com>
* sanei/sanei_usb.c: add calls to sanei_usb_set_altinterface in
sanei_usb_close and sanei_usb_clear_halt- hopefully work around
USB3/xhci problems in Linux.
2014-11-18 Rolf Bensch <rolf at bensch hyphen online dot de> 2014-11-18 Rolf Bensch <rolf at bensch hyphen online dot de>
* backend/pixma_imageclass.c: * backend/pixma_imageclass.c:
- Canon i-SENSYS MF8200C and MF8500C use generation 2 protocols. - Canon i-SENSYS MF8200C and MF8500C use generation 2 protocols.

Wyświetl plik

@ -154,6 +154,7 @@ typedef struct
SANE_Int control_in_ep; SANE_Int control_in_ep;
SANE_Int control_out_ep; SANE_Int control_out_ep;
SANE_Int interface_nr; SANE_Int interface_nr;
SANE_Int alt_setting;
SANE_Int missing; SANE_Int missing;
#ifdef HAVE_LIBUSB #ifdef HAVE_LIBUSB
usb_dev_handle *libusb_handle; usb_dev_handle *libusb_handle;
@ -633,6 +634,7 @@ static void usbcall_scan_devices(void)
device.product = pDevDesc->idProduct; device.product = pDevDesc->idProduct;
device.method = sanei_usb_method_usbcalls; device.method = sanei_usb_method_usbcalls;
device.interface_nr = interface; device.interface_nr = interface;
device.alt_setting = 0;
DBG (4, "%s: found usbcalls device (0x%04x/0x%04x) as device number %s\n", __func__, DBG (4, "%s: found usbcalls device (0x%04x/0x%04x) as device number %s\n", __func__,
pDevDesc->idVendor, pDevDesc->idProduct,device.devname); pDevDesc->idVendor, pDevDesc->idProduct,device.devname);
store_device(device); store_device(device);
@ -819,7 +821,7 @@ static void libusb_scan_devices(void)
"scanner (%d/%d)\n", __func__, dev->descriptor.idVendor, "scanner (%d/%d)\n", __func__, dev->descriptor.idVendor,
dev->descriptor.idProduct, interface, dev->descriptor.idProduct, interface,
dev->descriptor.bDeviceClass, dev->descriptor.bDeviceClass,
dev->config[0].interface[interface].altsetting != 0 dev->config[0].interface[interface].num_altsetting != 0
? dev->config[0].interface[interface].altsetting[0]. ? dev->config[0].interface[interface].altsetting[0].
bInterfaceClass : -1); bInterfaceClass : -1);
} }
@ -843,6 +845,7 @@ static void libusb_scan_devices(void)
device.product = dev->descriptor.idProduct; device.product = dev->descriptor.idProduct;
device.method = sanei_usb_method_libusb; device.method = sanei_usb_method_libusb;
device.interface_nr = interface; device.interface_nr = interface;
device.alt_setting = 0;
DBG (4, DBG (4,
"%s: found libusb device (0x%04x/0x%04x) interface " "%s: found libusb device (0x%04x/0x%04x) interface "
"%d at %s\n", __func__, "%d at %s\n", __func__,
@ -989,7 +992,7 @@ static void libusb_scan_devices(void)
"%s: device 0x%04x/0x%04x, interface %d " "%s: device 0x%04x/0x%04x, interface %d "
"doesn't look like a scanner (%d/%d)\n", __func__, "doesn't look like a scanner (%d/%d)\n", __func__,
vid, pid, interface, desc.bDeviceClass, vid, pid, interface, desc.bDeviceClass,
(config0->interface[interface].altsetting != 0) (config0->interface[interface].num_altsetting != 0)
? config0->interface[interface].altsetting[0].bInterfaceClass : -1); ? config0->interface[interface].altsetting[0].bInterfaceClass : -1);
} }
@ -1016,6 +1019,7 @@ static void libusb_scan_devices(void)
device.product = pid; device.product = pid;
device.method = sanei_usb_method_libusb; device.method = sanei_usb_method_libusb;
device.interface_nr = interface; device.interface_nr = interface;
device.alt_setting = 0;
DBG (4, DBG (4,
"%s: found libusb-1.0 device (0x%04x/0x%04x) interface " "%s: found libusb-1.0 device (0x%04x/0x%04x) interface "
"%d at %s\n", __func__, "%d at %s\n", __func__,
@ -2131,22 +2135,24 @@ sanei_usb_close (SANE_Int dn)
else else
#ifdef HAVE_LIBUSB #ifdef HAVE_LIBUSB
{ {
#if 0 /* This call seems to be required by Linux xhci driver
/* Should only be done in case of a stall */ * even though it should be a no-op. Without it, the
usb_clear_halt (devices[dn].libusb_handle, devices[dn].bulk_in_ep); * host or driver does not reset it's data toggle bit.
usb_clear_halt (devices[dn].libusb_handle, devices[dn].bulk_out_ep); * We intentionally ignore the return val */
usb_clear_halt (devices[dn].libusb_handle, devices[dn].iso_in_ep); sanei_usb_set_altinterface (dn, devices[dn].alt_setting);
/* be careful, we don't know if we are in DATA0 stage now */
usb_resetep (devices[dn].libusb_handle, devices[dn].bulk_in_ep);
usb_resetep (devices[dn].libusb_handle, devices[dn].bulk_out_ep);
usb_resetep (devices[dn].libusb_handle, devices[dn].iso_in_ep);
#endif /* 0 */
usb_release_interface (devices[dn].libusb_handle, usb_release_interface (devices[dn].libusb_handle,
devices[dn].interface_nr); devices[dn].interface_nr);
usb_close (devices[dn].libusb_handle); usb_close (devices[dn].libusb_handle);
} }
#elif defined(HAVE_LIBUSB_1_0) #elif defined(HAVE_LIBUSB_1_0)
{ {
/* This call seems to be required by Linux xhci driver
* even though it should be a no-op. Without it, the
* host or driver does not reset it's data toggle bit.
* We intentionally ignore the return val */
sanei_usb_set_altinterface (dn, devices[dn].alt_setting);
libusb_release_interface (devices[dn].lu_handle, libusb_release_interface (devices[dn].lu_handle,
devices[dn].interface_nr); devices[dn].interface_nr);
libusb_close (devices[dn].lu_handle); libusb_close (devices[dn].lu_handle);
@ -2171,7 +2177,6 @@ sanei_usb_set_timeout (SANE_Int timeout)
SANE_Status SANE_Status
sanei_usb_clear_halt (SANE_Int dn) sanei_usb_clear_halt (SANE_Int dn)
{ {
#ifdef HAVE_LIBUSB
int ret; int ret;
if (dn >= device_number || dn < 0) if (dn >= device_number || dn < 0)
@ -2180,6 +2185,14 @@ sanei_usb_clear_halt (SANE_Int dn)
return SANE_STATUS_INVAL; return SANE_STATUS_INVAL;
} }
#ifdef HAVE_LIBUSB
/* This call seems to be required by Linux xhci driver
* even though it should be a no-op. Without it, the
* host or driver does not send the clear to the device.
* We intentionally ignore the return val */
sanei_usb_set_altinterface (dn, devices[dn].alt_setting);
ret = usb_clear_halt (devices[dn].libusb_handle, devices[dn].bulk_in_ep); ret = usb_clear_halt (devices[dn].libusb_handle, devices[dn].bulk_in_ep);
if (ret){ if (ret){
DBG (1, "sanei_usb_clear_halt: BULK_IN ret=%d\n", ret); DBG (1, "sanei_usb_clear_halt: BULK_IN ret=%d\n", ret);
@ -2192,18 +2205,13 @@ sanei_usb_clear_halt (SANE_Int dn)
return SANE_STATUS_INVAL; return SANE_STATUS_INVAL;
} }
/* be careful, we don't know if we are in DATA0 stage now
ret = usb_resetep (devices[dn].libusb_handle, devices[dn].bulk_in_ep);
ret = usb_resetep (devices[dn].libusb_handle, devices[dn].bulk_out_ep);
*/
#elif defined(HAVE_LIBUSB_1_0) #elif defined(HAVE_LIBUSB_1_0)
int ret;
if (dn >= device_number || dn < 0) /* This call seems to be required by Linux xhci driver
{ * even though it should be a no-op. Without it, the
DBG (1, "sanei_usb_clear_halt: dn >= device number || dn < 0\n"); * host or driver does not send the clear to the device.
return SANE_STATUS_INVAL; * We intentionally ignore the return val */
} sanei_usb_set_altinterface (dn, devices[dn].alt_setting);
ret = libusb_clear_halt (devices[dn].lu_handle, devices[dn].bulk_in_ep); ret = libusb_clear_halt (devices[dn].lu_handle, devices[dn].bulk_in_ep);
if (ret){ if (ret){
@ -3041,6 +3049,8 @@ sanei_usb_set_altinterface (SANE_Int dn, SANE_Int alternate)
DBG (5, "sanei_usb_set_altinterface: alternate = %d\n", alternate); DBG (5, "sanei_usb_set_altinterface: alternate = %d\n", alternate);
devices[dn].alt_setting = alternate;
if (devices[dn].method == sanei_usb_method_scanner_driver) if (devices[dn].method == sanei_usb_method_scanner_driver)
{ {
#if defined(__linux__) #if defined(__linux__)