summaryrefslogtreecommitdiff
path: root/debian/patches/0100-usb3-corrections.patch
blob: eb2d5a5dbc713530486726566b4cc999ecf5a275 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
Description: work around USB3/xhci problems in Linux.
 Backport from upstream. 
Author: m. allan noah <kitno455 at gmail dot com>
Origin: upstream,http://anonscm.debian.org/cgit/sane/sane-backends.git/commit/?id=014b45d920f1fb630e1a31bb01f1da02ea2a6a87
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=738592
Forwarded: not-needed
Last-Update: 2014-12-26
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
Index: trunk/sanei/sanei_usb.c
===================================================================
--- trunk.orig/sanei/sanei_usb.c
+++ trunk/sanei/sanei_usb.c
@@ -154,6 +154,7 @@ typedef struct
   SANE_Int control_in_ep;
   SANE_Int control_out_ep;
   SANE_Int interface_nr;
+  SANE_Int alt_setting;
   SANE_Int missing;
 #ifdef HAVE_LIBUSB
   usb_dev_handle *libusb_handle;
@@ -635,6 +636,7 @@ static void usbcall_scan_devices(void)
 	  device.product = pDevDesc->idProduct;
 	  device.method = sanei_usb_method_usbcalls;
 	  device.interface_nr = interface;
+	  device.alt_setting = 0;
 	  DBG (4, "%s: found usbcalls device (0x%04x/0x%04x) as device number %s\n", __func__,
 	       pDevDesc->idVendor, pDevDesc->idProduct,device.devname);
 	  store_device(device);
@@ -821,7 +823,7 @@ static void libusb_scan_devices(void)
 		     "scanner (%d/%d)\n", __func__, dev->descriptor.idVendor,
 		     dev->descriptor.idProduct, interface,
 		     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].
 		       bInterfaceClass : -1);
 	    }
@@ -845,6 +847,7 @@ static void libusb_scan_devices(void)
 	  device.product = dev->descriptor.idProduct;
 	  device.method = sanei_usb_method_libusb;
 	  device.interface_nr = interface;
+	  device.alt_setting = 0;
 	  DBG (4,
 	       "%s: found libusb device (0x%04x/0x%04x) interface "
                "%d  at %s\n", __func__,
@@ -991,7 +994,7 @@ static void libusb_scan_devices(void)
 		 "%s: device 0x%04x/0x%04x, interface %d "
 		 "doesn't look like a scanner (%d/%d)\n", __func__,
 		 vid, pid, interface, desc.bDeviceClass,
-		 (config0->interface[interface].altsetting != 0)
+		 (config0->interface[interface].num_altsetting != 0)
 		 ? config0->interface[interface].altsetting[0].bInterfaceClass : -1);
 	}
 
@@ -1018,6 +1021,7 @@ static void libusb_scan_devices(void)
       device.product = pid;
       device.method = sanei_usb_method_libusb;
       device.interface_nr = interface;
+      device.alt_setting = 0;
       DBG (4,
 	   "%s: found libusb-1.0 device (0x%04x/0x%04x) interface "
 	   "%d at %s\n", __func__,
@@ -2128,22 +2132,24 @@ sanei_usb_close (SANE_Int dn)
   else
 #ifdef HAVE_LIBUSB
     {
-#if 0
-      /* Should only be done in case of a stall */
-      usb_clear_halt (devices[dn].libusb_handle, devices[dn].bulk_in_ep);
-      usb_clear_halt (devices[dn].libusb_handle, devices[dn].bulk_out_ep);
-      usb_clear_halt (devices[dn].libusb_handle, devices[dn].iso_in_ep);
-      /* 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 */
+      /* 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);
+
       usb_release_interface (devices[dn].libusb_handle,
 			     devices[dn].interface_nr);
       usb_close (devices[dn].libusb_handle);
     }
 #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,
 				devices[dn].interface_nr);
       libusb_close (devices[dn].lu_handle);
@@ -2168,7 +2174,6 @@ sanei_usb_set_timeout (SANE_Int timeout)
 SANE_Status
 sanei_usb_clear_halt (SANE_Int dn)
 {
-#ifdef HAVE_LIBUSB
   int ret;
 
   if (dn >= device_number || dn < 0)
@@ -2177,6 +2182,14 @@ sanei_usb_clear_halt (SANE_Int dn)
       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);
   if (ret){
     DBG (1, "sanei_usb_clear_halt: BULK_IN ret=%d\n", ret);
@@ -2189,18 +2202,13 @@ sanei_usb_clear_halt (SANE_Int dn)
     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)
-  int ret;
 
-  if (dn >= device_number || dn < 0)
-    {
-      DBG (1, "sanei_usb_clear_halt: dn >= device number || dn < 0\n");
-      return SANE_STATUS_INVAL;
-    }
+  /* 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 = libusb_clear_halt (devices[dn].lu_handle, devices[dn].bulk_in_ep);
   if (ret){
@@ -3038,6 +3046,8 @@ sanei_usb_set_altinterface (SANE_Int dn,
 
   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 defined(__linux__)
Index: trunk/ChangeLog
===================================================================
--- trunk.orig/ChangeLog
+++ trunk/ChangeLog
@@ -1,3 +1,9 @@
+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.
+
+
 ******  Release of sane-backends 1.0.24. End of code freeze ******
 
 2013-09-30 m. allan noah <kitno455 at gmail dot com>