diff options
Diffstat (limited to 'drivers/usb')
98 files changed, 9559 insertions, 4589 deletions
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index a61d4433a989..d79cd218a551 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile | |||
@@ -9,6 +9,7 @@ obj-$(CONFIG_USB) += core/ | |||
9 | obj-$(CONFIG_USB_MON) += mon/ | 9 | obj-$(CONFIG_USB_MON) += mon/ |
10 | 10 | ||
11 | obj-$(CONFIG_USB_EHCI_HCD) += host/ | 11 | obj-$(CONFIG_USB_EHCI_HCD) += host/ |
12 | obj-$(CONFIG_USB_ISP116X_HCD) += host/ | ||
12 | obj-$(CONFIG_USB_OHCI_HCD) += host/ | 13 | obj-$(CONFIG_USB_OHCI_HCD) += host/ |
13 | obj-$(CONFIG_USB_UHCI_HCD) += host/ | 14 | obj-$(CONFIG_USB_UHCI_HCD) += host/ |
14 | obj-$(CONFIG_USB_SL811_HCD) += host/ | 15 | obj-$(CONFIG_USB_SL811_HCD) += host/ |
@@ -31,6 +32,7 @@ obj-$(CONFIG_USB_MOUSE) += input/ | |||
31 | obj-$(CONFIG_USB_MTOUCH) += input/ | 32 | obj-$(CONFIG_USB_MTOUCH) += input/ |
32 | obj-$(CONFIG_USB_POWERMATE) += input/ | 33 | obj-$(CONFIG_USB_POWERMATE) += input/ |
33 | obj-$(CONFIG_USB_WACOM) += input/ | 34 | obj-$(CONFIG_USB_WACOM) += input/ |
35 | obj-$(CONFIG_USB_ACECAD) += input/ | ||
34 | obj-$(CONFIG_USB_XPAD) += input/ | 36 | obj-$(CONFIG_USB_XPAD) += input/ |
35 | 37 | ||
36 | obj-$(CONFIG_USB_DABUSB) += media/ | 38 | obj-$(CONFIG_USB_DABUSB) += media/ |
diff --git a/drivers/usb/atm/Kconfig b/drivers/usb/atm/Kconfig index 0d9f5379b8cf..f429862e0974 100644 --- a/drivers/usb/atm/Kconfig +++ b/drivers/usb/atm/Kconfig | |||
@@ -1,30 +1,60 @@ | |||
1 | # | 1 | # |
2 | # USB ATM driver configuration | 2 | # USB/ATM DSL configuration |
3 | # | 3 | # |
4 | comment "USB ATM/DSL drivers" | 4 | |
5 | menu "USB DSL modem support" | ||
5 | depends on USB | 6 | depends on USB |
6 | 7 | ||
7 | config USB_ATM | 8 | config USB_ATM |
8 | tristate "Generic USB ATM/DSL core I/O support" | 9 | tristate "USB DSL modem support" |
9 | depends on USB && ATM | 10 | depends on USB && ATM |
10 | select CRC32 | 11 | select CRC32 |
11 | default n | 12 | default n |
12 | help | 13 | help |
13 | This provides a library which is used for packet I/O by USB DSL | 14 | Say Y here if you want to connect a USB Digital Subscriber Line (DSL) |
14 | modems, such as the SpeedTouch driver below. | 15 | modem to your computer's USB port. You will then need to choose your |
16 | modem from the list below. | ||
15 | 17 | ||
16 | To compile this driver as a module, choose M here: the | 18 | To compile this driver as a module, choose M here: the |
17 | module will be called usb_atm. | 19 | module will be called usbatm. |
18 | 20 | ||
19 | config USB_SPEEDTOUCH | 21 | config USB_SPEEDTOUCH |
20 | tristate "Alcatel Speedtouch USB support" | 22 | tristate "Speedtouch USB support" |
21 | depends on USB && ATM | 23 | depends on USB_ATM |
22 | select USB_ATM | 24 | select FW_LOADER |
23 | help | 25 | help |
24 | Say Y here if you have an Alcatel SpeedTouch USB or SpeedTouch 330 | 26 | Say Y here if you have an SpeedTouch USB or SpeedTouch 330 |
25 | modem. In order to use your modem you will need to install the | 27 | modem. In order to use your modem you will need to install the |
26 | two parts of the firmware, extracted by the user space tools; see | 28 | two parts of the firmware, extracted by the user space tools; see |
27 | <http://www.linux-usb.org/SpeedTouch/> for details. | 29 | <http://www.linux-usb.org/SpeedTouch/> for details. |
28 | 30 | ||
29 | To compile this driver as a module, choose M here: the | 31 | To compile this driver as a module, choose M here: the |
30 | module will be called speedtch. | 32 | module will be called speedtch. |
33 | |||
34 | config USB_CXACRU | ||
35 | tristate "Conexant AccessRunner USB support" | ||
36 | depends on USB_ATM | ||
37 | select FW_LOADER | ||
38 | help | ||
39 | Say Y here if you have an ADSL USB modem based on the Conexant | ||
40 | AccessRunner chipset. In order to use your modem you will need to | ||
41 | install the firmware, extracted by the user space tools; see | ||
42 | <http://accessrunner.sourceforge.net/> for details. | ||
43 | |||
44 | To compile this driver as a module, choose M here: the | ||
45 | module will be called cxacru. | ||
46 | |||
47 | config USB_XUSBATM | ||
48 | tristate "Other USB DSL modem support" | ||
49 | depends on USB_ATM | ||
50 | help | ||
51 | Say Y here if you have a DSL USB modem not explicitly supported by | ||
52 | another USB DSL drivers. In order to use your modem you will need to | ||
53 | pass the vendor ID, product ID, and endpoint numbers for transmission | ||
54 | and reception as module parameters. You may need to initialize the | ||
55 | the modem using a user space utility (a firmware loader for example). | ||
56 | |||
57 | To compile this driver as a module, choose M here: the | ||
58 | module will be called xusbatm. | ||
59 | |||
60 | endmenu | ||
diff --git a/drivers/usb/atm/Makefile b/drivers/usb/atm/Makefile index 9213b8b97587..751f297be2ef 100644 --- a/drivers/usb/atm/Makefile +++ b/drivers/usb/atm/Makefile | |||
@@ -1,7 +1,8 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the rest of the USB drivers | 2 | # Makefile for USB ATM/xDSL drivers |
3 | # (the ones that don't fit into any other categories) | ||
4 | # | 3 | # |
5 | 4 | ||
6 | obj-$(CONFIG_USB_ATM) += usb_atm.o | 5 | obj-$(CONFIG_USB_CXACRU) += cxacru.o |
7 | obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o | 6 | obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o |
7 | obj-$(CONFIG_USB_ATM) += usbatm.o | ||
8 | obj-$(CONFIG_USB_XUSBATM) += xusbatm.o | ||
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c new file mode 100644 index 000000000000..cbd4a7d25d0b --- /dev/null +++ b/drivers/usb/atm/cxacru.c | |||
@@ -0,0 +1,878 @@ | |||
1 | /****************************************************************************** | ||
2 | * cxacru.c - driver for USB ADSL modems based on | ||
3 | * Conexant AccessRunner chipset | ||
4 | * | ||
5 | * Copyright (C) 2004 David Woodhouse, Duncan Sands, Roman Kagan | ||
6 | * Copyright (C) 2005 Duncan Sands, Roman Kagan (rkagan % mail ! ru) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
20 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | * | ||
22 | ******************************************************************************/ | ||
23 | |||
24 | /* | ||
25 | * Credit is due for Josep Comas, who created the original patch to speedtch.c | ||
26 | * to support the different padding used by the AccessRunner (now generalized | ||
27 | * into usbatm), and the userspace firmware loading utility. | ||
28 | */ | ||
29 | |||
30 | #include <linux/module.h> | ||
31 | #include <linux/moduleparam.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/timer.h> | ||
34 | #include <linux/errno.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/init.h> | ||
37 | #include <linux/device.h> /* FIXME: linux/firmware.h should include it itself */ | ||
38 | #include <linux/firmware.h> | ||
39 | |||
40 | #include "usbatm.h" | ||
41 | |||
42 | #define DRIVER_AUTHOR "Roman Kagan, David Woodhouse, Duncan Sands" | ||
43 | #define DRIVER_VERSION "0.2" | ||
44 | #define DRIVER_DESC "Conexant AccessRunner ADSL USB modem driver" | ||
45 | |||
46 | static const char cxacru_driver_name[] = "cxacru"; | ||
47 | |||
48 | #define CXACRU_EP_CMD 0x01 /* Bulk/interrupt in/out */ | ||
49 | #define CXACRU_EP_DATA 0x02 /* Bulk in/out */ | ||
50 | |||
51 | #define CMD_PACKET_SIZE 64 /* Should be maxpacket(ep)? */ | ||
52 | |||
53 | /* Addresses */ | ||
54 | #define PLLFCLK_ADDR 0x00350068 | ||
55 | #define PLLBCLK_ADDR 0x0035006c | ||
56 | #define SDRAMEN_ADDR 0x00350010 | ||
57 | #define FW_ADDR 0x00801000 | ||
58 | #define BR_ADDR 0x00180600 | ||
59 | #define SIG_ADDR 0x00180500 | ||
60 | #define BR_STACK_ADDR 0x00187f10 | ||
61 | |||
62 | /* Values */ | ||
63 | #define SDRAM_ENA 0x1 | ||
64 | |||
65 | #define CMD_TIMEOUT 2000 /* msecs */ | ||
66 | #define POLL_INTERVAL 5000 /* msecs */ | ||
67 | |||
68 | /* commands for interaction with the modem through the control channel before | ||
69 | * firmware is loaded */ | ||
70 | enum cxacru_fw_request { | ||
71 | FW_CMD_ERR, | ||
72 | FW_GET_VER, | ||
73 | FW_READ_MEM, | ||
74 | FW_WRITE_MEM, | ||
75 | FW_RMW_MEM, | ||
76 | FW_CHECKSUM_MEM, | ||
77 | FW_GOTO_MEM, | ||
78 | }; | ||
79 | |||
80 | /* commands for interaction with the modem through the control channel once | ||
81 | * firmware is loaded */ | ||
82 | enum cxacru_cm_request { | ||
83 | CM_REQUEST_UNDEFINED = 0x80, | ||
84 | CM_REQUEST_TEST, | ||
85 | CM_REQUEST_CHIP_GET_MAC_ADDRESS, | ||
86 | CM_REQUEST_CHIP_GET_DP_VERSIONS, | ||
87 | CM_REQUEST_CHIP_ADSL_LINE_START, | ||
88 | CM_REQUEST_CHIP_ADSL_LINE_STOP, | ||
89 | CM_REQUEST_CHIP_ADSL_LINE_GET_STATUS, | ||
90 | CM_REQUEST_CHIP_ADSL_LINE_GET_SPEED, | ||
91 | CM_REQUEST_CARD_INFO_GET, | ||
92 | CM_REQUEST_CARD_DATA_GET, | ||
93 | CM_REQUEST_CARD_DATA_SET, | ||
94 | CM_REQUEST_COMMAND_HW_IO, | ||
95 | CM_REQUEST_INTERFACE_HW_IO, | ||
96 | CM_REQUEST_CARD_SERIAL_DATA_PATH_GET, | ||
97 | CM_REQUEST_CARD_SERIAL_DATA_PATH_SET, | ||
98 | CM_REQUEST_CARD_CONTROLLER_VERSION_GET, | ||
99 | CM_REQUEST_CARD_GET_STATUS, | ||
100 | CM_REQUEST_CARD_GET_MAC_ADDRESS, | ||
101 | CM_REQUEST_CARD_GET_DATA_LINK_STATUS, | ||
102 | CM_REQUEST_MAX, | ||
103 | }; | ||
104 | |||
105 | /* reply codes to the commands above */ | ||
106 | enum cxacru_cm_status { | ||
107 | CM_STATUS_UNDEFINED, | ||
108 | CM_STATUS_SUCCESS, | ||
109 | CM_STATUS_ERROR, | ||
110 | CM_STATUS_UNSUPPORTED, | ||
111 | CM_STATUS_UNIMPLEMENTED, | ||
112 | CM_STATUS_PARAMETER_ERROR, | ||
113 | CM_STATUS_DBG_LOOPBACK, | ||
114 | CM_STATUS_MAX, | ||
115 | }; | ||
116 | |||
117 | /* indices into CARD_INFO_GET return array */ | ||
118 | enum cxacru_info_idx { | ||
119 | CXINF_DOWNSTREAM_RATE, | ||
120 | CXINF_UPSTREAM_RATE, | ||
121 | CXINF_LINK_STATUS, | ||
122 | CXINF_LINE_STATUS, | ||
123 | CXINF_MAC_ADDRESS_HIGH, | ||
124 | CXINF_MAC_ADDRESS_LOW, | ||
125 | CXINF_UPSTREAM_SNR_MARGIN, | ||
126 | CXINF_DOWNSTREAM_SNR_MARGIN, | ||
127 | CXINF_UPSTREAM_ATTENUATION, | ||
128 | CXINF_DOWNSTREAM_ATTENUATION, | ||
129 | CXINF_TRANSMITTER_POWER, | ||
130 | CXINF_UPSTREAM_BITS_PER_FRAME, | ||
131 | CXINF_DOWNSTREAM_BITS_PER_FRAME, | ||
132 | CXINF_STARTUP_ATTEMPTS, | ||
133 | CXINF_UPSTREAM_CRC_ERRORS, | ||
134 | CXINF_DOWNSTREAM_CRC_ERRORS, | ||
135 | CXINF_UPSTREAM_FEC_ERRORS, | ||
136 | CXINF_DOWNSTREAM_FEC_ERRORS, | ||
137 | CXINF_UPSTREAM_HEC_ERRORS, | ||
138 | CXINF_DOWNSTREAM_HEC_ERRORS, | ||
139 | CXINF_LINE_STARTABLE, | ||
140 | CXINF_MODULATION, | ||
141 | CXINF_ADSL_HEADEND, | ||
142 | CXINF_ADSL_HEADEND_ENVIRONMENT, | ||
143 | CXINF_CONTROLLER_VERSION, | ||
144 | /* dunno what the missing two mean */ | ||
145 | CXINF_MAX = 0x1c, | ||
146 | }; | ||
147 | |||
148 | struct cxacru_modem_type { | ||
149 | u32 pll_f_clk; | ||
150 | u32 pll_b_clk; | ||
151 | int boot_rom_patch; | ||
152 | }; | ||
153 | |||
154 | struct cxacru_data { | ||
155 | struct usbatm_data *usbatm; | ||
156 | |||
157 | const struct cxacru_modem_type *modem_type; | ||
158 | |||
159 | int line_status; | ||
160 | struct work_struct poll_work; | ||
161 | |||
162 | /* contol handles */ | ||
163 | struct semaphore cm_serialize; | ||
164 | u8 *rcv_buf; | ||
165 | u8 *snd_buf; | ||
166 | struct urb *rcv_urb; | ||
167 | struct urb *snd_urb; | ||
168 | struct completion rcv_done; | ||
169 | struct completion snd_done; | ||
170 | }; | ||
171 | |||
172 | /* the following three functions are stolen from drivers/usb/core/message.c */ | ||
173 | static void cxacru_blocking_completion(struct urb *urb, struct pt_regs *regs) | ||
174 | { | ||
175 | complete((struct completion *)urb->context); | ||
176 | } | ||
177 | |||
178 | static void cxacru_timeout_kill(unsigned long data) | ||
179 | { | ||
180 | usb_unlink_urb((struct urb *) data); | ||
181 | } | ||
182 | |||
183 | static int cxacru_start_wait_urb(struct urb *urb, struct completion *done, | ||
184 | int* actual_length) | ||
185 | { | ||
186 | struct timer_list timer; | ||
187 | int status; | ||
188 | |||
189 | init_timer(&timer); | ||
190 | timer.expires = jiffies + msecs_to_jiffies(CMD_TIMEOUT); | ||
191 | timer.data = (unsigned long) urb; | ||
192 | timer.function = cxacru_timeout_kill; | ||
193 | add_timer(&timer); | ||
194 | wait_for_completion(done); | ||
195 | status = urb->status; | ||
196 | if (status == -ECONNRESET) | ||
197 | status = -ETIMEDOUT; | ||
198 | del_timer_sync(&timer); | ||
199 | |||
200 | if (actual_length) | ||
201 | *actual_length = urb->actual_length; | ||
202 | return status; | ||
203 | } | ||
204 | |||
205 | static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm, | ||
206 | u8 *wdata, int wsize, u8 *rdata, int rsize) | ||
207 | { | ||
208 | int ret, actlen; | ||
209 | int offb, offd; | ||
210 | const int stride = CMD_PACKET_SIZE - 4; | ||
211 | u8 *wbuf = instance->snd_buf; | ||
212 | u8 *rbuf = instance->rcv_buf; | ||
213 | int wbuflen = ((wsize - 1) / stride + 1) * CMD_PACKET_SIZE; | ||
214 | int rbuflen = ((rsize - 1) / stride + 1) * CMD_PACKET_SIZE; | ||
215 | |||
216 | if (wbuflen > PAGE_SIZE || rbuflen > PAGE_SIZE) { | ||
217 | dbg("too big transfer requested"); | ||
218 | ret = -ENOMEM; | ||
219 | goto fail; | ||
220 | } | ||
221 | |||
222 | down(&instance->cm_serialize); | ||
223 | |||
224 | /* submit reading urb before the writing one */ | ||
225 | init_completion(&instance->rcv_done); | ||
226 | ret = usb_submit_urb(instance->rcv_urb, GFP_KERNEL); | ||
227 | if (ret < 0) { | ||
228 | dbg("submitting read urb for cm %#x failed", cm); | ||
229 | ret = ret; | ||
230 | goto fail; | ||
231 | } | ||
232 | |||
233 | memset(wbuf, 0, wbuflen); | ||
234 | /* handle wsize == 0 */ | ||
235 | wbuf[0] = cm; | ||
236 | for (offb = offd = 0; offd < wsize; offd += stride, offb += CMD_PACKET_SIZE) { | ||
237 | wbuf[offb] = cm; | ||
238 | memcpy(wbuf + offb + 4, wdata + offd, min_t(int, stride, wsize - offd)); | ||
239 | } | ||
240 | |||
241 | instance->snd_urb->transfer_buffer_length = wbuflen; | ||
242 | init_completion(&instance->snd_done); | ||
243 | ret = usb_submit_urb(instance->snd_urb, GFP_KERNEL); | ||
244 | if (ret < 0) { | ||
245 | dbg("submitting write urb for cm %#x failed", cm); | ||
246 | ret = ret; | ||
247 | goto fail; | ||
248 | } | ||
249 | |||
250 | ret = cxacru_start_wait_urb(instance->snd_urb, &instance->snd_done, NULL); | ||
251 | if (ret < 0) { | ||
252 | dbg("sending cm %#x failed", cm); | ||
253 | ret = ret; | ||
254 | goto fail; | ||
255 | } | ||
256 | |||
257 | ret = cxacru_start_wait_urb(instance->rcv_urb, &instance->rcv_done, &actlen); | ||
258 | if (ret < 0) { | ||
259 | dbg("receiving cm %#x failed", cm); | ||
260 | ret = ret; | ||
261 | goto fail; | ||
262 | } | ||
263 | if (actlen % CMD_PACKET_SIZE || !actlen) { | ||
264 | dbg("response is not a positive multiple of %d: %#x", | ||
265 | CMD_PACKET_SIZE, actlen); | ||
266 | ret = -EIO; | ||
267 | goto fail; | ||
268 | } | ||
269 | |||
270 | /* check the return status and copy the data to the output buffer, if needed */ | ||
271 | for (offb = offd = 0; offd < rsize && offb < actlen; offb += CMD_PACKET_SIZE) { | ||
272 | if (rbuf[offb] != cm) { | ||
273 | dbg("wrong cm %#x in response", rbuf[offb]); | ||
274 | ret = -EIO; | ||
275 | goto fail; | ||
276 | } | ||
277 | if (rbuf[offb + 1] != CM_STATUS_SUCCESS) { | ||
278 | dbg("response failed: %#x", rbuf[offb + 1]); | ||
279 | ret = -EIO; | ||
280 | goto fail; | ||
281 | } | ||
282 | if (offd >= rsize) | ||
283 | break; | ||
284 | memcpy(rdata + offd, rbuf + offb + 4, min_t(int, stride, rsize - offd)); | ||
285 | offd += stride; | ||
286 | } | ||
287 | |||
288 | ret = offd; | ||
289 | dbg("cm %#x", cm); | ||
290 | fail: | ||
291 | up(&instance->cm_serialize); | ||
292 | return ret; | ||
293 | } | ||
294 | |||
295 | static int cxacru_cm_get_array(struct cxacru_data *instance, enum cxacru_cm_request cm, | ||
296 | u32 *data, int size) | ||
297 | { | ||
298 | int ret, len; | ||
299 | u32 *buf; | ||
300 | int offb, offd; | ||
301 | const int stride = CMD_PACKET_SIZE / (4 * 2) - 1; | ||
302 | int buflen = ((size - 1) / stride + 1 + size * 2) * 4; | ||
303 | |||
304 | buf = kmalloc(buflen, GFP_KERNEL); | ||
305 | if (!buf) | ||
306 | return -ENOMEM; | ||
307 | |||
308 | ret = cxacru_cm(instance, cm, NULL, 0, (u8 *) buf, buflen); | ||
309 | if (ret < 0) | ||
310 | goto cleanup; | ||
311 | |||
312 | /* len > 0 && len % 4 == 0 guaranteed by cxacru_cm() */ | ||
313 | len = ret / 4; | ||
314 | for (offb = 0; offb < len; ) { | ||
315 | int l = le32_to_cpu(buf[offb++]); | ||
316 | if (l > stride || l > (len - offb) / 2) { | ||
317 | dbg("wrong data length %#x in response", l); | ||
318 | ret = -EIO; | ||
319 | goto cleanup; | ||
320 | } | ||
321 | while (l--) { | ||
322 | offd = le32_to_cpu(buf[offb++]); | ||
323 | if (offd >= size) { | ||
324 | dbg("wrong index %#x in response", offd); | ||
325 | ret = -EIO; | ||
326 | goto cleanup; | ||
327 | } | ||
328 | data[offd] = le32_to_cpu(buf[offb++]); | ||
329 | } | ||
330 | } | ||
331 | |||
332 | ret = 0; | ||
333 | |||
334 | cleanup: | ||
335 | kfree(buf); | ||
336 | return ret; | ||
337 | } | ||
338 | |||
339 | static int cxacru_card_status(struct cxacru_data *instance) | ||
340 | { | ||
341 | int ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0); | ||
342 | if (ret < 0) { /* firmware not loaded */ | ||
343 | dbg("cxacru_adsl_start: CARD_GET_STATUS returned %d", ret); | ||
344 | return ret; | ||
345 | } | ||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | static void cxacru_poll_status(struct cxacru_data *instance); | ||
350 | |||
351 | static int cxacru_atm_start(struct usbatm_data *usbatm_instance, | ||
352 | struct atm_dev *atm_dev) | ||
353 | { | ||
354 | struct cxacru_data *instance = usbatm_instance->driver_data; | ||
355 | struct device *dev = &usbatm_instance->usb_intf->dev; | ||
356 | /* | ||
357 | struct atm_dev *atm_dev = usbatm_instance->atm_dev; | ||
358 | */ | ||
359 | int ret; | ||
360 | |||
361 | dbg("cxacru_atm_start"); | ||
362 | |||
363 | /* Read MAC address */ | ||
364 | ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_MAC_ADDRESS, NULL, 0, | ||
365 | atm_dev->esi, sizeof(atm_dev->esi)); | ||
366 | if (ret < 0) { | ||
367 | dev_err(dev, "cxacru_atm_start: CARD_GET_MAC_ADDRESS returned %d\n", ret); | ||
368 | return ret; | ||
369 | } | ||
370 | |||
371 | /* start ADSL */ | ||
372 | ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0); | ||
373 | if (ret < 0) { | ||
374 | dev_err(dev, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret); | ||
375 | return ret; | ||
376 | } | ||
377 | |||
378 | /* Start status polling */ | ||
379 | cxacru_poll_status(instance); | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | static void cxacru_poll_status(struct cxacru_data *instance) | ||
384 | { | ||
385 | u32 buf[CXINF_MAX] = {}; | ||
386 | struct device *dev = &instance->usbatm->usb_intf->dev; | ||
387 | struct atm_dev *atm_dev = instance->usbatm->atm_dev; | ||
388 | int ret; | ||
389 | |||
390 | ret = cxacru_cm_get_array(instance, CM_REQUEST_CARD_INFO_GET, buf, CXINF_MAX); | ||
391 | if (ret < 0) { | ||
392 | dev_warn(dev, "poll status: error %d\n", ret); | ||
393 | goto reschedule; | ||
394 | } | ||
395 | |||
396 | if (instance->line_status == buf[CXINF_LINE_STATUS]) | ||
397 | goto reschedule; | ||
398 | |||
399 | instance->line_status = buf[CXINF_LINE_STATUS]; | ||
400 | switch (instance->line_status) { | ||
401 | case 0: | ||
402 | atm_dev->signal = ATM_PHY_SIG_LOST; | ||
403 | dev_info(dev, "ADSL line: down\n"); | ||
404 | break; | ||
405 | |||
406 | case 1: | ||
407 | atm_dev->signal = ATM_PHY_SIG_LOST; | ||
408 | dev_info(dev, "ADSL line: attemtping to activate\n"); | ||
409 | break; | ||
410 | |||
411 | case 2: | ||
412 | atm_dev->signal = ATM_PHY_SIG_LOST; | ||
413 | dev_info(dev, "ADSL line: training\n"); | ||
414 | break; | ||
415 | |||
416 | case 3: | ||
417 | atm_dev->signal = ATM_PHY_SIG_LOST; | ||
418 | dev_info(dev, "ADSL line: channel analysis\n"); | ||
419 | break; | ||
420 | |||
421 | case 4: | ||
422 | atm_dev->signal = ATM_PHY_SIG_LOST; | ||
423 | dev_info(dev, "ADSL line: exchange\n"); | ||
424 | break; | ||
425 | |||
426 | case 5: | ||
427 | atm_dev->link_rate = buf[CXINF_DOWNSTREAM_RATE] * 1000 / 424; | ||
428 | atm_dev->signal = ATM_PHY_SIG_FOUND; | ||
429 | |||
430 | dev_info(dev, "ADSL line: up (%d Kib/s down | %d Kib/s up)\n", | ||
431 | buf[CXINF_DOWNSTREAM_RATE], buf[CXINF_UPSTREAM_RATE]); | ||
432 | break; | ||
433 | |||
434 | case 6: | ||
435 | atm_dev->signal = ATM_PHY_SIG_LOST; | ||
436 | dev_info(dev, "ADSL line: waiting\n"); | ||
437 | break; | ||
438 | |||
439 | case 7: | ||
440 | atm_dev->signal = ATM_PHY_SIG_LOST; | ||
441 | dev_info(dev, "ADSL line: initializing\n"); | ||
442 | break; | ||
443 | |||
444 | default: | ||
445 | atm_dev->signal = ATM_PHY_SIG_UNKNOWN; | ||
446 | dev_info(dev, "Unknown line state %02x\n", instance->line_status); | ||
447 | break; | ||
448 | } | ||
449 | reschedule: | ||
450 | schedule_delayed_work(&instance->poll_work, msecs_to_jiffies(POLL_INTERVAL)); | ||
451 | } | ||
452 | |||
453 | static int cxacru_fw(struct usb_device *usb_dev, enum cxacru_fw_request fw, | ||
454 | u8 code1, u8 code2, u32 addr, u8 *data, int size) | ||
455 | { | ||
456 | int ret; | ||
457 | u8 *buf; | ||
458 | int offd, offb; | ||
459 | const int stride = CMD_PACKET_SIZE - 8; | ||
460 | |||
461 | buf = (u8 *) __get_free_page(GFP_KERNEL); | ||
462 | if (!buf) | ||
463 | return -ENOMEM; | ||
464 | |||
465 | offb = offd = 0; | ||
466 | do { | ||
467 | int l = min_t(int, stride, size - offd); | ||
468 | buf[offb++] = fw; | ||
469 | buf[offb++] = l; | ||
470 | buf[offb++] = code1; | ||
471 | buf[offb++] = code2; | ||
472 | *((u32 *) (buf + offb)) = cpu_to_le32(addr); | ||
473 | offb += 4; | ||
474 | addr += l; | ||
475 | if(l) | ||
476 | memcpy(buf + offb, data + offd, l); | ||
477 | if (l < stride) | ||
478 | memset(buf + offb + l, 0, stride - l); | ||
479 | offb += stride; | ||
480 | offd += stride; | ||
481 | if ((offb >= PAGE_SIZE) || (offd >= size)) { | ||
482 | ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD), | ||
483 | buf, offb, NULL, CMD_TIMEOUT); | ||
484 | if (ret < 0) { | ||
485 | dbg("sending fw %#x failed", fw); | ||
486 | goto cleanup; | ||
487 | } | ||
488 | offb = 0; | ||
489 | } | ||
490 | } while(offd < size); | ||
491 | dbg("sent fw %#x", fw); | ||
492 | |||
493 | ret = 0; | ||
494 | |||
495 | cleanup: | ||
496 | free_page((unsigned long) buf); | ||
497 | return ret; | ||
498 | } | ||
499 | |||
500 | static void cxacru_upload_firmware(struct cxacru_data *instance, | ||
501 | const struct firmware *fw, | ||
502 | const struct firmware *bp, | ||
503 | const struct firmware *cf) | ||
504 | { | ||
505 | int ret; | ||
506 | int off; | ||
507 | struct usb_device *usb_dev = instance->usbatm->usb_dev; | ||
508 | struct device *dev = &instance->usbatm->usb_intf->dev; | ||
509 | u16 signature[] = { usb_dev->descriptor.idVendor, usb_dev->descriptor.idProduct }; | ||
510 | u32 val; | ||
511 | |||
512 | dbg("cxacru_upload_firmware"); | ||
513 | |||
514 | /* FirmwarePllFClkValue */ | ||
515 | val = cpu_to_le32(instance->modem_type->pll_f_clk); | ||
516 | ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLFCLK_ADDR, (u8 *) &val, 4); | ||
517 | if (ret) { | ||
518 | dev_err(dev, "FirmwarePllFClkValue failed: %d\n", ret); | ||
519 | return; | ||
520 | } | ||
521 | |||
522 | /* FirmwarePllBClkValue */ | ||
523 | val = cpu_to_le32(instance->modem_type->pll_b_clk); | ||
524 | ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLBCLK_ADDR, (u8 *) &val, 4); | ||
525 | if (ret) { | ||
526 | dev_err(dev, "FirmwarePllBClkValue failed: %d\n", ret); | ||
527 | return; | ||
528 | } | ||
529 | |||
530 | /* Enable SDRAM */ | ||
531 | val = cpu_to_le32(SDRAM_ENA); | ||
532 | ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SDRAMEN_ADDR, (u8 *) &val, 4); | ||
533 | if (ret) { | ||
534 | dev_err(dev, "Enable SDRAM failed: %d\n", ret); | ||
535 | return; | ||
536 | } | ||
537 | |||
538 | /* Firmware */ | ||
539 | ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, FW_ADDR, fw->data, fw->size); | ||
540 | if (ret) { | ||
541 | dev_err(dev, "Firmware upload failed: %d\n", ret); | ||
542 | return; | ||
543 | } | ||
544 | |||
545 | /* Boot ROM patch */ | ||
546 | if (instance->modem_type->boot_rom_patch) { | ||
547 | ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_ADDR, bp->data, bp->size); | ||
548 | if (ret) { | ||
549 | dev_err(dev, "Boot ROM patching failed: %d\n", ret); | ||
550 | return; | ||
551 | } | ||
552 | } | ||
553 | |||
554 | /* Signature */ | ||
555 | ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SIG_ADDR, (u8 *) signature, 4); | ||
556 | if (ret) { | ||
557 | dev_err(dev, "Signature storing failed: %d\n", ret); | ||
558 | return; | ||
559 | } | ||
560 | |||
561 | if (instance->modem_type->boot_rom_patch) { | ||
562 | val = cpu_to_le32(BR_ADDR); | ||
563 | ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_STACK_ADDR, (u8 *) &val, 4); | ||
564 | } | ||
565 | else { | ||
566 | ret = cxacru_fw(usb_dev, FW_GOTO_MEM, 0x0, 0x0, FW_ADDR, NULL, 0); | ||
567 | } | ||
568 | if (ret) { | ||
569 | dev_err(dev, "Passing control to firmware failed: %d\n", ret); | ||
570 | return; | ||
571 | } | ||
572 | |||
573 | /* Delay to allow firmware to start up. */ | ||
574 | msleep_interruptible(1000); | ||
575 | |||
576 | usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD)); | ||
577 | usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_CMD)); | ||
578 | usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_DATA)); | ||
579 | usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_DATA)); | ||
580 | |||
581 | ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0); | ||
582 | if (ret < 0) { | ||
583 | dev_err(dev, "modem failed to initialize: %d\n", ret); | ||
584 | return; | ||
585 | } | ||
586 | |||
587 | /* Load config data (le32), doing one packet at a time */ | ||
588 | if (cf) | ||
589 | for (off = 0; off < cf->size / 4; ) { | ||
590 | u32 buf[CMD_PACKET_SIZE / 4 - 1]; | ||
591 | int i, len = min_t(int, cf->size / 4 - off, CMD_PACKET_SIZE / 4 / 2 - 1); | ||
592 | buf[0] = cpu_to_le32(len); | ||
593 | for (i = 0; i < len; i++, off++) { | ||
594 | buf[i * 2 + 1] = cpu_to_le32(off); | ||
595 | memcpy(buf + i * 2 + 2, cf->data + off * 4, 4); | ||
596 | } | ||
597 | ret = cxacru_cm(instance, CM_REQUEST_CARD_DATA_SET, | ||
598 | (u8 *) buf, len, NULL, 0); | ||
599 | if (ret < 0) { | ||
600 | dev_err(dev, "load config data failed: %d\n", ret); | ||
601 | return; | ||
602 | } | ||
603 | } | ||
604 | |||
605 | msleep_interruptible(4000); | ||
606 | } | ||
607 | |||
608 | static int cxacru_find_firmware(struct cxacru_data *instance, | ||
609 | char* phase, const struct firmware **fw_p) | ||
610 | { | ||
611 | struct device *dev = &instance->usbatm->usb_intf->dev; | ||
612 | char buf[16]; | ||
613 | |||
614 | sprintf(buf, "cxacru-%s.bin", phase); | ||
615 | dbg("cxacru_find_firmware: looking for %s", buf); | ||
616 | |||
617 | if (request_firmware(fw_p, buf, dev)) { | ||
618 | dev_dbg(dev, "no stage %s firmware found\n", phase); | ||
619 | return -ENOENT; | ||
620 | } | ||
621 | |||
622 | dev_info(dev, "found firmware %s\n", buf); | ||
623 | |||
624 | return 0; | ||
625 | } | ||
626 | |||
627 | static int cxacru_heavy_init(struct usbatm_data *usbatm_instance, | ||
628 | struct usb_interface *usb_intf) | ||
629 | { | ||
630 | struct device *dev = &usbatm_instance->usb_intf->dev; | ||
631 | const struct firmware *fw, *bp, *cf; | ||
632 | struct cxacru_data *instance = usbatm_instance->driver_data; | ||
633 | |||
634 | int ret = cxacru_find_firmware(instance, "fw", &fw); | ||
635 | if (ret) { | ||
636 | dev_warn(dev, "firmware (cxacru-fw.bin) unavailable (hotplug misconfiguration?)\n"); | ||
637 | return ret; | ||
638 | } | ||
639 | |||
640 | if (instance->modem_type->boot_rom_patch) { | ||
641 | ret = cxacru_find_firmware(instance, "bp", &bp); | ||
642 | if (ret) { | ||
643 | dev_warn(dev, "boot ROM patch (cxacru-bp.bin) unavailable (hotplug misconfiguration?)\n"); | ||
644 | release_firmware(fw); | ||
645 | return ret; | ||
646 | } | ||
647 | } | ||
648 | |||
649 | if (cxacru_find_firmware(instance, "cf", &cf)) /* optional */ | ||
650 | cf = NULL; | ||
651 | |||
652 | cxacru_upload_firmware(instance, fw, bp, cf); | ||
653 | |||
654 | if (cf) | ||
655 | release_firmware(cf); | ||
656 | if (instance->modem_type->boot_rom_patch) | ||
657 | release_firmware(bp); | ||
658 | release_firmware(fw); | ||
659 | |||
660 | ret = cxacru_card_status(instance); | ||
661 | if (ret) | ||
662 | dbg("modem initialisation failed"); | ||
663 | else | ||
664 | dbg("done setting up the modem"); | ||
665 | |||
666 | return ret; | ||
667 | } | ||
668 | |||
669 | static int cxacru_bind(struct usbatm_data *usbatm_instance, | ||
670 | struct usb_interface *intf, const struct usb_device_id *id, | ||
671 | int *need_heavy_init) | ||
672 | { | ||
673 | struct cxacru_data *instance; | ||
674 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
675 | int ret; | ||
676 | |||
677 | /* instance init */ | ||
678 | instance = kmalloc(sizeof(*instance), GFP_KERNEL); | ||
679 | if (!instance) { | ||
680 | dbg("cxacru_bind: no memory for instance data"); | ||
681 | return -ENOMEM; | ||
682 | } | ||
683 | |||
684 | memset(instance, 0, sizeof(*instance)); | ||
685 | |||
686 | instance->usbatm = usbatm_instance; | ||
687 | instance->modem_type = (struct cxacru_modem_type *) id->driver_info; | ||
688 | |||
689 | instance->rcv_buf = (u8 *) __get_free_page(GFP_KERNEL); | ||
690 | if (!instance->rcv_buf) { | ||
691 | dbg("cxacru_bind: no memory for rcv_buf"); | ||
692 | ret = -ENOMEM; | ||
693 | goto fail; | ||
694 | } | ||
695 | instance->snd_buf = (u8 *) __get_free_page(GFP_KERNEL); | ||
696 | if (!instance->snd_buf) { | ||
697 | dbg("cxacru_bind: no memory for snd_buf"); | ||
698 | ret = -ENOMEM; | ||
699 | goto fail; | ||
700 | } | ||
701 | instance->rcv_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
702 | if (!instance->rcv_urb) { | ||
703 | dbg("cxacru_bind: no memory for rcv_urb"); | ||
704 | ret = -ENOMEM; | ||
705 | goto fail; | ||
706 | } | ||
707 | instance->snd_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
708 | if (!instance->snd_urb) { | ||
709 | dbg("cxacru_bind: no memory for snd_urb"); | ||
710 | ret = -ENOMEM; | ||
711 | goto fail; | ||
712 | } | ||
713 | |||
714 | usb_fill_int_urb(instance->rcv_urb, | ||
715 | usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD), | ||
716 | instance->rcv_buf, PAGE_SIZE, | ||
717 | cxacru_blocking_completion, &instance->rcv_done, 1); | ||
718 | instance->rcv_urb->transfer_flags |= URB_ASYNC_UNLINK; | ||
719 | |||
720 | usb_fill_int_urb(instance->snd_urb, | ||
721 | usb_dev, usb_sndintpipe(usb_dev, CXACRU_EP_CMD), | ||
722 | instance->snd_buf, PAGE_SIZE, | ||
723 | cxacru_blocking_completion, &instance->snd_done, 4); | ||
724 | instance->snd_urb->transfer_flags |= URB_ASYNC_UNLINK; | ||
725 | |||
726 | init_MUTEX(&instance->cm_serialize); | ||
727 | |||
728 | INIT_WORK(&instance->poll_work, (void *)cxacru_poll_status, instance); | ||
729 | |||
730 | usbatm_instance->driver_data = instance; | ||
731 | |||
732 | *need_heavy_init = cxacru_card_status(instance); | ||
733 | |||
734 | return 0; | ||
735 | |||
736 | fail: | ||
737 | free_page((unsigned long) instance->snd_buf); | ||
738 | free_page((unsigned long) instance->rcv_buf); | ||
739 | usb_free_urb(instance->snd_urb); | ||
740 | usb_free_urb(instance->rcv_urb); | ||
741 | kfree(instance); | ||
742 | |||
743 | return ret; | ||
744 | } | ||
745 | |||
746 | static void cxacru_unbind(struct usbatm_data *usbatm_instance, | ||
747 | struct usb_interface *intf) | ||
748 | { | ||
749 | struct cxacru_data *instance = usbatm_instance->driver_data; | ||
750 | |||
751 | dbg("cxacru_unbind entered"); | ||
752 | |||
753 | if (!instance) { | ||
754 | dbg("cxacru_unbind: NULL instance!"); | ||
755 | return; | ||
756 | } | ||
757 | |||
758 | while (!cancel_delayed_work(&instance->poll_work)) | ||
759 | flush_scheduled_work(); | ||
760 | |||
761 | usb_kill_urb(instance->snd_urb); | ||
762 | usb_kill_urb(instance->rcv_urb); | ||
763 | usb_free_urb(instance->snd_urb); | ||
764 | usb_free_urb(instance->rcv_urb); | ||
765 | |||
766 | free_page((unsigned long) instance->snd_buf); | ||
767 | free_page((unsigned long) instance->rcv_buf); | ||
768 | kfree(instance); | ||
769 | |||
770 | usbatm_instance->driver_data = NULL; | ||
771 | } | ||
772 | |||
773 | static const struct cxacru_modem_type cxacru_cafe = { | ||
774 | .pll_f_clk = 0x02d874df, | ||
775 | .pll_b_clk = 0x0196a51a, | ||
776 | .boot_rom_patch = 1, | ||
777 | }; | ||
778 | |||
779 | static const struct cxacru_modem_type cxacru_cb00 = { | ||
780 | .pll_f_clk = 0x5, | ||
781 | .pll_b_clk = 0x3, | ||
782 | .boot_rom_patch = 0, | ||
783 | }; | ||
784 | |||
785 | static const struct usb_device_id cxacru_usb_ids[] = { | ||
786 | { /* V = Conexant P = ADSL modem (Euphrates project) */ | ||
787 | USB_DEVICE(0x0572, 0xcafe), .driver_info = (unsigned long) &cxacru_cafe | ||
788 | }, | ||
789 | { /* V = Conexant P = ADSL modem (Hasbani project) */ | ||
790 | USB_DEVICE(0x0572, 0xcb00), .driver_info = (unsigned long) &cxacru_cb00 | ||
791 | }, | ||
792 | { /* V = Conexant P = ADSL modem */ | ||
793 | USB_DEVICE(0x0572, 0xcb01), .driver_info = (unsigned long) &cxacru_cb00 | ||
794 | }, | ||
795 | { /* V = Conexant P = ADSL modem */ | ||
796 | USB_DEVICE(0x0572, 0xcb06), .driver_info = (unsigned long) &cxacru_cb00 | ||
797 | }, | ||
798 | { /* V = Olitec P = ADSL modem version 2 */ | ||
799 | USB_DEVICE(0x08e3, 0x0100), .driver_info = (unsigned long) &cxacru_cafe | ||
800 | }, | ||
801 | { /* V = Olitec P = ADSL modem version 3 */ | ||
802 | USB_DEVICE(0x08e3, 0x0102), .driver_info = (unsigned long) &cxacru_cb00 | ||
803 | }, | ||
804 | { /* V = Trust/Amigo Technology Co. P = AMX-CA86U */ | ||
805 | USB_DEVICE(0x0eb0, 0x3457), .driver_info = (unsigned long) &cxacru_cafe | ||
806 | }, | ||
807 | { /* V = Zoom P = 5510 */ | ||
808 | USB_DEVICE(0x1803, 0x5510), .driver_info = (unsigned long) &cxacru_cb00 | ||
809 | }, | ||
810 | { /* V = Draytek P = Vigor 318 */ | ||
811 | USB_DEVICE(0x0675, 0x0200), .driver_info = (unsigned long) &cxacru_cb00 | ||
812 | }, | ||
813 | { /* V = Zyxel P = 630-C1 aka OMNI ADSL USB (Annex A) */ | ||
814 | USB_DEVICE(0x0586, 0x330a), .driver_info = (unsigned long) &cxacru_cb00 | ||
815 | }, | ||
816 | { /* V = Zyxel P = 630-C3 aka OMNI ADSL USB (Annex B) */ | ||
817 | USB_DEVICE(0x0586, 0x330b), .driver_info = (unsigned long) &cxacru_cb00 | ||
818 | }, | ||
819 | { /* V = Aethra P = Starmodem UM1020 */ | ||
820 | USB_DEVICE(0x0659, 0x0020), .driver_info = (unsigned long) &cxacru_cb00 | ||
821 | }, | ||
822 | { /* V = Aztech Systems P = ? AKA Pirelli AUA-010 */ | ||
823 | USB_DEVICE(0x0509, 0x0812), .driver_info = (unsigned long) &cxacru_cb00 | ||
824 | }, | ||
825 | { /* V = Netopia P = Cayman 3341(Annex A)/3351(Annex B) */ | ||
826 | USB_DEVICE(0x100d, 0xcb01), .driver_info = (unsigned long) &cxacru_cb00 | ||
827 | }, | ||
828 | { /* V = Netopia P = Cayman 3342(Annex A)/3352(Annex B) */ | ||
829 | USB_DEVICE(0x100d, 0x3342), .driver_info = (unsigned long) &cxacru_cb00 | ||
830 | }, | ||
831 | {} | ||
832 | }; | ||
833 | |||
834 | MODULE_DEVICE_TABLE(usb, cxacru_usb_ids); | ||
835 | |||
836 | static struct usbatm_driver cxacru_driver = { | ||
837 | .owner = THIS_MODULE, | ||
838 | .driver_name = cxacru_driver_name, | ||
839 | .bind = cxacru_bind, | ||
840 | .heavy_init = cxacru_heavy_init, | ||
841 | .unbind = cxacru_unbind, | ||
842 | .atm_start = cxacru_atm_start, | ||
843 | .in = CXACRU_EP_DATA, | ||
844 | .out = CXACRU_EP_DATA, | ||
845 | .rx_padding = 3, | ||
846 | .tx_padding = 11, | ||
847 | }; | ||
848 | |||
849 | static int cxacru_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
850 | { | ||
851 | return usbatm_usb_probe(intf, id, &cxacru_driver); | ||
852 | } | ||
853 | |||
854 | static struct usb_driver cxacru_usb_driver = { | ||
855 | .owner = THIS_MODULE, | ||
856 | .name = cxacru_driver_name, | ||
857 | .probe = cxacru_usb_probe, | ||
858 | .disconnect = usbatm_usb_disconnect, | ||
859 | .id_table = cxacru_usb_ids | ||
860 | }; | ||
861 | |||
862 | static int __init cxacru_init(void) | ||
863 | { | ||
864 | return usb_register(&cxacru_usb_driver); | ||
865 | } | ||
866 | |||
867 | static void __exit cxacru_cleanup(void) | ||
868 | { | ||
869 | usb_deregister(&cxacru_usb_driver); | ||
870 | } | ||
871 | |||
872 | module_init(cxacru_init); | ||
873 | module_exit(cxacru_cleanup); | ||
874 | |||
875 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
876 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
877 | MODULE_LICENSE("GPL"); | ||
878 | MODULE_VERSION(DRIVER_VERSION); | ||
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index 2a1697bfd695..6a6eaa2a3b1c 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c | |||
@@ -5,6 +5,8 @@ | |||
5 | * Copyright (C) 2003, Duncan Sands | 5 | * Copyright (C) 2003, Duncan Sands |
6 | * Copyright (C) 2004, David Woodhouse | 6 | * Copyright (C) 2004, David Woodhouse |
7 | * | 7 | * |
8 | * Based on "modem_run.c", copyright (C) 2001, Benoit Papillault | ||
9 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | 10 | * This program is free software; you can redistribute it and/or modify it |
9 | * under the terms of the GNU General Public License as published by the Free | 11 | * under the terms of the GNU General Public License as published by the Free |
10 | * Software Foundation; either version 2 of the License, or (at your option) | 12 | * Software Foundation; either version 2 of the License, or (at your option) |
@@ -21,821 +23,798 @@ | |||
21 | * | 23 | * |
22 | ******************************************************************************/ | 24 | ******************************************************************************/ |
23 | 25 | ||
24 | #include <linux/module.h> | 26 | #include <asm/page.h> |
25 | #include <linux/moduleparam.h> | 27 | #include <linux/device.h> |
28 | #include <linux/errno.h> | ||
29 | #include <linux/firmware.h> | ||
26 | #include <linux/gfp.h> | 30 | #include <linux/gfp.h> |
31 | #include <linux/init.h> | ||
27 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
28 | #include <linux/sched.h> | 33 | #include <linux/module.h> |
29 | #include <linux/timer.h> | 34 | #include <linux/moduleparam.h> |
30 | #include <linux/errno.h> | ||
31 | #include <linux/proc_fs.h> | ||
32 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
33 | #include <linux/wait.h> | 36 | #include <linux/stat.h> |
34 | #include <linux/list.h> | 37 | #include <linux/timer.h> |
35 | #include <asm/processor.h> | 38 | #include <linux/workqueue.h> |
36 | #include <asm/uaccess.h> | ||
37 | #include <linux/smp_lock.h> | ||
38 | #include <linux/interrupt.h> | ||
39 | #include <linux/atm.h> | ||
40 | #include <linux/atmdev.h> | ||
41 | #include <linux/crc32.h> | ||
42 | #include <linux/init.h> | ||
43 | #include <linux/firmware.h> | ||
44 | |||
45 | #include "usb_atm.h" | ||
46 | 39 | ||
47 | #if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) | 40 | #include "usbatm.h" |
48 | # define USE_FW_LOADER | ||
49 | #endif | ||
50 | 41 | ||
51 | #define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>" | 42 | #define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>" |
52 | #define DRIVER_VERSION "1.8" | 43 | #define DRIVER_VERSION "1.9" |
53 | #define DRIVER_DESC "Alcatel SpeedTouch USB driver version " DRIVER_VERSION | 44 | #define DRIVER_DESC "Alcatel SpeedTouch USB driver version " DRIVER_VERSION |
54 | 45 | ||
55 | static const char speedtch_driver_name[] = "speedtch"; | 46 | static const char speedtch_driver_name[] = "speedtch"; |
56 | 47 | ||
57 | #define SPEEDTOUCH_VENDORID 0x06b9 | 48 | #define CTRL_TIMEOUT 2000 /* milliseconds */ |
58 | #define SPEEDTOUCH_PRODUCTID 0x4061 | 49 | #define DATA_TIMEOUT 2000 /* milliseconds */ |
59 | 50 | ||
60 | /* Timeout in jiffies */ | 51 | #define OFFSET_7 0 /* size 1 */ |
61 | #define CTRL_TIMEOUT 2000 | 52 | #define OFFSET_b 1 /* size 8 */ |
62 | #define DATA_TIMEOUT 2000 | 53 | #define OFFSET_d 9 /* size 4 */ |
54 | #define OFFSET_e 13 /* size 1 */ | ||
55 | #define OFFSET_f 14 /* size 1 */ | ||
56 | #define TOTAL 15 | ||
63 | 57 | ||
64 | #define OFFSET_7 0 /* size 1 */ | 58 | #define SIZE_7 1 |
65 | #define OFFSET_b 1 /* size 8 */ | 59 | #define SIZE_b 8 |
66 | #define OFFSET_d 9 /* size 4 */ | 60 | #define SIZE_d 4 |
67 | #define OFFSET_e 13 /* size 1 */ | 61 | #define SIZE_e 1 |
68 | #define OFFSET_f 14 /* size 1 */ | 62 | #define SIZE_f 1 |
69 | #define TOTAL 15 | ||
70 | 63 | ||
71 | #define SIZE_7 1 | 64 | #define MIN_POLL_DELAY 5000 /* milliseconds */ |
72 | #define SIZE_b 8 | 65 | #define MAX_POLL_DELAY 60000 /* milliseconds */ |
73 | #define SIZE_d 4 | ||
74 | #define SIZE_e 1 | ||
75 | #define SIZE_f 1 | ||
76 | 66 | ||
77 | static int dl_512_first = 0; | 67 | #define RESUBMIT_DELAY 1000 /* milliseconds */ |
78 | static int sw_buffering = 0; | ||
79 | 68 | ||
80 | module_param(dl_512_first, bool, 0444); | 69 | #define DEFAULT_ALTSETTING 1 |
81 | MODULE_PARM_DESC(dl_512_first, "Read 512 bytes before sending firmware"); | 70 | #define DEFAULT_DL_512_FIRST 0 |
71 | #define DEFAULT_SW_BUFFERING 0 | ||
82 | 72 | ||
83 | module_param(sw_buffering, uint, 0444); | 73 | static int altsetting = DEFAULT_ALTSETTING; |
84 | MODULE_PARM_DESC(sw_buffering, "Enable software buffering"); | 74 | static int dl_512_first = DEFAULT_DL_512_FIRST; |
75 | static int sw_buffering = DEFAULT_SW_BUFFERING; | ||
85 | 76 | ||
86 | #define UDSL_IOCTL_LINE_UP 1 | 77 | module_param(altsetting, int, S_IRUGO | S_IWUSR); |
87 | #define UDSL_IOCTL_LINE_DOWN 2 | 78 | MODULE_PARM_DESC(altsetting, |
79 | "Alternative setting for data interface (default: " | ||
80 | __MODULE_STRING(DEFAULT_ALTSETTING) ")"); | ||
88 | 81 | ||
89 | #define SPEEDTCH_ENDPOINT_INT 0x81 | 82 | module_param(dl_512_first, bool, S_IRUGO | S_IWUSR); |
90 | #define SPEEDTCH_ENDPOINT_DATA 0x07 | 83 | MODULE_PARM_DESC(dl_512_first, |
91 | #define SPEEDTCH_ENDPOINT_FIRMWARE 0x05 | 84 | "Read 512 bytes before sending firmware (default: " |
85 | __MODULE_STRING(DEFAULT_DL_512_FIRST) ")"); | ||
92 | 86 | ||
93 | #define hex2int(c) ( (c >= '0') && (c <= '9') ? (c - '0') : ((c & 0xf) + 9) ) | 87 | module_param(sw_buffering, bool, S_IRUGO | S_IWUSR); |
88 | MODULE_PARM_DESC(sw_buffering, | ||
89 | "Enable software buffering (default: " | ||
90 | __MODULE_STRING(DEFAULT_SW_BUFFERING) ")"); | ||
94 | 91 | ||
95 | static struct usb_device_id speedtch_usb_ids[] = { | 92 | #define ENDPOINT_INT 0x81 |
96 | {USB_DEVICE(SPEEDTOUCH_VENDORID, SPEEDTOUCH_PRODUCTID)}, | 93 | #define ENDPOINT_DATA 0x07 |
97 | {} | 94 | #define ENDPOINT_FIRMWARE 0x05 |
98 | }; | ||
99 | 95 | ||
100 | MODULE_DEVICE_TABLE(usb, speedtch_usb_ids); | 96 | #define hex2int(c) ( (c >= '0') && (c <= '9') ? (c - '0') : ((c & 0xf) + 9) ) |
101 | 97 | ||
102 | struct speedtch_instance_data { | 98 | struct speedtch_instance_data { |
103 | struct udsl_instance_data u; | 99 | struct usbatm_data *usbatm; |
100 | |||
101 | struct work_struct status_checker; | ||
104 | 102 | ||
105 | /* Status */ | 103 | int poll_delay; /* milliseconds */ |
104 | |||
105 | struct timer_list resubmit_timer; | ||
106 | struct urb *int_urb; | 106 | struct urb *int_urb; |
107 | unsigned char int_data[16]; | 107 | unsigned char int_data[16]; |
108 | struct work_struct poll_work; | ||
109 | struct timer_list poll_timer; | ||
110 | }; | ||
111 | /* USB */ | ||
112 | |||
113 | static int speedtch_usb_probe(struct usb_interface *intf, | ||
114 | const struct usb_device_id *id); | ||
115 | static void speedtch_usb_disconnect(struct usb_interface *intf); | ||
116 | static int speedtch_usb_ioctl(struct usb_interface *intf, unsigned int code, | ||
117 | void *user_data); | ||
118 | static void speedtch_handle_int(struct urb *urb, struct pt_regs *regs); | ||
119 | static void speedtch_poll_status(struct speedtch_instance_data *instance); | ||
120 | 108 | ||
121 | static struct usb_driver speedtch_usb_driver = { | 109 | unsigned char scratch_buffer[TOTAL]; |
122 | .owner = THIS_MODULE, | ||
123 | .name = speedtch_driver_name, | ||
124 | .probe = speedtch_usb_probe, | ||
125 | .disconnect = speedtch_usb_disconnect, | ||
126 | .ioctl = speedtch_usb_ioctl, | ||
127 | .id_table = speedtch_usb_ids, | ||
128 | }; | 110 | }; |
129 | 111 | ||
130 | /*************** | 112 | /*************** |
131 | ** firmware ** | 113 | ** firmware ** |
132 | ***************/ | 114 | ***************/ |
133 | 115 | ||
134 | static void speedtch_got_firmware(struct speedtch_instance_data *instance, | 116 | static void speedtch_set_swbuff(struct speedtch_instance_data *instance, int state) |
135 | int got_it) | ||
136 | { | 117 | { |
137 | int err; | 118 | struct usbatm_data *usbatm = instance->usbatm; |
138 | struct usb_interface *intf; | 119 | struct usb_device *usb_dev = usbatm->usb_dev; |
139 | |||
140 | down(&instance->u.serialize); /* vs self, speedtch_firmware_start */ | ||
141 | if (instance->u.status == UDSL_LOADED_FIRMWARE) | ||
142 | goto out; | ||
143 | if (!got_it) { | ||
144 | instance->u.status = UDSL_NO_FIRMWARE; | ||
145 | goto out; | ||
146 | } | ||
147 | if ((err = usb_set_interface(instance->u.usb_dev, 1, 1)) < 0) { | ||
148 | dbg("speedtch_got_firmware: usb_set_interface returned %d!", err); | ||
149 | instance->u.status = UDSL_NO_FIRMWARE; | ||
150 | goto out; | ||
151 | } | ||
152 | |||
153 | /* Set up interrupt endpoint */ | ||
154 | intf = usb_ifnum_to_if(instance->u.usb_dev, 0); | ||
155 | if (intf && !usb_driver_claim_interface(&speedtch_usb_driver, intf, NULL)) { | ||
156 | |||
157 | instance->int_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
158 | if (instance->int_urb) { | ||
159 | |||
160 | usb_fill_int_urb(instance->int_urb, instance->u.usb_dev, | ||
161 | usb_rcvintpipe(instance->u.usb_dev, SPEEDTCH_ENDPOINT_INT), | ||
162 | instance->int_data, | ||
163 | sizeof(instance->int_data), | ||
164 | speedtch_handle_int, instance, 50); | ||
165 | err = usb_submit_urb(instance->int_urb, GFP_KERNEL); | ||
166 | if (err) { | ||
167 | /* Doesn't matter; we'll poll anyway */ | ||
168 | dbg("speedtch_got_firmware: Submission of interrupt URB failed %d", err); | ||
169 | usb_free_urb(instance->int_urb); | ||
170 | instance->int_urb = NULL; | ||
171 | usb_driver_release_interface(&speedtch_usb_driver, intf); | ||
172 | } | ||
173 | } | ||
174 | } | ||
175 | /* Start status polling */ | ||
176 | mod_timer(&instance->poll_timer, jiffies + (1 * HZ)); | ||
177 | |||
178 | instance->u.status = UDSL_LOADED_FIRMWARE; | ||
179 | tasklet_schedule(&instance->u.receive_tasklet); | ||
180 | out: | ||
181 | up(&instance->u.serialize); | ||
182 | wake_up_interruptible(&instance->u.firmware_waiters); | ||
183 | } | ||
184 | |||
185 | static int speedtch_set_swbuff(struct speedtch_instance_data *instance, | ||
186 | int state) | ||
187 | { | ||
188 | struct usb_device *dev = instance->u.usb_dev; | ||
189 | int ret; | 120 | int ret; |
190 | 121 | ||
191 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 122 | ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), |
192 | 0x32, 0x40, state ? 0x01 : 0x00, | 123 | 0x32, 0x40, state ? 0x01 : 0x00, 0x00, NULL, 0, CTRL_TIMEOUT); |
193 | 0x00, NULL, 0, 100); | 124 | if (ret < 0) |
194 | if (ret < 0) { | 125 | usb_warn(usbatm, |
195 | printk("Warning: %sabling SW buffering: usb_control_msg returned %d\n", | 126 | "%sabling SW buffering: usb_control_msg returned %d\n", |
196 | state ? "En" : "Dis", ret); | 127 | state ? "En" : "Dis", ret); |
197 | return ret; | 128 | else |
198 | } | 129 | dbg("speedtch_set_swbuff: %sbled SW buffering", state ? "En" : "Dis"); |
199 | |||
200 | dbg("speedtch_set_swbuff: %sbled SW buffering", state ? "En" : "Dis"); | ||
201 | return 0; | ||
202 | } | 130 | } |
203 | 131 | ||
204 | static void speedtch_test_sequence(struct speedtch_instance_data *instance) | 132 | static void speedtch_test_sequence(struct speedtch_instance_data *instance) |
205 | { | 133 | { |
206 | struct usb_device *dev = instance->u.usb_dev; | 134 | struct usbatm_data *usbatm = instance->usbatm; |
207 | unsigned char buf[10]; | 135 | struct usb_device *usb_dev = usbatm->usb_dev; |
136 | unsigned char *buf = instance->scratch_buffer; | ||
208 | int ret; | 137 | int ret; |
209 | 138 | ||
210 | /* URB 147 */ | 139 | /* URB 147 */ |
211 | buf[0] = 0x1c; | 140 | buf[0] = 0x1c; |
212 | buf[1] = 0x50; | 141 | buf[1] = 0x50; |
213 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 142 | ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), |
214 | 0x01, 0x40, 0x0b, 0x00, buf, 2, 100); | 143 | 0x01, 0x40, 0x0b, 0x00, buf, 2, CTRL_TIMEOUT); |
215 | if (ret < 0) | 144 | if (ret < 0) |
216 | printk(KERN_WARNING "%s failed on URB147: %d\n", __func__, ret); | 145 | usb_warn(usbatm, "%s failed on URB147: %d\n", __func__, ret); |
217 | 146 | ||
218 | /* URB 148 */ | 147 | /* URB 148 */ |
219 | buf[0] = 0x32; | 148 | buf[0] = 0x32; |
220 | buf[1] = 0x00; | 149 | buf[1] = 0x00; |
221 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 150 | ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), |
222 | 0x01, 0x40, 0x02, 0x00, buf, 2, 100); | 151 | 0x01, 0x40, 0x02, 0x00, buf, 2, CTRL_TIMEOUT); |
223 | if (ret < 0) | 152 | if (ret < 0) |
224 | printk(KERN_WARNING "%s failed on URB148: %d\n", __func__, ret); | 153 | usb_warn(usbatm, "%s failed on URB148: %d\n", __func__, ret); |
225 | 154 | ||
226 | /* URB 149 */ | 155 | /* URB 149 */ |
227 | buf[0] = 0x01; | 156 | buf[0] = 0x01; |
228 | buf[1] = 0x00; | 157 | buf[1] = 0x00; |
229 | buf[2] = 0x01; | 158 | buf[2] = 0x01; |
230 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 159 | ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), |
231 | 0x01, 0x40, 0x03, 0x00, buf, 3, 100); | 160 | 0x01, 0x40, 0x03, 0x00, buf, 3, CTRL_TIMEOUT); |
232 | if (ret < 0) | 161 | if (ret < 0) |
233 | printk(KERN_WARNING "%s failed on URB149: %d\n", __func__, ret); | 162 | usb_warn(usbatm, "%s failed on URB149: %d\n", __func__, ret); |
234 | 163 | ||
235 | /* URB 150 */ | 164 | /* URB 150 */ |
236 | buf[0] = 0x01; | 165 | buf[0] = 0x01; |
237 | buf[1] = 0x00; | 166 | buf[1] = 0x00; |
238 | buf[2] = 0x01; | 167 | buf[2] = 0x01; |
239 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 168 | ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), |
240 | 0x01, 0x40, 0x04, 0x00, buf, 3, 100); | 169 | 0x01, 0x40, 0x04, 0x00, buf, 3, CTRL_TIMEOUT); |
241 | if (ret < 0) | 170 | if (ret < 0) |
242 | printk(KERN_WARNING "%s failed on URB150: %d\n", __func__, ret); | 171 | usb_warn(usbatm, "%s failed on URB150: %d\n", __func__, ret); |
243 | } | 172 | } |
244 | 173 | ||
245 | static int speedtch_start_synchro(struct speedtch_instance_data *instance) | 174 | static int speedtch_upload_firmware(struct speedtch_instance_data *instance, |
175 | const struct firmware *fw1, | ||
176 | const struct firmware *fw2) | ||
246 | { | 177 | { |
247 | struct usb_device *dev = instance->u.usb_dev; | 178 | unsigned char *buffer; |
248 | unsigned char buf[2]; | 179 | struct usbatm_data *usbatm = instance->usbatm; |
249 | int ret; | 180 | struct usb_interface *intf; |
181 | struct usb_device *usb_dev = usbatm->usb_dev; | ||
182 | int actual_length; | ||
183 | int ret = 0; | ||
184 | int offset; | ||
185 | |||
186 | usb_dbg(usbatm, "%s entered\n", __func__); | ||
187 | |||
188 | if (!(buffer = (unsigned char *)__get_free_page(GFP_KERNEL))) { | ||
189 | ret = -ENOMEM; | ||
190 | usb_dbg(usbatm, "%s: no memory for buffer!\n", __func__); | ||
191 | goto out; | ||
192 | } | ||
193 | |||
194 | if (!(intf = usb_ifnum_to_if(usb_dev, 2))) { | ||
195 | ret = -ENODEV; | ||
196 | usb_dbg(usbatm, "%s: interface not found!\n", __func__); | ||
197 | goto out_free; | ||
198 | } | ||
199 | |||
200 | /* URB 7 */ | ||
201 | if (dl_512_first) { /* some modems need a read before writing the firmware */ | ||
202 | ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, ENDPOINT_FIRMWARE), | ||
203 | buffer, 0x200, &actual_length, 2000); | ||
204 | |||
205 | if (ret < 0 && ret != -ETIMEDOUT) | ||
206 | usb_dbg(usbatm, "%s: read BLOCK0 from modem failed (%d)!\n", __func__, ret); | ||
207 | else | ||
208 | usb_dbg(usbatm, "%s: BLOCK0 downloaded (%d bytes)\n", __func__, ret); | ||
209 | } | ||
210 | |||
211 | /* URB 8 : both leds are static green */ | ||
212 | for (offset = 0; offset < fw1->size; offset += PAGE_SIZE) { | ||
213 | int thislen = min_t(int, PAGE_SIZE, fw1->size - offset); | ||
214 | memcpy(buffer, fw1->data + offset, thislen); | ||
215 | |||
216 | ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, ENDPOINT_FIRMWARE), | ||
217 | buffer, thislen, &actual_length, DATA_TIMEOUT); | ||
218 | |||
219 | if (ret < 0) { | ||
220 | usb_dbg(usbatm, "%s: write BLOCK1 to modem failed (%d)!\n", __func__, ret); | ||
221 | goto out_free; | ||
222 | } | ||
223 | usb_dbg(usbatm, "%s: BLOCK1 uploaded (%zu bytes)\n", __func__, fw1->size); | ||
224 | } | ||
225 | |||
226 | /* USB led blinking green, ADSL led off */ | ||
227 | |||
228 | /* URB 11 */ | ||
229 | ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, ENDPOINT_FIRMWARE), | ||
230 | buffer, 0x200, &actual_length, DATA_TIMEOUT); | ||
250 | 231 | ||
251 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
252 | 0x12, 0xc0, 0x04, 0x00, | ||
253 | buf, sizeof(buf), CTRL_TIMEOUT); | ||
254 | if (ret < 0) { | 232 | if (ret < 0) { |
255 | printk(KERN_WARNING "SpeedTouch: Failed to start ADSL synchronisation: %d\n", ret); | 233 | usb_dbg(usbatm, "%s: read BLOCK2 from modem failed (%d)!\n", __func__, ret); |
256 | return ret; | 234 | goto out_free; |
257 | } | 235 | } |
236 | usb_dbg(usbatm, "%s: BLOCK2 downloaded (%d bytes)\n", __func__, actual_length); | ||
258 | 237 | ||
259 | dbg("speedtch_start_synchro: modem prodded. %d Bytes returned: %02x %02x", ret, buf[0], buf[1]); | 238 | /* URBs 12 to 139 - USB led blinking green, ADSL led off */ |
260 | return 0; | 239 | for (offset = 0; offset < fw2->size; offset += PAGE_SIZE) { |
240 | int thislen = min_t(int, PAGE_SIZE, fw2->size - offset); | ||
241 | memcpy(buffer, fw2->data + offset, thislen); | ||
242 | |||
243 | ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, ENDPOINT_FIRMWARE), | ||
244 | buffer, thislen, &actual_length, DATA_TIMEOUT); | ||
245 | |||
246 | if (ret < 0) { | ||
247 | usb_dbg(usbatm, "%s: write BLOCK3 to modem failed (%d)!\n", __func__, ret); | ||
248 | goto out_free; | ||
249 | } | ||
250 | } | ||
251 | usb_dbg(usbatm, "%s: BLOCK3 uploaded (%zu bytes)\n", __func__, fw2->size); | ||
252 | |||
253 | /* USB led static green, ADSL led static red */ | ||
254 | |||
255 | /* URB 142 */ | ||
256 | ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, ENDPOINT_FIRMWARE), | ||
257 | buffer, 0x200, &actual_length, DATA_TIMEOUT); | ||
258 | |||
259 | if (ret < 0) { | ||
260 | usb_dbg(usbatm, "%s: read BLOCK4 from modem failed (%d)!\n", __func__, ret); | ||
261 | goto out_free; | ||
262 | } | ||
263 | |||
264 | /* success */ | ||
265 | usb_dbg(usbatm, "%s: BLOCK4 downloaded (%d bytes)\n", __func__, actual_length); | ||
266 | |||
267 | /* Delay to allow firmware to start up. We can do this here | ||
268 | because we're in our own kernel thread anyway. */ | ||
269 | msleep_interruptible(1000); | ||
270 | |||
271 | /* Enable software buffering, if requested */ | ||
272 | if (sw_buffering) | ||
273 | speedtch_set_swbuff(instance, 1); | ||
274 | |||
275 | /* Magic spell; don't ask us what this does */ | ||
276 | speedtch_test_sequence(instance); | ||
277 | |||
278 | ret = 0; | ||
279 | |||
280 | out_free: | ||
281 | free_page((unsigned long)buffer); | ||
282 | out: | ||
283 | return ret; | ||
261 | } | 284 | } |
262 | 285 | ||
263 | static void speedtch_handle_int(struct urb *urb, struct pt_regs *regs) | 286 | static int speedtch_find_firmware(struct usb_interface *intf, int phase, |
287 | const struct firmware **fw_p) | ||
264 | { | 288 | { |
265 | struct speedtch_instance_data *instance = urb->context; | 289 | struct device *dev = &intf->dev; |
266 | unsigned int count = urb->actual_length; | 290 | const u16 bcdDevice = le16_to_cpu(interface_to_usbdev(intf)->descriptor.bcdDevice); |
267 | int ret; | 291 | const u8 major_revision = bcdDevice >> 8; |
292 | const u8 minor_revision = bcdDevice & 0xff; | ||
293 | char buf[24]; | ||
268 | 294 | ||
269 | /* The magic interrupt for "up state" */ | 295 | sprintf(buf, "speedtch-%d.bin.%x.%02x", phase, major_revision, minor_revision); |
270 | const static unsigned char up_int[6] = { 0xa1, 0x00, 0x01, 0x00, 0x00, 0x00 }; | 296 | dev_dbg(dev, "%s: looking for %s\n", __func__, buf); |
271 | /* The magic interrupt for "down state" */ | ||
272 | const static unsigned char down_int[6] = { 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00 }; | ||
273 | 297 | ||
274 | switch (urb->status) { | 298 | if (request_firmware(fw_p, buf, dev)) { |
275 | case 0: | 299 | sprintf(buf, "speedtch-%d.bin.%x", phase, major_revision); |
276 | /* success */ | 300 | dev_dbg(dev, "%s: looking for %s\n", __func__, buf); |
277 | break; | ||
278 | case -ECONNRESET: | ||
279 | case -ENOENT: | ||
280 | case -ESHUTDOWN: | ||
281 | /* this urb is terminated; clean up */ | ||
282 | dbg("%s - urb shutting down with status: %d", __func__, urb->status); | ||
283 | return; | ||
284 | default: | ||
285 | dbg("%s - nonzero urb status received: %d", __func__, urb->status); | ||
286 | goto exit; | ||
287 | } | ||
288 | 301 | ||
289 | if (count < 6) { | 302 | if (request_firmware(fw_p, buf, dev)) { |
290 | dbg("%s - int packet too short", __func__); | 303 | sprintf(buf, "speedtch-%d.bin", phase); |
291 | goto exit; | 304 | dev_dbg(dev, "%s: looking for %s\n", __func__, buf); |
305 | |||
306 | if (request_firmware(fw_p, buf, dev)) { | ||
307 | dev_warn(dev, "no stage %d firmware found!\n", phase); | ||
308 | return -ENOENT; | ||
309 | } | ||
310 | } | ||
292 | } | 311 | } |
293 | 312 | ||
294 | if (!memcmp(up_int, instance->int_data, 6)) { | 313 | dev_info(dev, "found stage %d firmware %s\n", phase, buf); |
295 | del_timer(&instance->poll_timer); | ||
296 | printk(KERN_NOTICE "DSL line goes up\n"); | ||
297 | } else if (!memcmp(down_int, instance->int_data, 6)) { | ||
298 | printk(KERN_NOTICE "DSL line goes down\n"); | ||
299 | } else { | ||
300 | int i; | ||
301 | 314 | ||
302 | printk(KERN_DEBUG "Unknown interrupt packet of %d bytes:", count); | 315 | return 0; |
303 | for (i = 0; i < count; i++) | 316 | } |
304 | printk(" %02x", instance->int_data[i]); | 317 | |
305 | printk("\n"); | 318 | static int speedtch_heavy_init(struct usbatm_data *usbatm, struct usb_interface *intf) |
319 | { | ||
320 | const struct firmware *fw1, *fw2; | ||
321 | struct speedtch_instance_data *instance = usbatm->driver_data; | ||
322 | int ret; | ||
323 | |||
324 | if ((ret = speedtch_find_firmware(intf, 1, &fw1)) < 0) | ||
325 | return ret; | ||
326 | |||
327 | if ((ret = speedtch_find_firmware(intf, 2, &fw2)) < 0) { | ||
328 | release_firmware(fw1); | ||
329 | return ret; | ||
306 | } | 330 | } |
307 | schedule_work(&instance->poll_work); | ||
308 | 331 | ||
309 | exit: | 332 | ret = speedtch_upload_firmware(instance, fw1, fw2); |
310 | rmb(); | 333 | |
311 | if (!instance->int_urb) | 334 | release_firmware(fw2); |
312 | return; | 335 | release_firmware(fw1); |
313 | 336 | ||
314 | ret = usb_submit_urb(urb, GFP_ATOMIC); | 337 | return ret; |
315 | if (ret) | ||
316 | err("%s - usb_submit_urb failed with result %d", __func__, ret); | ||
317 | } | 338 | } |
318 | 339 | ||
319 | static int speedtch_get_status(struct speedtch_instance_data *instance, | 340 | |
320 | unsigned char *buf) | 341 | /********** |
342 | ** ATM ** | ||
343 | **********/ | ||
344 | |||
345 | static int speedtch_read_status(struct speedtch_instance_data *instance) | ||
321 | { | 346 | { |
322 | struct usb_device *dev = instance->u.usb_dev; | 347 | struct usbatm_data *usbatm = instance->usbatm; |
348 | struct usb_device *usb_dev = usbatm->usb_dev; | ||
349 | unsigned char *buf = instance->scratch_buffer; | ||
323 | int ret; | 350 | int ret; |
324 | 351 | ||
325 | memset(buf, 0, TOTAL); | 352 | memset(buf, 0, TOTAL); |
326 | 353 | ||
327 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | 354 | ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), |
328 | 0x12, 0xc0, 0x07, 0x00, buf + OFFSET_7, SIZE_7, | 355 | 0x12, 0xc0, 0x07, 0x00, buf + OFFSET_7, SIZE_7, |
329 | CTRL_TIMEOUT); | 356 | CTRL_TIMEOUT); |
330 | if (ret < 0) { | 357 | if (ret < 0) { |
331 | dbg("MSG 7 failed"); | 358 | atm_dbg(usbatm, "%s: MSG 7 failed\n", __func__); |
332 | return ret; | 359 | return ret; |
333 | } | 360 | } |
334 | 361 | ||
335 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | 362 | ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), |
336 | 0x12, 0xc0, 0x0b, 0x00, buf + OFFSET_b, SIZE_b, | 363 | 0x12, 0xc0, 0x0b, 0x00, buf + OFFSET_b, SIZE_b, |
337 | CTRL_TIMEOUT); | 364 | CTRL_TIMEOUT); |
338 | if (ret < 0) { | 365 | if (ret < 0) { |
339 | dbg("MSG B failed"); | 366 | atm_dbg(usbatm, "%s: MSG B failed\n", __func__); |
340 | return ret; | 367 | return ret; |
341 | } | 368 | } |
342 | 369 | ||
343 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | 370 | ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), |
344 | 0x12, 0xc0, 0x0d, 0x00, buf + OFFSET_d, SIZE_d, | 371 | 0x12, 0xc0, 0x0d, 0x00, buf + OFFSET_d, SIZE_d, |
345 | CTRL_TIMEOUT); | 372 | CTRL_TIMEOUT); |
346 | if (ret < 0) { | 373 | if (ret < 0) { |
347 | dbg("MSG D failed"); | 374 | atm_dbg(usbatm, "%s: MSG D failed\n", __func__); |
348 | return ret; | 375 | return ret; |
349 | } | 376 | } |
350 | 377 | ||
351 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | 378 | ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), |
352 | 0x01, 0xc0, 0x0e, 0x00, buf + OFFSET_e, SIZE_e, | 379 | 0x01, 0xc0, 0x0e, 0x00, buf + OFFSET_e, SIZE_e, |
353 | CTRL_TIMEOUT); | 380 | CTRL_TIMEOUT); |
354 | if (ret < 0) { | 381 | if (ret < 0) { |
355 | dbg("MSG E failed"); | 382 | atm_dbg(usbatm, "%s: MSG E failed\n", __func__); |
356 | return ret; | 383 | return ret; |
357 | } | 384 | } |
358 | 385 | ||
359 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | 386 | ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), |
360 | 0x01, 0xc0, 0x0f, 0x00, buf + OFFSET_f, SIZE_f, | 387 | 0x01, 0xc0, 0x0f, 0x00, buf + OFFSET_f, SIZE_f, |
361 | CTRL_TIMEOUT); | 388 | CTRL_TIMEOUT); |
362 | if (ret < 0) { | 389 | if (ret < 0) { |
363 | dbg("MSG F failed"); | 390 | atm_dbg(usbatm, "%s: MSG F failed\n", __func__); |
364 | return ret; | 391 | return ret; |
365 | } | 392 | } |
366 | 393 | ||
367 | return 0; | 394 | return 0; |
368 | } | 395 | } |
369 | 396 | ||
370 | static void speedtch_poll_status(struct speedtch_instance_data *instance) | 397 | static int speedtch_start_synchro(struct speedtch_instance_data *instance) |
371 | { | 398 | { |
372 | unsigned char buf[TOTAL]; | 399 | struct usbatm_data *usbatm = instance->usbatm; |
400 | struct usb_device *usb_dev = usbatm->usb_dev; | ||
401 | unsigned char *buf = instance->scratch_buffer; | ||
373 | int ret; | 402 | int ret; |
374 | 403 | ||
375 | ret = speedtch_get_status(instance, buf); | 404 | atm_dbg(usbatm, "%s entered\n", __func__); |
376 | if (ret) { | 405 | |
377 | printk(KERN_WARNING | 406 | memset(buf, 0, 2); |
378 | "SpeedTouch: Error %d fetching device status\n", ret); | 407 | |
408 | ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
409 | 0x12, 0xc0, 0x04, 0x00, | ||
410 | buf, 2, CTRL_TIMEOUT); | ||
411 | |||
412 | if (ret < 0) | ||
413 | atm_warn(usbatm, "failed to start ADSL synchronisation: %d\n", ret); | ||
414 | else | ||
415 | atm_dbg(usbatm, "%s: modem prodded. %d bytes returned: %02x %02x\n", | ||
416 | __func__, ret, buf[0], buf[1]); | ||
417 | |||
418 | return ret; | ||
419 | } | ||
420 | |||
421 | static void speedtch_check_status(struct speedtch_instance_data *instance) | ||
422 | { | ||
423 | struct usbatm_data *usbatm = instance->usbatm; | ||
424 | struct atm_dev *atm_dev = usbatm->atm_dev; | ||
425 | unsigned char *buf = instance->scratch_buffer; | ||
426 | int ret; | ||
427 | |||
428 | atm_dbg(usbatm, "%s entered\n", __func__); | ||
429 | |||
430 | ret = speedtch_read_status(instance); | ||
431 | if (ret < 0) { | ||
432 | atm_warn(usbatm, "error %d fetching device status\n", ret); | ||
433 | if (instance->poll_delay < MAX_POLL_DELAY) | ||
434 | instance->poll_delay *= 2; | ||
379 | return; | 435 | return; |
380 | } | 436 | } |
381 | 437 | ||
382 | dbg("Line state %02x", buf[OFFSET_7]); | 438 | if (instance->poll_delay > MIN_POLL_DELAY) |
439 | instance->poll_delay /= 2; | ||
440 | |||
441 | atm_dbg(usbatm, "%s: line state %02x\n", __func__, buf[OFFSET_7]); | ||
383 | 442 | ||
384 | switch (buf[OFFSET_7]) { | 443 | switch (buf[OFFSET_7]) { |
385 | case 0: | 444 | case 0: |
386 | if (instance->u.atm_dev->signal != ATM_PHY_SIG_LOST) { | 445 | if (atm_dev->signal != ATM_PHY_SIG_LOST) { |
387 | instance->u.atm_dev->signal = ATM_PHY_SIG_LOST; | 446 | atm_dev->signal = ATM_PHY_SIG_LOST; |
388 | printk(KERN_NOTICE "ADSL line is down\n"); | 447 | atm_info(usbatm, "ADSL line is down\n"); |
389 | /* It'll never resync again unless we ask it to... */ | 448 | /* It'll never resync again unless we ask it to... */ |
390 | speedtch_start_synchro(instance); | 449 | ret = speedtch_start_synchro(instance); |
391 | } | 450 | } |
392 | break; | 451 | break; |
393 | 452 | ||
394 | case 0x08: | 453 | case 0x08: |
395 | if (instance->u.atm_dev->signal != ATM_PHY_SIG_UNKNOWN) { | 454 | if (atm_dev->signal != ATM_PHY_SIG_UNKNOWN) { |
396 | instance->u.atm_dev->signal = ATM_PHY_SIG_UNKNOWN; | 455 | atm_dev->signal = ATM_PHY_SIG_UNKNOWN; |
397 | printk(KERN_NOTICE "ADSL line is blocked?\n"); | 456 | atm_info(usbatm, "ADSL line is blocked?\n"); |
398 | } | 457 | } |
399 | break; | 458 | break; |
400 | 459 | ||
401 | case 0x10: | 460 | case 0x10: |
402 | if (instance->u.atm_dev->signal != ATM_PHY_SIG_LOST) { | 461 | if (atm_dev->signal != ATM_PHY_SIG_LOST) { |
403 | instance->u.atm_dev->signal = ATM_PHY_SIG_LOST; | 462 | atm_dev->signal = ATM_PHY_SIG_LOST; |
404 | printk(KERN_NOTICE "ADSL line is synchronising\n"); | 463 | atm_info(usbatm, "ADSL line is synchronising\n"); |
405 | } | 464 | } |
406 | break; | 465 | break; |
407 | 466 | ||
408 | case 0x20: | 467 | case 0x20: |
409 | if (instance->u.atm_dev->signal != ATM_PHY_SIG_FOUND) { | 468 | if (atm_dev->signal != ATM_PHY_SIG_FOUND) { |
410 | int down_speed = buf[OFFSET_b] | (buf[OFFSET_b + 1] << 8) | 469 | int down_speed = buf[OFFSET_b] | (buf[OFFSET_b + 1] << 8) |
411 | | (buf[OFFSET_b + 2] << 16) | (buf[OFFSET_b + 3] << 24); | 470 | | (buf[OFFSET_b + 2] << 16) | (buf[OFFSET_b + 3] << 24); |
412 | int up_speed = buf[OFFSET_b + 4] | (buf[OFFSET_b + 5] << 8) | 471 | int up_speed = buf[OFFSET_b + 4] | (buf[OFFSET_b + 5] << 8) |
413 | | (buf[OFFSET_b + 6] << 16) | (buf[OFFSET_b + 7] << 24); | 472 | | (buf[OFFSET_b + 6] << 16) | (buf[OFFSET_b + 7] << 24); |
414 | 473 | ||
415 | if (!(down_speed & 0x0000ffff) && | 474 | if (!(down_speed & 0x0000ffff) && !(up_speed & 0x0000ffff)) { |
416 | !(up_speed & 0x0000ffff)) { | ||
417 | down_speed >>= 16; | 475 | down_speed >>= 16; |
418 | up_speed >>= 16; | 476 | up_speed >>= 16; |
419 | } | 477 | } |
420 | instance->u.atm_dev->link_rate = down_speed * 1000 / 424; | ||
421 | instance->u.atm_dev->signal = ATM_PHY_SIG_FOUND; | ||
422 | 478 | ||
423 | printk(KERN_NOTICE | 479 | atm_dev->link_rate = down_speed * 1000 / 424; |
424 | "ADSL line is up (%d Kib/s down | %d Kib/s up)\n", | 480 | atm_dev->signal = ATM_PHY_SIG_FOUND; |
425 | down_speed, up_speed); | 481 | |
482 | atm_info(usbatm, | ||
483 | "ADSL line is up (%d Kib/s down | %d Kib/s up)\n", | ||
484 | down_speed, up_speed); | ||
426 | } | 485 | } |
427 | break; | 486 | break; |
428 | 487 | ||
429 | default: | 488 | default: |
430 | if (instance->u.atm_dev->signal != ATM_PHY_SIG_UNKNOWN) { | 489 | if (atm_dev->signal != ATM_PHY_SIG_UNKNOWN) { |
431 | instance->u.atm_dev->signal = ATM_PHY_SIG_UNKNOWN; | 490 | atm_dev->signal = ATM_PHY_SIG_UNKNOWN; |
432 | printk(KERN_NOTICE "Unknown line state %02x\n", buf[OFFSET_7]); | 491 | atm_info(usbatm, "Unknown line state %02x\n", buf[OFFSET_7]); |
433 | } | 492 | } |
434 | break; | 493 | break; |
435 | } | 494 | } |
436 | } | 495 | } |
437 | 496 | ||
438 | static void speedtch_timer_poll(unsigned long data) | 497 | static void speedtch_status_poll(unsigned long data) |
439 | { | 498 | { |
440 | struct speedtch_instance_data *instance = (void *)data; | 499 | struct speedtch_instance_data *instance = (void *)data; |
441 | 500 | ||
442 | schedule_work(&instance->poll_work); | 501 | schedule_work(&instance->status_checker); |
443 | mod_timer(&instance->poll_timer, jiffies + (5 * HZ)); | 502 | |
503 | /* The following check is racy, but the race is harmless */ | ||
504 | if (instance->poll_delay < MAX_POLL_DELAY) | ||
505 | mod_timer(&instance->status_checker.timer, jiffies + msecs_to_jiffies(instance->poll_delay)); | ||
506 | else | ||
507 | atm_warn(instance->usbatm, "Too many failures - disabling line status polling\n"); | ||
444 | } | 508 | } |
445 | 509 | ||
446 | #ifdef USE_FW_LOADER | 510 | static void speedtch_resubmit_int(unsigned long data) |
447 | static void speedtch_upload_firmware(struct speedtch_instance_data *instance, | ||
448 | const struct firmware *fw1, | ||
449 | const struct firmware *fw2) | ||
450 | { | 511 | { |
451 | unsigned char *buffer; | 512 | struct speedtch_instance_data *instance = (void *)data; |
452 | struct usb_device *usb_dev = instance->u.usb_dev; | 513 | struct urb *int_urb = instance->int_urb; |
453 | struct usb_interface *intf; | 514 | int ret; |
454 | int actual_length, ret; | ||
455 | int offset; | ||
456 | |||
457 | dbg("speedtch_upload_firmware"); | ||
458 | |||
459 | if (!(intf = usb_ifnum_to_if(usb_dev, 2))) { | ||
460 | dbg("speedtch_upload_firmware: interface not found!"); | ||
461 | goto fail; | ||
462 | } | ||
463 | |||
464 | if (!(buffer = (unsigned char *)__get_free_page(GFP_KERNEL))) { | ||
465 | dbg("speedtch_upload_firmware: no memory for buffer!"); | ||
466 | goto fail; | ||
467 | } | ||
468 | |||
469 | /* A user-space firmware loader may already have claimed interface #2 */ | ||
470 | if ((ret = | ||
471 | usb_driver_claim_interface(&speedtch_usb_driver, intf, NULL)) < 0) { | ||
472 | dbg("speedtch_upload_firmware: interface in use (%d)!", ret); | ||
473 | goto fail_free; | ||
474 | } | ||
475 | |||
476 | /* URB 7 */ | ||
477 | if (dl_512_first) { /* some modems need a read before writing the firmware */ | ||
478 | ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, SPEEDTCH_ENDPOINT_FIRMWARE), | ||
479 | buffer, 0x200, &actual_length, 2000); | ||
480 | |||
481 | if (ret < 0 && ret != -ETIMEDOUT) | ||
482 | dbg("speedtch_upload_firmware: read BLOCK0 from modem failed (%d)!", ret); | ||
483 | else | ||
484 | dbg("speedtch_upload_firmware: BLOCK0 downloaded (%d bytes)", ret); | ||
485 | } | ||
486 | |||
487 | /* URB 8 : both leds are static green */ | ||
488 | for (offset = 0; offset < fw1->size; offset += PAGE_SIZE) { | ||
489 | int thislen = min_t(int, PAGE_SIZE, fw1->size - offset); | ||
490 | memcpy(buffer, fw1->data + offset, thislen); | ||
491 | 515 | ||
492 | ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, SPEEDTCH_ENDPOINT_FIRMWARE), | 516 | atm_dbg(instance->usbatm, "%s entered\n", __func__); |
493 | buffer, thislen, &actual_length, DATA_TIMEOUT); | ||
494 | 517 | ||
495 | if (ret < 0) { | 518 | if (int_urb) { |
496 | dbg("speedtch_upload_firmware: write BLOCK1 to modem failed (%d)!", ret); | 519 | ret = usb_submit_urb(int_urb, GFP_ATOMIC); |
497 | goto fail_release; | 520 | if (!ret) |
521 | schedule_work(&instance->status_checker); | ||
522 | else { | ||
523 | atm_dbg(instance->usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret); | ||
524 | mod_timer(&instance->resubmit_timer, jiffies + msecs_to_jiffies(RESUBMIT_DELAY)); | ||
498 | } | 525 | } |
499 | dbg("speedtch_upload_firmware: BLOCK1 uploaded (%zu bytes)", fw1->size); | ||
500 | } | 526 | } |
527 | } | ||
501 | 528 | ||
502 | /* USB led blinking green, ADSL led off */ | 529 | static void speedtch_handle_int(struct urb *int_urb, struct pt_regs *regs) |
530 | { | ||
531 | struct speedtch_instance_data *instance = int_urb->context; | ||
532 | struct usbatm_data *usbatm = instance->usbatm; | ||
533 | unsigned int count = int_urb->actual_length; | ||
534 | int ret = int_urb->status; | ||
503 | 535 | ||
504 | /* URB 11 */ | 536 | /* The magic interrupt for "up state" */ |
505 | ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, SPEEDTCH_ENDPOINT_FIRMWARE), | 537 | const static unsigned char up_int[6] = { 0xa1, 0x00, 0x01, 0x00, 0x00, 0x00 }; |
506 | buffer, 0x200, &actual_length, DATA_TIMEOUT); | 538 | /* The magic interrupt for "down state" */ |
539 | const static unsigned char down_int[6] = { 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00 }; | ||
540 | |||
541 | atm_dbg(usbatm, "%s entered\n", __func__); | ||
507 | 542 | ||
508 | if (ret < 0) { | 543 | if (ret < 0) { |
509 | dbg("speedtch_upload_firmware: read BLOCK2 from modem failed (%d)!", ret); | 544 | atm_dbg(usbatm, "%s: nonzero urb status %d!\n", __func__, ret); |
510 | goto fail_release; | 545 | goto fail; |
511 | } | 546 | } |
512 | dbg("speedtch_upload_firmware: BLOCK2 downloaded (%d bytes)", actual_length); | ||
513 | 547 | ||
514 | /* URBs 12 to 139 - USB led blinking green, ADSL led off */ | 548 | if ((count == 6) && !memcmp(up_int, instance->int_data, 6)) { |
515 | for (offset = 0; offset < fw2->size; offset += PAGE_SIZE) { | 549 | del_timer(&instance->status_checker.timer); |
516 | int thislen = min_t(int, PAGE_SIZE, fw2->size - offset); | 550 | atm_info(usbatm, "DSL line goes up\n"); |
517 | memcpy(buffer, fw2->data + offset, thislen); | 551 | } else if ((count == 6) && !memcmp(down_int, instance->int_data, 6)) { |
552 | atm_info(usbatm, "DSL line goes down\n"); | ||
553 | } else { | ||
554 | int i; | ||
518 | 555 | ||
519 | ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, SPEEDTCH_ENDPOINT_FIRMWARE), | 556 | atm_dbg(usbatm, "%s: unknown interrupt packet of length %d:", __func__, count); |
520 | buffer, thislen, &actual_length, DATA_TIMEOUT); | 557 | for (i = 0; i < count; i++) |
558 | printk(" %02x", instance->int_data[i]); | ||
559 | printk("\n"); | ||
560 | goto fail; | ||
561 | } | ||
521 | 562 | ||
563 | if ((int_urb = instance->int_urb)) { | ||
564 | ret = usb_submit_urb(int_urb, GFP_ATOMIC); | ||
565 | schedule_work(&instance->status_checker); | ||
522 | if (ret < 0) { | 566 | if (ret < 0) { |
523 | dbg("speedtch_upload_firmware: write BLOCK3 to modem failed (%d)!", ret); | 567 | atm_dbg(usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret); |
524 | goto fail_release; | 568 | goto fail; |
525 | } | 569 | } |
526 | } | 570 | } |
527 | dbg("speedtch_upload_firmware: BLOCK3 uploaded (%zu bytes)", fw2->size); | ||
528 | |||
529 | /* USB led static green, ADSL led static red */ | ||
530 | |||
531 | /* URB 142 */ | ||
532 | ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, SPEEDTCH_ENDPOINT_FIRMWARE), | ||
533 | buffer, 0x200, &actual_length, DATA_TIMEOUT); | ||
534 | |||
535 | if (ret < 0) { | ||
536 | dbg("speedtch_upload_firmware: read BLOCK4 from modem failed (%d)!", ret); | ||
537 | goto fail_release; | ||
538 | } | ||
539 | |||
540 | /* success */ | ||
541 | dbg("speedtch_upload_firmware: BLOCK4 downloaded (%d bytes)", actual_length); | ||
542 | |||
543 | /* Delay to allow firmware to start up. We can do this here | ||
544 | because we're in our own kernel thread anyway. */ | ||
545 | msleep(1000); | ||
546 | |||
547 | /* Enable software buffering, if requested */ | ||
548 | if (sw_buffering) | ||
549 | speedtch_set_swbuff(instance, 1); | ||
550 | |||
551 | /* Magic spell; don't ask us what this does */ | ||
552 | speedtch_test_sequence(instance); | ||
553 | |||
554 | /* Start modem synchronisation */ | ||
555 | if (speedtch_start_synchro(instance)) | ||
556 | dbg("speedtch_start_synchro: failed"); | ||
557 | |||
558 | speedtch_got_firmware(instance, 1); | ||
559 | 571 | ||
560 | free_page((unsigned long)buffer); | ||
561 | return; | 572 | return; |
562 | 573 | ||
563 | fail_release: | 574 | fail: |
564 | /* Only release interface #2 if uploading failed; we don't release it | 575 | if ((int_urb = instance->int_urb)) |
565 | we succeeded. This prevents the userspace tools from trying to load | 576 | mod_timer(&instance->resubmit_timer, jiffies + msecs_to_jiffies(RESUBMIT_DELAY)); |
566 | the firmware themselves */ | ||
567 | usb_driver_release_interface(&speedtch_usb_driver, intf); | ||
568 | fail_free: | ||
569 | free_page((unsigned long)buffer); | ||
570 | fail: | ||
571 | speedtch_got_firmware(instance, 0); | ||
572 | } | 577 | } |
573 | 578 | ||
574 | static int speedtch_find_firmware(struct speedtch_instance_data | 579 | static int speedtch_atm_start(struct usbatm_data *usbatm, struct atm_dev *atm_dev) |
575 | *instance, int phase, | ||
576 | const struct firmware **fw_p) | ||
577 | { | 580 | { |
578 | char buf[24]; | 581 | struct usb_device *usb_dev = usbatm->usb_dev; |
579 | const u16 bcdDevice = le16_to_cpu(instance->u.usb_dev->descriptor.bcdDevice); | 582 | struct speedtch_instance_data *instance = usbatm->driver_data; |
580 | const u8 major_revision = bcdDevice >> 8; | 583 | int i, ret; |
581 | const u8 minor_revision = bcdDevice & 0xff; | 584 | unsigned char mac_str[13]; |
582 | |||
583 | sprintf(buf, "speedtch-%d.bin.%x.%02x", phase, major_revision, minor_revision); | ||
584 | dbg("speedtch_find_firmware: looking for %s", buf); | ||
585 | |||
586 | if (request_firmware(fw_p, buf, &instance->u.usb_dev->dev)) { | ||
587 | sprintf(buf, "speedtch-%d.bin.%x", phase, major_revision); | ||
588 | dbg("speedtch_find_firmware: looking for %s", buf); | ||
589 | 585 | ||
590 | if (request_firmware(fw_p, buf, &instance->u.usb_dev->dev)) { | 586 | atm_dbg(usbatm, "%s entered\n", __func__); |
591 | sprintf(buf, "speedtch-%d.bin", phase); | ||
592 | dbg("speedtch_find_firmware: looking for %s", buf); | ||
593 | 587 | ||
594 | if (request_firmware(fw_p, buf, &instance->u.usb_dev->dev)) { | 588 | if ((ret = usb_set_interface(usb_dev, 1, altsetting)) < 0) { |
595 | dev_warn(&instance->u.usb_dev->dev, "no stage %d firmware found!", phase); | 589 | atm_dbg(usbatm, "%s: usb_set_interface returned %d!\n", __func__, ret); |
596 | return -ENOENT; | 590 | return ret; |
597 | } | ||
598 | } | ||
599 | } | 591 | } |
600 | 592 | ||
601 | dev_info(&instance->u.usb_dev->dev, "found stage %d firmware %s\n", phase, buf); | 593 | /* Set MAC address, it is stored in the serial number */ |
602 | 594 | memset(atm_dev->esi, 0, sizeof(atm_dev->esi)); | |
603 | return 0; | 595 | if (usb_string(usb_dev, usb_dev->descriptor.iSerialNumber, mac_str, sizeof(mac_str)) == 12) { |
604 | } | 596 | for (i = 0; i < 6; i++) |
605 | 597 | atm_dev->esi[i] = (hex2int(mac_str[i * 2]) * 16) + (hex2int(mac_str[i * 2 + 1])); | |
606 | static int speedtch_load_firmware(void *arg) | 598 | } |
607 | { | ||
608 | const struct firmware *fw1, *fw2; | ||
609 | struct speedtch_instance_data *instance = arg; | ||
610 | |||
611 | BUG_ON(!instance); | ||
612 | 599 | ||
613 | daemonize("firmware/speedtch"); | 600 | /* Start modem synchronisation */ |
601 | ret = speedtch_start_synchro(instance); | ||
614 | 602 | ||
615 | if (!speedtch_find_firmware(instance, 1, &fw1)) { | 603 | /* Set up interrupt endpoint */ |
616 | if (!speedtch_find_firmware(instance, 2, &fw2)) { | 604 | if (instance->int_urb) { |
617 | speedtch_upload_firmware(instance, fw1, fw2); | 605 | ret = usb_submit_urb(instance->int_urb, GFP_KERNEL); |
618 | release_firmware(fw2); | 606 | if (ret < 0) { |
607 | /* Doesn't matter; we'll poll anyway */ | ||
608 | atm_dbg(usbatm, "%s: submission of interrupt URB failed (%d)!\n", __func__, ret); | ||
609 | usb_free_urb(instance->int_urb); | ||
610 | instance->int_urb = NULL; | ||
619 | } | 611 | } |
620 | release_firmware(fw1); | ||
621 | } | 612 | } |
622 | 613 | ||
623 | /* In case we failed, set state back to NO_FIRMWARE so that | 614 | /* Start status polling */ |
624 | another later attempt may work. Otherwise, we never actually | 615 | mod_timer(&instance->status_checker.timer, jiffies + msecs_to_jiffies(1000)); |
625 | manage to recover if, for example, the firmware is on /usr and | ||
626 | we look for it too early. */ | ||
627 | speedtch_got_firmware(instance, 0); | ||
628 | 616 | ||
629 | module_put(THIS_MODULE); | ||
630 | udsl_put_instance(&instance->u); | ||
631 | return 0; | 617 | return 0; |
632 | } | 618 | } |
633 | #endif /* USE_FW_LOADER */ | ||
634 | 619 | ||
635 | static void speedtch_firmware_start(struct speedtch_instance_data *instance) | 620 | static void speedtch_atm_stop(struct usbatm_data *usbatm, struct atm_dev *atm_dev) |
636 | { | 621 | { |
637 | #ifdef USE_FW_LOADER | 622 | struct speedtch_instance_data *instance = usbatm->driver_data; |
638 | int ret; | 623 | struct urb *int_urb = instance->int_urb; |
639 | #endif | 624 | |
640 | 625 | atm_dbg(usbatm, "%s entered\n", __func__); | |
641 | dbg("speedtch_firmware_start"); | 626 | |
642 | 627 | del_timer_sync(&instance->status_checker.timer); | |
643 | down(&instance->u.serialize); /* vs self, speedtch_got_firmware */ | 628 | |
644 | 629 | /* | |
645 | if (instance->u.status >= UDSL_LOADING_FIRMWARE) { | 630 | * Since resubmit_timer and int_urb can schedule themselves and |
646 | up(&instance->u.serialize); | 631 | * each other, shutting them down correctly takes some care |
647 | return; | 632 | */ |
648 | } | 633 | instance->int_urb = NULL; /* signal shutdown */ |
634 | mb(); | ||
635 | usb_kill_urb(int_urb); | ||
636 | del_timer_sync(&instance->resubmit_timer); | ||
637 | /* | ||
638 | * At this point, speedtch_handle_int and speedtch_resubmit_int | ||
639 | * can run or be running, but instance->int_urb == NULL means that | ||
640 | * they will not reschedule | ||
641 | */ | ||
642 | usb_kill_urb(int_urb); | ||
643 | del_timer_sync(&instance->resubmit_timer); | ||
644 | usb_free_urb(int_urb); | ||
649 | 645 | ||
650 | instance->u.status = UDSL_LOADING_FIRMWARE; | 646 | flush_scheduled_work(); |
651 | up(&instance->u.serialize); | 647 | } |
652 | 648 | ||
653 | #ifdef USE_FW_LOADER | ||
654 | udsl_get_instance(&instance->u); | ||
655 | try_module_get(THIS_MODULE); | ||
656 | 649 | ||
657 | ret = kernel_thread(speedtch_load_firmware, instance, | 650 | /********** |
658 | CLONE_FS | CLONE_FILES); | 651 | ** USB ** |
652 | **********/ | ||
659 | 653 | ||
660 | if (ret >= 0) | 654 | static struct usb_device_id speedtch_usb_ids[] = { |
661 | return; /* OK */ | 655 | {USB_DEVICE(0x06b9, 0x4061)}, |
656 | {} | ||
657 | }; | ||
662 | 658 | ||
663 | dbg("speedtch_firmware_start: kernel_thread failed (%d)!", ret); | 659 | MODULE_DEVICE_TABLE(usb, speedtch_usb_ids); |
664 | 660 | ||
665 | module_put(THIS_MODULE); | 661 | static int speedtch_usb_probe(struct usb_interface *, const struct usb_device_id *); |
666 | udsl_put_instance(&instance->u); | ||
667 | /* Just pretend it never happened... hope modem_run happens */ | ||
668 | #endif /* USE_FW_LOADER */ | ||
669 | 662 | ||
670 | speedtch_got_firmware(instance, 0); | 663 | static struct usb_driver speedtch_usb_driver = { |
671 | } | 664 | .owner = THIS_MODULE, |
672 | 665 | .name = speedtch_driver_name, | |
673 | static int speedtch_firmware_wait(struct udsl_instance_data *instance) | 666 | .probe = speedtch_usb_probe, |
674 | { | 667 | .disconnect = usbatm_usb_disconnect, |
675 | speedtch_firmware_start((void *)instance); | 668 | .id_table = speedtch_usb_ids |
669 | }; | ||
676 | 670 | ||
677 | if (wait_event_interruptible(instance->firmware_waiters, instance->status != UDSL_LOADING_FIRMWARE) < 0) | 671 | static void speedtch_release_interfaces(struct usb_device *usb_dev, int num_interfaces) { |
678 | return -ERESTARTSYS; | 672 | struct usb_interface *cur_intf; |
673 | int i; | ||
679 | 674 | ||
680 | return (instance->status == UDSL_LOADED_FIRMWARE) ? 0 : -EAGAIN; | 675 | for(i = 0; i < num_interfaces; i++) |
676 | if ((cur_intf = usb_ifnum_to_if(usb_dev, i))) { | ||
677 | usb_set_intfdata(cur_intf, NULL); | ||
678 | usb_driver_release_interface(&speedtch_usb_driver, cur_intf); | ||
679 | } | ||
681 | } | 680 | } |
682 | 681 | ||
683 | /********** | 682 | static int speedtch_bind(struct usbatm_data *usbatm, |
684 | ** USB ** | 683 | struct usb_interface *intf, |
685 | **********/ | 684 | const struct usb_device_id *id, |
686 | 685 | int *need_heavy_init) | |
687 | static int speedtch_usb_ioctl(struct usb_interface *intf, unsigned int code, | ||
688 | void *user_data) | ||
689 | { | 686 | { |
690 | struct speedtch_instance_data *instance = usb_get_intfdata(intf); | 687 | struct usb_device *usb_dev = interface_to_usbdev(intf); |
688 | struct usb_interface *cur_intf; | ||
689 | struct speedtch_instance_data *instance; | ||
690 | int ifnum = intf->altsetting->desc.bInterfaceNumber; | ||
691 | int num_interfaces = usb_dev->actconfig->desc.bNumInterfaces; | ||
692 | int i, ret; | ||
691 | 693 | ||
692 | dbg("speedtch_usb_ioctl entered"); | 694 | usb_dbg(usbatm, "%s entered\n", __func__); |
693 | 695 | ||
694 | if (!instance) { | 696 | if (usb_dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) { |
695 | dbg("speedtch_usb_ioctl: NULL instance!"); | 697 | usb_dbg(usbatm, "%s: wrong device class %d\n", __func__, usb_dev->descriptor.bDeviceClass); |
696 | return -ENODEV; | 698 | return -ENODEV; |
697 | } | 699 | } |
698 | 700 | ||
699 | switch (code) { | 701 | /* claim all interfaces */ |
700 | case UDSL_IOCTL_LINE_UP: | ||
701 | instance->u.atm_dev->signal = ATM_PHY_SIG_FOUND; | ||
702 | speedtch_got_firmware(instance, 1); | ||
703 | return (instance->u.status == UDSL_LOADED_FIRMWARE) ? 0 : -EIO; | ||
704 | case UDSL_IOCTL_LINE_DOWN: | ||
705 | instance->u.atm_dev->signal = ATM_PHY_SIG_LOST; | ||
706 | return 0; | ||
707 | default: | ||
708 | return -ENOTTY; | ||
709 | } | ||
710 | } | ||
711 | 702 | ||
712 | static int speedtch_usb_probe(struct usb_interface *intf, | 703 | for (i=0; i < num_interfaces; i++) { |
713 | const struct usb_device_id *id) | 704 | cur_intf = usb_ifnum_to_if(usb_dev, i); |
714 | { | ||
715 | struct usb_device *dev = interface_to_usbdev(intf); | ||
716 | int ifnum = intf->altsetting->desc.bInterfaceNumber; | ||
717 | struct speedtch_instance_data *instance; | ||
718 | unsigned char mac_str[13]; | ||
719 | int ret, i; | ||
720 | char buf7[SIZE_7]; | ||
721 | 705 | ||
722 | dbg("speedtch_usb_probe: trying device with vendor=0x%x, product=0x%x, ifnum %d", | 706 | if ((i != ifnum) && cur_intf) { |
723 | le16_to_cpu(dev->descriptor.idVendor), | 707 | ret = usb_driver_claim_interface(&speedtch_usb_driver, cur_intf, usbatm); |
724 | le16_to_cpu(dev->descriptor.idProduct), ifnum); | ||
725 | 708 | ||
726 | if ((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) || | 709 | if (ret < 0) { |
727 | (ifnum != 1)) | 710 | usb_dbg(usbatm, "%s: failed to claim interface %d (%d)\n", __func__, i, ret); |
728 | return -ENODEV; | 711 | speedtch_release_interfaces(usb_dev, i); |
729 | 712 | return ret; | |
730 | dbg("speedtch_usb_probe: device accepted"); | 713 | } |
714 | } | ||
715 | } | ||
731 | 716 | ||
732 | /* instance init */ | ||
733 | instance = kmalloc(sizeof(*instance), GFP_KERNEL); | 717 | instance = kmalloc(sizeof(*instance), GFP_KERNEL); |
718 | |||
734 | if (!instance) { | 719 | if (!instance) { |
735 | dbg("speedtch_usb_probe: no memory for instance data!"); | 720 | usb_dbg(usbatm, "%s: no memory for instance data!\n", __func__); |
736 | return -ENOMEM; | 721 | ret = -ENOMEM; |
722 | goto fail_release; | ||
737 | } | 723 | } |
738 | 724 | ||
739 | memset(instance, 0, sizeof(struct speedtch_instance_data)); | 725 | memset(instance, 0, sizeof(struct speedtch_instance_data)); |
740 | 726 | ||
741 | if ((ret = usb_set_interface(dev, 0, 0)) < 0) | 727 | instance->usbatm = usbatm; |
742 | goto fail; | ||
743 | 728 | ||
744 | if ((ret = usb_set_interface(dev, 2, 0)) < 0) | 729 | INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance); |
745 | goto fail; | ||
746 | 730 | ||
747 | instance->u.data_endpoint = SPEEDTCH_ENDPOINT_DATA; | 731 | instance->status_checker.timer.function = speedtch_status_poll; |
748 | instance->u.firmware_wait = speedtch_firmware_wait; | 732 | instance->status_checker.timer.data = (unsigned long)instance; |
749 | instance->u.driver_name = speedtch_driver_name; | 733 | instance->poll_delay = MIN_POLL_DELAY; |
750 | 734 | ||
751 | ret = udsl_instance_setup(dev, &instance->u); | 735 | init_timer(&instance->resubmit_timer); |
752 | if (ret) | 736 | instance->resubmit_timer.function = speedtch_resubmit_int; |
753 | goto fail; | 737 | instance->resubmit_timer.data = (unsigned long)instance; |
754 | 738 | ||
755 | init_timer(&instance->poll_timer); | 739 | instance->int_urb = usb_alloc_urb(0, GFP_KERNEL); |
756 | instance->poll_timer.function = speedtch_timer_poll; | ||
757 | instance->poll_timer.data = (unsigned long)instance; | ||
758 | 740 | ||
759 | INIT_WORK(&instance->poll_work, (void *)speedtch_poll_status, instance); | 741 | if (instance->int_urb) |
742 | usb_fill_int_urb(instance->int_urb, usb_dev, | ||
743 | usb_rcvintpipe(usb_dev, ENDPOINT_INT), | ||
744 | instance->int_data, sizeof(instance->int_data), | ||
745 | speedtch_handle_int, instance, 50); | ||
746 | else | ||
747 | usb_dbg(usbatm, "%s: no memory for interrupt urb!\n", __func__); | ||
760 | 748 | ||
761 | /* set MAC address, it is stored in the serial number */ | 749 | /* check whether the modem already seems to be alive */ |
762 | memset(instance->u.atm_dev->esi, 0, sizeof(instance->u.atm_dev->esi)); | 750 | ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), |
763 | if (usb_string(dev, dev->descriptor.iSerialNumber, mac_str, sizeof(mac_str)) == 12) { | 751 | 0x12, 0xc0, 0x07, 0x00, |
764 | for (i = 0; i < 6; i++) | 752 | instance->scratch_buffer + OFFSET_7, SIZE_7, 500); |
765 | instance->u.atm_dev->esi[i] = | ||
766 | (hex2int(mac_str[i * 2]) * 16) + (hex2int(mac_str[i * 2 + 1])); | ||
767 | } | ||
768 | 753 | ||
769 | /* First check whether the modem already seems to be alive */ | 754 | *need_heavy_init = (ret != SIZE_7); |
770 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
771 | 0x12, 0xc0, 0x07, 0x00, buf7, SIZE_7, 500); | ||
772 | 755 | ||
773 | if (ret == SIZE_7) { | 756 | usb_dbg(usbatm, "%s: firmware %s loaded\n", __func__, need_heavy_init ? "not" : "already"); |
774 | dbg("firmware appears to be already loaded"); | 757 | |
775 | speedtch_got_firmware(instance, 1); | 758 | if (*need_heavy_init) |
776 | speedtch_poll_status(instance); | 759 | if ((ret = usb_reset_device(usb_dev)) < 0) |
777 | } else { | 760 | goto fail_free; |
778 | speedtch_firmware_start(instance); | ||
779 | } | ||
780 | 761 | ||
781 | usb_set_intfdata(intf, instance); | 762 | usbatm->driver_data = instance; |
782 | 763 | ||
783 | return 0; | 764 | return 0; |
784 | 765 | ||
785 | fail: | 766 | fail_free: |
767 | usb_free_urb(instance->int_urb); | ||
786 | kfree(instance); | 768 | kfree(instance); |
787 | 769 | fail_release: | |
788 | return -ENOMEM; | 770 | speedtch_release_interfaces(usb_dev, num_interfaces); |
771 | return ret; | ||
789 | } | 772 | } |
790 | 773 | ||
791 | static void speedtch_usb_disconnect(struct usb_interface *intf) | 774 | static void speedtch_unbind(struct usbatm_data *usbatm, struct usb_interface *intf) |
792 | { | 775 | { |
793 | struct speedtch_instance_data *instance = usb_get_intfdata(intf); | 776 | struct usb_device *usb_dev = interface_to_usbdev(intf); |
794 | 777 | struct speedtch_instance_data *instance = usbatm->driver_data; | |
795 | dbg("speedtch_usb_disconnect entered"); | ||
796 | |||
797 | if (!instance) { | ||
798 | dbg("speedtch_usb_disconnect: NULL instance!"); | ||
799 | return; | ||
800 | } | ||
801 | 778 | ||
802 | /*QQ need to handle disconnects on interface #2 while uploading firmware */ | 779 | usb_dbg(usbatm, "%s entered\n", __func__); |
803 | /*QQ and what about interface #1? */ | ||
804 | |||
805 | if (instance->int_urb) { | ||
806 | struct urb *int_urb = instance->int_urb; | ||
807 | instance->int_urb = NULL; | ||
808 | wmb(); | ||
809 | usb_unlink_urb(int_urb); | ||
810 | usb_free_urb(int_urb); | ||
811 | } | ||
812 | 780 | ||
813 | instance->int_data[0] = 1; | 781 | speedtch_release_interfaces(usb_dev, usb_dev->actconfig->desc.bNumInterfaces); |
814 | del_timer_sync(&instance->poll_timer); | 782 | usb_free_urb(instance->int_urb); |
815 | wmb(); | 783 | kfree(instance); |
816 | flush_scheduled_work(); | ||
817 | |||
818 | udsl_instance_disconnect(&instance->u); | ||
819 | |||
820 | /* clean up */ | ||
821 | usb_set_intfdata(intf, NULL); | ||
822 | udsl_put_instance(&instance->u); | ||
823 | } | 784 | } |
824 | 785 | ||
786 | |||
825 | /*********** | 787 | /*********** |
826 | ** init ** | 788 | ** init ** |
827 | ***********/ | 789 | ***********/ |
828 | 790 | ||
791 | static struct usbatm_driver speedtch_usbatm_driver = { | ||
792 | .owner = THIS_MODULE, | ||
793 | .driver_name = speedtch_driver_name, | ||
794 | .bind = speedtch_bind, | ||
795 | .heavy_init = speedtch_heavy_init, | ||
796 | .unbind = speedtch_unbind, | ||
797 | .atm_start = speedtch_atm_start, | ||
798 | .atm_stop = speedtch_atm_stop, | ||
799 | .in = ENDPOINT_DATA, | ||
800 | .out = ENDPOINT_DATA | ||
801 | }; | ||
802 | |||
803 | static int speedtch_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
804 | { | ||
805 | return usbatm_usb_probe(intf, id, &speedtch_usbatm_driver); | ||
806 | } | ||
807 | |||
829 | static int __init speedtch_usb_init(void) | 808 | static int __init speedtch_usb_init(void) |
830 | { | 809 | { |
831 | dbg("speedtch_usb_init: driver version " DRIVER_VERSION); | 810 | dbg("%s: driver version %s", __func__, DRIVER_VERSION); |
832 | 811 | ||
833 | return usb_register(&speedtch_usb_driver); | 812 | return usb_register(&speedtch_usb_driver); |
834 | } | 813 | } |
835 | 814 | ||
836 | static void __exit speedtch_usb_cleanup(void) | 815 | static void __exit speedtch_usb_cleanup(void) |
837 | { | 816 | { |
838 | dbg("speedtch_usb_cleanup entered"); | 817 | dbg("%s", __func__); |
839 | 818 | ||
840 | usb_deregister(&speedtch_usb_driver); | 819 | usb_deregister(&speedtch_usb_driver); |
841 | } | 820 | } |
diff --git a/drivers/usb/atm/usb_atm.c b/drivers/usb/atm/usb_atm.c deleted file mode 100644 index a4cd4476d49a..000000000000 --- a/drivers/usb/atm/usb_atm.c +++ /dev/null | |||
@@ -1,1188 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * usb_atm.c - Generic USB xDSL driver core | ||
3 | * | ||
4 | * Copyright (C) 2001, Alcatel | ||
5 | * Copyright (C) 2003, Duncan Sands, SolNegro, Josep Comas | ||
6 | * Copyright (C) 2004, David Woodhouse | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
20 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | * | ||
22 | ******************************************************************************/ | ||
23 | |||
24 | /* | ||
25 | * Written by Johan Verrept, maintained by Duncan Sands (duncan.sands@free.fr) | ||
26 | * | ||
27 | * 1.7+: - See the check-in logs | ||
28 | * | ||
29 | * 1.6: - No longer opens a connection if the firmware is not loaded | ||
30 | * - Added support for the speedtouch 330 | ||
31 | * - Removed the limit on the number of devices | ||
32 | * - Module now autoloads on device plugin | ||
33 | * - Merged relevant parts of sarlib | ||
34 | * - Replaced the kernel thread with a tasklet | ||
35 | * - New packet transmission code | ||
36 | * - Changed proc file contents | ||
37 | * - Fixed all known SMP races | ||
38 | * - Many fixes and cleanups | ||
39 | * - Various fixes by Oliver Neukum (oliver@neukum.name) | ||
40 | * | ||
41 | * 1.5A: - Version for inclusion in 2.5 series kernel | ||
42 | * - Modifications by Richard Purdie (rpurdie@rpsys.net) | ||
43 | * - made compatible with kernel 2.5.6 onwards by changing | ||
44 | * udsl_usb_send_data_context->urb to a pointer and adding code | ||
45 | * to alloc and free it | ||
46 | * - remove_wait_queue() added to udsl_atm_processqueue_thread() | ||
47 | * | ||
48 | * 1.5: - fixed memory leak when atmsar_decode_aal5 returned NULL. | ||
49 | * (reported by stephen.robinson@zen.co.uk) | ||
50 | * | ||
51 | * 1.4: - changed the spin_lock() under interrupt to spin_lock_irqsave() | ||
52 | * - unlink all active send urbs of a vcc that is being closed. | ||
53 | * | ||
54 | * 1.3.1: - added the version number | ||
55 | * | ||
56 | * 1.3: - Added multiple send urb support | ||
57 | * - fixed memory leak and vcc->tx_inuse starvation bug | ||
58 | * when not enough memory left in vcc. | ||
59 | * | ||
60 | * 1.2: - Fixed race condition in udsl_usb_send_data() | ||
61 | * 1.1: - Turned off packet debugging | ||
62 | * | ||
63 | */ | ||
64 | |||
65 | #include <linux/module.h> | ||
66 | #include <linux/moduleparam.h> | ||
67 | #include <linux/kernel.h> | ||
68 | #include <linux/sched.h> | ||
69 | #include <linux/timer.h> | ||
70 | #include <linux/errno.h> | ||
71 | #include <linux/proc_fs.h> | ||
72 | #include <linux/slab.h> | ||
73 | #include <linux/wait.h> | ||
74 | #include <linux/list.h> | ||
75 | #include <asm/uaccess.h> | ||
76 | #include <linux/smp_lock.h> | ||
77 | #include <linux/interrupt.h> | ||
78 | #include <linux/atm.h> | ||
79 | #include <linux/atmdev.h> | ||
80 | #include <linux/crc32.h> | ||
81 | #include <linux/init.h> | ||
82 | #include <linux/firmware.h> | ||
83 | |||
84 | #include "usb_atm.h" | ||
85 | |||
86 | #ifdef VERBOSE_DEBUG | ||
87 | static int udsl_print_packet(const unsigned char *data, int len); | ||
88 | #define PACKETDEBUG(arg...) udsl_print_packet (arg) | ||
89 | #define vdbg(arg...) dbg (arg) | ||
90 | #else | ||
91 | #define PACKETDEBUG(arg...) | ||
92 | #define vdbg(arg...) | ||
93 | #endif | ||
94 | |||
95 | #define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>" | ||
96 | #define DRIVER_VERSION "1.8" | ||
97 | #define DRIVER_DESC "Generic USB ATM/DSL I/O, version " DRIVER_VERSION | ||
98 | |||
99 | static unsigned int num_rcv_urbs = UDSL_DEFAULT_RCV_URBS; | ||
100 | static unsigned int num_snd_urbs = UDSL_DEFAULT_SND_URBS; | ||
101 | static unsigned int num_rcv_bufs = UDSL_DEFAULT_RCV_BUFS; | ||
102 | static unsigned int num_snd_bufs = UDSL_DEFAULT_SND_BUFS; | ||
103 | static unsigned int rcv_buf_size = UDSL_DEFAULT_RCV_BUF_SIZE; | ||
104 | static unsigned int snd_buf_size = UDSL_DEFAULT_SND_BUF_SIZE; | ||
105 | |||
106 | module_param(num_rcv_urbs, uint, 0444); | ||
107 | MODULE_PARM_DESC(num_rcv_urbs, | ||
108 | "Number of urbs used for reception (range: 0-" | ||
109 | __MODULE_STRING(UDSL_MAX_RCV_URBS) ", default: " | ||
110 | __MODULE_STRING(UDSL_DEFAULT_RCV_URBS) ")"); | ||
111 | |||
112 | module_param(num_snd_urbs, uint, 0444); | ||
113 | MODULE_PARM_DESC(num_snd_urbs, | ||
114 | "Number of urbs used for transmission (range: 0-" | ||
115 | __MODULE_STRING(UDSL_MAX_SND_URBS) ", default: " | ||
116 | __MODULE_STRING(UDSL_DEFAULT_SND_URBS) ")"); | ||
117 | |||
118 | module_param(num_rcv_bufs, uint, 0444); | ||
119 | MODULE_PARM_DESC(num_rcv_bufs, | ||
120 | "Number of buffers used for reception (range: 0-" | ||
121 | __MODULE_STRING(UDSL_MAX_RCV_BUFS) ", default: " | ||
122 | __MODULE_STRING(UDSL_DEFAULT_RCV_BUFS) ")"); | ||
123 | |||
124 | module_param(num_snd_bufs, uint, 0444); | ||
125 | MODULE_PARM_DESC(num_snd_bufs, | ||
126 | "Number of buffers used for transmission (range: 0-" | ||
127 | __MODULE_STRING(UDSL_MAX_SND_BUFS) ", default: " | ||
128 | __MODULE_STRING(UDSL_DEFAULT_SND_BUFS) ")"); | ||
129 | |||
130 | module_param(rcv_buf_size, uint, 0444); | ||
131 | MODULE_PARM_DESC(rcv_buf_size, | ||
132 | "Size of the buffers used for reception (range: 0-" | ||
133 | __MODULE_STRING(UDSL_MAX_RCV_BUF_SIZE) ", default: " | ||
134 | __MODULE_STRING(UDSL_DEFAULT_RCV_BUF_SIZE) ")"); | ||
135 | |||
136 | module_param(snd_buf_size, uint, 0444); | ||
137 | MODULE_PARM_DESC(snd_buf_size, | ||
138 | "Size of the buffers used for transmission (range: 0-" | ||
139 | __MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: " | ||
140 | __MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")"); | ||
141 | |||
142 | /* ATM */ | ||
143 | |||
144 | static void udsl_atm_dev_close(struct atm_dev *dev); | ||
145 | static int udsl_atm_open(struct atm_vcc *vcc); | ||
146 | static void udsl_atm_close(struct atm_vcc *vcc); | ||
147 | static int udsl_atm_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg); | ||
148 | static int udsl_atm_send(struct atm_vcc *vcc, struct sk_buff *skb); | ||
149 | static int udsl_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page); | ||
150 | |||
151 | static struct atmdev_ops udsl_atm_devops = { | ||
152 | .dev_close = udsl_atm_dev_close, | ||
153 | .open = udsl_atm_open, | ||
154 | .close = udsl_atm_close, | ||
155 | .ioctl = udsl_atm_ioctl, | ||
156 | .send = udsl_atm_send, | ||
157 | .proc_read = udsl_atm_proc_read, | ||
158 | .owner = THIS_MODULE, | ||
159 | }; | ||
160 | |||
161 | /*********** | ||
162 | ** misc ** | ||
163 | ***********/ | ||
164 | |||
165 | static inline void udsl_pop(struct atm_vcc *vcc, struct sk_buff *skb) | ||
166 | { | ||
167 | if (vcc->pop) | ||
168 | vcc->pop(vcc, skb); | ||
169 | else | ||
170 | dev_kfree_skb(skb); | ||
171 | } | ||
172 | |||
173 | /************* | ||
174 | ** decode ** | ||
175 | *************/ | ||
176 | |||
177 | static inline struct udsl_vcc_data *udsl_find_vcc(struct udsl_instance_data *instance, | ||
178 | short vpi, int vci) | ||
179 | { | ||
180 | struct udsl_vcc_data *vcc; | ||
181 | |||
182 | list_for_each_entry(vcc, &instance->vcc_list, list) | ||
183 | if ((vcc->vci == vci) && (vcc->vpi == vpi)) | ||
184 | return vcc; | ||
185 | return NULL; | ||
186 | } | ||
187 | |||
188 | static void udsl_extract_cells(struct udsl_instance_data *instance, | ||
189 | unsigned char *source, unsigned int howmany) | ||
190 | { | ||
191 | struct udsl_vcc_data *cached_vcc = NULL; | ||
192 | struct atm_vcc *vcc; | ||
193 | struct sk_buff *sarb; | ||
194 | struct udsl_vcc_data *vcc_data; | ||
195 | int cached_vci = 0; | ||
196 | unsigned int i; | ||
197 | int pti; | ||
198 | int vci; | ||
199 | short cached_vpi = 0; | ||
200 | short vpi; | ||
201 | |||
202 | for (i = 0; i < howmany; | ||
203 | i++, source += ATM_CELL_SIZE + instance->rcv_padding) { | ||
204 | vpi = ((source[0] & 0x0f) << 4) | (source[1] >> 4); | ||
205 | vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4); | ||
206 | pti = (source[3] & 0x2) != 0; | ||
207 | |||
208 | vdbg("udsl_extract_cells: vpi %hd, vci %d, pti %d", vpi, vci, pti); | ||
209 | |||
210 | if (cached_vcc && (vci == cached_vci) && (vpi == cached_vpi)) | ||
211 | vcc_data = cached_vcc; | ||
212 | else if ((vcc_data = udsl_find_vcc(instance, vpi, vci))) { | ||
213 | cached_vcc = vcc_data; | ||
214 | cached_vpi = vpi; | ||
215 | cached_vci = vci; | ||
216 | } else { | ||
217 | dbg("udsl_extract_cells: unknown vpi/vci (%hd/%d)!", vpi, vci); | ||
218 | continue; | ||
219 | } | ||
220 | |||
221 | vcc = vcc_data->vcc; | ||
222 | sarb = vcc_data->sarb; | ||
223 | |||
224 | if (sarb->tail + ATM_CELL_PAYLOAD > sarb->end) { | ||
225 | dbg("udsl_extract_cells: buffer overrun (sarb->len %u, vcc: 0x%p)!", sarb->len, vcc); | ||
226 | /* discard cells already received */ | ||
227 | skb_trim(sarb, 0); | ||
228 | } | ||
229 | |||
230 | memcpy(sarb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD); | ||
231 | __skb_put(sarb, ATM_CELL_PAYLOAD); | ||
232 | |||
233 | if (pti) { | ||
234 | struct sk_buff *skb; | ||
235 | unsigned int length; | ||
236 | unsigned int pdu_length; | ||
237 | |||
238 | length = (source[ATM_CELL_SIZE - 6] << 8) + source[ATM_CELL_SIZE - 5]; | ||
239 | |||
240 | /* guard against overflow */ | ||
241 | if (length > ATM_MAX_AAL5_PDU) { | ||
242 | dbg("udsl_extract_cells: bogus length %u (vcc: 0x%p)!", length, vcc); | ||
243 | atomic_inc(&vcc->stats->rx_err); | ||
244 | goto out; | ||
245 | } | ||
246 | |||
247 | pdu_length = UDSL_NUM_CELLS(length) * ATM_CELL_PAYLOAD; | ||
248 | |||
249 | if (sarb->len < pdu_length) { | ||
250 | dbg("udsl_extract_cells: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!", pdu_length, sarb->len, vcc); | ||
251 | atomic_inc(&vcc->stats->rx_err); | ||
252 | goto out; | ||
253 | } | ||
254 | |||
255 | if (crc32_be(~0, sarb->tail - pdu_length, pdu_length) != 0xc704dd7b) { | ||
256 | dbg("udsl_extract_cells: packet failed crc check (vcc: 0x%p)!", vcc); | ||
257 | atomic_inc(&vcc->stats->rx_err); | ||
258 | goto out; | ||
259 | } | ||
260 | |||
261 | vdbg("udsl_extract_cells: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", length, pdu_length, vcc); | ||
262 | |||
263 | if (!(skb = dev_alloc_skb(length))) { | ||
264 | dbg("udsl_extract_cells: no memory for skb (length: %u)!", length); | ||
265 | atomic_inc(&vcc->stats->rx_drop); | ||
266 | goto out; | ||
267 | } | ||
268 | |||
269 | vdbg("udsl_extract_cells: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", skb, skb->truesize); | ||
270 | |||
271 | if (!atm_charge(vcc, skb->truesize)) { | ||
272 | dbg("udsl_extract_cells: failed atm_charge (skb->truesize: %u)!", skb->truesize); | ||
273 | dev_kfree_skb(skb); | ||
274 | goto out; /* atm_charge increments rx_drop */ | ||
275 | } | ||
276 | |||
277 | memcpy(skb->data, sarb->tail - pdu_length, length); | ||
278 | __skb_put(skb, length); | ||
279 | |||
280 | vdbg("udsl_extract_cells: sending skb 0x%p, skb->len %u, skb->truesize %u", skb, skb->len, skb->truesize); | ||
281 | |||
282 | PACKETDEBUG(skb->data, skb->len); | ||
283 | |||
284 | vcc->push(vcc, skb); | ||
285 | |||
286 | atomic_inc(&vcc->stats->rx); | ||
287 | out: | ||
288 | skb_trim(sarb, 0); | ||
289 | } | ||
290 | } | ||
291 | } | ||
292 | |||
293 | /************* | ||
294 | ** encode ** | ||
295 | *************/ | ||
296 | |||
297 | static inline void udsl_fill_cell_header(unsigned char *target, struct atm_vcc *vcc) | ||
298 | { | ||
299 | target[0] = vcc->vpi >> 4; | ||
300 | target[1] = (vcc->vpi << 4) | (vcc->vci >> 12); | ||
301 | target[2] = vcc->vci >> 4; | ||
302 | target[3] = vcc->vci << 4; | ||
303 | target[4] = 0xec; | ||
304 | } | ||
305 | |||
306 | static const unsigned char zeros[ATM_CELL_PAYLOAD]; | ||
307 | |||
308 | static void udsl_groom_skb(struct atm_vcc *vcc, struct sk_buff *skb) | ||
309 | { | ||
310 | struct udsl_control *ctrl = UDSL_SKB(skb); | ||
311 | unsigned int zero_padding; | ||
312 | u32 crc; | ||
313 | |||
314 | ctrl->atm_data.vcc = vcc; | ||
315 | |||
316 | ctrl->num_cells = UDSL_NUM_CELLS(skb->len); | ||
317 | ctrl->num_entire = skb->len / ATM_CELL_PAYLOAD; | ||
318 | |||
319 | zero_padding = ctrl->num_cells * ATM_CELL_PAYLOAD - skb->len - ATM_AAL5_TRAILER; | ||
320 | |||
321 | if (ctrl->num_entire + 1 < ctrl->num_cells) | ||
322 | ctrl->pdu_padding = zero_padding - (ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER); | ||
323 | else | ||
324 | ctrl->pdu_padding = zero_padding; | ||
325 | |||
326 | ctrl->aal5_trailer[0] = 0; /* UU = 0 */ | ||
327 | ctrl->aal5_trailer[1] = 0; /* CPI = 0 */ | ||
328 | ctrl->aal5_trailer[2] = skb->len >> 8; | ||
329 | ctrl->aal5_trailer[3] = skb->len; | ||
330 | |||
331 | crc = crc32_be(~0, skb->data, skb->len); | ||
332 | crc = crc32_be(crc, zeros, zero_padding); | ||
333 | crc = crc32_be(crc, ctrl->aal5_trailer, 4); | ||
334 | crc = ~crc; | ||
335 | |||
336 | ctrl->aal5_trailer[4] = crc >> 24; | ||
337 | ctrl->aal5_trailer[5] = crc >> 16; | ||
338 | ctrl->aal5_trailer[6] = crc >> 8; | ||
339 | ctrl->aal5_trailer[7] = crc; | ||
340 | } | ||
341 | |||
342 | static unsigned int udsl_write_cells(struct udsl_instance_data *instance, | ||
343 | unsigned int howmany, struct sk_buff *skb, | ||
344 | unsigned char **target_p) | ||
345 | { | ||
346 | struct udsl_control *ctrl = UDSL_SKB(skb); | ||
347 | unsigned char *target = *target_p; | ||
348 | unsigned int nc, ne, i; | ||
349 | |||
350 | vdbg("udsl_write_cells: howmany=%u, skb->len=%d, num_cells=%u, num_entire=%u, pdu_padding=%u", howmany, skb->len, ctrl->num_cells, ctrl->num_entire, ctrl->pdu_padding); | ||
351 | |||
352 | nc = ctrl->num_cells; | ||
353 | ne = min(howmany, ctrl->num_entire); | ||
354 | |||
355 | for (i = 0; i < ne; i++) { | ||
356 | udsl_fill_cell_header(target, ctrl->atm_data.vcc); | ||
357 | target += ATM_CELL_HEADER; | ||
358 | memcpy(target, skb->data, ATM_CELL_PAYLOAD); | ||
359 | target += ATM_CELL_PAYLOAD; | ||
360 | if (instance->snd_padding) { | ||
361 | memset(target, 0, instance->snd_padding); | ||
362 | target += instance->snd_padding; | ||
363 | } | ||
364 | __skb_pull(skb, ATM_CELL_PAYLOAD); | ||
365 | } | ||
366 | |||
367 | ctrl->num_entire -= ne; | ||
368 | |||
369 | if (!(ctrl->num_cells -= ne) || !(howmany -= ne)) | ||
370 | goto out; | ||
371 | |||
372 | udsl_fill_cell_header(target, ctrl->atm_data.vcc); | ||
373 | target += ATM_CELL_HEADER; | ||
374 | memcpy(target, skb->data, skb->len); | ||
375 | target += skb->len; | ||
376 | __skb_pull(skb, skb->len); | ||
377 | memset(target, 0, ctrl->pdu_padding); | ||
378 | target += ctrl->pdu_padding; | ||
379 | |||
380 | if (--ctrl->num_cells) { | ||
381 | if (!--howmany) { | ||
382 | ctrl->pdu_padding = ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER; | ||
383 | goto out; | ||
384 | } | ||
385 | |||
386 | if (instance->snd_padding) { | ||
387 | memset(target, 0, instance->snd_padding); | ||
388 | target += instance->snd_padding; | ||
389 | } | ||
390 | udsl_fill_cell_header(target, ctrl->atm_data.vcc); | ||
391 | target += ATM_CELL_HEADER; | ||
392 | memset(target, 0, ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER); | ||
393 | target += ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER; | ||
394 | |||
395 | --ctrl->num_cells; | ||
396 | UDSL_ASSERT(!ctrl->num_cells); | ||
397 | } | ||
398 | |||
399 | memcpy(target, ctrl->aal5_trailer, ATM_AAL5_TRAILER); | ||
400 | target += ATM_AAL5_TRAILER; | ||
401 | /* set pti bit in last cell */ | ||
402 | *(target + 3 - ATM_CELL_SIZE) |= 0x2; | ||
403 | if (instance->snd_padding) { | ||
404 | memset(target, 0, instance->snd_padding); | ||
405 | target += instance->snd_padding; | ||
406 | } | ||
407 | out: | ||
408 | *target_p = target; | ||
409 | return nc - ctrl->num_cells; | ||
410 | } | ||
411 | |||
412 | /************** | ||
413 | ** receive ** | ||
414 | **************/ | ||
415 | |||
416 | static void udsl_complete_receive(struct urb *urb, struct pt_regs *regs) | ||
417 | { | ||
418 | struct udsl_receive_buffer *buf; | ||
419 | struct udsl_instance_data *instance; | ||
420 | struct udsl_receiver *rcv; | ||
421 | unsigned long flags; | ||
422 | |||
423 | if (!urb || !(rcv = urb->context)) { | ||
424 | dbg("udsl_complete_receive: bad urb!"); | ||
425 | return; | ||
426 | } | ||
427 | |||
428 | instance = rcv->instance; | ||
429 | buf = rcv->buffer; | ||
430 | |||
431 | buf->filled_cells = urb->actual_length / (ATM_CELL_SIZE + instance->rcv_padding); | ||
432 | |||
433 | vdbg("udsl_complete_receive: urb 0x%p, status %d, actual_length %d, filled_cells %u, rcv 0x%p, buf 0x%p", urb, urb->status, urb->actual_length, buf->filled_cells, rcv, buf); | ||
434 | |||
435 | UDSL_ASSERT(buf->filled_cells <= rcv_buf_size); | ||
436 | |||
437 | /* may not be in_interrupt() */ | ||
438 | spin_lock_irqsave(&instance->receive_lock, flags); | ||
439 | list_add(&rcv->list, &instance->spare_receivers); | ||
440 | list_add_tail(&buf->list, &instance->filled_receive_buffers); | ||
441 | if (likely(!urb->status)) | ||
442 | tasklet_schedule(&instance->receive_tasklet); | ||
443 | spin_unlock_irqrestore(&instance->receive_lock, flags); | ||
444 | } | ||
445 | |||
446 | static void udsl_process_receive(unsigned long data) | ||
447 | { | ||
448 | struct udsl_receive_buffer *buf; | ||
449 | struct udsl_instance_data *instance = (struct udsl_instance_data *)data; | ||
450 | struct udsl_receiver *rcv; | ||
451 | int err; | ||
452 | |||
453 | made_progress: | ||
454 | while (!list_empty(&instance->spare_receive_buffers)) { | ||
455 | spin_lock_irq(&instance->receive_lock); | ||
456 | if (list_empty(&instance->spare_receivers)) { | ||
457 | spin_unlock_irq(&instance->receive_lock); | ||
458 | break; | ||
459 | } | ||
460 | rcv = list_entry(instance->spare_receivers.next, | ||
461 | struct udsl_receiver, list); | ||
462 | list_del(&rcv->list); | ||
463 | spin_unlock_irq(&instance->receive_lock); | ||
464 | |||
465 | buf = list_entry(instance->spare_receive_buffers.next, | ||
466 | struct udsl_receive_buffer, list); | ||
467 | list_del(&buf->list); | ||
468 | |||
469 | rcv->buffer = buf; | ||
470 | |||
471 | usb_fill_bulk_urb(rcv->urb, instance->usb_dev, | ||
472 | usb_rcvbulkpipe(instance->usb_dev, instance->data_endpoint), | ||
473 | buf->base, | ||
474 | rcv_buf_size * (ATM_CELL_SIZE + instance->rcv_padding), | ||
475 | udsl_complete_receive, rcv); | ||
476 | |||
477 | vdbg("udsl_process_receive: sending urb 0x%p, rcv 0x%p, buf 0x%p", | ||
478 | rcv->urb, rcv, buf); | ||
479 | |||
480 | if ((err = usb_submit_urb(rcv->urb, GFP_ATOMIC)) < 0) { | ||
481 | dbg("udsl_process_receive: urb submission failed (%d)!", err); | ||
482 | list_add(&buf->list, &instance->spare_receive_buffers); | ||
483 | spin_lock_irq(&instance->receive_lock); | ||
484 | list_add(&rcv->list, &instance->spare_receivers); | ||
485 | spin_unlock_irq(&instance->receive_lock); | ||
486 | break; | ||
487 | } | ||
488 | } | ||
489 | |||
490 | spin_lock_irq(&instance->receive_lock); | ||
491 | if (list_empty(&instance->filled_receive_buffers)) { | ||
492 | spin_unlock_irq(&instance->receive_lock); | ||
493 | return; /* done - no more buffers */ | ||
494 | } | ||
495 | buf = list_entry(instance->filled_receive_buffers.next, | ||
496 | struct udsl_receive_buffer, list); | ||
497 | list_del(&buf->list); | ||
498 | spin_unlock_irq(&instance->receive_lock); | ||
499 | |||
500 | vdbg("udsl_process_receive: processing buf 0x%p", buf); | ||
501 | udsl_extract_cells(instance, buf->base, buf->filled_cells); | ||
502 | list_add(&buf->list, &instance->spare_receive_buffers); | ||
503 | goto made_progress; | ||
504 | } | ||
505 | |||
506 | /*********** | ||
507 | ** send ** | ||
508 | ***********/ | ||
509 | |||
510 | static void udsl_complete_send(struct urb *urb, struct pt_regs *regs) | ||
511 | { | ||
512 | struct udsl_instance_data *instance; | ||
513 | struct udsl_sender *snd; | ||
514 | unsigned long flags; | ||
515 | |||
516 | if (!urb || !(snd = urb->context) || !(instance = snd->instance)) { | ||
517 | dbg("udsl_complete_send: bad urb!"); | ||
518 | return; | ||
519 | } | ||
520 | |||
521 | vdbg("udsl_complete_send: urb 0x%p, status %d, snd 0x%p, buf 0x%p", urb, | ||
522 | urb->status, snd, snd->buffer); | ||
523 | |||
524 | /* may not be in_interrupt() */ | ||
525 | spin_lock_irqsave(&instance->send_lock, flags); | ||
526 | list_add(&snd->list, &instance->spare_senders); | ||
527 | list_add(&snd->buffer->list, &instance->spare_send_buffers); | ||
528 | tasklet_schedule(&instance->send_tasklet); | ||
529 | spin_unlock_irqrestore(&instance->send_lock, flags); | ||
530 | } | ||
531 | |||
532 | static void udsl_process_send(unsigned long data) | ||
533 | { | ||
534 | struct udsl_send_buffer *buf; | ||
535 | struct udsl_instance_data *instance = (struct udsl_instance_data *)data; | ||
536 | struct sk_buff *skb; | ||
537 | struct udsl_sender *snd; | ||
538 | int err; | ||
539 | unsigned int num_written; | ||
540 | |||
541 | made_progress: | ||
542 | spin_lock_irq(&instance->send_lock); | ||
543 | while (!list_empty(&instance->spare_senders)) { | ||
544 | if (!list_empty(&instance->filled_send_buffers)) { | ||
545 | buf = list_entry(instance->filled_send_buffers.next, | ||
546 | struct udsl_send_buffer, list); | ||
547 | list_del(&buf->list); | ||
548 | } else if ((buf = instance->current_buffer)) { | ||
549 | instance->current_buffer = NULL; | ||
550 | } else /* all buffers empty */ | ||
551 | break; | ||
552 | |||
553 | snd = list_entry(instance->spare_senders.next, | ||
554 | struct udsl_sender, list); | ||
555 | list_del(&snd->list); | ||
556 | spin_unlock_irq(&instance->send_lock); | ||
557 | |||
558 | snd->buffer = buf; | ||
559 | usb_fill_bulk_urb(snd->urb, instance->usb_dev, | ||
560 | usb_sndbulkpipe(instance->usb_dev, instance->data_endpoint), | ||
561 | buf->base, | ||
562 | (snd_buf_size - buf->free_cells) * (ATM_CELL_SIZE + instance->snd_padding), | ||
563 | udsl_complete_send, snd); | ||
564 | |||
565 | vdbg("udsl_process_send: submitting urb 0x%p (%d cells), snd 0x%p, buf 0x%p", | ||
566 | snd->urb, snd_buf_size - buf->free_cells, snd, buf); | ||
567 | |||
568 | if ((err = usb_submit_urb(snd->urb, GFP_ATOMIC)) < 0) { | ||
569 | dbg("udsl_process_send: urb submission failed (%d)!", err); | ||
570 | spin_lock_irq(&instance->send_lock); | ||
571 | list_add(&snd->list, &instance->spare_senders); | ||
572 | spin_unlock_irq(&instance->send_lock); | ||
573 | list_add(&buf->list, &instance->filled_send_buffers); | ||
574 | return; /* bail out */ | ||
575 | } | ||
576 | |||
577 | spin_lock_irq(&instance->send_lock); | ||
578 | } /* while */ | ||
579 | spin_unlock_irq(&instance->send_lock); | ||
580 | |||
581 | if (!instance->current_skb) | ||
582 | instance->current_skb = skb_dequeue(&instance->sndqueue); | ||
583 | if (!instance->current_skb) | ||
584 | return; /* done - no more skbs */ | ||
585 | |||
586 | skb = instance->current_skb; | ||
587 | |||
588 | if (!(buf = instance->current_buffer)) { | ||
589 | spin_lock_irq(&instance->send_lock); | ||
590 | if (list_empty(&instance->spare_send_buffers)) { | ||
591 | instance->current_buffer = NULL; | ||
592 | spin_unlock_irq(&instance->send_lock); | ||
593 | return; /* done - no more buffers */ | ||
594 | } | ||
595 | buf = list_entry(instance->spare_send_buffers.next, | ||
596 | struct udsl_send_buffer, list); | ||
597 | list_del(&buf->list); | ||
598 | spin_unlock_irq(&instance->send_lock); | ||
599 | |||
600 | buf->free_start = buf->base; | ||
601 | buf->free_cells = snd_buf_size; | ||
602 | |||
603 | instance->current_buffer = buf; | ||
604 | } | ||
605 | |||
606 | num_written = udsl_write_cells(instance, buf->free_cells, skb, &buf->free_start); | ||
607 | |||
608 | vdbg("udsl_process_send: wrote %u cells from skb 0x%p to buffer 0x%p", | ||
609 | num_written, skb, buf); | ||
610 | |||
611 | if (!(buf->free_cells -= num_written)) { | ||
612 | list_add_tail(&buf->list, &instance->filled_send_buffers); | ||
613 | instance->current_buffer = NULL; | ||
614 | } | ||
615 | |||
616 | vdbg("udsl_process_send: buffer contains %d cells, %d left", | ||
617 | snd_buf_size - buf->free_cells, buf->free_cells); | ||
618 | |||
619 | if (!UDSL_SKB(skb)->num_cells) { | ||
620 | struct atm_vcc *vcc = UDSL_SKB(skb)->atm_data.vcc; | ||
621 | |||
622 | udsl_pop(vcc, skb); | ||
623 | instance->current_skb = NULL; | ||
624 | |||
625 | atomic_inc(&vcc->stats->tx); | ||
626 | } | ||
627 | |||
628 | goto made_progress; | ||
629 | } | ||
630 | |||
631 | static void udsl_cancel_send(struct udsl_instance_data *instance, | ||
632 | struct atm_vcc *vcc) | ||
633 | { | ||
634 | struct sk_buff *skb, *n; | ||
635 | |||
636 | dbg("udsl_cancel_send entered"); | ||
637 | spin_lock_irq(&instance->sndqueue.lock); | ||
638 | for (skb = instance->sndqueue.next, n = skb->next; | ||
639 | skb != (struct sk_buff *)&instance->sndqueue; | ||
640 | skb = n, n = skb->next) | ||
641 | if (UDSL_SKB(skb)->atm_data.vcc == vcc) { | ||
642 | dbg("udsl_cancel_send: popping skb 0x%p", skb); | ||
643 | __skb_unlink(skb, &instance->sndqueue); | ||
644 | udsl_pop(vcc, skb); | ||
645 | } | ||
646 | spin_unlock_irq(&instance->sndqueue.lock); | ||
647 | |||
648 | tasklet_disable(&instance->send_tasklet); | ||
649 | if ((skb = instance->current_skb) && (UDSL_SKB(skb)->atm_data.vcc == vcc)) { | ||
650 | dbg("udsl_cancel_send: popping current skb (0x%p)", skb); | ||
651 | instance->current_skb = NULL; | ||
652 | udsl_pop(vcc, skb); | ||
653 | } | ||
654 | tasklet_enable(&instance->send_tasklet); | ||
655 | dbg("udsl_cancel_send done"); | ||
656 | } | ||
657 | |||
658 | static int udsl_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) | ||
659 | { | ||
660 | struct udsl_instance_data *instance = vcc->dev->dev_data; | ||
661 | int err; | ||
662 | |||
663 | vdbg("udsl_atm_send called (skb 0x%p, len %u)", skb, skb->len); | ||
664 | |||
665 | if (!instance) { | ||
666 | dbg("udsl_atm_send: NULL data!"); | ||
667 | err = -ENODEV; | ||
668 | goto fail; | ||
669 | } | ||
670 | |||
671 | if (vcc->qos.aal != ATM_AAL5) { | ||
672 | dbg("udsl_atm_send: unsupported ATM type %d!", vcc->qos.aal); | ||
673 | err = -EINVAL; | ||
674 | goto fail; | ||
675 | } | ||
676 | |||
677 | if (skb->len > ATM_MAX_AAL5_PDU) { | ||
678 | dbg("udsl_atm_send: packet too long (%d vs %d)!", skb->len, | ||
679 | ATM_MAX_AAL5_PDU); | ||
680 | err = -EINVAL; | ||
681 | goto fail; | ||
682 | } | ||
683 | |||
684 | PACKETDEBUG(skb->data, skb->len); | ||
685 | |||
686 | udsl_groom_skb(vcc, skb); | ||
687 | skb_queue_tail(&instance->sndqueue, skb); | ||
688 | tasklet_schedule(&instance->send_tasklet); | ||
689 | |||
690 | return 0; | ||
691 | |||
692 | fail: | ||
693 | udsl_pop(vcc, skb); | ||
694 | return err; | ||
695 | } | ||
696 | |||
697 | /******************** | ||
698 | ** bean counting ** | ||
699 | ********************/ | ||
700 | |||
701 | static void udsl_destroy_instance(struct kref *kref) | ||
702 | { | ||
703 | struct udsl_instance_data *instance = | ||
704 | container_of(kref, struct udsl_instance_data, refcount); | ||
705 | |||
706 | tasklet_kill(&instance->receive_tasklet); | ||
707 | tasklet_kill(&instance->send_tasklet); | ||
708 | usb_put_dev(instance->usb_dev); | ||
709 | kfree(instance); | ||
710 | } | ||
711 | |||
712 | void udsl_get_instance(struct udsl_instance_data *instance) | ||
713 | { | ||
714 | kref_get(&instance->refcount); | ||
715 | } | ||
716 | |||
717 | void udsl_put_instance(struct udsl_instance_data *instance) | ||
718 | { | ||
719 | kref_put(&instance->refcount, udsl_destroy_instance); | ||
720 | } | ||
721 | |||
722 | /********** | ||
723 | ** ATM ** | ||
724 | **********/ | ||
725 | |||
726 | static void udsl_atm_dev_close(struct atm_dev *dev) | ||
727 | { | ||
728 | struct udsl_instance_data *instance = dev->dev_data; | ||
729 | |||
730 | dev->dev_data = NULL; | ||
731 | udsl_put_instance(instance); | ||
732 | } | ||
733 | |||
734 | static int udsl_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page) | ||
735 | { | ||
736 | struct udsl_instance_data *instance = atm_dev->dev_data; | ||
737 | int left = *pos; | ||
738 | |||
739 | if (!instance) { | ||
740 | dbg("udsl_atm_proc_read: NULL instance!"); | ||
741 | return -ENODEV; | ||
742 | } | ||
743 | |||
744 | if (!left--) | ||
745 | return sprintf(page, "%s\n", instance->description); | ||
746 | |||
747 | if (!left--) | ||
748 | return sprintf(page, "MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
749 | atm_dev->esi[0], atm_dev->esi[1], | ||
750 | atm_dev->esi[2], atm_dev->esi[3], | ||
751 | atm_dev->esi[4], atm_dev->esi[5]); | ||
752 | |||
753 | if (!left--) | ||
754 | return sprintf(page, | ||
755 | "AAL5: tx %d ( %d err ), rx %d ( %d err, %d drop )\n", | ||
756 | atomic_read(&atm_dev->stats.aal5.tx), | ||
757 | atomic_read(&atm_dev->stats.aal5.tx_err), | ||
758 | atomic_read(&atm_dev->stats.aal5.rx), | ||
759 | atomic_read(&atm_dev->stats.aal5.rx_err), | ||
760 | atomic_read(&atm_dev->stats.aal5.rx_drop)); | ||
761 | |||
762 | if (!left--) { | ||
763 | switch (atm_dev->signal) { | ||
764 | case ATM_PHY_SIG_FOUND: | ||
765 | sprintf(page, "Line up"); | ||
766 | break; | ||
767 | case ATM_PHY_SIG_LOST: | ||
768 | sprintf(page, "Line down"); | ||
769 | break; | ||
770 | default: | ||
771 | sprintf(page, "Line state unknown"); | ||
772 | break; | ||
773 | } | ||
774 | |||
775 | if (instance->usb_dev->state == USB_STATE_NOTATTACHED) | ||
776 | strcat(page, ", disconnected\n"); | ||
777 | else { | ||
778 | if (instance->status == UDSL_LOADED_FIRMWARE) | ||
779 | strcat(page, ", firmware loaded\n"); | ||
780 | else if (instance->status == UDSL_LOADING_FIRMWARE) | ||
781 | strcat(page, ", firmware loading\n"); | ||
782 | else | ||
783 | strcat(page, ", no firmware\n"); | ||
784 | } | ||
785 | |||
786 | return strlen(page); | ||
787 | } | ||
788 | |||
789 | return 0; | ||
790 | } | ||
791 | |||
792 | static int udsl_atm_open(struct atm_vcc *vcc) | ||
793 | { | ||
794 | struct udsl_instance_data *instance = vcc->dev->dev_data; | ||
795 | struct udsl_vcc_data *new; | ||
796 | unsigned int max_pdu; | ||
797 | int vci = vcc->vci; | ||
798 | short vpi = vcc->vpi; | ||
799 | int err; | ||
800 | |||
801 | dbg("udsl_atm_open: vpi %hd, vci %d", vpi, vci); | ||
802 | |||
803 | if (!instance) { | ||
804 | dbg("udsl_atm_open: NULL data!"); | ||
805 | return -ENODEV; | ||
806 | } | ||
807 | |||
808 | /* only support AAL5 */ | ||
809 | if ((vcc->qos.aal != ATM_AAL5) || (vcc->qos.rxtp.max_sdu < 0) | ||
810 | || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU)) { | ||
811 | dbg("udsl_atm_open: unsupported ATM type %d!", vcc->qos.aal); | ||
812 | return -EINVAL; | ||
813 | } | ||
814 | |||
815 | if (instance->firmware_wait && | ||
816 | (err = instance->firmware_wait(instance)) < 0) { | ||
817 | dbg("udsl_atm_open: firmware not loaded (%d)!", err); | ||
818 | return err; | ||
819 | } | ||
820 | |||
821 | down(&instance->serialize); /* vs self, udsl_atm_close */ | ||
822 | |||
823 | if (udsl_find_vcc(instance, vpi, vci)) { | ||
824 | dbg("udsl_atm_open: %hd/%d already in use!", vpi, vci); | ||
825 | up(&instance->serialize); | ||
826 | return -EADDRINUSE; | ||
827 | } | ||
828 | |||
829 | if (!(new = kmalloc(sizeof(struct udsl_vcc_data), GFP_KERNEL))) { | ||
830 | dbg("udsl_atm_open: no memory for vcc_data!"); | ||
831 | up(&instance->serialize); | ||
832 | return -ENOMEM; | ||
833 | } | ||
834 | |||
835 | memset(new, 0, sizeof(struct udsl_vcc_data)); | ||
836 | new->vcc = vcc; | ||
837 | new->vpi = vpi; | ||
838 | new->vci = vci; | ||
839 | |||
840 | /* udsl_extract_cells requires at least one cell */ | ||
841 | max_pdu = max(1, UDSL_NUM_CELLS(vcc->qos.rxtp.max_sdu)) * ATM_CELL_PAYLOAD; | ||
842 | if (!(new->sarb = alloc_skb(max_pdu, GFP_KERNEL))) { | ||
843 | dbg("udsl_atm_open: no memory for SAR buffer!"); | ||
844 | kfree(new); | ||
845 | up(&instance->serialize); | ||
846 | return -ENOMEM; | ||
847 | } | ||
848 | |||
849 | vcc->dev_data = new; | ||
850 | |||
851 | tasklet_disable(&instance->receive_tasklet); | ||
852 | list_add(&new->list, &instance->vcc_list); | ||
853 | tasklet_enable(&instance->receive_tasklet); | ||
854 | |||
855 | set_bit(ATM_VF_ADDR, &vcc->flags); | ||
856 | set_bit(ATM_VF_PARTIAL, &vcc->flags); | ||
857 | set_bit(ATM_VF_READY, &vcc->flags); | ||
858 | |||
859 | up(&instance->serialize); | ||
860 | |||
861 | tasklet_schedule(&instance->receive_tasklet); | ||
862 | |||
863 | dbg("udsl_atm_open: allocated vcc data 0x%p (max_pdu: %u)", new, max_pdu); | ||
864 | |||
865 | return 0; | ||
866 | } | ||
867 | |||
868 | static void udsl_atm_close(struct atm_vcc *vcc) | ||
869 | { | ||
870 | struct udsl_instance_data *instance = vcc->dev->dev_data; | ||
871 | struct udsl_vcc_data *vcc_data = vcc->dev_data; | ||
872 | |||
873 | dbg("udsl_atm_close called"); | ||
874 | |||
875 | if (!instance || !vcc_data) { | ||
876 | dbg("udsl_atm_close: NULL data!"); | ||
877 | return; | ||
878 | } | ||
879 | |||
880 | dbg("udsl_atm_close: deallocating vcc 0x%p with vpi %d vci %d", | ||
881 | vcc_data, vcc_data->vpi, vcc_data->vci); | ||
882 | |||
883 | udsl_cancel_send(instance, vcc); | ||
884 | |||
885 | down(&instance->serialize); /* vs self, udsl_atm_open */ | ||
886 | |||
887 | tasklet_disable(&instance->receive_tasklet); | ||
888 | list_del(&vcc_data->list); | ||
889 | tasklet_enable(&instance->receive_tasklet); | ||
890 | |||
891 | kfree_skb(vcc_data->sarb); | ||
892 | vcc_data->sarb = NULL; | ||
893 | |||
894 | kfree(vcc_data); | ||
895 | vcc->dev_data = NULL; | ||
896 | |||
897 | vcc->vpi = ATM_VPI_UNSPEC; | ||
898 | vcc->vci = ATM_VCI_UNSPEC; | ||
899 | clear_bit(ATM_VF_READY, &vcc->flags); | ||
900 | clear_bit(ATM_VF_PARTIAL, &vcc->flags); | ||
901 | clear_bit(ATM_VF_ADDR, &vcc->flags); | ||
902 | |||
903 | up(&instance->serialize); | ||
904 | |||
905 | dbg("udsl_atm_close successful"); | ||
906 | } | ||
907 | |||
908 | static int udsl_atm_ioctl(struct atm_dev *dev, unsigned int cmd, | ||
909 | void __user * arg) | ||
910 | { | ||
911 | switch (cmd) { | ||
912 | case ATM_QUERYLOOP: | ||
913 | return put_user(ATM_LM_NONE, (int __user *)arg) ? -EFAULT : 0; | ||
914 | default: | ||
915 | return -ENOIOCTLCMD; | ||
916 | } | ||
917 | } | ||
918 | |||
919 | /********** | ||
920 | ** USB ** | ||
921 | **********/ | ||
922 | |||
923 | int udsl_instance_setup(struct usb_device *dev, | ||
924 | struct udsl_instance_data *instance) | ||
925 | { | ||
926 | char *buf; | ||
927 | int i, length; | ||
928 | |||
929 | kref_init(&instance->refcount); /* one for USB */ | ||
930 | udsl_get_instance(instance); /* one for ATM */ | ||
931 | |||
932 | init_MUTEX(&instance->serialize); | ||
933 | |||
934 | instance->usb_dev = dev; | ||
935 | |||
936 | INIT_LIST_HEAD(&instance->vcc_list); | ||
937 | |||
938 | instance->status = UDSL_NO_FIRMWARE; | ||
939 | init_waitqueue_head(&instance->firmware_waiters); | ||
940 | |||
941 | spin_lock_init(&instance->receive_lock); | ||
942 | INIT_LIST_HEAD(&instance->spare_receivers); | ||
943 | INIT_LIST_HEAD(&instance->filled_receive_buffers); | ||
944 | |||
945 | tasklet_init(&instance->receive_tasklet, udsl_process_receive, (unsigned long)instance); | ||
946 | INIT_LIST_HEAD(&instance->spare_receive_buffers); | ||
947 | |||
948 | skb_queue_head_init(&instance->sndqueue); | ||
949 | |||
950 | spin_lock_init(&instance->send_lock); | ||
951 | INIT_LIST_HEAD(&instance->spare_senders); | ||
952 | INIT_LIST_HEAD(&instance->spare_send_buffers); | ||
953 | |||
954 | tasklet_init(&instance->send_tasklet, udsl_process_send, | ||
955 | (unsigned long)instance); | ||
956 | INIT_LIST_HEAD(&instance->filled_send_buffers); | ||
957 | |||
958 | /* receive init */ | ||
959 | for (i = 0; i < num_rcv_urbs; i++) { | ||
960 | struct udsl_receiver *rcv = &(instance->receivers[i]); | ||
961 | |||
962 | if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) { | ||
963 | dbg("udsl_usb_probe: no memory for receive urb %d!", i); | ||
964 | goto fail; | ||
965 | } | ||
966 | |||
967 | rcv->instance = instance; | ||
968 | |||
969 | list_add(&rcv->list, &instance->spare_receivers); | ||
970 | } | ||
971 | |||
972 | for (i = 0; i < num_rcv_bufs; i++) { | ||
973 | struct udsl_receive_buffer *buf = | ||
974 | &(instance->receive_buffers[i]); | ||
975 | |||
976 | buf->base = kmalloc(rcv_buf_size * (ATM_CELL_SIZE + instance->rcv_padding), | ||
977 | GFP_KERNEL); | ||
978 | if (!buf->base) { | ||
979 | dbg("udsl_usb_probe: no memory for receive buffer %d!", i); | ||
980 | goto fail; | ||
981 | } | ||
982 | |||
983 | list_add(&buf->list, &instance->spare_receive_buffers); | ||
984 | } | ||
985 | |||
986 | /* send init */ | ||
987 | for (i = 0; i < num_snd_urbs; i++) { | ||
988 | struct udsl_sender *snd = &(instance->senders[i]); | ||
989 | |||
990 | if (!(snd->urb = usb_alloc_urb(0, GFP_KERNEL))) { | ||
991 | dbg("udsl_usb_probe: no memory for send urb %d!", i); | ||
992 | goto fail; | ||
993 | } | ||
994 | |||
995 | snd->instance = instance; | ||
996 | |||
997 | list_add(&snd->list, &instance->spare_senders); | ||
998 | } | ||
999 | |||
1000 | for (i = 0; i < num_snd_bufs; i++) { | ||
1001 | struct udsl_send_buffer *buf = &(instance->send_buffers[i]); | ||
1002 | |||
1003 | buf->base = kmalloc(snd_buf_size * (ATM_CELL_SIZE + instance->snd_padding), | ||
1004 | GFP_KERNEL); | ||
1005 | if (!buf->base) { | ||
1006 | dbg("udsl_usb_probe: no memory for send buffer %d!", i); | ||
1007 | goto fail; | ||
1008 | } | ||
1009 | |||
1010 | list_add(&buf->list, &instance->spare_send_buffers); | ||
1011 | } | ||
1012 | |||
1013 | /* ATM init */ | ||
1014 | instance->atm_dev = atm_dev_register(instance->driver_name, | ||
1015 | &udsl_atm_devops, -1, NULL); | ||
1016 | if (!instance->atm_dev) { | ||
1017 | dbg("udsl_usb_probe: failed to register ATM device!"); | ||
1018 | goto fail; | ||
1019 | } | ||
1020 | |||
1021 | instance->atm_dev->ci_range.vpi_bits = ATM_CI_MAX; | ||
1022 | instance->atm_dev->ci_range.vci_bits = ATM_CI_MAX; | ||
1023 | instance->atm_dev->signal = ATM_PHY_SIG_UNKNOWN; | ||
1024 | |||
1025 | /* temp init ATM device, set to 128kbit */ | ||
1026 | instance->atm_dev->link_rate = 128 * 1000 / 424; | ||
1027 | |||
1028 | /* device description */ | ||
1029 | buf = instance->description; | ||
1030 | length = sizeof(instance->description); | ||
1031 | |||
1032 | if ((i = usb_string(dev, dev->descriptor.iProduct, buf, length)) < 0) | ||
1033 | goto finish; | ||
1034 | |||
1035 | buf += i; | ||
1036 | length -= i; | ||
1037 | |||
1038 | i = scnprintf(buf, length, " ("); | ||
1039 | buf += i; | ||
1040 | length -= i; | ||
1041 | |||
1042 | if (length <= 0 || (i = usb_make_path(dev, buf, length)) < 0) | ||
1043 | goto finish; | ||
1044 | |||
1045 | buf += i; | ||
1046 | length -= i; | ||
1047 | |||
1048 | snprintf(buf, length, ")"); | ||
1049 | |||
1050 | finish: | ||
1051 | /* ready for ATM callbacks */ | ||
1052 | wmb(); | ||
1053 | instance->atm_dev->dev_data = instance; | ||
1054 | |||
1055 | usb_get_dev(dev); | ||
1056 | |||
1057 | return 0; | ||
1058 | |||
1059 | fail: | ||
1060 | for (i = 0; i < num_snd_bufs; i++) | ||
1061 | kfree(instance->send_buffers[i].base); | ||
1062 | |||
1063 | for (i = 0; i < num_snd_urbs; i++) | ||
1064 | usb_free_urb(instance->senders[i].urb); | ||
1065 | |||
1066 | for (i = 0; i < num_rcv_bufs; i++) | ||
1067 | kfree(instance->receive_buffers[i].base); | ||
1068 | |||
1069 | for (i = 0; i < num_rcv_urbs; i++) | ||
1070 | usb_free_urb(instance->receivers[i].urb); | ||
1071 | |||
1072 | return -ENOMEM; | ||
1073 | } | ||
1074 | |||
1075 | void udsl_instance_disconnect(struct udsl_instance_data *instance) | ||
1076 | { | ||
1077 | int i; | ||
1078 | |||
1079 | dbg("udsl_instance_disconnect entered"); | ||
1080 | |||
1081 | if (!instance) { | ||
1082 | dbg("udsl_instance_disconnect: NULL instance!"); | ||
1083 | return; | ||
1084 | } | ||
1085 | |||
1086 | /* receive finalize */ | ||
1087 | tasklet_disable(&instance->receive_tasklet); | ||
1088 | |||
1089 | for (i = 0; i < num_rcv_urbs; i++) | ||
1090 | usb_kill_urb(instance->receivers[i].urb); | ||
1091 | |||
1092 | /* no need to take the spinlock */ | ||
1093 | INIT_LIST_HEAD(&instance->filled_receive_buffers); | ||
1094 | INIT_LIST_HEAD(&instance->spare_receive_buffers); | ||
1095 | |||
1096 | tasklet_enable(&instance->receive_tasklet); | ||
1097 | |||
1098 | for (i = 0; i < num_rcv_urbs; i++) | ||
1099 | usb_free_urb(instance->receivers[i].urb); | ||
1100 | |||
1101 | for (i = 0; i < num_rcv_bufs; i++) | ||
1102 | kfree(instance->receive_buffers[i].base); | ||
1103 | |||
1104 | /* send finalize */ | ||
1105 | tasklet_disable(&instance->send_tasklet); | ||
1106 | |||
1107 | for (i = 0; i < num_snd_urbs; i++) | ||
1108 | usb_kill_urb(instance->senders[i].urb); | ||
1109 | |||
1110 | /* no need to take the spinlock */ | ||
1111 | INIT_LIST_HEAD(&instance->spare_senders); | ||
1112 | INIT_LIST_HEAD(&instance->spare_send_buffers); | ||
1113 | instance->current_buffer = NULL; | ||
1114 | |||
1115 | tasklet_enable(&instance->send_tasklet); | ||
1116 | |||
1117 | for (i = 0; i < num_snd_urbs; i++) | ||
1118 | usb_free_urb(instance->senders[i].urb); | ||
1119 | |||
1120 | for (i = 0; i < num_snd_bufs; i++) | ||
1121 | kfree(instance->send_buffers[i].base); | ||
1122 | |||
1123 | /* ATM finalize */ | ||
1124 | shutdown_atm_dev(instance->atm_dev); | ||
1125 | } | ||
1126 | |||
1127 | EXPORT_SYMBOL_GPL(udsl_get_instance); | ||
1128 | EXPORT_SYMBOL_GPL(udsl_put_instance); | ||
1129 | EXPORT_SYMBOL_GPL(udsl_instance_setup); | ||
1130 | EXPORT_SYMBOL_GPL(udsl_instance_disconnect); | ||
1131 | |||
1132 | /*********** | ||
1133 | ** init ** | ||
1134 | ***********/ | ||
1135 | |||
1136 | static int __init udsl_usb_init(void) | ||
1137 | { | ||
1138 | dbg("udsl_usb_init: driver version " DRIVER_VERSION); | ||
1139 | |||
1140 | if (sizeof(struct udsl_control) > sizeof(((struct sk_buff *) 0)->cb)) { | ||
1141 | printk(KERN_ERR __FILE__ ": unusable with this kernel!\n"); | ||
1142 | return -EIO; | ||
1143 | } | ||
1144 | |||
1145 | if ((num_rcv_urbs > UDSL_MAX_RCV_URBS) | ||
1146 | || (num_snd_urbs > UDSL_MAX_SND_URBS) | ||
1147 | || (num_rcv_bufs > UDSL_MAX_RCV_BUFS) | ||
1148 | || (num_snd_bufs > UDSL_MAX_SND_BUFS) | ||
1149 | || (rcv_buf_size > UDSL_MAX_RCV_BUF_SIZE) | ||
1150 | || (snd_buf_size > UDSL_MAX_SND_BUF_SIZE)) | ||
1151 | return -EINVAL; | ||
1152 | |||
1153 | return 0; | ||
1154 | } | ||
1155 | |||
1156 | static void __exit udsl_usb_exit(void) | ||
1157 | { | ||
1158 | } | ||
1159 | |||
1160 | module_init(udsl_usb_init); | ||
1161 | module_exit(udsl_usb_exit); | ||
1162 | |||
1163 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
1164 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
1165 | MODULE_LICENSE("GPL"); | ||
1166 | MODULE_VERSION(DRIVER_VERSION); | ||
1167 | |||
1168 | /************ | ||
1169 | ** debug ** | ||
1170 | ************/ | ||
1171 | |||
1172 | #ifdef VERBOSE_DEBUG | ||
1173 | static int udsl_print_packet(const unsigned char *data, int len) | ||
1174 | { | ||
1175 | unsigned char buffer[256]; | ||
1176 | int i = 0, j = 0; | ||
1177 | |||
1178 | for (i = 0; i < len;) { | ||
1179 | buffer[0] = '\0'; | ||
1180 | sprintf(buffer, "%.3d :", i); | ||
1181 | for (j = 0; (j < 16) && (i < len); j++, i++) { | ||
1182 | sprintf(buffer, "%s %2.2x", buffer, data[i]); | ||
1183 | } | ||
1184 | dbg("%s", buffer); | ||
1185 | } | ||
1186 | return i; | ||
1187 | } | ||
1188 | #endif | ||
diff --git a/drivers/usb/atm/usb_atm.h b/drivers/usb/atm/usb_atm.h deleted file mode 100644 index cf8c53283530..000000000000 --- a/drivers/usb/atm/usb_atm.h +++ /dev/null | |||
@@ -1,176 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * usb_atm.h - Generic USB xDSL driver core | ||
3 | * | ||
4 | * Copyright (C) 2001, Alcatel | ||
5 | * Copyright (C) 2003, Duncan Sands, SolNegro, Josep Comas | ||
6 | * Copyright (C) 2004, David Woodhouse | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
20 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | * | ||
22 | ******************************************************************************/ | ||
23 | |||
24 | #include <linux/config.h> | ||
25 | #include <linux/list.h> | ||
26 | #include <linux/kref.h> | ||
27 | #include <linux/atm.h> | ||
28 | #include <linux/atmdev.h> | ||
29 | #include <asm/semaphore.h> | ||
30 | |||
31 | /* | ||
32 | #define DEBUG | ||
33 | #define VERBOSE_DEBUG | ||
34 | */ | ||
35 | |||
36 | #if !defined (DEBUG) && defined (CONFIG_USB_DEBUG) | ||
37 | # define DEBUG | ||
38 | #endif | ||
39 | |||
40 | #include <linux/usb.h> | ||
41 | |||
42 | #ifdef DEBUG | ||
43 | #define UDSL_ASSERT(x) BUG_ON(!(x)) | ||
44 | #else | ||
45 | #define UDSL_ASSERT(x) do { if (!(x)) warn("failed assertion '" #x "' at line %d", __LINE__); } while(0) | ||
46 | #endif | ||
47 | |||
48 | #define UDSL_MAX_RCV_URBS 4 | ||
49 | #define UDSL_MAX_SND_URBS 4 | ||
50 | #define UDSL_MAX_RCV_BUFS 8 | ||
51 | #define UDSL_MAX_SND_BUFS 8 | ||
52 | #define UDSL_MAX_RCV_BUF_SIZE 1024 /* ATM cells */ | ||
53 | #define UDSL_MAX_SND_BUF_SIZE 1024 /* ATM cells */ | ||
54 | #define UDSL_DEFAULT_RCV_URBS 2 | ||
55 | #define UDSL_DEFAULT_SND_URBS 2 | ||
56 | #define UDSL_DEFAULT_RCV_BUFS 4 | ||
57 | #define UDSL_DEFAULT_SND_BUFS 4 | ||
58 | #define UDSL_DEFAULT_RCV_BUF_SIZE 64 /* ATM cells */ | ||
59 | #define UDSL_DEFAULT_SND_BUF_SIZE 64 /* ATM cells */ | ||
60 | |||
61 | #define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD) | ||
62 | #define UDSL_NUM_CELLS(x) (((x) + ATM_AAL5_TRAILER + ATM_CELL_PAYLOAD - 1) / ATM_CELL_PAYLOAD) | ||
63 | |||
64 | /* receive */ | ||
65 | |||
66 | struct udsl_receive_buffer { | ||
67 | struct list_head list; | ||
68 | unsigned char *base; | ||
69 | unsigned int filled_cells; | ||
70 | }; | ||
71 | |||
72 | struct udsl_receiver { | ||
73 | struct list_head list; | ||
74 | struct udsl_receive_buffer *buffer; | ||
75 | struct urb *urb; | ||
76 | struct udsl_instance_data *instance; | ||
77 | }; | ||
78 | |||
79 | struct udsl_vcc_data { | ||
80 | /* vpi/vci lookup */ | ||
81 | struct list_head list; | ||
82 | short vpi; | ||
83 | int vci; | ||
84 | struct atm_vcc *vcc; | ||
85 | |||
86 | /* raw cell reassembly */ | ||
87 | struct sk_buff *sarb; | ||
88 | }; | ||
89 | |||
90 | /* send */ | ||
91 | |||
92 | struct udsl_send_buffer { | ||
93 | struct list_head list; | ||
94 | unsigned char *base; | ||
95 | unsigned char *free_start; | ||
96 | unsigned int free_cells; | ||
97 | }; | ||
98 | |||
99 | struct udsl_sender { | ||
100 | struct list_head list; | ||
101 | struct udsl_send_buffer *buffer; | ||
102 | struct urb *urb; | ||
103 | struct udsl_instance_data *instance; | ||
104 | }; | ||
105 | |||
106 | struct udsl_control { | ||
107 | struct atm_skb_data atm_data; | ||
108 | unsigned int num_cells; | ||
109 | unsigned int num_entire; | ||
110 | unsigned int pdu_padding; | ||
111 | unsigned char aal5_trailer[ATM_AAL5_TRAILER]; | ||
112 | }; | ||
113 | |||
114 | #define UDSL_SKB(x) ((struct udsl_control *)(x)->cb) | ||
115 | |||
116 | /* main driver data */ | ||
117 | |||
118 | enum udsl_status { | ||
119 | UDSL_NO_FIRMWARE, | ||
120 | UDSL_LOADING_FIRMWARE, | ||
121 | UDSL_LOADED_FIRMWARE | ||
122 | }; | ||
123 | |||
124 | struct udsl_instance_data { | ||
125 | struct kref refcount; | ||
126 | struct semaphore serialize; | ||
127 | |||
128 | /* USB device part */ | ||
129 | struct usb_device *usb_dev; | ||
130 | char description[64]; | ||
131 | int data_endpoint; | ||
132 | int snd_padding; | ||
133 | int rcv_padding; | ||
134 | const char *driver_name; | ||
135 | |||
136 | /* ATM device part */ | ||
137 | struct atm_dev *atm_dev; | ||
138 | struct list_head vcc_list; | ||
139 | |||
140 | /* firmware */ | ||
141 | int (*firmware_wait) (struct udsl_instance_data *); | ||
142 | enum udsl_status status; | ||
143 | wait_queue_head_t firmware_waiters; | ||
144 | |||
145 | /* receive */ | ||
146 | struct udsl_receiver receivers[UDSL_MAX_RCV_URBS]; | ||
147 | struct udsl_receive_buffer receive_buffers[UDSL_MAX_RCV_BUFS]; | ||
148 | |||
149 | spinlock_t receive_lock; | ||
150 | struct list_head spare_receivers; | ||
151 | struct list_head filled_receive_buffers; | ||
152 | |||
153 | struct tasklet_struct receive_tasklet; | ||
154 | struct list_head spare_receive_buffers; | ||
155 | |||
156 | /* send */ | ||
157 | struct udsl_sender senders[UDSL_MAX_SND_URBS]; | ||
158 | struct udsl_send_buffer send_buffers[UDSL_MAX_SND_BUFS]; | ||
159 | |||
160 | struct sk_buff_head sndqueue; | ||
161 | |||
162 | spinlock_t send_lock; | ||
163 | struct list_head spare_senders; | ||
164 | struct list_head spare_send_buffers; | ||
165 | |||
166 | struct tasklet_struct send_tasklet; | ||
167 | struct sk_buff *current_skb; /* being emptied */ | ||
168 | struct udsl_send_buffer *current_buffer; /* being filled */ | ||
169 | struct list_head filled_send_buffers; | ||
170 | }; | ||
171 | |||
172 | extern int udsl_instance_setup(struct usb_device *dev, | ||
173 | struct udsl_instance_data *instance); | ||
174 | extern void udsl_instance_disconnect(struct udsl_instance_data *instance); | ||
175 | extern void udsl_get_instance(struct udsl_instance_data *instance); | ||
176 | extern void udsl_put_instance(struct udsl_instance_data *instance); | ||
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c new file mode 100644 index 000000000000..bb1db1959854 --- /dev/null +++ b/drivers/usb/atm/usbatm.c | |||
@@ -0,0 +1,1230 @@ | |||
1 | /****************************************************************************** | ||
2 | * usbatm.c - Generic USB xDSL driver core | ||
3 | * | ||
4 | * Copyright (C) 2001, Alcatel | ||
5 | * Copyright (C) 2003, Duncan Sands, SolNegro, Josep Comas | ||
6 | * Copyright (C) 2004, David Woodhouse, Roman Kagan | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
20 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | * | ||
22 | ******************************************************************************/ | ||
23 | |||
24 | /* | ||
25 | * Written by Johan Verrept, Duncan Sands (duncan.sands@free.fr) and David Woodhouse | ||
26 | * | ||
27 | * 1.7+: - See the check-in logs | ||
28 | * | ||
29 | * 1.6: - No longer opens a connection if the firmware is not loaded | ||
30 | * - Added support for the speedtouch 330 | ||
31 | * - Removed the limit on the number of devices | ||
32 | * - Module now autoloads on device plugin | ||
33 | * - Merged relevant parts of sarlib | ||
34 | * - Replaced the kernel thread with a tasklet | ||
35 | * - New packet transmission code | ||
36 | * - Changed proc file contents | ||
37 | * - Fixed all known SMP races | ||
38 | * - Many fixes and cleanups | ||
39 | * - Various fixes by Oliver Neukum (oliver@neukum.name) | ||
40 | * | ||
41 | * 1.5A: - Version for inclusion in 2.5 series kernel | ||
42 | * - Modifications by Richard Purdie (rpurdie@rpsys.net) | ||
43 | * - made compatible with kernel 2.5.6 onwards by changing | ||
44 | * usbatm_usb_send_data_context->urb to a pointer and adding code | ||
45 | * to alloc and free it | ||
46 | * - remove_wait_queue() added to usbatm_atm_processqueue_thread() | ||
47 | * | ||
48 | * 1.5: - fixed memory leak when atmsar_decode_aal5 returned NULL. | ||
49 | * (reported by stephen.robinson@zen.co.uk) | ||
50 | * | ||
51 | * 1.4: - changed the spin_lock() under interrupt to spin_lock_irqsave() | ||
52 | * - unlink all active send urbs of a vcc that is being closed. | ||
53 | * | ||
54 | * 1.3.1: - added the version number | ||
55 | * | ||
56 | * 1.3: - Added multiple send urb support | ||
57 | * - fixed memory leak and vcc->tx_inuse starvation bug | ||
58 | * when not enough memory left in vcc. | ||
59 | * | ||
60 | * 1.2: - Fixed race condition in usbatm_usb_send_data() | ||
61 | * 1.1: - Turned off packet debugging | ||
62 | * | ||
63 | */ | ||
64 | |||
65 | #include "usbatm.h" | ||
66 | |||
67 | #include <asm/uaccess.h> | ||
68 | #include <linux/crc32.h> | ||
69 | #include <linux/errno.h> | ||
70 | #include <linux/init.h> | ||
71 | #include <linux/interrupt.h> | ||
72 | #include <linux/kernel.h> | ||
73 | #include <linux/module.h> | ||
74 | #include <linux/moduleparam.h> | ||
75 | #include <linux/proc_fs.h> | ||
76 | #include <linux/sched.h> | ||
77 | #include <linux/signal.h> | ||
78 | #include <linux/slab.h> | ||
79 | #include <linux/smp_lock.h> | ||
80 | #include <linux/stat.h> | ||
81 | #include <linux/timer.h> | ||
82 | #include <linux/wait.h> | ||
83 | |||
84 | #ifdef VERBOSE_DEBUG | ||
85 | static int usbatm_print_packet(const unsigned char *data, int len); | ||
86 | #define PACKETDEBUG(arg...) usbatm_print_packet (arg) | ||
87 | #define vdbg(arg...) dbg (arg) | ||
88 | #else | ||
89 | #define PACKETDEBUG(arg...) | ||
90 | #define vdbg(arg...) | ||
91 | #endif | ||
92 | |||
93 | #define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>" | ||
94 | #define DRIVER_VERSION "1.9" | ||
95 | #define DRIVER_DESC "Generic USB ATM/DSL I/O, version " DRIVER_VERSION | ||
96 | |||
97 | static const char usbatm_driver_name[] = "usbatm"; | ||
98 | |||
99 | #define UDSL_MAX_RCV_URBS 16 | ||
100 | #define UDSL_MAX_SND_URBS 16 | ||
101 | #define UDSL_MAX_RCV_BUF_SIZE 1024 /* ATM cells */ | ||
102 | #define UDSL_MAX_SND_BUF_SIZE 1024 /* ATM cells */ | ||
103 | #define UDSL_DEFAULT_RCV_URBS 4 | ||
104 | #define UDSL_DEFAULT_SND_URBS 4 | ||
105 | #define UDSL_DEFAULT_RCV_BUF_SIZE 64 /* ATM cells */ | ||
106 | #define UDSL_DEFAULT_SND_BUF_SIZE 64 /* ATM cells */ | ||
107 | |||
108 | #define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD) | ||
109 | |||
110 | #define THROTTLE_MSECS 100 /* delay to recover processing after urb submission fails */ | ||
111 | |||
112 | static unsigned int num_rcv_urbs = UDSL_DEFAULT_RCV_URBS; | ||
113 | static unsigned int num_snd_urbs = UDSL_DEFAULT_SND_URBS; | ||
114 | static unsigned int rcv_buf_size = UDSL_DEFAULT_RCV_BUF_SIZE; | ||
115 | static unsigned int snd_buf_size = UDSL_DEFAULT_SND_BUF_SIZE; | ||
116 | |||
117 | module_param(num_rcv_urbs, uint, S_IRUGO); | ||
118 | MODULE_PARM_DESC(num_rcv_urbs, | ||
119 | "Number of urbs used for reception (range: 0-" | ||
120 | __MODULE_STRING(UDSL_MAX_RCV_URBS) ", default: " | ||
121 | __MODULE_STRING(UDSL_DEFAULT_RCV_URBS) ")"); | ||
122 | |||
123 | module_param(num_snd_urbs, uint, S_IRUGO); | ||
124 | MODULE_PARM_DESC(num_snd_urbs, | ||
125 | "Number of urbs used for transmission (range: 0-" | ||
126 | __MODULE_STRING(UDSL_MAX_SND_URBS) ", default: " | ||
127 | __MODULE_STRING(UDSL_DEFAULT_SND_URBS) ")"); | ||
128 | |||
129 | module_param(rcv_buf_size, uint, S_IRUGO); | ||
130 | MODULE_PARM_DESC(rcv_buf_size, | ||
131 | "Size of the buffers used for reception in ATM cells (range: 1-" | ||
132 | __MODULE_STRING(UDSL_MAX_RCV_BUF_SIZE) ", default: " | ||
133 | __MODULE_STRING(UDSL_DEFAULT_RCV_BUF_SIZE) ")"); | ||
134 | |||
135 | module_param(snd_buf_size, uint, S_IRUGO); | ||
136 | MODULE_PARM_DESC(snd_buf_size, | ||
137 | "Size of the buffers used for transmission in ATM cells (range: 1-" | ||
138 | __MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: " | ||
139 | __MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")"); | ||
140 | |||
141 | |||
142 | /* receive */ | ||
143 | |||
144 | struct usbatm_vcc_data { | ||
145 | /* vpi/vci lookup */ | ||
146 | struct list_head list; | ||
147 | short vpi; | ||
148 | int vci; | ||
149 | struct atm_vcc *vcc; | ||
150 | |||
151 | /* raw cell reassembly */ | ||
152 | struct sk_buff *sarb; | ||
153 | }; | ||
154 | |||
155 | |||
156 | /* send */ | ||
157 | |||
158 | struct usbatm_control { | ||
159 | struct atm_skb_data atm; | ||
160 | u32 len; | ||
161 | u32 crc; | ||
162 | }; | ||
163 | |||
164 | #define UDSL_SKB(x) ((struct usbatm_control *)(x)->cb) | ||
165 | |||
166 | |||
167 | /* ATM */ | ||
168 | |||
169 | static void usbatm_atm_dev_close(struct atm_dev *dev); | ||
170 | static int usbatm_atm_open(struct atm_vcc *vcc); | ||
171 | static void usbatm_atm_close(struct atm_vcc *vcc); | ||
172 | static int usbatm_atm_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg); | ||
173 | static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb); | ||
174 | static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page); | ||
175 | |||
176 | static struct atmdev_ops usbatm_atm_devops = { | ||
177 | .dev_close = usbatm_atm_dev_close, | ||
178 | .open = usbatm_atm_open, | ||
179 | .close = usbatm_atm_close, | ||
180 | .ioctl = usbatm_atm_ioctl, | ||
181 | .send = usbatm_atm_send, | ||
182 | .proc_read = usbatm_atm_proc_read, | ||
183 | .owner = THIS_MODULE, | ||
184 | }; | ||
185 | |||
186 | |||
187 | /*********** | ||
188 | ** misc ** | ||
189 | ***********/ | ||
190 | |||
191 | static inline unsigned int usbatm_pdu_length(unsigned int length) | ||
192 | { | ||
193 | length += ATM_CELL_PAYLOAD - 1 + ATM_AAL5_TRAILER; | ||
194 | return length - length % ATM_CELL_PAYLOAD; | ||
195 | } | ||
196 | |||
197 | static inline void usbatm_pop(struct atm_vcc *vcc, struct sk_buff *skb) | ||
198 | { | ||
199 | if (vcc->pop) | ||
200 | vcc->pop(vcc, skb); | ||
201 | else | ||
202 | dev_kfree_skb(skb); | ||
203 | } | ||
204 | |||
205 | |||
206 | /*********** | ||
207 | ** urbs ** | ||
208 | ************/ | ||
209 | |||
210 | static inline struct urb *usbatm_pop_urb(struct usbatm_channel *channel) | ||
211 | { | ||
212 | struct urb *urb; | ||
213 | |||
214 | spin_lock_irq(&channel->lock); | ||
215 | if (list_empty(&channel->list)) { | ||
216 | spin_unlock_irq(&channel->lock); | ||
217 | return NULL; | ||
218 | } | ||
219 | |||
220 | urb = list_entry(channel->list.next, struct urb, urb_list); | ||
221 | list_del(&urb->urb_list); | ||
222 | spin_unlock_irq(&channel->lock); | ||
223 | |||
224 | return urb; | ||
225 | } | ||
226 | |||
227 | static inline int usbatm_submit_urb(struct urb *urb) | ||
228 | { | ||
229 | struct usbatm_channel *channel = urb->context; | ||
230 | int ret; | ||
231 | |||
232 | vdbg("%s: submitting urb 0x%p, size %u", | ||
233 | __func__, urb, urb->transfer_buffer_length); | ||
234 | |||
235 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
236 | if (ret) { | ||
237 | atm_dbg(channel->usbatm, "%s: urb 0x%p submission failed (%d)!\n", | ||
238 | __func__, urb, ret); | ||
239 | |||
240 | /* consider all errors transient and return the buffer back to the queue */ | ||
241 | urb->status = -EAGAIN; | ||
242 | spin_lock_irq(&channel->lock); | ||
243 | |||
244 | /* must add to the front when sending; doesn't matter when receiving */ | ||
245 | list_add(&urb->urb_list, &channel->list); | ||
246 | |||
247 | spin_unlock_irq(&channel->lock); | ||
248 | |||
249 | /* make sure the channel doesn't stall */ | ||
250 | mod_timer(&channel->delay, jiffies + msecs_to_jiffies(THROTTLE_MSECS)); | ||
251 | } | ||
252 | |||
253 | return ret; | ||
254 | } | ||
255 | |||
256 | static void usbatm_complete(struct urb *urb, struct pt_regs *regs) | ||
257 | { | ||
258 | struct usbatm_channel *channel = urb->context; | ||
259 | unsigned long flags; | ||
260 | |||
261 | vdbg("%s: urb 0x%p, status %d, actual_length %d", | ||
262 | __func__, urb, urb->status, urb->actual_length); | ||
263 | |||
264 | /* usually in_interrupt(), but not always */ | ||
265 | spin_lock_irqsave(&channel->lock, flags); | ||
266 | |||
267 | /* must add to the back when receiving; doesn't matter when sending */ | ||
268 | list_add_tail(&urb->urb_list, &channel->list); | ||
269 | |||
270 | spin_unlock_irqrestore(&channel->lock, flags); | ||
271 | |||
272 | if (unlikely(urb->status)) | ||
273 | /* throttle processing in case of an error */ | ||
274 | mod_timer(&channel->delay, jiffies + msecs_to_jiffies(THROTTLE_MSECS)); | ||
275 | else | ||
276 | tasklet_schedule(&channel->tasklet); | ||
277 | } | ||
278 | |||
279 | |||
280 | /************* | ||
281 | ** decode ** | ||
282 | *************/ | ||
283 | |||
284 | static inline struct usbatm_vcc_data *usbatm_find_vcc(struct usbatm_data *instance, | ||
285 | short vpi, int vci) | ||
286 | { | ||
287 | struct usbatm_vcc_data *vcc; | ||
288 | |||
289 | list_for_each_entry(vcc, &instance->vcc_list, list) | ||
290 | if ((vcc->vci == vci) && (vcc->vpi == vpi)) | ||
291 | return vcc; | ||
292 | return NULL; | ||
293 | } | ||
294 | |||
295 | static void usbatm_extract_cells(struct usbatm_data *instance, | ||
296 | unsigned char *source, unsigned int avail_data) | ||
297 | { | ||
298 | struct usbatm_vcc_data *cached_vcc = NULL; | ||
299 | struct atm_vcc *vcc; | ||
300 | struct sk_buff *sarb; | ||
301 | unsigned int stride = instance->rx_channel.stride; | ||
302 | int vci, cached_vci = 0; | ||
303 | short vpi, cached_vpi = 0; | ||
304 | u8 pti; | ||
305 | |||
306 | for (; avail_data >= stride; avail_data -= stride, source += stride) { | ||
307 | vpi = ((source[0] & 0x0f) << 4) | (source[1] >> 4); | ||
308 | vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4); | ||
309 | pti = ((source[3] & 0xe) >> 1); | ||
310 | |||
311 | vdbg("%s: vpi %hd, vci %d, pti %d", __func__, vpi, vci, pti); | ||
312 | |||
313 | if ((vci != cached_vci) || (vpi != cached_vpi)) { | ||
314 | cached_vpi = vpi; | ||
315 | cached_vci = vci; | ||
316 | |||
317 | cached_vcc = usbatm_find_vcc(instance, vpi, vci); | ||
318 | |||
319 | if (!cached_vcc) | ||
320 | atm_dbg(instance, "%s: unknown vpi/vci (%hd/%d)!\n", __func__, vpi, vci); | ||
321 | } | ||
322 | |||
323 | if (!cached_vcc) | ||
324 | continue; | ||
325 | |||
326 | vcc = cached_vcc->vcc; | ||
327 | |||
328 | /* OAM F5 end-to-end */ | ||
329 | if (pti == ATM_PTI_E2EF5) { | ||
330 | atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n", __func__, vpi, vci); | ||
331 | atomic_inc(&vcc->stats->rx_err); | ||
332 | continue; | ||
333 | } | ||
334 | |||
335 | sarb = cached_vcc->sarb; | ||
336 | |||
337 | if (sarb->tail + ATM_CELL_PAYLOAD > sarb->end) { | ||
338 | atm_dbg(instance, "%s: buffer overrun (sarb->len %u, vcc: 0x%p)!\n", | ||
339 | __func__, sarb->len, vcc); | ||
340 | /* discard cells already received */ | ||
341 | skb_trim(sarb, 0); | ||
342 | UDSL_ASSERT(sarb->tail + ATM_CELL_PAYLOAD <= sarb->end); | ||
343 | } | ||
344 | |||
345 | memcpy(sarb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD); | ||
346 | __skb_put(sarb, ATM_CELL_PAYLOAD); | ||
347 | |||
348 | if (pti & 1) { | ||
349 | struct sk_buff *skb; | ||
350 | unsigned int length; | ||
351 | unsigned int pdu_length; | ||
352 | |||
353 | length = (source[ATM_CELL_SIZE - 6] << 8) + source[ATM_CELL_SIZE - 5]; | ||
354 | |||
355 | /* guard against overflow */ | ||
356 | if (length > ATM_MAX_AAL5_PDU) { | ||
357 | atm_dbg(instance, "%s: bogus length %u (vcc: 0x%p)!\n", | ||
358 | __func__, length, vcc); | ||
359 | atomic_inc(&vcc->stats->rx_err); | ||
360 | goto out; | ||
361 | } | ||
362 | |||
363 | pdu_length = usbatm_pdu_length(length); | ||
364 | |||
365 | if (sarb->len < pdu_length) { | ||
366 | atm_dbg(instance, "%s: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!\n", | ||
367 | __func__, pdu_length, sarb->len, vcc); | ||
368 | atomic_inc(&vcc->stats->rx_err); | ||
369 | goto out; | ||
370 | } | ||
371 | |||
372 | if (crc32_be(~0, sarb->tail - pdu_length, pdu_length) != 0xc704dd7b) { | ||
373 | atm_dbg(instance, "%s: packet failed crc check (vcc: 0x%p)!\n", | ||
374 | __func__, vcc); | ||
375 | atomic_inc(&vcc->stats->rx_err); | ||
376 | goto out; | ||
377 | } | ||
378 | |||
379 | vdbg("%s: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", __func__, length, pdu_length, vcc); | ||
380 | |||
381 | if (!(skb = dev_alloc_skb(length))) { | ||
382 | atm_dbg(instance, "%s: no memory for skb (length: %u)!\n", __func__, length); | ||
383 | atomic_inc(&vcc->stats->rx_drop); | ||
384 | goto out; | ||
385 | } | ||
386 | |||
387 | vdbg("%s: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", __func__, skb, skb->truesize); | ||
388 | |||
389 | if (!atm_charge(vcc, skb->truesize)) { | ||
390 | atm_dbg(instance, "%s: failed atm_charge (skb->truesize: %u)!\n", __func__, skb->truesize); | ||
391 | dev_kfree_skb(skb); | ||
392 | goto out; /* atm_charge increments rx_drop */ | ||
393 | } | ||
394 | |||
395 | memcpy(skb->data, sarb->tail - pdu_length, length); | ||
396 | __skb_put(skb, length); | ||
397 | |||
398 | vdbg("%s: sending skb 0x%p, skb->len %u, skb->truesize %u", | ||
399 | __func__, skb, skb->len, skb->truesize); | ||
400 | |||
401 | PACKETDEBUG(skb->data, skb->len); | ||
402 | |||
403 | vcc->push(vcc, skb); | ||
404 | |||
405 | atomic_inc(&vcc->stats->rx); | ||
406 | out: | ||
407 | skb_trim(sarb, 0); | ||
408 | } | ||
409 | } | ||
410 | } | ||
411 | |||
412 | |||
413 | /************* | ||
414 | ** encode ** | ||
415 | *************/ | ||
416 | |||
417 | static unsigned int usbatm_write_cells(struct usbatm_data *instance, | ||
418 | struct sk_buff *skb, | ||
419 | u8 *target, unsigned int avail_space) | ||
420 | { | ||
421 | struct usbatm_control *ctrl = UDSL_SKB(skb); | ||
422 | struct atm_vcc *vcc = ctrl->atm.vcc; | ||
423 | unsigned int num_written; | ||
424 | unsigned int stride = instance->tx_channel.stride; | ||
425 | |||
426 | vdbg("%s: skb->len=%d, avail_space=%u", __func__, skb->len, avail_space); | ||
427 | UDSL_ASSERT(!(avail_space % stride)); | ||
428 | |||
429 | for (num_written = 0; num_written < avail_space && ctrl->len; | ||
430 | num_written += stride, target += stride) { | ||
431 | unsigned int data_len = min_t(unsigned int, skb->len, ATM_CELL_PAYLOAD); | ||
432 | unsigned int left = ATM_CELL_PAYLOAD - data_len; | ||
433 | u8 *ptr = target; | ||
434 | |||
435 | ptr[0] = vcc->vpi >> 4; | ||
436 | ptr[1] = (vcc->vpi << 4) | (vcc->vci >> 12); | ||
437 | ptr[2] = vcc->vci >> 4; | ||
438 | ptr[3] = vcc->vci << 4; | ||
439 | ptr[4] = 0xec; | ||
440 | ptr += ATM_CELL_HEADER; | ||
441 | |||
442 | memcpy(ptr, skb->data, data_len); | ||
443 | ptr += data_len; | ||
444 | __skb_pull(skb, data_len); | ||
445 | |||
446 | if(!left) | ||
447 | continue; | ||
448 | |||
449 | memset(ptr, 0, left); | ||
450 | |||
451 | if (left >= ATM_AAL5_TRAILER) { /* trailer will go in this cell */ | ||
452 | u8 *trailer = target + ATM_CELL_SIZE - ATM_AAL5_TRAILER; | ||
453 | /* trailer[0] = 0; UU = 0 */ | ||
454 | /* trailer[1] = 0; CPI = 0 */ | ||
455 | trailer[2] = ctrl->len >> 8; | ||
456 | trailer[3] = ctrl->len; | ||
457 | |||
458 | ctrl->crc = ~ crc32_be(ctrl->crc, ptr, left - 4); | ||
459 | |||
460 | trailer[4] = ctrl->crc >> 24; | ||
461 | trailer[5] = ctrl->crc >> 16; | ||
462 | trailer[6] = ctrl->crc >> 8; | ||
463 | trailer[7] = ctrl->crc; | ||
464 | |||
465 | target[3] |= 0x2; /* adjust PTI */ | ||
466 | |||
467 | ctrl->len = 0; /* tag this skb finished */ | ||
468 | } | ||
469 | else | ||
470 | ctrl->crc = crc32_be(ctrl->crc, ptr, left); | ||
471 | } | ||
472 | |||
473 | return num_written; | ||
474 | } | ||
475 | |||
476 | |||
477 | /************** | ||
478 | ** receive ** | ||
479 | **************/ | ||
480 | |||
481 | static void usbatm_rx_process(unsigned long data) | ||
482 | { | ||
483 | struct usbatm_data *instance = (struct usbatm_data *)data; | ||
484 | struct urb *urb; | ||
485 | |||
486 | while ((urb = usbatm_pop_urb(&instance->rx_channel))) { | ||
487 | vdbg("%s: processing urb 0x%p", __func__, urb); | ||
488 | |||
489 | if (usb_pipeisoc(urb->pipe)) { | ||
490 | int i; | ||
491 | for (i = 0; i < urb->number_of_packets; i++) | ||
492 | if (!urb->iso_frame_desc[i].status) | ||
493 | usbatm_extract_cells(instance, | ||
494 | (u8 *)urb->transfer_buffer + urb->iso_frame_desc[i].offset, | ||
495 | urb->iso_frame_desc[i].actual_length); | ||
496 | } | ||
497 | else | ||
498 | if (!urb->status) | ||
499 | usbatm_extract_cells(instance, urb->transfer_buffer, urb->actual_length); | ||
500 | |||
501 | if (usbatm_submit_urb(urb)) | ||
502 | return; | ||
503 | } | ||
504 | } | ||
505 | |||
506 | |||
507 | /*********** | ||
508 | ** send ** | ||
509 | ***********/ | ||
510 | |||
511 | static void usbatm_tx_process(unsigned long data) | ||
512 | { | ||
513 | struct usbatm_data *instance = (struct usbatm_data *)data; | ||
514 | struct sk_buff *skb = instance->current_skb; | ||
515 | struct urb *urb = NULL; | ||
516 | const unsigned int buf_size = instance->tx_channel.buf_size; | ||
517 | unsigned int num_written = 0; | ||
518 | u8 *buffer = NULL; | ||
519 | |||
520 | if (!skb) | ||
521 | skb = skb_dequeue(&instance->sndqueue); | ||
522 | |||
523 | while (skb) { | ||
524 | if (!urb) { | ||
525 | urb = usbatm_pop_urb(&instance->tx_channel); | ||
526 | if (!urb) | ||
527 | break; /* no more senders */ | ||
528 | buffer = urb->transfer_buffer; | ||
529 | num_written = (urb->status == -EAGAIN) ? | ||
530 | urb->transfer_buffer_length : 0; | ||
531 | } | ||
532 | |||
533 | num_written += usbatm_write_cells(instance, skb, | ||
534 | buffer + num_written, | ||
535 | buf_size - num_written); | ||
536 | |||
537 | vdbg("%s: wrote %u bytes from skb 0x%p to urb 0x%p", | ||
538 | __func__, num_written, skb, urb); | ||
539 | |||
540 | if (!UDSL_SKB(skb)->len) { | ||
541 | struct atm_vcc *vcc = UDSL_SKB(skb)->atm.vcc; | ||
542 | |||
543 | usbatm_pop(vcc, skb); | ||
544 | atomic_inc(&vcc->stats->tx); | ||
545 | |||
546 | skb = skb_dequeue(&instance->sndqueue); | ||
547 | } | ||
548 | |||
549 | if (num_written == buf_size || (!skb && num_written)) { | ||
550 | urb->transfer_buffer_length = num_written; | ||
551 | |||
552 | if (usbatm_submit_urb(urb)) | ||
553 | break; | ||
554 | urb = NULL; | ||
555 | } | ||
556 | } | ||
557 | |||
558 | instance->current_skb = skb; | ||
559 | } | ||
560 | |||
561 | static void usbatm_cancel_send(struct usbatm_data *instance, | ||
562 | struct atm_vcc *vcc) | ||
563 | { | ||
564 | struct sk_buff *skb, *n; | ||
565 | |||
566 | atm_dbg(instance, "%s entered\n", __func__); | ||
567 | spin_lock_irq(&instance->sndqueue.lock); | ||
568 | for (skb = instance->sndqueue.next, n = skb->next; | ||
569 | skb != (struct sk_buff *)&instance->sndqueue; | ||
570 | skb = n, n = skb->next) | ||
571 | if (UDSL_SKB(skb)->atm.vcc == vcc) { | ||
572 | atm_dbg(instance, "%s: popping skb 0x%p\n", __func__, skb); | ||
573 | __skb_unlink(skb, &instance->sndqueue); | ||
574 | usbatm_pop(vcc, skb); | ||
575 | } | ||
576 | spin_unlock_irq(&instance->sndqueue.lock); | ||
577 | |||
578 | tasklet_disable(&instance->tx_channel.tasklet); | ||
579 | if ((skb = instance->current_skb) && (UDSL_SKB(skb)->atm.vcc == vcc)) { | ||
580 | atm_dbg(instance, "%s: popping current skb (0x%p)\n", __func__, skb); | ||
581 | instance->current_skb = NULL; | ||
582 | usbatm_pop(vcc, skb); | ||
583 | } | ||
584 | tasklet_enable(&instance->tx_channel.tasklet); | ||
585 | atm_dbg(instance, "%s done\n", __func__); | ||
586 | } | ||
587 | |||
588 | static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) | ||
589 | { | ||
590 | struct usbatm_data *instance = vcc->dev->dev_data; | ||
591 | struct usbatm_control *ctrl = UDSL_SKB(skb); | ||
592 | int err; | ||
593 | |||
594 | vdbg("%s called (skb 0x%p, len %u)", __func__, skb, skb->len); | ||
595 | |||
596 | if (!instance) { | ||
597 | dbg("%s: NULL data!", __func__); | ||
598 | err = -ENODEV; | ||
599 | goto fail; | ||
600 | } | ||
601 | |||
602 | if (vcc->qos.aal != ATM_AAL5) { | ||
603 | atm_dbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal); | ||
604 | err = -EINVAL; | ||
605 | goto fail; | ||
606 | } | ||
607 | |||
608 | if (skb->len > ATM_MAX_AAL5_PDU) { | ||
609 | atm_dbg(instance, "%s: packet too long (%d vs %d)!\n", | ||
610 | __func__, skb->len, ATM_MAX_AAL5_PDU); | ||
611 | err = -EINVAL; | ||
612 | goto fail; | ||
613 | } | ||
614 | |||
615 | PACKETDEBUG(skb->data, skb->len); | ||
616 | |||
617 | /* initialize the control block */ | ||
618 | ctrl->atm.vcc = vcc; | ||
619 | ctrl->len = skb->len; | ||
620 | ctrl->crc = crc32_be(~0, skb->data, skb->len); | ||
621 | |||
622 | skb_queue_tail(&instance->sndqueue, skb); | ||
623 | tasklet_schedule(&instance->tx_channel.tasklet); | ||
624 | |||
625 | return 0; | ||
626 | |||
627 | fail: | ||
628 | usbatm_pop(vcc, skb); | ||
629 | return err; | ||
630 | } | ||
631 | |||
632 | |||
633 | /******************** | ||
634 | ** bean counting ** | ||
635 | ********************/ | ||
636 | |||
637 | static void usbatm_destroy_instance(struct kref *kref) | ||
638 | { | ||
639 | struct usbatm_data *instance = container_of(kref, struct usbatm_data, refcount); | ||
640 | |||
641 | dbg("%s", __func__); | ||
642 | |||
643 | tasklet_kill(&instance->rx_channel.tasklet); | ||
644 | tasklet_kill(&instance->tx_channel.tasklet); | ||
645 | usb_put_dev(instance->usb_dev); | ||
646 | kfree(instance); | ||
647 | } | ||
648 | |||
649 | void usbatm_get_instance(struct usbatm_data *instance) | ||
650 | { | ||
651 | dbg("%s", __func__); | ||
652 | |||
653 | kref_get(&instance->refcount); | ||
654 | } | ||
655 | |||
656 | void usbatm_put_instance(struct usbatm_data *instance) | ||
657 | { | ||
658 | dbg("%s", __func__); | ||
659 | |||
660 | kref_put(&instance->refcount, usbatm_destroy_instance); | ||
661 | } | ||
662 | |||
663 | |||
664 | /********** | ||
665 | ** ATM ** | ||
666 | **********/ | ||
667 | |||
668 | static void usbatm_atm_dev_close(struct atm_dev *dev) | ||
669 | { | ||
670 | struct usbatm_data *instance = dev->dev_data; | ||
671 | |||
672 | dbg("%s", __func__); | ||
673 | |||
674 | if (!instance) | ||
675 | return; | ||
676 | |||
677 | dev->dev_data = NULL; | ||
678 | usbatm_put_instance(instance); /* taken in usbatm_atm_init */ | ||
679 | } | ||
680 | |||
681 | static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t * pos, char *page) | ||
682 | { | ||
683 | struct usbatm_data *instance = atm_dev->dev_data; | ||
684 | int left = *pos; | ||
685 | |||
686 | if (!instance) { | ||
687 | dbg("%s: NULL instance!", __func__); | ||
688 | return -ENODEV; | ||
689 | } | ||
690 | |||
691 | if (!left--) | ||
692 | return sprintf(page, "%s\n", instance->description); | ||
693 | |||
694 | if (!left--) | ||
695 | return sprintf(page, "MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
696 | atm_dev->esi[0], atm_dev->esi[1], | ||
697 | atm_dev->esi[2], atm_dev->esi[3], | ||
698 | atm_dev->esi[4], atm_dev->esi[5]); | ||
699 | |||
700 | if (!left--) | ||
701 | return sprintf(page, | ||
702 | "AAL5: tx %d ( %d err ), rx %d ( %d err, %d drop )\n", | ||
703 | atomic_read(&atm_dev->stats.aal5.tx), | ||
704 | atomic_read(&atm_dev->stats.aal5.tx_err), | ||
705 | atomic_read(&atm_dev->stats.aal5.rx), | ||
706 | atomic_read(&atm_dev->stats.aal5.rx_err), | ||
707 | atomic_read(&atm_dev->stats.aal5.rx_drop)); | ||
708 | |||
709 | if (!left--) | ||
710 | switch (atm_dev->signal) { | ||
711 | case ATM_PHY_SIG_FOUND: | ||
712 | return sprintf(page, "Line up\n"); | ||
713 | case ATM_PHY_SIG_LOST: | ||
714 | return sprintf(page, "Line down\n"); | ||
715 | default: | ||
716 | return sprintf(page, "Line state unknown\n"); | ||
717 | } | ||
718 | |||
719 | return 0; | ||
720 | } | ||
721 | |||
722 | static int usbatm_atm_open(struct atm_vcc *vcc) | ||
723 | { | ||
724 | struct usbatm_data *instance = vcc->dev->dev_data; | ||
725 | struct usbatm_vcc_data *new = NULL; | ||
726 | int ret; | ||
727 | int vci = vcc->vci; | ||
728 | short vpi = vcc->vpi; | ||
729 | |||
730 | if (!instance) { | ||
731 | dbg("%s: NULL data!", __func__); | ||
732 | return -ENODEV; | ||
733 | } | ||
734 | |||
735 | atm_dbg(instance, "%s: vpi %hd, vci %d\n", __func__, vpi, vci); | ||
736 | |||
737 | /* only support AAL5 */ | ||
738 | if ((vcc->qos.aal != ATM_AAL5) || (vcc->qos.rxtp.max_sdu < 0) | ||
739 | || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU)) { | ||
740 | atm_dbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal); | ||
741 | return -EINVAL; | ||
742 | } | ||
743 | |||
744 | down(&instance->serialize); /* vs self, usbatm_atm_close */ | ||
745 | |||
746 | if (usbatm_find_vcc(instance, vpi, vci)) { | ||
747 | atm_dbg(instance, "%s: %hd/%d already in use!\n", __func__, vpi, vci); | ||
748 | ret = -EADDRINUSE; | ||
749 | goto fail; | ||
750 | } | ||
751 | |||
752 | if (!(new = kmalloc(sizeof(struct usbatm_vcc_data), GFP_KERNEL))) { | ||
753 | atm_dbg(instance, "%s: no memory for vcc_data!\n", __func__); | ||
754 | ret = -ENOMEM; | ||
755 | goto fail; | ||
756 | } | ||
757 | |||
758 | memset(new, 0, sizeof(struct usbatm_vcc_data)); | ||
759 | new->vcc = vcc; | ||
760 | new->vpi = vpi; | ||
761 | new->vci = vci; | ||
762 | |||
763 | new->sarb = alloc_skb(usbatm_pdu_length(vcc->qos.rxtp.max_sdu), GFP_KERNEL); | ||
764 | if (!new->sarb) { | ||
765 | atm_dbg(instance, "%s: no memory for SAR buffer!\n", __func__); | ||
766 | ret = -ENOMEM; | ||
767 | goto fail; | ||
768 | } | ||
769 | |||
770 | vcc->dev_data = new; | ||
771 | |||
772 | tasklet_disable(&instance->rx_channel.tasklet); | ||
773 | list_add(&new->list, &instance->vcc_list); | ||
774 | tasklet_enable(&instance->rx_channel.tasklet); | ||
775 | |||
776 | set_bit(ATM_VF_ADDR, &vcc->flags); | ||
777 | set_bit(ATM_VF_PARTIAL, &vcc->flags); | ||
778 | set_bit(ATM_VF_READY, &vcc->flags); | ||
779 | |||
780 | up(&instance->serialize); | ||
781 | |||
782 | atm_dbg(instance, "%s: allocated vcc data 0x%p\n", __func__, new); | ||
783 | |||
784 | return 0; | ||
785 | |||
786 | fail: | ||
787 | kfree(new); | ||
788 | up(&instance->serialize); | ||
789 | return ret; | ||
790 | } | ||
791 | |||
792 | static void usbatm_atm_close(struct atm_vcc *vcc) | ||
793 | { | ||
794 | struct usbatm_data *instance = vcc->dev->dev_data; | ||
795 | struct usbatm_vcc_data *vcc_data = vcc->dev_data; | ||
796 | |||
797 | if (!instance || !vcc_data) { | ||
798 | dbg("%s: NULL data!", __func__); | ||
799 | return; | ||
800 | } | ||
801 | |||
802 | atm_dbg(instance, "%s entered\n", __func__); | ||
803 | |||
804 | atm_dbg(instance, "%s: deallocating vcc 0x%p with vpi %d vci %d\n", | ||
805 | __func__, vcc_data, vcc_data->vpi, vcc_data->vci); | ||
806 | |||
807 | usbatm_cancel_send(instance, vcc); | ||
808 | |||
809 | down(&instance->serialize); /* vs self, usbatm_atm_open */ | ||
810 | |||
811 | tasklet_disable(&instance->rx_channel.tasklet); | ||
812 | list_del(&vcc_data->list); | ||
813 | tasklet_enable(&instance->rx_channel.tasklet); | ||
814 | |||
815 | kfree_skb(vcc_data->sarb); | ||
816 | vcc_data->sarb = NULL; | ||
817 | |||
818 | kfree(vcc_data); | ||
819 | vcc->dev_data = NULL; | ||
820 | |||
821 | vcc->vpi = ATM_VPI_UNSPEC; | ||
822 | vcc->vci = ATM_VCI_UNSPEC; | ||
823 | clear_bit(ATM_VF_READY, &vcc->flags); | ||
824 | clear_bit(ATM_VF_PARTIAL, &vcc->flags); | ||
825 | clear_bit(ATM_VF_ADDR, &vcc->flags); | ||
826 | |||
827 | up(&instance->serialize); | ||
828 | |||
829 | atm_dbg(instance, "%s successful\n", __func__); | ||
830 | } | ||
831 | |||
832 | static int usbatm_atm_ioctl(struct atm_dev *dev, unsigned int cmd, | ||
833 | void __user * arg) | ||
834 | { | ||
835 | switch (cmd) { | ||
836 | case ATM_QUERYLOOP: | ||
837 | return put_user(ATM_LM_NONE, (int __user *)arg) ? -EFAULT : 0; | ||
838 | default: | ||
839 | return -ENOIOCTLCMD; | ||
840 | } | ||
841 | } | ||
842 | |||
843 | static int usbatm_atm_init(struct usbatm_data *instance) | ||
844 | { | ||
845 | struct atm_dev *atm_dev; | ||
846 | int ret, i; | ||
847 | |||
848 | /* ATM init */ | ||
849 | atm_dev = atm_dev_register(instance->driver_name, &usbatm_atm_devops, -1, NULL); | ||
850 | if (!atm_dev) { | ||
851 | usb_dbg(instance, "%s: failed to register ATM device!\n", __func__); | ||
852 | return -1; | ||
853 | } | ||
854 | |||
855 | instance->atm_dev = atm_dev; | ||
856 | |||
857 | atm_dev->ci_range.vpi_bits = ATM_CI_MAX; | ||
858 | atm_dev->ci_range.vci_bits = ATM_CI_MAX; | ||
859 | atm_dev->signal = ATM_PHY_SIG_UNKNOWN; | ||
860 | |||
861 | /* temp init ATM device, set to 128kbit */ | ||
862 | atm_dev->link_rate = 128 * 1000 / 424; | ||
863 | |||
864 | if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0)) { | ||
865 | atm_dbg(instance, "%s: atm_start failed: %d!\n", __func__, ret); | ||
866 | goto fail; | ||
867 | } | ||
868 | |||
869 | /* ready for ATM callbacks */ | ||
870 | usbatm_get_instance(instance); /* dropped in usbatm_atm_dev_close */ | ||
871 | mb(); | ||
872 | atm_dev->dev_data = instance; | ||
873 | |||
874 | /* submit all rx URBs */ | ||
875 | for (i = 0; i < num_rcv_urbs; i++) | ||
876 | usbatm_submit_urb(instance->urbs[i]); | ||
877 | |||
878 | return 0; | ||
879 | |||
880 | fail: | ||
881 | instance->atm_dev = NULL; | ||
882 | shutdown_atm_dev(atm_dev); /* usbatm_atm_dev_close will eventually be called */ | ||
883 | return ret; | ||
884 | } | ||
885 | |||
886 | |||
887 | /********** | ||
888 | ** USB ** | ||
889 | **********/ | ||
890 | |||
891 | static int usbatm_do_heavy_init(void *arg) | ||
892 | { | ||
893 | struct usbatm_data *instance = arg; | ||
894 | int ret; | ||
895 | |||
896 | daemonize(instance->driver->driver_name); | ||
897 | allow_signal(SIGTERM); | ||
898 | |||
899 | complete(&instance->thread_started); | ||
900 | |||
901 | ret = instance->driver->heavy_init(instance, instance->usb_intf); | ||
902 | |||
903 | if (!ret) | ||
904 | ret = usbatm_atm_init(instance); | ||
905 | |||
906 | down(&instance->serialize); | ||
907 | instance->thread_pid = -1; | ||
908 | up(&instance->serialize); | ||
909 | |||
910 | complete_and_exit(&instance->thread_exited, ret); | ||
911 | } | ||
912 | |||
913 | static int usbatm_heavy_init(struct usbatm_data *instance) | ||
914 | { | ||
915 | int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_KERNEL); | ||
916 | |||
917 | if (ret < 0) { | ||
918 | usb_dbg(instance, "%s: failed to create kernel_thread (%d)!\n", __func__, ret); | ||
919 | return ret; | ||
920 | } | ||
921 | |||
922 | down(&instance->serialize); | ||
923 | instance->thread_pid = ret; | ||
924 | up(&instance->serialize); | ||
925 | |||
926 | wait_for_completion(&instance->thread_started); | ||
927 | |||
928 | return 0; | ||
929 | } | ||
930 | |||
931 | static void usbatm_tasklet_schedule(unsigned long data) | ||
932 | { | ||
933 | tasklet_schedule((struct tasklet_struct *) data); | ||
934 | } | ||
935 | |||
936 | static inline void usbatm_init_channel(struct usbatm_channel *channel) | ||
937 | { | ||
938 | spin_lock_init(&channel->lock); | ||
939 | INIT_LIST_HEAD(&channel->list); | ||
940 | channel->delay.function = usbatm_tasklet_schedule; | ||
941 | channel->delay.data = (unsigned long) &channel->tasklet; | ||
942 | init_timer(&channel->delay); | ||
943 | } | ||
944 | |||
945 | int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, | ||
946 | struct usbatm_driver *driver) | ||
947 | { | ||
948 | struct device *dev = &intf->dev; | ||
949 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
950 | struct usbatm_data *instance; | ||
951 | char *buf; | ||
952 | int error = -ENOMEM; | ||
953 | int i, length; | ||
954 | int need_heavy; | ||
955 | |||
956 | dev_dbg(dev, "%s: trying driver %s with vendor=0x%x, product=0x%x, ifnum %d\n", | ||
957 | __func__, driver->driver_name, | ||
958 | le16_to_cpu(usb_dev->descriptor.idVendor), | ||
959 | le16_to_cpu(usb_dev->descriptor.idProduct), | ||
960 | intf->altsetting->desc.bInterfaceNumber); | ||
961 | |||
962 | /* instance init */ | ||
963 | instance = kcalloc(1, sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL); | ||
964 | if (!instance) { | ||
965 | dev_dbg(dev, "%s: no memory for instance data!\n", __func__); | ||
966 | return -ENOMEM; | ||
967 | } | ||
968 | |||
969 | /* public fields */ | ||
970 | |||
971 | instance->driver = driver; | ||
972 | snprintf(instance->driver_name, sizeof(instance->driver_name), driver->driver_name); | ||
973 | |||
974 | instance->usb_dev = usb_dev; | ||
975 | instance->usb_intf = intf; | ||
976 | |||
977 | buf = instance->description; | ||
978 | length = sizeof(instance->description); | ||
979 | |||
980 | if ((i = usb_string(usb_dev, usb_dev->descriptor.iProduct, buf, length)) < 0) | ||
981 | goto bind; | ||
982 | |||
983 | buf += i; | ||
984 | length -= i; | ||
985 | |||
986 | i = scnprintf(buf, length, " ("); | ||
987 | buf += i; | ||
988 | length -= i; | ||
989 | |||
990 | if (length <= 0 || (i = usb_make_path(usb_dev, buf, length)) < 0) | ||
991 | goto bind; | ||
992 | |||
993 | buf += i; | ||
994 | length -= i; | ||
995 | |||
996 | snprintf(buf, length, ")"); | ||
997 | |||
998 | bind: | ||
999 | need_heavy = 1; | ||
1000 | if (driver->bind && (error = driver->bind(instance, intf, id, &need_heavy)) < 0) { | ||
1001 | dev_dbg(dev, "%s: bind failed: %d!\n", __func__, error); | ||
1002 | goto fail_free; | ||
1003 | } | ||
1004 | |||
1005 | /* private fields */ | ||
1006 | |||
1007 | kref_init(&instance->refcount); /* dropped in usbatm_usb_disconnect */ | ||
1008 | init_MUTEX(&instance->serialize); | ||
1009 | |||
1010 | instance->thread_pid = -1; | ||
1011 | init_completion(&instance->thread_started); | ||
1012 | init_completion(&instance->thread_exited); | ||
1013 | |||
1014 | INIT_LIST_HEAD(&instance->vcc_list); | ||
1015 | |||
1016 | usbatm_init_channel(&instance->rx_channel); | ||
1017 | usbatm_init_channel(&instance->tx_channel); | ||
1018 | tasklet_init(&instance->rx_channel.tasklet, usbatm_rx_process, (unsigned long)instance); | ||
1019 | tasklet_init(&instance->tx_channel.tasklet, usbatm_tx_process, (unsigned long)instance); | ||
1020 | instance->rx_channel.endpoint = usb_rcvbulkpipe(usb_dev, driver->in); | ||
1021 | instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->out); | ||
1022 | instance->rx_channel.stride = ATM_CELL_SIZE + driver->rx_padding; | ||
1023 | instance->tx_channel.stride = ATM_CELL_SIZE + driver->tx_padding; | ||
1024 | instance->rx_channel.buf_size = rcv_buf_size * instance->rx_channel.stride; | ||
1025 | instance->tx_channel.buf_size = snd_buf_size * instance->tx_channel.stride; | ||
1026 | instance->rx_channel.usbatm = instance->tx_channel.usbatm = instance; | ||
1027 | |||
1028 | skb_queue_head_init(&instance->sndqueue); | ||
1029 | |||
1030 | for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) { | ||
1031 | struct urb *urb; | ||
1032 | u8 *buffer; | ||
1033 | unsigned int iso_packets = 0, iso_size = 0; | ||
1034 | struct usbatm_channel *channel = i < num_rcv_urbs ? | ||
1035 | &instance->rx_channel : &instance->tx_channel; | ||
1036 | |||
1037 | if (usb_pipeisoc(channel->endpoint)) { | ||
1038 | /* don't expect iso out endpoints */ | ||
1039 | iso_size = usb_maxpacket(instance->usb_dev, channel->endpoint, 0); | ||
1040 | iso_size -= iso_size % channel->stride; /* alignment */ | ||
1041 | BUG_ON(!iso_size); | ||
1042 | iso_packets = (channel->buf_size - 1) / iso_size + 1; | ||
1043 | } | ||
1044 | |||
1045 | urb = usb_alloc_urb(iso_packets, GFP_KERNEL); | ||
1046 | if (!urb) { | ||
1047 | dev_dbg(dev, "%s: no memory for urb %d!\n", __func__, i); | ||
1048 | goto fail_unbind; | ||
1049 | } | ||
1050 | |||
1051 | instance->urbs[i] = urb; | ||
1052 | |||
1053 | buffer = kmalloc(channel->buf_size, GFP_KERNEL); | ||
1054 | if (!buffer) { | ||
1055 | dev_dbg(dev, "%s: no memory for buffer %d!\n", __func__, i); | ||
1056 | goto fail_unbind; | ||
1057 | } | ||
1058 | memset(buffer, 0, channel->buf_size); | ||
1059 | |||
1060 | usb_fill_bulk_urb(urb, instance->usb_dev, channel->endpoint, | ||
1061 | buffer, channel->buf_size, usbatm_complete, channel); | ||
1062 | if (iso_packets) { | ||
1063 | int j; | ||
1064 | urb->interval = 1; | ||
1065 | urb->transfer_flags = URB_ISO_ASAP; | ||
1066 | urb->number_of_packets = iso_packets; | ||
1067 | for (j = 0; j < iso_packets; j++) { | ||
1068 | urb->iso_frame_desc[j].offset = iso_size * j; | ||
1069 | urb->iso_frame_desc[j].length = min_t(int, iso_size, | ||
1070 | channel->buf_size - urb->iso_frame_desc[j].offset); | ||
1071 | } | ||
1072 | } | ||
1073 | |||
1074 | /* put all tx URBs on the list of spares */ | ||
1075 | if (i >= num_rcv_urbs) | ||
1076 | list_add_tail(&urb->urb_list, &channel->list); | ||
1077 | |||
1078 | vdbg("%s: alloced buffer 0x%p buf size %u urb 0x%p", | ||
1079 | __func__, urb->transfer_buffer, urb->transfer_buffer_length, urb); | ||
1080 | } | ||
1081 | |||
1082 | if (need_heavy && driver->heavy_init) { | ||
1083 | error = usbatm_heavy_init(instance); | ||
1084 | } else { | ||
1085 | complete(&instance->thread_exited); /* pretend that heavy_init was run */ | ||
1086 | error = usbatm_atm_init(instance); | ||
1087 | } | ||
1088 | |||
1089 | if (error < 0) | ||
1090 | goto fail_unbind; | ||
1091 | |||
1092 | usb_get_dev(usb_dev); | ||
1093 | usb_set_intfdata(intf, instance); | ||
1094 | |||
1095 | return 0; | ||
1096 | |||
1097 | fail_unbind: | ||
1098 | if (instance->driver->unbind) | ||
1099 | instance->driver->unbind(instance, intf); | ||
1100 | fail_free: | ||
1101 | for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) { | ||
1102 | if (instance->urbs[i]) | ||
1103 | kfree(instance->urbs[i]->transfer_buffer); | ||
1104 | usb_free_urb(instance->urbs[i]); | ||
1105 | } | ||
1106 | |||
1107 | kfree (instance); | ||
1108 | |||
1109 | return error; | ||
1110 | } | ||
1111 | EXPORT_SYMBOL_GPL(usbatm_usb_probe); | ||
1112 | |||
1113 | void usbatm_usb_disconnect(struct usb_interface *intf) | ||
1114 | { | ||
1115 | struct device *dev = &intf->dev; | ||
1116 | struct usbatm_data *instance = usb_get_intfdata(intf); | ||
1117 | int i; | ||
1118 | |||
1119 | dev_dbg(dev, "%s entered\n", __func__); | ||
1120 | |||
1121 | if (!instance) { | ||
1122 | dev_dbg(dev, "%s: NULL instance!\n", __func__); | ||
1123 | return; | ||
1124 | } | ||
1125 | |||
1126 | usb_set_intfdata(intf, NULL); | ||
1127 | |||
1128 | down(&instance->serialize); | ||
1129 | if (instance->thread_pid >= 0) | ||
1130 | kill_proc(instance->thread_pid, SIGTERM, 1); | ||
1131 | up(&instance->serialize); | ||
1132 | |||
1133 | wait_for_completion(&instance->thread_exited); | ||
1134 | |||
1135 | tasklet_disable(&instance->rx_channel.tasklet); | ||
1136 | tasklet_disable(&instance->tx_channel.tasklet); | ||
1137 | |||
1138 | for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) | ||
1139 | usb_kill_urb(instance->urbs[i]); | ||
1140 | |||
1141 | del_timer_sync(&instance->rx_channel.delay); | ||
1142 | del_timer_sync(&instance->tx_channel.delay); | ||
1143 | |||
1144 | if (instance->atm_dev && instance->driver->atm_stop) | ||
1145 | instance->driver->atm_stop(instance, instance->atm_dev); | ||
1146 | |||
1147 | if (instance->driver->unbind) | ||
1148 | instance->driver->unbind(instance, intf); | ||
1149 | |||
1150 | instance->driver_data = NULL; | ||
1151 | |||
1152 | /* turn usbatm_[rt]x_process into noop */ | ||
1153 | /* no need to take the spinlock */ | ||
1154 | INIT_LIST_HEAD(&instance->rx_channel.list); | ||
1155 | INIT_LIST_HEAD(&instance->tx_channel.list); | ||
1156 | |||
1157 | tasklet_enable(&instance->rx_channel.tasklet); | ||
1158 | tasklet_enable(&instance->tx_channel.tasklet); | ||
1159 | |||
1160 | for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) { | ||
1161 | kfree(instance->urbs[i]->transfer_buffer); | ||
1162 | usb_free_urb(instance->urbs[i]); | ||
1163 | } | ||
1164 | |||
1165 | /* ATM finalize */ | ||
1166 | if (instance->atm_dev) | ||
1167 | shutdown_atm_dev(instance->atm_dev); | ||
1168 | |||
1169 | usbatm_put_instance(instance); /* taken in usbatm_usb_probe */ | ||
1170 | } | ||
1171 | EXPORT_SYMBOL_GPL(usbatm_usb_disconnect); | ||
1172 | |||
1173 | |||
1174 | /*********** | ||
1175 | ** init ** | ||
1176 | ***********/ | ||
1177 | |||
1178 | static int __init usbatm_usb_init(void) | ||
1179 | { | ||
1180 | dbg("%s: driver version %s", __func__, DRIVER_VERSION); | ||
1181 | |||
1182 | if (sizeof(struct usbatm_control) > sizeof(((struct sk_buff *) 0)->cb)) { | ||
1183 | printk(KERN_ERR "%s unusable with this kernel!\n", usbatm_driver_name); | ||
1184 | return -EIO; | ||
1185 | } | ||
1186 | |||
1187 | if ((num_rcv_urbs > UDSL_MAX_RCV_URBS) | ||
1188 | || (num_snd_urbs > UDSL_MAX_SND_URBS) | ||
1189 | || (rcv_buf_size < 1) | ||
1190 | || (rcv_buf_size > UDSL_MAX_RCV_BUF_SIZE) | ||
1191 | || (snd_buf_size < 1) | ||
1192 | || (snd_buf_size > UDSL_MAX_SND_BUF_SIZE)) | ||
1193 | return -EINVAL; | ||
1194 | |||
1195 | return 0; | ||
1196 | } | ||
1197 | module_init(usbatm_usb_init); | ||
1198 | |||
1199 | static void __exit usbatm_usb_exit(void) | ||
1200 | { | ||
1201 | dbg("%s", __func__); | ||
1202 | } | ||
1203 | module_exit(usbatm_usb_exit); | ||
1204 | |||
1205 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
1206 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
1207 | MODULE_LICENSE("GPL"); | ||
1208 | MODULE_VERSION(DRIVER_VERSION); | ||
1209 | |||
1210 | /************ | ||
1211 | ** debug ** | ||
1212 | ************/ | ||
1213 | |||
1214 | #ifdef VERBOSE_DEBUG | ||
1215 | static int usbatm_print_packet(const unsigned char *data, int len) | ||
1216 | { | ||
1217 | unsigned char buffer[256]; | ||
1218 | int i = 0, j = 0; | ||
1219 | |||
1220 | for (i = 0; i < len;) { | ||
1221 | buffer[0] = '\0'; | ||
1222 | sprintf(buffer, "%.3d :", i); | ||
1223 | for (j = 0; (j < 16) && (i < len); j++, i++) { | ||
1224 | sprintf(buffer, "%s %2.2x", buffer, data[i]); | ||
1225 | } | ||
1226 | dbg("%s", buffer); | ||
1227 | } | ||
1228 | return i; | ||
1229 | } | ||
1230 | #endif | ||
diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h new file mode 100644 index 000000000000..936646457935 --- /dev/null +++ b/drivers/usb/atm/usbatm.h | |||
@@ -0,0 +1,184 @@ | |||
1 | /****************************************************************************** | ||
2 | * usbatm.h - Generic USB xDSL driver core | ||
3 | * | ||
4 | * Copyright (C) 2001, Alcatel | ||
5 | * Copyright (C) 2003, Duncan Sands, SolNegro, Josep Comas | ||
6 | * Copyright (C) 2004, David Woodhouse | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
20 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | * | ||
22 | ******************************************************************************/ | ||
23 | |||
24 | #ifndef _USBATM_H_ | ||
25 | #define _USBATM_H_ | ||
26 | |||
27 | #include <linux/config.h> | ||
28 | |||
29 | /* | ||
30 | #define DEBUG | ||
31 | #define VERBOSE_DEBUG | ||
32 | */ | ||
33 | |||
34 | #if !defined (DEBUG) && defined (CONFIG_USB_DEBUG) | ||
35 | # define DEBUG | ||
36 | #endif | ||
37 | |||
38 | #include <asm/semaphore.h> | ||
39 | #include <linux/atm.h> | ||
40 | #include <linux/atmdev.h> | ||
41 | #include <linux/completion.h> | ||
42 | #include <linux/device.h> | ||
43 | #include <linux/kref.h> | ||
44 | #include <linux/list.h> | ||
45 | #include <linux/stringify.h> | ||
46 | #include <linux/usb.h> | ||
47 | |||
48 | #ifdef DEBUG | ||
49 | #define UDSL_ASSERT(x) BUG_ON(!(x)) | ||
50 | #else | ||
51 | #define UDSL_ASSERT(x) do { if (!(x)) warn("failed assertion '%s' at line %d", __stringify(x), __LINE__); } while(0) | ||
52 | #endif | ||
53 | |||
54 | #define usb_err(instance, format, arg...) \ | ||
55 | dev_err(&(instance)->usb_intf->dev , format , ## arg) | ||
56 | #define usb_info(instance, format, arg...) \ | ||
57 | dev_info(&(instance)->usb_intf->dev , format , ## arg) | ||
58 | #define usb_warn(instance, format, arg...) \ | ||
59 | dev_warn(&(instance)->usb_intf->dev , format , ## arg) | ||
60 | #define usb_dbg(instance, format, arg...) \ | ||
61 | dev_dbg(&(instance)->usb_intf->dev , format , ## arg) | ||
62 | |||
63 | /* FIXME: move to dev_* once ATM is driver model aware */ | ||
64 | #define atm_printk(level, instance, format, arg...) \ | ||
65 | printk(level "ATM dev %d: " format , \ | ||
66 | (instance)->atm_dev->number , ## arg) | ||
67 | |||
68 | #define atm_err(instance, format, arg...) \ | ||
69 | atm_printk(KERN_ERR, instance , format , ## arg) | ||
70 | #define atm_info(instance, format, arg...) \ | ||
71 | atm_printk(KERN_INFO, instance , format , ## arg) | ||
72 | #define atm_warn(instance, format, arg...) \ | ||
73 | atm_printk(KERN_WARNING, instance , format , ## arg) | ||
74 | #ifdef DEBUG | ||
75 | #define atm_dbg(instance, format, arg...) \ | ||
76 | atm_printk(KERN_DEBUG, instance , format , ## arg) | ||
77 | #else | ||
78 | #define atm_dbg(instance, format, arg...) \ | ||
79 | do {} while (0) | ||
80 | #endif | ||
81 | |||
82 | |||
83 | /* mini driver */ | ||
84 | |||
85 | struct usbatm_data; | ||
86 | |||
87 | /* | ||
88 | * Assuming all methods exist and succeed, they are called in this order: | ||
89 | * | ||
90 | * bind, heavy_init, atm_start, ..., atm_stop, unbind | ||
91 | */ | ||
92 | |||
93 | struct usbatm_driver { | ||
94 | struct module *owner; | ||
95 | |||
96 | const char *driver_name; | ||
97 | |||
98 | /* | ||
99 | * init device ... can sleep, or cause probe() failure. Drivers with a heavy_init | ||
100 | * method can avoid having it called by setting need_heavy_init to zero. | ||
101 | */ | ||
102 | int (*bind) (struct usbatm_data *, struct usb_interface *, | ||
103 | const struct usb_device_id *id, int *need_heavy_init); | ||
104 | |||
105 | /* additional device initialization that is too slow to be done in probe() */ | ||
106 | int (*heavy_init) (struct usbatm_data *, struct usb_interface *); | ||
107 | |||
108 | /* cleanup device ... can sleep, but can't fail */ | ||
109 | void (*unbind) (struct usbatm_data *, struct usb_interface *); | ||
110 | |||
111 | /* init ATM device ... can sleep, or cause ATM initialization failure */ | ||
112 | int (*atm_start) (struct usbatm_data *, struct atm_dev *); | ||
113 | |||
114 | /* cleanup ATM device ... can sleep, but can't fail */ | ||
115 | void (*atm_stop) (struct usbatm_data *, struct atm_dev *); | ||
116 | |||
117 | int in; /* rx endpoint */ | ||
118 | int out; /* tx endpoint */ | ||
119 | |||
120 | unsigned rx_padding; | ||
121 | unsigned tx_padding; | ||
122 | }; | ||
123 | |||
124 | extern int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, | ||
125 | struct usbatm_driver *driver); | ||
126 | extern void usbatm_usb_disconnect(struct usb_interface *intf); | ||
127 | |||
128 | |||
129 | struct usbatm_channel { | ||
130 | int endpoint; /* usb pipe */ | ||
131 | unsigned int stride; /* ATM cell size + padding */ | ||
132 | unsigned int buf_size; /* urb buffer size */ | ||
133 | spinlock_t lock; | ||
134 | struct list_head list; | ||
135 | struct tasklet_struct tasklet; | ||
136 | struct timer_list delay; | ||
137 | struct usbatm_data *usbatm; | ||
138 | }; | ||
139 | |||
140 | /* main driver data */ | ||
141 | |||
142 | struct usbatm_data { | ||
143 | /****************** | ||
144 | * public fields * | ||
145 | ******************/ | ||
146 | |||
147 | /* mini driver */ | ||
148 | struct usbatm_driver *driver; | ||
149 | void *driver_data; | ||
150 | char driver_name[16]; | ||
151 | |||
152 | /* USB device */ | ||
153 | struct usb_device *usb_dev; | ||
154 | struct usb_interface *usb_intf; | ||
155 | char description[64]; | ||
156 | |||
157 | /* ATM device */ | ||
158 | struct atm_dev *atm_dev; | ||
159 | |||
160 | /******************************** | ||
161 | * private fields - do not use * | ||
162 | ********************************/ | ||
163 | |||
164 | struct kref refcount; | ||
165 | struct semaphore serialize; | ||
166 | |||
167 | /* heavy init */ | ||
168 | int thread_pid; | ||
169 | struct completion thread_started; | ||
170 | struct completion thread_exited; | ||
171 | |||
172 | /* ATM device */ | ||
173 | struct list_head vcc_list; | ||
174 | |||
175 | struct usbatm_channel rx_channel; | ||
176 | struct usbatm_channel tx_channel; | ||
177 | |||
178 | struct sk_buff_head sndqueue; | ||
179 | struct sk_buff *current_skb; /* being emptied */ | ||
180 | |||
181 | struct urb *urbs[0]; | ||
182 | }; | ||
183 | |||
184 | #endif /* _USBATM_H_ */ | ||
diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c new file mode 100644 index 000000000000..7fe7fb484d10 --- /dev/null +++ b/drivers/usb/atm/xusbatm.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /****************************************************************************** | ||
2 | * xusbatm.c - dumb usbatm-based driver for modems initialized in userspace | ||
3 | * | ||
4 | * Copyright (C) 2005 Duncan Sands, Roman Kagan (rkagan % mail ! ru) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the Free | ||
8 | * Software Foundation; either version 2 of the License, or (at your option) | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program; if not, write to the Free Software Foundation, Inc., 59 | ||
18 | * Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | * | ||
20 | ******************************************************************************/ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/netdevice.h> /* FIXME: required by linux/etherdevice.h */ | ||
24 | #include <linux/etherdevice.h> /* for random_ether_addr() */ | ||
25 | |||
26 | #include "usbatm.h" | ||
27 | |||
28 | |||
29 | #define XUSBATM_DRIVERS_MAX 8 | ||
30 | |||
31 | #define XUSBATM_PARM(name, type, parmtype, desc) \ | ||
32 | static type name[XUSBATM_DRIVERS_MAX]; \ | ||
33 | static int num_##name; \ | ||
34 | module_param_array(name, parmtype, &num_##name, 0444); \ | ||
35 | MODULE_PARM_DESC(name, desc) | ||
36 | |||
37 | XUSBATM_PARM(vendor, unsigned short, ushort, "USB device vendor"); | ||
38 | XUSBATM_PARM(product, unsigned short, ushort, "USB device product"); | ||
39 | |||
40 | XUSBATM_PARM(rx_endpoint, unsigned char, byte, "rx endpoint number"); | ||
41 | XUSBATM_PARM(tx_endpoint, unsigned char, byte, "tx endpoint number"); | ||
42 | XUSBATM_PARM(rx_padding, unsigned char, byte, "rx padding (default 0)"); | ||
43 | XUSBATM_PARM(tx_padding, unsigned char, byte, "tx padding (default 0)"); | ||
44 | |||
45 | static const char xusbatm_driver_name[] = "xusbatm"; | ||
46 | |||
47 | static struct usbatm_driver xusbatm_drivers[XUSBATM_DRIVERS_MAX]; | ||
48 | static struct usb_device_id xusbatm_usb_ids[XUSBATM_DRIVERS_MAX + 1]; | ||
49 | static struct usb_driver xusbatm_usb_driver; | ||
50 | |||
51 | static int usb_intf_has_ep(const struct usb_interface *intf, u8 ep) | ||
52 | { | ||
53 | int i, j; | ||
54 | |||
55 | for (i = 0; i < intf->num_altsetting; i++) { | ||
56 | struct usb_host_interface *alt = intf->altsetting; | ||
57 | for (j = 0; j < alt->desc.bNumEndpoints; j++) | ||
58 | if ((alt->endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) == ep) | ||
59 | return 1; | ||
60 | } | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | static int xusbatm_bind(struct usbatm_data *usbatm_instance, | ||
65 | struct usb_interface *intf, const struct usb_device_id *id, | ||
66 | int *need_heavy_init) | ||
67 | { | ||
68 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
69 | int drv_ix = id - xusbatm_usb_ids; | ||
70 | int rx_ep_present = usb_intf_has_ep(intf, rx_endpoint[drv_ix]); | ||
71 | int tx_ep_present = usb_intf_has_ep(intf, tx_endpoint[drv_ix]); | ||
72 | u8 searched_ep = rx_ep_present ? tx_endpoint[drv_ix] : rx_endpoint[drv_ix]; | ||
73 | int i, ret; | ||
74 | |||
75 | usb_dbg(usbatm_instance, "%s: binding driver %d: vendor %#x product %#x" | ||
76 | " rx: ep %#x padd %d tx: ep %#x padd %d\n", | ||
77 | __func__, drv_ix, vendor[drv_ix], product[drv_ix], | ||
78 | rx_endpoint[drv_ix], rx_padding[drv_ix], | ||
79 | tx_endpoint[drv_ix], tx_padding[drv_ix]); | ||
80 | |||
81 | if (!rx_ep_present && !tx_ep_present) { | ||
82 | usb_dbg(usbatm_instance, "%s: intf #%d has neither rx (%#x) nor tx (%#x) endpoint\n", | ||
83 | __func__, intf->altsetting->desc.bInterfaceNumber, | ||
84 | rx_endpoint[drv_ix], tx_endpoint[drv_ix]); | ||
85 | return -ENODEV; | ||
86 | } | ||
87 | |||
88 | if (rx_ep_present && tx_ep_present) | ||
89 | return 0; | ||
90 | |||
91 | for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) { | ||
92 | struct usb_interface *cur_if = usb_dev->actconfig->interface[i]; | ||
93 | |||
94 | if (cur_if != intf && usb_intf_has_ep(cur_if, searched_ep)) { | ||
95 | ret = usb_driver_claim_interface(&xusbatm_usb_driver, | ||
96 | cur_if, usbatm_instance); | ||
97 | if (!ret) | ||
98 | usb_err(usbatm_instance, "%s: failed to claim interface #%d (%d)\n", | ||
99 | __func__, cur_if->altsetting->desc.bInterfaceNumber, ret); | ||
100 | return ret; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | usb_err(usbatm_instance, "%s: no interface has endpoint %#x\n", | ||
105 | __func__, searched_ep); | ||
106 | return -ENODEV; | ||
107 | } | ||
108 | |||
109 | static void xusbatm_unbind(struct usbatm_data *usbatm_instance, | ||
110 | struct usb_interface *intf) | ||
111 | { | ||
112 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
113 | int i; | ||
114 | usb_dbg(usbatm_instance, "%s entered\n", __func__); | ||
115 | |||
116 | for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) { | ||
117 | struct usb_interface *cur_if = usb_dev->actconfig->interface[i]; | ||
118 | usb_set_intfdata(cur_if, NULL); | ||
119 | usb_driver_release_interface(&xusbatm_usb_driver, cur_if); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | static int xusbatm_atm_start(struct usbatm_data *usbatm_instance, | ||
124 | struct atm_dev *atm_dev) | ||
125 | { | ||
126 | atm_dbg(usbatm_instance, "%s entered\n", __func__); | ||
127 | |||
128 | /* use random MAC as we've no way to get it from the device */ | ||
129 | random_ether_addr(atm_dev->esi); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | |||
135 | static int xusbatm_usb_probe(struct usb_interface *intf, | ||
136 | const struct usb_device_id *id) | ||
137 | { | ||
138 | return usbatm_usb_probe(intf, id, | ||
139 | xusbatm_drivers + (id - xusbatm_usb_ids)); | ||
140 | } | ||
141 | |||
142 | static struct usb_driver xusbatm_usb_driver = { | ||
143 | .owner = THIS_MODULE, | ||
144 | .name = xusbatm_driver_name, | ||
145 | .probe = xusbatm_usb_probe, | ||
146 | .disconnect = usbatm_usb_disconnect, | ||
147 | .id_table = xusbatm_usb_ids | ||
148 | }; | ||
149 | |||
150 | static int __init xusbatm_init(void) | ||
151 | { | ||
152 | int i; | ||
153 | |||
154 | dbg("xusbatm_init"); | ||
155 | |||
156 | if (!num_vendor || | ||
157 | num_vendor != num_product || | ||
158 | num_vendor != num_rx_endpoint || | ||
159 | num_vendor != num_tx_endpoint) { | ||
160 | warn("malformed module parameters"); | ||
161 | return -EINVAL; | ||
162 | } | ||
163 | |||
164 | for (i = 0; i < num_vendor; i++) { | ||
165 | xusbatm_usb_ids[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE; | ||
166 | xusbatm_usb_ids[i].idVendor = vendor[i]; | ||
167 | xusbatm_usb_ids[i].idProduct = product[i]; | ||
168 | |||
169 | |||
170 | xusbatm_drivers[i].owner = THIS_MODULE; | ||
171 | xusbatm_drivers[i].driver_name = xusbatm_driver_name; | ||
172 | xusbatm_drivers[i].bind = xusbatm_bind; | ||
173 | xusbatm_drivers[i].unbind = xusbatm_unbind; | ||
174 | xusbatm_drivers[i].atm_start = xusbatm_atm_start; | ||
175 | xusbatm_drivers[i].in = rx_endpoint[i]; | ||
176 | xusbatm_drivers[i].out = tx_endpoint[i]; | ||
177 | xusbatm_drivers[i].rx_padding = rx_padding[i]; | ||
178 | xusbatm_drivers[i].tx_padding = tx_padding[i]; | ||
179 | } | ||
180 | |||
181 | return usb_register(&xusbatm_usb_driver); | ||
182 | } | ||
183 | module_init(xusbatm_init); | ||
184 | |||
185 | static void __exit xusbatm_exit(void) | ||
186 | { | ||
187 | dbg("xusbatm_exit entered"); | ||
188 | |||
189 | usb_deregister(&xusbatm_usb_driver); | ||
190 | } | ||
191 | module_exit(xusbatm_exit); | ||
192 | |||
193 | MODULE_AUTHOR("Roman Kagan, Duncan Sands"); | ||
194 | MODULE_DESCRIPTION("Driver for USB ADSL modems initialized in userspace"); | ||
195 | MODULE_LICENSE("GPL"); | ||
196 | MODULE_VERSION("0.1"); | ||
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 6d1f9b6aecff..69e859e0f51d 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -106,6 +106,111 @@ static int acm_ctrl_msg(struct acm *acm, int request, int value, void *buf, int | |||
106 | acm_ctrl_msg(acm, USB_CDC_REQ_SEND_BREAK, ms, NULL, 0) | 106 | acm_ctrl_msg(acm, USB_CDC_REQ_SEND_BREAK, ms, NULL, 0) |
107 | 107 | ||
108 | /* | 108 | /* |
109 | * Write buffer management. | ||
110 | * All of these assume proper locks taken by the caller. | ||
111 | */ | ||
112 | |||
113 | static int acm_wb_alloc(struct acm *acm) | ||
114 | { | ||
115 | int i, wbn; | ||
116 | struct acm_wb *wb; | ||
117 | |||
118 | wbn = acm->write_current; | ||
119 | i = 0; | ||
120 | for (;;) { | ||
121 | wb = &acm->wb[wbn]; | ||
122 | if (!wb->use) { | ||
123 | wb->use = 1; | ||
124 | return wbn; | ||
125 | } | ||
126 | wbn = (wbn + 1) % ACM_NWB; | ||
127 | if (++i >= ACM_NWB) | ||
128 | return -1; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | static void acm_wb_free(struct acm *acm, int wbn) | ||
133 | { | ||
134 | acm->wb[wbn].use = 0; | ||
135 | } | ||
136 | |||
137 | static int acm_wb_is_avail(struct acm *acm) | ||
138 | { | ||
139 | int i, n; | ||
140 | |||
141 | n = 0; | ||
142 | for (i = 0; i < ACM_NWB; i++) { | ||
143 | if (!acm->wb[i].use) | ||
144 | n++; | ||
145 | } | ||
146 | return n; | ||
147 | } | ||
148 | |||
149 | static inline int acm_wb_is_used(struct acm *acm, int wbn) | ||
150 | { | ||
151 | return acm->wb[wbn].use; | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | * Finish write. | ||
156 | */ | ||
157 | static void acm_write_done(struct acm *acm) | ||
158 | { | ||
159 | unsigned long flags; | ||
160 | int wbn; | ||
161 | |||
162 | spin_lock_irqsave(&acm->write_lock, flags); | ||
163 | acm->write_ready = 1; | ||
164 | wbn = acm->write_current; | ||
165 | acm_wb_free(acm, wbn); | ||
166 | acm->write_current = (wbn + 1) % ACM_NWB; | ||
167 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
168 | } | ||
169 | |||
170 | /* | ||
171 | * Poke write. | ||
172 | */ | ||
173 | static int acm_write_start(struct acm *acm) | ||
174 | { | ||
175 | unsigned long flags; | ||
176 | int wbn; | ||
177 | struct acm_wb *wb; | ||
178 | int rc; | ||
179 | |||
180 | spin_lock_irqsave(&acm->write_lock, flags); | ||
181 | if (!acm->dev) { | ||
182 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
183 | return -ENODEV; | ||
184 | } | ||
185 | |||
186 | if (!acm->write_ready) { | ||
187 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
188 | return 0; /* A white lie */ | ||
189 | } | ||
190 | |||
191 | wbn = acm->write_current; | ||
192 | if (!acm_wb_is_used(acm, wbn)) { | ||
193 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
194 | return 0; | ||
195 | } | ||
196 | wb = &acm->wb[wbn]; | ||
197 | |||
198 | acm->write_ready = 0; | ||
199 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
200 | |||
201 | acm->writeurb->transfer_buffer = wb->buf; | ||
202 | acm->writeurb->transfer_dma = wb->dmah; | ||
203 | acm->writeurb->transfer_buffer_length = wb->len; | ||
204 | acm->writeurb->dev = acm->dev; | ||
205 | |||
206 | if ((rc = usb_submit_urb(acm->writeurb, GFP_ATOMIC)) < 0) { | ||
207 | dbg("usb_submit_urb(write bulk) failed: %d", rc); | ||
208 | acm_write_done(acm); | ||
209 | } | ||
210 | return rc; | ||
211 | } | ||
212 | |||
213 | /* | ||
109 | * Interrupt handlers for various ACM device responses | 214 | * Interrupt handlers for various ACM device responses |
110 | */ | 215 | */ |
111 | 216 | ||
@@ -237,17 +342,13 @@ static void acm_rx_tasklet(unsigned long _acm) | |||
237 | static void acm_write_bulk(struct urb *urb, struct pt_regs *regs) | 342 | static void acm_write_bulk(struct urb *urb, struct pt_regs *regs) |
238 | { | 343 | { |
239 | struct acm *acm = (struct acm *)urb->context; | 344 | struct acm *acm = (struct acm *)urb->context; |
240 | dbg("Entering acm_write_bulk with status %d\n", urb->status); | ||
241 | |||
242 | if (!ACM_READY(acm)) | ||
243 | goto out; | ||
244 | 345 | ||
245 | if (urb->status) | 346 | dbg("Entering acm_write_bulk with status %d\n", urb->status); |
246 | dbg("nonzero write bulk status received: %d", urb->status); | ||
247 | 347 | ||
248 | schedule_work(&acm->work); | 348 | acm_write_done(acm); |
249 | out: | 349 | acm_write_start(acm); |
250 | acm->ready_for_write = 1; | 350 | if (ACM_READY(acm)) |
351 | schedule_work(&acm->work); | ||
251 | } | 352 | } |
252 | 353 | ||
253 | static void acm_softint(void *private) | 354 | static void acm_softint(void *private) |
@@ -351,32 +452,33 @@ static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int c | |||
351 | { | 452 | { |
352 | struct acm *acm = tty->driver_data; | 453 | struct acm *acm = tty->driver_data; |
353 | int stat; | 454 | int stat; |
455 | unsigned long flags; | ||
456 | int wbn; | ||
457 | struct acm_wb *wb; | ||
458 | |||
354 | dbg("Entering acm_tty_write to write %d bytes,\n", count); | 459 | dbg("Entering acm_tty_write to write %d bytes,\n", count); |
355 | 460 | ||
356 | if (!ACM_READY(acm)) | 461 | if (!ACM_READY(acm)) |
357 | return -EINVAL; | 462 | return -EINVAL; |
358 | if (!acm->ready_for_write) | ||
359 | return 0; | ||
360 | if (!count) | 463 | if (!count) |
361 | return 0; | 464 | return 0; |
362 | 465 | ||
363 | count = (count > acm->writesize) ? acm->writesize : count; | 466 | spin_lock_irqsave(&acm->write_lock, flags); |
467 | if ((wbn = acm_wb_alloc(acm)) < 0) { | ||
468 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
469 | acm_write_start(acm); | ||
470 | return 0; | ||
471 | } | ||
472 | wb = &acm->wb[wbn]; | ||
364 | 473 | ||
474 | count = (count > acm->writesize) ? acm->writesize : count; | ||
365 | dbg("Get %d bytes...", count); | 475 | dbg("Get %d bytes...", count); |
366 | memcpy(acm->write_buffer, buf, count); | 476 | memcpy(wb->buf, buf, count); |
367 | dbg(" Successfully copied.\n"); | 477 | wb->len = count; |
478 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
368 | 479 | ||
369 | acm->writeurb->transfer_buffer_length = count; | 480 | if ((stat = acm_write_start(acm)) < 0) |
370 | acm->writeurb->dev = acm->dev; | ||
371 | |||
372 | acm->ready_for_write = 0; | ||
373 | stat = usb_submit_urb(acm->writeurb, GFP_ATOMIC); | ||
374 | if (stat < 0) { | ||
375 | dbg("usb_submit_urb(write bulk) failed"); | ||
376 | acm->ready_for_write = 1; | ||
377 | return stat; | 481 | return stat; |
378 | } | ||
379 | |||
380 | return count; | 482 | return count; |
381 | } | 483 | } |
382 | 484 | ||
@@ -385,7 +487,11 @@ static int acm_tty_write_room(struct tty_struct *tty) | |||
385 | struct acm *acm = tty->driver_data; | 487 | struct acm *acm = tty->driver_data; |
386 | if (!ACM_READY(acm)) | 488 | if (!ACM_READY(acm)) |
387 | return -EINVAL; | 489 | return -EINVAL; |
388 | return !acm->ready_for_write ? 0 : acm->writesize; | 490 | /* |
491 | * Do not let the line discipline to know that we have a reserve, | ||
492 | * or it might get too enthusiastic. | ||
493 | */ | ||
494 | return (acm->write_ready && acm_wb_is_avail(acm)) ? acm->writesize : 0; | ||
389 | } | 495 | } |
390 | 496 | ||
391 | static int acm_tty_chars_in_buffer(struct tty_struct *tty) | 497 | static int acm_tty_chars_in_buffer(struct tty_struct *tty) |
@@ -393,7 +499,10 @@ static int acm_tty_chars_in_buffer(struct tty_struct *tty) | |||
393 | struct acm *acm = tty->driver_data; | 499 | struct acm *acm = tty->driver_data; |
394 | if (!ACM_READY(acm)) | 500 | if (!ACM_READY(acm)) |
395 | return -EINVAL; | 501 | return -EINVAL; |
396 | return !acm->ready_for_write ? acm->writeurb->transfer_buffer_length : 0; | 502 | /* |
503 | * This is inaccurate (overcounts), but it works. | ||
504 | */ | ||
505 | return (ACM_NWB - acm_wb_is_avail(acm)) * acm->writesize; | ||
397 | } | 506 | } |
398 | 507 | ||
399 | static void acm_tty_throttle(struct tty_struct *tty) | 508 | static void acm_tty_throttle(struct tty_struct *tty) |
@@ -526,6 +635,39 @@ static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_ | |||
526 | * USB probe and disconnect routines. | 635 | * USB probe and disconnect routines. |
527 | */ | 636 | */ |
528 | 637 | ||
638 | /* Little helper: write buffers free */ | ||
639 | static void acm_write_buffers_free(struct acm *acm) | ||
640 | { | ||
641 | int i; | ||
642 | struct acm_wb *wb; | ||
643 | |||
644 | for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) { | ||
645 | usb_buffer_free(acm->dev, acm->writesize, wb->buf, wb->dmah); | ||
646 | } | ||
647 | } | ||
648 | |||
649 | /* Little helper: write buffers allocate */ | ||
650 | static int acm_write_buffers_alloc(struct acm *acm) | ||
651 | { | ||
652 | int i; | ||
653 | struct acm_wb *wb; | ||
654 | |||
655 | for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) { | ||
656 | wb->buf = usb_buffer_alloc(acm->dev, acm->writesize, GFP_KERNEL, | ||
657 | &wb->dmah); | ||
658 | if (!wb->buf) { | ||
659 | while (i != 0) { | ||
660 | --i; | ||
661 | --wb; | ||
662 | usb_buffer_free(acm->dev, acm->writesize, | ||
663 | wb->buf, wb->dmah); | ||
664 | } | ||
665 | return -ENOMEM; | ||
666 | } | ||
667 | } | ||
668 | return 0; | ||
669 | } | ||
670 | |||
529 | static int acm_probe (struct usb_interface *intf, | 671 | static int acm_probe (struct usb_interface *intf, |
530 | const struct usb_device_id *id) | 672 | const struct usb_device_id *id) |
531 | { | 673 | { |
@@ -700,7 +842,8 @@ skip_normal_probe: | |||
700 | acm->bh.data = (unsigned long) acm; | 842 | acm->bh.data = (unsigned long) acm; |
701 | INIT_WORK(&acm->work, acm_softint, acm); | 843 | INIT_WORK(&acm->work, acm_softint, acm); |
702 | spin_lock_init(&acm->throttle_lock); | 844 | spin_lock_init(&acm->throttle_lock); |
703 | acm->ready_for_write = 1; | 845 | spin_lock_init(&acm->write_lock); |
846 | acm->write_ready = 1; | ||
704 | 847 | ||
705 | buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); | 848 | buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); |
706 | if (!buf) { | 849 | if (!buf) { |
@@ -716,12 +859,10 @@ skip_normal_probe: | |||
716 | } | 859 | } |
717 | acm->read_buffer = buf; | 860 | acm->read_buffer = buf; |
718 | 861 | ||
719 | buf = usb_buffer_alloc(usb_dev, acm->writesize, GFP_KERNEL, &acm->write_dma); | 862 | if (acm_write_buffers_alloc(acm) < 0) { |
720 | if (!buf) { | ||
721 | dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n"); | 863 | dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n"); |
722 | goto alloc_fail4; | 864 | goto alloc_fail4; |
723 | } | 865 | } |
724 | acm->write_buffer = buf; | ||
725 | 866 | ||
726 | acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL); | 867 | acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL); |
727 | if (!acm->ctrlurb) { | 868 | if (!acm->ctrlurb) { |
@@ -750,9 +891,9 @@ skip_normal_probe: | |||
750 | acm->readurb->transfer_dma = acm->read_dma; | 891 | acm->readurb->transfer_dma = acm->read_dma; |
751 | 892 | ||
752 | usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), | 893 | usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), |
753 | acm->write_buffer, acm->writesize, acm_write_bulk, acm); | 894 | NULL, acm->writesize, acm_write_bulk, acm); |
754 | acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP; | 895 | acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP; |
755 | acm->writeurb->transfer_dma = acm->write_dma; | 896 | /* acm->writeurb->transfer_dma = 0; */ |
756 | 897 | ||
757 | dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); | 898 | dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); |
758 | 899 | ||
@@ -775,7 +916,7 @@ alloc_fail7: | |||
775 | alloc_fail6: | 916 | alloc_fail6: |
776 | usb_free_urb(acm->ctrlurb); | 917 | usb_free_urb(acm->ctrlurb); |
777 | alloc_fail5: | 918 | alloc_fail5: |
778 | usb_buffer_free(usb_dev, acm->writesize, acm->write_buffer, acm->write_dma); | 919 | acm_write_buffers_free(acm); |
779 | alloc_fail4: | 920 | alloc_fail4: |
780 | usb_buffer_free(usb_dev, readsize, acm->read_buffer, acm->read_dma); | 921 | usb_buffer_free(usb_dev, readsize, acm->read_buffer, acm->read_dma); |
781 | alloc_fail3: | 922 | alloc_fail3: |
@@ -806,7 +947,7 @@ static void acm_disconnect(struct usb_interface *intf) | |||
806 | 947 | ||
807 | flush_scheduled_work(); /* wait for acm_softint */ | 948 | flush_scheduled_work(); /* wait for acm_softint */ |
808 | 949 | ||
809 | usb_buffer_free(usb_dev, acm->writesize, acm->write_buffer, acm->write_dma); | 950 | acm_write_buffers_free(acm); |
810 | usb_buffer_free(usb_dev, acm->readsize, acm->read_buffer, acm->read_dma); | 951 | usb_buffer_free(usb_dev, acm->readsize, acm->read_buffer, acm->read_dma); |
811 | usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); | 952 | usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); |
812 | 953 | ||
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index 9009114e311b..963a5dfd2096 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h | |||
@@ -51,14 +51,34 @@ | |||
51 | * Internal driver structures. | 51 | * Internal driver structures. |
52 | */ | 52 | */ |
53 | 53 | ||
54 | /* | ||
55 | * The only reason to have several buffers is to accomodate assumptions | ||
56 | * in line disciplines. They ask for empty space amount, receive our URB size, | ||
57 | * and proceed to issue several 1-character writes, assuming they will fit. | ||
58 | * The very first write takes a complete URB. Fortunately, this only happens | ||
59 | * when processing onlcr, so we only need 2 buffers. | ||
60 | */ | ||
61 | #define ACM_NWB 2 | ||
62 | struct acm_wb { | ||
63 | unsigned char *buf; | ||
64 | dma_addr_t dmah; | ||
65 | int len; | ||
66 | int use; | ||
67 | }; | ||
68 | |||
54 | struct acm { | 69 | struct acm { |
55 | struct usb_device *dev; /* the corresponding usb device */ | 70 | struct usb_device *dev; /* the corresponding usb device */ |
56 | struct usb_interface *control; /* control interface */ | 71 | struct usb_interface *control; /* control interface */ |
57 | struct usb_interface *data; /* data interface */ | 72 | struct usb_interface *data; /* data interface */ |
58 | struct tty_struct *tty; /* the corresponding tty */ | 73 | struct tty_struct *tty; /* the corresponding tty */ |
59 | struct urb *ctrlurb, *readurb, *writeurb; /* urbs */ | 74 | struct urb *ctrlurb, *readurb, *writeurb; /* urbs */ |
60 | u8 *ctrl_buffer, *read_buffer, *write_buffer; /* buffers of urbs */ | 75 | u8 *ctrl_buffer, *read_buffer; /* buffers of urbs */ |
61 | dma_addr_t ctrl_dma, read_dma, write_dma; /* dma handles of buffers */ | 76 | dma_addr_t ctrl_dma, read_dma; /* dma handles of buffers */ |
77 | struct acm_wb wb[ACM_NWB]; | ||
78 | int write_current; /* current write buffer */ | ||
79 | int write_used; /* number of non-empty write buffers */ | ||
80 | int write_ready; /* write urb is not running */ | ||
81 | spinlock_t write_lock; | ||
62 | struct usb_cdc_line_coding line; /* bits, stop, parity */ | 82 | struct usb_cdc_line_coding line; /* bits, stop, parity */ |
63 | struct work_struct work; /* work queue entry for line discipline waking up */ | 83 | struct work_struct work; /* work queue entry for line discipline waking up */ |
64 | struct tasklet_struct bh; /* rx processing */ | 84 | struct tasklet_struct bh; /* rx processing */ |
@@ -71,7 +91,6 @@ struct acm { | |||
71 | unsigned int minor; /* acm minor number */ | 91 | unsigned int minor; /* acm minor number */ |
72 | unsigned char throttle; /* throttled by tty layer */ | 92 | unsigned char throttle; /* throttled by tty layer */ |
73 | unsigned char clocal; /* termios CLOCAL */ | 93 | unsigned char clocal; /* termios CLOCAL */ |
74 | unsigned char ready_for_write; /* write urb can be used */ | ||
75 | unsigned char resubmit_to_unthrottle; /* throtteling has disabled the read urb */ | 94 | unsigned char resubmit_to_unthrottle; /* throtteling has disabled the read urb */ |
76 | unsigned int ctrl_caps; /* control capabilities from the class specific header */ | 95 | unsigned int ctrl_caps; /* control capabilities from the class specific header */ |
77 | }; | 96 | }; |
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index bba22e97ea0f..7ce43fb8118a 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c | |||
@@ -379,6 +379,8 @@ static int usblp_open(struct inode *inode, struct file *file) | |||
379 | usblp->writeurb->transfer_buffer_length = 0; | 379 | usblp->writeurb->transfer_buffer_length = 0; |
380 | usblp->wcomplete = 1; /* we begin writeable */ | 380 | usblp->wcomplete = 1; /* we begin writeable */ |
381 | usblp->rcomplete = 0; | 381 | usblp->rcomplete = 0; |
382 | usblp->writeurb->status = 0; | ||
383 | usblp->readurb->status = 0; | ||
382 | 384 | ||
383 | if (usblp->bidir) { | 385 | if (usblp->bidir) { |
384 | usblp->readcount = 0; | 386 | usblp->readcount = 0; |
@@ -751,6 +753,7 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, | |||
751 | schedule(); | 753 | schedule(); |
752 | } else { | 754 | } else { |
753 | set_current_state(TASK_RUNNING); | 755 | set_current_state(TASK_RUNNING); |
756 | down(&usblp->sem); | ||
754 | break; | 757 | break; |
755 | } | 758 | } |
756 | down (&usblp->sem); | 759 | down (&usblp->sem); |
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 6bfab4bcaa9e..787c27a63c51 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
@@ -784,16 +784,16 @@ static int proc_setconfig(struct dev_state *ps, void __user *arg) | |||
784 | for (i = 0; i < actconfig->desc.bNumInterfaces; ++i) { | 784 | for (i = 0; i < actconfig->desc.bNumInterfaces; ++i) { |
785 | if (usb_interface_claimed(actconfig->interface[i])) { | 785 | if (usb_interface_claimed(actconfig->interface[i])) { |
786 | dev_warn (&ps->dev->dev, | 786 | dev_warn (&ps->dev->dev, |
787 | "usbfs: interface %d claimed " | 787 | "usbfs: interface %d claimed by %s " |
788 | "while '%s' sets config #%d\n", | 788 | "while '%s' sets config #%d\n", |
789 | actconfig->interface[i] | 789 | actconfig->interface[i] |
790 | ->cur_altsetting | 790 | ->cur_altsetting |
791 | ->desc.bInterfaceNumber, | 791 | ->desc.bInterfaceNumber, |
792 | actconfig->interface[i] | ||
793 | ->dev.driver->name, | ||
792 | current->comm, u); | 794 | current->comm, u); |
793 | #if 0 /* FIXME: enable in 2.6.10 or so */ | ||
794 | status = -EBUSY; | 795 | status = -EBUSY; |
795 | break; | 796 | break; |
796 | #endif | ||
797 | } | 797 | } |
798 | } | 798 | } |
799 | } | 799 | } |
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 0da23732e807..83e732a0d64a 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -519,119 +519,120 @@ error: | |||
519 | /*-------------------------------------------------------------------------*/ | 519 | /*-------------------------------------------------------------------------*/ |
520 | 520 | ||
521 | /* | 521 | /* |
522 | * Root Hub interrupt transfers are synthesized with a timer. | 522 | * Root Hub interrupt transfers are polled using a timer if the |
523 | * Completions are called in_interrupt() but not in_irq(). | 523 | * driver requests it; otherwise the driver is responsible for |
524 | * calling usb_hcd_poll_rh_status() when an event occurs. | ||
524 | * | 525 | * |
525 | * Note: some root hubs (including common UHCI based designs) can't | 526 | * Completions are called in_interrupt(), but they may or may not |
526 | * correctly issue port change IRQs. They're the ones that _need_ a | 527 | * be in_irq(). |
527 | * timer; most other root hubs don't. Some systems could save a | ||
528 | * lot of battery power by eliminating these root hub timer IRQs. | ||
529 | */ | 528 | */ |
529 | void usb_hcd_poll_rh_status(struct usb_hcd *hcd) | ||
530 | { | ||
531 | struct urb *urb; | ||
532 | int length; | ||
533 | unsigned long flags; | ||
534 | char buffer[4]; /* Any root hubs with > 31 ports? */ | ||
530 | 535 | ||
531 | static void rh_report_status (unsigned long ptr); | 536 | if (!hcd->uses_new_polling && !hcd->status_urb) |
537 | return; | ||
532 | 538 | ||
533 | static int rh_status_urb (struct usb_hcd *hcd, struct urb *urb) | 539 | length = hcd->driver->hub_status_data(hcd, buffer); |
534 | { | 540 | if (length > 0) { |
535 | int len = 1 + (urb->dev->maxchild / 8); | ||
536 | 541 | ||
537 | /* rh_timer protected by hcd_data_lock */ | 542 | /* try to complete the status urb */ |
538 | if (hcd->rh_timer.data || urb->transfer_buffer_length < len) { | 543 | local_irq_save (flags); |
539 | dev_dbg (hcd->self.controller, | 544 | spin_lock(&hcd_root_hub_lock); |
540 | "not queuing rh status urb, stat %d\n", | 545 | urb = hcd->status_urb; |
541 | urb->status); | 546 | if (urb) { |
542 | return -EINVAL; | 547 | spin_lock(&urb->lock); |
548 | if (urb->status == -EINPROGRESS) { | ||
549 | hcd->poll_pending = 0; | ||
550 | hcd->status_urb = NULL; | ||
551 | urb->status = 0; | ||
552 | urb->hcpriv = NULL; | ||
553 | urb->actual_length = length; | ||
554 | memcpy(urb->transfer_buffer, buffer, length); | ||
555 | } else /* urb has been unlinked */ | ||
556 | length = 0; | ||
557 | spin_unlock(&urb->lock); | ||
558 | } else | ||
559 | length = 0; | ||
560 | spin_unlock(&hcd_root_hub_lock); | ||
561 | |||
562 | /* local irqs are always blocked in completions */ | ||
563 | if (length > 0) | ||
564 | usb_hcd_giveback_urb (hcd, urb, NULL); | ||
565 | else | ||
566 | hcd->poll_pending = 1; | ||
567 | local_irq_restore (flags); | ||
543 | } | 568 | } |
544 | 569 | ||
545 | init_timer (&hcd->rh_timer); | 570 | /* The USB 2.0 spec says 256 ms. This is close enough and won't |
546 | hcd->rh_timer.function = rh_report_status; | 571 | * exceed that limit if HZ is 100. */ |
547 | hcd->rh_timer.data = (unsigned long) urb; | 572 | if (hcd->uses_new_polling ? hcd->poll_rh : |
548 | /* USB 2.0 spec says 256msec; this is close enough */ | 573 | (length == 0 && hcd->status_urb != NULL)) |
549 | hcd->rh_timer.expires = jiffies + HZ/4; | 574 | mod_timer (&hcd->rh_timer, jiffies + msecs_to_jiffies(250)); |
550 | add_timer (&hcd->rh_timer); | ||
551 | urb->hcpriv = hcd; /* nonzero to indicate it's queued */ | ||
552 | return 0; | ||
553 | } | 575 | } |
576 | EXPORT_SYMBOL_GPL(usb_hcd_poll_rh_status); | ||
554 | 577 | ||
555 | /* timer callback */ | 578 | /* timer callback */ |
579 | static void rh_timer_func (unsigned long _hcd) | ||
580 | { | ||
581 | usb_hcd_poll_rh_status((struct usb_hcd *) _hcd); | ||
582 | } | ||
556 | 583 | ||
557 | static void rh_report_status (unsigned long ptr) | 584 | /*-------------------------------------------------------------------------*/ |
585 | |||
586 | static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb) | ||
558 | { | 587 | { |
559 | struct urb *urb; | 588 | int retval; |
560 | struct usb_hcd *hcd; | ||
561 | int length = 0; | ||
562 | unsigned long flags; | 589 | unsigned long flags; |
590 | int len = 1 + (urb->dev->maxchild / 8); | ||
563 | 591 | ||
564 | urb = (struct urb *) ptr; | 592 | spin_lock_irqsave (&hcd_root_hub_lock, flags); |
565 | local_irq_save (flags); | 593 | if (urb->status != -EINPROGRESS) /* already unlinked */ |
566 | spin_lock (&urb->lock); | 594 | retval = urb->status; |
595 | else if (hcd->status_urb || urb->transfer_buffer_length < len) { | ||
596 | dev_dbg (hcd->self.controller, "not queuing rh status urb\n"); | ||
597 | retval = -EINVAL; | ||
598 | } else { | ||
599 | hcd->status_urb = urb; | ||
600 | urb->hcpriv = hcd; /* indicate it's queued */ | ||
567 | 601 | ||
568 | /* do nothing if the urb's been unlinked */ | 602 | if (!hcd->uses_new_polling) |
569 | if (!urb->dev | 603 | mod_timer (&hcd->rh_timer, jiffies + |
570 | || urb->status != -EINPROGRESS | 604 | msecs_to_jiffies(250)); |
571 | || (hcd = urb->dev->bus->hcpriv) == NULL) { | ||
572 | spin_unlock (&urb->lock); | ||
573 | local_irq_restore (flags); | ||
574 | return; | ||
575 | } | ||
576 | 605 | ||
577 | /* complete the status urb, or retrigger the timer */ | 606 | /* If a status change has already occurred, report it ASAP */ |
578 | spin_lock (&hcd_data_lock); | 607 | else if (hcd->poll_pending) |
579 | if (urb->dev->state == USB_STATE_CONFIGURED) { | 608 | mod_timer (&hcd->rh_timer, jiffies); |
580 | length = hcd->driver->hub_status_data ( | 609 | retval = 0; |
581 | hcd, urb->transfer_buffer); | ||
582 | if (length > 0) { | ||
583 | hcd->rh_timer.data = 0; | ||
584 | urb->actual_length = length; | ||
585 | urb->status = 0; | ||
586 | urb->hcpriv = NULL; | ||
587 | } else | ||
588 | mod_timer (&hcd->rh_timer, jiffies + HZ/4); | ||
589 | } | 610 | } |
590 | spin_unlock (&hcd_data_lock); | 611 | spin_unlock_irqrestore (&hcd_root_hub_lock, flags); |
591 | spin_unlock (&urb->lock); | 612 | return retval; |
592 | |||
593 | /* local irqs are always blocked in completions */ | ||
594 | if (length > 0) | ||
595 | usb_hcd_giveback_urb (hcd, urb, NULL); | ||
596 | local_irq_restore (flags); | ||
597 | } | 613 | } |
598 | 614 | ||
599 | /*-------------------------------------------------------------------------*/ | ||
600 | |||
601 | static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb) | 615 | static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb) |
602 | { | 616 | { |
603 | if (usb_pipeint (urb->pipe)) { | 617 | if (usb_pipeint (urb->pipe)) |
604 | int retval; | 618 | return rh_queue_status (hcd, urb); |
605 | unsigned long flags; | ||
606 | |||
607 | spin_lock_irqsave (&hcd_data_lock, flags); | ||
608 | retval = rh_status_urb (hcd, urb); | ||
609 | spin_unlock_irqrestore (&hcd_data_lock, flags); | ||
610 | return retval; | ||
611 | } | ||
612 | if (usb_pipecontrol (urb->pipe)) | 619 | if (usb_pipecontrol (urb->pipe)) |
613 | return rh_call_control (hcd, urb); | 620 | return rh_call_control (hcd, urb); |
614 | else | 621 | return -EINVAL; |
615 | return -EINVAL; | ||
616 | } | 622 | } |
617 | 623 | ||
618 | /*-------------------------------------------------------------------------*/ | 624 | /*-------------------------------------------------------------------------*/ |
619 | 625 | ||
626 | /* Asynchronous unlinks of root-hub control URBs are legal, but they | ||
627 | * don't do anything. Status URB unlinks must be made in process context | ||
628 | * with interrupts enabled. | ||
629 | */ | ||
620 | static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) | 630 | static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) |
621 | { | 631 | { |
622 | unsigned long flags; | 632 | if (usb_pipeendpoint(urb->pipe) == 0) { /* Control URB */ |
633 | if (in_interrupt()) | ||
634 | return 0; /* nothing to do */ | ||
623 | 635 | ||
624 | /* note: always a synchronous unlink */ | ||
625 | if ((unsigned long) urb == hcd->rh_timer.data) { | ||
626 | del_timer_sync (&hcd->rh_timer); | ||
627 | hcd->rh_timer.data = 0; | ||
628 | |||
629 | local_irq_save (flags); | ||
630 | urb->hcpriv = NULL; | ||
631 | usb_hcd_giveback_urb (hcd, urb, NULL); | ||
632 | local_irq_restore (flags); | ||
633 | |||
634 | } else if (usb_pipeendpoint(urb->pipe) == 0) { | ||
635 | spin_lock_irq(&urb->lock); /* from usb_kill_urb */ | 636 | spin_lock_irq(&urb->lock); /* from usb_kill_urb */ |
636 | ++urb->reject; | 637 | ++urb->reject; |
637 | spin_unlock_irq(&urb->lock); | 638 | spin_unlock_irq(&urb->lock); |
@@ -642,8 +643,22 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) | |||
642 | spin_lock_irq(&urb->lock); | 643 | spin_lock_irq(&urb->lock); |
643 | --urb->reject; | 644 | --urb->reject; |
644 | spin_unlock_irq(&urb->lock); | 645 | spin_unlock_irq(&urb->lock); |
645 | } else | 646 | |
646 | return -EINVAL; | 647 | } else { /* Status URB */ |
648 | if (!hcd->uses_new_polling) | ||
649 | del_timer_sync (&hcd->rh_timer); | ||
650 | local_irq_disable (); | ||
651 | spin_lock (&hcd_root_hub_lock); | ||
652 | if (urb == hcd->status_urb) { | ||
653 | hcd->status_urb = NULL; | ||
654 | urb->hcpriv = NULL; | ||
655 | } else | ||
656 | urb = NULL; /* wasn't fully queued */ | ||
657 | spin_unlock (&hcd_root_hub_lock); | ||
658 | if (urb) | ||
659 | usb_hcd_giveback_urb (hcd, urb, NULL); | ||
660 | local_irq_enable (); | ||
661 | } | ||
647 | 662 | ||
648 | return 0; | 663 | return 0; |
649 | } | 664 | } |
@@ -817,30 +832,22 @@ static void usb_deregister_bus (struct usb_bus *bus) | |||
817 | } | 832 | } |
818 | 833 | ||
819 | /** | 834 | /** |
820 | * usb_hcd_register_root_hub - called by HCD to register its root hub | 835 | * register_root_hub - called by usb_add_hcd() to register a root hub |
821 | * @usb_dev: the usb root hub device to be registered. | 836 | * @usb_dev: the usb root hub device to be registered. |
822 | * @hcd: host controller for this root hub | 837 | * @hcd: host controller for this root hub |
823 | * | 838 | * |
824 | * The USB host controller calls this function to register the root hub | 839 | * This function registers the root hub with the USB subsystem. It sets up |
825 | * properly with the USB subsystem. It sets up the device properly in | 840 | * the device properly in the device tree and stores the root_hub pointer |
826 | * the device tree and stores the root_hub pointer in the bus structure, | 841 | * in the bus structure, then calls usb_new_device() to register the usb |
827 | * then calls usb_new_device() to register the usb device. It also | 842 | * device. It also assigns the root hub's USB address (always 1). |
828 | * assigns the root hub's USB address (always 1). | ||
829 | */ | 843 | */ |
830 | int usb_hcd_register_root_hub (struct usb_device *usb_dev, struct usb_hcd *hcd) | 844 | static int register_root_hub (struct usb_device *usb_dev, |
845 | struct usb_hcd *hcd) | ||
831 | { | 846 | { |
832 | struct device *parent_dev = hcd->self.controller; | 847 | struct device *parent_dev = hcd->self.controller; |
833 | const int devnum = 1; | 848 | const int devnum = 1; |
834 | int retval; | 849 | int retval; |
835 | 850 | ||
836 | /* hcd->driver->start() reported can_wakeup, probably with | ||
837 | * assistance from board's boot firmware. | ||
838 | * NOTE: normal devices won't enable wakeup by default. | ||
839 | */ | ||
840 | if (hcd->can_wakeup) | ||
841 | dev_dbg (parent_dev, "supports USB remote wakeup\n"); | ||
842 | hcd->remote_wakeup = hcd->can_wakeup; | ||
843 | |||
844 | usb_dev->devnum = devnum; | 851 | usb_dev->devnum = devnum; |
845 | usb_dev->bus->devnum_next = devnum + 1; | 852 | usb_dev->bus->devnum_next = devnum + 1; |
846 | memset (&usb_dev->bus->devmap.devicemap, 0, | 853 | memset (&usb_dev->bus->devmap.devicemap, 0, |
@@ -883,7 +890,16 @@ int usb_hcd_register_root_hub (struct usb_device *usb_dev, struct usb_hcd *hcd) | |||
883 | 890 | ||
884 | return retval; | 891 | return retval; |
885 | } | 892 | } |
886 | EXPORT_SYMBOL_GPL(usb_hcd_register_root_hub); | 893 | |
894 | void usb_enable_root_hub_irq (struct usb_bus *bus) | ||
895 | { | ||
896 | struct usb_hcd *hcd; | ||
897 | |||
898 | hcd = container_of (bus, struct usb_hcd, self); | ||
899 | if (hcd->driver->hub_irq_enable && !hcd->poll_rh && | ||
900 | hcd->state != HC_STATE_HALT) | ||
901 | hcd->driver->hub_irq_enable (hcd); | ||
902 | } | ||
887 | 903 | ||
888 | 904 | ||
889 | /*-------------------------------------------------------------------------*/ | 905 | /*-------------------------------------------------------------------------*/ |
@@ -1348,7 +1364,8 @@ hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep) | |||
1348 | 1364 | ||
1349 | hcd = udev->bus->hcpriv; | 1365 | hcd = udev->bus->hcpriv; |
1350 | 1366 | ||
1351 | WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT); | 1367 | WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT && |
1368 | udev->state != USB_STATE_NOTATTACHED); | ||
1352 | 1369 | ||
1353 | local_irq_disable (); | 1370 | local_irq_disable (); |
1354 | 1371 | ||
@@ -1612,6 +1629,8 @@ void usb_hc_died (struct usb_hcd *hcd) | |||
1612 | 1629 | ||
1613 | spin_lock_irqsave (&hcd_root_hub_lock, flags); | 1630 | spin_lock_irqsave (&hcd_root_hub_lock, flags); |
1614 | if (hcd->rh_registered) { | 1631 | if (hcd->rh_registered) { |
1632 | hcd->poll_rh = 0; | ||
1633 | del_timer(&hcd->rh_timer); | ||
1615 | 1634 | ||
1616 | /* make khubd clean up old urbs and devices */ | 1635 | /* make khubd clean up old urbs and devices */ |
1617 | usb_set_device_state (hcd->self.root_hub, | 1636 | usb_set_device_state (hcd->self.root_hub, |
@@ -1665,6 +1684,8 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, | |||
1665 | hcd->self.bus_name = bus_name; | 1684 | hcd->self.bus_name = bus_name; |
1666 | 1685 | ||
1667 | init_timer(&hcd->rh_timer); | 1686 | init_timer(&hcd->rh_timer); |
1687 | hcd->rh_timer.function = rh_timer_func; | ||
1688 | hcd->rh_timer.data = (unsigned long) hcd; | ||
1668 | 1689 | ||
1669 | hcd->driver = driver; | 1690 | hcd->driver = driver; |
1670 | hcd->product_desc = (driver->product_desc) ? driver->product_desc : | 1691 | hcd->product_desc = (driver->product_desc) ? driver->product_desc : |
@@ -1694,7 +1715,8 @@ EXPORT_SYMBOL (usb_put_hcd); | |||
1694 | int usb_add_hcd(struct usb_hcd *hcd, | 1715 | int usb_add_hcd(struct usb_hcd *hcd, |
1695 | unsigned int irqnum, unsigned long irqflags) | 1716 | unsigned int irqnum, unsigned long irqflags) |
1696 | { | 1717 | { |
1697 | int retval; | 1718 | int retval; |
1719 | struct usb_device *rhdev; | ||
1698 | 1720 | ||
1699 | dev_info(hcd->self.controller, "%s\n", hcd->product_desc); | 1721 | dev_info(hcd->self.controller, "%s\n", hcd->product_desc); |
1700 | 1722 | ||
@@ -1710,7 +1732,7 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
1710 | } | 1732 | } |
1711 | 1733 | ||
1712 | if ((retval = usb_register_bus(&hcd->self)) < 0) | 1734 | if ((retval = usb_register_bus(&hcd->self)) < 0) |
1713 | goto err1; | 1735 | goto err_register_bus; |
1714 | 1736 | ||
1715 | if (hcd->driver->irq) { | 1737 | if (hcd->driver->irq) { |
1716 | char buf[8], *bufp = buf; | 1738 | char buf[8], *bufp = buf; |
@@ -1727,7 +1749,7 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
1727 | hcd->irq_descr, hcd)) != 0) { | 1749 | hcd->irq_descr, hcd)) != 0) { |
1728 | dev_err(hcd->self.controller, | 1750 | dev_err(hcd->self.controller, |
1729 | "request interrupt %s failed\n", bufp); | 1751 | "request interrupt %s failed\n", bufp); |
1730 | goto err2; | 1752 | goto err_request_irq; |
1731 | } | 1753 | } |
1732 | hcd->irq = irqnum; | 1754 | hcd->irq = irqnum; |
1733 | dev_info(hcd->self.controller, "irq %s, %s 0x%08llx\n", bufp, | 1755 | dev_info(hcd->self.controller, "irq %s, %s 0x%08llx\n", bufp, |
@@ -1743,19 +1765,55 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
1743 | (unsigned long long)hcd->rsrc_start); | 1765 | (unsigned long long)hcd->rsrc_start); |
1744 | } | 1766 | } |
1745 | 1767 | ||
1768 | /* Allocate the root hub before calling hcd->driver->start(), | ||
1769 | * but don't register it until afterward so that the hardware | ||
1770 | * is running. | ||
1771 | */ | ||
1772 | if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) { | ||
1773 | dev_err(hcd->self.controller, "unable to allocate root hub\n"); | ||
1774 | retval = -ENOMEM; | ||
1775 | goto err_allocate_root_hub; | ||
1776 | } | ||
1777 | rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH : | ||
1778 | USB_SPEED_FULL; | ||
1779 | |||
1780 | /* Although in principle hcd->driver->start() might need to use rhdev, | ||
1781 | * none of the current drivers do. | ||
1782 | */ | ||
1746 | if ((retval = hcd->driver->start(hcd)) < 0) { | 1783 | if ((retval = hcd->driver->start(hcd)) < 0) { |
1747 | dev_err(hcd->self.controller, "startup error %d\n", retval); | 1784 | dev_err(hcd->self.controller, "startup error %d\n", retval); |
1748 | goto err3; | 1785 | goto err_hcd_driver_start; |
1749 | } | 1786 | } |
1750 | 1787 | ||
1788 | /* hcd->driver->start() reported can_wakeup, probably with | ||
1789 | * assistance from board's boot firmware. | ||
1790 | * NOTE: normal devices won't enable wakeup by default. | ||
1791 | */ | ||
1792 | if (hcd->can_wakeup) | ||
1793 | dev_dbg(hcd->self.controller, "supports USB remote wakeup\n"); | ||
1794 | hcd->remote_wakeup = hcd->can_wakeup; | ||
1795 | |||
1796 | if ((retval = register_root_hub(rhdev, hcd)) != 0) | ||
1797 | goto err_register_root_hub; | ||
1798 | |||
1799 | if (hcd->uses_new_polling && hcd->poll_rh) | ||
1800 | usb_hcd_poll_rh_status(hcd); | ||
1751 | return retval; | 1801 | return retval; |
1752 | 1802 | ||
1753 | err3: | 1803 | err_register_root_hub: |
1804 | hcd->driver->stop(hcd); | ||
1805 | |||
1806 | err_hcd_driver_start: | ||
1807 | usb_put_dev(rhdev); | ||
1808 | |||
1809 | err_allocate_root_hub: | ||
1754 | if (hcd->irq >= 0) | 1810 | if (hcd->irq >= 0) |
1755 | free_irq(irqnum, hcd); | 1811 | free_irq(irqnum, hcd); |
1756 | err2: | 1812 | |
1813 | err_request_irq: | ||
1757 | usb_deregister_bus(&hcd->self); | 1814 | usb_deregister_bus(&hcd->self); |
1758 | err1: | 1815 | |
1816 | err_register_bus: | ||
1759 | hcd_buffer_destroy(hcd); | 1817 | hcd_buffer_destroy(hcd); |
1760 | return retval; | 1818 | return retval; |
1761 | } | 1819 | } |
@@ -1782,6 +1840,9 @@ void usb_remove_hcd(struct usb_hcd *hcd) | |||
1782 | spin_unlock_irq (&hcd_root_hub_lock); | 1840 | spin_unlock_irq (&hcd_root_hub_lock); |
1783 | usb_disconnect(&hcd->self.root_hub); | 1841 | usb_disconnect(&hcd->self.root_hub); |
1784 | 1842 | ||
1843 | hcd->poll_rh = 0; | ||
1844 | del_timer_sync(&hcd->rh_timer); | ||
1845 | |||
1785 | hcd->driver->stop(hcd); | 1846 | hcd->driver->stop(hcd); |
1786 | hcd->state = HC_STATE_HALT; | 1847 | hcd->state = HC_STATE_HALT; |
1787 | 1848 | ||
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 325a51656c3f..8dc13cde2f73 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h | |||
@@ -65,7 +65,8 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */ | |||
65 | const char *product_desc; /* product/vendor string */ | 65 | const char *product_desc; /* product/vendor string */ |
66 | char irq_descr[24]; /* driver + bus # */ | 66 | char irq_descr[24]; /* driver + bus # */ |
67 | 67 | ||
68 | struct timer_list rh_timer; /* drives root hub */ | 68 | struct timer_list rh_timer; /* drives root-hub polling */ |
69 | struct urb *status_urb; /* the current status urb */ | ||
69 | 70 | ||
70 | /* | 71 | /* |
71 | * hardware info/state | 72 | * hardware info/state |
@@ -76,10 +77,17 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */ | |||
76 | unsigned remote_wakeup:1;/* sw should use wakeup? */ | 77 | unsigned remote_wakeup:1;/* sw should use wakeup? */ |
77 | unsigned rh_registered:1;/* is root hub registered? */ | 78 | unsigned rh_registered:1;/* is root hub registered? */ |
78 | 79 | ||
80 | /* The next flag is a stopgap, to be removed when all the HCDs | ||
81 | * support the new root-hub polling mechanism. */ | ||
82 | unsigned uses_new_polling:1; | ||
83 | unsigned poll_rh:1; /* poll for rh status? */ | ||
84 | unsigned poll_pending:1; /* status has changed? */ | ||
85 | |||
79 | int irq; /* irq allocated */ | 86 | int irq; /* irq allocated */ |
80 | void __iomem *regs; /* device memory/io */ | 87 | void __iomem *regs; /* device memory/io */ |
81 | u64 rsrc_start; /* memory/io resource start */ | 88 | u64 rsrc_start; /* memory/io resource start */ |
82 | u64 rsrc_len; /* memory/io resource length */ | 89 | u64 rsrc_len; /* memory/io resource length */ |
90 | unsigned power_budget; /* in mA, 0 = no limit */ | ||
83 | 91 | ||
84 | #define HCD_BUFFER_POOLS 4 | 92 | #define HCD_BUFFER_POOLS 4 |
85 | struct dma_pool *pool [HCD_BUFFER_POOLS]; | 93 | struct dma_pool *pool [HCD_BUFFER_POOLS]; |
@@ -207,6 +215,8 @@ struct hc_driver { | |||
207 | int (*hub_suspend)(struct usb_hcd *); | 215 | int (*hub_suspend)(struct usb_hcd *); |
208 | int (*hub_resume)(struct usb_hcd *); | 216 | int (*hub_resume)(struct usb_hcd *); |
209 | int (*start_port_reset)(struct usb_hcd *, unsigned port_num); | 217 | int (*start_port_reset)(struct usb_hcd *, unsigned port_num); |
218 | void (*hub_irq_enable)(struct usb_hcd *); | ||
219 | /* Needed only if port-change IRQs are level-triggered */ | ||
210 | }; | 220 | }; |
211 | 221 | ||
212 | extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs); | 222 | extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs); |
@@ -243,7 +253,9 @@ void hcd_buffer_free (struct usb_bus *bus, size_t size, | |||
243 | 253 | ||
244 | /* generic bus glue, needed for host controllers that don't use PCI */ | 254 | /* generic bus glue, needed for host controllers that don't use PCI */ |
245 | extern irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r); | 255 | extern irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r); |
256 | |||
246 | extern void usb_hc_died (struct usb_hcd *hcd); | 257 | extern void usb_hc_died (struct usb_hcd *hcd); |
258 | extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd); | ||
247 | 259 | ||
248 | /* -------------------------------------------------------------------------- */ | 260 | /* -------------------------------------------------------------------------- */ |
249 | 261 | ||
@@ -341,9 +353,6 @@ extern long usb_calc_bus_time (int speed, int is_input, | |||
341 | 353 | ||
342 | extern struct usb_bus *usb_alloc_bus (struct usb_operations *); | 354 | extern struct usb_bus *usb_alloc_bus (struct usb_operations *); |
343 | 355 | ||
344 | extern int usb_hcd_register_root_hub (struct usb_device *usb_dev, | ||
345 | struct usb_hcd *hcd); | ||
346 | |||
347 | extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd); | 356 | extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd); |
348 | 357 | ||
349 | extern void usb_set_device_state(struct usb_device *udev, | 358 | extern void usb_set_device_state(struct usb_device *udev, |
@@ -360,6 +369,8 @@ extern wait_queue_head_t usb_kill_urb_queue; | |||
360 | extern struct usb_bus *usb_bus_get (struct usb_bus *bus); | 369 | extern struct usb_bus *usb_bus_get (struct usb_bus *bus); |
361 | extern void usb_bus_put (struct usb_bus *bus); | 370 | extern void usb_bus_put (struct usb_bus *bus); |
362 | 371 | ||
372 | extern void usb_enable_root_hub_irq (struct usb_bus *bus); | ||
373 | |||
363 | extern int usb_find_interface_driver (struct usb_device *dev, | 374 | extern int usb_find_interface_driver (struct usb_device *dev, |
364 | struct usb_interface *interface); | 375 | struct usb_interface *interface); |
365 | 376 | ||
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a8d879a85d04..32ff32181852 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -643,15 +643,21 @@ static int hub_configure(struct usb_hub *hub, | |||
643 | message = "can't get hub status"; | 643 | message = "can't get hub status"; |
644 | goto fail; | 644 | goto fail; |
645 | } | 645 | } |
646 | cpu_to_le16s(&hubstatus); | 646 | le16_to_cpus(&hubstatus); |
647 | if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) { | 647 | if (hdev == hdev->bus->root_hub) { |
648 | struct usb_hcd *hcd = | ||
649 | container_of(hdev->bus, struct usb_hcd, self); | ||
650 | |||
651 | hub->power_budget = min(500u, hcd->power_budget) / 2; | ||
652 | } else if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) { | ||
648 | dev_dbg(hub_dev, "hub controller current requirement: %dmA\n", | 653 | dev_dbg(hub_dev, "hub controller current requirement: %dmA\n", |
649 | hub->descriptor->bHubContrCurrent); | 654 | hub->descriptor->bHubContrCurrent); |
650 | hub->power_budget = (501 - hub->descriptor->bHubContrCurrent) | 655 | hub->power_budget = (501 - hub->descriptor->bHubContrCurrent) |
651 | / 2; | 656 | / 2; |
657 | } | ||
658 | if (hub->power_budget) | ||
652 | dev_dbg(hub_dev, "%dmA bus power budget for children\n", | 659 | dev_dbg(hub_dev, "%dmA bus power budget for children\n", |
653 | hub->power_budget * 2); | 660 | hub->power_budget * 2); |
654 | } | ||
655 | 661 | ||
656 | 662 | ||
657 | ret = hub_hub_status(hub, &hubstatus, &hubchange); | 663 | ret = hub_hub_status(hub, &hubstatus, &hubchange); |
@@ -1727,7 +1733,7 @@ static int finish_port_resume(struct usb_device *udev) | |||
1727 | struct usb_driver *driver; | 1733 | struct usb_driver *driver; |
1728 | 1734 | ||
1729 | intf = udev->actconfig->interface[i]; | 1735 | intf = udev->actconfig->interface[i]; |
1730 | if (intf->dev.power.power_state == PMSG_SUSPEND) | 1736 | if (intf->dev.power.power_state == PMSG_ON) |
1731 | continue; | 1737 | continue; |
1732 | if (!intf->dev.driver) { | 1738 | if (!intf->dev.driver) { |
1733 | /* FIXME maybe force to alt 0 */ | 1739 | /* FIXME maybe force to alt 0 */ |
@@ -2787,6 +2793,11 @@ static void hub_events(void) | |||
2787 | 2793 | ||
2788 | hub->activating = 0; | 2794 | hub->activating = 0; |
2789 | 2795 | ||
2796 | /* If this is a root hub, tell the HCD it's okay to | ||
2797 | * re-enable port-change interrupts now. */ | ||
2798 | if (!hdev->parent) | ||
2799 | usb_enable_root_hub_irq(hdev->bus); | ||
2800 | |||
2790 | loop: | 2801 | loop: |
2791 | usb_unlock_device(hdev); | 2802 | usb_unlock_device(hdev); |
2792 | usb_put_intf(intf); | 2803 | usb_put_intf(intf); |
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index d114b847d56f..53bf5649621e 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h | |||
@@ -224,15 +224,4 @@ struct usb_hub { | |||
224 | struct work_struct leds; | 224 | struct work_struct leds; |
225 | }; | 225 | }; |
226 | 226 | ||
227 | /* use this for low-powered root hubs */ | ||
228 | static inline void | ||
229 | hub_set_power_budget (struct usb_device *hubdev, unsigned mA) | ||
230 | { | ||
231 | struct usb_hub *hub; | ||
232 | |||
233 | hub = (struct usb_hub *) | ||
234 | usb_get_intfdata (hubdev->actconfig->interface[0]); | ||
235 | hub->power_budget = min(mA,(unsigned)500)/2; | ||
236 | } | ||
237 | |||
238 | #endif /* __LINUX_HUB_H */ | 227 | #endif /* __LINUX_HUB_H */ |
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 3b24f9f2c234..ff075a53c8d6 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -53,6 +53,9 @@ config USB_GADGET_DEBUG_FILES | |||
53 | driver on a new board. Enable these files by choosing "Y" | 53 | driver on a new board. Enable these files by choosing "Y" |
54 | here. If in doubt, or to conserve kernel memory, say "N". | 54 | here. If in doubt, or to conserve kernel memory, say "N". |
55 | 55 | ||
56 | config USB_GADGET_SELECTED | ||
57 | boolean | ||
58 | |||
56 | # | 59 | # |
57 | # USB Peripheral Controller Support | 60 | # USB Peripheral Controller Support |
58 | # | 61 | # |
@@ -85,6 +88,7 @@ config USB_NET2280 | |||
85 | tristate | 88 | tristate |
86 | depends on USB_GADGET_NET2280 | 89 | depends on USB_GADGET_NET2280 |
87 | default USB_GADGET | 90 | default USB_GADGET |
91 | select USB_GADGET_SELECTED | ||
88 | 92 | ||
89 | config USB_GADGET_PXA2XX | 93 | config USB_GADGET_PXA2XX |
90 | boolean "PXA 25x or IXP 4xx" | 94 | boolean "PXA 25x or IXP 4xx" |
@@ -105,6 +109,7 @@ config USB_PXA2XX | |||
105 | tristate | 109 | tristate |
106 | depends on USB_GADGET_PXA2XX | 110 | depends on USB_GADGET_PXA2XX |
107 | default USB_GADGET | 111 | default USB_GADGET |
112 | select USB_GADGET_SELECTED | ||
108 | 113 | ||
109 | # if there's only one gadget driver, using only two bulk endpoints, | 114 | # if there's only one gadget driver, using only two bulk endpoints, |
110 | # don't waste memory for the other endpoints | 115 | # don't waste memory for the other endpoints |
@@ -134,6 +139,7 @@ config USB_GOKU | |||
134 | tristate | 139 | tristate |
135 | depends on USB_GADGET_GOKU | 140 | depends on USB_GADGET_GOKU |
136 | default USB_GADGET | 141 | default USB_GADGET |
142 | select USB_GADGET_SELECTED | ||
137 | 143 | ||
138 | 144 | ||
139 | config USB_GADGET_LH7A40X | 145 | config USB_GADGET_LH7A40X |
@@ -146,6 +152,7 @@ config USB_LH7A40X | |||
146 | tristate | 152 | tristate |
147 | depends on USB_GADGET_LH7A40X | 153 | depends on USB_GADGET_LH7A40X |
148 | default USB_GADGET | 154 | default USB_GADGET |
155 | select USB_GADGET_SELECTED | ||
149 | 156 | ||
150 | 157 | ||
151 | config USB_GADGET_OMAP | 158 | config USB_GADGET_OMAP |
@@ -167,6 +174,7 @@ config USB_OMAP | |||
167 | tristate | 174 | tristate |
168 | depends on USB_GADGET_OMAP | 175 | depends on USB_GADGET_OMAP |
169 | default USB_GADGET | 176 | default USB_GADGET |
177 | select USB_GADGET_SELECTED | ||
170 | 178 | ||
171 | config USB_OTG | 179 | config USB_OTG |
172 | boolean "OTG Support" | 180 | boolean "OTG Support" |
@@ -207,6 +215,7 @@ config USB_DUMMY_HCD | |||
207 | tristate | 215 | tristate |
208 | depends on USB_GADGET_DUMMY_HCD | 216 | depends on USB_GADGET_DUMMY_HCD |
209 | default USB_GADGET | 217 | default USB_GADGET |
218 | select USB_GADGET_SELECTED | ||
210 | 219 | ||
211 | # NOTE: Please keep dummy_hcd LAST so that "real hardware" appears | 220 | # NOTE: Please keep dummy_hcd LAST so that "real hardware" appears |
212 | # first and will be selected by default. | 221 | # first and will be selected by default. |
@@ -226,7 +235,7 @@ config USB_GADGET_DUALSPEED | |||
226 | # | 235 | # |
227 | choice | 236 | choice |
228 | tristate "USB Gadget Drivers" | 237 | tristate "USB Gadget Drivers" |
229 | depends on USB_GADGET | 238 | depends on USB_GADGET && USB_GADGET_SELECTED |
230 | default USB_ETH | 239 | default USB_ETH |
231 | help | 240 | help |
232 | A Linux "Gadget Driver" talks to the USB Peripheral Controller | 241 | A Linux "Gadget Driver" talks to the USB Peripheral Controller |
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index c039d2fbe7ab..4d692670f288 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c | |||
@@ -65,7 +65,7 @@ | |||
65 | 65 | ||
66 | 66 | ||
67 | #define DRIVER_DESC "USB Host+Gadget Emulator" | 67 | #define DRIVER_DESC "USB Host+Gadget Emulator" |
68 | #define DRIVER_VERSION "17 Dec 2004" | 68 | #define DRIVER_VERSION "02 May 2005" |
69 | 69 | ||
70 | static const char driver_name [] = "dummy_hcd"; | 70 | static const char driver_name [] = "dummy_hcd"; |
71 | static const char driver_desc [] = "USB Host+Gadget Emulator"; | 71 | static const char driver_desc [] = "USB Host+Gadget Emulator"; |
@@ -141,6 +141,8 @@ static const char *const ep_name [] = { | |||
141 | }; | 141 | }; |
142 | #define DUMMY_ENDPOINTS (sizeof(ep_name)/sizeof(char *)) | 142 | #define DUMMY_ENDPOINTS (sizeof(ep_name)/sizeof(char *)) |
143 | 143 | ||
144 | /*-------------------------------------------------------------------------*/ | ||
145 | |||
144 | #define FIFO_SIZE 64 | 146 | #define FIFO_SIZE 64 |
145 | 147 | ||
146 | struct urbp { | 148 | struct urbp { |
@@ -148,6 +150,13 @@ struct urbp { | |||
148 | struct list_head urbp_list; | 150 | struct list_head urbp_list; |
149 | }; | 151 | }; |
150 | 152 | ||
153 | |||
154 | enum dummy_rh_state { | ||
155 | DUMMY_RH_RESET, | ||
156 | DUMMY_RH_SUSPENDED, | ||
157 | DUMMY_RH_RUNNING | ||
158 | }; | ||
159 | |||
151 | struct dummy { | 160 | struct dummy { |
152 | spinlock_t lock; | 161 | spinlock_t lock; |
153 | 162 | ||
@@ -161,12 +170,18 @@ struct dummy { | |||
161 | struct dummy_request fifo_req; | 170 | struct dummy_request fifo_req; |
162 | u8 fifo_buf [FIFO_SIZE]; | 171 | u8 fifo_buf [FIFO_SIZE]; |
163 | u16 devstatus; | 172 | u16 devstatus; |
173 | unsigned udc_suspended:1; | ||
174 | unsigned pullup:1; | ||
175 | unsigned active:1; | ||
176 | unsigned old_active:1; | ||
164 | 177 | ||
165 | /* | 178 | /* |
166 | * MASTER/HOST side support | 179 | * MASTER/HOST side support |
167 | */ | 180 | */ |
181 | enum dummy_rh_state rh_state; | ||
168 | struct timer_list timer; | 182 | struct timer_list timer; |
169 | u32 port_status; | 183 | u32 port_status; |
184 | u32 old_status; | ||
170 | unsigned resuming:1; | 185 | unsigned resuming:1; |
171 | unsigned long re_timeout; | 186 | unsigned long re_timeout; |
172 | 187 | ||
@@ -189,6 +204,11 @@ static inline struct device *dummy_dev (struct dummy *dum) | |||
189 | return dummy_to_hcd(dum)->self.controller; | 204 | return dummy_to_hcd(dum)->self.controller; |
190 | } | 205 | } |
191 | 206 | ||
207 | static inline struct device *udc_dev (struct dummy *dum) | ||
208 | { | ||
209 | return dum->gadget.dev.parent; | ||
210 | } | ||
211 | |||
192 | static inline struct dummy *ep_to_dummy (struct dummy_ep *ep) | 212 | static inline struct dummy *ep_to_dummy (struct dummy_ep *ep) |
193 | { | 213 | { |
194 | return container_of (ep->gadget, struct dummy, gadget); | 214 | return container_of (ep->gadget, struct dummy, gadget); |
@@ -208,16 +228,98 @@ static struct dummy *the_controller; | |||
208 | 228 | ||
209 | /*-------------------------------------------------------------------------*/ | 229 | /*-------------------------------------------------------------------------*/ |
210 | 230 | ||
211 | /* | 231 | /* SLAVE/GADGET SIDE UTILITY ROUTINES */ |
212 | * This "hardware" may look a bit odd in diagnostics since it's got both | ||
213 | * host and device sides; and it binds different drivers to each side. | ||
214 | */ | ||
215 | static struct platform_device the_pdev; | ||
216 | 232 | ||
217 | static struct device_driver dummy_driver = { | 233 | /* called with spinlock held */ |
218 | .name = (char *) driver_name, | 234 | static void nuke (struct dummy *dum, struct dummy_ep *ep) |
219 | .bus = &platform_bus_type, | 235 | { |
220 | }; | 236 | while (!list_empty (&ep->queue)) { |
237 | struct dummy_request *req; | ||
238 | |||
239 | req = list_entry (ep->queue.next, struct dummy_request, queue); | ||
240 | list_del_init (&req->queue); | ||
241 | req->req.status = -ESHUTDOWN; | ||
242 | |||
243 | spin_unlock (&dum->lock); | ||
244 | req->req.complete (&ep->ep, &req->req); | ||
245 | spin_lock (&dum->lock); | ||
246 | } | ||
247 | } | ||
248 | |||
249 | /* caller must hold lock */ | ||
250 | static void | ||
251 | stop_activity (struct dummy *dum) | ||
252 | { | ||
253 | struct dummy_ep *ep; | ||
254 | |||
255 | /* prevent any more requests */ | ||
256 | dum->address = 0; | ||
257 | |||
258 | /* The timer is left running so that outstanding URBs can fail */ | ||
259 | |||
260 | /* nuke any pending requests first, so driver i/o is quiesced */ | ||
261 | list_for_each_entry (ep, &dum->gadget.ep_list, ep.ep_list) | ||
262 | nuke (dum, ep); | ||
263 | |||
264 | /* driver now does any non-usb quiescing necessary */ | ||
265 | } | ||
266 | |||
267 | /* caller must hold lock */ | ||
268 | static void | ||
269 | set_link_state (struct dummy *dum) | ||
270 | { | ||
271 | dum->active = 0; | ||
272 | if ((dum->port_status & USB_PORT_STAT_POWER) == 0) | ||
273 | dum->port_status = 0; | ||
274 | |||
275 | /* UDC suspend must cause a disconnect */ | ||
276 | else if (!dum->pullup || dum->udc_suspended) { | ||
277 | dum->port_status &= ~(USB_PORT_STAT_CONNECTION | | ||
278 | USB_PORT_STAT_ENABLE | | ||
279 | USB_PORT_STAT_LOW_SPEED | | ||
280 | USB_PORT_STAT_HIGH_SPEED | | ||
281 | USB_PORT_STAT_SUSPEND); | ||
282 | if ((dum->old_status & USB_PORT_STAT_CONNECTION) != 0) | ||
283 | dum->port_status |= (USB_PORT_STAT_C_CONNECTION << 16); | ||
284 | } else { | ||
285 | dum->port_status |= USB_PORT_STAT_CONNECTION; | ||
286 | if ((dum->old_status & USB_PORT_STAT_CONNECTION) == 0) | ||
287 | dum->port_status |= (USB_PORT_STAT_C_CONNECTION << 16); | ||
288 | if ((dum->port_status & USB_PORT_STAT_ENABLE) == 0) | ||
289 | dum->port_status &= ~USB_PORT_STAT_SUSPEND; | ||
290 | else if ((dum->port_status & USB_PORT_STAT_SUSPEND) == 0 && | ||
291 | dum->rh_state != DUMMY_RH_SUSPENDED) | ||
292 | dum->active = 1; | ||
293 | } | ||
294 | |||
295 | if ((dum->port_status & USB_PORT_STAT_ENABLE) == 0 || dum->active) | ||
296 | dum->resuming = 0; | ||
297 | |||
298 | if ((dum->port_status & USB_PORT_STAT_CONNECTION) == 0 || | ||
299 | (dum->port_status & USB_PORT_STAT_RESET) != 0) { | ||
300 | if ((dum->old_status & USB_PORT_STAT_CONNECTION) != 0 && | ||
301 | (dum->old_status & USB_PORT_STAT_RESET) == 0 && | ||
302 | dum->driver) { | ||
303 | stop_activity (dum); | ||
304 | spin_unlock (&dum->lock); | ||
305 | dum->driver->disconnect (&dum->gadget); | ||
306 | spin_lock (&dum->lock); | ||
307 | } | ||
308 | } else if (dum->active != dum->old_active) { | ||
309 | if (dum->old_active && dum->driver->suspend) { | ||
310 | spin_unlock (&dum->lock); | ||
311 | dum->driver->suspend (&dum->gadget); | ||
312 | spin_lock (&dum->lock); | ||
313 | } else if (!dum->old_active && dum->driver->resume) { | ||
314 | spin_unlock (&dum->lock); | ||
315 | dum->driver->resume (&dum->gadget); | ||
316 | spin_lock (&dum->lock); | ||
317 | } | ||
318 | } | ||
319 | |||
320 | dum->old_status = dum->port_status; | ||
321 | dum->old_active = dum->active; | ||
322 | } | ||
221 | 323 | ||
222 | /*-------------------------------------------------------------------------*/ | 324 | /*-------------------------------------------------------------------------*/ |
223 | 325 | ||
@@ -324,7 +426,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) | |||
324 | _ep->maxpacket = max; | 426 | _ep->maxpacket = max; |
325 | ep->desc = desc; | 427 | ep->desc = desc; |
326 | 428 | ||
327 | dev_dbg (dummy_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d\n", | 429 | dev_dbg (udc_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d\n", |
328 | _ep->name, | 430 | _ep->name, |
329 | desc->bEndpointAddress & 0x0f, | 431 | desc->bEndpointAddress & 0x0f, |
330 | (desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out", | 432 | (desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out", |
@@ -345,22 +447,6 @@ done: | |||
345 | return retval; | 447 | return retval; |
346 | } | 448 | } |
347 | 449 | ||
348 | /* called with spinlock held */ | ||
349 | static void nuke (struct dummy *dum, struct dummy_ep *ep) | ||
350 | { | ||
351 | while (!list_empty (&ep->queue)) { | ||
352 | struct dummy_request *req; | ||
353 | |||
354 | req = list_entry (ep->queue.next, struct dummy_request, queue); | ||
355 | list_del_init (&req->queue); | ||
356 | req->req.status = -ESHUTDOWN; | ||
357 | |||
358 | spin_unlock (&dum->lock); | ||
359 | req->req.complete (&ep->ep, &req->req); | ||
360 | spin_lock (&dum->lock); | ||
361 | } | ||
362 | } | ||
363 | |||
364 | static int dummy_disable (struct usb_ep *_ep) | 450 | static int dummy_disable (struct usb_ep *_ep) |
365 | { | 451 | { |
366 | struct dummy_ep *ep; | 452 | struct dummy_ep *ep; |
@@ -379,7 +465,7 @@ static int dummy_disable (struct usb_ep *_ep) | |||
379 | nuke (dum, ep); | 465 | nuke (dum, ep); |
380 | spin_unlock_irqrestore (&dum->lock, flags); | 466 | spin_unlock_irqrestore (&dum->lock, flags); |
381 | 467 | ||
382 | dev_dbg (dummy_dev(dum), "disabled %s\n", _ep->name); | 468 | dev_dbg (udc_dev(dum), "disabled %s\n", _ep->name); |
383 | return retval; | 469 | return retval; |
384 | } | 470 | } |
385 | 471 | ||
@@ -474,7 +560,7 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req, int mem_flags) | |||
474 | return -ESHUTDOWN; | 560 | return -ESHUTDOWN; |
475 | 561 | ||
476 | #if 0 | 562 | #if 0 |
477 | dev_dbg (dummy_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n", | 563 | dev_dbg (udc_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n", |
478 | ep, _req, _ep->name, _req->length, _req->buf); | 564 | ep, _req, _ep->name, _req->length, _req->buf); |
479 | #endif | 565 | #endif |
480 | 566 | ||
@@ -537,7 +623,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req) | |||
537 | spin_unlock_irqrestore (&dum->lock, flags); | 623 | spin_unlock_irqrestore (&dum->lock, flags); |
538 | 624 | ||
539 | if (retval == 0) { | 625 | if (retval == 0) { |
540 | dev_dbg (dummy_dev(dum), | 626 | dev_dbg (udc_dev(dum), |
541 | "dequeued req %p from %s, len %d buf %p\n", | 627 | "dequeued req %p from %s, len %d buf %p\n", |
542 | req, _ep->name, _req->length, _req->buf); | 628 | req, _ep->name, _req->length, _req->buf); |
543 | _req->complete (_ep, _req); | 629 | _req->complete (_ep, _req); |
@@ -601,13 +687,21 @@ static int dummy_wakeup (struct usb_gadget *_gadget) | |||
601 | struct dummy *dum; | 687 | struct dummy *dum; |
602 | 688 | ||
603 | dum = gadget_to_dummy (_gadget); | 689 | dum = gadget_to_dummy (_gadget); |
604 | if ((dum->devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) == 0 | 690 | if (!(dum->devstatus & ( (1 << USB_DEVICE_B_HNP_ENABLE) |
605 | || !(dum->port_status & (1 << USB_PORT_FEAT_SUSPEND))) | 691 | | (1 << USB_DEVICE_REMOTE_WAKEUP)))) |
606 | return -EINVAL; | 692 | return -EINVAL; |
693 | if ((dum->port_status & USB_PORT_STAT_CONNECTION) == 0) | ||
694 | return -ENOLINK; | ||
695 | if ((dum->port_status & USB_PORT_STAT_SUSPEND) == 0 && | ||
696 | dum->rh_state != DUMMY_RH_SUSPENDED) | ||
697 | return -EIO; | ||
698 | |||
699 | /* FIXME: What if the root hub is suspended but the port isn't? */ | ||
607 | 700 | ||
608 | /* hub notices our request, issues downstream resume, etc */ | 701 | /* hub notices our request, issues downstream resume, etc */ |
609 | dum->resuming = 1; | 702 | dum->resuming = 1; |
610 | dum->port_status |= (1 << USB_PORT_FEAT_C_SUSPEND); | 703 | dum->re_timeout = jiffies + msecs_to_jiffies(20); |
704 | mod_timer (&dummy_to_hcd (dum)->rh_timer, dum->re_timeout); | ||
611 | return 0; | 705 | return 0; |
612 | } | 706 | } |
613 | 707 | ||
@@ -623,10 +717,26 @@ static int dummy_set_selfpowered (struct usb_gadget *_gadget, int value) | |||
623 | return 0; | 717 | return 0; |
624 | } | 718 | } |
625 | 719 | ||
720 | static int dummy_pullup (struct usb_gadget *_gadget, int value) | ||
721 | { | ||
722 | struct dummy *dum; | ||
723 | unsigned long flags; | ||
724 | |||
725 | dum = gadget_to_dummy (_gadget); | ||
726 | spin_lock_irqsave (&dum->lock, flags); | ||
727 | dum->pullup = (value != 0); | ||
728 | set_link_state (dum); | ||
729 | spin_unlock_irqrestore (&dum->lock, flags); | ||
730 | |||
731 | usb_hcd_poll_rh_status (dummy_to_hcd (dum)); | ||
732 | return 0; | ||
733 | } | ||
734 | |||
626 | static const struct usb_gadget_ops dummy_ops = { | 735 | static const struct usb_gadget_ops dummy_ops = { |
627 | .get_frame = dummy_g_get_frame, | 736 | .get_frame = dummy_g_get_frame, |
628 | .wakeup = dummy_wakeup, | 737 | .wakeup = dummy_wakeup, |
629 | .set_selfpowered = dummy_set_selfpowered, | 738 | .set_selfpowered = dummy_set_selfpowered, |
739 | .pullup = dummy_pullup, | ||
630 | }; | 740 | }; |
631 | 741 | ||
632 | /*-------------------------------------------------------------------------*/ | 742 | /*-------------------------------------------------------------------------*/ |
@@ -641,7 +751,7 @@ show_function (struct device *dev, struct device_attribute *attr, char *buf) | |||
641 | return 0; | 751 | return 0; |
642 | return scnprintf (buf, PAGE_SIZE, "%s\n", dum->driver->function); | 752 | return scnprintf (buf, PAGE_SIZE, "%s\n", dum->driver->function); |
643 | } | 753 | } |
644 | DEVICE_ATTR (function, S_IRUGO, show_function, NULL); | 754 | static DEVICE_ATTR (function, S_IRUGO, show_function, NULL); |
645 | 755 | ||
646 | /*-------------------------------------------------------------------------*/ | 756 | /*-------------------------------------------------------------------------*/ |
647 | 757 | ||
@@ -659,38 +769,6 @@ DEVICE_ATTR (function, S_IRUGO, show_function, NULL); | |||
659 | * for each driver that registers: just add to a big root hub. | 769 | * for each driver that registers: just add to a big root hub. |
660 | */ | 770 | */ |
661 | 771 | ||
662 | static void | ||
663 | dummy_udc_release (struct device *dev) | ||
664 | { | ||
665 | } | ||
666 | |||
667 | static void | ||
668 | dummy_pdev_release (struct device *dev) | ||
669 | { | ||
670 | } | ||
671 | |||
672 | static int | ||
673 | dummy_register_udc (struct dummy *dum) | ||
674 | { | ||
675 | int rc; | ||
676 | |||
677 | strcpy (dum->gadget.dev.bus_id, "udc"); | ||
678 | dum->gadget.dev.parent = dummy_dev(dum); | ||
679 | dum->gadget.dev.release = dummy_udc_release; | ||
680 | |||
681 | rc = device_register (&dum->gadget.dev); | ||
682 | if (rc == 0) | ||
683 | device_create_file (&dum->gadget.dev, &dev_attr_function); | ||
684 | return rc; | ||
685 | } | ||
686 | |||
687 | static void | ||
688 | dummy_unregister_udc (struct dummy *dum) | ||
689 | { | ||
690 | device_remove_file (&dum->gadget.dev, &dev_attr_function); | ||
691 | device_unregister (&dum->gadget.dev); | ||
692 | } | ||
693 | |||
694 | int | 772 | int |
695 | usb_gadget_register_driver (struct usb_gadget_driver *driver) | 773 | usb_gadget_register_driver (struct usb_gadget_driver *driver) |
696 | { | 774 | { |
@@ -709,12 +787,8 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
709 | * SLAVE side init ... the layer above hardware, which | 787 | * SLAVE side init ... the layer above hardware, which |
710 | * can't enumerate without help from the driver we're binding. | 788 | * can't enumerate without help from the driver we're binding. |
711 | */ | 789 | */ |
712 | dum->gadget.name = gadget_name; | ||
713 | dum->gadget.ops = &dummy_ops; | ||
714 | dum->gadget.is_dualspeed = 1; | ||
715 | 790 | ||
716 | dum->devstatus = 0; | 791 | dum->devstatus = 0; |
717 | dum->resuming = 0; | ||
718 | 792 | ||
719 | INIT_LIST_HEAD (&dum->gadget.ep_list); | 793 | INIT_LIST_HEAD (&dum->gadget.ep_list); |
720 | for (i = 0; i < DUMMY_ENDPOINTS; i++) { | 794 | for (i = 0; i < DUMMY_ENDPOINTS; i++) { |
@@ -740,7 +814,7 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
740 | 814 | ||
741 | dum->driver = driver; | 815 | dum->driver = driver; |
742 | dum->gadget.dev.driver = &driver->driver; | 816 | dum->gadget.dev.driver = &driver->driver; |
743 | dev_dbg (dummy_dev(dum), "binding gadget driver '%s'\n", | 817 | dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n", |
744 | driver->driver.name); | 818 | driver->driver.name); |
745 | if ((retval = driver->bind (&dum->gadget)) != 0) { | 819 | if ((retval = driver->bind (&dum->gadget)) != 0) { |
746 | dum->driver = NULL; | 820 | dum->driver = NULL; |
@@ -748,42 +822,21 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
748 | return retval; | 822 | return retval; |
749 | } | 823 | } |
750 | 824 | ||
751 | // FIXME: Check these calls for errors and re-order | ||
752 | driver->driver.bus = dum->gadget.dev.parent->bus; | 825 | driver->driver.bus = dum->gadget.dev.parent->bus; |
753 | driver_register (&driver->driver); | 826 | driver_register (&driver->driver); |
754 | |||
755 | device_bind_driver (&dum->gadget.dev); | 827 | device_bind_driver (&dum->gadget.dev); |
756 | 828 | ||
757 | /* khubd will enumerate this in a while */ | 829 | /* khubd will enumerate this in a while */ |
758 | dum->port_status |= USB_PORT_STAT_CONNECTION | 830 | spin_lock_irq (&dum->lock); |
759 | | (1 << USB_PORT_FEAT_C_CONNECTION); | 831 | dum->pullup = 1; |
832 | set_link_state (dum); | ||
833 | spin_unlock_irq (&dum->lock); | ||
834 | |||
835 | usb_hcd_poll_rh_status (dummy_to_hcd (dum)); | ||
760 | return 0; | 836 | return 0; |
761 | } | 837 | } |
762 | EXPORT_SYMBOL (usb_gadget_register_driver); | 838 | EXPORT_SYMBOL (usb_gadget_register_driver); |
763 | 839 | ||
764 | /* caller must hold lock */ | ||
765 | static void | ||
766 | stop_activity (struct dummy *dum, struct usb_gadget_driver *driver) | ||
767 | { | ||
768 | struct dummy_ep *ep; | ||
769 | |||
770 | /* prevent any more requests */ | ||
771 | dum->address = 0; | ||
772 | |||
773 | /* The timer is left running so that outstanding URBs can fail */ | ||
774 | |||
775 | /* nuke any pending requests first, so driver i/o is quiesced */ | ||
776 | list_for_each_entry (ep, &dum->gadget.ep_list, ep.ep_list) | ||
777 | nuke (dum, ep); | ||
778 | |||
779 | /* driver now does any non-usb quiescing necessary */ | ||
780 | if (driver) { | ||
781 | spin_unlock (&dum->lock); | ||
782 | driver->disconnect (&dum->gadget); | ||
783 | spin_lock (&dum->lock); | ||
784 | } | ||
785 | } | ||
786 | |||
787 | int | 840 | int |
788 | usb_gadget_unregister_driver (struct usb_gadget_driver *driver) | 841 | usb_gadget_unregister_driver (struct usb_gadget_driver *driver) |
789 | { | 842 | { |
@@ -795,35 +848,138 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver) | |||
795 | if (!driver || driver != dum->driver) | 848 | if (!driver || driver != dum->driver) |
796 | return -EINVAL; | 849 | return -EINVAL; |
797 | 850 | ||
798 | dev_dbg (dummy_dev(dum), "unregister gadget driver '%s'\n", | 851 | dev_dbg (udc_dev(dum), "unregister gadget driver '%s'\n", |
799 | driver->driver.name); | 852 | driver->driver.name); |
800 | 853 | ||
801 | spin_lock_irqsave (&dum->lock, flags); | 854 | spin_lock_irqsave (&dum->lock, flags); |
802 | stop_activity (dum, driver); | 855 | dum->pullup = 0; |
803 | dum->port_status &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE | | 856 | set_link_state (dum); |
804 | USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED); | ||
805 | dum->port_status |= (1 << USB_PORT_FEAT_C_CONNECTION); | ||
806 | spin_unlock_irqrestore (&dum->lock, flags); | 857 | spin_unlock_irqrestore (&dum->lock, flags); |
807 | 858 | ||
808 | driver->unbind (&dum->gadget); | 859 | driver->unbind (&dum->gadget); |
809 | dum->driver = NULL; | 860 | dum->driver = NULL; |
810 | 861 | ||
811 | device_release_driver (&dum->gadget.dev); | 862 | device_release_driver (&dum->gadget.dev); |
812 | |||
813 | driver_unregister (&driver->driver); | 863 | driver_unregister (&driver->driver); |
814 | 864 | ||
865 | spin_lock_irqsave (&dum->lock, flags); | ||
866 | dum->pullup = 0; | ||
867 | set_link_state (dum); | ||
868 | spin_unlock_irqrestore (&dum->lock, flags); | ||
869 | |||
870 | usb_hcd_poll_rh_status (dummy_to_hcd (dum)); | ||
815 | return 0; | 871 | return 0; |
816 | } | 872 | } |
817 | EXPORT_SYMBOL (usb_gadget_unregister_driver); | 873 | EXPORT_SYMBOL (usb_gadget_unregister_driver); |
818 | 874 | ||
819 | #undef is_enabled | 875 | #undef is_enabled |
820 | 876 | ||
877 | /* just declare this in any driver that really need it */ | ||
878 | extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode); | ||
879 | |||
821 | int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode) | 880 | int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode) |
822 | { | 881 | { |
823 | return -ENOSYS; | 882 | return -ENOSYS; |
824 | } | 883 | } |
825 | EXPORT_SYMBOL (net2280_set_fifo_mode); | 884 | EXPORT_SYMBOL (net2280_set_fifo_mode); |
826 | 885 | ||
886 | |||
887 | /* The gadget structure is stored inside the hcd structure and will be | ||
888 | * released along with it. */ | ||
889 | static void | ||
890 | dummy_gadget_release (struct device *dev) | ||
891 | { | ||
892 | #if 0 /* usb_bus_put isn't EXPORTed! */ | ||
893 | struct dummy *dum = gadget_dev_to_dummy (dev); | ||
894 | |||
895 | usb_bus_put (&dummy_to_hcd (dum)->self); | ||
896 | #endif | ||
897 | } | ||
898 | |||
899 | static int dummy_udc_probe (struct device *dev) | ||
900 | { | ||
901 | struct dummy *dum = the_controller; | ||
902 | int rc; | ||
903 | |||
904 | dum->gadget.name = gadget_name; | ||
905 | dum->gadget.ops = &dummy_ops; | ||
906 | dum->gadget.is_dualspeed = 1; | ||
907 | |||
908 | /* maybe claim OTG support, though we won't complete HNP */ | ||
909 | dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0); | ||
910 | |||
911 | strcpy (dum->gadget.dev.bus_id, "gadget"); | ||
912 | dum->gadget.dev.parent = dev; | ||
913 | dum->gadget.dev.release = dummy_gadget_release; | ||
914 | rc = device_register (&dum->gadget.dev); | ||
915 | if (rc < 0) | ||
916 | return rc; | ||
917 | |||
918 | #if 0 /* usb_bus_get isn't EXPORTed! */ | ||
919 | usb_bus_get (&dummy_to_hcd (dum)->self); | ||
920 | #endif | ||
921 | |||
922 | dev_set_drvdata (dev, dum); | ||
923 | device_create_file (&dum->gadget.dev, &dev_attr_function); | ||
924 | return rc; | ||
925 | } | ||
926 | |||
927 | static int dummy_udc_remove (struct device *dev) | ||
928 | { | ||
929 | struct dummy *dum = dev_get_drvdata (dev); | ||
930 | |||
931 | dev_set_drvdata (dev, NULL); | ||
932 | device_remove_file (&dum->gadget.dev, &dev_attr_function); | ||
933 | device_unregister (&dum->gadget.dev); | ||
934 | return 0; | ||
935 | } | ||
936 | |||
937 | static int dummy_udc_suspend (struct device *dev, pm_message_t state, | ||
938 | u32 level) | ||
939 | { | ||
940 | struct dummy *dum = dev_get_drvdata(dev); | ||
941 | |||
942 | if (level != SUSPEND_DISABLE) | ||
943 | return 0; | ||
944 | |||
945 | dev_dbg (dev, "%s\n", __FUNCTION__); | ||
946 | spin_lock_irq (&dum->lock); | ||
947 | dum->udc_suspended = 1; | ||
948 | set_link_state (dum); | ||
949 | spin_unlock_irq (&dum->lock); | ||
950 | |||
951 | dev->power.power_state = state; | ||
952 | usb_hcd_poll_rh_status (dummy_to_hcd (dum)); | ||
953 | return 0; | ||
954 | } | ||
955 | |||
956 | static int dummy_udc_resume (struct device *dev, u32 level) | ||
957 | { | ||
958 | struct dummy *dum = dev_get_drvdata(dev); | ||
959 | |||
960 | if (level != RESUME_ENABLE) | ||
961 | return 0; | ||
962 | |||
963 | dev_dbg (dev, "%s\n", __FUNCTION__); | ||
964 | spin_lock_irq (&dum->lock); | ||
965 | dum->udc_suspended = 0; | ||
966 | set_link_state (dum); | ||
967 | spin_unlock_irq (&dum->lock); | ||
968 | |||
969 | dev->power.power_state = PMSG_ON; | ||
970 | usb_hcd_poll_rh_status (dummy_to_hcd (dum)); | ||
971 | return 0; | ||
972 | } | ||
973 | |||
974 | static struct device_driver dummy_udc_driver = { | ||
975 | .name = (char *) gadget_name, | ||
976 | .bus = &platform_bus_type, | ||
977 | .probe = dummy_udc_probe, | ||
978 | .remove = dummy_udc_remove, | ||
979 | .suspend = dummy_udc_suspend, | ||
980 | .resume = dummy_udc_resume, | ||
981 | }; | ||
982 | |||
827 | /*-------------------------------------------------------------------------*/ | 983 | /*-------------------------------------------------------------------------*/ |
828 | 984 | ||
829 | /* MASTER/HOST SIDE DRIVER | 985 | /* MASTER/HOST SIDE DRIVER |
@@ -880,7 +1036,16 @@ static int dummy_urb_enqueue ( | |||
880 | 1036 | ||
881 | static int dummy_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) | 1037 | static int dummy_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) |
882 | { | 1038 | { |
883 | /* giveback happens automatically in timer callback */ | 1039 | struct dummy *dum; |
1040 | unsigned long flags; | ||
1041 | |||
1042 | /* giveback happens automatically in timer callback, | ||
1043 | * so make sure the callback happens */ | ||
1044 | dum = hcd_to_dummy (hcd); | ||
1045 | spin_lock_irqsave (&dum->lock, flags); | ||
1046 | if (dum->rh_state != DUMMY_RH_RUNNING && !list_empty(&dum->urbp_list)) | ||
1047 | mod_timer (&dum->timer, jiffies); | ||
1048 | spin_unlock_irqrestore (&dum->lock, flags); | ||
884 | return 0; | 1049 | return 0; |
885 | } | 1050 | } |
886 | 1051 | ||
@@ -1025,7 +1190,6 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep) | |||
1025 | 1190 | ||
1026 | /* high bandwidth mode */ | 1191 | /* high bandwidth mode */ |
1027 | tmp = le16_to_cpu(ep->desc->wMaxPacketSize); | 1192 | tmp = le16_to_cpu(ep->desc->wMaxPacketSize); |
1028 | tmp = le16_to_cpu (tmp); | ||
1029 | tmp = (tmp >> 11) & 0x03; | 1193 | tmp = (tmp >> 11) & 0x03; |
1030 | tmp *= 8 /* applies to entire frame */; | 1194 | tmp *= 8 /* applies to entire frame */; |
1031 | limit += limit * tmp; | 1195 | limit += limit * tmp; |
@@ -1123,7 +1287,8 @@ restart: | |||
1123 | if (urb->status != -EINPROGRESS) { | 1287 | if (urb->status != -EINPROGRESS) { |
1124 | /* likely it was just unlinked */ | 1288 | /* likely it was just unlinked */ |
1125 | goto return_urb; | 1289 | goto return_urb; |
1126 | } | 1290 | } else if (dum->rh_state != DUMMY_RH_RUNNING) |
1291 | continue; | ||
1127 | type = usb_pipetype (urb->pipe); | 1292 | type = usb_pipetype (urb->pipe); |
1128 | 1293 | ||
1129 | /* used up this frame's non-periodic bandwidth? | 1294 | /* used up this frame's non-periodic bandwidth? |
@@ -1168,12 +1333,14 @@ restart: | |||
1168 | struct usb_ctrlrequest setup; | 1333 | struct usb_ctrlrequest setup; |
1169 | int value = 1; | 1334 | int value = 1; |
1170 | struct dummy_ep *ep2; | 1335 | struct dummy_ep *ep2; |
1336 | unsigned w_index; | ||
1337 | unsigned w_value; | ||
1171 | 1338 | ||
1172 | setup = *(struct usb_ctrlrequest*) urb->setup_packet; | 1339 | setup = *(struct usb_ctrlrequest*) urb->setup_packet; |
1173 | le16_to_cpus (&setup.wIndex); | 1340 | w_index = le16_to_cpu(setup.wIndex); |
1174 | le16_to_cpus (&setup.wValue); | 1341 | w_value = le16_to_cpu(setup.wValue); |
1175 | le16_to_cpus (&setup.wLength); | 1342 | if (le16_to_cpu(setup.wLength) != |
1176 | if (setup.wLength != urb->transfer_buffer_length) { | 1343 | urb->transfer_buffer_length) { |
1177 | maybe_set_status (urb, -EOVERFLOW); | 1344 | maybe_set_status (urb, -EOVERFLOW); |
1178 | goto return_urb; | 1345 | goto return_urb; |
1179 | } | 1346 | } |
@@ -1182,7 +1349,7 @@ restart: | |||
1182 | list_for_each_entry (req, &ep->queue, queue) { | 1349 | list_for_each_entry (req, &ep->queue, queue) { |
1183 | list_del_init (&req->queue); | 1350 | list_del_init (&req->queue); |
1184 | req->req.status = -EOVERFLOW; | 1351 | req->req.status = -EOVERFLOW; |
1185 | dev_dbg (dummy_dev(dum), "stale req = %p\n", | 1352 | dev_dbg (udc_dev(dum), "stale req = %p\n", |
1186 | req); | 1353 | req); |
1187 | 1354 | ||
1188 | spin_unlock (&dum->lock); | 1355 | spin_unlock (&dum->lock); |
@@ -1203,31 +1370,40 @@ restart: | |||
1203 | case USB_REQ_SET_ADDRESS: | 1370 | case USB_REQ_SET_ADDRESS: |
1204 | if (setup.bRequestType != Dev_Request) | 1371 | if (setup.bRequestType != Dev_Request) |
1205 | break; | 1372 | break; |
1206 | dum->address = setup.wValue; | 1373 | dum->address = w_value; |
1207 | maybe_set_status (urb, 0); | 1374 | maybe_set_status (urb, 0); |
1208 | dev_dbg (dummy_dev(dum), "set_address = %d\n", | 1375 | dev_dbg (udc_dev(dum), "set_address = %d\n", |
1209 | setup.wValue); | 1376 | w_value); |
1210 | value = 0; | 1377 | value = 0; |
1211 | break; | 1378 | break; |
1212 | case USB_REQ_SET_FEATURE: | 1379 | case USB_REQ_SET_FEATURE: |
1213 | if (setup.bRequestType == Dev_Request) { | 1380 | if (setup.bRequestType == Dev_Request) { |
1214 | value = 0; | 1381 | value = 0; |
1215 | switch (setup.wValue) { | 1382 | switch (w_value) { |
1216 | case USB_DEVICE_REMOTE_WAKEUP: | 1383 | case USB_DEVICE_REMOTE_WAKEUP: |
1217 | break; | 1384 | break; |
1385 | case USB_DEVICE_B_HNP_ENABLE: | ||
1386 | dum->gadget.b_hnp_enable = 1; | ||
1387 | break; | ||
1388 | case USB_DEVICE_A_HNP_SUPPORT: | ||
1389 | dum->gadget.a_hnp_support = 1; | ||
1390 | break; | ||
1391 | case USB_DEVICE_A_ALT_HNP_SUPPORT: | ||
1392 | dum->gadget.a_alt_hnp_support | ||
1393 | = 1; | ||
1394 | break; | ||
1218 | default: | 1395 | default: |
1219 | value = -EOPNOTSUPP; | 1396 | value = -EOPNOTSUPP; |
1220 | } | 1397 | } |
1221 | if (value == 0) { | 1398 | if (value == 0) { |
1222 | dum->devstatus |= | 1399 | dum->devstatus |= |
1223 | (1 << setup.wValue); | 1400 | (1 << w_value); |
1224 | maybe_set_status (urb, 0); | 1401 | maybe_set_status (urb, 0); |
1225 | } | 1402 | } |
1226 | 1403 | ||
1227 | } else if (setup.bRequestType == Ep_Request) { | 1404 | } else if (setup.bRequestType == Ep_Request) { |
1228 | // endpoint halt | 1405 | // endpoint halt |
1229 | ep2 = find_endpoint (dum, | 1406 | ep2 = find_endpoint (dum, w_index); |
1230 | setup.wIndex); | ||
1231 | if (!ep2) { | 1407 | if (!ep2) { |
1232 | value = -EOPNOTSUPP; | 1408 | value = -EOPNOTSUPP; |
1233 | break; | 1409 | break; |
@@ -1239,7 +1415,7 @@ restart: | |||
1239 | break; | 1415 | break; |
1240 | case USB_REQ_CLEAR_FEATURE: | 1416 | case USB_REQ_CLEAR_FEATURE: |
1241 | if (setup.bRequestType == Dev_Request) { | 1417 | if (setup.bRequestType == Dev_Request) { |
1242 | switch (setup.wValue) { | 1418 | switch (w_value) { |
1243 | case USB_DEVICE_REMOTE_WAKEUP: | 1419 | case USB_DEVICE_REMOTE_WAKEUP: |
1244 | dum->devstatus &= ~(1 << | 1420 | dum->devstatus &= ~(1 << |
1245 | USB_DEVICE_REMOTE_WAKEUP); | 1421 | USB_DEVICE_REMOTE_WAKEUP); |
@@ -1252,8 +1428,7 @@ restart: | |||
1252 | } | 1428 | } |
1253 | } else if (setup.bRequestType == Ep_Request) { | 1429 | } else if (setup.bRequestType == Ep_Request) { |
1254 | // endpoint halt | 1430 | // endpoint halt |
1255 | ep2 = find_endpoint (dum, | 1431 | ep2 = find_endpoint (dum, w_index); |
1256 | setup.wIndex); | ||
1257 | if (!ep2) { | 1432 | if (!ep2) { |
1258 | value = -EOPNOTSUPP; | 1433 | value = -EOPNOTSUPP; |
1259 | break; | 1434 | break; |
@@ -1279,7 +1454,7 @@ restart: | |||
1279 | if (urb->transfer_buffer_length > 0) { | 1454 | if (urb->transfer_buffer_length > 0) { |
1280 | if (setup.bRequestType == | 1455 | if (setup.bRequestType == |
1281 | Ep_InRequest) { | 1456 | Ep_InRequest) { |
1282 | ep2 = find_endpoint (dum, setup.wIndex); | 1457 | ep2 = find_endpoint (dum, w_index); |
1283 | if (!ep2) { | 1458 | if (!ep2) { |
1284 | value = -EOPNOTSUPP; | 1459 | value = -EOPNOTSUPP; |
1285 | break; | 1460 | break; |
@@ -1321,7 +1496,7 @@ restart: | |||
1321 | 1496 | ||
1322 | if (value < 0) { | 1497 | if (value < 0) { |
1323 | if (value != -EOPNOTSUPP) | 1498 | if (value != -EOPNOTSUPP) |
1324 | dev_dbg (dummy_dev(dum), | 1499 | dev_dbg (udc_dev(dum), |
1325 | "setup --> %d\n", | 1500 | "setup --> %d\n", |
1326 | value); | 1501 | value); |
1327 | maybe_set_status (urb, -EPIPE); | 1502 | maybe_set_status (urb, -EPIPE); |
@@ -1377,12 +1552,12 @@ return_urb: | |||
1377 | goto restart; | 1552 | goto restart; |
1378 | } | 1553 | } |
1379 | 1554 | ||
1380 | /* want a 1 msec delay here */ | 1555 | if (list_empty (&dum->urbp_list)) { |
1381 | if (!list_empty (&dum->urbp_list)) | ||
1382 | mod_timer (&dum->timer, jiffies + msecs_to_jiffies(1)); | ||
1383 | else { | ||
1384 | usb_put_dev (dum->udev); | 1556 | usb_put_dev (dum->udev); |
1385 | dum->udev = NULL; | 1557 | dum->udev = NULL; |
1558 | } else if (dum->rh_state == DUMMY_RH_RUNNING) { | ||
1559 | /* want a 1 msec delay here */ | ||
1560 | mod_timer (&dum->timer, jiffies + msecs_to_jiffies(1)); | ||
1386 | } | 1561 | } |
1387 | 1562 | ||
1388 | spin_unlock_irqrestore (&dum->lock, flags); | 1563 | spin_unlock_irqrestore (&dum->lock, flags); |
@@ -1391,29 +1566,39 @@ return_urb: | |||
1391 | /*-------------------------------------------------------------------------*/ | 1566 | /*-------------------------------------------------------------------------*/ |
1392 | 1567 | ||
1393 | #define PORT_C_MASK \ | 1568 | #define PORT_C_MASK \ |
1394 | ((1 << USB_PORT_FEAT_C_CONNECTION) \ | 1569 | ((USB_PORT_STAT_C_CONNECTION \ |
1395 | | (1 << USB_PORT_FEAT_C_ENABLE) \ | 1570 | | USB_PORT_STAT_C_ENABLE \ |
1396 | | (1 << USB_PORT_FEAT_C_SUSPEND) \ | 1571 | | USB_PORT_STAT_C_SUSPEND \ |
1397 | | (1 << USB_PORT_FEAT_C_OVER_CURRENT) \ | 1572 | | USB_PORT_STAT_C_OVERCURRENT \ |
1398 | | (1 << USB_PORT_FEAT_C_RESET)) | 1573 | | USB_PORT_STAT_C_RESET) << 16) |
1399 | 1574 | ||
1400 | static int dummy_hub_status (struct usb_hcd *hcd, char *buf) | 1575 | static int dummy_hub_status (struct usb_hcd *hcd, char *buf) |
1401 | { | 1576 | { |
1402 | struct dummy *dum; | 1577 | struct dummy *dum; |
1403 | unsigned long flags; | 1578 | unsigned long flags; |
1404 | int retval; | 1579 | int retval = 0; |
1405 | 1580 | ||
1406 | dum = hcd_to_dummy (hcd); | 1581 | dum = hcd_to_dummy (hcd); |
1407 | 1582 | ||
1408 | spin_lock_irqsave (&dum->lock, flags); | 1583 | spin_lock_irqsave (&dum->lock, flags); |
1409 | if (!(dum->port_status & PORT_C_MASK)) | 1584 | if (hcd->state != HC_STATE_RUNNING) |
1410 | retval = 0; | 1585 | goto done; |
1411 | else { | 1586 | |
1587 | if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) { | ||
1588 | dum->port_status |= (USB_PORT_STAT_C_SUSPEND << 16); | ||
1589 | dum->port_status &= ~USB_PORT_STAT_SUSPEND; | ||
1590 | set_link_state (dum); | ||
1591 | } | ||
1592 | |||
1593 | if ((dum->port_status & PORT_C_MASK) != 0) { | ||
1412 | *buf = (1 << 1); | 1594 | *buf = (1 << 1); |
1413 | dev_dbg (dummy_dev(dum), "port status 0x%08x has changes\n", | 1595 | dev_dbg (dummy_dev(dum), "port status 0x%08x has changes\n", |
1414 | dum->port_status); | 1596 | dum->port_status); |
1415 | retval = 1; | 1597 | retval = 1; |
1598 | if (dum->rh_state == DUMMY_RH_SUSPENDED) | ||
1599 | usb_hcd_resume_root_hub (hcd); | ||
1416 | } | 1600 | } |
1601 | done: | ||
1417 | spin_unlock_irqrestore (&dum->lock, flags); | 1602 | spin_unlock_irqrestore (&dum->lock, flags); |
1418 | return retval; | 1603 | return retval; |
1419 | } | 1604 | } |
@@ -1424,7 +1609,8 @@ hub_descriptor (struct usb_hub_descriptor *desc) | |||
1424 | memset (desc, 0, sizeof *desc); | 1609 | memset (desc, 0, sizeof *desc); |
1425 | desc->bDescriptorType = 0x29; | 1610 | desc->bDescriptorType = 0x29; |
1426 | desc->bDescLength = 9; | 1611 | desc->bDescLength = 9; |
1427 | desc->wHubCharacteristics = __constant_cpu_to_le16 (0x0001); | 1612 | desc->wHubCharacteristics = (__force __u16) |
1613 | (__constant_cpu_to_le16 (0x0001)); | ||
1428 | desc->bNbrPorts = 1; | 1614 | desc->bNbrPorts = 1; |
1429 | desc->bitmap [0] = 0xff; | 1615 | desc->bitmap [0] = 0xff; |
1430 | desc->bitmap [1] = 0xff; | 1616 | desc->bitmap [1] = 0xff; |
@@ -1442,6 +1628,9 @@ static int dummy_hub_control ( | |||
1442 | int retval = 0; | 1628 | int retval = 0; |
1443 | unsigned long flags; | 1629 | unsigned long flags; |
1444 | 1630 | ||
1631 | if (hcd->state != HC_STATE_RUNNING) | ||
1632 | return -ETIMEDOUT; | ||
1633 | |||
1445 | dum = hcd_to_dummy (hcd); | 1634 | dum = hcd_to_dummy (hcd); |
1446 | spin_lock_irqsave (&dum->lock, flags); | 1635 | spin_lock_irqsave (&dum->lock, flags); |
1447 | switch (typeReq) { | 1636 | switch (typeReq) { |
@@ -1450,27 +1639,27 @@ static int dummy_hub_control ( | |||
1450 | case ClearPortFeature: | 1639 | case ClearPortFeature: |
1451 | switch (wValue) { | 1640 | switch (wValue) { |
1452 | case USB_PORT_FEAT_SUSPEND: | 1641 | case USB_PORT_FEAT_SUSPEND: |
1453 | if (dum->port_status & (1 << USB_PORT_FEAT_SUSPEND)) { | 1642 | if (dum->port_status & USB_PORT_STAT_SUSPEND) { |
1454 | /* 20msec resume signaling */ | 1643 | /* 20msec resume signaling */ |
1455 | dum->resuming = 1; | 1644 | dum->resuming = 1; |
1456 | dum->re_timeout = jiffies + | 1645 | dum->re_timeout = jiffies + |
1457 | msecs_to_jiffies(20); | 1646 | msecs_to_jiffies(20); |
1458 | } | 1647 | } |
1459 | break; | 1648 | break; |
1460 | case USB_PORT_FEAT_POWER: | 1649 | case USB_PORT_FEAT_POWER: |
1461 | dum->port_status = 0; | 1650 | if (dum->port_status & USB_PORT_STAT_POWER) |
1462 | dum->resuming = 0; | 1651 | dev_dbg (dummy_dev(dum), "power-off\n"); |
1463 | stop_activity(dum, dum->driver); | 1652 | /* FALLS THROUGH */ |
1464 | break; | ||
1465 | default: | 1653 | default: |
1466 | dum->port_status &= ~(1 << wValue); | 1654 | dum->port_status &= ~(1 << wValue); |
1655 | set_link_state (dum); | ||
1467 | } | 1656 | } |
1468 | break; | 1657 | break; |
1469 | case GetHubDescriptor: | 1658 | case GetHubDescriptor: |
1470 | hub_descriptor ((struct usb_hub_descriptor *) buf); | 1659 | hub_descriptor ((struct usb_hub_descriptor *) buf); |
1471 | break; | 1660 | break; |
1472 | case GetHubStatus: | 1661 | case GetHubStatus: |
1473 | *(u32 *) buf = __constant_cpu_to_le32 (0); | 1662 | *(__le32 *) buf = __constant_cpu_to_le32 (0); |
1474 | break; | 1663 | break; |
1475 | case GetPortStatus: | 1664 | case GetPortStatus: |
1476 | if (wIndex != 1) | 1665 | if (wIndex != 1) |
@@ -1479,23 +1668,16 @@ static int dummy_hub_control ( | |||
1479 | /* whoever resets or resumes must GetPortStatus to | 1668 | /* whoever resets or resumes must GetPortStatus to |
1480 | * complete it!! | 1669 | * complete it!! |
1481 | */ | 1670 | */ |
1482 | if (dum->resuming && time_after (jiffies, dum->re_timeout)) { | 1671 | if (dum->resuming && |
1483 | dum->port_status |= (1 << USB_PORT_FEAT_C_SUSPEND); | 1672 | time_after_eq (jiffies, dum->re_timeout)) { |
1484 | dum->port_status &= ~(1 << USB_PORT_FEAT_SUSPEND); | 1673 | dum->port_status |= (USB_PORT_STAT_C_SUSPEND << 16); |
1485 | dum->resuming = 0; | 1674 | dum->port_status &= ~USB_PORT_STAT_SUSPEND; |
1486 | dum->re_timeout = 0; | ||
1487 | if (dum->driver && dum->driver->resume) { | ||
1488 | spin_unlock (&dum->lock); | ||
1489 | dum->driver->resume (&dum->gadget); | ||
1490 | spin_lock (&dum->lock); | ||
1491 | } | ||
1492 | } | 1675 | } |
1493 | if ((dum->port_status & (1 << USB_PORT_FEAT_RESET)) != 0 | 1676 | if ((dum->port_status & USB_PORT_STAT_RESET) != 0 && |
1494 | && time_after (jiffies, dum->re_timeout)) { | 1677 | time_after_eq (jiffies, dum->re_timeout)) { |
1495 | dum->port_status |= (1 << USB_PORT_FEAT_C_RESET); | 1678 | dum->port_status |= (USB_PORT_STAT_C_RESET << 16); |
1496 | dum->port_status &= ~(1 << USB_PORT_FEAT_RESET); | 1679 | dum->port_status &= ~USB_PORT_STAT_RESET; |
1497 | dum->re_timeout = 0; | 1680 | if (dum->pullup) { |
1498 | if (dum->driver) { | ||
1499 | dum->port_status |= USB_PORT_STAT_ENABLE; | 1681 | dum->port_status |= USB_PORT_STAT_ENABLE; |
1500 | /* give it the best speed we agree on */ | 1682 | /* give it the best speed we agree on */ |
1501 | dum->gadget.speed = dum->driver->speed; | 1683 | dum->gadget.speed = dum->driver->speed; |
@@ -1516,8 +1698,9 @@ static int dummy_hub_control ( | |||
1516 | } | 1698 | } |
1517 | } | 1699 | } |
1518 | } | 1700 | } |
1519 | ((u16 *) buf)[0] = cpu_to_le16 (dum->port_status); | 1701 | set_link_state (dum); |
1520 | ((u16 *) buf)[1] = cpu_to_le16 (dum->port_status >> 16); | 1702 | ((__le16 *) buf)[0] = cpu_to_le16 (dum->port_status); |
1703 | ((__le16 *) buf)[1] = cpu_to_le16 (dum->port_status >> 16); | ||
1521 | break; | 1704 | break; |
1522 | case SetHubFeature: | 1705 | case SetHubFeature: |
1523 | retval = -EPIPE; | 1706 | retval = -EPIPE; |
@@ -1525,36 +1708,37 @@ static int dummy_hub_control ( | |||
1525 | case SetPortFeature: | 1708 | case SetPortFeature: |
1526 | switch (wValue) { | 1709 | switch (wValue) { |
1527 | case USB_PORT_FEAT_SUSPEND: | 1710 | case USB_PORT_FEAT_SUSPEND: |
1528 | if ((dum->port_status & (1 << USB_PORT_FEAT_SUSPEND)) | 1711 | if (dum->active) { |
1529 | == 0) { | 1712 | dum->port_status |= USB_PORT_STAT_SUSPEND; |
1530 | dum->port_status |= | 1713 | |
1531 | (1 << USB_PORT_FEAT_SUSPEND); | 1714 | /* HNP would happen here; for now we |
1532 | if (dum->driver && dum->driver->suspend) { | 1715 | * assume b_bus_req is always true. |
1533 | spin_unlock (&dum->lock); | 1716 | */ |
1534 | dum->driver->suspend (&dum->gadget); | 1717 | set_link_state (dum); |
1535 | spin_lock (&dum->lock); | 1718 | if (((1 << USB_DEVICE_B_HNP_ENABLE) |
1536 | } | 1719 | & dum->devstatus) != 0) |
1720 | dev_dbg (dummy_dev(dum), | ||
1721 | "no HNP yet!\n"); | ||
1537 | } | 1722 | } |
1538 | break; | 1723 | break; |
1724 | case USB_PORT_FEAT_POWER: | ||
1725 | dum->port_status |= USB_PORT_STAT_POWER; | ||
1726 | set_link_state (dum); | ||
1727 | break; | ||
1539 | case USB_PORT_FEAT_RESET: | 1728 | case USB_PORT_FEAT_RESET: |
1540 | /* if it's already running, disconnect first */ | 1729 | /* if it's already enabled, disable */ |
1541 | if (dum->port_status & USB_PORT_STAT_ENABLE) { | 1730 | dum->port_status &= ~(USB_PORT_STAT_ENABLE |
1542 | dum->port_status &= ~(USB_PORT_STAT_ENABLE | 1731 | | USB_PORT_STAT_LOW_SPEED |
1543 | | USB_PORT_STAT_LOW_SPEED | 1732 | | USB_PORT_STAT_HIGH_SPEED); |
1544 | | USB_PORT_STAT_HIGH_SPEED); | 1733 | dum->devstatus = 0; |
1545 | if (dum->driver) { | ||
1546 | dev_dbg (dummy_dev(dum), | ||
1547 | "disconnect\n"); | ||
1548 | stop_activity (dum, dum->driver); | ||
1549 | } | ||
1550 | |||
1551 | /* FIXME test that code path! */ | ||
1552 | } | ||
1553 | /* 50msec reset signaling */ | 1734 | /* 50msec reset signaling */ |
1554 | dum->re_timeout = jiffies + msecs_to_jiffies(50); | 1735 | dum->re_timeout = jiffies + msecs_to_jiffies(50); |
1555 | /* FALLTHROUGH */ | 1736 | /* FALLS THROUGH */ |
1556 | default: | 1737 | default: |
1557 | dum->port_status |= (1 << wValue); | 1738 | if ((dum->port_status & USB_PORT_STAT_POWER) != 0) { |
1739 | dum->port_status |= (1 << wValue); | ||
1740 | set_link_state (dum); | ||
1741 | } | ||
1558 | } | 1742 | } |
1559 | break; | 1743 | break; |
1560 | 1744 | ||
@@ -1567,9 +1751,35 @@ static int dummy_hub_control ( | |||
1567 | retval = -EPIPE; | 1751 | retval = -EPIPE; |
1568 | } | 1752 | } |
1569 | spin_unlock_irqrestore (&dum->lock, flags); | 1753 | spin_unlock_irqrestore (&dum->lock, flags); |
1754 | |||
1755 | if ((dum->port_status & PORT_C_MASK) != 0) | ||
1756 | usb_hcd_poll_rh_status (hcd); | ||
1570 | return retval; | 1757 | return retval; |
1571 | } | 1758 | } |
1572 | 1759 | ||
1760 | static int dummy_hub_suspend (struct usb_hcd *hcd) | ||
1761 | { | ||
1762 | struct dummy *dum = hcd_to_dummy (hcd); | ||
1763 | |||
1764 | spin_lock_irq (&dum->lock); | ||
1765 | dum->rh_state = DUMMY_RH_SUSPENDED; | ||
1766 | set_link_state (dum); | ||
1767 | spin_unlock_irq (&dum->lock); | ||
1768 | return 0; | ||
1769 | } | ||
1770 | |||
1771 | static int dummy_hub_resume (struct usb_hcd *hcd) | ||
1772 | { | ||
1773 | struct dummy *dum = hcd_to_dummy (hcd); | ||
1774 | |||
1775 | spin_lock_irq (&dum->lock); | ||
1776 | dum->rh_state = DUMMY_RH_RUNNING; | ||
1777 | set_link_state (dum); | ||
1778 | if (!list_empty(&dum->urbp_list)) | ||
1779 | mod_timer (&dum->timer, jiffies); | ||
1780 | spin_unlock_irq (&dum->lock); | ||
1781 | return 0; | ||
1782 | } | ||
1573 | 1783 | ||
1574 | /*-------------------------------------------------------------------------*/ | 1784 | /*-------------------------------------------------------------------------*/ |
1575 | 1785 | ||
@@ -1625,8 +1835,6 @@ static DEVICE_ATTR (urbs, S_IRUGO, show_urbs, NULL); | |||
1625 | static int dummy_start (struct usb_hcd *hcd) | 1835 | static int dummy_start (struct usb_hcd *hcd) |
1626 | { | 1836 | { |
1627 | struct dummy *dum; | 1837 | struct dummy *dum; |
1628 | struct usb_device *root; | ||
1629 | int retval; | ||
1630 | 1838 | ||
1631 | dum = hcd_to_dummy (hcd); | 1839 | dum = hcd_to_dummy (hcd); |
1632 | 1840 | ||
@@ -1639,38 +1847,22 @@ static int dummy_start (struct usb_hcd *hcd) | |||
1639 | init_timer (&dum->timer); | 1847 | init_timer (&dum->timer); |
1640 | dum->timer.function = dummy_timer; | 1848 | dum->timer.function = dummy_timer; |
1641 | dum->timer.data = (unsigned long) dum; | 1849 | dum->timer.data = (unsigned long) dum; |
1850 | dum->rh_state = DUMMY_RH_RUNNING; | ||
1642 | 1851 | ||
1643 | INIT_LIST_HEAD (&dum->urbp_list); | 1852 | INIT_LIST_HEAD (&dum->urbp_list); |
1644 | 1853 | ||
1645 | root = usb_alloc_dev (NULL, &hcd->self, 0); | ||
1646 | if (!root) | ||
1647 | return -ENOMEM; | ||
1648 | |||
1649 | /* root hub enters addressed state... */ | ||
1650 | hcd->state = HC_STATE_RUNNING; | ||
1651 | root->speed = USB_SPEED_HIGH; | ||
1652 | |||
1653 | /* ...then configured, so khubd sees us. */ | ||
1654 | if ((retval = usb_hcd_register_root_hub (root, hcd)) != 0) { | ||
1655 | goto err1; | ||
1656 | } | ||
1657 | |||
1658 | /* only show a low-power port: just 8mA */ | 1854 | /* only show a low-power port: just 8mA */ |
1659 | hub_set_power_budget (root, 8); | 1855 | hcd->power_budget = 8; |
1856 | hcd->state = HC_STATE_RUNNING; | ||
1857 | hcd->uses_new_polling = 1; | ||
1660 | 1858 | ||
1661 | if ((retval = dummy_register_udc (dum)) != 0) | 1859 | #ifdef CONFIG_USB_OTG |
1662 | goto err2; | 1860 | hcd->self.otg_port = 1; |
1861 | #endif | ||
1663 | 1862 | ||
1664 | /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */ | 1863 | /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */ |
1665 | device_create_file (dummy_dev(dum), &dev_attr_urbs); | 1864 | device_create_file (dummy_dev(dum), &dev_attr_urbs); |
1666 | return 0; | 1865 | return 0; |
1667 | |||
1668 | err2: | ||
1669 | usb_disconnect (&hcd->self.root_hub); | ||
1670 | err1: | ||
1671 | usb_put_dev (root); | ||
1672 | hcd->state = HC_STATE_QUIESCING; | ||
1673 | return retval; | ||
1674 | } | 1866 | } |
1675 | 1867 | ||
1676 | static void dummy_stop (struct usb_hcd *hcd) | 1868 | static void dummy_stop (struct usb_hcd *hcd) |
@@ -1680,10 +1872,7 @@ static void dummy_stop (struct usb_hcd *hcd) | |||
1680 | dum = hcd_to_dummy (hcd); | 1872 | dum = hcd_to_dummy (hcd); |
1681 | 1873 | ||
1682 | device_remove_file (dummy_dev(dum), &dev_attr_urbs); | 1874 | device_remove_file (dummy_dev(dum), &dev_attr_urbs); |
1683 | |||
1684 | usb_gadget_unregister_driver (dum->driver); | 1875 | usb_gadget_unregister_driver (dum->driver); |
1685 | dummy_unregister_udc (dum); | ||
1686 | |||
1687 | dev_info (dummy_dev(dum), "stopped\n"); | 1876 | dev_info (dummy_dev(dum), "stopped\n"); |
1688 | } | 1877 | } |
1689 | 1878 | ||
@@ -1711,9 +1900,11 @@ static const struct hc_driver dummy_hcd = { | |||
1711 | 1900 | ||
1712 | .hub_status_data = dummy_hub_status, | 1901 | .hub_status_data = dummy_hub_status, |
1713 | .hub_control = dummy_hub_control, | 1902 | .hub_control = dummy_hub_control, |
1903 | .hub_suspend = dummy_hub_suspend, | ||
1904 | .hub_resume = dummy_hub_resume, | ||
1714 | }; | 1905 | }; |
1715 | 1906 | ||
1716 | static int dummy_probe (struct device *dev) | 1907 | static int dummy_hcd_probe (struct device *dev) |
1717 | { | 1908 | { |
1718 | struct usb_hcd *hcd; | 1909 | struct usb_hcd *hcd; |
1719 | int retval; | 1910 | int retval; |
@@ -1733,7 +1924,7 @@ static int dummy_probe (struct device *dev) | |||
1733 | return retval; | 1924 | return retval; |
1734 | } | 1925 | } |
1735 | 1926 | ||
1736 | static void dummy_remove (struct device *dev) | 1927 | static int dummy_hcd_remove (struct device *dev) |
1737 | { | 1928 | { |
1738 | struct usb_hcd *hcd; | 1929 | struct usb_hcd *hcd; |
1739 | 1930 | ||
@@ -1741,53 +1932,127 @@ static void dummy_remove (struct device *dev) | |||
1741 | usb_remove_hcd (hcd); | 1932 | usb_remove_hcd (hcd); |
1742 | usb_put_hcd (hcd); | 1933 | usb_put_hcd (hcd); |
1743 | the_controller = NULL; | 1934 | the_controller = NULL; |
1935 | return 0; | ||
1744 | } | 1936 | } |
1745 | 1937 | ||
1746 | /*-------------------------------------------------------------------------*/ | 1938 | static int dummy_hcd_suspend (struct device *dev, pm_message_t state, |
1747 | 1939 | u32 level) | |
1748 | static int dummy_pdev_detect (void) | ||
1749 | { | 1940 | { |
1750 | int retval; | 1941 | struct usb_hcd *hcd; |
1751 | 1942 | ||
1752 | retval = driver_register (&dummy_driver); | 1943 | if (level != SUSPEND_DISABLE) |
1753 | if (retval < 0) | 1944 | return 0; |
1754 | return retval; | 1945 | |
1946 | dev_dbg (dev, "%s\n", __FUNCTION__); | ||
1947 | hcd = dev_get_drvdata (dev); | ||
1755 | 1948 | ||
1756 | the_pdev.name = "hc"; | 1949 | #ifndef CONFIG_USB_SUSPEND |
1757 | the_pdev.dev.driver = &dummy_driver; | 1950 | /* Otherwise this would never happen */ |
1758 | the_pdev.dev.release = dummy_pdev_release; | 1951 | usb_lock_device (hcd->self.root_hub); |
1952 | dummy_hub_suspend (hcd); | ||
1953 | usb_unlock_device (hcd->self.root_hub); | ||
1954 | #endif | ||
1759 | 1955 | ||
1760 | retval = platform_device_register (&the_pdev); | 1956 | hcd->state = HC_STATE_SUSPENDED; |
1761 | if (retval < 0) | 1957 | return 0; |
1762 | driver_unregister (&dummy_driver); | ||
1763 | return retval; | ||
1764 | } | 1958 | } |
1765 | 1959 | ||
1766 | static void dummy_pdev_remove (void) | 1960 | static int dummy_hcd_resume (struct device *dev, u32 level) |
1767 | { | 1961 | { |
1768 | platform_device_unregister (&the_pdev); | 1962 | struct usb_hcd *hcd; |
1769 | driver_unregister (&dummy_driver); | 1963 | |
1964 | if (level != RESUME_ENABLE) | ||
1965 | return 0; | ||
1966 | |||
1967 | dev_dbg (dev, "%s\n", __FUNCTION__); | ||
1968 | hcd = dev_get_drvdata (dev); | ||
1969 | hcd->state = HC_STATE_RUNNING; | ||
1970 | |||
1971 | #ifndef CONFIG_USB_SUSPEND | ||
1972 | /* Otherwise this would never happen */ | ||
1973 | usb_lock_device (hcd->self.root_hub); | ||
1974 | dummy_hub_resume (hcd); | ||
1975 | usb_unlock_device (hcd->self.root_hub); | ||
1976 | #endif | ||
1977 | |||
1978 | usb_hcd_poll_rh_status (hcd); | ||
1979 | return 0; | ||
1770 | } | 1980 | } |
1771 | 1981 | ||
1982 | static struct device_driver dummy_hcd_driver = { | ||
1983 | .name = (char *) driver_name, | ||
1984 | .bus = &platform_bus_type, | ||
1985 | .probe = dummy_hcd_probe, | ||
1986 | .remove = dummy_hcd_remove, | ||
1987 | .suspend = dummy_hcd_suspend, | ||
1988 | .resume = dummy_hcd_resume, | ||
1989 | }; | ||
1990 | |||
1772 | /*-------------------------------------------------------------------------*/ | 1991 | /*-------------------------------------------------------------------------*/ |
1773 | 1992 | ||
1993 | /* These don't need to do anything because the pdev structures are | ||
1994 | * statically allocated. */ | ||
1995 | static void | ||
1996 | dummy_udc_release (struct device *dev) {} | ||
1997 | |||
1998 | static void | ||
1999 | dummy_hcd_release (struct device *dev) {} | ||
2000 | |||
2001 | static struct platform_device the_udc_pdev = { | ||
2002 | .name = (char *) gadget_name, | ||
2003 | .id = -1, | ||
2004 | .dev = { | ||
2005 | .release = dummy_udc_release, | ||
2006 | }, | ||
2007 | }; | ||
2008 | |||
2009 | static struct platform_device the_hcd_pdev = { | ||
2010 | .name = (char *) driver_name, | ||
2011 | .id = -1, | ||
2012 | .dev = { | ||
2013 | .release = dummy_hcd_release, | ||
2014 | }, | ||
2015 | }; | ||
2016 | |||
1774 | static int __init init (void) | 2017 | static int __init init (void) |
1775 | { | 2018 | { |
1776 | int retval; | 2019 | int retval; |
1777 | 2020 | ||
1778 | if (usb_disabled ()) | 2021 | if (usb_disabled ()) |
1779 | return -ENODEV; | 2022 | return -ENODEV; |
1780 | if ((retval = dummy_pdev_detect ()) != 0) | 2023 | |
2024 | retval = driver_register (&dummy_hcd_driver); | ||
2025 | if (retval < 0) | ||
1781 | return retval; | 2026 | return retval; |
1782 | if ((retval = dummy_probe (&the_pdev.dev)) != 0) | 2027 | |
1783 | dummy_pdev_remove (); | 2028 | retval = driver_register (&dummy_udc_driver); |
2029 | if (retval < 0) | ||
2030 | goto err_register_udc_driver; | ||
2031 | |||
2032 | retval = platform_device_register (&the_hcd_pdev); | ||
2033 | if (retval < 0) | ||
2034 | goto err_register_hcd; | ||
2035 | |||
2036 | retval = platform_device_register (&the_udc_pdev); | ||
2037 | if (retval < 0) | ||
2038 | goto err_register_udc; | ||
2039 | return retval; | ||
2040 | |||
2041 | err_register_udc: | ||
2042 | platform_device_unregister (&the_hcd_pdev); | ||
2043 | err_register_hcd: | ||
2044 | driver_unregister (&dummy_udc_driver); | ||
2045 | err_register_udc_driver: | ||
2046 | driver_unregister (&dummy_hcd_driver); | ||
1784 | return retval; | 2047 | return retval; |
1785 | } | 2048 | } |
1786 | module_init (init); | 2049 | module_init (init); |
1787 | 2050 | ||
1788 | static void __exit cleanup (void) | 2051 | static void __exit cleanup (void) |
1789 | { | 2052 | { |
1790 | dummy_remove (&the_pdev.dev); | 2053 | platform_device_unregister (&the_udc_pdev); |
1791 | dummy_pdev_remove (); | 2054 | platform_device_unregister (&the_hcd_pdev); |
2055 | driver_unregister (&dummy_udc_driver); | ||
2056 | driver_unregister (&dummy_hcd_driver); | ||
1792 | } | 2057 | } |
1793 | module_exit (cleanup); | 2058 | module_exit (cleanup); |
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 3f783cbdc7c3..5bb53ae88969 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c | |||
@@ -84,18 +84,19 @@ | |||
84 | */ | 84 | */ |
85 | 85 | ||
86 | #define DRIVER_DESC "Ethernet Gadget" | 86 | #define DRIVER_DESC "Ethernet Gadget" |
87 | #define DRIVER_VERSION "Equinox 2004" | 87 | #define DRIVER_VERSION "May Day 2005" |
88 | 88 | ||
89 | static const char shortname [] = "ether"; | 89 | static const char shortname [] = "ether"; |
90 | static const char driver_desc [] = DRIVER_DESC; | 90 | static const char driver_desc [] = DRIVER_DESC; |
91 | 91 | ||
92 | #define RX_EXTRA 20 /* guard against rx overflows */ | 92 | #define RX_EXTRA 20 /* guard against rx overflows */ |
93 | 93 | ||
94 | #ifdef CONFIG_USB_ETH_RNDIS | ||
95 | #include "rndis.h" | 94 | #include "rndis.h" |
96 | #else | 95 | |
97 | #define rndis_init() 0 | 96 | #ifndef CONFIG_USB_ETH_RNDIS |
98 | #define rndis_exit() do{}while(0) | 97 | #define rndis_uninit(x) do{}while(0) |
98 | #define rndis_deregister(c) do{}while(0) | ||
99 | #define rndis_exit() do{}while(0) | ||
99 | #endif | 100 | #endif |
100 | 101 | ||
101 | /* CDC and RNDIS support the same host-chosen outgoing packet filters. */ | 102 | /* CDC and RNDIS support the same host-chosen outgoing packet filters. */ |
@@ -140,9 +141,6 @@ struct eth_dev { | |||
140 | * It also ASSUMES a self-powered device, without remote wakeup, | 141 | * It also ASSUMES a self-powered device, without remote wakeup, |
141 | * although remote wakeup support would make sense. | 142 | * although remote wakeup support would make sense. |
142 | */ | 143 | */ |
143 | static const char *EP_IN_NAME; | ||
144 | static const char *EP_OUT_NAME; | ||
145 | static const char *EP_STATUS_NAME; | ||
146 | 144 | ||
147 | /*-------------------------------------------------------------------------*/ | 145 | /*-------------------------------------------------------------------------*/ |
148 | 146 | ||
@@ -312,6 +310,7 @@ static inline int rndis_active(struct eth_dev *dev) | |||
312 | #define FS_BPS (19 * 64 * 1 * 1000 * 8) | 310 | #define FS_BPS (19 * 64 * 1 * 1000 * 8) |
313 | 311 | ||
314 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 312 | #ifdef CONFIG_USB_GADGET_DUALSPEED |
313 | #define DEVSPEED USB_SPEED_HIGH | ||
315 | 314 | ||
316 | static unsigned qmult = 5; | 315 | static unsigned qmult = 5; |
317 | module_param (qmult, uint, S_IRUGO|S_IWUSR); | 316 | module_param (qmult, uint, S_IRUGO|S_IWUSR); |
@@ -330,6 +329,8 @@ static inline int BITRATE(struct usb_gadget *g) | |||
330 | } | 329 | } |
331 | 330 | ||
332 | #else /* full speed (low speed doesn't do bulk) */ | 331 | #else /* full speed (low speed doesn't do bulk) */ |
332 | #define DEVSPEED USB_SPEED_FULL | ||
333 | |||
333 | #define qlen(gadget) DEFAULT_QLEN | 334 | #define qlen(gadget) DEFAULT_QLEN |
334 | 335 | ||
335 | static inline int BITRATE(struct usb_gadget *g) | 336 | static inline int BITRATE(struct usb_gadget *g) |
@@ -395,7 +396,8 @@ static inline int BITRATE(struct usb_gadget *g) | |||
395 | #define STRING_SUBSET 8 | 396 | #define STRING_SUBSET 8 |
396 | #define STRING_RNDIS 9 | 397 | #define STRING_RNDIS 9 |
397 | 398 | ||
398 | #define USB_BUFSIZ 256 /* holds our biggest descriptor */ | 399 | /* holds our biggest descriptor (or RNDIS response) */ |
400 | #define USB_BUFSIZ 256 | ||
399 | 401 | ||
400 | /* | 402 | /* |
401 | * This device advertises one configuration, eth_config, unless RNDIS | 403 | * This device advertises one configuration, eth_config, unless RNDIS |
@@ -538,7 +540,7 @@ static const struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = { | |||
538 | .bDataInterface = 0x01, | 540 | .bDataInterface = 0x01, |
539 | }; | 541 | }; |
540 | 542 | ||
541 | static struct usb_cdc_acm_descriptor acm_descriptor = { | 543 | static const struct usb_cdc_acm_descriptor acm_descriptor = { |
542 | .bLength = sizeof acm_descriptor, | 544 | .bLength = sizeof acm_descriptor, |
543 | .bDescriptorType = USB_DT_CS_INTERFACE, | 545 | .bDescriptorType = USB_DT_CS_INTERFACE, |
544 | .bDescriptorSubType = USB_CDC_ACM_TYPE, | 546 | .bDescriptorSubType = USB_CDC_ACM_TYPE, |
@@ -846,7 +848,7 @@ static const struct usb_descriptor_header *hs_rndis_function [] = { | |||
846 | #else | 848 | #else |
847 | 849 | ||
848 | /* if there's no high speed support, maxpacket doesn't change. */ | 850 | /* if there's no high speed support, maxpacket doesn't change. */ |
849 | #define ep_desc(g,hs,fs) fs | 851 | #define ep_desc(g,hs,fs) (((void)(g)), (fs)) |
850 | 852 | ||
851 | static inline void __init hs_subset_descriptors(void) | 853 | static inline void __init hs_subset_descriptors(void) |
852 | { | 854 | { |
@@ -946,10 +948,31 @@ config_buf (enum usb_device_speed speed, | |||
946 | static void eth_start (struct eth_dev *dev, int gfp_flags); | 948 | static void eth_start (struct eth_dev *dev, int gfp_flags); |
947 | static int alloc_requests (struct eth_dev *dev, unsigned n, int gfp_flags); | 949 | static int alloc_requests (struct eth_dev *dev, unsigned n, int gfp_flags); |
948 | 950 | ||
949 | #ifdef DEV_CONFIG_CDC | 951 | static int |
950 | static inline int ether_alt_ep_setup (struct eth_dev *dev, struct usb_ep *ep) | 952 | set_ether_config (struct eth_dev *dev, int gfp_flags) |
951 | { | 953 | { |
952 | const struct usb_endpoint_descriptor *d; | 954 | int result = 0; |
955 | struct usb_gadget *gadget = dev->gadget; | ||
956 | |||
957 | /* status endpoint used for RNDIS and (optionally) CDC */ | ||
958 | if (!subset_active(dev) && dev->status_ep) { | ||
959 | dev->status = ep_desc (gadget, &hs_status_desc, | ||
960 | &fs_status_desc); | ||
961 | dev->status_ep->driver_data = dev; | ||
962 | |||
963 | result = usb_ep_enable (dev->status_ep, dev->status); | ||
964 | if (result != 0) { | ||
965 | DEBUG (dev, "enable %s --> %d\n", | ||
966 | dev->status_ep->name, result); | ||
967 | goto done; | ||
968 | } | ||
969 | } | ||
970 | |||
971 | dev->in = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc); | ||
972 | dev->in_ep->driver_data = dev; | ||
973 | |||
974 | dev->out = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc); | ||
975 | dev->out_ep->driver_data = dev; | ||
953 | 976 | ||
954 | /* With CDC, the host isn't allowed to use these two data | 977 | /* With CDC, the host isn't allowed to use these two data |
955 | * endpoints in the default altsetting for the interface. | 978 | * endpoints in the default altsetting for the interface. |
@@ -959,135 +982,33 @@ static inline int ether_alt_ep_setup (struct eth_dev *dev, struct usb_ep *ep) | |||
959 | * a side effect of setting a packet filter. Deactivation is | 982 | * a side effect of setting a packet filter. Deactivation is |
960 | * from REMOTE_NDIS_HALT_MSG, reset from REMOTE_NDIS_RESET_MSG. | 983 | * from REMOTE_NDIS_HALT_MSG, reset from REMOTE_NDIS_RESET_MSG. |
961 | */ | 984 | */ |
962 | 985 | if (!cdc_active(dev)) { | |
963 | /* one endpoint writes data back IN to the host */ | 986 | result = usb_ep_enable (dev->in_ep, dev->in); |
964 | if (strcmp (ep->name, EP_IN_NAME) == 0) { | 987 | if (result != 0) { |
965 | d = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc); | 988 | DEBUG(dev, "enable %s --> %d\n", |
966 | ep->driver_data = dev; | 989 | dev->in_ep->name, result); |
967 | dev->in = d; | 990 | goto done; |
968 | |||
969 | /* one endpoint just reads OUT packets */ | ||
970 | } else if (strcmp (ep->name, EP_OUT_NAME) == 0) { | ||
971 | d = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc); | ||
972 | ep->driver_data = dev; | ||
973 | dev->out = d; | ||
974 | |||
975 | /* optional status/notification endpoint */ | ||
976 | } else if (EP_STATUS_NAME && | ||
977 | strcmp (ep->name, EP_STATUS_NAME) == 0) { | ||
978 | int result; | ||
979 | |||
980 | d = ep_desc (dev->gadget, &hs_status_desc, &fs_status_desc); | ||
981 | result = usb_ep_enable (ep, d); | ||
982 | if (result < 0) | ||
983 | return result; | ||
984 | |||
985 | ep->driver_data = dev; | ||
986 | dev->status = d; | ||
987 | } | ||
988 | return 0; | ||
989 | } | ||
990 | #endif | ||
991 | |||
992 | #if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS) | ||
993 | static inline int ether_ep_setup (struct eth_dev *dev, struct usb_ep *ep) | ||
994 | { | ||
995 | int result; | ||
996 | const struct usb_endpoint_descriptor *d; | ||
997 | |||
998 | /* CDC subset is simpler: if the device is there, | ||
999 | * it's live with rx and tx endpoints. | ||
1000 | * | ||
1001 | * Do this as a shortcut for RNDIS too. | ||
1002 | */ | ||
1003 | |||
1004 | /* one endpoint writes data back IN to the host */ | ||
1005 | if (strcmp (ep->name, EP_IN_NAME) == 0) { | ||
1006 | d = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc); | ||
1007 | result = usb_ep_enable (ep, d); | ||
1008 | if (result < 0) | ||
1009 | return result; | ||
1010 | |||
1011 | ep->driver_data = dev; | ||
1012 | dev->in = d; | ||
1013 | |||
1014 | /* one endpoint just reads OUT packets */ | ||
1015 | } else if (strcmp (ep->name, EP_OUT_NAME) == 0) { | ||
1016 | d = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc); | ||
1017 | result = usb_ep_enable (ep, d); | ||
1018 | if (result < 0) | ||
1019 | return result; | ||
1020 | |||
1021 | ep->driver_data = dev; | ||
1022 | dev->out = d; | ||
1023 | } | ||
1024 | |||
1025 | return 0; | ||
1026 | } | ||
1027 | #endif | ||
1028 | |||
1029 | static int | ||
1030 | set_ether_config (struct eth_dev *dev, int gfp_flags) | ||
1031 | { | ||
1032 | int result = 0; | ||
1033 | struct usb_ep *ep; | ||
1034 | struct usb_gadget *gadget = dev->gadget; | ||
1035 | |||
1036 | gadget_for_each_ep (ep, gadget) { | ||
1037 | #ifdef DEV_CONFIG_CDC | ||
1038 | if (!dev->rndis && dev->cdc) { | ||
1039 | result = ether_alt_ep_setup (dev, ep); | ||
1040 | if (result == 0) | ||
1041 | continue; | ||
1042 | } | 991 | } |
1043 | #endif | ||
1044 | |||
1045 | #ifdef CONFIG_USB_ETH_RNDIS | ||
1046 | if (dev->rndis && strcmp (ep->name, EP_STATUS_NAME) == 0) { | ||
1047 | const struct usb_endpoint_descriptor *d; | ||
1048 | d = ep_desc (gadget, &hs_status_desc, &fs_status_desc); | ||
1049 | result = usb_ep_enable (ep, d); | ||
1050 | if (result == 0) { | ||
1051 | ep->driver_data = dev; | ||
1052 | dev->status = d; | ||
1053 | continue; | ||
1054 | } | ||
1055 | } else | ||
1056 | #endif | ||
1057 | 992 | ||
1058 | { | 993 | result = usb_ep_enable (dev->out_ep, dev->out); |
1059 | #if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS) | 994 | if (result != 0) { |
1060 | result = ether_ep_setup (dev, ep); | 995 | DEBUG (dev, "enable %s --> %d\n", |
1061 | if (result == 0) | 996 | dev->in_ep->name, result); |
1062 | continue; | 997 | goto done; |
1063 | #endif | ||
1064 | } | 998 | } |
1065 | |||
1066 | /* stop on error */ | ||
1067 | ERROR (dev, "can't enable %s, result %d\n", ep->name, result); | ||
1068 | break; | ||
1069 | } | 999 | } |
1070 | if (!result && (!dev->in_ep || !dev->out_ep)) | ||
1071 | result = -ENODEV; | ||
1072 | 1000 | ||
1001 | done: | ||
1073 | if (result == 0) | 1002 | if (result == 0) |
1074 | result = alloc_requests (dev, qlen (gadget), gfp_flags); | 1003 | result = alloc_requests (dev, qlen (gadget), gfp_flags); |
1075 | 1004 | ||
1076 | /* on error, disable any endpoints */ | 1005 | /* on error, disable any endpoints */ |
1077 | if (result < 0) { | 1006 | if (result < 0) { |
1078 | #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) | 1007 | if (!subset_active(dev)) |
1079 | if (dev->status) | ||
1080 | (void) usb_ep_disable (dev->status_ep); | 1008 | (void) usb_ep_disable (dev->status_ep); |
1081 | #endif | ||
1082 | dev->status = NULL; | 1009 | dev->status = NULL; |
1083 | #if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS) | 1010 | (void) usb_ep_disable (dev->in_ep); |
1084 | if (dev->rndis || !dev->cdc) { | 1011 | (void) usb_ep_disable (dev->out_ep); |
1085 | if (dev->in) | ||
1086 | (void) usb_ep_disable (dev->in_ep); | ||
1087 | if (dev->out) | ||
1088 | (void) usb_ep_disable (dev->out_ep); | ||
1089 | } | ||
1090 | #endif | ||
1091 | dev->in = NULL; | 1012 | dev->in = NULL; |
1092 | dev->out = NULL; | 1013 | dev->out = NULL; |
1093 | } else | 1014 | } else |
@@ -1095,8 +1016,7 @@ set_ether_config (struct eth_dev *dev, int gfp_flags) | |||
1095 | /* activate non-CDC configs right away | 1016 | /* activate non-CDC configs right away |
1096 | * this isn't strictly according to the RNDIS spec | 1017 | * this isn't strictly according to the RNDIS spec |
1097 | */ | 1018 | */ |
1098 | #if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS) | 1019 | if (!cdc_active (dev)) { |
1099 | if (dev->rndis || !dev->cdc) { | ||
1100 | netif_carrier_on (dev->net); | 1020 | netif_carrier_on (dev->net); |
1101 | if (netif_running (dev->net)) { | 1021 | if (netif_running (dev->net)) { |
1102 | spin_unlock (&dev->lock); | 1022 | spin_unlock (&dev->lock); |
@@ -1104,7 +1024,6 @@ set_ether_config (struct eth_dev *dev, int gfp_flags) | |||
1104 | spin_lock (&dev->lock); | 1024 | spin_lock (&dev->lock); |
1105 | } | 1025 | } |
1106 | } | 1026 | } |
1107 | #endif | ||
1108 | 1027 | ||
1109 | if (result == 0) | 1028 | if (result == 0) |
1110 | DEBUG (dev, "qlen %d\n", qlen (gadget)); | 1029 | DEBUG (dev, "qlen %d\n", qlen (gadget)); |
@@ -1124,6 +1043,7 @@ static void eth_reset_config (struct eth_dev *dev) | |||
1124 | 1043 | ||
1125 | netif_stop_queue (dev->net); | 1044 | netif_stop_queue (dev->net); |
1126 | netif_carrier_off (dev->net); | 1045 | netif_carrier_off (dev->net); |
1046 | rndis_uninit(dev->rndis_config); | ||
1127 | 1047 | ||
1128 | /* disable endpoints, forcing (synchronous) completion of | 1048 | /* disable endpoints, forcing (synchronous) completion of |
1129 | * pending i/o. then free the requests. | 1049 | * pending i/o. then free the requests. |
@@ -1150,6 +1070,8 @@ static void eth_reset_config (struct eth_dev *dev) | |||
1150 | if (dev->status) { | 1070 | if (dev->status) { |
1151 | usb_ep_disable (dev->status_ep); | 1071 | usb_ep_disable (dev->status_ep); |
1152 | } | 1072 | } |
1073 | dev->rndis = 0; | ||
1074 | dev->cdc_filter = 0; | ||
1153 | dev->config = 0; | 1075 | dev->config = 0; |
1154 | } | 1076 | } |
1155 | 1077 | ||
@@ -1162,9 +1084,6 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags) | |||
1162 | int result = 0; | 1084 | int result = 0; |
1163 | struct usb_gadget *gadget = dev->gadget; | 1085 | struct usb_gadget *gadget = dev->gadget; |
1164 | 1086 | ||
1165 | if (number == dev->config) | ||
1166 | return 0; | ||
1167 | |||
1168 | if (gadget_is_sa1100 (gadget) | 1087 | if (gadget_is_sa1100 (gadget) |
1169 | && dev->config | 1088 | && dev->config |
1170 | && atomic_read (&dev->tx_qlen) != 0) { | 1089 | && atomic_read (&dev->tx_qlen) != 0) { |
@@ -1174,12 +1093,8 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags) | |||
1174 | } | 1093 | } |
1175 | eth_reset_config (dev); | 1094 | eth_reset_config (dev); |
1176 | 1095 | ||
1177 | /* default: pass all packets, no multicast filtering */ | ||
1178 | dev->cdc_filter = DEFAULT_FILTER; | ||
1179 | |||
1180 | switch (number) { | 1096 | switch (number) { |
1181 | case DEV_CONFIG_VALUE: | 1097 | case DEV_CONFIG_VALUE: |
1182 | dev->rndis = 0; | ||
1183 | result = set_ether_config (dev, gfp_flags); | 1098 | result = set_ether_config (dev, gfp_flags); |
1184 | break; | 1099 | break; |
1185 | #ifdef CONFIG_USB_ETH_RNDIS | 1100 | #ifdef CONFIG_USB_ETH_RNDIS |
@@ -1218,9 +1133,9 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags) | |||
1218 | dev->config = number; | 1133 | dev->config = number; |
1219 | INFO (dev, "%s speed config #%d: %d mA, %s, using %s\n", | 1134 | INFO (dev, "%s speed config #%d: %d mA, %s, using %s\n", |
1220 | speed, number, power, driver_desc, | 1135 | speed, number, power, driver_desc, |
1221 | dev->rndis | 1136 | rndis_active(dev) |
1222 | ? "RNDIS" | 1137 | ? "RNDIS" |
1223 | : (dev->cdc | 1138 | : (cdc_active(dev) |
1224 | ? "CDC Ethernet" | 1139 | ? "CDC Ethernet" |
1225 | : "CDC Ethernet Subset")); | 1140 | : "CDC Ethernet Subset")); |
1226 | } | 1141 | } |
@@ -1231,6 +1146,13 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags) | |||
1231 | 1146 | ||
1232 | #ifdef DEV_CONFIG_CDC | 1147 | #ifdef DEV_CONFIG_CDC |
1233 | 1148 | ||
1149 | /* The interrupt endpoint is used in CDC networking models (Ethernet, ATM) | ||
1150 | * only to notify the host about link status changes (which we support) or | ||
1151 | * report completion of some encapsulated command (as used in RNDIS). Since | ||
1152 | * we want this CDC Ethernet code to be vendor-neutral, we don't use that | ||
1153 | * command mechanism; and only one status request is ever queued. | ||
1154 | */ | ||
1155 | |||
1234 | static void eth_status_complete (struct usb_ep *ep, struct usb_request *req) | 1156 | static void eth_status_complete (struct usb_ep *ep, struct usb_request *req) |
1235 | { | 1157 | { |
1236 | struct usb_cdc_notification *event = req->buf; | 1158 | struct usb_cdc_notification *event = req->buf; |
@@ -1259,7 +1181,7 @@ static void eth_status_complete (struct usb_ep *ep, struct usb_request *req) | |||
1259 | } else if (value != -ECONNRESET) | 1181 | } else if (value != -ECONNRESET) |
1260 | DEBUG (dev, "event %02x --> %d\n", | 1182 | DEBUG (dev, "event %02x --> %d\n", |
1261 | event->bNotificationType, value); | 1183 | event->bNotificationType, value); |
1262 | event->bmRequestType = 0xff; | 1184 | req->context = NULL; |
1263 | } | 1185 | } |
1264 | 1186 | ||
1265 | static void issue_start_status (struct eth_dev *dev) | 1187 | static void issue_start_status (struct eth_dev *dev) |
@@ -1276,6 +1198,8 @@ static void issue_start_status (struct eth_dev *dev) | |||
1276 | * a "cancel the whole queue" primitive since any | 1198 | * a "cancel the whole queue" primitive since any |
1277 | * unlink-one primitive has way too many error modes. | 1199 | * unlink-one primitive has way too many error modes. |
1278 | * here, we "know" toggle is already clear... | 1200 | * here, we "know" toggle is already clear... |
1201 | * | ||
1202 | * FIXME iff req->context != null just dequeue it | ||
1279 | */ | 1203 | */ |
1280 | usb_ep_disable (dev->status_ep); | 1204 | usb_ep_disable (dev->status_ep); |
1281 | usb_ep_enable (dev->status_ep, dev->status); | 1205 | usb_ep_enable (dev->status_ep, dev->status); |
@@ -1292,6 +1216,8 @@ static void issue_start_status (struct eth_dev *dev) | |||
1292 | 1216 | ||
1293 | req->length = sizeof *event; | 1217 | req->length = sizeof *event; |
1294 | req->complete = eth_status_complete; | 1218 | req->complete = eth_status_complete; |
1219 | req->context = dev; | ||
1220 | |||
1295 | value = usb_ep_queue (dev->status_ep, req, GFP_ATOMIC); | 1221 | value = usb_ep_queue (dev->status_ep, req, GFP_ATOMIC); |
1296 | if (value < 0) | 1222 | if (value < 0) |
1297 | DEBUG (dev, "status buf queue --> %d\n", value); | 1223 | DEBUG (dev, "status buf queue --> %d\n", value); |
@@ -1351,9 +1277,9 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
1351 | struct eth_dev *dev = get_gadget_data (gadget); | 1277 | struct eth_dev *dev = get_gadget_data (gadget); |
1352 | struct usb_request *req = dev->req; | 1278 | struct usb_request *req = dev->req; |
1353 | int value = -EOPNOTSUPP; | 1279 | int value = -EOPNOTSUPP; |
1354 | u16 wIndex = (__force u16) ctrl->wIndex; | 1280 | u16 wIndex = le16_to_cpu(ctrl->wIndex); |
1355 | u16 wValue = (__force u16) ctrl->wValue; | 1281 | u16 wValue = le16_to_cpu(ctrl->wValue); |
1356 | u16 wLength = (__force u16) ctrl->wLength; | 1282 | u16 wLength = le16_to_cpu(ctrl->wLength); |
1357 | 1283 | ||
1358 | /* descriptors just go into the pre-allocated ep0 buffer, | 1284 | /* descriptors just go into the pre-allocated ep0 buffer, |
1359 | * while config change events may enable network traffic. | 1285 | * while config change events may enable network traffic. |
@@ -1424,7 +1350,7 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
1424 | || !dev->config | 1350 | || !dev->config |
1425 | || wIndex > 1) | 1351 | || wIndex > 1) |
1426 | break; | 1352 | break; |
1427 | if (!dev->cdc && wIndex != 0) | 1353 | if (!cdc_active(dev) && wIndex != 0) |
1428 | break; | 1354 | break; |
1429 | spin_lock (&dev->lock); | 1355 | spin_lock (&dev->lock); |
1430 | 1356 | ||
@@ -1456,9 +1382,11 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
1456 | 1382 | ||
1457 | /* CDC requires the data transfers not be done from | 1383 | /* CDC requires the data transfers not be done from |
1458 | * the default interface setting ... also, setting | 1384 | * the default interface setting ... also, setting |
1459 | * the non-default interface clears filters etc. | 1385 | * the non-default interface resets filters etc. |
1460 | */ | 1386 | */ |
1461 | if (wValue == 1) { | 1387 | if (wValue == 1) { |
1388 | if (!cdc_active (dev)) | ||
1389 | break; | ||
1462 | usb_ep_enable (dev->in_ep, dev->in); | 1390 | usb_ep_enable (dev->in_ep, dev->in); |
1463 | usb_ep_enable (dev->out_ep, dev->out); | 1391 | usb_ep_enable (dev->out_ep, dev->out); |
1464 | dev->cdc_filter = DEFAULT_FILTER; | 1392 | dev->cdc_filter = DEFAULT_FILTER; |
@@ -1492,11 +1420,11 @@ done_set_intf: | |||
1492 | || !dev->config | 1420 | || !dev->config |
1493 | || wIndex > 1) | 1421 | || wIndex > 1) |
1494 | break; | 1422 | break; |
1495 | if (!(dev->cdc || dev->rndis) && wIndex != 0) | 1423 | if (!(cdc_active(dev) || rndis_active(dev)) && wIndex != 0) |
1496 | break; | 1424 | break; |
1497 | 1425 | ||
1498 | /* for CDC, iff carrier is on, data interface is active. */ | 1426 | /* for CDC, iff carrier is on, data interface is active. */ |
1499 | if (dev->rndis || wIndex != 1) | 1427 | if (rndis_active(dev) || wIndex != 1) |
1500 | *(u8 *)req->buf = 0; | 1428 | *(u8 *)req->buf = 0; |
1501 | else | 1429 | else |
1502 | *(u8 *)req->buf = netif_carrier_ok (dev->net) ? 1 : 0; | 1430 | *(u8 *)req->buf = netif_carrier_ok (dev->net) ? 1 : 0; |
@@ -1509,8 +1437,7 @@ done_set_intf: | |||
1509 | * wValue = packet filter bitmap | 1437 | * wValue = packet filter bitmap |
1510 | */ | 1438 | */ |
1511 | if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE) | 1439 | if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE) |
1512 | || !dev->cdc | 1440 | || !cdc_active(dev) |
1513 | || dev->rndis | ||
1514 | || wLength != 0 | 1441 | || wLength != 0 |
1515 | || wIndex > 1) | 1442 | || wIndex > 1) |
1516 | break; | 1443 | break; |
@@ -1534,7 +1461,7 @@ done_set_intf: | |||
1534 | */ | 1461 | */ |
1535 | case USB_CDC_SEND_ENCAPSULATED_COMMAND: | 1462 | case USB_CDC_SEND_ENCAPSULATED_COMMAND: |
1536 | if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE) | 1463 | if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE) |
1537 | || !dev->rndis | 1464 | || !rndis_active(dev) |
1538 | || wLength > USB_BUFSIZ | 1465 | || wLength > USB_BUFSIZ |
1539 | || wValue | 1466 | || wValue |
1540 | || rndis_control_intf.bInterfaceNumber | 1467 | || rndis_control_intf.bInterfaceNumber |
@@ -1549,7 +1476,7 @@ done_set_intf: | |||
1549 | case USB_CDC_GET_ENCAPSULATED_RESPONSE: | 1476 | case USB_CDC_GET_ENCAPSULATED_RESPONSE: |
1550 | if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE) | 1477 | if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE) |
1551 | == ctrl->bRequestType | 1478 | == ctrl->bRequestType |
1552 | && dev->rndis | 1479 | && rndis_active(dev) |
1553 | // && wLength >= 0x0400 | 1480 | // && wLength >= 0x0400 |
1554 | && !wValue | 1481 | && !wValue |
1555 | && rndis_control_intf.bInterfaceNumber | 1482 | && rndis_control_intf.bInterfaceNumber |
@@ -1688,10 +1615,8 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, int gfp_flags) | |||
1688 | */ | 1615 | */ |
1689 | size = (sizeof (struct ethhdr) + dev->net->mtu + RX_EXTRA); | 1616 | size = (sizeof (struct ethhdr) + dev->net->mtu + RX_EXTRA); |
1690 | size += dev->out_ep->maxpacket - 1; | 1617 | size += dev->out_ep->maxpacket - 1; |
1691 | #ifdef CONFIG_USB_ETH_RNDIS | 1618 | if (rndis_active(dev)) |
1692 | if (dev->rndis) | ||
1693 | size += sizeof (struct rndis_packet_msg_type); | 1619 | size += sizeof (struct rndis_packet_msg_type); |
1694 | #endif | ||
1695 | size -= size % dev->out_ep->maxpacket; | 1620 | size -= size % dev->out_ep->maxpacket; |
1696 | 1621 | ||
1697 | if ((skb = alloc_skb (size + NET_IP_ALIGN, gfp_flags)) == 0) { | 1622 | if ((skb = alloc_skb (size + NET_IP_ALIGN, gfp_flags)) == 0) { |
@@ -1735,11 +1660,9 @@ static void rx_complete (struct usb_ep *ep, struct usb_request *req) | |||
1735 | /* normal completion */ | 1660 | /* normal completion */ |
1736 | case 0: | 1661 | case 0: |
1737 | skb_put (skb, req->actual); | 1662 | skb_put (skb, req->actual); |
1738 | #ifdef CONFIG_USB_ETH_RNDIS | ||
1739 | /* we know MaxPacketsPerTransfer == 1 here */ | 1663 | /* we know MaxPacketsPerTransfer == 1 here */ |
1740 | if (dev->rndis) | 1664 | if (rndis_active(dev)) |
1741 | status = rndis_rm_hdr (skb); | 1665 | status = rndis_rm_hdr (skb); |
1742 | #endif | ||
1743 | if (status < 0 | 1666 | if (status < 0 |
1744 | || ETH_HLEN > skb->len | 1667 | || ETH_HLEN > skb->len |
1745 | || skb->len > ETH_FRAME_LEN) { | 1668 | || skb->len > ETH_FRAME_LEN) { |
@@ -1859,8 +1782,6 @@ static void rx_fill (struct eth_dev *dev, int gfp_flags) | |||
1859 | struct usb_request *req; | 1782 | struct usb_request *req; |
1860 | unsigned long flags; | 1783 | unsigned long flags; |
1861 | 1784 | ||
1862 | clear_bit (WORK_RX_MEMORY, &dev->todo); | ||
1863 | |||
1864 | /* fill unused rxq slots with some skb */ | 1785 | /* fill unused rxq slots with some skb */ |
1865 | spin_lock_irqsave (&dev->lock, flags); | 1786 | spin_lock_irqsave (&dev->lock, flags); |
1866 | while (!list_empty (&dev->rx_reqs)) { | 1787 | while (!list_empty (&dev->rx_reqs)) { |
@@ -1883,11 +1804,9 @@ static void eth_work (void *_dev) | |||
1883 | { | 1804 | { |
1884 | struct eth_dev *dev = _dev; | 1805 | struct eth_dev *dev = _dev; |
1885 | 1806 | ||
1886 | if (test_bit (WORK_RX_MEMORY, &dev->todo)) { | 1807 | if (test_and_clear_bit (WORK_RX_MEMORY, &dev->todo)) { |
1887 | if (netif_running (dev->net)) | 1808 | if (netif_running (dev->net)) |
1888 | rx_fill (dev, GFP_KERNEL); | 1809 | rx_fill (dev, GFP_KERNEL); |
1889 | else | ||
1890 | clear_bit (WORK_RX_MEMORY, &dev->todo); | ||
1891 | } | 1810 | } |
1892 | 1811 | ||
1893 | if (dev->todo) | 1812 | if (dev->todo) |
@@ -1971,8 +1890,7 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) | |||
1971 | * or the hardware can't use skb buffers. | 1890 | * or the hardware can't use skb buffers. |
1972 | * or there's not enough space for any RNDIS headers we need | 1891 | * or there's not enough space for any RNDIS headers we need |
1973 | */ | 1892 | */ |
1974 | #ifdef CONFIG_USB_ETH_RNDIS | 1893 | if (rndis_active(dev)) { |
1975 | if (dev->rndis) { | ||
1976 | struct sk_buff *skb_rndis; | 1894 | struct sk_buff *skb_rndis; |
1977 | 1895 | ||
1978 | skb_rndis = skb_realloc_headroom (skb, | 1896 | skb_rndis = skb_realloc_headroom (skb, |
@@ -1985,7 +1903,6 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) | |||
1985 | rndis_add_hdr (skb); | 1903 | rndis_add_hdr (skb); |
1986 | length = skb->len; | 1904 | length = skb->len; |
1987 | } | 1905 | } |
1988 | #endif | ||
1989 | req->buf = skb->data; | 1906 | req->buf = skb->data; |
1990 | req->context = skb; | 1907 | req->context = skb; |
1991 | req->complete = tx_complete; | 1908 | req->complete = tx_complete; |
@@ -2018,9 +1935,7 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) | |||
2018 | } | 1935 | } |
2019 | 1936 | ||
2020 | if (retval) { | 1937 | if (retval) { |
2021 | #ifdef CONFIG_USB_ETH_RNDIS | ||
2022 | drop: | 1938 | drop: |
2023 | #endif | ||
2024 | dev->stats.tx_dropped++; | 1939 | dev->stats.tx_dropped++; |
2025 | dev_kfree_skb_any (skb); | 1940 | dev_kfree_skb_any (skb); |
2026 | spin_lock_irqsave (&dev->lock, flags); | 1941 | spin_lock_irqsave (&dev->lock, flags); |
@@ -2036,27 +1951,31 @@ drop: | |||
2036 | 1951 | ||
2037 | #ifdef CONFIG_USB_ETH_RNDIS | 1952 | #ifdef CONFIG_USB_ETH_RNDIS |
2038 | 1953 | ||
2039 | static void rndis_send_media_state (struct eth_dev *dev, int connect) | 1954 | /* The interrupt endpoint is used in RNDIS to notify the host when messages |
2040 | { | 1955 | * other than data packets are available ... notably the REMOTE_NDIS_*_CMPLT |
2041 | if (!dev) | 1956 | * messages, but also REMOTE_NDIS_INDICATE_STATUS_MSG and potentially even |
2042 | return; | 1957 | * REMOTE_NDIS_KEEPALIVE_MSG. |
2043 | 1958 | * | |
2044 | if (connect) { | 1959 | * The RNDIS control queue is processed by GET_ENCAPSULATED_RESPONSE, and |
2045 | if (rndis_signal_connect (dev->rndis_config)) | 1960 | * normally just one notification will be queued. |
2046 | return; | 1961 | */ |
2047 | } else { | 1962 | |
2048 | if (rndis_signal_disconnect (dev->rndis_config)) | 1963 | static struct usb_request *eth_req_alloc (struct usb_ep *, unsigned, unsigned); |
2049 | return; | 1964 | static void eth_req_free (struct usb_ep *ep, struct usb_request *req); |
2050 | } | ||
2051 | } | ||
2052 | 1965 | ||
2053 | static void | 1966 | static void |
2054 | rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req) | 1967 | rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req) |
2055 | { | 1968 | { |
1969 | struct eth_dev *dev = ep->driver_data; | ||
1970 | |||
2056 | if (req->status || req->actual != req->length) | 1971 | if (req->status || req->actual != req->length) |
2057 | DEBUG ((struct eth_dev *) ep->driver_data, | 1972 | DEBUG (dev, |
2058 | "rndis control ack complete --> %d, %d/%d\n", | 1973 | "rndis control ack complete --> %d, %d/%d\n", |
2059 | req->status, req->actual, req->length); | 1974 | req->status, req->actual, req->length); |
1975 | req->context = NULL; | ||
1976 | |||
1977 | if (req != dev->stat_req) | ||
1978 | eth_req_free(ep, req); | ||
2060 | } | 1979 | } |
2061 | 1980 | ||
2062 | static int rndis_control_ack (struct net_device *net) | 1981 | static int rndis_control_ack (struct net_device *net) |
@@ -2071,11 +1990,19 @@ static int rndis_control_ack (struct net_device *net) | |||
2071 | return -ENODEV; | 1990 | return -ENODEV; |
2072 | } | 1991 | } |
2073 | 1992 | ||
1993 | /* in case queue length > 1 */ | ||
1994 | if (resp->context) { | ||
1995 | resp = eth_req_alloc (dev->status_ep, 8, GFP_ATOMIC); | ||
1996 | if (!resp) | ||
1997 | return -ENOMEM; | ||
1998 | } | ||
1999 | |||
2074 | /* Send RNDIS RESPONSE_AVAILABLE notification; | 2000 | /* Send RNDIS RESPONSE_AVAILABLE notification; |
2075 | * USB_CDC_NOTIFY_RESPONSE_AVAILABLE should work too | 2001 | * USB_CDC_NOTIFY_RESPONSE_AVAILABLE should work too |
2076 | */ | 2002 | */ |
2077 | resp->length = 8; | 2003 | resp->length = 8; |
2078 | resp->complete = rndis_control_ack_complete; | 2004 | resp->complete = rndis_control_ack_complete; |
2005 | resp->context = dev; | ||
2079 | 2006 | ||
2080 | *((__le32 *) resp->buf) = __constant_cpu_to_le32 (1); | 2007 | *((__le32 *) resp->buf) = __constant_cpu_to_le32 (1); |
2081 | *((__le32 *) resp->buf + 1) = __constant_cpu_to_le32 (0); | 2008 | *((__le32 *) resp->buf + 1) = __constant_cpu_to_le32 (0); |
@@ -2089,6 +2016,10 @@ static int rndis_control_ack (struct net_device *net) | |||
2089 | return 0; | 2016 | return 0; |
2090 | } | 2017 | } |
2091 | 2018 | ||
2019 | #else | ||
2020 | |||
2021 | #define rndis_control_ack NULL | ||
2022 | |||
2092 | #endif /* RNDIS */ | 2023 | #endif /* RNDIS */ |
2093 | 2024 | ||
2094 | static void eth_start (struct eth_dev *dev, int gfp_flags) | 2025 | static void eth_start (struct eth_dev *dev, int gfp_flags) |
@@ -2101,14 +2032,12 @@ static void eth_start (struct eth_dev *dev, int gfp_flags) | |||
2101 | /* and open the tx floodgates */ | 2032 | /* and open the tx floodgates */ |
2102 | atomic_set (&dev->tx_qlen, 0); | 2033 | atomic_set (&dev->tx_qlen, 0); |
2103 | netif_wake_queue (dev->net); | 2034 | netif_wake_queue (dev->net); |
2104 | #ifdef CONFIG_USB_ETH_RNDIS | 2035 | if (rndis_active(dev)) { |
2105 | if (dev->rndis) { | ||
2106 | rndis_set_param_medium (dev->rndis_config, | 2036 | rndis_set_param_medium (dev->rndis_config, |
2107 | NDIS_MEDIUM_802_3, | 2037 | NDIS_MEDIUM_802_3, |
2108 | BITRATE(dev->gadget)/100); | 2038 | BITRATE(dev->gadget)/100); |
2109 | rndis_send_media_state (dev, 1); | 2039 | (void) rndis_signal_connect (dev->rndis_config); |
2110 | } | 2040 | } |
2111 | #endif | ||
2112 | } | 2041 | } |
2113 | 2042 | ||
2114 | static int eth_open (struct net_device *net) | 2043 | static int eth_open (struct net_device *net) |
@@ -2149,28 +2078,27 @@ static int eth_stop (struct net_device *net) | |||
2149 | } | 2078 | } |
2150 | } | 2079 | } |
2151 | 2080 | ||
2152 | #ifdef CONFIG_USB_ETH_RNDIS | 2081 | if (rndis_active(dev)) { |
2153 | if (dev->rndis) { | ||
2154 | rndis_set_param_medium (dev->rndis_config, | 2082 | rndis_set_param_medium (dev->rndis_config, |
2155 | NDIS_MEDIUM_802_3, 0); | 2083 | NDIS_MEDIUM_802_3, 0); |
2156 | rndis_send_media_state (dev, 0); | 2084 | (void) rndis_signal_disconnect (dev->rndis_config); |
2157 | } | 2085 | } |
2158 | #endif | ||
2159 | 2086 | ||
2160 | return 0; | 2087 | return 0; |
2161 | } | 2088 | } |
2162 | 2089 | ||
2163 | /*-------------------------------------------------------------------------*/ | 2090 | /*-------------------------------------------------------------------------*/ |
2164 | 2091 | ||
2165 | static struct usb_request *eth_req_alloc (struct usb_ep *ep, unsigned size) | 2092 | static struct usb_request * |
2093 | eth_req_alloc (struct usb_ep *ep, unsigned size, unsigned gfp_flags) | ||
2166 | { | 2094 | { |
2167 | struct usb_request *req; | 2095 | struct usb_request *req; |
2168 | 2096 | ||
2169 | req = usb_ep_alloc_request (ep, GFP_KERNEL); | 2097 | req = usb_ep_alloc_request (ep, gfp_flags); |
2170 | if (!req) | 2098 | if (!req) |
2171 | return NULL; | 2099 | return NULL; |
2172 | 2100 | ||
2173 | req->buf = kmalloc (size, GFP_KERNEL); | 2101 | req->buf = kmalloc (size, gfp_flags); |
2174 | if (!req->buf) { | 2102 | if (!req->buf) { |
2175 | usb_ep_free_request (ep, req); | 2103 | usb_ep_free_request (ep, req); |
2176 | req = NULL; | 2104 | req = NULL; |
@@ -2192,10 +2120,8 @@ eth_unbind (struct usb_gadget *gadget) | |||
2192 | struct eth_dev *dev = get_gadget_data (gadget); | 2120 | struct eth_dev *dev = get_gadget_data (gadget); |
2193 | 2121 | ||
2194 | DEBUG (dev, "unbind\n"); | 2122 | DEBUG (dev, "unbind\n"); |
2195 | #ifdef CONFIG_USB_ETH_RNDIS | ||
2196 | rndis_deregister (dev->rndis_config); | 2123 | rndis_deregister (dev->rndis_config); |
2197 | rndis_exit (); | 2124 | rndis_exit (); |
2198 | #endif | ||
2199 | 2125 | ||
2200 | /* we've already been disconnected ... no i/o is active */ | 2126 | /* we've already been disconnected ... no i/o is active */ |
2201 | if (dev->req) { | 2127 | if (dev->req) { |
@@ -2368,13 +2294,11 @@ autoconf_fail: | |||
2368 | gadget->name); | 2294 | gadget->name); |
2369 | return -ENODEV; | 2295 | return -ENODEV; |
2370 | } | 2296 | } |
2371 | EP_IN_NAME = in_ep->name; | ||
2372 | in_ep->driver_data = in_ep; /* claim */ | 2297 | in_ep->driver_data = in_ep; /* claim */ |
2373 | 2298 | ||
2374 | out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc); | 2299 | out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc); |
2375 | if (!out_ep) | 2300 | if (!out_ep) |
2376 | goto autoconf_fail; | 2301 | goto autoconf_fail; |
2377 | EP_OUT_NAME = out_ep->name; | ||
2378 | out_ep->driver_data = out_ep; /* claim */ | 2302 | out_ep->driver_data = out_ep; /* claim */ |
2379 | 2303 | ||
2380 | #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) | 2304 | #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) |
@@ -2384,7 +2308,6 @@ autoconf_fail: | |||
2384 | if (cdc || rndis) { | 2308 | if (cdc || rndis) { |
2385 | status_ep = usb_ep_autoconfig (gadget, &fs_status_desc); | 2309 | status_ep = usb_ep_autoconfig (gadget, &fs_status_desc); |
2386 | if (status_ep) { | 2310 | if (status_ep) { |
2387 | EP_STATUS_NAME = status_ep->name; | ||
2388 | status_ep->driver_data = status_ep; /* claim */ | 2311 | status_ep->driver_data = status_ep; /* claim */ |
2389 | } else if (rndis) { | 2312 | } else if (rndis) { |
2390 | dev_err (&gadget->dev, | 2313 | dev_err (&gadget->dev, |
@@ -2426,7 +2349,7 @@ autoconf_fail: | |||
2426 | hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; | 2349 | hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; |
2427 | hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; | 2350 | hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; |
2428 | #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) | 2351 | #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) |
2429 | if (EP_STATUS_NAME) | 2352 | if (status_ep) |
2430 | hs_status_desc.bEndpointAddress = | 2353 | hs_status_desc.bEndpointAddress = |
2431 | fs_status_desc.bEndpointAddress; | 2354 | fs_status_desc.bEndpointAddress; |
2432 | #endif | 2355 | #endif |
@@ -2499,20 +2422,23 @@ autoconf_fail: | |||
2499 | SET_ETHTOOL_OPS(net, &ops); | 2422 | SET_ETHTOOL_OPS(net, &ops); |
2500 | 2423 | ||
2501 | /* preallocate control message data and buffer */ | 2424 | /* preallocate control message data and buffer */ |
2502 | dev->req = eth_req_alloc (gadget->ep0, USB_BUFSIZ); | 2425 | dev->req = eth_req_alloc (gadget->ep0, USB_BUFSIZ, GFP_KERNEL); |
2503 | if (!dev->req) | 2426 | if (!dev->req) |
2504 | goto fail; | 2427 | goto fail; |
2505 | dev->req->complete = eth_setup_complete; | 2428 | dev->req->complete = eth_setup_complete; |
2506 | 2429 | ||
2507 | /* ... and maybe likewise for status transfer */ | 2430 | /* ... and maybe likewise for status transfer */ |
2431 | #ifdef DEV_CONFIG_CDC | ||
2508 | if (dev->status_ep) { | 2432 | if (dev->status_ep) { |
2509 | dev->stat_req = eth_req_alloc (dev->status_ep, | 2433 | dev->stat_req = eth_req_alloc (dev->status_ep, |
2510 | STATUS_BYTECOUNT); | 2434 | STATUS_BYTECOUNT, GFP_KERNEL); |
2511 | if (!dev->stat_req) { | 2435 | if (!dev->stat_req) { |
2512 | eth_req_free (gadget->ep0, dev->req); | 2436 | eth_req_free (gadget->ep0, dev->req); |
2513 | goto fail; | 2437 | goto fail; |
2514 | } | 2438 | } |
2439 | dev->stat_req->context = NULL; | ||
2515 | } | 2440 | } |
2441 | #endif | ||
2516 | 2442 | ||
2517 | /* finish hookup to lower layer ... */ | 2443 | /* finish hookup to lower layer ... */ |
2518 | dev->gadget = gadget; | 2444 | dev->gadget = gadget; |
@@ -2526,16 +2452,16 @@ autoconf_fail: | |||
2526 | netif_stop_queue (dev->net); | 2452 | netif_stop_queue (dev->net); |
2527 | netif_carrier_off (dev->net); | 2453 | netif_carrier_off (dev->net); |
2528 | 2454 | ||
2529 | // SET_NETDEV_DEV (dev->net, &gadget->dev); | 2455 | SET_NETDEV_DEV (dev->net, &gadget->dev); |
2530 | status = register_netdev (dev->net); | 2456 | status = register_netdev (dev->net); |
2531 | if (status < 0) | 2457 | if (status < 0) |
2532 | goto fail1; | 2458 | goto fail1; |
2533 | 2459 | ||
2534 | INFO (dev, "%s, version: " DRIVER_VERSION "\n", driver_desc); | 2460 | INFO (dev, "%s, version: " DRIVER_VERSION "\n", driver_desc); |
2535 | INFO (dev, "using %s, OUT %s IN %s%s%s\n", gadget->name, | 2461 | INFO (dev, "using %s, OUT %s IN %s%s%s\n", gadget->name, |
2536 | EP_OUT_NAME, EP_IN_NAME, | 2462 | out_ep->name, in_ep->name, |
2537 | EP_STATUS_NAME ? " STATUS " : "", | 2463 | status_ep ? " STATUS " : "", |
2538 | EP_STATUS_NAME ? EP_STATUS_NAME : "" | 2464 | status_ep ? status_ep->name : "" |
2539 | ); | 2465 | ); |
2540 | INFO (dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n", | 2466 | INFO (dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n", |
2541 | net->dev_addr [0], net->dev_addr [1], | 2467 | net->dev_addr [0], net->dev_addr [1], |
@@ -2548,7 +2474,6 @@ autoconf_fail: | |||
2548 | dev->host_mac [2], dev->host_mac [3], | 2474 | dev->host_mac [2], dev->host_mac [3], |
2549 | dev->host_mac [4], dev->host_mac [5]); | 2475 | dev->host_mac [4], dev->host_mac [5]); |
2550 | 2476 | ||
2551 | #ifdef CONFIG_USB_ETH_RNDIS | ||
2552 | if (rndis) { | 2477 | if (rndis) { |
2553 | u32 vendorID = 0; | 2478 | u32 vendorID = 0; |
2554 | 2479 | ||
@@ -2565,7 +2490,7 @@ fail0: | |||
2565 | /* these set up a lot of the OIDs that RNDIS needs */ | 2490 | /* these set up a lot of the OIDs that RNDIS needs */ |
2566 | rndis_set_host_mac (dev->rndis_config, dev->host_mac); | 2491 | rndis_set_host_mac (dev->rndis_config, dev->host_mac); |
2567 | if (rndis_set_param_dev (dev->rndis_config, dev->net, | 2492 | if (rndis_set_param_dev (dev->rndis_config, dev->net, |
2568 | &dev->stats)) | 2493 | &dev->stats, &dev->cdc_filter)) |
2569 | goto fail0; | 2494 | goto fail0; |
2570 | if (rndis_set_param_vendor (dev->rndis_config, vendorID, | 2495 | if (rndis_set_param_vendor (dev->rndis_config, vendorID, |
2571 | manufacturer)) | 2496 | manufacturer)) |
@@ -2576,7 +2501,6 @@ fail0: | |||
2576 | goto fail0; | 2501 | goto fail0; |
2577 | INFO (dev, "RNDIS ready\n"); | 2502 | INFO (dev, "RNDIS ready\n"); |
2578 | } | 2503 | } |
2579 | #endif | ||
2580 | 2504 | ||
2581 | return status; | 2505 | return status; |
2582 | 2506 | ||
@@ -2610,11 +2534,8 @@ eth_resume (struct usb_gadget *gadget) | |||
2610 | /*-------------------------------------------------------------------------*/ | 2534 | /*-------------------------------------------------------------------------*/ |
2611 | 2535 | ||
2612 | static struct usb_gadget_driver eth_driver = { | 2536 | static struct usb_gadget_driver eth_driver = { |
2613 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 2537 | .speed = DEVSPEED, |
2614 | .speed = USB_SPEED_HIGH, | 2538 | |
2615 | #else | ||
2616 | .speed = USB_SPEED_FULL, | ||
2617 | #endif | ||
2618 | .function = (char *) driver_desc, | 2539 | .function = (char *) driver_desc, |
2619 | .bind = eth_bind, | 2540 | .bind = eth_bind, |
2620 | .unbind = eth_unbind, | 2541 | .unbind = eth_unbind, |
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index a9be85103d23..4f57085619b4 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
@@ -81,6 +81,10 @@ | |||
81 | * removable Default false, boolean for removable media | 81 | * removable Default false, boolean for removable media |
82 | * luns=N Default N = number of filenames, number of | 82 | * luns=N Default N = number of filenames, number of |
83 | * LUNs to support | 83 | * LUNs to support |
84 | * stall Default determined according to the type of | ||
85 | * USB device controller (usually true), | ||
86 | * boolean to permit the driver to halt | ||
87 | * bulk endpoints | ||
84 | * transport=XXX Default BBB, transport name (CB, CBI, or BBB) | 88 | * transport=XXX Default BBB, transport name (CB, CBI, or BBB) |
85 | * protocol=YYY Default SCSI, protocol name (RBC, 8020 or | 89 | * protocol=YYY Default SCSI, protocol name (RBC, 8020 or |
86 | * ATAPI, QIC, UFI, 8070, or SCSI; | 90 | * ATAPI, QIC, UFI, 8070, or SCSI; |
@@ -91,14 +95,10 @@ | |||
91 | * buflen=N Default N=16384, buffer size used (will be | 95 | * buflen=N Default N=16384, buffer size used (will be |
92 | * rounded down to a multiple of | 96 | * rounded down to a multiple of |
93 | * PAGE_CACHE_SIZE) | 97 | * PAGE_CACHE_SIZE) |
94 | * stall Default determined according to the type of | ||
95 | * USB device controller (usually true), | ||
96 | * boolean to permit the driver to halt | ||
97 | * bulk endpoints | ||
98 | * | 98 | * |
99 | * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro", | 99 | * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro", |
100 | * "removable", and "luns" options are available; default values are used | 100 | * "removable", "luns", and "stall" options are available; default values |
101 | * for everything else. | 101 | * are used for everything else. |
102 | * | 102 | * |
103 | * The pathnames of the backing files and the ro settings are available in | 103 | * The pathnames of the backing files and the ro settings are available in |
104 | * the attribute files "file" and "ro" in the lun<n> subdirectory of the | 104 | * the attribute files "file" and "ro" in the lun<n> subdirectory of the |
@@ -342,14 +342,15 @@ static struct { | |||
342 | int num_ros; | 342 | int num_ros; |
343 | unsigned int nluns; | 343 | unsigned int nluns; |
344 | 344 | ||
345 | int removable; | ||
346 | int can_stall; | ||
347 | |||
345 | char *transport_parm; | 348 | char *transport_parm; |
346 | char *protocol_parm; | 349 | char *protocol_parm; |
347 | int removable; | ||
348 | unsigned short vendor; | 350 | unsigned short vendor; |
349 | unsigned short product; | 351 | unsigned short product; |
350 | unsigned short release; | 352 | unsigned short release; |
351 | unsigned int buflen; | 353 | unsigned int buflen; |
352 | int can_stall; | ||
353 | 354 | ||
354 | int transport_type; | 355 | int transport_type; |
355 | char *transport_name; | 356 | char *transport_name; |
@@ -360,11 +361,11 @@ static struct { | |||
360 | .transport_parm = "BBB", | 361 | .transport_parm = "BBB", |
361 | .protocol_parm = "SCSI", | 362 | .protocol_parm = "SCSI", |
362 | .removable = 0, | 363 | .removable = 0, |
364 | .can_stall = 1, | ||
363 | .vendor = DRIVER_VENDOR_ID, | 365 | .vendor = DRIVER_VENDOR_ID, |
364 | .product = DRIVER_PRODUCT_ID, | 366 | .product = DRIVER_PRODUCT_ID, |
365 | .release = 0xffff, // Use controller chip type | 367 | .release = 0xffff, // Use controller chip type |
366 | .buflen = 16384, | 368 | .buflen = 16384, |
367 | .can_stall = 1, | ||
368 | }; | 369 | }; |
369 | 370 | ||
370 | 371 | ||
@@ -380,6 +381,9 @@ MODULE_PARM_DESC(luns, "number of LUNs"); | |||
380 | module_param_named(removable, mod_data.removable, bool, S_IRUGO); | 381 | module_param_named(removable, mod_data.removable, bool, S_IRUGO); |
381 | MODULE_PARM_DESC(removable, "true to simulate removable media"); | 382 | MODULE_PARM_DESC(removable, "true to simulate removable media"); |
382 | 383 | ||
384 | module_param_named(stall, mod_data.can_stall, bool, S_IRUGO); | ||
385 | MODULE_PARM_DESC(stall, "false to prevent bulk stalls"); | ||
386 | |||
383 | 387 | ||
384 | /* In the non-TEST version, only the module parameters listed above | 388 | /* In the non-TEST version, only the module parameters listed above |
385 | * are available. */ | 389 | * are available. */ |
@@ -404,9 +408,6 @@ MODULE_PARM_DESC(release, "USB release number"); | |||
404 | module_param_named(buflen, mod_data.buflen, uint, S_IRUGO); | 408 | module_param_named(buflen, mod_data.buflen, uint, S_IRUGO); |
405 | MODULE_PARM_DESC(buflen, "I/O buffer size"); | 409 | MODULE_PARM_DESC(buflen, "I/O buffer size"); |
406 | 410 | ||
407 | module_param_named(stall, mod_data.can_stall, bool, S_IRUGO); | ||
408 | MODULE_PARM_DESC(stall, "false to prevent bulk stalls"); | ||
409 | |||
410 | #endif /* CONFIG_USB_FILE_STORAGE_TEST */ | 411 | #endif /* CONFIG_USB_FILE_STORAGE_TEST */ |
411 | 412 | ||
412 | 413 | ||
@@ -818,7 +819,7 @@ static void inline put_be32(u8 *buf, u32 val) | |||
818 | buf[0] = val >> 24; | 819 | buf[0] = val >> 24; |
819 | buf[1] = val >> 16; | 820 | buf[1] = val >> 16; |
820 | buf[2] = val >> 8; | 821 | buf[2] = val >> 8; |
821 | buf[3] = val; | 822 | buf[3] = val & 0xff; |
822 | } | 823 | } |
823 | 824 | ||
824 | 825 | ||
@@ -1276,8 +1277,8 @@ static int class_setup_req(struct fsg_dev *fsg, | |||
1276 | { | 1277 | { |
1277 | struct usb_request *req = fsg->ep0req; | 1278 | struct usb_request *req = fsg->ep0req; |
1278 | int value = -EOPNOTSUPP; | 1279 | int value = -EOPNOTSUPP; |
1279 | u16 w_index = ctrl->wIndex; | 1280 | u16 w_index = le16_to_cpu(ctrl->wIndex); |
1280 | u16 w_length = ctrl->wLength; | 1281 | u16 w_length = le16_to_cpu(ctrl->wLength); |
1281 | 1282 | ||
1282 | if (!fsg->config) | 1283 | if (!fsg->config) |
1283 | return value; | 1284 | return value; |
@@ -1312,7 +1313,7 @@ static int class_setup_req(struct fsg_dev *fsg, | |||
1312 | } | 1313 | } |
1313 | VDBG(fsg, "get max LUN\n"); | 1314 | VDBG(fsg, "get max LUN\n"); |
1314 | *(u8 *) req->buf = fsg->nluns - 1; | 1315 | *(u8 *) req->buf = fsg->nluns - 1; |
1315 | value = min(w_length, (u16) 1); | 1316 | value = 1; |
1316 | break; | 1317 | break; |
1317 | } | 1318 | } |
1318 | } | 1319 | } |
@@ -1344,7 +1345,7 @@ static int class_setup_req(struct fsg_dev *fsg, | |||
1344 | "unknown class-specific control req " | 1345 | "unknown class-specific control req " |
1345 | "%02x.%02x v%04x i%04x l%u\n", | 1346 | "%02x.%02x v%04x i%04x l%u\n", |
1346 | ctrl->bRequestType, ctrl->bRequest, | 1347 | ctrl->bRequestType, ctrl->bRequest, |
1347 | ctrl->wValue, w_index, w_length); | 1348 | le16_to_cpu(ctrl->wValue), w_index, w_length); |
1348 | return value; | 1349 | return value; |
1349 | } | 1350 | } |
1350 | 1351 | ||
@@ -1358,9 +1359,8 @@ static int standard_setup_req(struct fsg_dev *fsg, | |||
1358 | { | 1359 | { |
1359 | struct usb_request *req = fsg->ep0req; | 1360 | struct usb_request *req = fsg->ep0req; |
1360 | int value = -EOPNOTSUPP; | 1361 | int value = -EOPNOTSUPP; |
1361 | u16 w_index = ctrl->wIndex; | 1362 | u16 w_index = le16_to_cpu(ctrl->wIndex); |
1362 | u16 w_value = ctrl->wValue; | 1363 | u16 w_value = le16_to_cpu(ctrl->wValue); |
1363 | u16 w_length = ctrl->wLength; | ||
1364 | 1364 | ||
1365 | /* Usually this just stores reply data in the pre-allocated ep0 buffer, | 1365 | /* Usually this just stores reply data in the pre-allocated ep0 buffer, |
1366 | * but config change events will also reconfigure hardware. */ | 1366 | * but config change events will also reconfigure hardware. */ |
@@ -1374,7 +1374,7 @@ static int standard_setup_req(struct fsg_dev *fsg, | |||
1374 | 1374 | ||
1375 | case USB_DT_DEVICE: | 1375 | case USB_DT_DEVICE: |
1376 | VDBG(fsg, "get device descriptor\n"); | 1376 | VDBG(fsg, "get device descriptor\n"); |
1377 | value = min(w_length, (u16) sizeof device_desc); | 1377 | value = sizeof device_desc; |
1378 | memcpy(req->buf, &device_desc, value); | 1378 | memcpy(req->buf, &device_desc, value); |
1379 | break; | 1379 | break; |
1380 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 1380 | #ifdef CONFIG_USB_GADGET_DUALSPEED |
@@ -1382,7 +1382,7 @@ static int standard_setup_req(struct fsg_dev *fsg, | |||
1382 | VDBG(fsg, "get device qualifier\n"); | 1382 | VDBG(fsg, "get device qualifier\n"); |
1383 | if (!fsg->gadget->is_dualspeed) | 1383 | if (!fsg->gadget->is_dualspeed) |
1384 | break; | 1384 | break; |
1385 | value = min(w_length, (u16) sizeof dev_qualifier); | 1385 | value = sizeof dev_qualifier; |
1386 | memcpy(req->buf, &dev_qualifier, value); | 1386 | memcpy(req->buf, &dev_qualifier, value); |
1387 | break; | 1387 | break; |
1388 | 1388 | ||
@@ -1401,8 +1401,6 @@ static int standard_setup_req(struct fsg_dev *fsg, | |||
1401 | req->buf, | 1401 | req->buf, |
1402 | w_value >> 8, | 1402 | w_value >> 8, |
1403 | w_value & 0xff); | 1403 | w_value & 0xff); |
1404 | if (value >= 0) | ||
1405 | value = min(w_length, (u16) value); | ||
1406 | break; | 1404 | break; |
1407 | 1405 | ||
1408 | case USB_DT_STRING: | 1406 | case USB_DT_STRING: |
@@ -1411,8 +1409,6 @@ static int standard_setup_req(struct fsg_dev *fsg, | |||
1411 | /* wIndex == language code */ | 1409 | /* wIndex == language code */ |
1412 | value = usb_gadget_get_string(&stringtab, | 1410 | value = usb_gadget_get_string(&stringtab, |
1413 | w_value & 0xff, req->buf); | 1411 | w_value & 0xff, req->buf); |
1414 | if (value >= 0) | ||
1415 | value = min(w_length, (u16) value); | ||
1416 | break; | 1412 | break; |
1417 | } | 1413 | } |
1418 | break; | 1414 | break; |
@@ -1438,7 +1434,7 @@ static int standard_setup_req(struct fsg_dev *fsg, | |||
1438 | break; | 1434 | break; |
1439 | VDBG(fsg, "get configuration\n"); | 1435 | VDBG(fsg, "get configuration\n"); |
1440 | *(u8 *) req->buf = fsg->config; | 1436 | *(u8 *) req->buf = fsg->config; |
1441 | value = min(w_length, (u16) 1); | 1437 | value = 1; |
1442 | break; | 1438 | break; |
1443 | 1439 | ||
1444 | case USB_REQ_SET_INTERFACE: | 1440 | case USB_REQ_SET_INTERFACE: |
@@ -1466,14 +1462,14 @@ static int standard_setup_req(struct fsg_dev *fsg, | |||
1466 | } | 1462 | } |
1467 | VDBG(fsg, "get interface\n"); | 1463 | VDBG(fsg, "get interface\n"); |
1468 | *(u8 *) req->buf = 0; | 1464 | *(u8 *) req->buf = 0; |
1469 | value = min(w_length, (u16) 1); | 1465 | value = 1; |
1470 | break; | 1466 | break; |
1471 | 1467 | ||
1472 | default: | 1468 | default: |
1473 | VDBG(fsg, | 1469 | VDBG(fsg, |
1474 | "unknown control req %02x.%02x v%04x i%04x l%u\n", | 1470 | "unknown control req %02x.%02x v%04x i%04x l%u\n", |
1475 | ctrl->bRequestType, ctrl->bRequest, | 1471 | ctrl->bRequestType, ctrl->bRequest, |
1476 | w_value, w_index, w_length); | 1472 | w_value, w_index, le16_to_cpu(ctrl->wLength)); |
1477 | } | 1473 | } |
1478 | 1474 | ||
1479 | return value; | 1475 | return value; |
@@ -1485,6 +1481,7 @@ static int fsg_setup(struct usb_gadget *gadget, | |||
1485 | { | 1481 | { |
1486 | struct fsg_dev *fsg = get_gadget_data(gadget); | 1482 | struct fsg_dev *fsg = get_gadget_data(gadget); |
1487 | int rc; | 1483 | int rc; |
1484 | int w_length = le16_to_cpu(ctrl->wLength); | ||
1488 | 1485 | ||
1489 | ++fsg->ep0_req_tag; // Record arrival of a new request | 1486 | ++fsg->ep0_req_tag; // Record arrival of a new request |
1490 | fsg->ep0req->context = NULL; | 1487 | fsg->ep0req->context = NULL; |
@@ -1498,9 +1495,9 @@ static int fsg_setup(struct usb_gadget *gadget, | |||
1498 | 1495 | ||
1499 | /* Respond with data/status or defer until later? */ | 1496 | /* Respond with data/status or defer until later? */ |
1500 | if (rc >= 0 && rc != DELAYED_STATUS) { | 1497 | if (rc >= 0 && rc != DELAYED_STATUS) { |
1498 | rc = min(rc, w_length); | ||
1501 | fsg->ep0req->length = rc; | 1499 | fsg->ep0req->length = rc; |
1502 | fsg->ep0req->zero = (rc < ctrl->wLength && | 1500 | fsg->ep0req->zero = rc < w_length; |
1503 | (rc % gadget->ep0->maxpacket) == 0); | ||
1504 | fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ? | 1501 | fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ? |
1505 | "ep0-in" : "ep0-out"); | 1502 | "ep0-in" : "ep0-out"); |
1506 | rc = ep0_queue(fsg); | 1503 | rc = ep0_queue(fsg); |
@@ -2660,7 +2657,7 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, | |||
2660 | } | 2657 | } |
2661 | } | 2658 | } |
2662 | 2659 | ||
2663 | /* Check that the LUN values are oonsistent */ | 2660 | /* Check that the LUN values are consistent */ |
2664 | if (transport_is_bbb()) { | 2661 | if (transport_is_bbb()) { |
2665 | if (fsg->lun != lun) | 2662 | if (fsg->lun != lun) |
2666 | DBG(fsg, "using LUN %d from CBW, " | 2663 | DBG(fsg, "using LUN %d from CBW, " |
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 005db7cca292..ed773a9111de 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c | |||
@@ -70,7 +70,7 @@ MODULE_LICENSE("GPL"); | |||
70 | * seem to behave quite as expected. Used by default. | 70 | * seem to behave quite as expected. Used by default. |
71 | * | 71 | * |
72 | * OUT dma documents design problems handling the common "short packet" | 72 | * OUT dma documents design problems handling the common "short packet" |
73 | * transfer termination policy; it couldn't enabled by default, even | 73 | * transfer termination policy; it couldn't be enabled by default, even |
74 | * if the OUT-dma abort problems had a resolution. | 74 | * if the OUT-dma abort problems had a resolution. |
75 | */ | 75 | */ |
76 | static unsigned use_dma = 1; | 76 | static unsigned use_dma = 1; |
@@ -313,7 +313,7 @@ goku_free_request(struct usb_ep *_ep, struct usb_request *_req) | |||
313 | #if defined(CONFIG_X86) | 313 | #if defined(CONFIG_X86) |
314 | #define USE_KMALLOC | 314 | #define USE_KMALLOC |
315 | 315 | ||
316 | #elif defined(CONFIG_MIPS) && !defined(CONFIG_NONCOHERENT_IO) | 316 | #elif defined(CONFIG_MIPS) && !defined(CONFIG_DMA_NONCOHERENT) |
317 | #define USE_KMALLOC | 317 | #define USE_KMALLOC |
318 | 318 | ||
319 | #elif defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE) | 319 | #elif defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE) |
@@ -1524,9 +1524,12 @@ static void ep0_setup(struct goku_udc *dev) | |||
1524 | /* read SETUP packet and enter DATA stage */ | 1524 | /* read SETUP packet and enter DATA stage */ |
1525 | ctrl.bRequestType = readl(®s->bRequestType); | 1525 | ctrl.bRequestType = readl(®s->bRequestType); |
1526 | ctrl.bRequest = readl(®s->bRequest); | 1526 | ctrl.bRequest = readl(®s->bRequest); |
1527 | ctrl.wValue = (readl(®s->wValueH) << 8) | readl(®s->wValueL); | 1527 | ctrl.wValue = cpu_to_le16((readl(®s->wValueH) << 8) |
1528 | ctrl.wIndex = (readl(®s->wIndexH) << 8) | readl(®s->wIndexL); | 1528 | | readl(®s->wValueL)); |
1529 | ctrl.wLength = (readl(®s->wLengthH) << 8) | readl(®s->wLengthL); | 1529 | ctrl.wIndex = cpu_to_le16((readl(®s->wIndexH) << 8) |
1530 | | readl(®s->wIndexL)); | ||
1531 | ctrl.wLength = cpu_to_le16((readl(®s->wLengthH) << 8) | ||
1532 | | readl(®s->wLengthL)); | ||
1530 | writel(0, ®s->SetupRecv); | 1533 | writel(0, ®s->SetupRecv); |
1531 | 1534 | ||
1532 | nuke(&dev->ep[0], 0); | 1535 | nuke(&dev->ep[0], 0); |
@@ -1548,18 +1551,20 @@ static void ep0_setup(struct goku_udc *dev) | |||
1548 | case USB_REQ_CLEAR_FEATURE: | 1551 | case USB_REQ_CLEAR_FEATURE: |
1549 | switch (ctrl.bRequestType) { | 1552 | switch (ctrl.bRequestType) { |
1550 | case USB_RECIP_ENDPOINT: | 1553 | case USB_RECIP_ENDPOINT: |
1551 | tmp = ctrl.wIndex & 0x0f; | 1554 | tmp = le16_to_cpu(ctrl.wIndex) & 0x0f; |
1552 | /* active endpoint */ | 1555 | /* active endpoint */ |
1553 | if (tmp > 3 || (!dev->ep[tmp].desc && tmp != 0)) | 1556 | if (tmp > 3 || (!dev->ep[tmp].desc && tmp != 0)) |
1554 | goto stall; | 1557 | goto stall; |
1555 | if (ctrl.wIndex & USB_DIR_IN) { | 1558 | if (ctrl.wIndex & __constant_cpu_to_le16( |
1559 | USB_DIR_IN)) { | ||
1556 | if (!dev->ep[tmp].is_in) | 1560 | if (!dev->ep[tmp].is_in) |
1557 | goto stall; | 1561 | goto stall; |
1558 | } else { | 1562 | } else { |
1559 | if (dev->ep[tmp].is_in) | 1563 | if (dev->ep[tmp].is_in) |
1560 | goto stall; | 1564 | goto stall; |
1561 | } | 1565 | } |
1562 | if (ctrl.wValue != USB_ENDPOINT_HALT) | 1566 | if (ctrl.wValue != __constant_cpu_to_le16( |
1567 | USB_ENDPOINT_HALT)) | ||
1563 | goto stall; | 1568 | goto stall; |
1564 | if (tmp) | 1569 | if (tmp) |
1565 | goku_clear_halt(&dev->ep[tmp]); | 1570 | goku_clear_halt(&dev->ep[tmp]); |
@@ -1571,7 +1576,7 @@ succeed: | |||
1571 | return; | 1576 | return; |
1572 | case USB_RECIP_DEVICE: | 1577 | case USB_RECIP_DEVICE: |
1573 | /* device remote wakeup: always clear */ | 1578 | /* device remote wakeup: always clear */ |
1574 | if (ctrl.wValue != 1) | 1579 | if (ctrl.wValue != __constant_cpu_to_le16(1)) |
1575 | goto stall; | 1580 | goto stall; |
1576 | VDBG(dev, "clear dev remote wakeup\n"); | 1581 | VDBG(dev, "clear dev remote wakeup\n"); |
1577 | goto succeed; | 1582 | goto succeed; |
@@ -1589,14 +1594,15 @@ succeed: | |||
1589 | #ifdef USB_TRACE | 1594 | #ifdef USB_TRACE |
1590 | VDBG(dev, "SETUP %02x.%02x v%04x i%04x l%04x\n", | 1595 | VDBG(dev, "SETUP %02x.%02x v%04x i%04x l%04x\n", |
1591 | ctrl.bRequestType, ctrl.bRequest, | 1596 | ctrl.bRequestType, ctrl.bRequest, |
1592 | ctrl.wValue, ctrl.wIndex, ctrl.wLength); | 1597 | le16_to_cpu(ctrl.wValue), le16_to_cpu(ctrl.wIndex), |
1598 | le16_to_cpu(ctrl.wLength)); | ||
1593 | #endif | 1599 | #endif |
1594 | 1600 | ||
1595 | /* hw wants to know when we're configured (or not) */ | 1601 | /* hw wants to know when we're configured (or not) */ |
1596 | dev->req_config = (ctrl.bRequest == USB_REQ_SET_CONFIGURATION | 1602 | dev->req_config = (ctrl.bRequest == USB_REQ_SET_CONFIGURATION |
1597 | && ctrl.bRequestType == USB_RECIP_DEVICE); | 1603 | && ctrl.bRequestType == USB_RECIP_DEVICE); |
1598 | if (unlikely(dev->req_config)) | 1604 | if (unlikely(dev->req_config)) |
1599 | dev->configured = (ctrl.wValue != 0); | 1605 | dev->configured = (ctrl.wValue != __constant_cpu_to_le16(0)); |
1600 | 1606 | ||
1601 | /* delegate everything to the gadget driver. | 1607 | /* delegate everything to the gadget driver. |
1602 | * it may respond after this irq handler returns. | 1608 | * it may respond after this irq handler returns. |
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 1e5e6ddef787..020815397a49 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c | |||
@@ -417,8 +417,8 @@ ep_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) | |||
417 | goto free1; | 417 | goto free1; |
418 | 418 | ||
419 | value = ep_io (data, kbuf, len); | 419 | value = ep_io (data, kbuf, len); |
420 | VDEBUG (data->dev, "%s read %d OUT, status %d\n", | 420 | VDEBUG (data->dev, "%s read %zu OUT, status %d\n", |
421 | data->name, len, value); | 421 | data->name, len, (int) value); |
422 | if (value >= 0 && copy_to_user (buf, kbuf, value)) | 422 | if (value >= 0 && copy_to_user (buf, kbuf, value)) |
423 | value = -EFAULT; | 423 | value = -EFAULT; |
424 | 424 | ||
@@ -465,8 +465,8 @@ ep_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) | |||
465 | } | 465 | } |
466 | 466 | ||
467 | value = ep_io (data, kbuf, len); | 467 | value = ep_io (data, kbuf, len); |
468 | VDEBUG (data->dev, "%s write %d IN, status %d\n", | 468 | VDEBUG (data->dev, "%s write %zu IN, status %d\n", |
469 | data->name, len, value); | 469 | data->name, len, (int) value); |
470 | free1: | 470 | free1: |
471 | up (&data->lock); | 471 | up (&data->lock); |
472 | kfree (kbuf); | 472 | kfree (kbuf); |
@@ -1318,8 +1318,8 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
1318 | struct usb_request *req = dev->req; | 1318 | struct usb_request *req = dev->req; |
1319 | int value = -EOPNOTSUPP; | 1319 | int value = -EOPNOTSUPP; |
1320 | struct usb_gadgetfs_event *event; | 1320 | struct usb_gadgetfs_event *event; |
1321 | u16 w_value = ctrl->wValue; | 1321 | u16 w_value = le16_to_cpu(ctrl->wValue); |
1322 | u16 w_length = ctrl->wLength; | 1322 | u16 w_length = le16_to_cpu(ctrl->wLength); |
1323 | 1323 | ||
1324 | spin_lock (&dev->lock); | 1324 | spin_lock (&dev->lock); |
1325 | dev->setup_abort = 0; | 1325 | dev->setup_abort = 0; |
diff --git a/drivers/usb/gadget/ndis.h b/drivers/usb/gadget/ndis.h index c553bbf68cab..09e3ee4eeae1 100644 --- a/drivers/usb/gadget/ndis.h +++ b/drivers/usb/gadget/ndis.h | |||
@@ -47,17 +47,17 @@ struct NDIS_PM_WAKE_UP_CAPABILITIES { | |||
47 | #define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004 | 47 | #define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004 |
48 | 48 | ||
49 | struct NDIS_PNP_CAPABILITIES { | 49 | struct NDIS_PNP_CAPABILITIES { |
50 | u32 Flags; | 50 | __le32 Flags; |
51 | struct NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities; | 51 | struct NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | struct NDIS_PM_PACKET_PATTERN { | 54 | struct NDIS_PM_PACKET_PATTERN { |
55 | u32 Priority; | 55 | __le32 Priority; |
56 | u32 Reserved; | 56 | __le32 Reserved; |
57 | u32 MaskSize; | 57 | __le32 MaskSize; |
58 | u32 PatternOffset; | 58 | __le32 PatternOffset; |
59 | u32 PatternSize; | 59 | __le32 PatternSize; |
60 | u32 PatternFlags; | 60 | __le32 PatternFlags; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | 63 | ||
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index e47e398daeb5..13a3dbc9949b 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c | |||
@@ -448,7 +448,7 @@ net2280_free_request (struct usb_ep *_ep, struct usb_request *_req) | |||
448 | #elif defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE) | 448 | #elif defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE) |
449 | #define USE_KMALLOC | 449 | #define USE_KMALLOC |
450 | 450 | ||
451 | #elif defined(CONFIG_MIPS) && !defined(CONFIG_NONCOHERENT_IO) | 451 | #elif defined(CONFIG_MIPS) && !defined(CONFIG_DMA_NONCOHERENT) |
452 | #define USE_KMALLOC | 452 | #define USE_KMALLOC |
453 | 453 | ||
454 | /* FIXME there are other cases, including an x86-64 one ... */ | 454 | /* FIXME there are other cases, including an x86-64 one ... */ |
@@ -1113,7 +1113,7 @@ static void restart_dma (struct net2280_ep *ep) | |||
1113 | if (ep->in_fifo_validate) | 1113 | if (ep->in_fifo_validate) |
1114 | dmactl |= (1 << DMA_FIFO_VALIDATE); | 1114 | dmactl |= (1 << DMA_FIFO_VALIDATE); |
1115 | list_for_each_entry (entry, &ep->queue, queue) { | 1115 | list_for_each_entry (entry, &ep->queue, queue) { |
1116 | u32 dmacount; | 1116 | __le32 dmacount; |
1117 | 1117 | ||
1118 | if (entry == req) | 1118 | if (entry == req) |
1119 | continue; | 1119 | continue; |
@@ -1238,7 +1238,7 @@ static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req) | |||
1238 | &ep->dma->dmadesc); | 1238 | &ep->dma->dmadesc); |
1239 | if (req->td->dmacount & dma_done_ie) | 1239 | if (req->td->dmacount & dma_done_ie) |
1240 | writel (readl (&ep->dma->dmacount) | 1240 | writel (readl (&ep->dma->dmacount) |
1241 | | dma_done_ie, | 1241 | | le32_to_cpu(dma_done_ie), |
1242 | &ep->dma->dmacount); | 1242 | &ep->dma->dmacount); |
1243 | } else { | 1243 | } else { |
1244 | struct net2280_request *prev; | 1244 | struct net2280_request *prev; |
@@ -1779,6 +1779,9 @@ static void set_fifo_mode (struct net2280 *dev, int mode) | |||
1779 | list_add_tail (&dev->ep [6].ep.ep_list, &dev->gadget.ep_list); | 1779 | list_add_tail (&dev->ep [6].ep.ep_list, &dev->gadget.ep_list); |
1780 | } | 1780 | } |
1781 | 1781 | ||
1782 | /* just declare this in any driver that really need it */ | ||
1783 | extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode); | ||
1784 | |||
1782 | /** | 1785 | /** |
1783 | * net2280_set_fifo_mode - change allocation of fifo buffers | 1786 | * net2280_set_fifo_mode - change allocation of fifo buffers |
1784 | * @gadget: access to the net2280 device that will be updated | 1787 | * @gadget: access to the net2280 device that will be updated |
@@ -2382,9 +2385,9 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) | |||
2382 | cpu_to_le32s (&u.raw [0]); | 2385 | cpu_to_le32s (&u.raw [0]); |
2383 | cpu_to_le32s (&u.raw [1]); | 2386 | cpu_to_le32s (&u.raw [1]); |
2384 | 2387 | ||
2385 | le16_to_cpus (&u.r.wValue); | 2388 | #define w_value le16_to_cpup (&u.r.wValue) |
2386 | le16_to_cpus (&u.r.wIndex); | 2389 | #define w_index le16_to_cpup (&u.r.wIndex) |
2387 | le16_to_cpus (&u.r.wLength); | 2390 | #define w_length le16_to_cpup (&u.r.wLength) |
2388 | 2391 | ||
2389 | /* ack the irq */ | 2392 | /* ack the irq */ |
2390 | writel (1 << SETUP_PACKET_INTERRUPT, &dev->regs->irqstat0); | 2393 | writel (1 << SETUP_PACKET_INTERRUPT, &dev->regs->irqstat0); |
@@ -2413,25 +2416,25 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) | |||
2413 | switch (u.r.bRequest) { | 2416 | switch (u.r.bRequest) { |
2414 | case USB_REQ_GET_STATUS: { | 2417 | case USB_REQ_GET_STATUS: { |
2415 | struct net2280_ep *e; | 2418 | struct net2280_ep *e; |
2416 | u16 status; | 2419 | __le32 status; |
2417 | 2420 | ||
2418 | /* hw handles device and interface status */ | 2421 | /* hw handles device and interface status */ |
2419 | if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT)) | 2422 | if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT)) |
2420 | goto delegate; | 2423 | goto delegate; |
2421 | if ((e = get_ep_by_addr (dev, u.r.wIndex)) == 0 | 2424 | if ((e = get_ep_by_addr (dev, w_index)) == 0 |
2422 | || u.r.wLength > 2) | 2425 | || w_length > 2) |
2423 | goto do_stall; | 2426 | goto do_stall; |
2424 | 2427 | ||
2425 | if (readl (&e->regs->ep_rsp) | 2428 | if (readl (&e->regs->ep_rsp) |
2426 | & (1 << SET_ENDPOINT_HALT)) | 2429 | & (1 << SET_ENDPOINT_HALT)) |
2427 | status = __constant_cpu_to_le16 (1); | 2430 | status = __constant_cpu_to_le32 (1); |
2428 | else | 2431 | else |
2429 | status = __constant_cpu_to_le16 (0); | 2432 | status = __constant_cpu_to_le32 (0); |
2430 | 2433 | ||
2431 | /* don't bother with a request object! */ | 2434 | /* don't bother with a request object! */ |
2432 | writel (0, &dev->epregs [0].ep_irqenb); | 2435 | writel (0, &dev->epregs [0].ep_irqenb); |
2433 | set_fifo_bytecount (ep, u.r.wLength); | 2436 | set_fifo_bytecount (ep, w_length); |
2434 | writel (status, &dev->epregs [0].ep_data); | 2437 | writel ((__force u32)status, &dev->epregs [0].ep_data); |
2435 | allow_status (ep); | 2438 | allow_status (ep); |
2436 | VDEBUG (dev, "%s stat %02x\n", ep->ep.name, status); | 2439 | VDEBUG (dev, "%s stat %02x\n", ep->ep.name, status); |
2437 | goto next_endpoints; | 2440 | goto next_endpoints; |
@@ -2443,10 +2446,10 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) | |||
2443 | /* hw handles device features */ | 2446 | /* hw handles device features */ |
2444 | if (u.r.bRequestType != USB_RECIP_ENDPOINT) | 2447 | if (u.r.bRequestType != USB_RECIP_ENDPOINT) |
2445 | goto delegate; | 2448 | goto delegate; |
2446 | if (u.r.wValue != USB_ENDPOINT_HALT | 2449 | if (w_value != USB_ENDPOINT_HALT |
2447 | || u.r.wLength != 0) | 2450 | || w_length != 0) |
2448 | goto do_stall; | 2451 | goto do_stall; |
2449 | if ((e = get_ep_by_addr (dev, u.r.wIndex)) == 0) | 2452 | if ((e = get_ep_by_addr (dev, w_index)) == 0) |
2450 | goto do_stall; | 2453 | goto do_stall; |
2451 | clear_halt (e); | 2454 | clear_halt (e); |
2452 | allow_status (ep); | 2455 | allow_status (ep); |
@@ -2460,10 +2463,10 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) | |||
2460 | /* hw handles device features */ | 2463 | /* hw handles device features */ |
2461 | if (u.r.bRequestType != USB_RECIP_ENDPOINT) | 2464 | if (u.r.bRequestType != USB_RECIP_ENDPOINT) |
2462 | goto delegate; | 2465 | goto delegate; |
2463 | if (u.r.wValue != USB_ENDPOINT_HALT | 2466 | if (w_value != USB_ENDPOINT_HALT |
2464 | || u.r.wLength != 0) | 2467 | || w_length != 0) |
2465 | goto do_stall; | 2468 | goto do_stall; |
2466 | if ((e = get_ep_by_addr (dev, u.r.wIndex)) == 0) | 2469 | if ((e = get_ep_by_addr (dev, w_index)) == 0) |
2467 | goto do_stall; | 2470 | goto do_stall; |
2468 | set_halt (e); | 2471 | set_halt (e); |
2469 | allow_status (ep); | 2472 | allow_status (ep); |
@@ -2473,10 +2476,10 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) | |||
2473 | break; | 2476 | break; |
2474 | default: | 2477 | default: |
2475 | delegate: | 2478 | delegate: |
2476 | VDEBUG (dev, "setup %02x.%02x v%04x i%04x " | 2479 | VDEBUG (dev, "setup %02x.%02x v%04x i%04x l%04x" |
2477 | "ep_cfg %08x\n", | 2480 | "ep_cfg %08x\n", |
2478 | u.r.bRequestType, u.r.bRequest, | 2481 | u.r.bRequestType, u.r.bRequest, |
2479 | u.r.wValue, u.r.wIndex, | 2482 | w_value, w_index, w_length, |
2480 | readl (&ep->regs->ep_cfg)); | 2483 | readl (&ep->regs->ep_cfg)); |
2481 | spin_unlock (&dev->lock); | 2484 | spin_unlock (&dev->lock); |
2482 | tmp = dev->driver->setup (&dev->gadget, &u.r); | 2485 | tmp = dev->driver->setup (&dev->gadget, &u.r); |
@@ -2497,6 +2500,10 @@ do_stall: | |||
2497 | */ | 2500 | */ |
2498 | } | 2501 | } |
2499 | 2502 | ||
2503 | #undef w_value | ||
2504 | #undef w_index | ||
2505 | #undef w_length | ||
2506 | |||
2500 | next_endpoints: | 2507 | next_endpoints: |
2501 | /* endpoint data irq ? */ | 2508 | /* endpoint data irq ? */ |
2502 | scratch = stat & 0x7f; | 2509 | scratch = stat & 0x7f; |
@@ -2653,7 +2660,7 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat) | |||
2653 | restart_dma (ep); | 2660 | restart_dma (ep); |
2654 | else if (ep->is_in && use_dma_chaining) { | 2661 | else if (ep->is_in && use_dma_chaining) { |
2655 | struct net2280_request *req; | 2662 | struct net2280_request *req; |
2656 | u32 dmacount; | 2663 | __le32 dmacount; |
2657 | 2664 | ||
2658 | /* the descriptor at the head of the chain | 2665 | /* the descriptor at the head of the chain |
2659 | * may still have VALID_BIT clear; that's | 2666 | * may still have VALID_BIT clear; that's |
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 98cbcbc16cc1..a2b812af6e66 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c | |||
@@ -52,7 +52,6 @@ | |||
52 | #include <asm/mach-types.h> | 52 | #include <asm/mach-types.h> |
53 | 53 | ||
54 | #include <asm/arch/dma.h> | 54 | #include <asm/arch/dma.h> |
55 | #include <asm/arch/mux.h> | ||
56 | #include <asm/arch/usb.h> | 55 | #include <asm/arch/usb.h> |
57 | 56 | ||
58 | #include "omap_udc.h" | 57 | #include "omap_udc.h" |
@@ -167,7 +166,7 @@ static int omap_ep_enable(struct usb_ep *_ep, | |||
167 | maxp = le16_to_cpu (desc->wMaxPacketSize); | 166 | maxp = le16_to_cpu (desc->wMaxPacketSize); |
168 | if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK | 167 | if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK |
169 | && maxp != ep->maxpacket) | 168 | && maxp != ep->maxpacket) |
170 | || desc->wMaxPacketSize > ep->maxpacket | 169 | || le16_to_cpu(desc->wMaxPacketSize) > ep->maxpacket |
171 | || !desc->wMaxPacketSize) { | 170 | || !desc->wMaxPacketSize) { |
172 | DBG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name); | 171 | DBG("%s, bad %s maxpacket\n", __FUNCTION__, _ep->name); |
173 | return -ERANGE; | 172 | return -ERANGE; |
@@ -214,7 +213,7 @@ static int omap_ep_enable(struct usb_ep *_ep, | |||
214 | ep->has_dma = 0; | 213 | ep->has_dma = 0; |
215 | ep->lch = -1; | 214 | ep->lch = -1; |
216 | use_ep(ep, UDC_EP_SEL); | 215 | use_ep(ep, UDC_EP_SEL); |
217 | UDC_CTRL_REG = UDC_RESET_EP; | 216 | UDC_CTRL_REG = udc->clr_halt; |
218 | ep->ackwait = 0; | 217 | ep->ackwait = 0; |
219 | deselect_ep(); | 218 | deselect_ep(); |
220 | 219 | ||
@@ -253,7 +252,7 @@ static int omap_ep_disable(struct usb_ep *_ep) | |||
253 | } | 252 | } |
254 | 253 | ||
255 | spin_lock_irqsave(&ep->udc->lock, flags); | 254 | spin_lock_irqsave(&ep->udc->lock, flags); |
256 | ep->desc = 0; | 255 | ep->desc = NULL; |
257 | nuke (ep, -ESHUTDOWN); | 256 | nuke (ep, -ESHUTDOWN); |
258 | ep->ep.maxpacket = ep->maxpacket; | 257 | ep->ep.maxpacket = ep->maxpacket; |
259 | ep->has_dma = 0; | 258 | ep->has_dma = 0; |
@@ -388,8 +387,8 @@ done(struct omap_ep *ep, struct omap_req *req, int status) | |||
388 | 387 | ||
389 | /*-------------------------------------------------------------------------*/ | 388 | /*-------------------------------------------------------------------------*/ |
390 | 389 | ||
391 | #define FIFO_FULL (UDC_NON_ISO_FIFO_FULL | UDC_ISO_FIFO_FULL) | 390 | #define UDC_FIFO_FULL (UDC_NON_ISO_FIFO_FULL | UDC_ISO_FIFO_FULL) |
392 | #define FIFO_UNWRITABLE (UDC_EP_HALTED | FIFO_FULL) | 391 | #define UDC_FIFO_UNWRITABLE (UDC_EP_HALTED | UDC_FIFO_FULL) |
393 | 392 | ||
394 | #define FIFO_EMPTY (UDC_NON_ISO_FIFO_EMPTY | UDC_ISO_FIFO_EMPTY) | 393 | #define FIFO_EMPTY (UDC_NON_ISO_FIFO_EMPTY | UDC_ISO_FIFO_EMPTY) |
395 | #define FIFO_UNREADABLE (UDC_EP_HALTED | FIFO_EMPTY) | 394 | #define FIFO_UNREADABLE (UDC_EP_HALTED | FIFO_EMPTY) |
@@ -433,7 +432,7 @@ static int write_fifo(struct omap_ep *ep, struct omap_req *req) | |||
433 | 432 | ||
434 | /* PIO-IN isn't double buffered except for iso */ | 433 | /* PIO-IN isn't double buffered except for iso */ |
435 | ep_stat = UDC_STAT_FLG_REG; | 434 | ep_stat = UDC_STAT_FLG_REG; |
436 | if (ep_stat & FIFO_UNWRITABLE) | 435 | if (ep_stat & UDC_FIFO_UNWRITABLE) |
437 | return 0; | 436 | return 0; |
438 | 437 | ||
439 | count = ep->ep.maxpacket; | 438 | count = ep->ep.maxpacket; |
@@ -504,7 +503,7 @@ static int read_fifo(struct omap_ep *ep, struct omap_req *req) | |||
504 | if (ep_stat & UDC_EP_HALTED) | 503 | if (ep_stat & UDC_EP_HALTED) |
505 | break; | 504 | break; |
506 | 505 | ||
507 | if (ep_stat & FIFO_FULL) | 506 | if (ep_stat & UDC_FIFO_FULL) |
508 | avail = ep->ep.maxpacket; | 507 | avail = ep->ep.maxpacket; |
509 | else { | 508 | else { |
510 | avail = UDC_RXFSTAT_REG; | 509 | avail = UDC_RXFSTAT_REG; |
@@ -538,6 +537,32 @@ static int read_fifo(struct omap_ep *ep, struct omap_req *req) | |||
538 | 537 | ||
539 | /*-------------------------------------------------------------------------*/ | 538 | /*-------------------------------------------------------------------------*/ |
540 | 539 | ||
540 | static inline dma_addr_t dma_csac(unsigned lch) | ||
541 | { | ||
542 | dma_addr_t csac; | ||
543 | |||
544 | /* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is | ||
545 | * read before the DMA controller finished disabling the channel. | ||
546 | */ | ||
547 | csac = omap_readw(OMAP_DMA_CSAC(lch)); | ||
548 | if (csac == 0) | ||
549 | csac = omap_readw(OMAP_DMA_CSAC(lch)); | ||
550 | return csac; | ||
551 | } | ||
552 | |||
553 | static inline dma_addr_t dma_cdac(unsigned lch) | ||
554 | { | ||
555 | dma_addr_t cdac; | ||
556 | |||
557 | /* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is | ||
558 | * read before the DMA controller finished disabling the channel. | ||
559 | */ | ||
560 | cdac = omap_readw(OMAP_DMA_CDAC(lch)); | ||
561 | if (cdac == 0) | ||
562 | cdac = omap_readw(OMAP_DMA_CDAC(lch)); | ||
563 | return cdac; | ||
564 | } | ||
565 | |||
541 | static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start) | 566 | static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start) |
542 | { | 567 | { |
543 | dma_addr_t end; | 568 | dma_addr_t end; |
@@ -548,7 +573,7 @@ static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start) | |||
548 | if (cpu_is_omap15xx()) | 573 | if (cpu_is_omap15xx()) |
549 | return 0; | 574 | return 0; |
550 | 575 | ||
551 | end = omap_readw(OMAP_DMA_CSAC(ep->lch)); | 576 | end = dma_csac(ep->lch); |
552 | if (end == ep->dma_counter) | 577 | if (end == ep->dma_counter) |
553 | return 0; | 578 | return 0; |
554 | 579 | ||
@@ -559,14 +584,14 @@ static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start) | |||
559 | } | 584 | } |
560 | 585 | ||
561 | #define DMA_DEST_LAST(x) (cpu_is_omap15xx() \ | 586 | #define DMA_DEST_LAST(x) (cpu_is_omap15xx() \ |
562 | ? OMAP_DMA_CSAC(x) /* really: CPC */ \ | 587 | ? omap_readw(OMAP_DMA_CSAC(x)) /* really: CPC */ \ |
563 | : OMAP_DMA_CDAC(x)) | 588 | : dma_cdac(x)) |
564 | 589 | ||
565 | static u16 dma_dest_len(struct omap_ep *ep, dma_addr_t start) | 590 | static u16 dma_dest_len(struct omap_ep *ep, dma_addr_t start) |
566 | { | 591 | { |
567 | dma_addr_t end; | 592 | dma_addr_t end; |
568 | 593 | ||
569 | end = omap_readw(DMA_DEST_LAST(ep->lch)); | 594 | end = DMA_DEST_LAST(ep->lch); |
570 | if (end == ep->dma_counter) | 595 | if (end == ep->dma_counter) |
571 | return 0; | 596 | return 0; |
572 | 597 | ||
@@ -593,7 +618,7 @@ static void next_in_dma(struct omap_ep *ep, struct omap_req *req) | |||
593 | : OMAP_DMA_SYNC_ELEMENT; | 618 | : OMAP_DMA_SYNC_ELEMENT; |
594 | 619 | ||
595 | /* measure length in either bytes or packets */ | 620 | /* measure length in either bytes or packets */ |
596 | if ((cpu_is_omap16xx() && length <= (UDC_TXN_TSC + 1)) | 621 | if ((cpu_is_omap16xx() && length <= UDC_TXN_TSC) |
597 | || (cpu_is_omap15xx() && length < ep->maxpacket)) { | 622 | || (cpu_is_omap15xx() && length < ep->maxpacket)) { |
598 | txdma_ctrl = UDC_TXN_EOT | length; | 623 | txdma_ctrl = UDC_TXN_EOT | length; |
599 | omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8, | 624 | omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8, |
@@ -602,15 +627,15 @@ static void next_in_dma(struct omap_ep *ep, struct omap_req *req) | |||
602 | length = min(length / ep->maxpacket, | 627 | length = min(length / ep->maxpacket, |
603 | (unsigned) UDC_TXN_TSC + 1); | 628 | (unsigned) UDC_TXN_TSC + 1); |
604 | txdma_ctrl = length; | 629 | txdma_ctrl = length; |
605 | omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8, | 630 | omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16, |
606 | ep->ep.maxpacket, length, sync_mode); | 631 | ep->ep.maxpacket >> 1, length, sync_mode); |
607 | length *= ep->maxpacket; | 632 | length *= ep->maxpacket; |
608 | } | 633 | } |
609 | omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF, | 634 | omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF, |
610 | OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual); | 635 | OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual); |
611 | 636 | ||
612 | omap_start_dma(ep->lch); | 637 | omap_start_dma(ep->lch); |
613 | ep->dma_counter = omap_readw(OMAP_DMA_CSAC(ep->lch)); | 638 | ep->dma_counter = dma_csac(ep->lch); |
614 | UDC_DMA_IRQ_EN_REG |= UDC_TX_DONE_IE(ep->dma_channel); | 639 | UDC_DMA_IRQ_EN_REG |= UDC_TX_DONE_IE(ep->dma_channel); |
615 | UDC_TXDMA_REG(ep->dma_channel) = UDC_TXN_START | txdma_ctrl; | 640 | UDC_TXDMA_REG(ep->dma_channel) = UDC_TXN_START | txdma_ctrl; |
616 | req->dma_bytes = length; | 641 | req->dma_bytes = length; |
@@ -650,12 +675,12 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req) | |||
650 | packets = (req->req.length - req->req.actual) / ep->ep.maxpacket; | 675 | packets = (req->req.length - req->req.actual) / ep->ep.maxpacket; |
651 | packets = min(packets, (unsigned)UDC_RXN_TC + 1); | 676 | packets = min(packets, (unsigned)UDC_RXN_TC + 1); |
652 | req->dma_bytes = packets * ep->ep.maxpacket; | 677 | req->dma_bytes = packets * ep->ep.maxpacket; |
653 | omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8, | 678 | omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16, |
654 | ep->ep.maxpacket, packets, | 679 | ep->ep.maxpacket >> 1, packets, |
655 | OMAP_DMA_SYNC_ELEMENT); | 680 | OMAP_DMA_SYNC_ELEMENT); |
656 | omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF, | 681 | omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF, |
657 | OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual); | 682 | OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual); |
658 | ep->dma_counter = omap_readw(DMA_DEST_LAST(ep->lch)); | 683 | ep->dma_counter = DMA_DEST_LAST(ep->lch); |
659 | 684 | ||
660 | UDC_RXDMA_REG(ep->dma_channel) = UDC_RXN_STOP | (packets - 1); | 685 | UDC_RXDMA_REG(ep->dma_channel) = UDC_RXN_STOP | (packets - 1); |
661 | UDC_DMA_IRQ_EN_REG |= UDC_RX_EOT_IE(ep->dma_channel); | 686 | UDC_DMA_IRQ_EN_REG |= UDC_RX_EOT_IE(ep->dma_channel); |
@@ -763,7 +788,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) | |||
763 | reg = UDC_TXDMA_CFG_REG; | 788 | reg = UDC_TXDMA_CFG_REG; |
764 | else | 789 | else |
765 | reg = UDC_RXDMA_CFG_REG; | 790 | reg = UDC_RXDMA_CFG_REG; |
766 | reg |= 1 << 12; /* "pulse" activated */ | 791 | reg |= UDC_DMA_REQ; /* "pulse" activated */ |
767 | 792 | ||
768 | ep->dma_channel = 0; | 793 | ep->dma_channel = 0; |
769 | ep->lch = -1; | 794 | ep->lch = -1; |
@@ -787,6 +812,11 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) | |||
787 | ep->ep.name, dma_error, ep, &ep->lch); | 812 | ep->ep.name, dma_error, ep, &ep->lch); |
788 | if (status == 0) { | 813 | if (status == 0) { |
789 | UDC_TXDMA_CFG_REG = reg; | 814 | UDC_TXDMA_CFG_REG = reg; |
815 | /* EMIFF */ | ||
816 | omap_set_dma_src_burst_mode(ep->lch, | ||
817 | OMAP_DMA_DATA_BURST_4); | ||
818 | omap_set_dma_src_data_pack(ep->lch, 1); | ||
819 | /* TIPB */ | ||
790 | omap_set_dma_dest_params(ep->lch, | 820 | omap_set_dma_dest_params(ep->lch, |
791 | OMAP_DMA_PORT_TIPB, | 821 | OMAP_DMA_PORT_TIPB, |
792 | OMAP_DMA_AMODE_CONSTANT, | 822 | OMAP_DMA_AMODE_CONSTANT, |
@@ -797,10 +827,15 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) | |||
797 | ep->ep.name, dma_error, ep, &ep->lch); | 827 | ep->ep.name, dma_error, ep, &ep->lch); |
798 | if (status == 0) { | 828 | if (status == 0) { |
799 | UDC_RXDMA_CFG_REG = reg; | 829 | UDC_RXDMA_CFG_REG = reg; |
830 | /* TIPB */ | ||
800 | omap_set_dma_src_params(ep->lch, | 831 | omap_set_dma_src_params(ep->lch, |
801 | OMAP_DMA_PORT_TIPB, | 832 | OMAP_DMA_PORT_TIPB, |
802 | OMAP_DMA_AMODE_CONSTANT, | 833 | OMAP_DMA_AMODE_CONSTANT, |
803 | (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG)); | 834 | (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG)); |
835 | /* EMIFF */ | ||
836 | omap_set_dma_dest_burst_mode(ep->lch, | ||
837 | OMAP_DMA_DATA_BURST_4); | ||
838 | omap_set_dma_dest_data_pack(ep->lch, 1); | ||
804 | } | 839 | } |
805 | } | 840 | } |
806 | if (status) | 841 | if (status) |
@@ -856,7 +891,7 @@ static void dma_channel_release(struct omap_ep *ep) | |||
856 | if (!list_empty(&ep->queue)) | 891 | if (!list_empty(&ep->queue)) |
857 | req = container_of(ep->queue.next, struct omap_req, queue); | 892 | req = container_of(ep->queue.next, struct omap_req, queue); |
858 | else | 893 | else |
859 | req = 0; | 894 | req = NULL; |
860 | 895 | ||
861 | active = ((1 << 7) & omap_readl(OMAP_DMA_CCR(ep->lch))) != 0; | 896 | active = ((1 << 7) & omap_readl(OMAP_DMA_CCR(ep->lch))) != 0; |
862 | 897 | ||
@@ -865,9 +900,13 @@ static void dma_channel_release(struct omap_ep *ep) | |||
865 | (ep->bEndpointAddress & USB_DIR_IN) ? 't' : 'r', | 900 | (ep->bEndpointAddress & USB_DIR_IN) ? 't' : 'r', |
866 | ep->dma_channel - 1, req); | 901 | ep->dma_channel - 1, req); |
867 | 902 | ||
903 | /* NOTE: re-setting RX_REQ/TX_REQ because of a chip bug (before | ||
904 | * OMAP 1710 ES2.0) where reading the DMA_CFG can clear them. | ||
905 | */ | ||
906 | |||
868 | /* wait till current packet DMA finishes, and fifo empties */ | 907 | /* wait till current packet DMA finishes, and fifo empties */ |
869 | if (ep->bEndpointAddress & USB_DIR_IN) { | 908 | if (ep->bEndpointAddress & USB_DIR_IN) { |
870 | UDC_TXDMA_CFG_REG &= ~mask; | 909 | UDC_TXDMA_CFG_REG = (UDC_TXDMA_CFG_REG & ~mask) | UDC_DMA_REQ; |
871 | 910 | ||
872 | if (req) { | 911 | if (req) { |
873 | finish_in_dma(ep, req, -ECONNRESET); | 912 | finish_in_dma(ep, req, -ECONNRESET); |
@@ -880,7 +919,7 @@ static void dma_channel_release(struct omap_ep *ep) | |||
880 | while (UDC_TXDMA_CFG_REG & mask) | 919 | while (UDC_TXDMA_CFG_REG & mask) |
881 | udelay(10); | 920 | udelay(10); |
882 | } else { | 921 | } else { |
883 | UDC_RXDMA_CFG_REG &= ~mask; | 922 | UDC_RXDMA_CFG_REG = (UDC_RXDMA_CFG_REG & ~mask) | UDC_DMA_REQ; |
884 | 923 | ||
885 | /* dma empties the fifo */ | 924 | /* dma empties the fifo */ |
886 | while (UDC_RXDMA_CFG_REG & mask) | 925 | while (UDC_RXDMA_CFG_REG & mask) |
@@ -997,18 +1036,19 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags) | |||
997 | UDC_IRQ_EN_REG = irq_en; | 1036 | UDC_IRQ_EN_REG = irq_en; |
998 | } | 1037 | } |
999 | 1038 | ||
1000 | /* STATUS is reverse direction */ | 1039 | /* STATUS for zero length DATA stages is |
1001 | UDC_EP_NUM_REG = is_in | 1040 | * always an IN ... even for IN transfers, |
1002 | ? UDC_EP_SEL | 1041 | * a wierd case which seem to stall OMAP. |
1003 | : (UDC_EP_SEL|UDC_EP_DIR); | 1042 | */ |
1043 | UDC_EP_NUM_REG = (UDC_EP_SEL|UDC_EP_DIR); | ||
1004 | UDC_CTRL_REG = UDC_CLR_EP; | 1044 | UDC_CTRL_REG = UDC_CLR_EP; |
1005 | UDC_CTRL_REG = UDC_SET_FIFO_EN; | 1045 | UDC_CTRL_REG = UDC_SET_FIFO_EN; |
1006 | UDC_EP_NUM_REG = udc->ep0_in ? 0 : UDC_EP_DIR; | 1046 | UDC_EP_NUM_REG = UDC_EP_DIR; |
1007 | 1047 | ||
1008 | /* cleanup */ | 1048 | /* cleanup */ |
1009 | udc->ep0_pending = 0; | 1049 | udc->ep0_pending = 0; |
1010 | done(ep, req, 0); | 1050 | done(ep, req, 0); |
1011 | req = 0; | 1051 | req = NULL; |
1012 | 1052 | ||
1013 | /* non-empty DATA stage */ | 1053 | /* non-empty DATA stage */ |
1014 | } else if (is_in) { | 1054 | } else if (is_in) { |
@@ -1029,7 +1069,7 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags) | |||
1029 | (is_in ? next_in_dma : next_out_dma)(ep, req); | 1069 | (is_in ? next_in_dma : next_out_dma)(ep, req); |
1030 | else if (req) { | 1070 | else if (req) { |
1031 | if ((is_in ? write_fifo : read_fifo)(ep, req) == 1) | 1071 | if ((is_in ? write_fifo : read_fifo)(ep, req) == 1) |
1032 | req = 0; | 1072 | req = NULL; |
1033 | deselect_ep(); | 1073 | deselect_ep(); |
1034 | if (!is_in) { | 1074 | if (!is_in) { |
1035 | UDC_CTRL_REG = UDC_SET_FIFO_EN; | 1075 | UDC_CTRL_REG = UDC_SET_FIFO_EN; |
@@ -1041,7 +1081,7 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags) | |||
1041 | 1081 | ||
1042 | irq_wait: | 1082 | irq_wait: |
1043 | /* irq handler advances the queue */ | 1083 | /* irq handler advances the queue */ |
1044 | if (req != 0) | 1084 | if (req != NULL) |
1045 | list_add_tail(&req->queue, &ep->queue); | 1085 | list_add_tail(&req->queue, &ep->queue); |
1046 | spin_unlock_irqrestore(&udc->lock, flags); | 1086 | spin_unlock_irqrestore(&udc->lock, flags); |
1047 | 1087 | ||
@@ -1140,7 +1180,7 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value) | |||
1140 | dma_channel_claim(ep, channel); | 1180 | dma_channel_claim(ep, channel); |
1141 | } else { | 1181 | } else { |
1142 | use_ep(ep, 0); | 1182 | use_ep(ep, 0); |
1143 | UDC_CTRL_REG = UDC_RESET_EP; | 1183 | UDC_CTRL_REG = ep->udc->clr_halt; |
1144 | ep->ackwait = 0; | 1184 | ep->ackwait = 0; |
1145 | if (!(ep->bEndpointAddress & USB_DIR_IN)) { | 1185 | if (!(ep->bEndpointAddress & USB_DIR_IN)) { |
1146 | UDC_CTRL_REG = UDC_SET_FIFO_EN; | 1186 | UDC_CTRL_REG = UDC_SET_FIFO_EN; |
@@ -1238,6 +1278,8 @@ static int can_pullup(struct omap_udc *udc) | |||
1238 | 1278 | ||
1239 | static void pullup_enable(struct omap_udc *udc) | 1279 | static void pullup_enable(struct omap_udc *udc) |
1240 | { | 1280 | { |
1281 | udc->gadget.dev.parent->power.power_state = PMSG_ON; | ||
1282 | udc->gadget.dev.power.power_state = PMSG_ON; | ||
1241 | UDC_SYSCON1_REG |= UDC_PULLUP_EN; | 1283 | UDC_SYSCON1_REG |= UDC_PULLUP_EN; |
1242 | #ifndef CONFIG_USB_OTG | 1284 | #ifndef CONFIG_USB_OTG |
1243 | if (!cpu_is_omap15xx()) | 1285 | if (!cpu_is_omap15xx()) |
@@ -1382,7 +1424,7 @@ static void update_otg(struct omap_udc *udc) | |||
1382 | static void ep0_irq(struct omap_udc *udc, u16 irq_src) | 1424 | static void ep0_irq(struct omap_udc *udc, u16 irq_src) |
1383 | { | 1425 | { |
1384 | struct omap_ep *ep0 = &udc->ep[0]; | 1426 | struct omap_ep *ep0 = &udc->ep[0]; |
1385 | struct omap_req *req = 0; | 1427 | struct omap_req *req = NULL; |
1386 | 1428 | ||
1387 | ep0->irqs++; | 1429 | ep0->irqs++; |
1388 | 1430 | ||
@@ -1438,7 +1480,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) | |||
1438 | if (req) | 1480 | if (req) |
1439 | done(ep0, req, 0); | 1481 | done(ep0, req, 0); |
1440 | } | 1482 | } |
1441 | req = 0; | 1483 | req = NULL; |
1442 | } else if (stat & UDC_STALL) { | 1484 | } else if (stat & UDC_STALL) { |
1443 | UDC_CTRL_REG = UDC_CLR_HALT; | 1485 | UDC_CTRL_REG = UDC_CLR_HALT; |
1444 | UDC_EP_NUM_REG = UDC_EP_DIR; | 1486 | UDC_EP_NUM_REG = UDC_EP_DIR; |
@@ -1511,9 +1553,10 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) | |||
1511 | u.word[3] = UDC_DATA_REG; | 1553 | u.word[3] = UDC_DATA_REG; |
1512 | UDC_EP_NUM_REG = 0; | 1554 | UDC_EP_NUM_REG = 0; |
1513 | } while (UDC_IRQ_SRC_REG & UDC_SETUP); | 1555 | } while (UDC_IRQ_SRC_REG & UDC_SETUP); |
1514 | le16_to_cpus (&u.r.wValue); | 1556 | |
1515 | le16_to_cpus (&u.r.wIndex); | 1557 | #define w_value le16_to_cpup (&u.r.wValue) |
1516 | le16_to_cpus (&u.r.wLength); | 1558 | #define w_index le16_to_cpup (&u.r.wIndex) |
1559 | #define w_length le16_to_cpup (&u.r.wLength) | ||
1517 | 1560 | ||
1518 | /* Delegate almost all control requests to the gadget driver, | 1561 | /* Delegate almost all control requests to the gadget driver, |
1519 | * except for a handful of ch9 status/feature requests that | 1562 | * except for a handful of ch9 status/feature requests that |
@@ -1529,11 +1572,11 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) | |||
1529 | /* udc needs to know when ep != 0 is valid */ | 1572 | /* udc needs to know when ep != 0 is valid */ |
1530 | if (u.r.bRequestType != USB_RECIP_DEVICE) | 1573 | if (u.r.bRequestType != USB_RECIP_DEVICE) |
1531 | goto delegate; | 1574 | goto delegate; |
1532 | if (u.r.wLength != 0) | 1575 | if (w_length != 0) |
1533 | goto do_stall; | 1576 | goto do_stall; |
1534 | udc->ep0_set_config = 1; | 1577 | udc->ep0_set_config = 1; |
1535 | udc->ep0_reset_config = (u.r.wValue == 0); | 1578 | udc->ep0_reset_config = (w_value == 0); |
1536 | VDBG("set config %d\n", u.r.wValue); | 1579 | VDBG("set config %d\n", w_value); |
1537 | 1580 | ||
1538 | /* update udc NOW since gadget driver may start | 1581 | /* update udc NOW since gadget driver may start |
1539 | * queueing requests immediately; clear config | 1582 | * queueing requests immediately; clear config |
@@ -1549,23 +1592,28 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) | |||
1549 | /* clear endpoint halt */ | 1592 | /* clear endpoint halt */ |
1550 | if (u.r.bRequestType != USB_RECIP_ENDPOINT) | 1593 | if (u.r.bRequestType != USB_RECIP_ENDPOINT) |
1551 | goto delegate; | 1594 | goto delegate; |
1552 | if (u.r.wValue != USB_ENDPOINT_HALT | 1595 | if (w_value != USB_ENDPOINT_HALT |
1553 | || u.r.wLength != 0) | 1596 | || w_length != 0) |
1554 | goto do_stall; | 1597 | goto do_stall; |
1555 | ep = &udc->ep[u.r.wIndex & 0xf]; | 1598 | ep = &udc->ep[w_index & 0xf]; |
1556 | if (ep != ep0) { | 1599 | if (ep != ep0) { |
1557 | if (u.r.wIndex & USB_DIR_IN) | 1600 | if (w_index & USB_DIR_IN) |
1558 | ep += 16; | 1601 | ep += 16; |
1559 | if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC | 1602 | if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC |
1560 | || !ep->desc) | 1603 | || !ep->desc) |
1561 | goto do_stall; | 1604 | goto do_stall; |
1562 | use_ep(ep, 0); | 1605 | use_ep(ep, 0); |
1563 | UDC_CTRL_REG = UDC_RESET_EP; | 1606 | UDC_CTRL_REG = udc->clr_halt; |
1564 | ep->ackwait = 0; | 1607 | ep->ackwait = 0; |
1565 | if (!(ep->bEndpointAddress & USB_DIR_IN)) { | 1608 | if (!(ep->bEndpointAddress & USB_DIR_IN)) { |
1566 | UDC_CTRL_REG = UDC_SET_FIFO_EN; | 1609 | UDC_CTRL_REG = UDC_SET_FIFO_EN; |
1567 | ep->ackwait = 1 + ep->double_buf; | 1610 | ep->ackwait = 1 + ep->double_buf; |
1568 | } | 1611 | } |
1612 | /* NOTE: assumes the host behaves sanely, | ||
1613 | * only clearing real halts. Else we may | ||
1614 | * need to kill pending transfers and then | ||
1615 | * restart the queue... very messy for DMA! | ||
1616 | */ | ||
1569 | } | 1617 | } |
1570 | VDBG("%s halt cleared by host\n", ep->name); | 1618 | VDBG("%s halt cleared by host\n", ep->name); |
1571 | goto ep0out_status_stage; | 1619 | goto ep0out_status_stage; |
@@ -1573,11 +1621,11 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) | |||
1573 | /* set endpoint halt */ | 1621 | /* set endpoint halt */ |
1574 | if (u.r.bRequestType != USB_RECIP_ENDPOINT) | 1622 | if (u.r.bRequestType != USB_RECIP_ENDPOINT) |
1575 | goto delegate; | 1623 | goto delegate; |
1576 | if (u.r.wValue != USB_ENDPOINT_HALT | 1624 | if (w_value != USB_ENDPOINT_HALT |
1577 | || u.r.wLength != 0) | 1625 | || w_length != 0) |
1578 | goto do_stall; | 1626 | goto do_stall; |
1579 | ep = &udc->ep[u.r.wIndex & 0xf]; | 1627 | ep = &udc->ep[w_index & 0xf]; |
1580 | if (u.r.wIndex & USB_DIR_IN) | 1628 | if (w_index & USB_DIR_IN) |
1581 | ep += 16; | 1629 | ep += 16; |
1582 | if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC | 1630 | if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC |
1583 | || ep == ep0 || !ep->desc) | 1631 | || ep == ep0 || !ep->desc) |
@@ -1615,13 +1663,13 @@ ep0out_status_stage: | |||
1615 | UDC_CTRL_REG = UDC_SET_FIFO_EN; | 1663 | UDC_CTRL_REG = UDC_SET_FIFO_EN; |
1616 | UDC_EP_NUM_REG = UDC_EP_DIR; | 1664 | UDC_EP_NUM_REG = UDC_EP_DIR; |
1617 | status = 0; | 1665 | status = 0; |
1618 | VDBG("GET_STATUS, interface %d\n", u.r.wIndex); | 1666 | VDBG("GET_STATUS, interface %d\n", w_index); |
1619 | /* next, status stage */ | 1667 | /* next, status stage */ |
1620 | break; | 1668 | break; |
1621 | default: | 1669 | default: |
1622 | delegate: | 1670 | delegate: |
1623 | /* activate the ep0out fifo right away */ | 1671 | /* activate the ep0out fifo right away */ |
1624 | if (!udc->ep0_in && u.r.wLength) { | 1672 | if (!udc->ep0_in && w_length) { |
1625 | UDC_EP_NUM_REG = 0; | 1673 | UDC_EP_NUM_REG = 0; |
1626 | UDC_CTRL_REG = UDC_SET_FIFO_EN; | 1674 | UDC_CTRL_REG = UDC_SET_FIFO_EN; |
1627 | } | 1675 | } |
@@ -1632,7 +1680,11 @@ delegate: | |||
1632 | */ | 1680 | */ |
1633 | VDBG("SETUP %02x.%02x v%04x i%04x l%04x\n", | 1681 | VDBG("SETUP %02x.%02x v%04x i%04x l%04x\n", |
1634 | u.r.bRequestType, u.r.bRequest, | 1682 | u.r.bRequestType, u.r.bRequest, |
1635 | u.r.wValue, u.r.wIndex, u.r.wLength); | 1683 | w_value, w_index, w_length); |
1684 | |||
1685 | #undef w_value | ||
1686 | #undef w_index | ||
1687 | #undef w_length | ||
1636 | 1688 | ||
1637 | /* The gadget driver may return an error here, | 1689 | /* The gadget driver may return an error here, |
1638 | * causing an immediate protocol stall. | 1690 | * causing an immediate protocol stall. |
@@ -2013,7 +2065,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
2013 | udc->softconnect = 1; | 2065 | udc->softconnect = 1; |
2014 | 2066 | ||
2015 | /* hook up the driver */ | 2067 | /* hook up the driver */ |
2016 | driver->driver.bus = 0; | 2068 | driver->driver.bus = NULL; |
2017 | udc->driver = driver; | 2069 | udc->driver = driver; |
2018 | udc->gadget.dev.driver = &driver->driver; | 2070 | udc->gadget.dev.driver = &driver->driver; |
2019 | spin_unlock_irqrestore(&udc->lock, flags); | 2071 | spin_unlock_irqrestore(&udc->lock, flags); |
@@ -2021,8 +2073,8 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
2021 | status = driver->bind (&udc->gadget); | 2073 | status = driver->bind (&udc->gadget); |
2022 | if (status) { | 2074 | if (status) { |
2023 | DBG("bind to %s --> %d\n", driver->driver.name, status); | 2075 | DBG("bind to %s --> %d\n", driver->driver.name, status); |
2024 | udc->gadget.dev.driver = 0; | 2076 | udc->gadget.dev.driver = NULL; |
2025 | udc->driver = 0; | 2077 | udc->driver = NULL; |
2026 | goto done; | 2078 | goto done; |
2027 | } | 2079 | } |
2028 | DBG("bound to driver %s\n", driver->driver.name); | 2080 | DBG("bound to driver %s\n", driver->driver.name); |
@@ -2035,8 +2087,8 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
2035 | if (status < 0) { | 2087 | if (status < 0) { |
2036 | ERR("can't bind to transceiver\n"); | 2088 | ERR("can't bind to transceiver\n"); |
2037 | driver->unbind (&udc->gadget); | 2089 | driver->unbind (&udc->gadget); |
2038 | udc->gadget.dev.driver = 0; | 2090 | udc->gadget.dev.driver = NULL; |
2039 | udc->driver = 0; | 2091 | udc->driver = NULL; |
2040 | goto done; | 2092 | goto done; |
2041 | } | 2093 | } |
2042 | } else { | 2094 | } else { |
@@ -2071,7 +2123,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) | |||
2071 | omap_vbus_session(&udc->gadget, 0); | 2123 | omap_vbus_session(&udc->gadget, 0); |
2072 | 2124 | ||
2073 | if (udc->transceiver) | 2125 | if (udc->transceiver) |
2074 | (void) otg_set_peripheral(udc->transceiver, 0); | 2126 | (void) otg_set_peripheral(udc->transceiver, NULL); |
2075 | else | 2127 | else |
2076 | pullup_disable(udc); | 2128 | pullup_disable(udc); |
2077 | 2129 | ||
@@ -2080,9 +2132,8 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) | |||
2080 | spin_unlock_irqrestore(&udc->lock, flags); | 2132 | spin_unlock_irqrestore(&udc->lock, flags); |
2081 | 2133 | ||
2082 | driver->unbind(&udc->gadget); | 2134 | driver->unbind(&udc->gadget); |
2083 | udc->gadget.dev.driver = 0; | 2135 | udc->gadget.dev.driver = NULL; |
2084 | udc->driver = 0; | 2136 | udc->driver = NULL; |
2085 | |||
2086 | 2137 | ||
2087 | DBG("unregistered driver '%s'\n", driver->driver.name); | 2138 | DBG("unregistered driver '%s'\n", driver->driver.name); |
2088 | return status; | 2139 | return status; |
@@ -2178,14 +2229,14 @@ static int proc_otg_show(struct seq_file *s) | |||
2178 | 2229 | ||
2179 | tmp = OTG_REV_REG; | 2230 | tmp = OTG_REV_REG; |
2180 | trans = USB_TRANSCEIVER_CTRL_REG; | 2231 | trans = USB_TRANSCEIVER_CTRL_REG; |
2181 | seq_printf(s, "OTG rev %d.%d, transceiver_ctrl %03x\n", | 2232 | seq_printf(s, "\nOTG rev %d.%d, transceiver_ctrl %05x\n", |
2182 | tmp >> 4, tmp & 0xf, trans); | 2233 | tmp >> 4, tmp & 0xf, trans); |
2183 | tmp = OTG_SYSCON_1_REG; | 2234 | tmp = OTG_SYSCON_1_REG; |
2184 | seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s," | 2235 | seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s," |
2185 | FOURBITS "\n", tmp, | 2236 | FOURBITS "\n", tmp, |
2186 | trx_mode(USB2_TRX_MODE(tmp), trans & CONF_USB2_UNI_R), | 2237 | trx_mode(USB2_TRX_MODE(tmp), trans & CONF_USB2_UNI_R), |
2187 | trx_mode(USB1_TRX_MODE(tmp), trans & CONF_USB1_UNI_R), | 2238 | trx_mode(USB1_TRX_MODE(tmp), trans & CONF_USB1_UNI_R), |
2188 | (USB0_TRX_MODE(tmp) == 0) | 2239 | (USB0_TRX_MODE(tmp) == 0 && !cpu_is_omap1710()) |
2189 | ? "internal" | 2240 | ? "internal" |
2190 | : trx_mode(USB0_TRX_MODE(tmp), 1), | 2241 | : trx_mode(USB0_TRX_MODE(tmp), 1), |
2191 | (tmp & OTG_IDLE_EN) ? " !otg" : "", | 2242 | (tmp & OTG_IDLE_EN) ? " !otg" : "", |
@@ -2235,6 +2286,7 @@ static int proc_otg_show(struct seq_file *s) | |||
2235 | seq_printf(s, "otg_outctrl %04x" "\n", tmp); | 2286 | seq_printf(s, "otg_outctrl %04x" "\n", tmp); |
2236 | tmp = OTG_TEST_REG; | 2287 | tmp = OTG_TEST_REG; |
2237 | seq_printf(s, "otg_test %04x" "\n", tmp); | 2288 | seq_printf(s, "otg_test %04x" "\n", tmp); |
2289 | return 0; | ||
2238 | } | 2290 | } |
2239 | 2291 | ||
2240 | static int proc_udc_show(struct seq_file *s, void *_) | 2292 | static int proc_udc_show(struct seq_file *s, void *_) |
@@ -2378,7 +2430,7 @@ static int proc_udc_show(struct seq_file *s, void *_) | |||
2378 | 2430 | ||
2379 | static int proc_udc_open(struct inode *inode, struct file *file) | 2431 | static int proc_udc_open(struct inode *inode, struct file *file) |
2380 | { | 2432 | { |
2381 | return single_open(file, proc_udc_show, 0); | 2433 | return single_open(file, proc_udc_show, NULL); |
2382 | } | 2434 | } |
2383 | 2435 | ||
2384 | static struct file_operations proc_ops = { | 2436 | static struct file_operations proc_ops = { |
@@ -2399,7 +2451,7 @@ static void create_proc_file(void) | |||
2399 | 2451 | ||
2400 | static void remove_proc_file(void) | 2452 | static void remove_proc_file(void) |
2401 | { | 2453 | { |
2402 | remove_proc_entry(proc_filename, 0); | 2454 | remove_proc_entry(proc_filename, NULL); |
2403 | } | 2455 | } |
2404 | 2456 | ||
2405 | #else | 2457 | #else |
@@ -2414,6 +2466,10 @@ static inline void remove_proc_file(void) {} | |||
2414 | /* Before this controller can enumerate, we need to pick an endpoint | 2466 | /* Before this controller can enumerate, we need to pick an endpoint |
2415 | * configuration, or "fifo_mode" That involves allocating 2KB of packet | 2467 | * configuration, or "fifo_mode" That involves allocating 2KB of packet |
2416 | * buffer space among the endpoints we'll be operating. | 2468 | * buffer space among the endpoints we'll be operating. |
2469 | * | ||
2470 | * NOTE: as of OMAP 1710 ES2.0, writing a new endpoint config when | ||
2471 | * UDC_SYSCON_1_REG.CFG_LOCK is set can now work. We won't use that | ||
2472 | * capability yet though. | ||
2417 | */ | 2473 | */ |
2418 | static unsigned __init | 2474 | static unsigned __init |
2419 | omap_ep_setup(char *name, u8 addr, u8 type, | 2475 | omap_ep_setup(char *name, u8 addr, u8 type, |
@@ -2505,7 +2561,7 @@ static void omap_udc_release(struct device *dev) | |||
2505 | { | 2561 | { |
2506 | complete(udc->done); | 2562 | complete(udc->done); |
2507 | kfree (udc); | 2563 | kfree (udc); |
2508 | udc = 0; | 2564 | udc = NULL; |
2509 | } | 2565 | } |
2510 | 2566 | ||
2511 | static int __init | 2567 | static int __init |
@@ -2577,23 +2633,33 @@ omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv) | |||
2577 | case 1: | 2633 | case 1: |
2578 | OMAP_BULK_EP("ep1in", USB_DIR_IN | 1); | 2634 | OMAP_BULK_EP("ep1in", USB_DIR_IN | 1); |
2579 | OMAP_BULK_EP("ep2out", USB_DIR_OUT | 2); | 2635 | OMAP_BULK_EP("ep2out", USB_DIR_OUT | 2); |
2636 | OMAP_INT_EP("ep9in", USB_DIR_IN | 9, 16); | ||
2637 | |||
2580 | OMAP_BULK_EP("ep3in", USB_DIR_IN | 3); | 2638 | OMAP_BULK_EP("ep3in", USB_DIR_IN | 3); |
2581 | OMAP_BULK_EP("ep4out", USB_DIR_OUT | 4); | 2639 | OMAP_BULK_EP("ep4out", USB_DIR_OUT | 4); |
2640 | OMAP_INT_EP("ep10in", USB_DIR_IN | 10, 16); | ||
2582 | 2641 | ||
2583 | OMAP_BULK_EP("ep5in", USB_DIR_IN | 5); | 2642 | OMAP_BULK_EP("ep5in", USB_DIR_IN | 5); |
2584 | OMAP_BULK_EP("ep5out", USB_DIR_OUT | 5); | 2643 | OMAP_BULK_EP("ep5out", USB_DIR_OUT | 5); |
2644 | OMAP_INT_EP("ep11in", USB_DIR_IN | 11, 16); | ||
2645 | |||
2585 | OMAP_BULK_EP("ep6in", USB_DIR_IN | 6); | 2646 | OMAP_BULK_EP("ep6in", USB_DIR_IN | 6); |
2586 | OMAP_BULK_EP("ep6out", USB_DIR_OUT | 6); | 2647 | OMAP_BULK_EP("ep6out", USB_DIR_OUT | 6); |
2648 | OMAP_INT_EP("ep12in", USB_DIR_IN | 12, 16); | ||
2587 | 2649 | ||
2588 | OMAP_BULK_EP("ep7in", USB_DIR_IN | 7); | 2650 | OMAP_BULK_EP("ep7in", USB_DIR_IN | 7); |
2589 | OMAP_BULK_EP("ep7out", USB_DIR_OUT | 7); | 2651 | OMAP_BULK_EP("ep7out", USB_DIR_OUT | 7); |
2652 | OMAP_INT_EP("ep13in", USB_DIR_IN | 13, 16); | ||
2653 | OMAP_INT_EP("ep13out", USB_DIR_OUT | 13, 16); | ||
2654 | |||
2590 | OMAP_BULK_EP("ep8in", USB_DIR_IN | 8); | 2655 | OMAP_BULK_EP("ep8in", USB_DIR_IN | 8); |
2591 | OMAP_BULK_EP("ep8out", USB_DIR_OUT | 8); | 2656 | OMAP_BULK_EP("ep8out", USB_DIR_OUT | 8); |
2657 | OMAP_INT_EP("ep14in", USB_DIR_IN | 14, 16); | ||
2658 | OMAP_INT_EP("ep14out", USB_DIR_OUT | 14, 16); | ||
2659 | |||
2660 | OMAP_BULK_EP("ep15in", USB_DIR_IN | 15); | ||
2661 | OMAP_BULK_EP("ep15out", USB_DIR_OUT | 15); | ||
2592 | 2662 | ||
2593 | OMAP_INT_EP("ep9in", USB_DIR_IN | 9, 16); | ||
2594 | OMAP_INT_EP("ep10out", USB_DIR_IN | 10, 16); | ||
2595 | OMAP_INT_EP("ep11in", USB_DIR_IN | 9, 16); | ||
2596 | OMAP_INT_EP("ep12out", USB_DIR_IN | 10, 16); | ||
2597 | break; | 2663 | break; |
2598 | 2664 | ||
2599 | #ifdef USE_ISO | 2665 | #ifdef USE_ISO |
@@ -2640,8 +2706,8 @@ static int __init omap_udc_probe(struct device *dev) | |||
2640 | struct platform_device *odev = to_platform_device(dev); | 2706 | struct platform_device *odev = to_platform_device(dev); |
2641 | int status = -ENODEV; | 2707 | int status = -ENODEV; |
2642 | int hmc; | 2708 | int hmc; |
2643 | struct otg_transceiver *xceiv = 0; | 2709 | struct otg_transceiver *xceiv = NULL; |
2644 | const char *type = 0; | 2710 | const char *type = NULL; |
2645 | struct omap_usb_config *config = dev->platform_data; | 2711 | struct omap_usb_config *config = dev->platform_data; |
2646 | 2712 | ||
2647 | /* NOTE: "knows" the order of the resources! */ | 2713 | /* NOTE: "knows" the order of the resources! */ |
@@ -2676,54 +2742,78 @@ static int __init omap_udc_probe(struct device *dev) | |||
2676 | FUNC_MUX_CTRL_0_REG = tmp; | 2742 | FUNC_MUX_CTRL_0_REG = tmp; |
2677 | } | 2743 | } |
2678 | } else { | 2744 | } else { |
2745 | /* The transceiver may package some GPIO logic or handle | ||
2746 | * loopback and/or transceiverless setup; if we find one, | ||
2747 | * use it. Except for OTG, we don't _need_ to talk to one; | ||
2748 | * but not having one probably means no VBUS detection. | ||
2749 | */ | ||
2750 | xceiv = otg_get_transceiver(); | ||
2751 | if (xceiv) | ||
2752 | type = xceiv->label; | ||
2753 | else if (config->otg) { | ||
2754 | DBG("OTG requires external transceiver!\n"); | ||
2755 | goto cleanup0; | ||
2756 | } | ||
2757 | |||
2679 | hmc = HMC_1610; | 2758 | hmc = HMC_1610; |
2680 | switch (hmc) { | 2759 | switch (hmc) { |
2760 | case 0: /* POWERUP DEFAULT == 0 */ | ||
2761 | case 4: | ||
2762 | case 12: | ||
2763 | case 20: | ||
2764 | if (!cpu_is_omap1710()) { | ||
2765 | type = "integrated"; | ||
2766 | break; | ||
2767 | } | ||
2768 | /* FALL THROUGH */ | ||
2681 | case 3: | 2769 | case 3: |
2682 | case 11: | 2770 | case 11: |
2683 | case 16: | 2771 | case 16: |
2684 | case 19: | 2772 | case 19: |
2685 | case 25: | 2773 | case 25: |
2686 | xceiv = otg_get_transceiver(); | ||
2687 | if (!xceiv) { | 2774 | if (!xceiv) { |
2688 | DBG("external transceiver not registered!\n"); | 2775 | DBG("external transceiver not registered!\n"); |
2689 | if (config->otg) | 2776 | type = "unknown"; |
2690 | goto cleanup0; | 2777 | } |
2691 | type = "(unknown external)"; | ||
2692 | } else | ||
2693 | type = xceiv->label; | ||
2694 | break; | ||
2695 | case 0: /* POWERUP DEFAULT == 0 */ | ||
2696 | case 4: | ||
2697 | case 12: | ||
2698 | case 20: | ||
2699 | type = "INTEGRATED"; | ||
2700 | break; | 2778 | break; |
2701 | case 21: /* internal loopback */ | 2779 | case 21: /* internal loopback */ |
2702 | type = "(loopback)"; | 2780 | type = "loopback"; |
2703 | break; | 2781 | break; |
2704 | case 14: /* transceiverless */ | 2782 | case 14: /* transceiverless */ |
2705 | type = "(none)"; | 2783 | if (cpu_is_omap1710()) |
2784 | goto bad_on_1710; | ||
2785 | /* FALL THROUGH */ | ||
2786 | case 13: | ||
2787 | case 15: | ||
2788 | type = "no"; | ||
2706 | break; | 2789 | break; |
2707 | 2790 | ||
2708 | default: | 2791 | default: |
2792 | bad_on_1710: | ||
2709 | ERR("unrecognized UDC HMC mode %d\n", hmc); | 2793 | ERR("unrecognized UDC HMC mode %d\n", hmc); |
2710 | return -ENODEV; | 2794 | goto cleanup0; |
2711 | } | 2795 | } |
2712 | } | 2796 | } |
2713 | INFO("hmc mode %d, transceiver %s\n", hmc, type); | 2797 | INFO("hmc mode %d, %s transceiver\n", hmc, type); |
2714 | 2798 | ||
2715 | /* a "gadget" abstracts/virtualizes the controller */ | 2799 | /* a "gadget" abstracts/virtualizes the controller */ |
2716 | status = omap_udc_setup(odev, xceiv); | 2800 | status = omap_udc_setup(odev, xceiv); |
2717 | if (status) { | 2801 | if (status) { |
2718 | goto cleanup0; | 2802 | goto cleanup0; |
2719 | } | 2803 | } |
2720 | xceiv = 0; | 2804 | xceiv = NULL; |
2721 | // "udc" is now valid | 2805 | // "udc" is now valid |
2722 | pullup_disable(udc); | 2806 | pullup_disable(udc); |
2723 | #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) | 2807 | #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) |
2724 | udc->gadget.is_otg = (config->otg != 0); | 2808 | udc->gadget.is_otg = (config->otg != 0); |
2725 | #endif | 2809 | #endif |
2726 | 2810 | ||
2811 | /* starting with omap1710 es2.0, clear toggle is a separate bit */ | ||
2812 | if (UDC_REV_REG >= 0x61) | ||
2813 | udc->clr_halt = UDC_RESET_EP | UDC_CLRDATA_TOGGLE; | ||
2814 | else | ||
2815 | udc->clr_halt = UDC_RESET_EP; | ||
2816 | |||
2727 | /* USB general purpose IRQ: ep0, state changes, dma, etc */ | 2817 | /* USB general purpose IRQ: ep0, state changes, dma, etc */ |
2728 | status = request_irq(odev->resource[1].start, omap_udc_irq, | 2818 | status = request_irq(odev->resource[1].start, omap_udc_irq, |
2729 | SA_SAMPLE_RANDOM, driver_name, udc); | 2819 | SA_SAMPLE_RANDOM, driver_name, udc); |
@@ -2765,7 +2855,7 @@ cleanup2: | |||
2765 | 2855 | ||
2766 | cleanup1: | 2856 | cleanup1: |
2767 | kfree (udc); | 2857 | kfree (udc); |
2768 | udc = 0; | 2858 | udc = NULL; |
2769 | 2859 | ||
2770 | cleanup0: | 2860 | cleanup0: |
2771 | if (xceiv) | 2861 | if (xceiv) |
@@ -2788,7 +2878,7 @@ static int __exit omap_udc_remove(struct device *dev) | |||
2788 | pullup_disable(udc); | 2878 | pullup_disable(udc); |
2789 | if (udc->transceiver) { | 2879 | if (udc->transceiver) { |
2790 | put_device(udc->transceiver->dev); | 2880 | put_device(udc->transceiver->dev); |
2791 | udc->transceiver = 0; | 2881 | udc->transceiver = NULL; |
2792 | } | 2882 | } |
2793 | UDC_SYSCON1_REG = 0; | 2883 | UDC_SYSCON1_REG = 0; |
2794 | 2884 | ||
@@ -2809,13 +2899,32 @@ static int __exit omap_udc_remove(struct device *dev) | |||
2809 | return 0; | 2899 | return 0; |
2810 | } | 2900 | } |
2811 | 2901 | ||
2812 | static int omap_udc_suspend(struct device *dev, pm_message_t state, u32 level) | 2902 | /* suspend/resume/wakeup from sysfs (echo > power/state) or when the |
2903 | * system is forced into deep sleep | ||
2904 | * | ||
2905 | * REVISIT we should probably reject suspend requests when there's a host | ||
2906 | * session active, rather than disconnecting, at least on boards that can | ||
2907 | * report VBUS irqs (UDC_DEVSTAT_REG.UDC_ATT). And in any case, we need to | ||
2908 | * make host resumes and VBUS detection trigger OMAP wakeup events; that | ||
2909 | * may involve talking to an external transceiver (e.g. isp1301). | ||
2910 | */ | ||
2911 | static int omap_udc_suspend(struct device *dev, pm_message_t message, u32 level) | ||
2813 | { | 2912 | { |
2814 | if (level != 0) | 2913 | u32 devstat; |
2914 | |||
2915 | if (level != SUSPEND_POWER_DOWN) | ||
2815 | return 0; | 2916 | return 0; |
2917 | devstat = UDC_DEVSTAT_REG; | ||
2918 | |||
2919 | /* we're requesting 48 MHz clock if the pullup is enabled | ||
2920 | * (== we're attached to the host) and we're not suspended, | ||
2921 | * which would prevent entry to deep sleep... | ||
2922 | */ | ||
2923 | if ((devstat & UDC_ATT) != 0 && (devstat & UDC_SUS) == 0) { | ||
2924 | WARN("session active; suspend requires disconnect\n"); | ||
2925 | omap_pullup(&udc->gadget, 0); | ||
2926 | } | ||
2816 | 2927 | ||
2817 | DBG("suspend, state %d\n", state); | ||
2818 | omap_pullup(&udc->gadget, 0); | ||
2819 | udc->gadget.dev.power.power_state = PMSG_SUSPEND; | 2928 | udc->gadget.dev.power.power_state = PMSG_SUSPEND; |
2820 | udc->gadget.dev.parent->power.power_state = PMSG_SUSPEND; | 2929 | udc->gadget.dev.parent->power.power_state = PMSG_SUSPEND; |
2821 | return 0; | 2930 | return 0; |
@@ -2823,7 +2932,7 @@ static int omap_udc_suspend(struct device *dev, pm_message_t state, u32 level) | |||
2823 | 2932 | ||
2824 | static int omap_udc_resume(struct device *dev, u32 level) | 2933 | static int omap_udc_resume(struct device *dev, u32 level) |
2825 | { | 2934 | { |
2826 | if (level != 0) | 2935 | if (level != RESUME_POWER_ON) |
2827 | return 0; | 2936 | return 0; |
2828 | 2937 | ||
2829 | DBG("resume + wakeup/SRP\n"); | 2938 | DBG("resume + wakeup/SRP\n"); |
diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h index c9e68541622c..652ee4627344 100644 --- a/drivers/usb/gadget/omap_udc.h +++ b/drivers/usb/gadget/omap_udc.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #define UDC_CTRL_REG UDC_REG(0x0C) /* Endpoint control */ | 20 | #define UDC_CTRL_REG UDC_REG(0x0C) /* Endpoint control */ |
21 | # define UDC_CLR_HALT (1 << 7) | 21 | # define UDC_CLR_HALT (1 << 7) |
22 | # define UDC_SET_HALT (1 << 6) | 22 | # define UDC_SET_HALT (1 << 6) |
23 | # define UDC_CLRDATA_TOGGLE (1 << 3) | ||
23 | # define UDC_SET_FIFO_EN (1 << 2) | 24 | # define UDC_SET_FIFO_EN (1 << 2) |
24 | # define UDC_CLR_EP (1 << 1) | 25 | # define UDC_CLR_EP (1 << 1) |
25 | # define UDC_RESET_EP (1 << 0) | 26 | # define UDC_RESET_EP (1 << 0) |
@@ -99,6 +100,7 @@ | |||
99 | 100 | ||
100 | /* DMA configuration registers: up to three channels in each direction. */ | 101 | /* DMA configuration registers: up to three channels in each direction. */ |
101 | #define UDC_RXDMA_CFG_REG UDC_REG(0x40) /* 3 eps for RX DMA */ | 102 | #define UDC_RXDMA_CFG_REG UDC_REG(0x40) /* 3 eps for RX DMA */ |
103 | # define UDC_DMA_REQ (1 << 12) | ||
102 | #define UDC_TXDMA_CFG_REG UDC_REG(0x44) /* 3 eps for TX DMA */ | 104 | #define UDC_TXDMA_CFG_REG UDC_REG(0x44) /* 3 eps for TX DMA */ |
103 | #define UDC_DATA_DMA_REG UDC_REG(0x48) /* rx/tx fifo addr */ | 105 | #define UDC_DATA_DMA_REG UDC_REG(0x48) /* rx/tx fifo addr */ |
104 | 106 | ||
@@ -162,6 +164,7 @@ struct omap_udc { | |||
162 | spinlock_t lock; | 164 | spinlock_t lock; |
163 | struct omap_ep ep[32]; | 165 | struct omap_ep ep[32]; |
164 | u16 devstat; | 166 | u16 devstat; |
167 | u16 clr_halt; | ||
165 | struct otg_transceiver *transceiver; | 168 | struct otg_transceiver *transceiver; |
166 | struct list_head iso; | 169 | struct list_head iso; |
167 | unsigned softconnect:1; | 170 | unsigned softconnect:1; |
@@ -171,7 +174,6 @@ struct omap_udc { | |||
171 | unsigned ep0_set_config:1; | 174 | unsigned ep0_set_config:1; |
172 | unsigned ep0_reset_config:1; | 175 | unsigned ep0_reset_config:1; |
173 | unsigned ep0_setup:1; | 176 | unsigned ep0_setup:1; |
174 | |||
175 | struct completion *done; | 177 | struct completion *done; |
176 | }; | 178 | }; |
177 | 179 | ||
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index b8b4524ed746..6a0b957af335 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/usb/gadget/pxa2xx_udc.c | 2 | * linux/drivers/usb/gadget/pxa2xx_udc.c |
3 | * Intel PXA2xx and IXP4xx on-chip full speed USB device controllers | 3 | * Intel PXA25x and IXP4xx on-chip full speed USB device controllers |
4 | * | 4 | * |
5 | * Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker) | 5 | * Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker) |
6 | * Copyright (C) 2003 Robert Schwebel, Pengutronix | 6 | * Copyright (C) 2003 Robert Schwebel, Pengutronix |
@@ -63,7 +63,7 @@ | |||
63 | 63 | ||
64 | 64 | ||
65 | /* | 65 | /* |
66 | * This driver handles the USB Device Controller (UDC) in Intel's PXA 2xx | 66 | * This driver handles the USB Device Controller (UDC) in Intel's PXA 25x |
67 | * series processors. The UDC for the IXP 4xx series is very similar. | 67 | * series processors. The UDC for the IXP 4xx series is very similar. |
68 | * There are fifteen endpoints, in addition to ep0. | 68 | * There are fifteen endpoints, in addition to ep0. |
69 | * | 69 | * |
@@ -79,8 +79,8 @@ | |||
79 | * pxa250 a0/a1 b0/b1/b2 sure act like they're still there. | 79 | * pxa250 a0/a1 b0/b1/b2 sure act like they're still there. |
80 | */ | 80 | */ |
81 | 81 | ||
82 | #define DRIVER_VERSION "14-Dec-2003" | 82 | #define DRIVER_VERSION "4-May-2005" |
83 | #define DRIVER_DESC "PXA 2xx USB Device Controller driver" | 83 | #define DRIVER_DESC "PXA 25x USB Device Controller driver" |
84 | 84 | ||
85 | 85 | ||
86 | static const char driver_name [] = "pxa2xx_udc"; | 86 | static const char driver_name [] = "pxa2xx_udc"; |
@@ -290,6 +290,7 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep, | |||
290 | static int pxa2xx_ep_disable (struct usb_ep *_ep) | 290 | static int pxa2xx_ep_disable (struct usb_ep *_ep) |
291 | { | 291 | { |
292 | struct pxa2xx_ep *ep; | 292 | struct pxa2xx_ep *ep; |
293 | unsigned long flags; | ||
293 | 294 | ||
294 | ep = container_of (_ep, struct pxa2xx_ep, ep); | 295 | ep = container_of (_ep, struct pxa2xx_ep, ep); |
295 | if (!_ep || !ep->desc) { | 296 | if (!_ep || !ep->desc) { |
@@ -297,6 +298,8 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep) | |||
297 | _ep ? ep->ep.name : NULL); | 298 | _ep ? ep->ep.name : NULL); |
298 | return -EINVAL; | 299 | return -EINVAL; |
299 | } | 300 | } |
301 | local_irq_save(flags); | ||
302 | |||
300 | nuke (ep, -ESHUTDOWN); | 303 | nuke (ep, -ESHUTDOWN); |
301 | 304 | ||
302 | #ifdef USE_DMA | 305 | #ifdef USE_DMA |
@@ -313,6 +316,7 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep) | |||
313 | ep->desc = NULL; | 316 | ep->desc = NULL; |
314 | ep->stopped = 1; | 317 | ep->stopped = 1; |
315 | 318 | ||
319 | local_irq_restore(flags); | ||
316 | DBG(DBG_VERBOSE, "%s disabled\n", _ep->name); | 320 | DBG(DBG_VERBOSE, "%s disabled\n", _ep->name); |
317 | return 0; | 321 | return 0; |
318 | } | 322 | } |
@@ -971,10 +975,10 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags) | |||
971 | kick_dma(ep, req); | 975 | kick_dma(ep, req); |
972 | #endif | 976 | #endif |
973 | /* can the FIFO can satisfy the request immediately? */ | 977 | /* can the FIFO can satisfy the request immediately? */ |
974 | } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0 | 978 | } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0) { |
975 | && (*ep->reg_udccs & UDCCS_BI_TFS) != 0 | 979 | if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0 |
976 | && write_fifo(ep, req)) { | 980 | && write_fifo(ep, req)) |
977 | req = NULL; | 981 | req = NULL; |
978 | } else if ((*ep->reg_udccs & UDCCS_BO_RFS) != 0 | 982 | } else if ((*ep->reg_udccs & UDCCS_BO_RFS) != 0 |
979 | && read_fifo(ep, req)) { | 983 | && read_fifo(ep, req)) { |
980 | req = NULL; | 984 | req = NULL; |
@@ -1290,7 +1294,7 @@ udc_proc_read(char *page, char **start, off_t off, int count, | |||
1290 | "%s version: %s\nGadget driver: %s\nHost %s\n\n", | 1294 | "%s version: %s\nGadget driver: %s\nHost %s\n\n", |
1291 | driver_name, DRIVER_VERSION SIZE_STR DMASTR, | 1295 | driver_name, DRIVER_VERSION SIZE_STR DMASTR, |
1292 | dev->driver ? dev->driver->driver.name : "(none)", | 1296 | dev->driver ? dev->driver->driver.name : "(none)", |
1293 | is_usb_connected() ? "full speed" : "disconnected"); | 1297 | is_vbus_present() ? "full speed" : "disconnected"); |
1294 | size -= t; | 1298 | size -= t; |
1295 | next += t; | 1299 | next += t; |
1296 | 1300 | ||
@@ -1339,7 +1343,7 @@ udc_proc_read(char *page, char **start, off_t off, int count, | |||
1339 | next += t; | 1343 | next += t; |
1340 | } | 1344 | } |
1341 | 1345 | ||
1342 | if (!is_usb_connected() || !dev->driver) | 1346 | if (!is_vbus_present() || !dev->driver) |
1343 | goto done; | 1347 | goto done; |
1344 | 1348 | ||
1345 | t = scnprintf(next, size, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n", | 1349 | t = scnprintf(next, size, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n", |
@@ -1454,7 +1458,7 @@ static void udc_disable(struct pxa2xx_udc *dev) | |||
1454 | UFNRH = UFNRH_SIM; | 1458 | UFNRH = UFNRH_SIM; |
1455 | 1459 | ||
1456 | /* if hardware supports it, disconnect from usb */ | 1460 | /* if hardware supports it, disconnect from usb */ |
1457 | make_usb_disappear(); | 1461 | pullup_off(); |
1458 | 1462 | ||
1459 | udc_clear_mask_UDCCR(UDCCR_UDE); | 1463 | udc_clear_mask_UDCCR(UDCCR_UDE); |
1460 | 1464 | ||
@@ -1567,7 +1571,7 @@ static void udc_enable (struct pxa2xx_udc *dev) | |||
1567 | UICR0 &= ~UICR0_IM0; | 1571 | UICR0 &= ~UICR0_IM0; |
1568 | 1572 | ||
1569 | /* if hardware supports it, pullup D+ and wait for reset */ | 1573 | /* if hardware supports it, pullup D+ and wait for reset */ |
1570 | let_usb_appear(); | 1574 | pullup_on(); |
1571 | } | 1575 | } |
1572 | 1576 | ||
1573 | 1577 | ||
@@ -2052,10 +2056,10 @@ pxa2xx_udc_irq(int irq, void *_dev, struct pt_regs *r) | |||
2052 | if (unlikely(udccr & UDCCR_SUSIR)) { | 2056 | if (unlikely(udccr & UDCCR_SUSIR)) { |
2053 | udc_ack_int_UDCCR(UDCCR_SUSIR); | 2057 | udc_ack_int_UDCCR(UDCCR_SUSIR); |
2054 | handled = 1; | 2058 | handled = 1; |
2055 | DBG(DBG_VERBOSE, "USB suspend%s\n", is_usb_connected() | 2059 | DBG(DBG_VERBOSE, "USB suspend%s\n", is_vbus_present() |
2056 | ? "" : "+disconnect"); | 2060 | ? "" : "+disconnect"); |
2057 | 2061 | ||
2058 | if (!is_usb_connected()) | 2062 | if (!is_vbus_present()) |
2059 | stop_activity(dev, dev->driver); | 2063 | stop_activity(dev, dev->driver); |
2060 | else if (dev->gadget.speed != USB_SPEED_UNKNOWN | 2064 | else if (dev->gadget.speed != USB_SPEED_UNKNOWN |
2061 | && dev->driver | 2065 | && dev->driver |
@@ -2073,7 +2077,7 @@ pxa2xx_udc_irq(int irq, void *_dev, struct pt_regs *r) | |||
2073 | if (dev->gadget.speed != USB_SPEED_UNKNOWN | 2077 | if (dev->gadget.speed != USB_SPEED_UNKNOWN |
2074 | && dev->driver | 2078 | && dev->driver |
2075 | && dev->driver->resume | 2079 | && dev->driver->resume |
2076 | && is_usb_connected()) | 2080 | && is_vbus_present()) |
2077 | dev->driver->resume(&dev->gadget); | 2081 | dev->driver->resume(&dev->gadget); |
2078 | } | 2082 | } |
2079 | 2083 | ||
@@ -2509,7 +2513,7 @@ static int __init pxa2xx_udc_probe(struct device *_dev) | |||
2509 | udc_disable(dev); | 2513 | udc_disable(dev); |
2510 | udc_reinit(dev); | 2514 | udc_reinit(dev); |
2511 | 2515 | ||
2512 | dev->vbus = is_usb_connected(); | 2516 | dev->vbus = is_vbus_present(); |
2513 | 2517 | ||
2514 | /* irq setup after old hardware state is cleaned up */ | 2518 | /* irq setup after old hardware state is cleaned up */ |
2515 | retval = request_irq(IRQ_USB, pxa2xx_udc_irq, | 2519 | retval = request_irq(IRQ_USB, pxa2xx_udc_irq, |
@@ -2555,6 +2559,12 @@ lubbock_fail0: | |||
2555 | 2559 | ||
2556 | return 0; | 2560 | return 0; |
2557 | } | 2561 | } |
2562 | |||
2563 | static void pxa2xx_udc_shutdown(struct device *_dev) | ||
2564 | { | ||
2565 | pullup_off(); | ||
2566 | } | ||
2567 | |||
2558 | static int __exit pxa2xx_udc_remove(struct device *_dev) | 2568 | static int __exit pxa2xx_udc_remove(struct device *_dev) |
2559 | { | 2569 | { |
2560 | struct pxa2xx_udc *dev = dev_get_drvdata(_dev); | 2570 | struct pxa2xx_udc *dev = dev_get_drvdata(_dev); |
@@ -2624,6 +2634,7 @@ static struct device_driver udc_driver = { | |||
2624 | .name = "pxa2xx-udc", | 2634 | .name = "pxa2xx-udc", |
2625 | .bus = &platform_bus_type, | 2635 | .bus = &platform_bus_type, |
2626 | .probe = pxa2xx_udc_probe, | 2636 | .probe = pxa2xx_udc_probe, |
2637 | .shutdown = pxa2xx_udc_shutdown, | ||
2627 | .remove = __exit_p(pxa2xx_udc_remove), | 2638 | .remove = __exit_p(pxa2xx_udc_remove), |
2628 | .suspend = pxa2xx_udc_suspend, | 2639 | .suspend = pxa2xx_udc_suspend, |
2629 | .resume = pxa2xx_udc_resume, | 2640 | .resume = pxa2xx_udc_resume, |
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h index 1f3a7d999da7..d0bc396a85d5 100644 --- a/drivers/usb/gadget/pxa2xx_udc.h +++ b/drivers/usb/gadget/pxa2xx_udc.h | |||
@@ -177,23 +177,23 @@ struct pxa2xx_udc { | |||
177 | 177 | ||
178 | static struct pxa2xx_udc *the_controller; | 178 | static struct pxa2xx_udc *the_controller; |
179 | 179 | ||
180 | /* one GPIO should be used to detect host disconnect */ | 180 | /* one GPIO should be used to detect VBUS from the host */ |
181 | static inline int is_usb_connected(void) | 181 | static inline int is_vbus_present(void) |
182 | { | 182 | { |
183 | if (!the_controller->mach->udc_is_connected) | 183 | if (!the_controller->mach->udc_is_connected) |
184 | return 1; | 184 | return 1; |
185 | return the_controller->mach->udc_is_connected(); | 185 | return the_controller->mach->udc_is_connected(); |
186 | } | 186 | } |
187 | 187 | ||
188 | /* one GPIO should force the host to see this device (or not) */ | 188 | /* one GPIO should control a D+ pullup, so host sees this device (or not) */ |
189 | static inline void make_usb_disappear(void) | 189 | static inline void pullup_off(void) |
190 | { | 190 | { |
191 | if (!the_controller->mach->udc_command) | 191 | if (!the_controller->mach->udc_command) |
192 | return; | 192 | return; |
193 | the_controller->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); | 193 | the_controller->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); |
194 | } | 194 | } |
195 | 195 | ||
196 | static inline void let_usb_appear(void) | 196 | static inline void pullup_on(void) |
197 | { | 197 | { |
198 | if (!the_controller->mach->udc_command) | 198 | if (!the_controller->mach->udc_command) |
199 | return; | 199 | return; |
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 7457268d5f28..06b6eba925b5 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c | |||
@@ -41,6 +41,7 @@ | |||
41 | 41 | ||
42 | 42 | ||
43 | #undef RNDIS_PM | 43 | #undef RNDIS_PM |
44 | #undef RNDIS_WAKEUP | ||
44 | #undef VERBOSE | 45 | #undef VERBOSE |
45 | 46 | ||
46 | #include "rndis.h" | 47 | #include "rndis.h" |
@@ -60,7 +61,7 @@ | |||
60 | } while (0) | 61 | } while (0) |
61 | static int rndis_debug = 0; | 62 | static int rndis_debug = 0; |
62 | 63 | ||
63 | module_param (rndis_debug, bool, 0); | 64 | module_param (rndis_debug, int, 0); |
64 | MODULE_PARM_DESC (rndis_debug, "enable debugging"); | 65 | MODULE_PARM_DESC (rndis_debug, "enable debugging"); |
65 | 66 | ||
66 | #else | 67 | #else |
@@ -78,22 +79,103 @@ static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS]; | |||
78 | static const __le32 rndis_driver_version = __constant_cpu_to_le32 (1); | 79 | static const __le32 rndis_driver_version = __constant_cpu_to_le32 (1); |
79 | 80 | ||
80 | /* Function Prototypes */ | 81 | /* Function Prototypes */ |
81 | static int rndis_init_response (int configNr, rndis_init_msg_type *buf); | ||
82 | static int rndis_query_response (int configNr, rndis_query_msg_type *buf); | ||
83 | static int rndis_set_response (int configNr, rndis_set_msg_type *buf); | ||
84 | static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf); | ||
85 | static int rndis_keepalive_response (int configNr, | ||
86 | rndis_keepalive_msg_type *buf); | ||
87 | |||
88 | static rndis_resp_t *rndis_add_response (int configNr, u32 length); | 82 | static rndis_resp_t *rndis_add_response (int configNr, u32 length); |
89 | 83 | ||
90 | 84 | ||
85 | /* supported OIDs */ | ||
86 | static const u32 oid_supported_list [] = | ||
87 | { | ||
88 | /* the general stuff */ | ||
89 | OID_GEN_SUPPORTED_LIST, | ||
90 | OID_GEN_HARDWARE_STATUS, | ||
91 | OID_GEN_MEDIA_SUPPORTED, | ||
92 | OID_GEN_MEDIA_IN_USE, | ||
93 | OID_GEN_MAXIMUM_FRAME_SIZE, | ||
94 | OID_GEN_LINK_SPEED, | ||
95 | OID_GEN_TRANSMIT_BLOCK_SIZE, | ||
96 | OID_GEN_RECEIVE_BLOCK_SIZE, | ||
97 | OID_GEN_VENDOR_ID, | ||
98 | OID_GEN_VENDOR_DESCRIPTION, | ||
99 | OID_GEN_VENDOR_DRIVER_VERSION, | ||
100 | OID_GEN_CURRENT_PACKET_FILTER, | ||
101 | OID_GEN_MAXIMUM_TOTAL_SIZE, | ||
102 | OID_GEN_MEDIA_CONNECT_STATUS, | ||
103 | OID_GEN_PHYSICAL_MEDIUM, | ||
104 | #if 0 | ||
105 | OID_GEN_RNDIS_CONFIG_PARAMETER, | ||
106 | #endif | ||
107 | |||
108 | /* the statistical stuff */ | ||
109 | OID_GEN_XMIT_OK, | ||
110 | OID_GEN_RCV_OK, | ||
111 | OID_GEN_XMIT_ERROR, | ||
112 | OID_GEN_RCV_ERROR, | ||
113 | OID_GEN_RCV_NO_BUFFER, | ||
114 | #ifdef RNDIS_OPTIONAL_STATS | ||
115 | OID_GEN_DIRECTED_BYTES_XMIT, | ||
116 | OID_GEN_DIRECTED_FRAMES_XMIT, | ||
117 | OID_GEN_MULTICAST_BYTES_XMIT, | ||
118 | OID_GEN_MULTICAST_FRAMES_XMIT, | ||
119 | OID_GEN_BROADCAST_BYTES_XMIT, | ||
120 | OID_GEN_BROADCAST_FRAMES_XMIT, | ||
121 | OID_GEN_DIRECTED_BYTES_RCV, | ||
122 | OID_GEN_DIRECTED_FRAMES_RCV, | ||
123 | OID_GEN_MULTICAST_BYTES_RCV, | ||
124 | OID_GEN_MULTICAST_FRAMES_RCV, | ||
125 | OID_GEN_BROADCAST_BYTES_RCV, | ||
126 | OID_GEN_BROADCAST_FRAMES_RCV, | ||
127 | OID_GEN_RCV_CRC_ERROR, | ||
128 | OID_GEN_TRANSMIT_QUEUE_LENGTH, | ||
129 | #endif /* RNDIS_OPTIONAL_STATS */ | ||
130 | |||
131 | /* mandatory 802.3 */ | ||
132 | /* the general stuff */ | ||
133 | OID_802_3_PERMANENT_ADDRESS, | ||
134 | OID_802_3_CURRENT_ADDRESS, | ||
135 | OID_802_3_MULTICAST_LIST, | ||
136 | OID_802_3_MAC_OPTIONS, | ||
137 | OID_802_3_MAXIMUM_LIST_SIZE, | ||
138 | |||
139 | /* the statistical stuff */ | ||
140 | OID_802_3_RCV_ERROR_ALIGNMENT, | ||
141 | OID_802_3_XMIT_ONE_COLLISION, | ||
142 | OID_802_3_XMIT_MORE_COLLISIONS, | ||
143 | #ifdef RNDIS_OPTIONAL_STATS | ||
144 | OID_802_3_XMIT_DEFERRED, | ||
145 | OID_802_3_XMIT_MAX_COLLISIONS, | ||
146 | OID_802_3_RCV_OVERRUN, | ||
147 | OID_802_3_XMIT_UNDERRUN, | ||
148 | OID_802_3_XMIT_HEARTBEAT_FAILURE, | ||
149 | OID_802_3_XMIT_TIMES_CRS_LOST, | ||
150 | OID_802_3_XMIT_LATE_COLLISIONS, | ||
151 | #endif /* RNDIS_OPTIONAL_STATS */ | ||
152 | |||
153 | #ifdef RNDIS_PM | ||
154 | /* PM and wakeup are mandatory for USB: */ | ||
155 | |||
156 | /* power management */ | ||
157 | OID_PNP_CAPABILITIES, | ||
158 | OID_PNP_QUERY_POWER, | ||
159 | OID_PNP_SET_POWER, | ||
160 | |||
161 | #ifdef RNDIS_WAKEUP | ||
162 | /* wake up host */ | ||
163 | OID_PNP_ENABLE_WAKE_UP, | ||
164 | OID_PNP_ADD_WAKE_UP_PATTERN, | ||
165 | OID_PNP_REMOVE_WAKE_UP_PATTERN, | ||
166 | #endif /* RNDIS_WAKEUP */ | ||
167 | #endif /* RNDIS_PM */ | ||
168 | }; | ||
169 | |||
170 | |||
91 | /* NDIS Functions */ | 171 | /* NDIS Functions */ |
92 | static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | 172 | static int |
173 | gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | ||
174 | rndis_resp_t *r) | ||
93 | { | 175 | { |
94 | int retval = -ENOTSUPP; | 176 | int retval = -ENOTSUPP; |
95 | u32 length = 0; | 177 | u32 length = 4; /* usually */ |
96 | __le32 *tmp; | 178 | __le32 *outbuf; |
97 | int i, count; | 179 | int i, count; |
98 | rndis_query_cmplt_type *resp; | 180 | rndis_query_cmplt_type *resp; |
99 | 181 | ||
@@ -101,7 +183,22 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
101 | resp = (rndis_query_cmplt_type *) r->buf; | 183 | resp = (rndis_query_cmplt_type *) r->buf; |
102 | 184 | ||
103 | if (!resp) return -ENOMEM; | 185 | if (!resp) return -ENOMEM; |
104 | 186 | ||
187 | if (buf_len && rndis_debug > 1) { | ||
188 | DEBUG("query OID %08x value, len %d:\n", OID, buf_len); | ||
189 | for (i = 0; i < buf_len; i += 16) { | ||
190 | DEBUG ("%03d: %08x %08x %08x %08x\n", i, | ||
191 | le32_to_cpup((__le32 *)&buf[i]), | ||
192 | le32_to_cpup((__le32 *)&buf[i + 4]), | ||
193 | le32_to_cpup((__le32 *)&buf[i + 8]), | ||
194 | le32_to_cpup((__le32 *)&buf[i + 12])); | ||
195 | } | ||
196 | } | ||
197 | |||
198 | /* response goes here, right after the header */ | ||
199 | outbuf = (__le32 *) &resp[1]; | ||
200 | resp->InformationBufferOffset = __constant_cpu_to_le32 (16); | ||
201 | |||
105 | switch (OID) { | 202 | switch (OID) { |
106 | 203 | ||
107 | /* general oids (table 4-1) */ | 204 | /* general oids (table 4-1) */ |
@@ -111,42 +208,36 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
111 | DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__); | 208 | DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__); |
112 | length = sizeof (oid_supported_list); | 209 | length = sizeof (oid_supported_list); |
113 | count = length / sizeof (u32); | 210 | count = length / sizeof (u32); |
114 | tmp = (__le32 *) ((u8 *)resp + 24); | ||
115 | for (i = 0; i < count; i++) | 211 | for (i = 0; i < count; i++) |
116 | tmp[i] = cpu_to_le32 (oid_supported_list[i]); | 212 | outbuf[i] = cpu_to_le32 (oid_supported_list[i]); |
117 | retval = 0; | 213 | retval = 0; |
118 | break; | 214 | break; |
119 | 215 | ||
120 | /* mandatory */ | 216 | /* mandatory */ |
121 | case OID_GEN_HARDWARE_STATUS: | 217 | case OID_GEN_HARDWARE_STATUS: |
122 | DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__); | 218 | DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__); |
123 | length = 4; | ||
124 | /* Bogus question! | 219 | /* Bogus question! |
125 | * Hardware must be ready to receive high level protocols. | 220 | * Hardware must be ready to receive high level protocols. |
126 | * BTW: | 221 | * BTW: |
127 | * reddite ergo quae sunt Caesaris Caesari | 222 | * reddite ergo quae sunt Caesaris Caesari |
128 | * et quae sunt Dei Deo! | 223 | * et quae sunt Dei Deo! |
129 | */ | 224 | */ |
130 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | 225 | *outbuf = __constant_cpu_to_le32 (0); |
131 | retval = 0; | 226 | retval = 0; |
132 | break; | 227 | break; |
133 | 228 | ||
134 | /* mandatory */ | 229 | /* mandatory */ |
135 | case OID_GEN_MEDIA_SUPPORTED: | 230 | case OID_GEN_MEDIA_SUPPORTED: |
136 | DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__); | 231 | DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__); |
137 | length = 4; | 232 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); |
138 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
139 | rndis_per_dev_params [configNr].medium); | ||
140 | retval = 0; | 233 | retval = 0; |
141 | break; | 234 | break; |
142 | 235 | ||
143 | /* mandatory */ | 236 | /* mandatory */ |
144 | case OID_GEN_MEDIA_IN_USE: | 237 | case OID_GEN_MEDIA_IN_USE: |
145 | DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__); | 238 | DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__); |
146 | length = 4; | ||
147 | /* one medium, one transport... (maybe you do it better) */ | 239 | /* one medium, one transport... (maybe you do it better) */ |
148 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 240 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); |
149 | rndis_per_dev_params [configNr].medium); | ||
150 | retval = 0; | 241 | retval = 0; |
151 | break; | 242 | break; |
152 | 243 | ||
@@ -154,25 +245,21 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
154 | case OID_GEN_MAXIMUM_FRAME_SIZE: | 245 | case OID_GEN_MAXIMUM_FRAME_SIZE: |
155 | DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__); | 246 | DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__); |
156 | if (rndis_per_dev_params [configNr].dev) { | 247 | if (rndis_per_dev_params [configNr].dev) { |
157 | length = 4; | 248 | *outbuf = cpu_to_le32 ( |
158 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
159 | rndis_per_dev_params [configNr].dev->mtu); | 249 | rndis_per_dev_params [configNr].dev->mtu); |
160 | retval = 0; | 250 | retval = 0; |
161 | } else { | ||
162 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
163 | retval = 0; | ||
164 | } | 251 | } |
165 | break; | 252 | break; |
166 | 253 | ||
167 | /* mandatory */ | 254 | /* mandatory */ |
168 | case OID_GEN_LINK_SPEED: | 255 | case OID_GEN_LINK_SPEED: |
169 | // DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__); | 256 | if (rndis_debug > 1) |
170 | length = 4; | 257 | DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__); |
171 | if (rndis_per_dev_params [configNr].media_state | 258 | if (rndis_per_dev_params [configNr].media_state |
172 | == NDIS_MEDIA_STATE_DISCONNECTED) | 259 | == NDIS_MEDIA_STATE_DISCONNECTED) |
173 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | 260 | *outbuf = __constant_cpu_to_le32 (0); |
174 | else | 261 | else |
175 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 262 | *outbuf = cpu_to_le32 ( |
176 | rndis_per_dev_params [configNr].speed); | 263 | rndis_per_dev_params [configNr].speed); |
177 | retval = 0; | 264 | retval = 0; |
178 | break; | 265 | break; |
@@ -181,8 +268,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
181 | case OID_GEN_TRANSMIT_BLOCK_SIZE: | 268 | case OID_GEN_TRANSMIT_BLOCK_SIZE: |
182 | DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__); | 269 | DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__); |
183 | if (rndis_per_dev_params [configNr].dev) { | 270 | if (rndis_per_dev_params [configNr].dev) { |
184 | length = 4; | 271 | *outbuf = cpu_to_le32 ( |
185 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
186 | rndis_per_dev_params [configNr].dev->mtu); | 272 | rndis_per_dev_params [configNr].dev->mtu); |
187 | retval = 0; | 273 | retval = 0; |
188 | } | 274 | } |
@@ -192,8 +278,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
192 | case OID_GEN_RECEIVE_BLOCK_SIZE: | 278 | case OID_GEN_RECEIVE_BLOCK_SIZE: |
193 | DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__); | 279 | DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__); |
194 | if (rndis_per_dev_params [configNr].dev) { | 280 | if (rndis_per_dev_params [configNr].dev) { |
195 | length = 4; | 281 | *outbuf = cpu_to_le32 ( |
196 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
197 | rndis_per_dev_params [configNr].dev->mtu); | 282 | rndis_per_dev_params [configNr].dev->mtu); |
198 | retval = 0; | 283 | retval = 0; |
199 | } | 284 | } |
@@ -202,8 +287,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
202 | /* mandatory */ | 287 | /* mandatory */ |
203 | case OID_GEN_VENDOR_ID: | 288 | case OID_GEN_VENDOR_ID: |
204 | DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__); | 289 | DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__); |
205 | length = 4; | 290 | *outbuf = cpu_to_le32 ( |
206 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
207 | rndis_per_dev_params [configNr].vendorID); | 291 | rndis_per_dev_params [configNr].vendorID); |
208 | retval = 0; | 292 | retval = 0; |
209 | break; | 293 | break; |
@@ -212,51 +296,44 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
212 | case OID_GEN_VENDOR_DESCRIPTION: | 296 | case OID_GEN_VENDOR_DESCRIPTION: |
213 | DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__); | 297 | DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__); |
214 | length = strlen (rndis_per_dev_params [configNr].vendorDescr); | 298 | length = strlen (rndis_per_dev_params [configNr].vendorDescr); |
215 | memcpy ((u8 *) resp + 24, | 299 | memcpy (outbuf, |
216 | rndis_per_dev_params [configNr].vendorDescr, length); | 300 | rndis_per_dev_params [configNr].vendorDescr, length); |
217 | retval = 0; | 301 | retval = 0; |
218 | break; | 302 | break; |
219 | 303 | ||
220 | case OID_GEN_VENDOR_DRIVER_VERSION: | 304 | case OID_GEN_VENDOR_DRIVER_VERSION: |
221 | DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__); | 305 | DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__); |
222 | length = 4; | ||
223 | /* Created as LE */ | 306 | /* Created as LE */ |
224 | *((__le32 *) resp + 6) = rndis_driver_version; | 307 | *outbuf = rndis_driver_version; |
225 | retval = 0; | 308 | retval = 0; |
226 | break; | 309 | break; |
227 | 310 | ||
228 | /* mandatory */ | 311 | /* mandatory */ |
229 | case OID_GEN_CURRENT_PACKET_FILTER: | 312 | case OID_GEN_CURRENT_PACKET_FILTER: |
230 | DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__); | 313 | DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__); |
231 | length = 4; | 314 | *outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter); |
232 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
233 | rndis_per_dev_params[configNr].filter); | ||
234 | retval = 0; | 315 | retval = 0; |
235 | break; | 316 | break; |
236 | 317 | ||
237 | /* mandatory */ | 318 | /* mandatory */ |
238 | case OID_GEN_MAXIMUM_TOTAL_SIZE: | 319 | case OID_GEN_MAXIMUM_TOTAL_SIZE: |
239 | DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__); | 320 | DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__); |
240 | length = 4; | 321 | *outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE); |
241 | *((__le32 *) resp + 6) = __constant_cpu_to_le32( | ||
242 | RNDIS_MAX_TOTAL_SIZE); | ||
243 | retval = 0; | 322 | retval = 0; |
244 | break; | 323 | break; |
245 | 324 | ||
246 | /* mandatory */ | 325 | /* mandatory */ |
247 | case OID_GEN_MEDIA_CONNECT_STATUS: | 326 | case OID_GEN_MEDIA_CONNECT_STATUS: |
248 | DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__); | 327 | if (rndis_debug > 1) |
249 | length = 4; | 328 | DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__); |
250 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 329 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
251 | rndis_per_dev_params [configNr] | ||
252 | .media_state); | 330 | .media_state); |
253 | retval = 0; | 331 | retval = 0; |
254 | break; | 332 | break; |
255 | 333 | ||
256 | case OID_GEN_PHYSICAL_MEDIUM: | 334 | case OID_GEN_PHYSICAL_MEDIUM: |
257 | DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__); | 335 | DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__); |
258 | length = 4; | 336 | *outbuf = __constant_cpu_to_le32 (0); |
259 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
260 | retval = 0; | 337 | retval = 0; |
261 | break; | 338 | break; |
262 | 339 | ||
@@ -266,8 +343,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
266 | */ | 343 | */ |
267 | case OID_GEN_MAC_OPTIONS: /* from WinME */ | 344 | case OID_GEN_MAC_OPTIONS: /* from WinME */ |
268 | DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__); | 345 | DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__); |
269 | length = 4; | 346 | *outbuf = __constant_cpu_to_le32( |
270 | *((__le32 *) resp + 6) = __constant_cpu_to_le32( | ||
271 | NDIS_MAC_OPTION_RECEIVE_SERIALIZED | 347 | NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
272 | | NDIS_MAC_OPTION_FULL_DUPLEX); | 348 | | NDIS_MAC_OPTION_FULL_DUPLEX); |
273 | retval = 0; | 349 | retval = 0; |
@@ -277,62 +353,49 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
277 | 353 | ||
278 | /* mandatory */ | 354 | /* mandatory */ |
279 | case OID_GEN_XMIT_OK: | 355 | case OID_GEN_XMIT_OK: |
280 | DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__); | 356 | if (rndis_debug > 1) |
357 | DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__); | ||
281 | if (rndis_per_dev_params [configNr].stats) { | 358 | if (rndis_per_dev_params [configNr].stats) { |
282 | length = 4; | 359 | *outbuf = cpu_to_le32 ( |
283 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
284 | rndis_per_dev_params [configNr].stats->tx_packets - | 360 | rndis_per_dev_params [configNr].stats->tx_packets - |
285 | rndis_per_dev_params [configNr].stats->tx_errors - | 361 | rndis_per_dev_params [configNr].stats->tx_errors - |
286 | rndis_per_dev_params [configNr].stats->tx_dropped); | 362 | rndis_per_dev_params [configNr].stats->tx_dropped); |
287 | retval = 0; | 363 | retval = 0; |
288 | } else { | ||
289 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
290 | retval = 0; | ||
291 | } | 364 | } |
292 | break; | 365 | break; |
293 | 366 | ||
294 | /* mandatory */ | 367 | /* mandatory */ |
295 | case OID_GEN_RCV_OK: | 368 | case OID_GEN_RCV_OK: |
296 | DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__); | 369 | if (rndis_debug > 1) |
370 | DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__); | ||
297 | if (rndis_per_dev_params [configNr].stats) { | 371 | if (rndis_per_dev_params [configNr].stats) { |
298 | length = 4; | 372 | *outbuf = cpu_to_le32 ( |
299 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
300 | rndis_per_dev_params [configNr].stats->rx_packets - | 373 | rndis_per_dev_params [configNr].stats->rx_packets - |
301 | rndis_per_dev_params [configNr].stats->rx_errors - | 374 | rndis_per_dev_params [configNr].stats->rx_errors - |
302 | rndis_per_dev_params [configNr].stats->rx_dropped); | 375 | rndis_per_dev_params [configNr].stats->rx_dropped); |
303 | retval = 0; | 376 | retval = 0; |
304 | } else { | ||
305 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
306 | retval = 0; | ||
307 | } | 377 | } |
308 | break; | 378 | break; |
309 | 379 | ||
310 | /* mandatory */ | 380 | /* mandatory */ |
311 | case OID_GEN_XMIT_ERROR: | 381 | case OID_GEN_XMIT_ERROR: |
312 | DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__); | 382 | if (rndis_debug > 1) |
383 | DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__); | ||
313 | if (rndis_per_dev_params [configNr].stats) { | 384 | if (rndis_per_dev_params [configNr].stats) { |
314 | length = 4; | 385 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
315 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
316 | rndis_per_dev_params [configNr] | ||
317 | .stats->tx_errors); | 386 | .stats->tx_errors); |
318 | retval = 0; | 387 | retval = 0; |
319 | } else { | ||
320 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
321 | retval = 0; | ||
322 | } | 388 | } |
323 | break; | 389 | break; |
324 | 390 | ||
325 | /* mandatory */ | 391 | /* mandatory */ |
326 | case OID_GEN_RCV_ERROR: | 392 | case OID_GEN_RCV_ERROR: |
327 | DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__); | 393 | if (rndis_debug > 1) |
394 | DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__); | ||
328 | if (rndis_per_dev_params [configNr].stats) { | 395 | if (rndis_per_dev_params [configNr].stats) { |
329 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 396 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
330 | rndis_per_dev_params [configNr] | ||
331 | .stats->rx_errors); | 397 | .stats->rx_errors); |
332 | retval = 0; | 398 | retval = 0; |
333 | } else { | ||
334 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
335 | retval = 0; | ||
336 | } | 399 | } |
337 | break; | 400 | break; |
338 | 401 | ||
@@ -340,13 +403,9 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
340 | case OID_GEN_RCV_NO_BUFFER: | 403 | case OID_GEN_RCV_NO_BUFFER: |
341 | DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__); | 404 | DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__); |
342 | if (rndis_per_dev_params [configNr].stats) { | 405 | if (rndis_per_dev_params [configNr].stats) { |
343 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 406 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
344 | rndis_per_dev_params [configNr] | ||
345 | .stats->rx_dropped); | 407 | .stats->rx_dropped); |
346 | retval = 0; | 408 | retval = 0; |
347 | } else { | ||
348 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
349 | retval = 0; | ||
350 | } | 409 | } |
351 | break; | 410 | break; |
352 | 411 | ||
@@ -359,8 +418,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
359 | * divided by weight of Alpha Centauri | 418 | * divided by weight of Alpha Centauri |
360 | */ | 419 | */ |
361 | if (rndis_per_dev_params [configNr].stats) { | 420 | if (rndis_per_dev_params [configNr].stats) { |
362 | length = 4; | 421 | *outbuf = cpu_to_le32 ( |
363 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
364 | (rndis_per_dev_params [configNr] | 422 | (rndis_per_dev_params [configNr] |
365 | .stats->tx_packets - | 423 | .stats->tx_packets - |
366 | rndis_per_dev_params [configNr] | 424 | rndis_per_dev_params [configNr] |
@@ -369,9 +427,6 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
369 | .stats->tx_dropped) | 427 | .stats->tx_dropped) |
370 | * 123); | 428 | * 123); |
371 | retval = 0; | 429 | retval = 0; |
372 | } else { | ||
373 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
374 | retval = 0; | ||
375 | } | 430 | } |
376 | break; | 431 | break; |
377 | 432 | ||
@@ -379,8 +434,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
379 | DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__); | 434 | DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__); |
380 | /* dito */ | 435 | /* dito */ |
381 | if (rndis_per_dev_params [configNr].stats) { | 436 | if (rndis_per_dev_params [configNr].stats) { |
382 | length = 4; | 437 | *outbuf = cpu_to_le32 ( |
383 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
384 | (rndis_per_dev_params [configNr] | 438 | (rndis_per_dev_params [configNr] |
385 | .stats->tx_packets - | 439 | .stats->tx_packets - |
386 | rndis_per_dev_params [configNr] | 440 | rndis_per_dev_params [configNr] |
@@ -389,144 +443,105 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
389 | .stats->tx_dropped) | 443 | .stats->tx_dropped) |
390 | / 123); | 444 | / 123); |
391 | retval = 0; | 445 | retval = 0; |
392 | } else { | ||
393 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
394 | retval = 0; | ||
395 | } | 446 | } |
396 | break; | 447 | break; |
397 | 448 | ||
398 | case OID_GEN_MULTICAST_BYTES_XMIT: | 449 | case OID_GEN_MULTICAST_BYTES_XMIT: |
399 | DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__); | 450 | DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__); |
400 | if (rndis_per_dev_params [configNr].stats) { | 451 | if (rndis_per_dev_params [configNr].stats) { |
401 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 452 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
402 | rndis_per_dev_params [configNr] | ||
403 | .stats->multicast*1234); | 453 | .stats->multicast*1234); |
404 | retval = 0; | 454 | retval = 0; |
405 | } else { | ||
406 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
407 | retval = 0; | ||
408 | } | 455 | } |
409 | break; | 456 | break; |
410 | 457 | ||
411 | case OID_GEN_MULTICAST_FRAMES_XMIT: | 458 | case OID_GEN_MULTICAST_FRAMES_XMIT: |
412 | DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__); | 459 | DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__); |
413 | if (rndis_per_dev_params [configNr].stats) { | 460 | if (rndis_per_dev_params [configNr].stats) { |
414 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 461 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
415 | rndis_per_dev_params [configNr] | ||
416 | .stats->multicast); | 462 | .stats->multicast); |
417 | retval = 0; | 463 | retval = 0; |
418 | } else { | ||
419 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
420 | retval = 0; | ||
421 | } | 464 | } |
422 | break; | 465 | break; |
423 | 466 | ||
424 | case OID_GEN_BROADCAST_BYTES_XMIT: | 467 | case OID_GEN_BROADCAST_BYTES_XMIT: |
425 | DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__); | 468 | DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__); |
426 | if (rndis_per_dev_params [configNr].stats) { | 469 | if (rndis_per_dev_params [configNr].stats) { |
427 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 470 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
428 | rndis_per_dev_params [configNr] | ||
429 | .stats->tx_packets/42*255); | 471 | .stats->tx_packets/42*255); |
430 | retval = 0; | 472 | retval = 0; |
431 | } else { | ||
432 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
433 | retval = 0; | ||
434 | } | 473 | } |
435 | break; | 474 | break; |
436 | 475 | ||
437 | case OID_GEN_BROADCAST_FRAMES_XMIT: | 476 | case OID_GEN_BROADCAST_FRAMES_XMIT: |
438 | DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__); | 477 | DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__); |
439 | if (rndis_per_dev_params [configNr].stats) { | 478 | if (rndis_per_dev_params [configNr].stats) { |
440 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 479 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
441 | rndis_per_dev_params [configNr] | ||
442 | .stats->tx_packets/42); | 480 | .stats->tx_packets/42); |
443 | retval = 0; | 481 | retval = 0; |
444 | } else { | ||
445 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
446 | retval = 0; | ||
447 | } | 482 | } |
448 | break; | 483 | break; |
449 | 484 | ||
450 | case OID_GEN_DIRECTED_BYTES_RCV: | 485 | case OID_GEN_DIRECTED_BYTES_RCV: |
451 | DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__); | 486 | DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__); |
452 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | 487 | *outbuf = __constant_cpu_to_le32 (0); |
453 | retval = 0; | 488 | retval = 0; |
454 | break; | 489 | break; |
455 | 490 | ||
456 | case OID_GEN_DIRECTED_FRAMES_RCV: | 491 | case OID_GEN_DIRECTED_FRAMES_RCV: |
457 | DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__); | 492 | DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__); |
458 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | 493 | *outbuf = __constant_cpu_to_le32 (0); |
459 | retval = 0; | 494 | retval = 0; |
460 | break; | 495 | break; |
461 | 496 | ||
462 | case OID_GEN_MULTICAST_BYTES_RCV: | 497 | case OID_GEN_MULTICAST_BYTES_RCV: |
463 | DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__); | 498 | DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__); |
464 | if (rndis_per_dev_params [configNr].stats) { | 499 | if (rndis_per_dev_params [configNr].stats) { |
465 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 500 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
466 | rndis_per_dev_params [configNr] | ||
467 | .stats->multicast * 1111); | 501 | .stats->multicast * 1111); |
468 | retval = 0; | 502 | retval = 0; |
469 | } else { | ||
470 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
471 | retval = 0; | ||
472 | } | 503 | } |
473 | break; | 504 | break; |
474 | 505 | ||
475 | case OID_GEN_MULTICAST_FRAMES_RCV: | 506 | case OID_GEN_MULTICAST_FRAMES_RCV: |
476 | DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__); | 507 | DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__); |
477 | if (rndis_per_dev_params [configNr].stats) { | 508 | if (rndis_per_dev_params [configNr].stats) { |
478 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 509 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
479 | rndis_per_dev_params [configNr] | ||
480 | .stats->multicast); | 510 | .stats->multicast); |
481 | retval = 0; | 511 | retval = 0; |
482 | } else { | ||
483 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
484 | retval = 0; | ||
485 | } | 512 | } |
486 | break; | 513 | break; |
487 | 514 | ||
488 | case OID_GEN_BROADCAST_BYTES_RCV: | 515 | case OID_GEN_BROADCAST_BYTES_RCV: |
489 | DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__); | 516 | DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__); |
490 | if (rndis_per_dev_params [configNr].stats) { | 517 | if (rndis_per_dev_params [configNr].stats) { |
491 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 518 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
492 | rndis_per_dev_params [configNr] | ||
493 | .stats->rx_packets/42*255); | 519 | .stats->rx_packets/42*255); |
494 | retval = 0; | 520 | retval = 0; |
495 | } else { | ||
496 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
497 | retval = 0; | ||
498 | } | 521 | } |
499 | break; | 522 | break; |
500 | 523 | ||
501 | case OID_GEN_BROADCAST_FRAMES_RCV: | 524 | case OID_GEN_BROADCAST_FRAMES_RCV: |
502 | DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__); | 525 | DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__); |
503 | if (rndis_per_dev_params [configNr].stats) { | 526 | if (rndis_per_dev_params [configNr].stats) { |
504 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 527 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
505 | rndis_per_dev_params [configNr] | ||
506 | .stats->rx_packets/42); | 528 | .stats->rx_packets/42); |
507 | retval = 0; | 529 | retval = 0; |
508 | } else { | ||
509 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
510 | retval = 0; | ||
511 | } | 530 | } |
512 | break; | 531 | break; |
513 | 532 | ||
514 | case OID_GEN_RCV_CRC_ERROR: | 533 | case OID_GEN_RCV_CRC_ERROR: |
515 | DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__); | 534 | DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__); |
516 | if (rndis_per_dev_params [configNr].stats) { | 535 | if (rndis_per_dev_params [configNr].stats) { |
517 | *((__le32 *) resp + 6) = cpu_to_le32 ( | 536 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
518 | rndis_per_dev_params [configNr] | ||
519 | .stats->rx_crc_errors); | 537 | .stats->rx_crc_errors); |
520 | retval = 0; | 538 | retval = 0; |
521 | } else { | ||
522 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
523 | retval = 0; | ||
524 | } | 539 | } |
525 | break; | 540 | break; |
526 | 541 | ||
527 | case OID_GEN_TRANSMIT_QUEUE_LENGTH: | 542 | case OID_GEN_TRANSMIT_QUEUE_LENGTH: |
528 | DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__); | 543 | DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__); |
529 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | 544 | *outbuf = __constant_cpu_to_le32 (0); |
530 | retval = 0; | 545 | retval = 0; |
531 | break; | 546 | break; |
532 | #endif /* RNDIS_OPTIONAL_STATS */ | 547 | #endif /* RNDIS_OPTIONAL_STATS */ |
@@ -538,13 +553,10 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
538 | DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__); | 553 | DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__); |
539 | if (rndis_per_dev_params [configNr].dev) { | 554 | if (rndis_per_dev_params [configNr].dev) { |
540 | length = ETH_ALEN; | 555 | length = ETH_ALEN; |
541 | memcpy ((u8 *) resp + 24, | 556 | memcpy (outbuf, |
542 | rndis_per_dev_params [configNr].host_mac, | 557 | rndis_per_dev_params [configNr].host_mac, |
543 | length); | 558 | length); |
544 | retval = 0; | 559 | retval = 0; |
545 | } else { | ||
546 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
547 | retval = 0; | ||
548 | } | 560 | } |
549 | break; | 561 | break; |
550 | 562 | ||
@@ -553,7 +565,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
553 | DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__); | 565 | DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__); |
554 | if (rndis_per_dev_params [configNr].dev) { | 566 | if (rndis_per_dev_params [configNr].dev) { |
555 | length = ETH_ALEN; | 567 | length = ETH_ALEN; |
556 | memcpy ((u8 *) resp + 24, | 568 | memcpy (outbuf, |
557 | rndis_per_dev_params [configNr].host_mac, | 569 | rndis_per_dev_params [configNr].host_mac, |
558 | length); | 570 | length); |
559 | retval = 0; | 571 | retval = 0; |
@@ -563,18 +575,16 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
563 | /* mandatory */ | 575 | /* mandatory */ |
564 | case OID_802_3_MULTICAST_LIST: | 576 | case OID_802_3_MULTICAST_LIST: |
565 | DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); | 577 | DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); |
566 | length = 4; | ||
567 | /* Multicast base address only */ | 578 | /* Multicast base address only */ |
568 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0xE0000000); | 579 | *outbuf = __constant_cpu_to_le32 (0xE0000000); |
569 | retval = 0; | 580 | retval = 0; |
570 | break; | 581 | break; |
571 | 582 | ||
572 | /* mandatory */ | 583 | /* mandatory */ |
573 | case OID_802_3_MAXIMUM_LIST_SIZE: | 584 | case OID_802_3_MAXIMUM_LIST_SIZE: |
574 | DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__); | 585 | DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__); |
575 | length = 4; | ||
576 | /* Multicast base address only */ | 586 | /* Multicast base address only */ |
577 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (1); | 587 | *outbuf = __constant_cpu_to_le32 (1); |
578 | retval = 0; | 588 | retval = 0; |
579 | break; | 589 | break; |
580 | 590 | ||
@@ -587,11 +597,8 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
587 | /* mandatory */ | 597 | /* mandatory */ |
588 | case OID_802_3_RCV_ERROR_ALIGNMENT: | 598 | case OID_802_3_RCV_ERROR_ALIGNMENT: |
589 | DEBUG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__); | 599 | DEBUG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__); |
590 | if (rndis_per_dev_params [configNr].stats) | 600 | if (rndis_per_dev_params [configNr].stats) { |
591 | { | 601 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
592 | length = 4; | ||
593 | *((__le32 *) resp + 6) = cpu_to_le32 ( | ||
594 | rndis_per_dev_params [configNr] | ||
595 | .stats->rx_frame_errors); | 602 | .stats->rx_frame_errors); |
596 | retval = 0; | 603 | retval = 0; |
597 | } | 604 | } |
@@ -600,16 +607,14 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
600 | /* mandatory */ | 607 | /* mandatory */ |
601 | case OID_802_3_XMIT_ONE_COLLISION: | 608 | case OID_802_3_XMIT_ONE_COLLISION: |
602 | DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__); | 609 | DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__); |
603 | length = 4; | 610 | *outbuf = __constant_cpu_to_le32 (0); |
604 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
605 | retval = 0; | 611 | retval = 0; |
606 | break; | 612 | break; |
607 | 613 | ||
608 | /* mandatory */ | 614 | /* mandatory */ |
609 | case OID_802_3_XMIT_MORE_COLLISIONS: | 615 | case OID_802_3_XMIT_MORE_COLLISIONS: |
610 | DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__); | 616 | DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__); |
611 | length = 4; | 617 | *outbuf = __constant_cpu_to_le32 (0); |
612 | *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); | ||
613 | retval = 0; | 618 | retval = 0; |
614 | break; | 619 | break; |
615 | 620 | ||
@@ -655,27 +660,18 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
655 | case OID_PNP_CAPABILITIES: | 660 | case OID_PNP_CAPABILITIES: |
656 | DEBUG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__); | 661 | DEBUG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__); |
657 | 662 | ||
658 | /* just PM, and remote wakeup on link status change | 663 | /* for now, no wakeup capabilities */ |
659 | * (not magic packet or pattern match) | ||
660 | */ | ||
661 | length = sizeof (struct NDIS_PNP_CAPABILITIES); | 664 | length = sizeof (struct NDIS_PNP_CAPABILITIES); |
662 | memset (resp, 0, length); | 665 | memset(outbuf, 0, length); |
663 | { | ||
664 | struct NDIS_PNP_CAPABILITIES *caps = (void *) resp; | ||
665 | |||
666 | caps->Flags = NDIS_DEVICE_WAKE_UP_ENABLE; | ||
667 | caps->WakeUpCapabilities.MinLinkChangeWakeUp | ||
668 | = NdisDeviceStateD3; | ||
669 | |||
670 | /* FIXME then use usb_gadget_wakeup(), and | ||
671 | * set USB_CONFIG_ATT_WAKEUP in config desc | ||
672 | */ | ||
673 | } | ||
674 | retval = 0; | 666 | retval = 0; |
675 | break; | 667 | break; |
676 | case OID_PNP_QUERY_POWER: | 668 | case OID_PNP_QUERY_POWER: |
677 | DEBUG("%s: OID_PNP_QUERY_POWER\n", __FUNCTION__); | 669 | DEBUG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__, |
678 | /* sure, handle any power state that maps to USB suspend */ | 670 | le32_to_cpup((__le32 *) buf) - 1); |
671 | /* only suspend is a real power state, and | ||
672 | * it can't be entered by OID_PNP_SET_POWER... | ||
673 | */ | ||
674 | length = 0; | ||
679 | retval = 0; | 675 | retval = 0; |
680 | break; | 676 | break; |
681 | #endif | 677 | #endif |
@@ -684,11 +680,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r) | |||
684 | printk (KERN_WARNING "%s: query unknown OID 0x%08X\n", | 680 | printk (KERN_WARNING "%s: query unknown OID 0x%08X\n", |
685 | __FUNCTION__, OID); | 681 | __FUNCTION__, OID); |
686 | } | 682 | } |
683 | if (retval < 0) | ||
684 | length = 0; | ||
687 | 685 | ||
688 | resp->InformationBufferOffset = __constant_cpu_to_le32 (16); | ||
689 | resp->InformationBufferLength = cpu_to_le32 (length); | 686 | resp->InformationBufferLength = cpu_to_le32 (length); |
690 | resp->MessageLength = cpu_to_le32 (24 + length); | 687 | r->length = length + sizeof *resp; |
691 | r->length = 24 + length; | 688 | resp->MessageLength = cpu_to_le32 (r->length); |
692 | return retval; | 689 | return retval; |
693 | } | 690 | } |
694 | 691 | ||
@@ -705,45 +702,40 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, | |||
705 | if (!resp) | 702 | if (!resp) |
706 | return -ENOMEM; | 703 | return -ENOMEM; |
707 | 704 | ||
708 | DEBUG("set OID %08x value, len %d:\n", OID, buf_len); | 705 | if (buf_len && rndis_debug > 1) { |
709 | for (i = 0; i < buf_len; i += 16) { | 706 | DEBUG("set OID %08x value, len %d:\n", OID, buf_len); |
710 | DEBUG ("%03d: " | 707 | for (i = 0; i < buf_len; i += 16) { |
711 | " %02x %02x %02x %02x" | 708 | DEBUG ("%03d: %08x %08x %08x %08x\n", i, |
712 | " %02x %02x %02x %02x" | 709 | le32_to_cpup((__le32 *)&buf[i]), |
713 | " %02x %02x %02x %02x" | 710 | le32_to_cpup((__le32 *)&buf[i + 4]), |
714 | " %02x %02x %02x %02x" | 711 | le32_to_cpup((__le32 *)&buf[i + 8]), |
715 | "\n", | 712 | le32_to_cpup((__le32 *)&buf[i + 12])); |
716 | i, | 713 | } |
717 | buf[i], buf [i+1], | ||
718 | buf[i+2], buf[i+3], | ||
719 | buf[i+4], buf [i+5], | ||
720 | buf[i+6], buf[i+7], | ||
721 | buf[i+8], buf [i+9], | ||
722 | buf[i+10], buf[i+11], | ||
723 | buf[i+12], buf [i+13], | ||
724 | buf[i+14], buf[i+15]); | ||
725 | } | 714 | } |
726 | 715 | ||
716 | params = &rndis_per_dev_params [configNr]; | ||
727 | switch (OID) { | 717 | switch (OID) { |
728 | case OID_GEN_CURRENT_PACKET_FILTER: | 718 | case OID_GEN_CURRENT_PACKET_FILTER: |
729 | params = &rndis_per_dev_params [configNr]; | ||
730 | retval = 0; | ||
731 | 719 | ||
732 | /* FIXME use these NDIS_PACKET_TYPE_* bitflags to | 720 | /* these NDIS_PACKET_TYPE_* bitflags are shared with |
733 | * set the cdc_filter; it's not RNDIS-specific | 721 | * cdc_filter; it's not RNDIS-specific |
734 | * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in: | 722 | * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in: |
735 | * PROMISCUOUS, DIRECTED, | 723 | * PROMISCUOUS, DIRECTED, |
736 | * MULTICAST, ALL_MULTICAST, BROADCAST | 724 | * MULTICAST, ALL_MULTICAST, BROADCAST |
737 | */ | 725 | */ |
738 | params->filter = le32_to_cpup((__le32 *)buf); | 726 | *params->filter = (u16) le32_to_cpup((__le32 *)buf); |
739 | DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n", | 727 | DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n", |
740 | __FUNCTION__, params->filter); | 728 | __FUNCTION__, *params->filter); |
741 | 729 | ||
742 | /* this call has a significant side effect: it's | 730 | /* this call has a significant side effect: it's |
743 | * what makes the packet flow start and stop, like | 731 | * what makes the packet flow start and stop, like |
744 | * activating the CDC Ethernet altsetting. | 732 | * activating the CDC Ethernet altsetting. |
745 | */ | 733 | */ |
746 | if (params->filter) { | 734 | #ifdef RNDIS_PM |
735 | update_linkstate: | ||
736 | #endif | ||
737 | retval = 0; | ||
738 | if (*params->filter) { | ||
747 | params->state = RNDIS_DATA_INITIALIZED; | 739 | params->state = RNDIS_DATA_INITIALIZED; |
748 | netif_carrier_on(params->dev); | 740 | netif_carrier_on(params->dev); |
749 | if (netif_running(params->dev)) | 741 | if (netif_running(params->dev)) |
@@ -776,21 +768,34 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, | |||
776 | 768 | ||
777 | #ifdef RNDIS_PM | 769 | #ifdef RNDIS_PM |
778 | case OID_PNP_SET_POWER: | 770 | case OID_PNP_SET_POWER: |
779 | DEBUG ("OID_PNP_SET_POWER\n"); | 771 | /* The only real power state is USB suspend, and RNDIS requests |
780 | /* sure, handle any power state that maps to USB suspend */ | 772 | * can't enter it; this one isn't really about power. After |
781 | retval = 0; | 773 | * resuming, Windows forces a reset, and then SET_POWER D0. |
782 | break; | 774 | * FIXME ... then things go batty; Windows wedges itself. |
783 | 775 | */ | |
784 | case OID_PNP_ENABLE_WAKE_UP: | 776 | i = le32_to_cpup((__force __le32 *)buf); |
785 | /* always-connected ... */ | 777 | DEBUG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1); |
786 | DEBUG ("OID_PNP_ENABLE_WAKE_UP\n"); | 778 | switch (i) { |
787 | retval = 0; | 779 | case NdisDeviceStateD0: |
780 | *params->filter = params->saved_filter; | ||
781 | goto update_linkstate; | ||
782 | case NdisDeviceStateD3: | ||
783 | case NdisDeviceStateD2: | ||
784 | case NdisDeviceStateD1: | ||
785 | params->saved_filter = *params->filter; | ||
786 | retval = 0; | ||
787 | break; | ||
788 | } | ||
788 | break; | 789 | break; |
789 | 790 | ||
790 | // no PM resume patterns supported (specified where?) | 791 | #ifdef RNDIS_WAKEUP |
791 | // so OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN always fails | 792 | // no wakeup support advertised, so wakeup OIDs always fail: |
793 | // - OID_PNP_ENABLE_WAKE_UP | ||
794 | // - OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN | ||
792 | #endif | 795 | #endif |
793 | 796 | ||
797 | #endif /* RNDIS_PM */ | ||
798 | |||
794 | default: | 799 | default: |
795 | printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n", | 800 | printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n", |
796 | __FUNCTION__, OID, buf_len); | 801 | __FUNCTION__, OID, buf_len); |
@@ -811,13 +816,10 @@ static int rndis_init_response (int configNr, rndis_init_msg_type *buf) | |||
811 | if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; | 816 | if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; |
812 | 817 | ||
813 | r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type)); | 818 | r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type)); |
814 | 819 | if (!r) | |
815 | if (!r) return -ENOMEM; | 820 | return -ENOMEM; |
816 | |||
817 | resp = (rndis_init_cmplt_type *) r->buf; | 821 | resp = (rndis_init_cmplt_type *) r->buf; |
818 | 822 | ||
819 | if (!resp) return -ENOMEM; | ||
820 | |||
821 | resp->MessageType = __constant_cpu_to_le32 ( | 823 | resp->MessageType = __constant_cpu_to_le32 ( |
822 | REMOTE_NDIS_INITIALIZE_CMPLT); | 824 | REMOTE_NDIS_INITIALIZE_CMPLT); |
823 | resp->MessageLength = __constant_cpu_to_le32 (52); | 825 | resp->MessageLength = __constant_cpu_to_le32 (52); |
@@ -857,20 +859,22 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf) | |||
857 | * oid_supported_list is the largest answer | 859 | * oid_supported_list is the largest answer |
858 | */ | 860 | */ |
859 | r = rndis_add_response (configNr, sizeof (oid_supported_list)); | 861 | r = rndis_add_response (configNr, sizeof (oid_supported_list)); |
860 | 862 | if (!r) | |
861 | if (!r) return -ENOMEM; | 863 | return -ENOMEM; |
862 | resp = (rndis_query_cmplt_type *) r->buf; | 864 | resp = (rndis_query_cmplt_type *) r->buf; |
863 | 865 | ||
864 | if (!resp) return -ENOMEM; | ||
865 | |||
866 | resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT); | 866 | resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT); |
867 | resp->MessageLength = __constant_cpu_to_le32 (24); | ||
868 | resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ | 867 | resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ |
869 | 868 | ||
870 | if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID), r)) { | 869 | if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID), |
870 | le32_to_cpu(buf->InformationBufferOffset) | ||
871 | + 8 + (u8 *) buf, | ||
872 | le32_to_cpu(buf->InformationBufferLength), | ||
873 | r)) { | ||
871 | /* OID not supported */ | 874 | /* OID not supported */ |
872 | resp->Status = __constant_cpu_to_le32 ( | 875 | resp->Status = __constant_cpu_to_le32 ( |
873 | RNDIS_STATUS_NOT_SUPPORTED); | 876 | RNDIS_STATUS_NOT_SUPPORTED); |
877 | resp->MessageLength = __constant_cpu_to_le32 (sizeof *resp); | ||
874 | resp->InformationBufferLength = __constant_cpu_to_le32 (0); | 878 | resp->InformationBufferLength = __constant_cpu_to_le32 (0); |
875 | resp->InformationBufferOffset = __constant_cpu_to_le32 (0); | 879 | resp->InformationBufferOffset = __constant_cpu_to_le32 (0); |
876 | } else | 880 | } else |
@@ -889,10 +893,9 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf) | |||
889 | rndis_resp_t *r; | 893 | rndis_resp_t *r; |
890 | 894 | ||
891 | r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type)); | 895 | r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type)); |
892 | 896 | if (!r) | |
893 | if (!r) return -ENOMEM; | 897 | return -ENOMEM; |
894 | resp = (rndis_set_cmplt_type *) r->buf; | 898 | resp = (rndis_set_cmplt_type *) r->buf; |
895 | if (!resp) return -ENOMEM; | ||
896 | 899 | ||
897 | BufLength = le32_to_cpu (buf->InformationBufferLength); | 900 | BufLength = le32_to_cpu (buf->InformationBufferLength); |
898 | BufOffset = le32_to_cpu (buf->InformationBufferOffset); | 901 | BufOffset = le32_to_cpu (buf->InformationBufferOffset); |
@@ -930,10 +933,9 @@ static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf) | |||
930 | rndis_resp_t *r; | 933 | rndis_resp_t *r; |
931 | 934 | ||
932 | r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type)); | 935 | r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type)); |
933 | 936 | if (!r) | |
934 | if (!r) return -ENOMEM; | 937 | return -ENOMEM; |
935 | resp = (rndis_reset_cmplt_type *) r->buf; | 938 | resp = (rndis_reset_cmplt_type *) r->buf; |
936 | if (!resp) return -ENOMEM; | ||
937 | 939 | ||
938 | resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT); | 940 | resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT); |
939 | resp->MessageLength = __constant_cpu_to_le32 (16); | 941 | resp->MessageLength = __constant_cpu_to_le32 (16); |
@@ -957,8 +959,9 @@ static int rndis_keepalive_response (int configNr, | |||
957 | /* host "should" check only in RNDIS_DATA_INITIALIZED state */ | 959 | /* host "should" check only in RNDIS_DATA_INITIALIZED state */ |
958 | 960 | ||
959 | r = rndis_add_response (configNr, sizeof (rndis_keepalive_cmplt_type)); | 961 | r = rndis_add_response (configNr, sizeof (rndis_keepalive_cmplt_type)); |
962 | if (!r) | ||
963 | return -ENOMEM; | ||
960 | resp = (rndis_keepalive_cmplt_type *) r->buf; | 964 | resp = (rndis_keepalive_cmplt_type *) r->buf; |
961 | if (!resp) return -ENOMEM; | ||
962 | 965 | ||
963 | resp->MessageType = __constant_cpu_to_le32 ( | 966 | resp->MessageType = __constant_cpu_to_le32 ( |
964 | REMOTE_NDIS_KEEPALIVE_CMPLT); | 967 | REMOTE_NDIS_KEEPALIVE_CMPLT); |
@@ -987,10 +990,9 @@ static int rndis_indicate_status_msg (int configNr, u32 status) | |||
987 | 990 | ||
988 | r = rndis_add_response (configNr, | 991 | r = rndis_add_response (configNr, |
989 | sizeof (rndis_indicate_status_msg_type)); | 992 | sizeof (rndis_indicate_status_msg_type)); |
990 | if (!r) return -ENOMEM; | 993 | if (!r) |
991 | 994 | return -ENOMEM; | |
992 | resp = (rndis_indicate_status_msg_type *) r->buf; | 995 | resp = (rndis_indicate_status_msg_type *) r->buf; |
993 | if (!resp) return -ENOMEM; | ||
994 | 996 | ||
995 | resp->MessageType = __constant_cpu_to_le32 ( | 997 | resp->MessageType = __constant_cpu_to_le32 ( |
996 | REMOTE_NDIS_INDICATE_STATUS_MSG); | 998 | REMOTE_NDIS_INDICATE_STATUS_MSG); |
@@ -1021,6 +1023,21 @@ int rndis_signal_disconnect (int configNr) | |||
1021 | RNDIS_STATUS_MEDIA_DISCONNECT); | 1023 | RNDIS_STATUS_MEDIA_DISCONNECT); |
1022 | } | 1024 | } |
1023 | 1025 | ||
1026 | void rndis_uninit (int configNr) | ||
1027 | { | ||
1028 | u8 *buf; | ||
1029 | u32 length; | ||
1030 | |||
1031 | if (configNr >= RNDIS_MAX_CONFIGS) | ||
1032 | return; | ||
1033 | rndis_per_dev_params [configNr].used = 0; | ||
1034 | rndis_per_dev_params [configNr].state = RNDIS_UNINITIALIZED; | ||
1035 | |||
1036 | /* drain the response queue */ | ||
1037 | while ((buf = rndis_get_next_response(configNr, &length))) | ||
1038 | rndis_free_response(configNr, buf); | ||
1039 | } | ||
1040 | |||
1024 | void rndis_set_host_mac (int configNr, const u8 *addr) | 1041 | void rndis_set_host_mac (int configNr, const u8 *addr) |
1025 | { | 1042 | { |
1026 | rndis_per_dev_params [configNr].host_mac = addr; | 1043 | rndis_per_dev_params [configNr].host_mac = addr; |
@@ -1046,9 +1063,13 @@ int rndis_msg_parser (u8 configNr, u8 *buf) | |||
1046 | return -ENOTSUPP; | 1063 | return -ENOTSUPP; |
1047 | params = &rndis_per_dev_params [configNr]; | 1064 | params = &rndis_per_dev_params [configNr]; |
1048 | 1065 | ||
1066 | /* NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for | ||
1067 | * rx/tx statistics and link status, in addition to KEEPALIVE traffic | ||
1068 | * and normal HC level polling to see if there's any IN traffic. | ||
1069 | */ | ||
1070 | |||
1049 | /* For USB: responses may take up to 10 seconds */ | 1071 | /* For USB: responses may take up to 10 seconds */ |
1050 | switch (MsgType) | 1072 | switch (MsgType) { |
1051 | { | ||
1052 | case REMOTE_NDIS_INITIALIZE_MSG: | 1073 | case REMOTE_NDIS_INITIALIZE_MSG: |
1053 | DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", | 1074 | DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", |
1054 | __FUNCTION__ ); | 1075 | __FUNCTION__ ); |
@@ -1082,10 +1103,9 @@ int rndis_msg_parser (u8 configNr, u8 *buf) | |||
1082 | 1103 | ||
1083 | case REMOTE_NDIS_KEEPALIVE_MSG: | 1104 | case REMOTE_NDIS_KEEPALIVE_MSG: |
1084 | /* For USB: host does this every 5 seconds */ | 1105 | /* For USB: host does this every 5 seconds */ |
1085 | #ifdef VERBOSE | 1106 | if (rndis_debug > 1) |
1086 | DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", | 1107 | DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", |
1087 | __FUNCTION__ ); | 1108 | __FUNCTION__ ); |
1088 | #endif | ||
1089 | return rndis_keepalive_response (configNr, | 1109 | return rndis_keepalive_response (configNr, |
1090 | (rndis_keepalive_msg_type *) | 1110 | (rndis_keepalive_msg_type *) |
1091 | buf); | 1111 | buf); |
@@ -1152,7 +1172,8 @@ void rndis_deregister (int configNr) | |||
1152 | } | 1172 | } |
1153 | 1173 | ||
1154 | int rndis_set_param_dev (u8 configNr, struct net_device *dev, | 1174 | int rndis_set_param_dev (u8 configNr, struct net_device *dev, |
1155 | struct net_device_stats *stats) | 1175 | struct net_device_stats *stats, |
1176 | u16 *cdc_filter) | ||
1156 | { | 1177 | { |
1157 | DEBUG("%s:\n", __FUNCTION__ ); | 1178 | DEBUG("%s:\n", __FUNCTION__ ); |
1158 | if (!dev || !stats) return -1; | 1179 | if (!dev || !stats) return -1; |
@@ -1160,6 +1181,7 @@ int rndis_set_param_dev (u8 configNr, struct net_device *dev, | |||
1160 | 1181 | ||
1161 | rndis_per_dev_params [configNr].dev = dev; | 1182 | rndis_per_dev_params [configNr].dev = dev; |
1162 | rndis_per_dev_params [configNr].stats = stats; | 1183 | rndis_per_dev_params [configNr].stats = stats; |
1184 | rndis_per_dev_params [configNr].filter = cdc_filter; | ||
1163 | 1185 | ||
1164 | return 0; | 1186 | return 0; |
1165 | } | 1187 | } |
@@ -1178,7 +1200,7 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr) | |||
1178 | 1200 | ||
1179 | int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed) | 1201 | int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed) |
1180 | { | 1202 | { |
1181 | DEBUG("%s:\n", __FUNCTION__ ); | 1203 | DEBUG("%s: %u %u\n", __FUNCTION__, medium, speed); |
1182 | if (configNr >= RNDIS_MAX_CONFIGS) return -1; | 1204 | if (configNr >= RNDIS_MAX_CONFIGS) return -1; |
1183 | 1205 | ||
1184 | rndis_per_dev_params [configNr].medium = medium; | 1206 | rndis_per_dev_params [configNr].medium = medium; |
@@ -1242,6 +1264,7 @@ static rndis_resp_t *rndis_add_response (int configNr, u32 length) | |||
1242 | { | 1264 | { |
1243 | rndis_resp_t *r; | 1265 | rndis_resp_t *r; |
1244 | 1266 | ||
1267 | /* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */ | ||
1245 | r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC); | 1268 | r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC); |
1246 | if (!r) return NULL; | 1269 | if (!r) return NULL; |
1247 | 1270 | ||
diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h index 2b5b55df3cfd..95b4c6326100 100644 --- a/drivers/usb/gadget/rndis.h +++ b/drivers/usb/gadget/rndis.h | |||
@@ -69,90 +69,6 @@ | |||
69 | #define OID_PNP_ENABLE_WAKE_UP 0xFD010106 | 69 | #define OID_PNP_ENABLE_WAKE_UP 0xFD010106 |
70 | 70 | ||
71 | 71 | ||
72 | /* supported OIDs */ | ||
73 | static const u32 oid_supported_list [] = | ||
74 | { | ||
75 | /* the general stuff */ | ||
76 | OID_GEN_SUPPORTED_LIST, | ||
77 | OID_GEN_HARDWARE_STATUS, | ||
78 | OID_GEN_MEDIA_SUPPORTED, | ||
79 | OID_GEN_MEDIA_IN_USE, | ||
80 | OID_GEN_MAXIMUM_FRAME_SIZE, | ||
81 | OID_GEN_LINK_SPEED, | ||
82 | OID_GEN_TRANSMIT_BLOCK_SIZE, | ||
83 | OID_GEN_RECEIVE_BLOCK_SIZE, | ||
84 | OID_GEN_VENDOR_ID, | ||
85 | OID_GEN_VENDOR_DESCRIPTION, | ||
86 | OID_GEN_VENDOR_DRIVER_VERSION, | ||
87 | OID_GEN_CURRENT_PACKET_FILTER, | ||
88 | OID_GEN_MAXIMUM_TOTAL_SIZE, | ||
89 | OID_GEN_MEDIA_CONNECT_STATUS, | ||
90 | OID_GEN_PHYSICAL_MEDIUM, | ||
91 | #if 0 | ||
92 | OID_GEN_RNDIS_CONFIG_PARAMETER, | ||
93 | #endif | ||
94 | |||
95 | /* the statistical stuff */ | ||
96 | OID_GEN_XMIT_OK, | ||
97 | OID_GEN_RCV_OK, | ||
98 | OID_GEN_XMIT_ERROR, | ||
99 | OID_GEN_RCV_ERROR, | ||
100 | OID_GEN_RCV_NO_BUFFER, | ||
101 | #ifdef RNDIS_OPTIONAL_STATS | ||
102 | OID_GEN_DIRECTED_BYTES_XMIT, | ||
103 | OID_GEN_DIRECTED_FRAMES_XMIT, | ||
104 | OID_GEN_MULTICAST_BYTES_XMIT, | ||
105 | OID_GEN_MULTICAST_FRAMES_XMIT, | ||
106 | OID_GEN_BROADCAST_BYTES_XMIT, | ||
107 | OID_GEN_BROADCAST_FRAMES_XMIT, | ||
108 | OID_GEN_DIRECTED_BYTES_RCV, | ||
109 | OID_GEN_DIRECTED_FRAMES_RCV, | ||
110 | OID_GEN_MULTICAST_BYTES_RCV, | ||
111 | OID_GEN_MULTICAST_FRAMES_RCV, | ||
112 | OID_GEN_BROADCAST_BYTES_RCV, | ||
113 | OID_GEN_BROADCAST_FRAMES_RCV, | ||
114 | OID_GEN_RCV_CRC_ERROR, | ||
115 | OID_GEN_TRANSMIT_QUEUE_LENGTH, | ||
116 | #endif /* RNDIS_OPTIONAL_STATS */ | ||
117 | |||
118 | /* mandatory 802.3 */ | ||
119 | /* the general stuff */ | ||
120 | OID_802_3_PERMANENT_ADDRESS, | ||
121 | OID_802_3_CURRENT_ADDRESS, | ||
122 | OID_802_3_MULTICAST_LIST, | ||
123 | OID_802_3_MAC_OPTIONS, | ||
124 | OID_802_3_MAXIMUM_LIST_SIZE, | ||
125 | |||
126 | /* the statistical stuff */ | ||
127 | OID_802_3_RCV_ERROR_ALIGNMENT, | ||
128 | OID_802_3_XMIT_ONE_COLLISION, | ||
129 | OID_802_3_XMIT_MORE_COLLISIONS, | ||
130 | #ifdef RNDIS_OPTIONAL_STATS | ||
131 | OID_802_3_XMIT_DEFERRED, | ||
132 | OID_802_3_XMIT_MAX_COLLISIONS, | ||
133 | OID_802_3_RCV_OVERRUN, | ||
134 | OID_802_3_XMIT_UNDERRUN, | ||
135 | OID_802_3_XMIT_HEARTBEAT_FAILURE, | ||
136 | OID_802_3_XMIT_TIMES_CRS_LOST, | ||
137 | OID_802_3_XMIT_LATE_COLLISIONS, | ||
138 | #endif /* RNDIS_OPTIONAL_STATS */ | ||
139 | |||
140 | #ifdef RNDIS_PM | ||
141 | /* PM and wakeup are mandatory for USB: */ | ||
142 | |||
143 | /* power management */ | ||
144 | OID_PNP_CAPABILITIES, | ||
145 | OID_PNP_QUERY_POWER, | ||
146 | OID_PNP_SET_POWER, | ||
147 | |||
148 | /* wake up host */ | ||
149 | OID_PNP_ENABLE_WAKE_UP, | ||
150 | OID_PNP_ADD_WAKE_UP_PATTERN, | ||
151 | OID_PNP_REMOVE_WAKE_UP_PATTERN, | ||
152 | #endif | ||
153 | }; | ||
154 | |||
155 | |||
156 | typedef struct rndis_init_msg_type | 72 | typedef struct rndis_init_msg_type |
157 | { | 73 | { |
158 | __le32 MessageType; | 74 | __le32 MessageType; |
@@ -309,15 +225,18 @@ typedef struct rndis_resp_t | |||
309 | typedef struct rndis_params | 225 | typedef struct rndis_params |
310 | { | 226 | { |
311 | u8 confignr; | 227 | u8 confignr; |
312 | int used; | 228 | u8 used; |
229 | u16 saved_filter; | ||
313 | enum rndis_state state; | 230 | enum rndis_state state; |
314 | u32 filter; | ||
315 | u32 medium; | 231 | u32 medium; |
316 | u32 speed; | 232 | u32 speed; |
317 | u32 media_state; | 233 | u32 media_state; |
234 | |||
318 | const u8 *host_mac; | 235 | const u8 *host_mac; |
236 | u16 *filter; | ||
319 | struct net_device *dev; | 237 | struct net_device *dev; |
320 | struct net_device_stats *stats; | 238 | struct net_device_stats *stats; |
239 | |||
321 | u32 vendorID; | 240 | u32 vendorID; |
322 | const char *vendorDescr; | 241 | const char *vendorDescr; |
323 | int (*ack) (struct net_device *); | 242 | int (*ack) (struct net_device *); |
@@ -329,7 +248,8 @@ int rndis_msg_parser (u8 configNr, u8 *buf); | |||
329 | int rndis_register (int (*rndis_control_ack) (struct net_device *)); | 248 | int rndis_register (int (*rndis_control_ack) (struct net_device *)); |
330 | void rndis_deregister (int configNr); | 249 | void rndis_deregister (int configNr); |
331 | int rndis_set_param_dev (u8 configNr, struct net_device *dev, | 250 | int rndis_set_param_dev (u8 configNr, struct net_device *dev, |
332 | struct net_device_stats *stats); | 251 | struct net_device_stats *stats, |
252 | u16 *cdc_filter); | ||
333 | int rndis_set_param_vendor (u8 configNr, u32 vendorID, | 253 | int rndis_set_param_vendor (u8 configNr, u32 vendorID, |
334 | const char *vendorDescr); | 254 | const char *vendorDescr); |
335 | int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed); | 255 | int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed); |
@@ -338,6 +258,7 @@ int rndis_rm_hdr (struct sk_buff *skb); | |||
338 | u8 *rndis_get_next_response (int configNr, u32 *length); | 258 | u8 *rndis_get_next_response (int configNr, u32 *length); |
339 | void rndis_free_response (int configNr, u8 *buf); | 259 | void rndis_free_response (int configNr, u8 *buf); |
340 | 260 | ||
261 | void rndis_uninit (int configNr); | ||
341 | int rndis_signal_connect (int configNr); | 262 | int rndis_signal_connect (int configNr); |
342 | int rndis_signal_disconnect (int configNr); | 263 | int rndis_signal_disconnect (int configNr); |
343 | int rndis_state (int configNr); | 264 | int rndis_state (int configNr); |
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 4d591c764e38..9e4f1c6935a5 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c | |||
@@ -300,18 +300,18 @@ static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed, | |||
300 | u8 type, unsigned int index, int is_otg); | 300 | u8 type, unsigned int index, int is_otg); |
301 | 301 | ||
302 | static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len, | 302 | static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len, |
303 | int kmalloc_flags); | 303 | unsigned kmalloc_flags); |
304 | static void gs_free_req(struct usb_ep *ep, struct usb_request *req); | 304 | static void gs_free_req(struct usb_ep *ep, struct usb_request *req); |
305 | 305 | ||
306 | static struct gs_req_entry *gs_alloc_req_entry(struct usb_ep *ep, unsigned len, | 306 | static struct gs_req_entry *gs_alloc_req_entry(struct usb_ep *ep, unsigned len, |
307 | int kmalloc_flags); | 307 | unsigned kmalloc_flags); |
308 | static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req); | 308 | static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req); |
309 | 309 | ||
310 | static int gs_alloc_ports(struct gs_dev *dev, int kmalloc_flags); | 310 | static int gs_alloc_ports(struct gs_dev *dev, unsigned kmalloc_flags); |
311 | static void gs_free_ports(struct gs_dev *dev); | 311 | static void gs_free_ports(struct gs_dev *dev); |
312 | 312 | ||
313 | /* circular buffer */ | 313 | /* circular buffer */ |
314 | static struct gs_buf *gs_buf_alloc(unsigned int size, int kmalloc_flags); | 314 | static struct gs_buf *gs_buf_alloc(unsigned int size, unsigned kmalloc_flags); |
315 | static void gs_buf_free(struct gs_buf *gb); | 315 | static void gs_buf_free(struct gs_buf *gb); |
316 | static void gs_buf_clear(struct gs_buf *gb); | 316 | static void gs_buf_clear(struct gs_buf *gb); |
317 | static unsigned int gs_buf_data_avail(struct gs_buf *gb); | 317 | static unsigned int gs_buf_data_avail(struct gs_buf *gb); |
@@ -1607,9 +1607,9 @@ static int gs_setup(struct usb_gadget *gadget, | |||
1607 | int ret = -EOPNOTSUPP; | 1607 | int ret = -EOPNOTSUPP; |
1608 | struct gs_dev *dev = get_gadget_data(gadget); | 1608 | struct gs_dev *dev = get_gadget_data(gadget); |
1609 | struct usb_request *req = dev->dev_ctrl_req; | 1609 | struct usb_request *req = dev->dev_ctrl_req; |
1610 | u16 wIndex = ctrl->wIndex; | 1610 | u16 wIndex = le16_to_cpu(ctrl->wIndex); |
1611 | u16 wValue = ctrl->wValue; | 1611 | u16 wValue = le16_to_cpu(ctrl->wValue); |
1612 | u16 wLength = ctrl->wLength; | 1612 | u16 wLength = le16_to_cpu(ctrl->wLength); |
1613 | 1613 | ||
1614 | switch (ctrl->bRequestType & USB_TYPE_MASK) { | 1614 | switch (ctrl->bRequestType & USB_TYPE_MASK) { |
1615 | case USB_TYPE_STANDARD: | 1615 | case USB_TYPE_STANDARD: |
@@ -1651,9 +1651,9 @@ static int gs_setup_standard(struct usb_gadget *gadget, | |||
1651 | int ret = -EOPNOTSUPP; | 1651 | int ret = -EOPNOTSUPP; |
1652 | struct gs_dev *dev = get_gadget_data(gadget); | 1652 | struct gs_dev *dev = get_gadget_data(gadget); |
1653 | struct usb_request *req = dev->dev_ctrl_req; | 1653 | struct usb_request *req = dev->dev_ctrl_req; |
1654 | u16 wIndex = ctrl->wIndex; | 1654 | u16 wIndex = le16_to_cpu(ctrl->wIndex); |
1655 | u16 wValue = ctrl->wValue; | 1655 | u16 wValue = le16_to_cpu(ctrl->wValue); |
1656 | u16 wLength = ctrl->wLength; | 1656 | u16 wLength = le16_to_cpu(ctrl->wLength); |
1657 | 1657 | ||
1658 | switch (ctrl->bRequest) { | 1658 | switch (ctrl->bRequest) { |
1659 | case USB_REQ_GET_DESCRIPTOR: | 1659 | case USB_REQ_GET_DESCRIPTOR: |
@@ -1782,9 +1782,9 @@ static int gs_setup_class(struct usb_gadget *gadget, | |||
1782 | struct gs_dev *dev = get_gadget_data(gadget); | 1782 | struct gs_dev *dev = get_gadget_data(gadget); |
1783 | struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */ | 1783 | struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */ |
1784 | struct usb_request *req = dev->dev_ctrl_req; | 1784 | struct usb_request *req = dev->dev_ctrl_req; |
1785 | u16 wIndex = ctrl->wIndex; | 1785 | u16 wIndex = le16_to_cpu(ctrl->wIndex); |
1786 | u16 wValue = ctrl->wValue; | 1786 | u16 wValue = le16_to_cpu(ctrl->wValue); |
1787 | u16 wLength = ctrl->wLength; | 1787 | u16 wLength = le16_to_cpu(ctrl->wLength); |
1788 | 1788 | ||
1789 | switch (ctrl->bRequest) { | 1789 | switch (ctrl->bRequest) { |
1790 | case USB_CDC_REQ_SET_LINE_CODING: | 1790 | case USB_CDC_REQ_SET_LINE_CODING: |
@@ -2119,7 +2119,8 @@ static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed, | |||
2119 | * Allocate a usb_request and its buffer. Returns a pointer to the | 2119 | * Allocate a usb_request and its buffer. Returns a pointer to the |
2120 | * usb_request or NULL if there is an error. | 2120 | * usb_request or NULL if there is an error. |
2121 | */ | 2121 | */ |
2122 | static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len, int kmalloc_flags) | 2122 | static struct usb_request * |
2123 | gs_alloc_req(struct usb_ep *ep, unsigned int len, unsigned kmalloc_flags) | ||
2123 | { | 2124 | { |
2124 | struct usb_request *req; | 2125 | struct usb_request *req; |
2125 | 2126 | ||
@@ -2159,7 +2160,8 @@ static void gs_free_req(struct usb_ep *ep, struct usb_request *req) | |||
2159 | * Allocates a request and its buffer, using the given | 2160 | * Allocates a request and its buffer, using the given |
2160 | * endpoint, buffer len, and kmalloc flags. | 2161 | * endpoint, buffer len, and kmalloc flags. |
2161 | */ | 2162 | */ |
2162 | static struct gs_req_entry *gs_alloc_req_entry(struct usb_ep *ep, unsigned len, int kmalloc_flags) | 2163 | static struct gs_req_entry * |
2164 | gs_alloc_req_entry(struct usb_ep *ep, unsigned len, unsigned kmalloc_flags) | ||
2163 | { | 2165 | { |
2164 | struct gs_req_entry *req; | 2166 | struct gs_req_entry *req; |
2165 | 2167 | ||
@@ -2200,7 +2202,7 @@ static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req) | |||
2200 | * | 2202 | * |
2201 | * The device lock is normally held when calling this function. | 2203 | * The device lock is normally held when calling this function. |
2202 | */ | 2204 | */ |
2203 | static int gs_alloc_ports(struct gs_dev *dev, int kmalloc_flags) | 2205 | static int gs_alloc_ports(struct gs_dev *dev, unsigned kmalloc_flags) |
2204 | { | 2206 | { |
2205 | int i; | 2207 | int i; |
2206 | struct gs_port *port; | 2208 | struct gs_port *port; |
@@ -2282,7 +2284,7 @@ static void gs_free_ports(struct gs_dev *dev) | |||
2282 | * | 2284 | * |
2283 | * Allocate a circular buffer and all associated memory. | 2285 | * Allocate a circular buffer and all associated memory. |
2284 | */ | 2286 | */ |
2285 | static struct gs_buf *gs_buf_alloc(unsigned int size, int kmalloc_flags) | 2287 | static struct gs_buf *gs_buf_alloc(unsigned int size, unsigned kmalloc_flags) |
2286 | { | 2288 | { |
2287 | struct gs_buf *gb; | 2289 | struct gs_buf *gb; |
2288 | 2290 | ||
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 6e49432071a1..a6e035e24479 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c | |||
@@ -919,9 +919,9 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
919 | struct zero_dev *dev = get_gadget_data (gadget); | 919 | struct zero_dev *dev = get_gadget_data (gadget); |
920 | struct usb_request *req = dev->req; | 920 | struct usb_request *req = dev->req; |
921 | int value = -EOPNOTSUPP; | 921 | int value = -EOPNOTSUPP; |
922 | u16 w_index = ctrl->wIndex; | 922 | u16 w_index = le16_to_cpu(ctrl->wIndex); |
923 | u16 w_value = ctrl->wValue; | 923 | u16 w_value = le16_to_cpu(ctrl->wValue); |
924 | u16 w_length = ctrl->wLength; | 924 | u16 w_length = le16_to_cpu(ctrl->wLength); |
925 | 925 | ||
926 | /* usually this stores reply data in the pre-allocated ep0 buffer, | 926 | /* usually this stores reply data in the pre-allocated ep0 buffer, |
927 | * but config change events will reconfigure hardware. | 927 | * but config change events will reconfigure hardware. |
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 19e598c9641f..ed1899d307db 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -49,6 +49,19 @@ config USB_EHCI_ROOT_HUB_TT | |||
49 | 49 | ||
50 | This supports the EHCI implementation from TransDimension Inc. | 50 | This supports the EHCI implementation from TransDimension Inc. |
51 | 51 | ||
52 | config USB_ISP116X_HCD | ||
53 | tristate "ISP116X HCD support" | ||
54 | depends on USB | ||
55 | default N | ||
56 | ---help--- | ||
57 | The ISP1160 and ISP1161 chips are USB host controllers. Enable this | ||
58 | option if your board has this chip. If unsure, say N. | ||
59 | |||
60 | This driver does not support isochronous transfers. | ||
61 | |||
62 | To compile this driver as a module, choose M here: the | ||
63 | module will be called isp116x-hcd. | ||
64 | |||
52 | config USB_OHCI_HCD | 65 | config USB_OHCI_HCD |
53 | tristate "OHCI HCD support" | 66 | tristate "OHCI HCD support" |
54 | depends on USB && USB_ARCH_HAS_OHCI | 67 | depends on USB && USB_ARCH_HAS_OHCI |
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 5dbd3e7a27c7..350d14fc1cc9 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | # | 4 | # |
5 | 5 | ||
6 | obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o | 6 | obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o |
7 | obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o | ||
7 | obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o | 8 | obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o |
8 | obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o | 9 | obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o |
9 | obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o | 10 | obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o |
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 2ff11d53567b..50cb01831075 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c | |||
@@ -254,7 +254,7 @@ dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) | |||
254 | } | 254 | } |
255 | 255 | ||
256 | return scnprintf (buf, len, | 256 | return scnprintf (buf, len, |
257 | "%s%sport %d status %06x%s%s sig=%s %s%s%s%s%s%s%s%s%s", | 257 | "%s%sport %d status %06x%s%s sig=%s%s%s%s%s%s%s%s%s%s", |
258 | label, label [0] ? " " : "", port, status, | 258 | label, label [0] ? " " : "", port, status, |
259 | (status & PORT_POWER) ? " POWER" : "", | 259 | (status & PORT_POWER) ? " POWER" : "", |
260 | (status & PORT_OWNER) ? " OWNER" : "", | 260 | (status & PORT_OWNER) ? " OWNER" : "", |
@@ -644,9 +644,11 @@ show_registers (struct class_device *class_dev, char *buf) | |||
644 | if (bus->controller->power.power_state) { | 644 | if (bus->controller->power.power_state) { |
645 | size = scnprintf (next, size, | 645 | size = scnprintf (next, size, |
646 | "bus %s, device %s (driver " DRIVER_VERSION ")\n" | 646 | "bus %s, device %s (driver " DRIVER_VERSION ")\n" |
647 | "%s\n" | ||
647 | "SUSPENDED (no register access)\n", | 648 | "SUSPENDED (no register access)\n", |
648 | hcd->self.controller->bus->name, | 649 | hcd->self.controller->bus->name, |
649 | hcd->self.controller->bus_id); | 650 | hcd->self.controller->bus_id, |
651 | hcd->product_desc); | ||
650 | goto done; | 652 | goto done; |
651 | } | 653 | } |
652 | 654 | ||
@@ -654,13 +656,53 @@ show_registers (struct class_device *class_dev, char *buf) | |||
654 | i = HC_VERSION(readl (&ehci->caps->hc_capbase)); | 656 | i = HC_VERSION(readl (&ehci->caps->hc_capbase)); |
655 | temp = scnprintf (next, size, | 657 | temp = scnprintf (next, size, |
656 | "bus %s, device %s (driver " DRIVER_VERSION ")\n" | 658 | "bus %s, device %s (driver " DRIVER_VERSION ")\n" |
659 | "%s\n" | ||
657 | "EHCI %x.%02x, hcd state %d\n", | 660 | "EHCI %x.%02x, hcd state %d\n", |
658 | hcd->self.controller->bus->name, | 661 | hcd->self.controller->bus->name, |
659 | hcd->self.controller->bus_id, | 662 | hcd->self.controller->bus_id, |
663 | hcd->product_desc, | ||
660 | i >> 8, i & 0x0ff, hcd->state); | 664 | i >> 8, i & 0x0ff, hcd->state); |
661 | size -= temp; | 665 | size -= temp; |
662 | next += temp; | 666 | next += temp; |
663 | 667 | ||
668 | #ifdef CONFIG_PCI | ||
669 | /* EHCI 0.96 and later may have "extended capabilities" */ | ||
670 | if (hcd->self.controller->bus == &pci_bus_type) { | ||
671 | struct pci_dev *pdev; | ||
672 | u32 offset, cap, cap2; | ||
673 | unsigned count = 256/4; | ||
674 | |||
675 | pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); | ||
676 | offset = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params)); | ||
677 | while (offset && count--) { | ||
678 | pci_read_config_dword (pdev, offset, &cap); | ||
679 | switch (cap & 0xff) { | ||
680 | case 1: | ||
681 | temp = scnprintf (next, size, | ||
682 | "ownership %08x%s%s\n", cap, | ||
683 | (cap & (1 << 24)) ? " linux" : "", | ||
684 | (cap & (1 << 16)) ? " firmware" : ""); | ||
685 | size -= temp; | ||
686 | next += temp; | ||
687 | |||
688 | offset += 4; | ||
689 | pci_read_config_dword (pdev, offset, &cap2); | ||
690 | temp = scnprintf (next, size, | ||
691 | "SMI sts/enable 0x%08x\n", cap2); | ||
692 | size -= temp; | ||
693 | next += temp; | ||
694 | break; | ||
695 | case 0: /* illegal reserved capability */ | ||
696 | cap = 0; | ||
697 | /* FALLTHROUGH */ | ||
698 | default: /* unknown */ | ||
699 | break; | ||
700 | } | ||
701 | temp = (cap >> 8) & 0xff; | ||
702 | } | ||
703 | } | ||
704 | #endif | ||
705 | |||
664 | // FIXME interpret both types of params | 706 | // FIXME interpret both types of params |
665 | i = readl (&ehci->caps->hcs_params); | 707 | i = readl (&ehci->caps->hcs_params); |
666 | temp = scnprintf (next, size, "structural params 0x%08x\n", i); | 708 | temp = scnprintf (next, size, "structural params 0x%08x\n", i); |
@@ -696,12 +738,19 @@ show_registers (struct class_device *class_dev, char *buf) | |||
696 | size -= temp; | 738 | size -= temp; |
697 | next += temp; | 739 | next += temp; |
698 | 740 | ||
699 | for (i = 0; i < HCS_N_PORTS (ehci->hcs_params); i++) { | 741 | for (i = 1; i <= HCS_N_PORTS (ehci->hcs_params); i++) { |
700 | temp = dbg_port_buf (scratch, sizeof scratch, label, i + 1, | 742 | temp = dbg_port_buf (scratch, sizeof scratch, label, i, |
701 | readl (&ehci->regs->port_status [i])); | 743 | readl (&ehci->regs->port_status [i - 1])); |
702 | temp = scnprintf (next, size, fmt, temp, scratch); | 744 | temp = scnprintf (next, size, fmt, temp, scratch); |
703 | size -= temp; | 745 | size -= temp; |
704 | next += temp; | 746 | next += temp; |
747 | if (i == HCS_DEBUG_PORT(ehci->hcs_params) && ehci->debug) { | ||
748 | temp = scnprintf (next, size, | ||
749 | " debug control %08x\n", | ||
750 | readl (&ehci->debug->control)); | ||
751 | size -= temp; | ||
752 | next += temp; | ||
753 | } | ||
705 | } | 754 | } |
706 | 755 | ||
707 | if (ehci->reclaim) { | 756 | if (ehci->reclaim) { |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index bc69bd7acebe..35248a37b717 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -304,30 +304,31 @@ static void ehci_watchdog (unsigned long param) | |||
304 | */ | 304 | */ |
305 | static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap) | 305 | static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap) |
306 | { | 306 | { |
307 | struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); | ||
308 | |||
309 | /* always say Linux will own the hardware */ | ||
310 | pci_write_config_byte(pdev, where + 3, 1); | ||
311 | |||
312 | /* maybe wait a while for BIOS to respond */ | ||
307 | if (cap & (1 << 16)) { | 313 | if (cap & (1 << 16)) { |
308 | int msec = 5000; | 314 | int msec = 5000; |
309 | struct pci_dev *pdev = | ||
310 | to_pci_dev(ehci_to_hcd(ehci)->self.controller); | ||
311 | 315 | ||
312 | /* request handoff to OS */ | ||
313 | cap |= 1 << 24; | ||
314 | pci_write_config_dword(pdev, where, cap); | ||
315 | |||
316 | /* and wait a while for it to happen */ | ||
317 | do { | 316 | do { |
318 | msleep(10); | 317 | msleep(10); |
319 | msec -= 10; | 318 | msec -= 10; |
320 | pci_read_config_dword(pdev, where, &cap); | 319 | pci_read_config_dword(pdev, where, &cap); |
321 | } while ((cap & (1 << 16)) && msec); | 320 | } while ((cap & (1 << 16)) && msec); |
322 | if (cap & (1 << 16)) { | 321 | if (cap & (1 << 16)) { |
323 | ehci_err (ehci, "BIOS handoff failed (%d, %04x)\n", | 322 | ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n", |
324 | where, cap); | 323 | where, cap); |
325 | // some BIOS versions seem buggy... | 324 | // some BIOS versions seem buggy... |
326 | // return 1; | 325 | // return 1; |
327 | ehci_warn (ehci, "continuing after BIOS bug...\n"); | 326 | ehci_warn (ehci, "continuing after BIOS bug...\n"); |
328 | return 0; | 327 | /* disable all SMIs, and clear "BIOS owns" flag */ |
329 | } | 328 | pci_write_config_dword(pdev, where + 4, 0); |
330 | ehci_dbg (ehci, "BIOS handoff succeeded\n"); | 329 | pci_write_config_byte(pdev, where + 2, 0); |
330 | } else | ||
331 | ehci_dbg(ehci, "BIOS handoff succeeded\n"); | ||
331 | } | 332 | } |
332 | return 0; | 333 | return 0; |
333 | } | 334 | } |
@@ -492,8 +493,6 @@ static int ehci_start (struct usb_hcd *hcd) | |||
492 | { | 493 | { |
493 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | 494 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); |
494 | u32 temp; | 495 | u32 temp; |
495 | struct usb_device *udev; | ||
496 | struct usb_bus *bus; | ||
497 | int retval; | 496 | int retval; |
498 | u32 hcc_params; | 497 | u32 hcc_params; |
499 | u8 sbrn = 0; | 498 | u8 sbrn = 0; |
@@ -588,8 +587,8 @@ static int ehci_start (struct usb_hcd *hcd) | |||
588 | writel (0, &ehci->regs->segment); | 587 | writel (0, &ehci->regs->segment); |
589 | #if 0 | 588 | #if 0 |
590 | // this is deeply broken on almost all architectures | 589 | // this is deeply broken on almost all architectures |
591 | if (!pci_set_dma_mask (to_pci_dev(hcd->self.controller), 0xffffffffffffffffULL)) | 590 | if (!dma_set_mask (hcd->self.controller, DMA_64BIT_MASK)) |
592 | ehci_info (ehci, "enabled 64bit PCI DMA\n"); | 591 | ehci_info (ehci, "enabled 64bit DMA\n"); |
593 | #endif | 592 | #endif |
594 | } | 593 | } |
595 | 594 | ||
@@ -631,17 +630,6 @@ static int ehci_start (struct usb_hcd *hcd) | |||
631 | 630 | ||
632 | /* set async sleep time = 10 us ... ? */ | 631 | /* set async sleep time = 10 us ... ? */ |
633 | 632 | ||
634 | /* wire up the root hub */ | ||
635 | bus = hcd_to_bus (hcd); | ||
636 | udev = first ? usb_alloc_dev (NULL, bus, 0) : bus->root_hub; | ||
637 | if (!udev) { | ||
638 | done2: | ||
639 | ehci_mem_cleanup (ehci); | ||
640 | return -ENOMEM; | ||
641 | } | ||
642 | udev->speed = USB_SPEED_HIGH; | ||
643 | udev->state = first ? USB_STATE_ATTACHED : USB_STATE_CONFIGURED; | ||
644 | |||
645 | /* | 633 | /* |
646 | * Start, enabling full USB 2.0 functionality ... usb 1.1 devices | 634 | * Start, enabling full USB 2.0 functionality ... usb 1.1 devices |
647 | * are explicitly handed to companion controller(s), so no TT is | 635 | * are explicitly handed to companion controller(s), so no TT is |
@@ -664,24 +652,6 @@ done2: | |||
664 | first ? "initialized" : "restarted", | 652 | first ? "initialized" : "restarted", |
665 | temp >> 8, temp & 0xff, DRIVER_VERSION); | 653 | temp >> 8, temp & 0xff, DRIVER_VERSION); |
666 | 654 | ||
667 | /* | ||
668 | * From here on, khubd concurrently accesses the root | ||
669 | * hub; drivers will be talking to enumerated devices. | ||
670 | * (On restart paths, khubd already knows about the root | ||
671 | * hub and could find work as soon as we wrote FLAG_CF.) | ||
672 | * | ||
673 | * Before this point the HC was idle/ready. After, khubd | ||
674 | * and device drivers may start it running. | ||
675 | */ | ||
676 | if (first && usb_hcd_register_root_hub (udev, hcd) != 0) { | ||
677 | if (hcd->state == HC_STATE_RUNNING) | ||
678 | ehci_quiesce (ehci); | ||
679 | ehci_reset (ehci); | ||
680 | usb_put_dev (udev); | ||
681 | retval = -ENODEV; | ||
682 | goto done2; | ||
683 | } | ||
684 | |||
685 | writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */ | 655 | writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */ |
686 | 656 | ||
687 | if (first) | 657 | if (first) |
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index d7b4f7939ded..36cc1f2218d5 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2001-2002 by David Brownell | 2 | * Copyright (C) 2001-2004 by David Brownell |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of the GNU General Public License as published by the | 5 | * under the terms of the GNU General Public License as published by the |
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 7df9b9af54f6..45d89a7083b1 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2001-2002 by David Brownell | 2 | * Copyright (C) 2001-2004 by David Brownell |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of the GNU General Public License as published by the | 5 | * under the terms of the GNU General Public License as published by the |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 2fa1ffee5ff3..c2104cad4033 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -637,9 +637,8 @@ iso_stream_alloc (int mem_flags) | |||
637 | { | 637 | { |
638 | struct ehci_iso_stream *stream; | 638 | struct ehci_iso_stream *stream; |
639 | 639 | ||
640 | stream = kmalloc(sizeof *stream, mem_flags); | 640 | stream = kcalloc(1, sizeof *stream, mem_flags); |
641 | if (likely (stream != NULL)) { | 641 | if (likely (stream != NULL)) { |
642 | memset (stream, 0, sizeof(*stream)); | ||
643 | INIT_LIST_HEAD(&stream->td_list); | 642 | INIT_LIST_HEAD(&stream->td_list); |
644 | INIT_LIST_HEAD(&stream->free_list); | 643 | INIT_LIST_HEAD(&stream->free_list); |
645 | stream->next_uframe = -1; | 644 | stream->next_uframe = -1; |
@@ -894,7 +893,7 @@ itd_sched_init ( | |||
894 | trans |= length << 16; | 893 | trans |= length << 16; |
895 | uframe->transaction = cpu_to_le32 (trans); | 894 | uframe->transaction = cpu_to_le32 (trans); |
896 | 895 | ||
897 | /* might need to cross a buffer page within a td */ | 896 | /* might need to cross a buffer page within a uframe */ |
898 | uframe->bufp = (buf & ~(u64)0x0fff); | 897 | uframe->bufp = (buf & ~(u64)0x0fff); |
899 | buf += length; | 898 | buf += length; |
900 | if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff)))) | 899 | if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff)))) |
@@ -1194,6 +1193,7 @@ itd_init (struct ehci_iso_stream *stream, struct ehci_itd *itd) | |||
1194 | { | 1193 | { |
1195 | int i; | 1194 | int i; |
1196 | 1195 | ||
1196 | /* it's been recently zeroed */ | ||
1197 | itd->hw_next = EHCI_LIST_END; | 1197 | itd->hw_next = EHCI_LIST_END; |
1198 | itd->hw_bufp [0] = stream->buf0; | 1198 | itd->hw_bufp [0] = stream->buf0; |
1199 | itd->hw_bufp [1] = stream->buf1; | 1199 | itd->hw_bufp [1] = stream->buf1; |
@@ -1210,8 +1210,7 @@ itd_patch ( | |||
1210 | struct ehci_itd *itd, | 1210 | struct ehci_itd *itd, |
1211 | struct ehci_iso_sched *iso_sched, | 1211 | struct ehci_iso_sched *iso_sched, |
1212 | unsigned index, | 1212 | unsigned index, |
1213 | u16 uframe, | 1213 | u16 uframe |
1214 | int first | ||
1215 | ) | 1214 | ) |
1216 | { | 1215 | { |
1217 | struct ehci_iso_packet *uf = &iso_sched->packet [index]; | 1216 | struct ehci_iso_packet *uf = &iso_sched->packet [index]; |
@@ -1228,7 +1227,7 @@ itd_patch ( | |||
1228 | itd->hw_bufp_hi [pg] |= cpu_to_le32 ((u32)(uf->bufp >> 32)); | 1227 | itd->hw_bufp_hi [pg] |= cpu_to_le32 ((u32)(uf->bufp >> 32)); |
1229 | 1228 | ||
1230 | /* iso_frame_desc[].offset must be strictly increasing */ | 1229 | /* iso_frame_desc[].offset must be strictly increasing */ |
1231 | if (unlikely (!first && uf->cross)) { | 1230 | if (unlikely (uf->cross)) { |
1232 | u64 bufp = uf->bufp + 4096; | 1231 | u64 bufp = uf->bufp + 4096; |
1233 | itd->pg = ++pg; | 1232 | itd->pg = ++pg; |
1234 | itd->hw_bufp [pg] |= cpu_to_le32 (bufp & ~(u32)0); | 1233 | itd->hw_bufp [pg] |= cpu_to_le32 (bufp & ~(u32)0); |
@@ -1257,7 +1256,7 @@ itd_link_urb ( | |||
1257 | struct ehci_iso_stream *stream | 1256 | struct ehci_iso_stream *stream |
1258 | ) | 1257 | ) |
1259 | { | 1258 | { |
1260 | int packet, first = 1; | 1259 | int packet; |
1261 | unsigned next_uframe, uframe, frame; | 1260 | unsigned next_uframe, uframe, frame; |
1262 | struct ehci_iso_sched *iso_sched = urb->hcpriv; | 1261 | struct ehci_iso_sched *iso_sched = urb->hcpriv; |
1263 | struct ehci_itd *itd; | 1262 | struct ehci_itd *itd; |
@@ -1290,7 +1289,6 @@ itd_link_urb ( | |||
1290 | list_move_tail (&itd->itd_list, &stream->td_list); | 1289 | list_move_tail (&itd->itd_list, &stream->td_list); |
1291 | itd->stream = iso_stream_get (stream); | 1290 | itd->stream = iso_stream_get (stream); |
1292 | itd->urb = usb_get_urb (urb); | 1291 | itd->urb = usb_get_urb (urb); |
1293 | first = 1; | ||
1294 | itd_init (stream, itd); | 1292 | itd_init (stream, itd); |
1295 | } | 1293 | } |
1296 | 1294 | ||
@@ -1298,8 +1296,7 @@ itd_link_urb ( | |||
1298 | frame = next_uframe >> 3; | 1296 | frame = next_uframe >> 3; |
1299 | 1297 | ||
1300 | itd->usecs [uframe] = stream->usecs; | 1298 | itd->usecs [uframe] = stream->usecs; |
1301 | itd_patch (itd, iso_sched, packet, uframe, first); | 1299 | itd_patch (itd, iso_sched, packet, uframe); |
1302 | first = 0; | ||
1303 | 1300 | ||
1304 | next_uframe += stream->interval; | 1301 | next_uframe += stream->interval; |
1305 | stream->depth += stream->interval; | 1302 | stream->depth += stream->interval; |
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c new file mode 100644 index 000000000000..ff0a168e8eed --- /dev/null +++ b/drivers/usb/host/isp116x-hcd.c | |||
@@ -0,0 +1,1875 @@ | |||
1 | /* | ||
2 | * ISP116x HCD (Host Controller Driver) for USB. | ||
3 | * | ||
4 | * Derived from the SL811 HCD, rewritten for ISP116x. | ||
5 | * Copyright (C) 2005 Olav Kongas <ok@artecdesign.ee> | ||
6 | * | ||
7 | * Portions: | ||
8 | * Copyright (C) 2004 Psion Teklogix (for NetBook PRO) | ||
9 | * Copyright (C) 2004 David Brownell | ||
10 | * | ||
11 | * Periodic scheduling is based on Roman's OHCI code | ||
12 | * Copyright (C) 1999 Roman Weissgaerber | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | /* | ||
17 | * The driver basically works. A number of people have used it with a range | ||
18 | * of devices. | ||
19 | * | ||
20 | *The driver passes all usbtests 1-14. | ||
21 | * | ||
22 | * Suspending/resuming of root hub via sysfs works. Remote wakeup works too. | ||
23 | * And suspending/resuming of platform device works too. Suspend/resume | ||
24 | * via HCD operations vector is not implemented. | ||
25 | * | ||
26 | * Iso transfer support is not implemented. Adding this would include | ||
27 | * implementing recovery from the failure to service the processed ITL | ||
28 | * fifo ram in time, which will involve chip reset. | ||
29 | * | ||
30 | * TODO: | ||
31 | + More testing of suspend/resume. | ||
32 | */ | ||
33 | |||
34 | /* | ||
35 | ISP116x chips require certain delays between accesses to its | ||
36 | registers. The following timing options exist. | ||
37 | |||
38 | 1. Configure your memory controller (the best) | ||
39 | 2. Implement platform-specific delay function possibly | ||
40 | combined with configuring the memory controller; see | ||
41 | include/linux/usb-isp116x.h for more info. Some broken | ||
42 | memory controllers line LH7A400 SMC need this. Also, | ||
43 | uncomment for that to work the following | ||
44 | USE_PLATFORM_DELAY macro. | ||
45 | 3. Use ndelay (easiest, poorest). For that, uncomment | ||
46 | the following USE_NDELAY macro. | ||
47 | */ | ||
48 | #define USE_PLATFORM_DELAY | ||
49 | //#define USE_NDELAY | ||
50 | |||
51 | //#define DEBUG | ||
52 | //#define VERBOSE | ||
53 | /* Transfer descriptors. See dump_ptd() for printout format */ | ||
54 | //#define PTD_TRACE | ||
55 | /* enqueuing/finishing log of urbs */ | ||
56 | //#define URB_TRACE | ||
57 | |||
58 | #include <linux/config.h> | ||
59 | #include <linux/module.h> | ||
60 | #include <linux/moduleparam.h> | ||
61 | #include <linux/kernel.h> | ||
62 | #include <linux/delay.h> | ||
63 | #include <linux/ioport.h> | ||
64 | #include <linux/sched.h> | ||
65 | #include <linux/slab.h> | ||
66 | #include <linux/smp_lock.h> | ||
67 | #include <linux/errno.h> | ||
68 | #include <linux/init.h> | ||
69 | #include <linux/list.h> | ||
70 | #include <linux/interrupt.h> | ||
71 | #include <linux/usb.h> | ||
72 | #include <linux/usb_isp116x.h> | ||
73 | |||
74 | #include <asm/io.h> | ||
75 | #include <asm/irq.h> | ||
76 | #include <asm/system.h> | ||
77 | #include <asm/byteorder.h> | ||
78 | |||
79 | #ifndef DEBUG | ||
80 | # define STUB_DEBUG_FILE | ||
81 | #endif | ||
82 | |||
83 | #include "../core/hcd.h" | ||
84 | #include "isp116x.h" | ||
85 | |||
86 | #define DRIVER_VERSION "08 Apr 2005" | ||
87 | #define DRIVER_DESC "ISP116x USB Host Controller Driver" | ||
88 | |||
89 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
90 | MODULE_LICENSE("GPL"); | ||
91 | |||
92 | static const char hcd_name[] = "isp116x-hcd"; | ||
93 | |||
94 | /*-----------------------------------------------------------------*/ | ||
95 | |||
96 | /* | ||
97 | Write len bytes to fifo, pad till 32-bit boundary | ||
98 | */ | ||
99 | static void write_ptddata_to_fifo(struct isp116x *isp116x, void *buf, int len) | ||
100 | { | ||
101 | u8 *dp = (u8 *) buf; | ||
102 | u16 *dp2 = (u16 *) buf; | ||
103 | u16 w; | ||
104 | int quot = len % 4; | ||
105 | |||
106 | if ((unsigned long)dp2 & 1) { | ||
107 | /* not aligned */ | ||
108 | for (; len > 1; len -= 2) { | ||
109 | w = *dp++; | ||
110 | w |= *dp++ << 8; | ||
111 | isp116x_raw_write_data16(isp116x, w); | ||
112 | } | ||
113 | if (len) | ||
114 | isp116x_write_data16(isp116x, (u16) * dp); | ||
115 | } else { | ||
116 | /* aligned */ | ||
117 | for (; len > 1; len -= 2) | ||
118 | isp116x_raw_write_data16(isp116x, *dp2++); | ||
119 | if (len) | ||
120 | isp116x_write_data16(isp116x, 0xff & *((u8 *) dp2)); | ||
121 | } | ||
122 | if (quot == 1 || quot == 2) | ||
123 | isp116x_raw_write_data16(isp116x, 0); | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | Read len bytes from fifo and then read till 32-bit boundary. | ||
128 | */ | ||
129 | static void read_ptddata_from_fifo(struct isp116x *isp116x, void *buf, int len) | ||
130 | { | ||
131 | u8 *dp = (u8 *) buf; | ||
132 | u16 *dp2 = (u16 *) buf; | ||
133 | u16 w; | ||
134 | int quot = len % 4; | ||
135 | |||
136 | if ((unsigned long)dp2 & 1) { | ||
137 | /* not aligned */ | ||
138 | for (; len > 1; len -= 2) { | ||
139 | w = isp116x_raw_read_data16(isp116x); | ||
140 | *dp++ = w & 0xff; | ||
141 | *dp++ = (w >> 8) & 0xff; | ||
142 | } | ||
143 | if (len) | ||
144 | *dp = 0xff & isp116x_read_data16(isp116x); | ||
145 | } else { | ||
146 | /* aligned */ | ||
147 | for (; len > 1; len -= 2) | ||
148 | *dp2++ = isp116x_raw_read_data16(isp116x); | ||
149 | if (len) | ||
150 | *(u8 *) dp2 = 0xff & isp116x_read_data16(isp116x); | ||
151 | } | ||
152 | if (quot == 1 || quot == 2) | ||
153 | isp116x_raw_read_data16(isp116x); | ||
154 | } | ||
155 | |||
156 | /* | ||
157 | Write ptd's and data for scheduled transfers into | ||
158 | the fifo ram. Fifo must be empty and ready. | ||
159 | */ | ||
160 | static void pack_fifo(struct isp116x *isp116x) | ||
161 | { | ||
162 | struct isp116x_ep *ep; | ||
163 | struct ptd *ptd; | ||
164 | int buflen = isp116x->atl_last_dir == PTD_DIR_IN | ||
165 | ? isp116x->atl_bufshrt : isp116x->atl_buflen; | ||
166 | int ptd_count = 0; | ||
167 | |||
168 | isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT); | ||
169 | isp116x_write_reg16(isp116x, HCXFERCTR, buflen); | ||
170 | isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET); | ||
171 | for (ep = isp116x->atl_active; ep; ep = ep->active) { | ||
172 | ++ptd_count; | ||
173 | ptd = &ep->ptd; | ||
174 | dump_ptd(ptd); | ||
175 | dump_ptd_out_data(ptd, ep->data); | ||
176 | isp116x_write_data16(isp116x, ptd->count); | ||
177 | isp116x_write_data16(isp116x, ptd->mps); | ||
178 | isp116x_write_data16(isp116x, ptd->len); | ||
179 | isp116x_write_data16(isp116x, ptd->faddr); | ||
180 | buflen -= sizeof(struct ptd); | ||
181 | /* Skip writing data for last IN PTD */ | ||
182 | if (ep->active || (isp116x->atl_last_dir != PTD_DIR_IN)) { | ||
183 | write_ptddata_to_fifo(isp116x, ep->data, ep->length); | ||
184 | buflen -= ALIGN(ep->length, 4); | ||
185 | } | ||
186 | } | ||
187 | BUG_ON(buflen); | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | Read the processed ptd's and data from fifo ram back to | ||
192 | URBs' buffers. Fifo must be full and done | ||
193 | */ | ||
194 | static void unpack_fifo(struct isp116x *isp116x) | ||
195 | { | ||
196 | struct isp116x_ep *ep; | ||
197 | struct ptd *ptd; | ||
198 | int buflen = isp116x->atl_last_dir == PTD_DIR_IN | ||
199 | ? isp116x->atl_buflen : isp116x->atl_bufshrt; | ||
200 | |||
201 | isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT); | ||
202 | isp116x_write_reg16(isp116x, HCXFERCTR, buflen); | ||
203 | isp116x_write_addr(isp116x, HCATLPORT); | ||
204 | for (ep = isp116x->atl_active; ep; ep = ep->active) { | ||
205 | ptd = &ep->ptd; | ||
206 | ptd->count = isp116x_read_data16(isp116x); | ||
207 | ptd->mps = isp116x_read_data16(isp116x); | ||
208 | ptd->len = isp116x_read_data16(isp116x); | ||
209 | ptd->faddr = isp116x_read_data16(isp116x); | ||
210 | buflen -= sizeof(struct ptd); | ||
211 | /* Skip reading data for last Setup or Out PTD */ | ||
212 | if (ep->active || (isp116x->atl_last_dir == PTD_DIR_IN)) { | ||
213 | read_ptddata_from_fifo(isp116x, ep->data, ep->length); | ||
214 | buflen -= ALIGN(ep->length, 4); | ||
215 | } | ||
216 | dump_ptd(ptd); | ||
217 | dump_ptd_in_data(ptd, ep->data); | ||
218 | } | ||
219 | BUG_ON(buflen); | ||
220 | } | ||
221 | |||
222 | /*---------------------------------------------------------------*/ | ||
223 | |||
224 | /* | ||
225 | Set up PTD's. | ||
226 | */ | ||
227 | static void preproc_atl_queue(struct isp116x *isp116x) | ||
228 | { | ||
229 | struct isp116x_ep *ep; | ||
230 | struct urb *urb; | ||
231 | struct ptd *ptd; | ||
232 | u16 toggle, dir, len; | ||
233 | |||
234 | for (ep = isp116x->atl_active; ep; ep = ep->active) { | ||
235 | BUG_ON(list_empty(&ep->hep->urb_list)); | ||
236 | urb = container_of(ep->hep->urb_list.next, | ||
237 | struct urb, urb_list); | ||
238 | ptd = &ep->ptd; | ||
239 | len = ep->length; | ||
240 | spin_lock(&urb->lock); | ||
241 | ep->data = (unsigned char *)urb->transfer_buffer | ||
242 | + urb->actual_length; | ||
243 | |||
244 | switch (ep->nextpid) { | ||
245 | case USB_PID_IN: | ||
246 | toggle = usb_gettoggle(urb->dev, ep->epnum, 0); | ||
247 | dir = PTD_DIR_IN; | ||
248 | break; | ||
249 | case USB_PID_OUT: | ||
250 | toggle = usb_gettoggle(urb->dev, ep->epnum, 1); | ||
251 | dir = PTD_DIR_OUT; | ||
252 | break; | ||
253 | case USB_PID_SETUP: | ||
254 | toggle = 0; | ||
255 | dir = PTD_DIR_SETUP; | ||
256 | len = sizeof(struct usb_ctrlrequest); | ||
257 | ep->data = urb->setup_packet; | ||
258 | break; | ||
259 | case USB_PID_ACK: | ||
260 | toggle = 1; | ||
261 | len = 0; | ||
262 | dir = (urb->transfer_buffer_length | ||
263 | && usb_pipein(urb->pipe)) | ||
264 | ? PTD_DIR_OUT : PTD_DIR_IN; | ||
265 | break; | ||
266 | default: | ||
267 | /* To please gcc */ | ||
268 | toggle = dir = 0; | ||
269 | ERR("%s %d: ep->nextpid %d\n", __func__, __LINE__, | ||
270 | ep->nextpid); | ||
271 | BUG_ON(1); | ||
272 | } | ||
273 | |||
274 | ptd->count = PTD_CC_MSK | PTD_ACTIVE_MSK | PTD_TOGGLE(toggle); | ||
275 | ptd->mps = PTD_MPS(ep->maxpacket) | ||
276 | | PTD_SPD(urb->dev->speed == USB_SPEED_LOW) | ||
277 | | PTD_EP(ep->epnum); | ||
278 | ptd->len = PTD_LEN(len) | PTD_DIR(dir); | ||
279 | ptd->faddr = PTD_FA(usb_pipedevice(urb->pipe)); | ||
280 | spin_unlock(&urb->lock); | ||
281 | if (!ep->active) { | ||
282 | ptd->mps |= PTD_LAST_MSK; | ||
283 | isp116x->atl_last_dir = dir; | ||
284 | } | ||
285 | isp116x->atl_bufshrt = sizeof(struct ptd) + isp116x->atl_buflen; | ||
286 | isp116x->atl_buflen = isp116x->atl_bufshrt + ALIGN(len, 4); | ||
287 | } | ||
288 | } | ||
289 | |||
290 | /* | ||
291 | Analyze transfer results, handle partial transfers and errors | ||
292 | */ | ||
293 | static void postproc_atl_queue(struct isp116x *isp116x) | ||
294 | { | ||
295 | struct isp116x_ep *ep; | ||
296 | struct urb *urb; | ||
297 | struct usb_device *udev; | ||
298 | struct ptd *ptd; | ||
299 | int short_not_ok; | ||
300 | u8 cc; | ||
301 | |||
302 | for (ep = isp116x->atl_active; ep; ep = ep->active) { | ||
303 | BUG_ON(list_empty(&ep->hep->urb_list)); | ||
304 | urb = | ||
305 | container_of(ep->hep->urb_list.next, struct urb, urb_list); | ||
306 | udev = urb->dev; | ||
307 | ptd = &ep->ptd; | ||
308 | cc = PTD_GET_CC(ptd); | ||
309 | |||
310 | spin_lock(&urb->lock); | ||
311 | short_not_ok = 1; | ||
312 | |||
313 | /* Data underrun is special. For allowed underrun | ||
314 | we clear the error and continue as normal. For | ||
315 | forbidden underrun we finish the DATA stage | ||
316 | immediately while for control transfer, | ||
317 | we do a STATUS stage. */ | ||
318 | if (cc == TD_DATAUNDERRUN) { | ||
319 | if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) { | ||
320 | DBG("Allowed data underrun\n"); | ||
321 | cc = TD_CC_NOERROR; | ||
322 | short_not_ok = 0; | ||
323 | } else { | ||
324 | ep->error_count = 1; | ||
325 | if (usb_pipecontrol(urb->pipe)) | ||
326 | ep->nextpid = USB_PID_ACK; | ||
327 | else | ||
328 | usb_settoggle(udev, ep->epnum, | ||
329 | ep->nextpid == | ||
330 | USB_PID_OUT, | ||
331 | PTD_GET_TOGGLE(ptd) ^ 1); | ||
332 | urb->status = cc_to_error[TD_DATAUNDERRUN]; | ||
333 | spin_unlock(&urb->lock); | ||
334 | continue; | ||
335 | } | ||
336 | } | ||
337 | /* Keep underrun error through the STATUS stage */ | ||
338 | if (urb->status == cc_to_error[TD_DATAUNDERRUN]) | ||
339 | cc = TD_DATAUNDERRUN; | ||
340 | |||
341 | if (cc != TD_CC_NOERROR && cc != TD_NOTACCESSED | ||
342 | && (++ep->error_count >= 3 || cc == TD_CC_STALL | ||
343 | || cc == TD_DATAOVERRUN)) { | ||
344 | if (urb->status == -EINPROGRESS) | ||
345 | urb->status = cc_to_error[cc]; | ||
346 | if (ep->nextpid == USB_PID_ACK) | ||
347 | ep->nextpid = 0; | ||
348 | spin_unlock(&urb->lock); | ||
349 | continue; | ||
350 | } | ||
351 | /* According to usb spec, zero-length Int transfer signals | ||
352 | finishing of the urb. Hey, does this apply only | ||
353 | for IN endpoints? */ | ||
354 | if (usb_pipeint(urb->pipe) && !PTD_GET_LEN(ptd)) { | ||
355 | if (urb->status == -EINPROGRESS) | ||
356 | urb->status = 0; | ||
357 | spin_unlock(&urb->lock); | ||
358 | continue; | ||
359 | } | ||
360 | |||
361 | /* Relax after previously failed, but later succeeded | ||
362 | or correctly NAK'ed retransmission attempt */ | ||
363 | if (ep->error_count | ||
364 | && (cc == TD_CC_NOERROR || cc == TD_NOTACCESSED)) | ||
365 | ep->error_count = 0; | ||
366 | |||
367 | /* Take into account idiosyncracies of the isp116x chip | ||
368 | regarding toggle bit for failed transfers */ | ||
369 | if (ep->nextpid == USB_PID_OUT) | ||
370 | usb_settoggle(udev, ep->epnum, 1, PTD_GET_TOGGLE(ptd) | ||
371 | ^ (ep->error_count > 0)); | ||
372 | else if (ep->nextpid == USB_PID_IN) | ||
373 | usb_settoggle(udev, ep->epnum, 0, PTD_GET_TOGGLE(ptd) | ||
374 | ^ (ep->error_count > 0)); | ||
375 | |||
376 | switch (ep->nextpid) { | ||
377 | case USB_PID_IN: | ||
378 | case USB_PID_OUT: | ||
379 | urb->actual_length += PTD_GET_COUNT(ptd); | ||
380 | if (PTD_GET_ACTIVE(ptd) | ||
381 | || (cc != TD_CC_NOERROR && cc < 0x0E)) | ||
382 | break; | ||
383 | if (urb->transfer_buffer_length != urb->actual_length) { | ||
384 | if (short_not_ok) | ||
385 | break; | ||
386 | } else { | ||
387 | if (urb->transfer_flags & URB_ZERO_PACKET | ||
388 | && ep->nextpid == USB_PID_OUT | ||
389 | && !(PTD_GET_COUNT(ptd) % ep->maxpacket)) { | ||
390 | DBG("Zero packet requested\n"); | ||
391 | break; | ||
392 | } | ||
393 | } | ||
394 | /* All data for this URB is transferred, let's finish */ | ||
395 | if (usb_pipecontrol(urb->pipe)) | ||
396 | ep->nextpid = USB_PID_ACK; | ||
397 | else if (urb->status == -EINPROGRESS) | ||
398 | urb->status = 0; | ||
399 | break; | ||
400 | case USB_PID_SETUP: | ||
401 | if (PTD_GET_ACTIVE(ptd) | ||
402 | || (cc != TD_CC_NOERROR && cc < 0x0E)) | ||
403 | break; | ||
404 | if (urb->transfer_buffer_length == urb->actual_length) | ||
405 | ep->nextpid = USB_PID_ACK; | ||
406 | else if (usb_pipeout(urb->pipe)) { | ||
407 | usb_settoggle(udev, 0, 1, 1); | ||
408 | ep->nextpid = USB_PID_OUT; | ||
409 | } else { | ||
410 | usb_settoggle(udev, 0, 0, 1); | ||
411 | ep->nextpid = USB_PID_IN; | ||
412 | } | ||
413 | break; | ||
414 | case USB_PID_ACK: | ||
415 | if (PTD_GET_ACTIVE(ptd) | ||
416 | || (cc != TD_CC_NOERROR && cc < 0x0E)) | ||
417 | break; | ||
418 | if (urb->status == -EINPROGRESS) | ||
419 | urb->status = 0; | ||
420 | ep->nextpid = 0; | ||
421 | break; | ||
422 | default: | ||
423 | BUG_ON(1); | ||
424 | } | ||
425 | spin_unlock(&urb->lock); | ||
426 | } | ||
427 | } | ||
428 | |||
429 | /* | ||
430 | Take done or failed requests out of schedule. Give back | ||
431 | processed urbs. | ||
432 | */ | ||
433 | static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep, | ||
434 | struct urb *urb, struct pt_regs *regs) | ||
435 | __releases(isp116x->lock) __acquires(isp116x->lock) | ||
436 | { | ||
437 | unsigned i; | ||
438 | |||
439 | urb->hcpriv = NULL; | ||
440 | ep->error_count = 0; | ||
441 | |||
442 | if (usb_pipecontrol(urb->pipe)) | ||
443 | ep->nextpid = USB_PID_SETUP; | ||
444 | |||
445 | urb_dbg(urb, "Finish"); | ||
446 | |||
447 | spin_unlock(&isp116x->lock); | ||
448 | usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb, regs); | ||
449 | spin_lock(&isp116x->lock); | ||
450 | |||
451 | /* take idle endpoints out of the schedule */ | ||
452 | if (!list_empty(&ep->hep->urb_list)) | ||
453 | return; | ||
454 | |||
455 | /* async deschedule */ | ||
456 | if (!list_empty(&ep->schedule)) { | ||
457 | list_del_init(&ep->schedule); | ||
458 | return; | ||
459 | } | ||
460 | |||
461 | /* periodic deschedule */ | ||
462 | DBG("deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch); | ||
463 | for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) { | ||
464 | struct isp116x_ep *temp; | ||
465 | struct isp116x_ep **prev = &isp116x->periodic[i]; | ||
466 | |||
467 | while (*prev && ((temp = *prev) != ep)) | ||
468 | prev = &temp->next; | ||
469 | if (*prev) | ||
470 | *prev = ep->next; | ||
471 | isp116x->load[i] -= ep->load; | ||
472 | } | ||
473 | ep->branch = PERIODIC_SIZE; | ||
474 | isp116x_to_hcd(isp116x)->self.bandwidth_allocated -= | ||
475 | ep->load / ep->period; | ||
476 | |||
477 | /* switch irq type? */ | ||
478 | if (!--isp116x->periodic_count) { | ||
479 | isp116x->irqenb &= ~HCuPINT_SOF; | ||
480 | isp116x->irqenb |= HCuPINT_ATL; | ||
481 | } | ||
482 | } | ||
483 | |||
484 | /* | ||
485 | Scan transfer lists, schedule transfers, send data off | ||
486 | to chip. | ||
487 | */ | ||
488 | static void start_atl_transfers(struct isp116x *isp116x) | ||
489 | { | ||
490 | struct isp116x_ep *last_ep = NULL, *ep; | ||
491 | struct urb *urb; | ||
492 | u16 load = 0; | ||
493 | int len, index, speed, byte_time; | ||
494 | |||
495 | if (atomic_read(&isp116x->atl_finishing)) | ||
496 | return; | ||
497 | |||
498 | if (!HC_IS_RUNNING(isp116x_to_hcd(isp116x)->state)) | ||
499 | return; | ||
500 | |||
501 | /* FIFO not empty? */ | ||
502 | if (isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_FULL) | ||
503 | return; | ||
504 | |||
505 | isp116x->atl_active = NULL; | ||
506 | isp116x->atl_buflen = isp116x->atl_bufshrt = 0; | ||
507 | |||
508 | /* Schedule int transfers */ | ||
509 | if (isp116x->periodic_count) { | ||
510 | isp116x->fmindex = index = | ||
511 | (isp116x->fmindex + 1) & (PERIODIC_SIZE - 1); | ||
512 | if ((load = isp116x->load[index])) { | ||
513 | /* Bring all int transfers for this frame | ||
514 | into the active queue */ | ||
515 | isp116x->atl_active = last_ep = | ||
516 | isp116x->periodic[index]; | ||
517 | while (last_ep->next) | ||
518 | last_ep = (last_ep->active = last_ep->next); | ||
519 | last_ep->active = NULL; | ||
520 | } | ||
521 | } | ||
522 | |||
523 | /* Schedule control/bulk transfers */ | ||
524 | list_for_each_entry(ep, &isp116x->async, schedule) { | ||
525 | urb = container_of(ep->hep->urb_list.next, | ||
526 | struct urb, urb_list); | ||
527 | speed = urb->dev->speed; | ||
528 | byte_time = speed == USB_SPEED_LOW | ||
529 | ? BYTE_TIME_LOWSPEED : BYTE_TIME_FULLSPEED; | ||
530 | |||
531 | if (ep->nextpid == USB_PID_SETUP) { | ||
532 | len = sizeof(struct usb_ctrlrequest); | ||
533 | } else if (ep->nextpid == USB_PID_ACK) { | ||
534 | len = 0; | ||
535 | } else { | ||
536 | /* Find current free length ... */ | ||
537 | len = (MAX_LOAD_LIMIT - load) / byte_time; | ||
538 | |||
539 | /* ... then limit it to configured max size ... */ | ||
540 | len = min(len, speed == USB_SPEED_LOW ? | ||
541 | MAX_TRANSFER_SIZE_LOWSPEED : | ||
542 | MAX_TRANSFER_SIZE_FULLSPEED); | ||
543 | |||
544 | /* ... and finally cut to the multiple of MaxPacketSize, | ||
545 | or to the real length if there's enough room. */ | ||
546 | if (len < | ||
547 | (urb->transfer_buffer_length - | ||
548 | urb->actual_length)) { | ||
549 | len -= len % ep->maxpacket; | ||
550 | if (!len) | ||
551 | continue; | ||
552 | } else | ||
553 | len = urb->transfer_buffer_length - | ||
554 | urb->actual_length; | ||
555 | BUG_ON(len < 0); | ||
556 | } | ||
557 | |||
558 | load += len * byte_time; | ||
559 | if (load > MAX_LOAD_LIMIT) | ||
560 | break; | ||
561 | |||
562 | ep->active = NULL; | ||
563 | ep->length = len; | ||
564 | if (last_ep) | ||
565 | last_ep->active = ep; | ||
566 | else | ||
567 | isp116x->atl_active = ep; | ||
568 | last_ep = ep; | ||
569 | } | ||
570 | |||
571 | /* Avoid starving of endpoints */ | ||
572 | if ((&isp116x->async)->next != (&isp116x->async)->prev) | ||
573 | list_move(&isp116x->async, (&isp116x->async)->next); | ||
574 | |||
575 | if (isp116x->atl_active) { | ||
576 | preproc_atl_queue(isp116x); | ||
577 | pack_fifo(isp116x); | ||
578 | } | ||
579 | } | ||
580 | |||
581 | /* | ||
582 | Finish the processed transfers | ||
583 | */ | ||
584 | static void finish_atl_transfers(struct isp116x *isp116x, struct pt_regs *regs) | ||
585 | { | ||
586 | struct isp116x_ep *ep; | ||
587 | struct urb *urb; | ||
588 | |||
589 | if (!isp116x->atl_active) | ||
590 | return; | ||
591 | /* Fifo not ready? */ | ||
592 | if (!(isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_DONE)) | ||
593 | return; | ||
594 | |||
595 | atomic_inc(&isp116x->atl_finishing); | ||
596 | unpack_fifo(isp116x); | ||
597 | postproc_atl_queue(isp116x); | ||
598 | for (ep = isp116x->atl_active; ep; ep = ep->active) { | ||
599 | urb = | ||
600 | container_of(ep->hep->urb_list.next, struct urb, urb_list); | ||
601 | /* USB_PID_ACK check here avoids finishing of | ||
602 | control transfers, for which TD_DATAUNDERRUN | ||
603 | occured, while URB_SHORT_NOT_OK was set */ | ||
604 | if (urb && urb->status != -EINPROGRESS | ||
605 | && ep->nextpid != USB_PID_ACK) | ||
606 | finish_request(isp116x, ep, urb, regs); | ||
607 | } | ||
608 | atomic_dec(&isp116x->atl_finishing); | ||
609 | } | ||
610 | |||
611 | static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs) | ||
612 | { | ||
613 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
614 | u16 irqstat; | ||
615 | irqreturn_t ret = IRQ_NONE; | ||
616 | |||
617 | spin_lock(&isp116x->lock); | ||
618 | isp116x_write_reg16(isp116x, HCuPINTENB, 0); | ||
619 | irqstat = isp116x_read_reg16(isp116x, HCuPINT); | ||
620 | isp116x_write_reg16(isp116x, HCuPINT, irqstat); | ||
621 | |||
622 | if (irqstat & (HCuPINT_ATL | HCuPINT_SOF)) { | ||
623 | ret = IRQ_HANDLED; | ||
624 | finish_atl_transfers(isp116x, regs); | ||
625 | } | ||
626 | |||
627 | if (irqstat & HCuPINT_OPR) { | ||
628 | u32 intstat = isp116x_read_reg32(isp116x, HCINTSTAT); | ||
629 | isp116x_write_reg32(isp116x, HCINTSTAT, intstat); | ||
630 | if (intstat & HCINT_UE) { | ||
631 | ERR("Unrecoverable error\n"); | ||
632 | /* What should we do here? Reset? */ | ||
633 | } | ||
634 | if (intstat & HCINT_RHSC) { | ||
635 | isp116x->rhstatus = | ||
636 | isp116x_read_reg32(isp116x, HCRHSTATUS); | ||
637 | isp116x->rhport[0] = | ||
638 | isp116x_read_reg32(isp116x, HCRHPORT1); | ||
639 | isp116x->rhport[1] = | ||
640 | isp116x_read_reg32(isp116x, HCRHPORT2); | ||
641 | } | ||
642 | if (intstat & HCINT_RD) { | ||
643 | DBG("---- remote wakeup\n"); | ||
644 | schedule_work(&isp116x->rh_resume); | ||
645 | ret = IRQ_HANDLED; | ||
646 | } | ||
647 | irqstat &= ~HCuPINT_OPR; | ||
648 | ret = IRQ_HANDLED; | ||
649 | } | ||
650 | |||
651 | if (irqstat & (HCuPINT_ATL | HCuPINT_SOF)) { | ||
652 | start_atl_transfers(isp116x); | ||
653 | } | ||
654 | |||
655 | isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb); | ||
656 | spin_unlock(&isp116x->lock); | ||
657 | return ret; | ||
658 | } | ||
659 | |||
660 | /*-----------------------------------------------------------------*/ | ||
661 | |||
662 | /* usb 1.1 says max 90% of a frame is available for periodic transfers. | ||
663 | * this driver doesn't promise that much since it's got to handle an | ||
664 | * IRQ per packet; irq handling latencies also use up that time. | ||
665 | */ | ||
666 | |||
667 | /* out of 1000 us */ | ||
668 | #define MAX_PERIODIC_LOAD 600 | ||
669 | static int balance(struct isp116x *isp116x, u16 period, u16 load) | ||
670 | { | ||
671 | int i, branch = -ENOSPC; | ||
672 | |||
673 | /* search for the least loaded schedule branch of that period | ||
674 | which has enough bandwidth left unreserved. */ | ||
675 | for (i = 0; i < period; i++) { | ||
676 | if (branch < 0 || isp116x->load[branch] > isp116x->load[i]) { | ||
677 | int j; | ||
678 | |||
679 | for (j = i; j < PERIODIC_SIZE; j += period) { | ||
680 | if ((isp116x->load[j] + load) | ||
681 | > MAX_PERIODIC_LOAD) | ||
682 | break; | ||
683 | } | ||
684 | if (j < PERIODIC_SIZE) | ||
685 | continue; | ||
686 | branch = i; | ||
687 | } | ||
688 | } | ||
689 | return branch; | ||
690 | } | ||
691 | |||
692 | /* NB! ALL the code above this point runs with isp116x->lock | ||
693 | held, irqs off | ||
694 | */ | ||
695 | |||
696 | /*-----------------------------------------------------------------*/ | ||
697 | |||
698 | static int isp116x_urb_enqueue(struct usb_hcd *hcd, | ||
699 | struct usb_host_endpoint *hep, struct urb *urb, | ||
700 | int mem_flags) | ||
701 | { | ||
702 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
703 | struct usb_device *udev = urb->dev; | ||
704 | unsigned int pipe = urb->pipe; | ||
705 | int is_out = !usb_pipein(pipe); | ||
706 | int type = usb_pipetype(pipe); | ||
707 | int epnum = usb_pipeendpoint(pipe); | ||
708 | struct isp116x_ep *ep = NULL; | ||
709 | unsigned long flags; | ||
710 | int i; | ||
711 | int ret = 0; | ||
712 | |||
713 | urb_dbg(urb, "Enqueue"); | ||
714 | |||
715 | if (type == PIPE_ISOCHRONOUS) { | ||
716 | ERR("Isochronous transfers not supported\n"); | ||
717 | urb_dbg(urb, "Refused to enqueue"); | ||
718 | return -ENXIO; | ||
719 | } | ||
720 | /* avoid all allocations within spinlocks: request or endpoint */ | ||
721 | if (!hep->hcpriv) { | ||
722 | ep = kcalloc(1, sizeof *ep, (__force unsigned)mem_flags); | ||
723 | if (!ep) | ||
724 | return -ENOMEM; | ||
725 | } | ||
726 | |||
727 | spin_lock_irqsave(&isp116x->lock, flags); | ||
728 | if (!HC_IS_RUNNING(hcd->state)) { | ||
729 | ret = -ENODEV; | ||
730 | goto fail; | ||
731 | } | ||
732 | |||
733 | if (hep->hcpriv) | ||
734 | ep = hep->hcpriv; | ||
735 | else { | ||
736 | INIT_LIST_HEAD(&ep->schedule); | ||
737 | ep->udev = usb_get_dev(udev); | ||
738 | ep->epnum = epnum; | ||
739 | ep->maxpacket = usb_maxpacket(udev, urb->pipe, is_out); | ||
740 | usb_settoggle(udev, epnum, is_out, 0); | ||
741 | |||
742 | if (type == PIPE_CONTROL) { | ||
743 | ep->nextpid = USB_PID_SETUP; | ||
744 | } else if (is_out) { | ||
745 | ep->nextpid = USB_PID_OUT; | ||
746 | } else { | ||
747 | ep->nextpid = USB_PID_IN; | ||
748 | } | ||
749 | |||
750 | if (urb->interval) { | ||
751 | /* | ||
752 | With INT URBs submitted, the driver works with SOF | ||
753 | interrupt enabled and ATL interrupt disabled. After | ||
754 | the PTDs are written to fifo ram, the chip starts | ||
755 | fifo processing and usb transfers after the next | ||
756 | SOF and continues until the transfers are finished | ||
757 | (succeeded or failed) or the frame ends. Therefore, | ||
758 | the transfers occur only in every second frame, | ||
759 | while fifo reading/writing and data processing | ||
760 | occur in every other second frame. */ | ||
761 | if (urb->interval < 2) | ||
762 | urb->interval = 2; | ||
763 | if (urb->interval > 2 * PERIODIC_SIZE) | ||
764 | urb->interval = 2 * PERIODIC_SIZE; | ||
765 | ep->period = urb->interval >> 1; | ||
766 | ep->branch = PERIODIC_SIZE; | ||
767 | ep->load = usb_calc_bus_time(udev->speed, | ||
768 | !is_out, | ||
769 | (type == PIPE_ISOCHRONOUS), | ||
770 | usb_maxpacket(udev, pipe, | ||
771 | is_out)) / | ||
772 | 1000; | ||
773 | } | ||
774 | hep->hcpriv = ep; | ||
775 | ep->hep = hep; | ||
776 | } | ||
777 | |||
778 | /* maybe put endpoint into schedule */ | ||
779 | switch (type) { | ||
780 | case PIPE_CONTROL: | ||
781 | case PIPE_BULK: | ||
782 | if (list_empty(&ep->schedule)) | ||
783 | list_add_tail(&ep->schedule, &isp116x->async); | ||
784 | break; | ||
785 | case PIPE_INTERRUPT: | ||
786 | urb->interval = ep->period; | ||
787 | ep->length = min((int)ep->maxpacket, | ||
788 | urb->transfer_buffer_length); | ||
789 | |||
790 | /* urb submitted for already existing endpoint */ | ||
791 | if (ep->branch < PERIODIC_SIZE) | ||
792 | break; | ||
793 | |||
794 | ret = ep->branch = balance(isp116x, ep->period, ep->load); | ||
795 | if (ret < 0) | ||
796 | goto fail; | ||
797 | ret = 0; | ||
798 | |||
799 | urb->start_frame = (isp116x->fmindex & (PERIODIC_SIZE - 1)) | ||
800 | + ep->branch; | ||
801 | |||
802 | /* sort each schedule branch by period (slow before fast) | ||
803 | to share the faster parts of the tree without needing | ||
804 | dummy/placeholder nodes */ | ||
805 | DBG("schedule qh%d/%p branch %d\n", ep->period, ep, ep->branch); | ||
806 | for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) { | ||
807 | struct isp116x_ep **prev = &isp116x->periodic[i]; | ||
808 | struct isp116x_ep *here = *prev; | ||
809 | |||
810 | while (here && ep != here) { | ||
811 | if (ep->period > here->period) | ||
812 | break; | ||
813 | prev = &here->next; | ||
814 | here = *prev; | ||
815 | } | ||
816 | if (ep != here) { | ||
817 | ep->next = here; | ||
818 | *prev = ep; | ||
819 | } | ||
820 | isp116x->load[i] += ep->load; | ||
821 | } | ||
822 | hcd->self.bandwidth_allocated += ep->load / ep->period; | ||
823 | |||
824 | /* switch over to SOFint */ | ||
825 | if (!isp116x->periodic_count++) { | ||
826 | isp116x->irqenb &= ~HCuPINT_ATL; | ||
827 | isp116x->irqenb |= HCuPINT_SOF; | ||
828 | isp116x_write_reg16(isp116x, HCuPINTENB, | ||
829 | isp116x->irqenb); | ||
830 | } | ||
831 | } | ||
832 | |||
833 | /* in case of unlink-during-submit */ | ||
834 | spin_lock(&urb->lock); | ||
835 | if (urb->status != -EINPROGRESS) { | ||
836 | spin_unlock(&urb->lock); | ||
837 | finish_request(isp116x, ep, urb, NULL); | ||
838 | ret = 0; | ||
839 | goto fail; | ||
840 | } | ||
841 | urb->hcpriv = hep; | ||
842 | spin_unlock(&urb->lock); | ||
843 | start_atl_transfers(isp116x); | ||
844 | |||
845 | fail: | ||
846 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
847 | return ret; | ||
848 | } | ||
849 | |||
850 | /* | ||
851 | Dequeue URBs. | ||
852 | */ | ||
853 | static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | ||
854 | { | ||
855 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
856 | struct usb_host_endpoint *hep; | ||
857 | struct isp116x_ep *ep, *ep_act; | ||
858 | unsigned long flags; | ||
859 | |||
860 | spin_lock_irqsave(&isp116x->lock, flags); | ||
861 | hep = urb->hcpriv; | ||
862 | /* URB already unlinked (or never linked)? */ | ||
863 | if (!hep) { | ||
864 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
865 | return 0; | ||
866 | } | ||
867 | ep = hep->hcpriv; | ||
868 | WARN_ON(hep != ep->hep); | ||
869 | |||
870 | /* In front of queue? */ | ||
871 | if (ep->hep->urb_list.next == &urb->urb_list) | ||
872 | /* active? */ | ||
873 | for (ep_act = isp116x->atl_active; ep_act; | ||
874 | ep_act = ep_act->active) | ||
875 | if (ep_act == ep) { | ||
876 | VDBG("dequeue, urb %p active; wait for irq\n", | ||
877 | urb); | ||
878 | urb = NULL; | ||
879 | break; | ||
880 | } | ||
881 | |||
882 | if (urb) | ||
883 | finish_request(isp116x, ep, urb, NULL); | ||
884 | |||
885 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
886 | return 0; | ||
887 | } | ||
888 | |||
889 | static void isp116x_endpoint_disable(struct usb_hcd *hcd, | ||
890 | struct usb_host_endpoint *hep) | ||
891 | { | ||
892 | int i; | ||
893 | struct isp116x_ep *ep = hep->hcpriv;; | ||
894 | |||
895 | if (!ep) | ||
896 | return; | ||
897 | |||
898 | /* assume we'd just wait for the irq */ | ||
899 | for (i = 0; i < 100 && !list_empty(&hep->urb_list); i++) | ||
900 | msleep(3); | ||
901 | if (!list_empty(&hep->urb_list)) | ||
902 | WARN("ep %p not empty?\n", ep); | ||
903 | |||
904 | usb_put_dev(ep->udev); | ||
905 | kfree(ep); | ||
906 | hep->hcpriv = NULL; | ||
907 | } | ||
908 | |||
909 | static int isp116x_get_frame(struct usb_hcd *hcd) | ||
910 | { | ||
911 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
912 | u32 fmnum; | ||
913 | unsigned long flags; | ||
914 | |||
915 | spin_lock_irqsave(&isp116x->lock, flags); | ||
916 | fmnum = isp116x_read_reg32(isp116x, HCFMNUM); | ||
917 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
918 | return (int)fmnum; | ||
919 | } | ||
920 | |||
921 | /*----------------------------------------------------------------*/ | ||
922 | |||
923 | /* | ||
924 | Adapted from ohci-hub.c. Currently we don't support autosuspend. | ||
925 | */ | ||
926 | static int isp116x_hub_status_data(struct usb_hcd *hcd, char *buf) | ||
927 | { | ||
928 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
929 | int ports, i, changed = 0; | ||
930 | |||
931 | if (!HC_IS_RUNNING(hcd->state)) | ||
932 | return -ESHUTDOWN; | ||
933 | |||
934 | ports = isp116x->rhdesca & RH_A_NDP; | ||
935 | |||
936 | /* init status */ | ||
937 | if (isp116x->rhstatus & (RH_HS_LPSC | RH_HS_OCIC)) | ||
938 | buf[0] = changed = 1; | ||
939 | else | ||
940 | buf[0] = 0; | ||
941 | |||
942 | for (i = 0; i < ports; i++) { | ||
943 | u32 status = isp116x->rhport[i]; | ||
944 | |||
945 | if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | ||
946 | | RH_PS_OCIC | RH_PS_PRSC)) { | ||
947 | changed = 1; | ||
948 | buf[0] |= 1 << (i + 1); | ||
949 | continue; | ||
950 | } | ||
951 | } | ||
952 | return changed; | ||
953 | } | ||
954 | |||
955 | static void isp116x_hub_descriptor(struct isp116x *isp116x, | ||
956 | struct usb_hub_descriptor *desc) | ||
957 | { | ||
958 | u32 reg = isp116x->rhdesca; | ||
959 | |||
960 | desc->bDescriptorType = 0x29; | ||
961 | desc->bDescLength = 9; | ||
962 | desc->bHubContrCurrent = 0; | ||
963 | desc->bNbrPorts = (u8) (reg & 0x3); | ||
964 | /* Power switching, device type, overcurrent. */ | ||
965 | desc->wHubCharacteristics = | ||
966 | (__force __u16) cpu_to_le16((u16) ((reg >> 8) & 0x1f)); | ||
967 | desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff); | ||
968 | /* two bitmaps: ports removable, and legacy PortPwrCtrlMask */ | ||
969 | desc->bitmap[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1; | ||
970 | desc->bitmap[1] = ~0; | ||
971 | } | ||
972 | |||
973 | /* Perform reset of a given port. | ||
974 | It would be great to just start the reset and let the | ||
975 | USB core to clear the reset in due time. However, | ||
976 | root hub ports should be reset for at least 50 ms, while | ||
977 | our chip stays in reset for about 10 ms. I.e., we must | ||
978 | repeatedly reset it ourself here. | ||
979 | */ | ||
980 | static inline void root_port_reset(struct isp116x *isp116x, unsigned port) | ||
981 | { | ||
982 | u32 tmp; | ||
983 | unsigned long flags, t; | ||
984 | |||
985 | /* Root hub reset should be 50 ms, but some devices | ||
986 | want it even longer. */ | ||
987 | t = jiffies + msecs_to_jiffies(100); | ||
988 | |||
989 | while (time_before(jiffies, t)) { | ||
990 | spin_lock_irqsave(&isp116x->lock, flags); | ||
991 | /* spin until any current reset finishes */ | ||
992 | for (;;) { | ||
993 | tmp = isp116x_read_reg32(isp116x, port ? | ||
994 | HCRHPORT2 : HCRHPORT1); | ||
995 | if (!(tmp & RH_PS_PRS)) | ||
996 | break; | ||
997 | udelay(500); | ||
998 | } | ||
999 | /* Don't reset a disconnected port */ | ||
1000 | if (!(tmp & RH_PS_CCS)) { | ||
1001 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1002 | break; | ||
1003 | } | ||
1004 | /* Reset lasts 10ms (claims datasheet) */ | ||
1005 | isp116x_write_reg32(isp116x, port ? HCRHPORT2 : | ||
1006 | HCRHPORT1, (RH_PS_PRS)); | ||
1007 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1008 | msleep(10); | ||
1009 | } | ||
1010 | } | ||
1011 | |||
1012 | /* Adapted from ohci-hub.c */ | ||
1013 | static int isp116x_hub_control(struct usb_hcd *hcd, | ||
1014 | u16 typeReq, | ||
1015 | u16 wValue, u16 wIndex, char *buf, u16 wLength) | ||
1016 | { | ||
1017 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
1018 | int ret = 0; | ||
1019 | unsigned long flags; | ||
1020 | int ports = isp116x->rhdesca & RH_A_NDP; | ||
1021 | u32 tmp = 0; | ||
1022 | |||
1023 | switch (typeReq) { | ||
1024 | case ClearHubFeature: | ||
1025 | DBG("ClearHubFeature: "); | ||
1026 | switch (wValue) { | ||
1027 | case C_HUB_OVER_CURRENT: | ||
1028 | DBG("C_HUB_OVER_CURRENT\n"); | ||
1029 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1030 | isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_OCIC); | ||
1031 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1032 | case C_HUB_LOCAL_POWER: | ||
1033 | DBG("C_HUB_LOCAL_POWER\n"); | ||
1034 | break; | ||
1035 | default: | ||
1036 | goto error; | ||
1037 | } | ||
1038 | break; | ||
1039 | case SetHubFeature: | ||
1040 | DBG("SetHubFeature: "); | ||
1041 | switch (wValue) { | ||
1042 | case C_HUB_OVER_CURRENT: | ||
1043 | case C_HUB_LOCAL_POWER: | ||
1044 | DBG("C_HUB_OVER_CURRENT or C_HUB_LOCAL_POWER\n"); | ||
1045 | break; | ||
1046 | default: | ||
1047 | goto error; | ||
1048 | } | ||
1049 | break; | ||
1050 | case GetHubDescriptor: | ||
1051 | DBG("GetHubDescriptor\n"); | ||
1052 | isp116x_hub_descriptor(isp116x, | ||
1053 | (struct usb_hub_descriptor *)buf); | ||
1054 | break; | ||
1055 | case GetHubStatus: | ||
1056 | DBG("GetHubStatus\n"); | ||
1057 | *(__le32 *) buf = cpu_to_le32(0); | ||
1058 | break; | ||
1059 | case GetPortStatus: | ||
1060 | DBG("GetPortStatus\n"); | ||
1061 | if (!wIndex || wIndex > ports) | ||
1062 | goto error; | ||
1063 | tmp = isp116x->rhport[--wIndex]; | ||
1064 | *(__le32 *) buf = cpu_to_le32(tmp); | ||
1065 | DBG("GetPortStatus: port[%d] %08x\n", wIndex + 1, tmp); | ||
1066 | break; | ||
1067 | case ClearPortFeature: | ||
1068 | DBG("ClearPortFeature: "); | ||
1069 | if (!wIndex || wIndex > ports) | ||
1070 | goto error; | ||
1071 | wIndex--; | ||
1072 | |||
1073 | switch (wValue) { | ||
1074 | case USB_PORT_FEAT_ENABLE: | ||
1075 | DBG("USB_PORT_FEAT_ENABLE\n"); | ||
1076 | tmp = RH_PS_CCS; | ||
1077 | break; | ||
1078 | case USB_PORT_FEAT_C_ENABLE: | ||
1079 | DBG("USB_PORT_FEAT_C_ENABLE\n"); | ||
1080 | tmp = RH_PS_PESC; | ||
1081 | break; | ||
1082 | case USB_PORT_FEAT_SUSPEND: | ||
1083 | DBG("USB_PORT_FEAT_SUSPEND\n"); | ||
1084 | tmp = RH_PS_POCI; | ||
1085 | break; | ||
1086 | case USB_PORT_FEAT_C_SUSPEND: | ||
1087 | DBG("USB_PORT_FEAT_C_SUSPEND\n"); | ||
1088 | tmp = RH_PS_PSSC; | ||
1089 | break; | ||
1090 | case USB_PORT_FEAT_POWER: | ||
1091 | DBG("USB_PORT_FEAT_POWER\n"); | ||
1092 | tmp = RH_PS_LSDA; | ||
1093 | break; | ||
1094 | case USB_PORT_FEAT_C_CONNECTION: | ||
1095 | DBG("USB_PORT_FEAT_C_CONNECTION\n"); | ||
1096 | tmp = RH_PS_CSC; | ||
1097 | break; | ||
1098 | case USB_PORT_FEAT_C_OVER_CURRENT: | ||
1099 | DBG("USB_PORT_FEAT_C_OVER_CURRENT\n"); | ||
1100 | tmp = RH_PS_OCIC; | ||
1101 | break; | ||
1102 | case USB_PORT_FEAT_C_RESET: | ||
1103 | DBG("USB_PORT_FEAT_C_RESET\n"); | ||
1104 | tmp = RH_PS_PRSC; | ||
1105 | break; | ||
1106 | default: | ||
1107 | goto error; | ||
1108 | } | ||
1109 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1110 | isp116x_write_reg32(isp116x, wIndex | ||
1111 | ? HCRHPORT2 : HCRHPORT1, tmp); | ||
1112 | isp116x->rhport[wIndex] = | ||
1113 | isp116x_read_reg32(isp116x, wIndex ? HCRHPORT2 : HCRHPORT1); | ||
1114 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1115 | break; | ||
1116 | case SetPortFeature: | ||
1117 | DBG("SetPortFeature: "); | ||
1118 | if (!wIndex || wIndex > ports) | ||
1119 | goto error; | ||
1120 | wIndex--; | ||
1121 | switch (wValue) { | ||
1122 | case USB_PORT_FEAT_SUSPEND: | ||
1123 | DBG("USB_PORT_FEAT_SUSPEND\n"); | ||
1124 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1125 | isp116x_write_reg32(isp116x, wIndex | ||
1126 | ? HCRHPORT2 : HCRHPORT1, RH_PS_PSS); | ||
1127 | break; | ||
1128 | case USB_PORT_FEAT_POWER: | ||
1129 | DBG("USB_PORT_FEAT_POWER\n"); | ||
1130 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1131 | isp116x_write_reg32(isp116x, wIndex | ||
1132 | ? HCRHPORT2 : HCRHPORT1, RH_PS_PPS); | ||
1133 | break; | ||
1134 | case USB_PORT_FEAT_RESET: | ||
1135 | DBG("USB_PORT_FEAT_RESET\n"); | ||
1136 | root_port_reset(isp116x, wIndex); | ||
1137 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1138 | break; | ||
1139 | default: | ||
1140 | goto error; | ||
1141 | } | ||
1142 | isp116x->rhport[wIndex] = | ||
1143 | isp116x_read_reg32(isp116x, wIndex ? HCRHPORT2 : HCRHPORT1); | ||
1144 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1145 | break; | ||
1146 | |||
1147 | default: | ||
1148 | error: | ||
1149 | /* "protocol stall" on error */ | ||
1150 | DBG("PROTOCOL STALL\n"); | ||
1151 | ret = -EPIPE; | ||
1152 | } | ||
1153 | return ret; | ||
1154 | } | ||
1155 | |||
1156 | #ifdef CONFIG_PM | ||
1157 | |||
1158 | static int isp116x_hub_suspend(struct usb_hcd *hcd) | ||
1159 | { | ||
1160 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
1161 | unsigned long flags; | ||
1162 | u32 val; | ||
1163 | int ret = 0; | ||
1164 | |||
1165 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1166 | |||
1167 | val = isp116x_read_reg32(isp116x, HCCONTROL); | ||
1168 | switch (val & HCCONTROL_HCFS) { | ||
1169 | case HCCONTROL_USB_OPER: | ||
1170 | hcd->state = HC_STATE_QUIESCING; | ||
1171 | val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE); | ||
1172 | val |= HCCONTROL_USB_SUSPEND; | ||
1173 | if (hcd->remote_wakeup) | ||
1174 | val |= HCCONTROL_RWE; | ||
1175 | /* Wait for usb transfers to finish */ | ||
1176 | mdelay(2); | ||
1177 | isp116x_write_reg32(isp116x, HCCONTROL, val); | ||
1178 | hcd->state = HC_STATE_SUSPENDED; | ||
1179 | /* Wait for devices to suspend */ | ||
1180 | mdelay(5); | ||
1181 | case HCCONTROL_USB_SUSPEND: | ||
1182 | break; | ||
1183 | case HCCONTROL_USB_RESUME: | ||
1184 | isp116x_write_reg32(isp116x, HCCONTROL, | ||
1185 | (val & ~HCCONTROL_HCFS) | | ||
1186 | HCCONTROL_USB_RESET); | ||
1187 | case HCCONTROL_USB_RESET: | ||
1188 | ret = -EBUSY; | ||
1189 | break; | ||
1190 | default: | ||
1191 | ret = -EINVAL; | ||
1192 | } | ||
1193 | |||
1194 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1195 | return ret; | ||
1196 | } | ||
1197 | |||
1198 | static int isp116x_hub_resume(struct usb_hcd *hcd) | ||
1199 | { | ||
1200 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
1201 | u32 val; | ||
1202 | int ret = -EINPROGRESS; | ||
1203 | |||
1204 | msleep(5); | ||
1205 | spin_lock_irq(&isp116x->lock); | ||
1206 | |||
1207 | val = isp116x_read_reg32(isp116x, HCCONTROL); | ||
1208 | switch (val & HCCONTROL_HCFS) { | ||
1209 | case HCCONTROL_USB_SUSPEND: | ||
1210 | val &= ~HCCONTROL_HCFS; | ||
1211 | val |= HCCONTROL_USB_RESUME; | ||
1212 | isp116x_write_reg32(isp116x, HCCONTROL, val); | ||
1213 | case HCCONTROL_USB_RESUME: | ||
1214 | break; | ||
1215 | case HCCONTROL_USB_OPER: | ||
1216 | /* Without setting power_state here the | ||
1217 | SUSPENDED state won't be removed from | ||
1218 | sysfs/usbN/power.state as a response to remote | ||
1219 | wakeup. Maybe in the future. */ | ||
1220 | hcd->self.root_hub->dev.power.power_state = PMSG_ON; | ||
1221 | ret = 0; | ||
1222 | break; | ||
1223 | default: | ||
1224 | ret = -EBUSY; | ||
1225 | } | ||
1226 | |||
1227 | if (ret != -EINPROGRESS) { | ||
1228 | spin_unlock_irq(&isp116x->lock); | ||
1229 | return ret; | ||
1230 | } | ||
1231 | |||
1232 | val = isp116x->rhdesca & RH_A_NDP; | ||
1233 | while (val--) { | ||
1234 | u32 stat = | ||
1235 | isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1); | ||
1236 | /* force global, not selective, resume */ | ||
1237 | if (!(stat & RH_PS_PSS)) | ||
1238 | continue; | ||
1239 | DBG("%s: Resuming port %d\n", __func__, val); | ||
1240 | isp116x_write_reg32(isp116x, RH_PS_POCI, val | ||
1241 | ? HCRHPORT2 : HCRHPORT1); | ||
1242 | } | ||
1243 | spin_unlock_irq(&isp116x->lock); | ||
1244 | |||
1245 | hcd->state = HC_STATE_RESUMING; | ||
1246 | mdelay(20); | ||
1247 | |||
1248 | /* Go operational */ | ||
1249 | spin_lock_irq(&isp116x->lock); | ||
1250 | val = isp116x_read_reg32(isp116x, HCCONTROL); | ||
1251 | isp116x_write_reg32(isp116x, HCCONTROL, | ||
1252 | (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER); | ||
1253 | spin_unlock_irq(&isp116x->lock); | ||
1254 | /* see analogous comment above */ | ||
1255 | hcd->self.root_hub->dev.power.power_state = PMSG_ON; | ||
1256 | hcd->state = HC_STATE_RUNNING; | ||
1257 | |||
1258 | return 0; | ||
1259 | } | ||
1260 | |||
1261 | static void isp116x_rh_resume(void *_hcd) | ||
1262 | { | ||
1263 | struct usb_hcd *hcd = _hcd; | ||
1264 | |||
1265 | usb_resume_device(hcd->self.root_hub); | ||
1266 | } | ||
1267 | |||
1268 | #else | ||
1269 | |||
1270 | #define isp116x_hub_suspend NULL | ||
1271 | #define isp116x_hub_resume NULL | ||
1272 | |||
1273 | static void isp116x_rh_resume(void *_hcd) | ||
1274 | { | ||
1275 | } | ||
1276 | |||
1277 | #endif | ||
1278 | |||
1279 | /*-----------------------------------------------------------------*/ | ||
1280 | |||
1281 | #ifdef STUB_DEBUG_FILE | ||
1282 | |||
1283 | static inline void create_debug_file(struct isp116x *isp116x) | ||
1284 | { | ||
1285 | } | ||
1286 | |||
1287 | static inline void remove_debug_file(struct isp116x *isp116x) | ||
1288 | { | ||
1289 | } | ||
1290 | |||
1291 | #else | ||
1292 | |||
1293 | #include <linux/proc_fs.h> | ||
1294 | #include <linux/seq_file.h> | ||
1295 | |||
1296 | static void dump_irq(struct seq_file *s, char *label, u16 mask) | ||
1297 | { | ||
1298 | seq_printf(s, "%s %04x%s%s%s%s%s%s\n", label, mask, | ||
1299 | mask & HCuPINT_CLKRDY ? " clkrdy" : "", | ||
1300 | mask & HCuPINT_SUSP ? " susp" : "", | ||
1301 | mask & HCuPINT_OPR ? " opr" : "", | ||
1302 | mask & HCuPINT_AIIEOT ? " eot" : "", | ||
1303 | mask & HCuPINT_ATL ? " atl" : "", | ||
1304 | mask & HCuPINT_SOF ? " sof" : ""); | ||
1305 | } | ||
1306 | |||
1307 | static void dump_int(struct seq_file *s, char *label, u32 mask) | ||
1308 | { | ||
1309 | seq_printf(s, "%s %08x%s%s%s%s%s%s%s\n", label, mask, | ||
1310 | mask & HCINT_MIE ? " MIE" : "", | ||
1311 | mask & HCINT_RHSC ? " rhsc" : "", | ||
1312 | mask & HCINT_FNO ? " fno" : "", | ||
1313 | mask & HCINT_UE ? " ue" : "", | ||
1314 | mask & HCINT_RD ? " rd" : "", | ||
1315 | mask & HCINT_SF ? " sof" : "", mask & HCINT_SO ? " so" : ""); | ||
1316 | } | ||
1317 | |||
1318 | static int proc_isp116x_show(struct seq_file *s, void *unused) | ||
1319 | { | ||
1320 | struct isp116x *isp116x = s->private; | ||
1321 | struct isp116x_ep *ep; | ||
1322 | struct urb *urb; | ||
1323 | unsigned i; | ||
1324 | char *str; | ||
1325 | |||
1326 | seq_printf(s, "%s\n%s version %s\n", | ||
1327 | isp116x_to_hcd(isp116x)->product_desc, hcd_name, | ||
1328 | DRIVER_VERSION); | ||
1329 | |||
1330 | if (HC_IS_SUSPENDED(isp116x_to_hcd(isp116x)->state)) { | ||
1331 | seq_printf(s, "HCD is suspended\n"); | ||
1332 | return 0; | ||
1333 | } | ||
1334 | if (!HC_IS_RUNNING(isp116x_to_hcd(isp116x)->state)) { | ||
1335 | seq_printf(s, "HCD not running\n"); | ||
1336 | return 0; | ||
1337 | } | ||
1338 | |||
1339 | spin_lock_irq(&isp116x->lock); | ||
1340 | |||
1341 | dump_irq(s, "hc_irq_enable", isp116x_read_reg16(isp116x, HCuPINTENB)); | ||
1342 | dump_irq(s, "hc_irq_status", isp116x_read_reg16(isp116x, HCuPINT)); | ||
1343 | dump_int(s, "hc_int_enable", isp116x_read_reg32(isp116x, HCINTENB)); | ||
1344 | dump_int(s, "hc_int_status", isp116x_read_reg32(isp116x, HCINTSTAT)); | ||
1345 | |||
1346 | list_for_each_entry(ep, &isp116x->async, schedule) { | ||
1347 | |||
1348 | switch (ep->nextpid) { | ||
1349 | case USB_PID_IN: | ||
1350 | str = "in"; | ||
1351 | break; | ||
1352 | case USB_PID_OUT: | ||
1353 | str = "out"; | ||
1354 | break; | ||
1355 | case USB_PID_SETUP: | ||
1356 | str = "setup"; | ||
1357 | break; | ||
1358 | case USB_PID_ACK: | ||
1359 | str = "status"; | ||
1360 | break; | ||
1361 | default: | ||
1362 | str = "?"; | ||
1363 | break; | ||
1364 | }; | ||
1365 | seq_printf(s, "%p, ep%d%s, maxpacket %d:\n", ep, | ||
1366 | ep->epnum, str, ep->maxpacket); | ||
1367 | list_for_each_entry(urb, &ep->hep->urb_list, urb_list) { | ||
1368 | seq_printf(s, " urb%p, %d/%d\n", urb, | ||
1369 | urb->actual_length, | ||
1370 | urb->transfer_buffer_length); | ||
1371 | } | ||
1372 | } | ||
1373 | if (!list_empty(&isp116x->async)) | ||
1374 | seq_printf(s, "\n"); | ||
1375 | |||
1376 | seq_printf(s, "periodic size= %d\n", PERIODIC_SIZE); | ||
1377 | |||
1378 | for (i = 0; i < PERIODIC_SIZE; i++) { | ||
1379 | ep = isp116x->periodic[i]; | ||
1380 | if (!ep) | ||
1381 | continue; | ||
1382 | seq_printf(s, "%2d [%3d]:\n", i, isp116x->load[i]); | ||
1383 | |||
1384 | /* DUMB: prints shared entries multiple times */ | ||
1385 | do { | ||
1386 | seq_printf(s, " %d/%p (%sdev%d ep%d%s max %d)\n", | ||
1387 | ep->period, ep, | ||
1388 | (ep->udev->speed == | ||
1389 | USB_SPEED_FULL) ? "" : "ls ", | ||
1390 | ep->udev->devnum, ep->epnum, | ||
1391 | (ep->epnum == | ||
1392 | 0) ? "" : ((ep->nextpid == | ||
1393 | USB_PID_IN) ? "in" : "out"), | ||
1394 | ep->maxpacket); | ||
1395 | ep = ep->next; | ||
1396 | } while (ep); | ||
1397 | } | ||
1398 | spin_unlock_irq(&isp116x->lock); | ||
1399 | seq_printf(s, "\n"); | ||
1400 | |||
1401 | return 0; | ||
1402 | } | ||
1403 | |||
1404 | static int proc_isp116x_open(struct inode *inode, struct file *file) | ||
1405 | { | ||
1406 | return single_open(file, proc_isp116x_show, PDE(inode)->data); | ||
1407 | } | ||
1408 | |||
1409 | static struct file_operations proc_ops = { | ||
1410 | .open = proc_isp116x_open, | ||
1411 | .read = seq_read, | ||
1412 | .llseek = seq_lseek, | ||
1413 | .release = single_release, | ||
1414 | }; | ||
1415 | |||
1416 | /* expect just one isp116x per system */ | ||
1417 | static const char proc_filename[] = "driver/isp116x"; | ||
1418 | |||
1419 | static void create_debug_file(struct isp116x *isp116x) | ||
1420 | { | ||
1421 | struct proc_dir_entry *pde; | ||
1422 | |||
1423 | pde = create_proc_entry(proc_filename, 0, NULL); | ||
1424 | if (pde == NULL) | ||
1425 | return; | ||
1426 | |||
1427 | pde->proc_fops = &proc_ops; | ||
1428 | pde->data = isp116x; | ||
1429 | isp116x->pde = pde; | ||
1430 | } | ||
1431 | |||
1432 | static void remove_debug_file(struct isp116x *isp116x) | ||
1433 | { | ||
1434 | if (isp116x->pde) | ||
1435 | remove_proc_entry(proc_filename, NULL); | ||
1436 | } | ||
1437 | |||
1438 | #endif | ||
1439 | |||
1440 | /*-----------------------------------------------------------------*/ | ||
1441 | |||
1442 | /* | ||
1443 | Software reset - can be called from any contect. | ||
1444 | */ | ||
1445 | static int isp116x_sw_reset(struct isp116x *isp116x) | ||
1446 | { | ||
1447 | int retries = 15; | ||
1448 | unsigned long flags; | ||
1449 | int ret = 0; | ||
1450 | |||
1451 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1452 | isp116x_write_reg16(isp116x, HCSWRES, HCSWRES_MAGIC); | ||
1453 | isp116x_write_reg32(isp116x, HCCMDSTAT, HCCMDSTAT_HCR); | ||
1454 | while (--retries) { | ||
1455 | /* It usually resets within 1 ms */ | ||
1456 | mdelay(1); | ||
1457 | if (!(isp116x_read_reg32(isp116x, HCCMDSTAT) & HCCMDSTAT_HCR)) | ||
1458 | break; | ||
1459 | } | ||
1460 | if (!retries) { | ||
1461 | ERR("Software reset timeout\n"); | ||
1462 | ret = -ETIME; | ||
1463 | } | ||
1464 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1465 | return ret; | ||
1466 | } | ||
1467 | |||
1468 | /* | ||
1469 | Reset. Tries to perform platform-specific hardware | ||
1470 | reset first; falls back to software reset. | ||
1471 | */ | ||
1472 | static int isp116x_reset(struct usb_hcd *hcd) | ||
1473 | { | ||
1474 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
1475 | unsigned long t; | ||
1476 | u16 clkrdy = 0; | ||
1477 | int ret = 0, timeout = 15 /* ms */ ; | ||
1478 | |||
1479 | if (isp116x->board && isp116x->board->reset) { | ||
1480 | /* Hardware reset */ | ||
1481 | isp116x->board->reset(hcd->self.controller, 1); | ||
1482 | msleep(10); | ||
1483 | if (isp116x->board->clock) | ||
1484 | isp116x->board->clock(hcd->self.controller, 1); | ||
1485 | msleep(1); | ||
1486 | isp116x->board->reset(hcd->self.controller, 0); | ||
1487 | } else | ||
1488 | ret = isp116x_sw_reset(isp116x); | ||
1489 | |||
1490 | if (ret) | ||
1491 | return ret; | ||
1492 | |||
1493 | t = jiffies + msecs_to_jiffies(timeout); | ||
1494 | while (time_before_eq(jiffies, t)) { | ||
1495 | msleep(4); | ||
1496 | spin_lock_irq(&isp116x->lock); | ||
1497 | clkrdy = isp116x_read_reg16(isp116x, HCuPINT) & HCuPINT_CLKRDY; | ||
1498 | spin_unlock_irq(&isp116x->lock); | ||
1499 | if (clkrdy) | ||
1500 | break; | ||
1501 | } | ||
1502 | if (!clkrdy) { | ||
1503 | ERR("Clock not ready after 20ms\n"); | ||
1504 | /* After sw_reset the clock won't report to be ready, if | ||
1505 | H_WAKEUP pin is high. */ | ||
1506 | if (!isp116x->board || !isp116x->board->reset) | ||
1507 | ERR("The driver does not support hardware wakeup.\n"); | ||
1508 | ERR("Please make sure that the H_WAKEUP pin " | ||
1509 | "is pulled low!\n"); | ||
1510 | ret = -ENODEV; | ||
1511 | } | ||
1512 | return ret; | ||
1513 | } | ||
1514 | |||
1515 | static void isp116x_stop(struct usb_hcd *hcd) | ||
1516 | { | ||
1517 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
1518 | unsigned long flags; | ||
1519 | u32 val; | ||
1520 | |||
1521 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1522 | isp116x_write_reg16(isp116x, HCuPINTENB, 0); | ||
1523 | |||
1524 | /* Switch off ports' power, some devices don't come up | ||
1525 | after next 'insmod' without this */ | ||
1526 | val = isp116x_read_reg32(isp116x, HCRHDESCA); | ||
1527 | val &= ~(RH_A_NPS | RH_A_PSM); | ||
1528 | isp116x_write_reg32(isp116x, HCRHDESCA, val); | ||
1529 | isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS); | ||
1530 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1531 | |||
1532 | /* Put the chip into reset state */ | ||
1533 | if (isp116x->board && isp116x->board->reset) | ||
1534 | isp116x->board->reset(hcd->self.controller, 0); | ||
1535 | else | ||
1536 | isp116x_sw_reset(isp116x); | ||
1537 | |||
1538 | /* Stop the clock */ | ||
1539 | if (isp116x->board && isp116x->board->clock) | ||
1540 | isp116x->board->clock(hcd->self.controller, 0); | ||
1541 | } | ||
1542 | |||
1543 | /* | ||
1544 | Configure the chip. The chip must be successfully reset by now. | ||
1545 | */ | ||
1546 | static int isp116x_start(struct usb_hcd *hcd) | ||
1547 | { | ||
1548 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | ||
1549 | struct isp116x_platform_data *board = isp116x->board; | ||
1550 | u32 val; | ||
1551 | unsigned long flags; | ||
1552 | |||
1553 | spin_lock_irqsave(&isp116x->lock, flags); | ||
1554 | |||
1555 | /* clear interrupt status and disable all interrupt sources */ | ||
1556 | isp116x_write_reg16(isp116x, HCuPINT, 0xff); | ||
1557 | isp116x_write_reg16(isp116x, HCuPINTENB, 0); | ||
1558 | |||
1559 | val = isp116x_read_reg16(isp116x, HCCHIPID); | ||
1560 | if ((val & HCCHIPID_MASK) != HCCHIPID_MAGIC) { | ||
1561 | ERR("Invalid chip ID %04x\n", val); | ||
1562 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1563 | return -ENODEV; | ||
1564 | } | ||
1565 | |||
1566 | isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE); | ||
1567 | isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE); | ||
1568 | |||
1569 | /* ----- HW conf */ | ||
1570 | val = HCHWCFG_INT_ENABLE | HCHWCFG_DBWIDTH(1); | ||
1571 | if (board->sel15Kres) | ||
1572 | val |= HCHWCFG_15KRSEL; | ||
1573 | /* Remote wakeup won't work without working clock */ | ||
1574 | if (board->clknotstop || board->remote_wakeup_enable) | ||
1575 | val |= HCHWCFG_CLKNOTSTOP; | ||
1576 | if (board->oc_enable) | ||
1577 | val |= HCHWCFG_ANALOG_OC; | ||
1578 | if (board->int_act_high) | ||
1579 | val |= HCHWCFG_INT_POL; | ||
1580 | if (board->int_edge_triggered) | ||
1581 | val |= HCHWCFG_INT_TRIGGER; | ||
1582 | isp116x_write_reg16(isp116x, HCHWCFG, val); | ||
1583 | |||
1584 | /* ----- Root hub conf */ | ||
1585 | val = 0; | ||
1586 | /* AN10003_1.pdf recommends NPS to be always 1 */ | ||
1587 | if (board->no_power_switching) | ||
1588 | val |= RH_A_NPS; | ||
1589 | if (board->power_switching_mode) | ||
1590 | val |= RH_A_PSM; | ||
1591 | if (board->potpg) | ||
1592 | val |= (board->potpg << 24) & RH_A_POTPGT; | ||
1593 | else | ||
1594 | val |= (25 << 24) & RH_A_POTPGT; | ||
1595 | isp116x_write_reg32(isp116x, HCRHDESCA, val); | ||
1596 | isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA); | ||
1597 | |||
1598 | val = RH_B_PPCM; | ||
1599 | isp116x_write_reg32(isp116x, HCRHDESCB, val); | ||
1600 | isp116x->rhdescb = isp116x_read_reg32(isp116x, HCRHDESCB); | ||
1601 | |||
1602 | val = 0; | ||
1603 | if (board->remote_wakeup_enable) { | ||
1604 | hcd->can_wakeup = 1; | ||
1605 | val |= RH_HS_DRWE; | ||
1606 | } | ||
1607 | isp116x_write_reg32(isp116x, HCRHSTATUS, val); | ||
1608 | isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS); | ||
1609 | |||
1610 | isp116x_write_reg32(isp116x, HCFMINTVL, 0x27782edf); | ||
1611 | |||
1612 | hcd->state = HC_STATE_RUNNING; | ||
1613 | |||
1614 | /* Set up interrupts */ | ||
1615 | isp116x->intenb = HCINT_MIE | HCINT_RHSC | HCINT_UE; | ||
1616 | if (board->remote_wakeup_enable) | ||
1617 | isp116x->intenb |= HCINT_RD; | ||
1618 | isp116x->irqenb = HCuPINT_ATL | HCuPINT_OPR; /* | HCuPINT_SUSP; */ | ||
1619 | isp116x_write_reg32(isp116x, HCINTENB, isp116x->intenb); | ||
1620 | isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb); | ||
1621 | |||
1622 | /* Go operational */ | ||
1623 | val = HCCONTROL_USB_OPER; | ||
1624 | /* Remote wakeup connected - NOT SUPPORTED */ | ||
1625 | /* if (board->remote_wakeup_connected) | ||
1626 | val |= HCCONTROL_RWC; */ | ||
1627 | if (board->remote_wakeup_enable) | ||
1628 | val |= HCCONTROL_RWE; | ||
1629 | isp116x_write_reg32(isp116x, HCCONTROL, val); | ||
1630 | |||
1631 | /* Disable ports to avoid race in device enumeration */ | ||
1632 | isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS); | ||
1633 | isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS); | ||
1634 | |||
1635 | isp116x_show_regs(isp116x); | ||
1636 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
1637 | return 0; | ||
1638 | } | ||
1639 | |||
1640 | /*-----------------------------------------------------------------*/ | ||
1641 | |||
1642 | static struct hc_driver isp116x_hc_driver = { | ||
1643 | .description = hcd_name, | ||
1644 | .product_desc = "ISP116x Host Controller", | ||
1645 | .hcd_priv_size = sizeof(struct isp116x), | ||
1646 | |||
1647 | .irq = isp116x_irq, | ||
1648 | .flags = HCD_USB11, | ||
1649 | |||
1650 | .reset = isp116x_reset, | ||
1651 | .start = isp116x_start, | ||
1652 | .stop = isp116x_stop, | ||
1653 | |||
1654 | .urb_enqueue = isp116x_urb_enqueue, | ||
1655 | .urb_dequeue = isp116x_urb_dequeue, | ||
1656 | .endpoint_disable = isp116x_endpoint_disable, | ||
1657 | |||
1658 | .get_frame_number = isp116x_get_frame, | ||
1659 | |||
1660 | .hub_status_data = isp116x_hub_status_data, | ||
1661 | .hub_control = isp116x_hub_control, | ||
1662 | .hub_suspend = isp116x_hub_suspend, | ||
1663 | .hub_resume = isp116x_hub_resume, | ||
1664 | }; | ||
1665 | |||
1666 | /*----------------------------------------------------------------*/ | ||
1667 | |||
1668 | static int __init_or_module isp116x_remove(struct device *dev) | ||
1669 | { | ||
1670 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
1671 | struct isp116x *isp116x; | ||
1672 | struct platform_device *pdev; | ||
1673 | struct resource *res; | ||
1674 | |||
1675 | if(!hcd) | ||
1676 | return 0; | ||
1677 | isp116x = hcd_to_isp116x(hcd); | ||
1678 | pdev = container_of(dev, struct platform_device, dev); | ||
1679 | remove_debug_file(isp116x); | ||
1680 | usb_remove_hcd(hcd); | ||
1681 | |||
1682 | iounmap(isp116x->data_reg); | ||
1683 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
1684 | release_mem_region(res->start, 2); | ||
1685 | iounmap(isp116x->addr_reg); | ||
1686 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1687 | release_mem_region(res->start, 2); | ||
1688 | |||
1689 | usb_put_hcd(hcd); | ||
1690 | return 0; | ||
1691 | } | ||
1692 | |||
1693 | #define resource_len(r) (((r)->end - (r)->start) + 1) | ||
1694 | |||
1695 | static int __init isp116x_probe(struct device *dev) | ||
1696 | { | ||
1697 | struct usb_hcd *hcd; | ||
1698 | struct isp116x *isp116x; | ||
1699 | struct platform_device *pdev; | ||
1700 | struct resource *addr, *data; | ||
1701 | void __iomem *addr_reg; | ||
1702 | void __iomem *data_reg; | ||
1703 | int irq; | ||
1704 | int ret = 0; | ||
1705 | |||
1706 | pdev = container_of(dev, struct platform_device, dev); | ||
1707 | if (pdev->num_resources < 3) { | ||
1708 | ret = -ENODEV; | ||
1709 | goto err1; | ||
1710 | } | ||
1711 | |||
1712 | data = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1713 | addr = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
1714 | irq = platform_get_irq(pdev, 0); | ||
1715 | if (!addr || !data || irq < 0) { | ||
1716 | ret = -ENODEV; | ||
1717 | goto err1; | ||
1718 | } | ||
1719 | |||
1720 | if (dev->dma_mask) { | ||
1721 | DBG("DMA not supported\n"); | ||
1722 | ret = -EINVAL; | ||
1723 | goto err1; | ||
1724 | } | ||
1725 | |||
1726 | if (!request_mem_region(addr->start, 2, hcd_name)) { | ||
1727 | ret = -EBUSY; | ||
1728 | goto err1; | ||
1729 | } | ||
1730 | addr_reg = ioremap(addr->start, resource_len(addr)); | ||
1731 | if (addr_reg == NULL) { | ||
1732 | ret = -ENOMEM; | ||
1733 | goto err2; | ||
1734 | } | ||
1735 | if (!request_mem_region(data->start, 2, hcd_name)) { | ||
1736 | ret = -EBUSY; | ||
1737 | goto err3; | ||
1738 | } | ||
1739 | data_reg = ioremap(data->start, resource_len(data)); | ||
1740 | if (data_reg == NULL) { | ||
1741 | ret = -ENOMEM; | ||
1742 | goto err4; | ||
1743 | } | ||
1744 | |||
1745 | /* allocate and initialize hcd */ | ||
1746 | hcd = usb_create_hcd(&isp116x_hc_driver, dev, dev->bus_id); | ||
1747 | if (!hcd) { | ||
1748 | ret = -ENOMEM; | ||
1749 | goto err5; | ||
1750 | } | ||
1751 | /* this rsrc_start is bogus */ | ||
1752 | hcd->rsrc_start = addr->start; | ||
1753 | isp116x = hcd_to_isp116x(hcd); | ||
1754 | isp116x->data_reg = data_reg; | ||
1755 | isp116x->addr_reg = addr_reg; | ||
1756 | spin_lock_init(&isp116x->lock); | ||
1757 | INIT_LIST_HEAD(&isp116x->async); | ||
1758 | INIT_WORK(&isp116x->rh_resume, isp116x_rh_resume, hcd); | ||
1759 | isp116x->board = dev->platform_data; | ||
1760 | |||
1761 | if (!isp116x->board) { | ||
1762 | ERR("Platform data structure not initialized\n"); | ||
1763 | ret = -ENODEV; | ||
1764 | goto err6; | ||
1765 | } | ||
1766 | if (isp116x_check_platform_delay(isp116x)) { | ||
1767 | ERR("USE_PLATFORM_DELAY defined, but delay function not " | ||
1768 | "implemented.\n"); | ||
1769 | ERR("See comments in drivers/usb/host/isp116x-hcd.c\n"); | ||
1770 | ret = -ENODEV; | ||
1771 | goto err6; | ||
1772 | } | ||
1773 | |||
1774 | ret = usb_add_hcd(hcd, irq, SA_INTERRUPT); | ||
1775 | if (ret != 0) | ||
1776 | goto err6; | ||
1777 | |||
1778 | create_debug_file(isp116x); | ||
1779 | return 0; | ||
1780 | |||
1781 | err6: | ||
1782 | usb_put_hcd(hcd); | ||
1783 | err5: | ||
1784 | iounmap(data_reg); | ||
1785 | err4: | ||
1786 | release_mem_region(data->start, 2); | ||
1787 | err3: | ||
1788 | iounmap(addr_reg); | ||
1789 | err2: | ||
1790 | release_mem_region(addr->start, 2); | ||
1791 | err1: | ||
1792 | ERR("init error, %d\n", ret); | ||
1793 | return ret; | ||
1794 | } | ||
1795 | |||
1796 | #ifdef CONFIG_PM | ||
1797 | /* | ||
1798 | Suspend of platform device | ||
1799 | */ | ||
1800 | static int isp116x_suspend(struct device *dev, pm_message_t state, u32 phase) | ||
1801 | { | ||
1802 | int ret = 0; | ||
1803 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
1804 | |||
1805 | VDBG("%s: state %x, phase %x\n", __func__, state, phase); | ||
1806 | |||
1807 | if (phase != SUSPEND_DISABLE && phase != SUSPEND_POWER_DOWN) | ||
1808 | return 0; | ||
1809 | |||
1810 | ret = usb_suspend_device(hcd->self.root_hub, state); | ||
1811 | if (!ret) { | ||
1812 | dev->power.power_state = state; | ||
1813 | INFO("%s suspended\n", (char *)hcd_name); | ||
1814 | } else | ||
1815 | ERR("%s suspend failed\n", (char *)hcd_name); | ||
1816 | |||
1817 | return ret; | ||
1818 | } | ||
1819 | |||
1820 | /* | ||
1821 | Resume platform device | ||
1822 | */ | ||
1823 | static int isp116x_resume(struct device *dev, u32 phase) | ||
1824 | { | ||
1825 | int ret = 0; | ||
1826 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
1827 | |||
1828 | VDBG("%s: state %x, phase %x\n", __func__, dev->power.power_state, | ||
1829 | phase); | ||
1830 | if (phase != RESUME_POWER_ON) | ||
1831 | return 0; | ||
1832 | |||
1833 | ret = usb_resume_device(hcd->self.root_hub); | ||
1834 | if (!ret) { | ||
1835 | dev->power.power_state = PMSG_ON; | ||
1836 | VDBG("%s resumed\n", (char *)hcd_name); | ||
1837 | } | ||
1838 | return ret; | ||
1839 | } | ||
1840 | |||
1841 | #else | ||
1842 | |||
1843 | #define isp116x_suspend NULL | ||
1844 | #define isp116x_resume NULL | ||
1845 | |||
1846 | #endif | ||
1847 | |||
1848 | static struct device_driver isp116x_driver = { | ||
1849 | .name = (char *)hcd_name, | ||
1850 | .bus = &platform_bus_type, | ||
1851 | .probe = isp116x_probe, | ||
1852 | .remove = isp116x_remove, | ||
1853 | .suspend = isp116x_suspend, | ||
1854 | .resume = isp116x_resume, | ||
1855 | }; | ||
1856 | |||
1857 | /*-----------------------------------------------------------------*/ | ||
1858 | |||
1859 | static int __init isp116x_init(void) | ||
1860 | { | ||
1861 | if (usb_disabled()) | ||
1862 | return -ENODEV; | ||
1863 | |||
1864 | INFO("driver %s, %s\n", hcd_name, DRIVER_VERSION); | ||
1865 | return driver_register(&isp116x_driver); | ||
1866 | } | ||
1867 | |||
1868 | module_init(isp116x_init); | ||
1869 | |||
1870 | static void __exit isp116x_cleanup(void) | ||
1871 | { | ||
1872 | driver_unregister(&isp116x_driver); | ||
1873 | } | ||
1874 | |||
1875 | module_exit(isp116x_cleanup); | ||
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h new file mode 100644 index 000000000000..58873470dcf5 --- /dev/null +++ b/drivers/usb/host/isp116x.h | |||
@@ -0,0 +1,583 @@ | |||
1 | /* | ||
2 | * ISP116x register declarations and HCD data structures | ||
3 | * | ||
4 | * Copyright (C) 2005 Olav Kongas <ok@artecdesign.ee> | ||
5 | * Portions: | ||
6 | * Copyright (C) 2004 Lothar Wassmann | ||
7 | * Copyright (C) 2004 Psion Teklogix | ||
8 | * Copyright (C) 2004 David Brownell | ||
9 | */ | ||
10 | |||
11 | /* us of 1ms frame */ | ||
12 | #define MAX_LOAD_LIMIT 850 | ||
13 | |||
14 | /* Full speed: max # of bytes to transfer for a single urb | ||
15 | at a time must be < 1024 && must be multiple of 64. | ||
16 | 832 allows transfering 4kiB within 5 frames. */ | ||
17 | #define MAX_TRANSFER_SIZE_FULLSPEED 832 | ||
18 | |||
19 | /* Low speed: there is no reason to schedule in very big | ||
20 | chunks; often the requested long transfers are for | ||
21 | string descriptors containing short strings. */ | ||
22 | #define MAX_TRANSFER_SIZE_LOWSPEED 64 | ||
23 | |||
24 | /* Bytetime (us), a rough indication of how much time it | ||
25 | would take to transfer a byte of useful data over USB */ | ||
26 | #define BYTE_TIME_FULLSPEED 1 | ||
27 | #define BYTE_TIME_LOWSPEED 20 | ||
28 | |||
29 | /* Buffer sizes */ | ||
30 | #define ISP116x_BUF_SIZE 4096 | ||
31 | #define ISP116x_ITL_BUFSIZE 0 | ||
32 | #define ISP116x_ATL_BUFSIZE ((ISP116x_BUF_SIZE) - 2*(ISP116x_ITL_BUFSIZE)) | ||
33 | |||
34 | #define ISP116x_WRITE_OFFSET 0x80 | ||
35 | |||
36 | /*------------ ISP116x registers/bits ------------*/ | ||
37 | #define HCREVISION 0x00 | ||
38 | #define HCCONTROL 0x01 | ||
39 | #define HCCONTROL_HCFS (3 << 6) /* host controller | ||
40 | functional state */ | ||
41 | #define HCCONTROL_USB_RESET (0 << 6) | ||
42 | #define HCCONTROL_USB_RESUME (1 << 6) | ||
43 | #define HCCONTROL_USB_OPER (2 << 6) | ||
44 | #define HCCONTROL_USB_SUSPEND (3 << 6) | ||
45 | #define HCCONTROL_RWC (1 << 9) /* remote wakeup connected */ | ||
46 | #define HCCONTROL_RWE (1 << 10) /* remote wakeup enable */ | ||
47 | #define HCCMDSTAT 0x02 | ||
48 | #define HCCMDSTAT_HCR (1 << 0) /* host controller reset */ | ||
49 | #define HCCMDSTAT_SOC (3 << 16) /* scheduling overrun count */ | ||
50 | #define HCINTSTAT 0x03 | ||
51 | #define HCINT_SO (1 << 0) /* scheduling overrun */ | ||
52 | #define HCINT_WDH (1 << 1) /* writeback of done_head */ | ||
53 | #define HCINT_SF (1 << 2) /* start frame */ | ||
54 | #define HCINT_RD (1 << 3) /* resume detect */ | ||
55 | #define HCINT_UE (1 << 4) /* unrecoverable error */ | ||
56 | #define HCINT_FNO (1 << 5) /* frame number overflow */ | ||
57 | #define HCINT_RHSC (1 << 6) /* root hub status change */ | ||
58 | #define HCINT_OC (1 << 30) /* ownership change */ | ||
59 | #define HCINT_MIE (1 << 31) /* master interrupt enable */ | ||
60 | #define HCINTENB 0x04 | ||
61 | #define HCINTDIS 0x05 | ||
62 | #define HCFMINTVL 0x0d | ||
63 | #define HCFMREM 0x0e | ||
64 | #define HCFMNUM 0x0f | ||
65 | #define HCLSTHRESH 0x11 | ||
66 | #define HCRHDESCA 0x12 | ||
67 | #define RH_A_NDP (0x3 << 0) /* # downstream ports */ | ||
68 | #define RH_A_PSM (1 << 8) /* power switching mode */ | ||
69 | #define RH_A_NPS (1 << 9) /* no power switching */ | ||
70 | #define RH_A_DT (1 << 10) /* device type (mbz) */ | ||
71 | #define RH_A_OCPM (1 << 11) /* overcurrent protection | ||
72 | mode */ | ||
73 | #define RH_A_NOCP (1 << 12) /* no overcurrent protection */ | ||
74 | #define RH_A_POTPGT (0xff << 24) /* power on -> power good | ||
75 | time */ | ||
76 | #define HCRHDESCB 0x13 | ||
77 | #define RH_B_DR (0xffff << 0) /* device removable flags */ | ||
78 | #define RH_B_PPCM (0xffff << 16) /* port power control mask */ | ||
79 | #define HCRHSTATUS 0x14 | ||
80 | #define RH_HS_LPS (1 << 0) /* local power status */ | ||
81 | #define RH_HS_OCI (1 << 1) /* over current indicator */ | ||
82 | #define RH_HS_DRWE (1 << 15) /* device remote wakeup | ||
83 | enable */ | ||
84 | #define RH_HS_LPSC (1 << 16) /* local power status change */ | ||
85 | #define RH_HS_OCIC (1 << 17) /* over current indicator | ||
86 | change */ | ||
87 | #define RH_HS_CRWE (1 << 31) /* clear remote wakeup | ||
88 | enable */ | ||
89 | #define HCRHPORT1 0x15 | ||
90 | #define RH_PS_CCS (1 << 0) /* current connect status */ | ||
91 | #define RH_PS_PES (1 << 1) /* port enable status */ | ||
92 | #define RH_PS_PSS (1 << 2) /* port suspend status */ | ||
93 | #define RH_PS_POCI (1 << 3) /* port over current | ||
94 | indicator */ | ||
95 | #define RH_PS_PRS (1 << 4) /* port reset status */ | ||
96 | #define RH_PS_PPS (1 << 8) /* port power status */ | ||
97 | #define RH_PS_LSDA (1 << 9) /* low speed device attached */ | ||
98 | #define RH_PS_CSC (1 << 16) /* connect status change */ | ||
99 | #define RH_PS_PESC (1 << 17) /* port enable status change */ | ||
100 | #define RH_PS_PSSC (1 << 18) /* port suspend status | ||
101 | change */ | ||
102 | #define RH_PS_OCIC (1 << 19) /* over current indicator | ||
103 | change */ | ||
104 | #define RH_PS_PRSC (1 << 20) /* port reset status change */ | ||
105 | #define HCRHPORT_CLRMASK (0x1f << 16) | ||
106 | #define HCRHPORT2 0x16 | ||
107 | #define HCHWCFG 0x20 | ||
108 | #define HCHWCFG_15KRSEL (1 << 12) | ||
109 | #define HCHWCFG_CLKNOTSTOP (1 << 11) | ||
110 | #define HCHWCFG_ANALOG_OC (1 << 10) | ||
111 | #define HCHWCFG_DACK_MODE (1 << 8) | ||
112 | #define HCHWCFG_EOT_POL (1 << 7) | ||
113 | #define HCHWCFG_DACK_POL (1 << 6) | ||
114 | #define HCHWCFG_DREQ_POL (1 << 5) | ||
115 | #define HCHWCFG_DBWIDTH_MASK (0x03 << 3) | ||
116 | #define HCHWCFG_DBWIDTH(n) (((n) << 3) & HCHWCFG_DBWIDTH_MASK) | ||
117 | #define HCHWCFG_INT_POL (1 << 2) | ||
118 | #define HCHWCFG_INT_TRIGGER (1 << 1) | ||
119 | #define HCHWCFG_INT_ENABLE (1 << 0) | ||
120 | #define HCDMACFG 0x21 | ||
121 | #define HCDMACFG_BURST_LEN_MASK (0x03 << 5) | ||
122 | #define HCDMACFG_BURST_LEN(n) (((n) << 5) & HCDMACFG_BURST_LEN_MASK) | ||
123 | #define HCDMACFG_BURST_LEN_1 HCDMACFG_BURST_LEN(0) | ||
124 | #define HCDMACFG_BURST_LEN_4 HCDMACFG_BURST_LEN(1) | ||
125 | #define HCDMACFG_BURST_LEN_8 HCDMACFG_BURST_LEN(2) | ||
126 | #define HCDMACFG_DMA_ENABLE (1 << 4) | ||
127 | #define HCDMACFG_BUF_TYPE_MASK (0x07 << 1) | ||
128 | #define HCDMACFG_CTR_SEL (1 << 2) | ||
129 | #define HCDMACFG_ITLATL_SEL (1 << 1) | ||
130 | #define HCDMACFG_DMA_RW_SELECT (1 << 0) | ||
131 | #define HCXFERCTR 0x22 | ||
132 | #define HCuPINT 0x24 | ||
133 | #define HCuPINT_SOF (1 << 0) | ||
134 | #define HCuPINT_ATL (1 << 1) | ||
135 | #define HCuPINT_AIIEOT (1 << 2) | ||
136 | #define HCuPINT_OPR (1 << 4) | ||
137 | #define HCuPINT_SUSP (1 << 5) | ||
138 | #define HCuPINT_CLKRDY (1 << 6) | ||
139 | #define HCuPINTENB 0x25 | ||
140 | #define HCCHIPID 0x27 | ||
141 | #define HCCHIPID_MASK 0xff00 | ||
142 | #define HCCHIPID_MAGIC 0x6100 | ||
143 | #define HCSCRATCH 0x28 | ||
144 | #define HCSWRES 0x29 | ||
145 | #define HCSWRES_MAGIC 0x00f6 | ||
146 | #define HCITLBUFLEN 0x2a | ||
147 | #define HCATLBUFLEN 0x2b | ||
148 | #define HCBUFSTAT 0x2c | ||
149 | #define HCBUFSTAT_ITL0_FULL (1 << 0) | ||
150 | #define HCBUFSTAT_ITL1_FULL (1 << 1) | ||
151 | #define HCBUFSTAT_ATL_FULL (1 << 2) | ||
152 | #define HCBUFSTAT_ITL0_DONE (1 << 3) | ||
153 | #define HCBUFSTAT_ITL1_DONE (1 << 4) | ||
154 | #define HCBUFSTAT_ATL_DONE (1 << 5) | ||
155 | #define HCRDITL0LEN 0x2d | ||
156 | #define HCRDITL1LEN 0x2e | ||
157 | #define HCITLPORT 0x40 | ||
158 | #define HCATLPORT 0x41 | ||
159 | |||
160 | /* Philips transfer descriptor */ | ||
161 | struct ptd { | ||
162 | u16 count; | ||
163 | #define PTD_COUNT_MSK (0x3ff << 0) | ||
164 | #define PTD_TOGGLE_MSK (1 << 10) | ||
165 | #define PTD_ACTIVE_MSK (1 << 11) | ||
166 | #define PTD_CC_MSK (0xf << 12) | ||
167 | u16 mps; | ||
168 | #define PTD_MPS_MSK (0x3ff << 0) | ||
169 | #define PTD_SPD_MSK (1 << 10) | ||
170 | #define PTD_LAST_MSK (1 << 11) | ||
171 | #define PTD_EP_MSK (0xf << 12) | ||
172 | u16 len; | ||
173 | #define PTD_LEN_MSK (0x3ff << 0) | ||
174 | #define PTD_DIR_MSK (3 << 10) | ||
175 | #define PTD_DIR_SETUP (0) | ||
176 | #define PTD_DIR_OUT (1) | ||
177 | #define PTD_DIR_IN (2) | ||
178 | #define PTD_B5_5_MSK (1 << 13) | ||
179 | u16 faddr; | ||
180 | #define PTD_FA_MSK (0x7f << 0) | ||
181 | #define PTD_FMT_MSK (1 << 7) | ||
182 | } __attribute__ ((packed, aligned(2))); | ||
183 | |||
184 | /* PTD accessor macros. */ | ||
185 | #define PTD_GET_COUNT(p) (((p)->count & PTD_COUNT_MSK) >> 0) | ||
186 | #define PTD_COUNT(v) (((v) << 0) & PTD_COUNT_MSK) | ||
187 | #define PTD_GET_TOGGLE(p) (((p)->count & PTD_TOGGLE_MSK) >> 10) | ||
188 | #define PTD_TOGGLE(v) (((v) << 10) & PTD_TOGGLE_MSK) | ||
189 | #define PTD_GET_ACTIVE(p) (((p)->count & PTD_ACTIVE_MSK) >> 11) | ||
190 | #define PTD_ACTIVE(v) (((v) << 11) & PTD_ACTIVE_MSK) | ||
191 | #define PTD_GET_CC(p) (((p)->count & PTD_CC_MSK) >> 12) | ||
192 | #define PTD_CC(v) (((v) << 12) & PTD_CC_MSK) | ||
193 | #define PTD_GET_MPS(p) (((p)->mps & PTD_MPS_MSK) >> 0) | ||
194 | #define PTD_MPS(v) (((v) << 0) & PTD_MPS_MSK) | ||
195 | #define PTD_GET_SPD(p) (((p)->mps & PTD_SPD_MSK) >> 10) | ||
196 | #define PTD_SPD(v) (((v) << 10) & PTD_SPD_MSK) | ||
197 | #define PTD_GET_LAST(p) (((p)->mps & PTD_LAST_MSK) >> 11) | ||
198 | #define PTD_LAST(v) (((v) << 11) & PTD_LAST_MSK) | ||
199 | #define PTD_GET_EP(p) (((p)->mps & PTD_EP_MSK) >> 12) | ||
200 | #define PTD_EP(v) (((v) << 12) & PTD_EP_MSK) | ||
201 | #define PTD_GET_LEN(p) (((p)->len & PTD_LEN_MSK) >> 0) | ||
202 | #define PTD_LEN(v) (((v) << 0) & PTD_LEN_MSK) | ||
203 | #define PTD_GET_DIR(p) (((p)->len & PTD_DIR_MSK) >> 10) | ||
204 | #define PTD_DIR(v) (((v) << 10) & PTD_DIR_MSK) | ||
205 | #define PTD_GET_B5_5(p) (((p)->len & PTD_B5_5_MSK) >> 13) | ||
206 | #define PTD_B5_5(v) (((v) << 13) & PTD_B5_5_MSK) | ||
207 | #define PTD_GET_FA(p) (((p)->faddr & PTD_FA_MSK) >> 0) | ||
208 | #define PTD_FA(v) (((v) << 0) & PTD_FA_MSK) | ||
209 | #define PTD_GET_FMT(p) (((p)->faddr & PTD_FMT_MSK) >> 7) | ||
210 | #define PTD_FMT(v) (((v) << 7) & PTD_FMT_MSK) | ||
211 | |||
212 | /* Hardware transfer status codes -- CC from ptd->count */ | ||
213 | #define TD_CC_NOERROR 0x00 | ||
214 | #define TD_CC_CRC 0x01 | ||
215 | #define TD_CC_BITSTUFFING 0x02 | ||
216 | #define TD_CC_DATATOGGLEM 0x03 | ||
217 | #define TD_CC_STALL 0x04 | ||
218 | #define TD_DEVNOTRESP 0x05 | ||
219 | #define TD_PIDCHECKFAIL 0x06 | ||
220 | #define TD_UNEXPECTEDPID 0x07 | ||
221 | #define TD_DATAOVERRUN 0x08 | ||
222 | #define TD_DATAUNDERRUN 0x09 | ||
223 | /* 0x0A, 0x0B reserved for hardware */ | ||
224 | #define TD_BUFFEROVERRUN 0x0C | ||
225 | #define TD_BUFFERUNDERRUN 0x0D | ||
226 | /* 0x0E, 0x0F reserved for HCD */ | ||
227 | #define TD_NOTACCESSED 0x0F | ||
228 | |||
229 | /* map PTD status codes (CC) to errno values */ | ||
230 | static const int cc_to_error[16] = { | ||
231 | /* No Error */ 0, | ||
232 | /* CRC Error */ -EILSEQ, | ||
233 | /* Bit Stuff */ -EPROTO, | ||
234 | /* Data Togg */ -EILSEQ, | ||
235 | /* Stall */ -EPIPE, | ||
236 | /* DevNotResp */ -ETIMEDOUT, | ||
237 | /* PIDCheck */ -EPROTO, | ||
238 | /* UnExpPID */ -EPROTO, | ||
239 | /* DataOver */ -EOVERFLOW, | ||
240 | /* DataUnder */ -EREMOTEIO, | ||
241 | /* (for hw) */ -EIO, | ||
242 | /* (for hw) */ -EIO, | ||
243 | /* BufferOver */ -ECOMM, | ||
244 | /* BuffUnder */ -ENOSR, | ||
245 | /* (for HCD) */ -EALREADY, | ||
246 | /* (for HCD) */ -EALREADY | ||
247 | }; | ||
248 | |||
249 | /*--------------------------------------------------------------*/ | ||
250 | |||
251 | #define LOG2_PERIODIC_SIZE 5 /* arbitrary; this matches OHCI */ | ||
252 | #define PERIODIC_SIZE (1 << LOG2_PERIODIC_SIZE) | ||
253 | |||
254 | struct isp116x { | ||
255 | spinlock_t lock; | ||
256 | struct work_struct rh_resume; | ||
257 | |||
258 | void __iomem *addr_reg; | ||
259 | void __iomem *data_reg; | ||
260 | |||
261 | struct isp116x_platform_data *board; | ||
262 | |||
263 | struct proc_dir_entry *pde; | ||
264 | unsigned long stat1, stat2, stat4, stat8, stat16; | ||
265 | |||
266 | /* HC registers */ | ||
267 | u32 intenb; /* "OHCI" interrupts */ | ||
268 | u16 irqenb; /* uP interrupts */ | ||
269 | |||
270 | /* Root hub registers */ | ||
271 | u32 rhdesca; | ||
272 | u32 rhdescb; | ||
273 | u32 rhstatus; | ||
274 | u32 rhport[2]; | ||
275 | |||
276 | /* async schedule: control, bulk */ | ||
277 | struct list_head async; | ||
278 | |||
279 | /* periodic schedule: int */ | ||
280 | u16 load[PERIODIC_SIZE]; | ||
281 | struct isp116x_ep *periodic[PERIODIC_SIZE]; | ||
282 | unsigned periodic_count; | ||
283 | u16 fmindex; | ||
284 | |||
285 | /* Schedule for the current frame */ | ||
286 | struct isp116x_ep *atl_active; | ||
287 | int atl_buflen; | ||
288 | int atl_bufshrt; | ||
289 | int atl_last_dir; | ||
290 | atomic_t atl_finishing; | ||
291 | }; | ||
292 | |||
293 | static inline struct isp116x *hcd_to_isp116x(struct usb_hcd *hcd) | ||
294 | { | ||
295 | return (struct isp116x *)(hcd->hcd_priv); | ||
296 | } | ||
297 | |||
298 | static inline struct usb_hcd *isp116x_to_hcd(struct isp116x *isp116x) | ||
299 | { | ||
300 | return container_of((void *)isp116x, struct usb_hcd, hcd_priv); | ||
301 | } | ||
302 | |||
303 | struct isp116x_ep { | ||
304 | struct usb_host_endpoint *hep; | ||
305 | struct usb_device *udev; | ||
306 | struct ptd ptd; | ||
307 | |||
308 | u8 maxpacket; | ||
309 | u8 epnum; | ||
310 | u8 nextpid; | ||
311 | u16 error_count; | ||
312 | u16 length; /* of current packet */ | ||
313 | unsigned char *data; /* to databuf */ | ||
314 | /* queue of active EP's (the ones scheduled for the | ||
315 | current frame) */ | ||
316 | struct isp116x_ep *active; | ||
317 | |||
318 | /* periodic schedule */ | ||
319 | u16 period; | ||
320 | u16 branch; | ||
321 | u16 load; | ||
322 | struct isp116x_ep *next; | ||
323 | |||
324 | /* async schedule */ | ||
325 | struct list_head schedule; | ||
326 | }; | ||
327 | |||
328 | /*-------------------------------------------------------------------------*/ | ||
329 | |||
330 | #ifdef DEBUG | ||
331 | #define DBG(stuff...) printk(KERN_DEBUG "116x: " stuff) | ||
332 | #else | ||
333 | #define DBG(stuff...) do{}while(0) | ||
334 | #endif | ||
335 | |||
336 | #ifdef VERBOSE | ||
337 | # define VDBG DBG | ||
338 | #else | ||
339 | # define VDBG(stuff...) do{}while(0) | ||
340 | #endif | ||
341 | |||
342 | #define ERR(stuff...) printk(KERN_ERR "116x: " stuff) | ||
343 | #define WARN(stuff...) printk(KERN_WARNING "116x: " stuff) | ||
344 | #define INFO(stuff...) printk(KERN_INFO "116x: " stuff) | ||
345 | |||
346 | /* ------------------------------------------------- */ | ||
347 | |||
348 | #if defined(USE_PLATFORM_DELAY) | ||
349 | #if defined(USE_NDELAY) | ||
350 | #error USE_PLATFORM_DELAY and USE_NDELAY simultaneously defined. | ||
351 | #endif | ||
352 | #define isp116x_delay(h,d) (h)->board->delay( \ | ||
353 | isp116x_to_hcd(h)->self.controller,d) | ||
354 | #define isp116x_check_platform_delay(h) ((h)->board->delay == NULL) | ||
355 | #elif defined(USE_NDELAY) | ||
356 | #define isp116x_delay(h,d) ndelay(d) | ||
357 | #define isp116x_check_platform_delay(h) 0 | ||
358 | #else | ||
359 | #define isp116x_delay(h,d) do{}while(0) | ||
360 | #define isp116x_check_platform_delay(h) 0 | ||
361 | #endif | ||
362 | |||
363 | #if defined(DEBUG) | ||
364 | #define IRQ_TEST() BUG_ON(!irqs_disabled()) | ||
365 | #else | ||
366 | #define IRQ_TEST() do{}while(0) | ||
367 | #endif | ||
368 | |||
369 | static inline void isp116x_write_addr(struct isp116x *isp116x, unsigned reg) | ||
370 | { | ||
371 | IRQ_TEST(); | ||
372 | writew(reg & 0xff, isp116x->addr_reg); | ||
373 | isp116x_delay(isp116x, 300); | ||
374 | } | ||
375 | |||
376 | static inline void isp116x_write_data16(struct isp116x *isp116x, u16 val) | ||
377 | { | ||
378 | writew(val, isp116x->data_reg); | ||
379 | isp116x_delay(isp116x, 150); | ||
380 | } | ||
381 | |||
382 | static inline void isp116x_raw_write_data16(struct isp116x *isp116x, u16 val) | ||
383 | { | ||
384 | __raw_writew(val, isp116x->data_reg); | ||
385 | isp116x_delay(isp116x, 150); | ||
386 | } | ||
387 | |||
388 | static inline u16 isp116x_read_data16(struct isp116x *isp116x) | ||
389 | { | ||
390 | u16 val; | ||
391 | |||
392 | val = readw(isp116x->data_reg); | ||
393 | isp116x_delay(isp116x, 150); | ||
394 | return val; | ||
395 | } | ||
396 | |||
397 | static inline u16 isp116x_raw_read_data16(struct isp116x *isp116x) | ||
398 | { | ||
399 | u16 val; | ||
400 | |||
401 | val = __raw_readw(isp116x->data_reg); | ||
402 | isp116x_delay(isp116x, 150); | ||
403 | return val; | ||
404 | } | ||
405 | |||
406 | static inline void isp116x_write_data32(struct isp116x *isp116x, u32 val) | ||
407 | { | ||
408 | writew(val & 0xffff, isp116x->data_reg); | ||
409 | isp116x_delay(isp116x, 150); | ||
410 | writew(val >> 16, isp116x->data_reg); | ||
411 | isp116x_delay(isp116x, 150); | ||
412 | } | ||
413 | |||
414 | static inline u32 isp116x_read_data32(struct isp116x *isp116x) | ||
415 | { | ||
416 | u32 val; | ||
417 | |||
418 | val = (u32) readw(isp116x->data_reg); | ||
419 | isp116x_delay(isp116x, 150); | ||
420 | val |= ((u32) readw(isp116x->data_reg)) << 16; | ||
421 | isp116x_delay(isp116x, 150); | ||
422 | return val; | ||
423 | } | ||
424 | |||
425 | /* Let's keep register access functions out of line. Hint: | ||
426 | we wait at least 150 ns at every access. | ||
427 | */ | ||
428 | static u16 isp116x_read_reg16(struct isp116x *isp116x, unsigned reg) | ||
429 | { | ||
430 | isp116x_write_addr(isp116x, reg); | ||
431 | return isp116x_read_data16(isp116x); | ||
432 | } | ||
433 | |||
434 | static u32 isp116x_read_reg32(struct isp116x *isp116x, unsigned reg) | ||
435 | { | ||
436 | isp116x_write_addr(isp116x, reg); | ||
437 | return isp116x_read_data32(isp116x); | ||
438 | } | ||
439 | |||
440 | static void isp116x_write_reg16(struct isp116x *isp116x, unsigned reg, | ||
441 | unsigned val) | ||
442 | { | ||
443 | isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET); | ||
444 | isp116x_write_data16(isp116x, (u16) (val & 0xffff)); | ||
445 | } | ||
446 | |||
447 | static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg, | ||
448 | unsigned val) | ||
449 | { | ||
450 | isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET); | ||
451 | isp116x_write_data32(isp116x, (u32) val); | ||
452 | } | ||
453 | |||
454 | #define isp116x_show_reg(d,r) { \ | ||
455 | if ((r) < 0x20) { \ | ||
456 | DBG("%-12s[%02x]: %08x\n", #r, \ | ||
457 | r, isp116x_read_reg32(d, r)); \ | ||
458 | } else { \ | ||
459 | DBG("%-12s[%02x]: %04x\n", #r, \ | ||
460 | r, isp116x_read_reg16(d, r)); \ | ||
461 | } \ | ||
462 | } | ||
463 | |||
464 | static inline void isp116x_show_regs(struct isp116x *isp116x) | ||
465 | { | ||
466 | isp116x_show_reg(isp116x, HCREVISION); | ||
467 | isp116x_show_reg(isp116x, HCCONTROL); | ||
468 | isp116x_show_reg(isp116x, HCCMDSTAT); | ||
469 | isp116x_show_reg(isp116x, HCINTSTAT); | ||
470 | isp116x_show_reg(isp116x, HCINTENB); | ||
471 | isp116x_show_reg(isp116x, HCFMINTVL); | ||
472 | isp116x_show_reg(isp116x, HCFMREM); | ||
473 | isp116x_show_reg(isp116x, HCFMNUM); | ||
474 | isp116x_show_reg(isp116x, HCLSTHRESH); | ||
475 | isp116x_show_reg(isp116x, HCRHDESCA); | ||
476 | isp116x_show_reg(isp116x, HCRHDESCB); | ||
477 | isp116x_show_reg(isp116x, HCRHSTATUS); | ||
478 | isp116x_show_reg(isp116x, HCRHPORT1); | ||
479 | isp116x_show_reg(isp116x, HCRHPORT2); | ||
480 | isp116x_show_reg(isp116x, HCHWCFG); | ||
481 | isp116x_show_reg(isp116x, HCDMACFG); | ||
482 | isp116x_show_reg(isp116x, HCXFERCTR); | ||
483 | isp116x_show_reg(isp116x, HCuPINT); | ||
484 | isp116x_show_reg(isp116x, HCuPINTENB); | ||
485 | isp116x_show_reg(isp116x, HCCHIPID); | ||
486 | isp116x_show_reg(isp116x, HCSCRATCH); | ||
487 | isp116x_show_reg(isp116x, HCITLBUFLEN); | ||
488 | isp116x_show_reg(isp116x, HCATLBUFLEN); | ||
489 | isp116x_show_reg(isp116x, HCBUFSTAT); | ||
490 | isp116x_show_reg(isp116x, HCRDITL0LEN); | ||
491 | isp116x_show_reg(isp116x, HCRDITL1LEN); | ||
492 | } | ||
493 | |||
494 | #if defined(URB_TRACE) | ||
495 | |||
496 | #define PIPETYPE(pipe) ({ char *__s; \ | ||
497 | if (usb_pipecontrol(pipe)) __s = "ctrl"; \ | ||
498 | else if (usb_pipeint(pipe)) __s = "int"; \ | ||
499 | else if (usb_pipebulk(pipe)) __s = "bulk"; \ | ||
500 | else __s = "iso"; \ | ||
501 | __s;}) | ||
502 | #define PIPEDIR(pipe) ({ usb_pipein(pipe) ? "in" : "out"; }) | ||
503 | #define URB_NOTSHORT(urb) ({ (urb)->transfer_flags & URB_SHORT_NOT_OK ? \ | ||
504 | "short_not_ok" : ""; }) | ||
505 | |||
506 | /* print debug info about the URB */ | ||
507 | static void urb_dbg(struct urb *urb, char *msg) | ||
508 | { | ||
509 | unsigned int pipe; | ||
510 | |||
511 | if (!urb) { | ||
512 | DBG("%s: zero urb\n", msg); | ||
513 | return; | ||
514 | } | ||
515 | pipe = urb->pipe; | ||
516 | DBG("%s: FA %d ep%d%s %s: len %d/%d %s\n", msg, | ||
517 | usb_pipedevice(pipe), usb_pipeendpoint(pipe), | ||
518 | PIPEDIR(pipe), PIPETYPE(pipe), | ||
519 | urb->transfer_buffer_length, urb->actual_length, URB_NOTSHORT(urb)); | ||
520 | } | ||
521 | |||
522 | #else | ||
523 | |||
524 | #define urb_dbg(urb,msg) do{}while(0) | ||
525 | |||
526 | #endif /* ! defined(URB_TRACE) */ | ||
527 | |||
528 | #if defined(PTD_TRACE) | ||
529 | |||
530 | #define PTD_DIR_STR(ptd) ({char __c; \ | ||
531 | switch(PTD_GET_DIR(ptd)){ \ | ||
532 | case 0: __c = 's'; break; \ | ||
533 | case 1: __c = 'o'; break; \ | ||
534 | default: __c = 'i'; break; \ | ||
535 | }; __c;}) | ||
536 | |||
537 | /* | ||
538 | Dump PTD info. The code documents the format | ||
539 | perfectly, right :) | ||
540 | */ | ||
541 | static inline void dump_ptd(struct ptd *ptd) | ||
542 | { | ||
543 | printk("td: %x %d%c%d %d,%d,%d %x %x%x%x\n", | ||
544 | PTD_GET_CC(ptd), PTD_GET_FA(ptd), | ||
545 | PTD_DIR_STR(ptd), PTD_GET_EP(ptd), | ||
546 | PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd), | ||
547 | PTD_GET_TOGGLE(ptd), PTD_GET_ACTIVE(ptd), | ||
548 | PTD_GET_SPD(ptd), PTD_GET_LAST(ptd)); | ||
549 | } | ||
550 | |||
551 | static inline void dump_ptd_out_data(struct ptd *ptd, u8 * buf) | ||
552 | { | ||
553 | int k; | ||
554 | |||
555 | if (PTD_GET_DIR(ptd) != PTD_DIR_IN && PTD_GET_LEN(ptd)) { | ||
556 | printk("-> "); | ||
557 | for (k = 0; k < PTD_GET_LEN(ptd); ++k) | ||
558 | printk("%02x ", ((u8 *) buf)[k]); | ||
559 | printk("\n"); | ||
560 | } | ||
561 | } | ||
562 | |||
563 | static inline void dump_ptd_in_data(struct ptd *ptd, u8 * buf) | ||
564 | { | ||
565 | int k; | ||
566 | |||
567 | if (PTD_GET_DIR(ptd) == PTD_DIR_IN && PTD_GET_COUNT(ptd)) { | ||
568 | printk("<- "); | ||
569 | for (k = 0; k < PTD_GET_COUNT(ptd); ++k) | ||
570 | printk("%02x ", ((u8 *) buf)[k]); | ||
571 | printk("\n"); | ||
572 | } | ||
573 | if (PTD_GET_LAST(ptd)) | ||
574 | printk("-\n"); | ||
575 | } | ||
576 | |||
577 | #else | ||
578 | |||
579 | #define dump_ptd(ptd) do{}while(0) | ||
580 | #define dump_ptd_in_data(ptd,buf) do{}while(0) | ||
581 | #define dump_ptd_out_data(ptd,buf) do{}while(0) | ||
582 | |||
583 | #endif /* ! defined(PTD_TRACE) */ | ||
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 1e27f10c1592..13cd2177b557 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -95,12 +95,11 @@ | |||
95 | #include <linux/init.h> | 95 | #include <linux/init.h> |
96 | #include <linux/timer.h> | 96 | #include <linux/timer.h> |
97 | #include <linux/list.h> | 97 | #include <linux/list.h> |
98 | #include <linux/interrupt.h> /* for in_interrupt () */ | ||
99 | #include <linux/usb.h> | 98 | #include <linux/usb.h> |
100 | #include <linux/usb_otg.h> | 99 | #include <linux/usb_otg.h> |
101 | #include "../core/hcd.h" | ||
102 | #include <linux/dma-mapping.h> | 100 | #include <linux/dma-mapping.h> |
103 | #include <linux/dmapool.h> /* needed by ohci-mem.c when no PCI */ | 101 | #include <linux/dmapool.h> |
102 | #include <linux/reboot.h> | ||
104 | 103 | ||
105 | #include <asm/io.h> | 104 | #include <asm/io.h> |
106 | #include <asm/irq.h> | 105 | #include <asm/irq.h> |
@@ -108,8 +107,9 @@ | |||
108 | #include <asm/unaligned.h> | 107 | #include <asm/unaligned.h> |
109 | #include <asm/byteorder.h> | 108 | #include <asm/byteorder.h> |
110 | 109 | ||
110 | #include "../core/hcd.h" | ||
111 | 111 | ||
112 | #define DRIVER_VERSION "2004 Nov 08" | 112 | #define DRIVER_VERSION "2005 April 22" |
113 | #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" | 113 | #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" |
114 | #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" | 114 | #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" |
115 | 115 | ||
@@ -141,6 +141,7 @@ static const char hcd_name [] = "ohci_hcd"; | |||
141 | static void ohci_dump (struct ohci_hcd *ohci, int verbose); | 141 | static void ohci_dump (struct ohci_hcd *ohci, int verbose); |
142 | static int ohci_init (struct ohci_hcd *ohci); | 142 | static int ohci_init (struct ohci_hcd *ohci); |
143 | static void ohci_stop (struct usb_hcd *hcd); | 143 | static void ohci_stop (struct usb_hcd *hcd); |
144 | static int ohci_reboot (struct notifier_block *, unsigned long , void *); | ||
144 | 145 | ||
145 | #include "ohci-hub.c" | 146 | #include "ohci-hub.c" |
146 | #include "ohci-dbg.c" | 147 | #include "ohci-dbg.c" |
@@ -420,6 +421,23 @@ static void ohci_usb_reset (struct ohci_hcd *ohci) | |||
420 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); | 421 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); |
421 | } | 422 | } |
422 | 423 | ||
424 | /* reboot notifier forcibly disables IRQs and DMA, helping kexec and | ||
425 | * other cases where the next software may expect clean state from the | ||
426 | * "firmware". this is bus-neutral, unlike shutdown() methods. | ||
427 | */ | ||
428 | static int | ||
429 | ohci_reboot (struct notifier_block *block, unsigned long code, void *null) | ||
430 | { | ||
431 | struct ohci_hcd *ohci; | ||
432 | |||
433 | ohci = container_of (block, struct ohci_hcd, reboot_notifier); | ||
434 | ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); | ||
435 | ohci_usb_reset (ohci); | ||
436 | /* flush the writes */ | ||
437 | (void) ohci_readl (ohci, &ohci->regs->control); | ||
438 | return 0; | ||
439 | } | ||
440 | |||
423 | /*-------------------------------------------------------------------------* | 441 | /*-------------------------------------------------------------------------* |
424 | * HC functions | 442 | * HC functions |
425 | *-------------------------------------------------------------------------*/ | 443 | *-------------------------------------------------------------------------*/ |
@@ -487,13 +505,10 @@ static int ohci_init (struct ohci_hcd *ohci) | |||
487 | /* Start an OHCI controller, set the BUS operational | 505 | /* Start an OHCI controller, set the BUS operational |
488 | * resets USB and controller | 506 | * resets USB and controller |
489 | * enable interrupts | 507 | * enable interrupts |
490 | * connect the virtual root hub | ||
491 | */ | 508 | */ |
492 | static int ohci_run (struct ohci_hcd *ohci) | 509 | static int ohci_run (struct ohci_hcd *ohci) |
493 | { | 510 | { |
494 | u32 mask, temp; | 511 | u32 mask, temp; |
495 | struct usb_device *udev; | ||
496 | struct usb_bus *bus; | ||
497 | int first = ohci->fminterval == 0; | 512 | int first = ohci->fminterval == 0; |
498 | 513 | ||
499 | disable (ohci); | 514 | disable (ohci); |
@@ -654,37 +669,13 @@ retry: | |||
654 | 669 | ||
655 | // POTPGT delay is bits 24-31, in 2 ms units. | 670 | // POTPGT delay is bits 24-31, in 2 ms units. |
656 | mdelay ((temp >> 23) & 0x1fe); | 671 | mdelay ((temp >> 23) & 0x1fe); |
657 | bus = &ohci_to_hcd(ohci)->self; | ||
658 | ohci_to_hcd(ohci)->state = HC_STATE_RUNNING; | 672 | ohci_to_hcd(ohci)->state = HC_STATE_RUNNING; |
659 | 673 | ||
660 | ohci_dump (ohci, 1); | 674 | ohci_dump (ohci, 1); |
661 | 675 | ||
662 | udev = bus->root_hub; | 676 | if (ohci_to_hcd(ohci)->self.root_hub == NULL) |
663 | if (udev) { | 677 | create_debug_files (ohci); |
664 | return 0; | ||
665 | } | ||
666 | |||
667 | /* connect the virtual root hub */ | ||
668 | udev = usb_alloc_dev (NULL, bus, 0); | ||
669 | if (!udev) { | ||
670 | disable (ohci); | ||
671 | ohci->hc_control &= ~OHCI_CTRL_HCFS; | ||
672 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); | ||
673 | return -ENOMEM; | ||
674 | } | ||
675 | |||
676 | udev->speed = USB_SPEED_FULL; | ||
677 | if (usb_hcd_register_root_hub (udev, ohci_to_hcd(ohci)) != 0) { | ||
678 | usb_put_dev (udev); | ||
679 | disable (ohci); | ||
680 | ohci->hc_control &= ~OHCI_CTRL_HCFS; | ||
681 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); | ||
682 | return -ENODEV; | ||
683 | } | ||
684 | if (ohci->power_budget) | ||
685 | hub_set_power_budget(udev, ohci->power_budget); | ||
686 | 678 | ||
687 | create_debug_files (ohci); | ||
688 | return 0; | 679 | return 0; |
689 | } | 680 | } |
690 | 681 | ||
@@ -781,6 +772,7 @@ static void ohci_stop (struct usb_hcd *hcd) | |||
781 | ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); | 772 | ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); |
782 | 773 | ||
783 | remove_debug_files (ohci); | 774 | remove_debug_files (ohci); |
775 | unregister_reboot_notifier (&ohci->reboot_notifier); | ||
784 | ohci_mem_cleanup (ohci); | 776 | ohci_mem_cleanup (ohci); |
785 | if (ohci->hcca) { | 777 | if (ohci->hcca) { |
786 | dma_free_coherent (hcd->self.controller, | 778 | dma_free_coherent (hcd->self.controller, |
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c index e55682b4919d..23735a36af00 100644 --- a/drivers/usb/host/ohci-mem.c +++ b/drivers/usb/host/ohci-mem.c | |||
@@ -29,6 +29,7 @@ static void ohci_hcd_init (struct ohci_hcd *ohci) | |||
29 | spin_lock_init (&ohci->lock); | 29 | spin_lock_init (&ohci->lock); |
30 | INIT_LIST_HEAD (&ohci->pending); | 30 | INIT_LIST_HEAD (&ohci->pending); |
31 | INIT_WORK (&ohci->rh_resume, ohci_rh_resume, ohci_to_hcd(ohci)); | 31 | INIT_WORK (&ohci->rh_resume, ohci_rh_resume, ohci_to_hcd(ohci)); |
32 | ohci->reboot_notifier.notifier_call = ohci_reboot; | ||
32 | } | 33 | } |
33 | 34 | ||
34 | /*-------------------------------------------------------------------------*/ | 35 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 8aab5907afe9..b62d69937694 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c | |||
@@ -181,7 +181,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev) | |||
181 | if (config->otg) { | 181 | if (config->otg) { |
182 | ohci_to_hcd(ohci)->self.otg_port = config->otg; | 182 | ohci_to_hcd(ohci)->self.otg_port = config->otg; |
183 | /* default/minimum OTG power budget: 8 mA */ | 183 | /* default/minimum OTG power budget: 8 mA */ |
184 | ohci->power_budget = 8; | 184 | ohci_to_hcd(ohci)->power_budget = 8; |
185 | } | 185 | } |
186 | 186 | ||
187 | /* boards can use OTG transceivers in non-OTG modes */ | 187 | /* boards can use OTG transceivers in non-OTG modes */ |
@@ -230,7 +230,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev) | |||
230 | 230 | ||
231 | /* TPS2045 switch for internal transceiver (port 1) */ | 231 | /* TPS2045 switch for internal transceiver (port 1) */ |
232 | if (machine_is_omap_osk()) { | 232 | if (machine_is_omap_osk()) { |
233 | ohci->power_budget = 250; | 233 | ohci_to_hcd(ohci)->power_budget = 250; |
234 | 234 | ||
235 | rh &= ~RH_A_NOCP; | 235 | rh &= ~RH_A_NOCP; |
236 | 236 | ||
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 57fd07d00549..eede6be098d2 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
@@ -14,14 +14,11 @@ | |||
14 | * This file is licenced under the GPL. | 14 | * This file is licenced under the GPL. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #ifdef CONFIG_PMAC_PBOOK | 17 | #ifdef CONFIG_PPC_PMAC |
18 | #include <asm/machdep.h> | 18 | #include <asm/machdep.h> |
19 | #include <asm/pmac_feature.h> | 19 | #include <asm/pmac_feature.h> |
20 | #include <asm/pci-bridge.h> | 20 | #include <asm/pci-bridge.h> |
21 | #include <asm/prom.h> | 21 | #include <asm/prom.h> |
22 | #ifndef CONFIG_PM | ||
23 | # define CONFIG_PM | ||
24 | #endif | ||
25 | #endif | 22 | #endif |
26 | 23 | ||
27 | #ifndef CONFIG_PCI | 24 | #ifndef CONFIG_PCI |
@@ -132,7 +129,7 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) | |||
132 | /* let things settle down a bit */ | 129 | /* let things settle down a bit */ |
133 | msleep (100); | 130 | msleep (100); |
134 | 131 | ||
135 | #ifdef CONFIG_PMAC_PBOOK | 132 | #ifdef CONFIG_PPC_PMAC |
136 | if (_machine == _MACH_Pmac) { | 133 | if (_machine == _MACH_Pmac) { |
137 | struct device_node *of_node; | 134 | struct device_node *of_node; |
138 | 135 | ||
@@ -141,7 +138,7 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) | |||
141 | if (of_node) | 138 | if (of_node) |
142 | pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); | 139 | pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); |
143 | } | 140 | } |
144 | #endif /* CONFIG_PMAC_PBOOK */ | 141 | #endif /* CONFIG_PPC_PMAC */ |
145 | return 0; | 142 | return 0; |
146 | } | 143 | } |
147 | 144 | ||
@@ -151,7 +148,7 @@ static int ohci_pci_resume (struct usb_hcd *hcd) | |||
151 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 148 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
152 | int retval = 0; | 149 | int retval = 0; |
153 | 150 | ||
154 | #ifdef CONFIG_PMAC_PBOOK | 151 | #ifdef CONFIG_PPC_PMAC |
155 | if (_machine == _MACH_Pmac) { | 152 | if (_machine == _MACH_Pmac) { |
156 | struct device_node *of_node; | 153 | struct device_node *of_node; |
157 | 154 | ||
@@ -160,7 +157,7 @@ static int ohci_pci_resume (struct usb_hcd *hcd) | |||
160 | if (of_node) | 157 | if (of_node) |
161 | pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1); | 158 | pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1); |
162 | } | 159 | } |
163 | #endif /* CONFIG_PMAC_PBOOK */ | 160 | #endif /* CONFIG_PPC_PMAC */ |
164 | 161 | ||
165 | /* resume root hub */ | 162 | /* resume root hub */ |
166 | if (time_before (jiffies, ohci->next_statechange)) | 163 | if (time_before (jiffies, ohci->next_statechange)) |
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 22e1ac138ac0..71cdd2262860 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h | |||
@@ -371,7 +371,6 @@ struct ohci_hcd { | |||
371 | * other external transceivers should be software-transparent | 371 | * other external transceivers should be software-transparent |
372 | */ | 372 | */ |
373 | struct otg_transceiver *transceiver; | 373 | struct otg_transceiver *transceiver; |
374 | unsigned power_budget; | ||
375 | 374 | ||
376 | /* | 375 | /* |
377 | * memory management for queue data structures | 376 | * memory management for queue data structures |
@@ -390,6 +389,7 @@ struct ohci_hcd { | |||
390 | u32 fminterval; /* saved register */ | 389 | u32 fminterval; /* saved register */ |
391 | 390 | ||
392 | struct work_struct rh_resume; | 391 | struct work_struct rh_resume; |
392 | struct notifier_block reboot_notifier; | ||
393 | 393 | ||
394 | unsigned long flags; /* for HC bugs */ | 394 | unsigned long flags; /* for HC bugs */ |
395 | #define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ | 395 | #define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ |
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 99d43f758ad0..6c3f910bc307 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c | |||
@@ -1563,29 +1563,15 @@ static int | |||
1563 | sl811h_start(struct usb_hcd *hcd) | 1563 | sl811h_start(struct usb_hcd *hcd) |
1564 | { | 1564 | { |
1565 | struct sl811 *sl811 = hcd_to_sl811(hcd); | 1565 | struct sl811 *sl811 = hcd_to_sl811(hcd); |
1566 | struct usb_device *udev; | ||
1567 | 1566 | ||
1568 | /* chip has been reset, VBUS power is off */ | 1567 | /* chip has been reset, VBUS power is off */ |
1569 | |||
1570 | udev = usb_alloc_dev(NULL, &hcd->self, 0); | ||
1571 | if (!udev) | ||
1572 | return -ENOMEM; | ||
1573 | |||
1574 | udev->speed = USB_SPEED_FULL; | ||
1575 | hcd->state = HC_STATE_RUNNING; | 1568 | hcd->state = HC_STATE_RUNNING; |
1576 | 1569 | ||
1577 | if (sl811->board) | 1570 | if (sl811->board) { |
1578 | hcd->can_wakeup = sl811->board->can_wakeup; | 1571 | hcd->can_wakeup = sl811->board->can_wakeup; |
1579 | 1572 | hcd->power_budget = sl811->board->power * 2; | |
1580 | if (usb_hcd_register_root_hub(udev, hcd) != 0) { | ||
1581 | usb_put_dev(udev); | ||
1582 | sl811h_stop(hcd); | ||
1583 | return -ENODEV; | ||
1584 | } | 1573 | } |
1585 | 1574 | ||
1586 | if (sl811->board && sl811->board->power) | ||
1587 | hub_set_power_budget(udev, sl811->board->power * 2); | ||
1588 | |||
1589 | /* enable power and interupts */ | 1575 | /* enable power and interupts */ |
1590 | port_power(sl811, 1); | 1576 | port_power(sl811, 1); |
1591 | 1577 | ||
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 24c73c5a3435..4538a98b6f9d 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c | |||
@@ -237,6 +237,37 @@ static int uhci_show_sc(int port, unsigned short status, char *buf, int len) | |||
237 | return out - buf; | 237 | return out - buf; |
238 | } | 238 | } |
239 | 239 | ||
240 | static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf, int len) | ||
241 | { | ||
242 | char *out = buf; | ||
243 | char *rh_state; | ||
244 | |||
245 | /* Try to make sure there's enough memory */ | ||
246 | if (len < 60) | ||
247 | return 0; | ||
248 | |||
249 | switch (uhci->rh_state) { | ||
250 | case UHCI_RH_RESET: | ||
251 | rh_state = "reset"; break; | ||
252 | case UHCI_RH_SUSPENDED: | ||
253 | rh_state = "suspended"; break; | ||
254 | case UHCI_RH_AUTO_STOPPED: | ||
255 | rh_state = "auto-stopped"; break; | ||
256 | case UHCI_RH_RESUMING: | ||
257 | rh_state = "resuming"; break; | ||
258 | case UHCI_RH_SUSPENDING: | ||
259 | rh_state = "suspending"; break; | ||
260 | case UHCI_RH_RUNNING: | ||
261 | rh_state = "running"; break; | ||
262 | case UHCI_RH_RUNNING_NODEVS: | ||
263 | rh_state = "running, no devs"; break; | ||
264 | default: | ||
265 | rh_state = "?"; break; | ||
266 | } | ||
267 | out += sprintf(out, "Root-hub state: %s\n", rh_state); | ||
268 | return out - buf; | ||
269 | } | ||
270 | |||
240 | static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) | 271 | static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) |
241 | { | 272 | { |
242 | char *out = buf; | 273 | char *out = buf; |
@@ -408,6 +439,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) | |||
408 | 439 | ||
409 | spin_lock_irqsave(&uhci->lock, flags); | 440 | spin_lock_irqsave(&uhci->lock, flags); |
410 | 441 | ||
442 | out += uhci_show_root_hub_state(uhci, out, len - (out - buf)); | ||
411 | out += sprintf(out, "HC status\n"); | 443 | out += sprintf(out, "HC status\n"); |
412 | out += uhci_show_status(uhci, out, len - (out - buf)); | 444 | out += uhci_show_status(uhci, out, len - (out - buf)); |
413 | 445 | ||
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 49bd83ee0c75..0d5d2545bf07 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -13,18 +13,13 @@ | |||
13 | * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface | 13 | * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface |
14 | * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). | 14 | * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). |
15 | * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) | 15 | * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) |
16 | * (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu | 16 | * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu |
17 | * | 17 | * |
18 | * Intel documents this fairly well, and as far as I know there | 18 | * Intel documents this fairly well, and as far as I know there |
19 | * are no royalties or anything like that, but even so there are | 19 | * are no royalties or anything like that, but even so there are |
20 | * people who decided that they want to do the same thing in a | 20 | * people who decided that they want to do the same thing in a |
21 | * completely different way. | 21 | * completely different way. |
22 | * | 22 | * |
23 | * WARNING! The USB documentation is downright evil. Most of it | ||
24 | * is just crap, written by a committee. You're better off ignoring | ||
25 | * most of it, the important stuff is: | ||
26 | * - the low-level protocol (fairly simple but lots of small details) | ||
27 | * - working around the horridness of the rest | ||
28 | */ | 23 | */ |
29 | 24 | ||
30 | #include <linux/config.h> | 25 | #include <linux/config.h> |
@@ -64,7 +59,7 @@ | |||
64 | /* | 59 | /* |
65 | * Version Information | 60 | * Version Information |
66 | */ | 61 | */ |
67 | #define DRIVER_VERSION "v2.2" | 62 | #define DRIVER_VERSION "v2.3" |
68 | #define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \ | 63 | #define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \ |
69 | Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \ | 64 | Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \ |
70 | Alan Stern" | 65 | Alan Stern" |
@@ -89,8 +84,9 @@ static char *errbuf; | |||
89 | 84 | ||
90 | static kmem_cache_t *uhci_up_cachep; /* urb_priv */ | 85 | static kmem_cache_t *uhci_up_cachep; /* urb_priv */ |
91 | 86 | ||
87 | static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state); | ||
88 | static void wakeup_rh(struct uhci_hcd *uhci); | ||
92 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci); | 89 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci); |
93 | static void hc_state_transitions(struct uhci_hcd *uhci); | ||
94 | 90 | ||
95 | /* If a transfer is still active after this much time, turn off FSBR */ | 91 | /* If a transfer is still active after this much time, turn off FSBR */ |
96 | #define IDLE_TIMEOUT msecs_to_jiffies(50) | 92 | #define IDLE_TIMEOUT msecs_to_jiffies(50) |
@@ -101,308 +97,352 @@ static void hc_state_transitions(struct uhci_hcd *uhci); | |||
101 | /* to make sure it doesn't hog all of the bandwidth */ | 97 | /* to make sure it doesn't hog all of the bandwidth */ |
102 | #define DEPTH_INTERVAL 5 | 98 | #define DEPTH_INTERVAL 5 |
103 | 99 | ||
100 | static inline void restart_timer(struct uhci_hcd *uhci) | ||
101 | { | ||
102 | mod_timer(&uhci->stall_timer, jiffies + msecs_to_jiffies(100)); | ||
103 | } | ||
104 | |||
104 | #include "uhci-hub.c" | 105 | #include "uhci-hub.c" |
105 | #include "uhci-debug.c" | 106 | #include "uhci-debug.c" |
106 | #include "uhci-q.c" | 107 | #include "uhci-q.c" |
107 | 108 | ||
108 | static int init_stall_timer(struct usb_hcd *hcd); | 109 | /* |
109 | 110 | * Make sure the controller is completely inactive, unable to | |
110 | static void stall_callback(unsigned long ptr) | 111 | * generate interrupts or do DMA. |
112 | */ | ||
113 | static void reset_hc(struct uhci_hcd *uhci) | ||
111 | { | 114 | { |
112 | struct usb_hcd *hcd = (struct usb_hcd *)ptr; | 115 | int port; |
113 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | ||
114 | struct urb_priv *up; | ||
115 | unsigned long flags; | ||
116 | 116 | ||
117 | spin_lock_irqsave(&uhci->lock, flags); | 117 | /* Turn off PIRQ enable and SMI enable. (This also turns off the |
118 | uhci_scan_schedule(uhci, NULL); | 118 | * BIOS's USB Legacy Support.) Turn off all the R/WC bits too. |
119 | 119 | */ | |
120 | list_for_each_entry(up, &uhci->urb_list, urb_list) { | 120 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, |
121 | struct urb *u = up->urb; | 121 | USBLEGSUP_RWC); |
122 | |||
123 | spin_lock(&u->lock); | ||
124 | |||
125 | /* Check if the FSBR timed out */ | ||
126 | if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT)) | ||
127 | uhci_fsbr_timeout(uhci, u); | ||
128 | 122 | ||
129 | spin_unlock(&u->lock); | 123 | /* Reset the HC - this will force us to get a |
130 | } | 124 | * new notification of any already connected |
125 | * ports due to the virtual disconnect that it | ||
126 | * implies. | ||
127 | */ | ||
128 | outw(USBCMD_HCRESET, uhci->io_addr + USBCMD); | ||
129 | mb(); | ||
130 | udelay(5); | ||
131 | if (inw(uhci->io_addr + USBCMD) & USBCMD_HCRESET) | ||
132 | dev_warn(uhci_dev(uhci), "HCRESET not completed yet!\n"); | ||
131 | 133 | ||
132 | /* Really disable FSBR */ | 134 | /* Just to be safe, disable interrupt requests and |
133 | if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) { | 135 | * make sure the controller is stopped. |
134 | uhci->fsbrtimeout = 0; | 136 | */ |
135 | uhci->skel_term_qh->link = UHCI_PTR_TERM; | 137 | outw(0, uhci->io_addr + USBINTR); |
136 | } | 138 | outw(0, uhci->io_addr + USBCMD); |
137 | 139 | ||
138 | /* Poll for and perform state transitions */ | 140 | /* HCRESET doesn't affect the Suspend, Reset, and Resume Detect |
139 | hc_state_transitions(uhci); | 141 | * bits in the port status and control registers. |
140 | if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED)) | 142 | * We have to clear them by hand. |
141 | uhci_check_ports(uhci); | 143 | */ |
144 | for (port = 0; port < uhci->rh_numports; ++port) | ||
145 | outw(0, uhci->io_addr + USBPORTSC1 + (port * 2)); | ||
142 | 146 | ||
143 | init_stall_timer(hcd); | 147 | uhci->port_c_suspend = uhci->suspended_ports = |
144 | spin_unlock_irqrestore(&uhci->lock, flags); | 148 | uhci->resuming_ports = 0; |
149 | uhci->rh_state = UHCI_RH_RESET; | ||
150 | uhci->is_stopped = UHCI_IS_STOPPED; | ||
151 | uhci_to_hcd(uhci)->state = HC_STATE_HALT; | ||
152 | uhci_to_hcd(uhci)->poll_rh = 0; | ||
145 | } | 153 | } |
146 | 154 | ||
147 | static int init_stall_timer(struct usb_hcd *hcd) | 155 | /* |
156 | * Last rites for a defunct/nonfunctional controller | ||
157 | * or one we don't want to use any more. | ||
158 | */ | ||
159 | static void hc_died(struct uhci_hcd *uhci) | ||
148 | { | 160 | { |
149 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 161 | reset_hc(uhci); |
150 | 162 | uhci->hc_inaccessible = 1; | |
151 | init_timer(&uhci->stall_timer); | 163 | del_timer(&uhci->stall_timer); |
152 | uhci->stall_timer.function = stall_callback; | ||
153 | uhci->stall_timer.data = (unsigned long)hcd; | ||
154 | uhci->stall_timer.expires = jiffies + msecs_to_jiffies(100); | ||
155 | add_timer(&uhci->stall_timer); | ||
156 | |||
157 | return 0; | ||
158 | } | 164 | } |
159 | 165 | ||
160 | static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) | 166 | /* |
167 | * Initialize a controller that was newly discovered or has just been | ||
168 | * resumed. In either case we can't be sure of its previous state. | ||
169 | */ | ||
170 | static void check_and_reset_hc(struct uhci_hcd *uhci) | ||
161 | { | 171 | { |
162 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 172 | u16 legsup; |
163 | unsigned long io_addr = uhci->io_addr; | 173 | unsigned int cmd, intr; |
164 | unsigned short status; | ||
165 | 174 | ||
166 | /* | 175 | /* |
167 | * Read the interrupt status, and write it back to clear the | 176 | * When restarting a suspended controller, we expect all the |
168 | * interrupt cause. Contrary to the UHCI specification, the | 177 | * settings to be the same as we left them: |
169 | * "HC Halted" status bit is persistent: it is RO, not R/WC. | 178 | * |
179 | * PIRQ and SMI disabled, no R/W bits set in USBLEGSUP; | ||
180 | * Controller is stopped and configured with EGSM set; | ||
181 | * No interrupts enabled except possibly Resume Detect. | ||
182 | * | ||
183 | * If any of these conditions are violated we do a complete reset. | ||
170 | */ | 184 | */ |
171 | status = inw(io_addr + USBSTS); | 185 | pci_read_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, &legsup); |
172 | if (!(status & ~USBSTS_HCH)) /* shared interrupt, not mine */ | 186 | if (legsup & ~(USBLEGSUP_RO | USBLEGSUP_RWC)) { |
173 | return IRQ_NONE; | 187 | dev_dbg(uhci_dev(uhci), "%s: legsup = 0x%04x\n", |
174 | outw(status, io_addr + USBSTS); /* Clear it */ | 188 | __FUNCTION__, legsup); |
175 | 189 | goto reset_needed; | |
176 | if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { | ||
177 | if (status & USBSTS_HSE) | ||
178 | dev_err(uhci_dev(uhci), "host system error, " | ||
179 | "PCI problems?\n"); | ||
180 | if (status & USBSTS_HCPE) | ||
181 | dev_err(uhci_dev(uhci), "host controller process " | ||
182 | "error, something bad happened!\n"); | ||
183 | if ((status & USBSTS_HCH) && uhci->state > 0) { | ||
184 | dev_err(uhci_dev(uhci), "host controller halted, " | ||
185 | "very bad!\n"); | ||
186 | /* FIXME: Reset the controller, fix the offending TD */ | ||
187 | } | ||
188 | } | 190 | } |
189 | 191 | ||
190 | if (status & USBSTS_RD) | 192 | cmd = inw(uhci->io_addr + USBCMD); |
191 | uhci->resume_detect = 1; | 193 | if ((cmd & USBCMD_RS) || !(cmd & USBCMD_CF) || !(cmd & USBCMD_EGSM)) { |
194 | dev_dbg(uhci_dev(uhci), "%s: cmd = 0x%04x\n", | ||
195 | __FUNCTION__, cmd); | ||
196 | goto reset_needed; | ||
197 | } | ||
192 | 198 | ||
193 | spin_lock(&uhci->lock); | 199 | intr = inw(uhci->io_addr + USBINTR); |
194 | uhci_scan_schedule(uhci, regs); | 200 | if (intr & (~USBINTR_RESUME)) { |
195 | spin_unlock(&uhci->lock); | 201 | dev_dbg(uhci_dev(uhci), "%s: intr = 0x%04x\n", |
202 | __FUNCTION__, intr); | ||
203 | goto reset_needed; | ||
204 | } | ||
205 | return; | ||
196 | 206 | ||
197 | return IRQ_HANDLED; | 207 | reset_needed: |
208 | dev_dbg(uhci_dev(uhci), "Performing full reset\n"); | ||
209 | reset_hc(uhci); | ||
198 | } | 210 | } |
199 | 211 | ||
200 | static void reset_hc(struct uhci_hcd *uhci) | 212 | /* |
213 | * Store the basic register settings needed by the controller. | ||
214 | */ | ||
215 | static void configure_hc(struct uhci_hcd *uhci) | ||
201 | { | 216 | { |
202 | unsigned long io_addr = uhci->io_addr; | 217 | /* Set the frame length to the default: 1 ms exactly */ |
218 | outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF); | ||
203 | 219 | ||
204 | /* Turn off PIRQ, SMI, and all interrupts. This also turns off | 220 | /* Store the frame list base address */ |
205 | * the BIOS's USB Legacy Support. | 221 | outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD); |
206 | */ | ||
207 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); | ||
208 | outw(0, uhci->io_addr + USBINTR); | ||
209 | 222 | ||
210 | /* Global reset for 50ms */ | 223 | /* Set the current frame number */ |
211 | uhci->state = UHCI_RESET; | 224 | outw(uhci->frame_number, uhci->io_addr + USBFRNUM); |
212 | outw(USBCMD_GRESET, io_addr + USBCMD); | ||
213 | msleep(50); | ||
214 | outw(0, io_addr + USBCMD); | ||
215 | 225 | ||
216 | /* Another 10ms delay */ | 226 | /* Mark controller as running before we enable interrupts */ |
217 | msleep(10); | 227 | uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; |
218 | uhci->resume_detect = 0; | 228 | mb(); |
219 | uhci->is_stopped = UHCI_IS_STOPPED; | 229 | |
230 | /* Enable PIRQ */ | ||
231 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, | ||
232 | USBLEGSUP_DEFAULT); | ||
220 | } | 233 | } |
221 | 234 | ||
222 | static void suspend_hc(struct uhci_hcd *uhci) | 235 | |
236 | static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci) | ||
223 | { | 237 | { |
224 | unsigned long io_addr = uhci->io_addr; | 238 | int port; |
225 | 239 | ||
226 | dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); | 240 | switch (to_pci_dev(uhci_dev(uhci))->vendor) { |
227 | uhci->state = UHCI_SUSPENDED; | 241 | default: |
228 | uhci->resume_detect = 0; | 242 | break; |
229 | outw(USBCMD_EGSM, io_addr + USBCMD); | ||
230 | 243 | ||
231 | /* FIXME: Wait for the controller to actually stop */ | 244 | case PCI_VENDOR_ID_GENESYS: |
232 | uhci_get_current_frame_number(uhci); | 245 | /* Genesys Logic's GL880S controllers don't generate |
233 | uhci->is_stopped = UHCI_IS_STOPPED; | 246 | * resume-detect interrupts. |
247 | */ | ||
248 | return 1; | ||
234 | 249 | ||
235 | uhci_scan_schedule(uhci, NULL); | 250 | case PCI_VENDOR_ID_INTEL: |
251 | /* Some of Intel's USB controllers have a bug that causes | ||
252 | * resume-detect interrupts if any port has an over-current | ||
253 | * condition. To make matters worse, some motherboards | ||
254 | * hardwire unused USB ports' over-current inputs active! | ||
255 | * To prevent problems, we will not enable resume-detect | ||
256 | * interrupts if any ports are OC. | ||
257 | */ | ||
258 | for (port = 0; port < uhci->rh_numports; ++port) { | ||
259 | if (inw(uhci->io_addr + USBPORTSC1 + port * 2) & | ||
260 | USBPORTSC_OC) | ||
261 | return 1; | ||
262 | } | ||
263 | break; | ||
264 | } | ||
265 | return 0; | ||
236 | } | 266 | } |
237 | 267 | ||
238 | static void wakeup_hc(struct uhci_hcd *uhci) | 268 | static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state) |
269 | __releases(uhci->lock) | ||
270 | __acquires(uhci->lock) | ||
239 | { | 271 | { |
240 | unsigned long io_addr = uhci->io_addr; | 272 | int auto_stop; |
273 | int int_enable; | ||
241 | 274 | ||
242 | switch (uhci->state) { | 275 | auto_stop = (new_state == UHCI_RH_AUTO_STOPPED); |
243 | case UHCI_SUSPENDED: /* Start the resume */ | 276 | dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__, |
244 | dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); | 277 | (auto_stop ? " (auto-stop)" : "")); |
245 | |||
246 | /* Global resume for >= 20ms */ | ||
247 | outw(USBCMD_FGR | USBCMD_EGSM, io_addr + USBCMD); | ||
248 | uhci->state = UHCI_RESUMING_1; | ||
249 | uhci->state_end = jiffies + msecs_to_jiffies(20); | ||
250 | uhci->is_stopped = 0; | ||
251 | break; | ||
252 | 278 | ||
253 | case UHCI_RESUMING_1: /* End global resume */ | 279 | /* If we get a suspend request when we're already auto-stopped |
254 | uhci->state = UHCI_RESUMING_2; | 280 | * then there's nothing to do. |
255 | outw(0, io_addr + USBCMD); | 281 | */ |
256 | /* Falls through */ | 282 | if (uhci->rh_state == UHCI_RH_AUTO_STOPPED) { |
257 | 283 | uhci->rh_state = new_state; | |
258 | case UHCI_RESUMING_2: /* Wait for EOP to be sent */ | 284 | return; |
259 | if (inw(io_addr + USBCMD) & USBCMD_FGR) | 285 | } |
260 | break; | ||
261 | |||
262 | /* Run for at least 1 second, and | ||
263 | * mark it configured with a 64-byte max packet */ | ||
264 | uhci->state = UHCI_RUNNING_GRACE; | ||
265 | uhci->state_end = jiffies + HZ; | ||
266 | outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, | ||
267 | io_addr + USBCMD); | ||
268 | break; | ||
269 | 286 | ||
270 | case UHCI_RUNNING_GRACE: /* Now allowed to suspend */ | 287 | /* Enable resume-detect interrupts if they work. |
271 | uhci->state = UHCI_RUNNING; | 288 | * Then enter Global Suspend mode, still configured. |
272 | break; | 289 | */ |
290 | int_enable = (resume_detect_interrupts_are_broken(uhci) ? | ||
291 | 0 : USBINTR_RESUME); | ||
292 | outw(int_enable, uhci->io_addr + USBINTR); | ||
293 | outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD); | ||
294 | mb(); | ||
295 | udelay(5); | ||
273 | 296 | ||
274 | default: | 297 | /* If we're auto-stopping then no devices have been attached |
275 | break; | 298 | * for a while, so there shouldn't be any active URBs and the |
299 | * controller should stop after a few microseconds. Otherwise | ||
300 | * we will give the controller one frame to stop. | ||
301 | */ | ||
302 | if (!auto_stop && !(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) { | ||
303 | uhci->rh_state = UHCI_RH_SUSPENDING; | ||
304 | spin_unlock_irq(&uhci->lock); | ||
305 | msleep(1); | ||
306 | spin_lock_irq(&uhci->lock); | ||
307 | if (uhci->hc_inaccessible) /* Died */ | ||
308 | return; | ||
276 | } | 309 | } |
277 | } | 310 | if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) |
311 | dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n"); | ||
278 | 312 | ||
279 | static int ports_active(struct uhci_hcd *uhci) | 313 | uhci_get_current_frame_number(uhci); |
280 | { | 314 | smp_wmb(); |
281 | unsigned long io_addr = uhci->io_addr; | ||
282 | int connection = 0; | ||
283 | int i; | ||
284 | 315 | ||
285 | for (i = 0; i < uhci->rh_numports; i++) | 316 | uhci->rh_state = new_state; |
286 | connection |= (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_CCS); | 317 | uhci->is_stopped = UHCI_IS_STOPPED; |
318 | del_timer(&uhci->stall_timer); | ||
319 | uhci_to_hcd(uhci)->poll_rh = !int_enable; | ||
287 | 320 | ||
288 | return connection; | 321 | uhci_scan_schedule(uhci, NULL); |
289 | } | 322 | } |
290 | 323 | ||
291 | static int suspend_allowed(struct uhci_hcd *uhci) | 324 | static void start_rh(struct uhci_hcd *uhci) |
292 | { | 325 | { |
293 | unsigned long io_addr = uhci->io_addr; | 326 | uhci->is_stopped = 0; |
294 | int i; | 327 | smp_wmb(); |
295 | |||
296 | if (to_pci_dev(uhci_dev(uhci))->vendor != PCI_VENDOR_ID_INTEL) | ||
297 | return 1; | ||
298 | 328 | ||
299 | /* Some of Intel's USB controllers have a bug that causes false | 329 | /* Mark it configured and running with a 64-byte max packet. |
300 | * resume indications if any port has an over current condition. | 330 | * All interrupts are enabled, even though RESUME won't do anything. |
301 | * To prevent problems, we will not allow a global suspend if | ||
302 | * any ports are OC. | ||
303 | * | ||
304 | * Some motherboards using Intel's chipsets (but not using all | ||
305 | * the USB ports) appear to hardwire the over current inputs active | ||
306 | * to disable the USB ports. | ||
307 | */ | 331 | */ |
308 | 332 | outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, uhci->io_addr + USBCMD); | |
309 | /* check for over current condition on any port */ | 333 | outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, |
310 | for (i = 0; i < uhci->rh_numports; i++) { | 334 | uhci->io_addr + USBINTR); |
311 | if (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_OC) | 335 | mb(); |
312 | return 0; | 336 | uhci->rh_state = UHCI_RH_RUNNING; |
313 | } | 337 | uhci_to_hcd(uhci)->poll_rh = 1; |
314 | 338 | restart_timer(uhci); | |
315 | return 1; | ||
316 | } | 339 | } |
317 | 340 | ||
318 | static void hc_state_transitions(struct uhci_hcd *uhci) | 341 | static void wakeup_rh(struct uhci_hcd *uhci) |
342 | __releases(uhci->lock) | ||
343 | __acquires(uhci->lock) | ||
319 | { | 344 | { |
320 | switch (uhci->state) { | 345 | dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__, |
321 | case UHCI_RUNNING: | 346 | uhci->rh_state == UHCI_RH_AUTO_STOPPED ? |
347 | " (auto-start)" : ""); | ||
322 | 348 | ||
323 | /* global suspend if nothing connected for 1 second */ | 349 | /* If we are auto-stopped then no devices are attached so there's |
324 | if (!ports_active(uhci) && suspend_allowed(uhci)) { | 350 | * no need for wakeup signals. Otherwise we send Global Resume |
325 | uhci->state = UHCI_SUSPENDING_GRACE; | 351 | * for 20 ms. |
326 | uhci->state_end = jiffies + HZ; | 352 | */ |
327 | } | 353 | if (uhci->rh_state == UHCI_RH_SUSPENDED) { |
328 | break; | 354 | uhci->rh_state = UHCI_RH_RESUMING; |
329 | 355 | outw(USBCMD_FGR | USBCMD_EGSM | USBCMD_CF, | |
330 | case UHCI_SUSPENDING_GRACE: | 356 | uhci->io_addr + USBCMD); |
331 | if (ports_active(uhci)) | 357 | spin_unlock_irq(&uhci->lock); |
332 | uhci->state = UHCI_RUNNING; | 358 | msleep(20); |
333 | else if (time_after_eq(jiffies, uhci->state_end)) | 359 | spin_lock_irq(&uhci->lock); |
334 | suspend_hc(uhci); | 360 | if (uhci->hc_inaccessible) /* Died */ |
335 | break; | 361 | return; |
336 | 362 | ||
337 | case UHCI_SUSPENDED: | 363 | /* End Global Resume and wait for EOP to be sent */ |
338 | 364 | outw(USBCMD_CF, uhci->io_addr + USBCMD); | |
339 | /* wakeup if requested by a device */ | 365 | mb(); |
340 | if (uhci->resume_detect) | 366 | udelay(4); |
341 | wakeup_hc(uhci); | 367 | if (inw(uhci->io_addr + USBCMD) & USBCMD_FGR) |
342 | break; | 368 | dev_warn(uhci_dev(uhci), "FGR not stopped yet!\n"); |
369 | } | ||
343 | 370 | ||
344 | case UHCI_RESUMING_1: | 371 | start_rh(uhci); |
345 | case UHCI_RESUMING_2: | ||
346 | case UHCI_RUNNING_GRACE: | ||
347 | if (time_after_eq(jiffies, uhci->state_end)) | ||
348 | wakeup_hc(uhci); | ||
349 | break; | ||
350 | 372 | ||
351 | default: | 373 | /* Restart root hub polling */ |
352 | break; | 374 | mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); |
353 | } | ||
354 | } | 375 | } |
355 | 376 | ||
356 | /* | 377 | static void stall_callback(unsigned long _uhci) |
357 | * Store the current frame number in uhci->frame_number if the controller | ||
358 | * is runnning | ||
359 | */ | ||
360 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci) | ||
361 | { | 378 | { |
379 | struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci; | ||
380 | unsigned long flags; | ||
381 | |||
382 | spin_lock_irqsave(&uhci->lock, flags); | ||
383 | uhci_scan_schedule(uhci, NULL); | ||
384 | check_fsbr(uhci); | ||
385 | |||
362 | if (!uhci->is_stopped) | 386 | if (!uhci->is_stopped) |
363 | uhci->frame_number = inw(uhci->io_addr + USBFRNUM); | 387 | restart_timer(uhci); |
388 | spin_unlock_irqrestore(&uhci->lock, flags); | ||
364 | } | 389 | } |
365 | 390 | ||
366 | static int start_hc(struct uhci_hcd *uhci) | 391 | static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) |
367 | { | 392 | { |
368 | unsigned long io_addr = uhci->io_addr; | 393 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
369 | int timeout = 10; | 394 | unsigned short status; |
395 | unsigned long flags; | ||
370 | 396 | ||
371 | /* | 397 | /* |
372 | * Reset the HC - this will force us to get a | 398 | * Read the interrupt status, and write it back to clear the |
373 | * new notification of any already connected | 399 | * interrupt cause. Contrary to the UHCI specification, the |
374 | * ports due to the virtual disconnect that it | 400 | * "HC Halted" status bit is persistent: it is RO, not R/WC. |
375 | * implies. | ||
376 | */ | 401 | */ |
377 | outw(USBCMD_HCRESET, io_addr + USBCMD); | 402 | status = inw(uhci->io_addr + USBSTS); |
378 | while (inw(io_addr + USBCMD) & USBCMD_HCRESET) { | 403 | if (!(status & ~USBSTS_HCH)) /* shared interrupt, not mine */ |
379 | if (--timeout < 0) { | 404 | return IRQ_NONE; |
380 | dev_err(uhci_dev(uhci), "USBCMD_HCRESET timed out!\n"); | 405 | outw(status, uhci->io_addr + USBSTS); /* Clear it */ |
381 | return -ETIMEDOUT; | 406 | |
407 | if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { | ||
408 | if (status & USBSTS_HSE) | ||
409 | dev_err(uhci_dev(uhci), "host system error, " | ||
410 | "PCI problems?\n"); | ||
411 | if (status & USBSTS_HCPE) | ||
412 | dev_err(uhci_dev(uhci), "host controller process " | ||
413 | "error, something bad happened!\n"); | ||
414 | if (status & USBSTS_HCH) { | ||
415 | spin_lock_irqsave(&uhci->lock, flags); | ||
416 | if (uhci->rh_state >= UHCI_RH_RUNNING) { | ||
417 | dev_err(uhci_dev(uhci), | ||
418 | "host controller halted, " | ||
419 | "very bad!\n"); | ||
420 | hc_died(uhci); | ||
421 | spin_unlock_irqrestore(&uhci->lock, flags); | ||
422 | return IRQ_HANDLED; | ||
423 | } | ||
424 | spin_unlock_irqrestore(&uhci->lock, flags); | ||
382 | } | 425 | } |
383 | msleep(1); | ||
384 | } | 426 | } |
385 | 427 | ||
386 | /* Mark controller as running before we enable interrupts */ | 428 | if (status & USBSTS_RD) |
387 | uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; | 429 | usb_hcd_poll_rh_status(hcd); |
388 | |||
389 | /* Turn on PIRQ and all interrupts */ | ||
390 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, | ||
391 | USBLEGSUP_DEFAULT); | ||
392 | outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, | ||
393 | io_addr + USBINTR); | ||
394 | 430 | ||
395 | /* Start at frame 0 */ | 431 | spin_lock_irqsave(&uhci->lock, flags); |
396 | outw(0, io_addr + USBFRNUM); | 432 | uhci_scan_schedule(uhci, regs); |
397 | outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD); | 433 | spin_unlock_irqrestore(&uhci->lock, flags); |
398 | 434 | ||
399 | /* Run and mark it configured with a 64-byte max packet */ | 435 | return IRQ_HANDLED; |
400 | uhci->state = UHCI_RUNNING_GRACE; | 436 | } |
401 | uhci->state_end = jiffies + HZ; | ||
402 | outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD); | ||
403 | uhci->is_stopped = 0; | ||
404 | 437 | ||
405 | return 0; | 438 | /* |
439 | * Store the current frame number in uhci->frame_number if the controller | ||
440 | * is runnning | ||
441 | */ | ||
442 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci) | ||
443 | { | ||
444 | if (!uhci->is_stopped) | ||
445 | uhci->frame_number = inw(uhci->io_addr + USBFRNUM); | ||
406 | } | 446 | } |
407 | 447 | ||
408 | /* | 448 | /* |
@@ -448,16 +488,58 @@ static void release_uhci(struct uhci_hcd *uhci) | |||
448 | static int uhci_reset(struct usb_hcd *hcd) | 488 | static int uhci_reset(struct usb_hcd *hcd) |
449 | { | 489 | { |
450 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 490 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
491 | unsigned io_size = (unsigned) hcd->rsrc_len; | ||
492 | int port; | ||
451 | 493 | ||
452 | uhci->io_addr = (unsigned long) hcd->rsrc_start; | 494 | uhci->io_addr = (unsigned long) hcd->rsrc_start; |
453 | 495 | ||
454 | /* Kick BIOS off this hardware and reset, so we won't get | 496 | /* The UHCI spec says devices must have 2 ports, and goes on to say |
455 | * interrupts from any previous setup. | 497 | * they may have more but gives no way to determine how many there |
498 | * are. However according to the UHCI spec, Bit 7 of the port | ||
499 | * status and control register is always set to 1. So we try to | ||
500 | * use this to our advantage. Another common failure mode when | ||
501 | * a nonexistent register is addressed is to return all ones, so | ||
502 | * we test for that also. | ||
456 | */ | 503 | */ |
457 | reset_hc(uhci); | 504 | for (port = 0; port < (io_size - USBPORTSC1) / 2; port++) { |
505 | unsigned int portstatus; | ||
506 | |||
507 | portstatus = inw(uhci->io_addr + USBPORTSC1 + (port * 2)); | ||
508 | if (!(portstatus & 0x0080) || portstatus == 0xffff) | ||
509 | break; | ||
510 | } | ||
511 | if (debug) | ||
512 | dev_info(uhci_dev(uhci), "detected %d ports\n", port); | ||
513 | |||
514 | /* Anything greater than 7 is weird so we'll ignore it. */ | ||
515 | if (port > UHCI_RH_MAXCHILD) { | ||
516 | dev_info(uhci_dev(uhci), "port count misdetected? " | ||
517 | "forcing to 2 ports\n"); | ||
518 | port = 2; | ||
519 | } | ||
520 | uhci->rh_numports = port; | ||
521 | |||
522 | /* Kick BIOS off this hardware and reset if the controller | ||
523 | * isn't already safely quiescent. | ||
524 | */ | ||
525 | check_and_reset_hc(uhci); | ||
458 | return 0; | 526 | return 0; |
459 | } | 527 | } |
460 | 528 | ||
529 | /* Make sure the controller is quiescent and that we're not using it | ||
530 | * any more. This is mainly for the benefit of programs which, like kexec, | ||
531 | * expect the hardware to be idle: not doing DMA or generating IRQs. | ||
532 | * | ||
533 | * This routine may be called in a damaged or failing kernel. Hence we | ||
534 | * do not acquire the spinlock before shutting down the controller. | ||
535 | */ | ||
536 | static void uhci_shutdown(struct pci_dev *pdev) | ||
537 | { | ||
538 | struct usb_hcd *hcd = (struct usb_hcd *) pci_get_drvdata(pdev); | ||
539 | |||
540 | hc_died(hcd_to_uhci(hcd)); | ||
541 | } | ||
542 | |||
461 | /* | 543 | /* |
462 | * Allocate a frame list, and then setup the skeleton | 544 | * Allocate a frame list, and then setup the skeleton |
463 | * | 545 | * |
@@ -478,17 +560,20 @@ static int uhci_start(struct usb_hcd *hcd) | |||
478 | { | 560 | { |
479 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 561 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
480 | int retval = -EBUSY; | 562 | int retval = -EBUSY; |
481 | int i, port; | 563 | int i; |
482 | unsigned io_size; | ||
483 | dma_addr_t dma_handle; | 564 | dma_addr_t dma_handle; |
484 | struct usb_device *udev; | ||
485 | struct dentry *dentry; | 565 | struct dentry *dentry; |
486 | 566 | ||
487 | io_size = (unsigned) hcd->rsrc_len; | 567 | hcd->uses_new_polling = 1; |
568 | if (pci_find_capability(to_pci_dev(uhci_dev(uhci)), PCI_CAP_ID_PM)) | ||
569 | hcd->can_wakeup = 1; /* Assume it supports PME# */ | ||
488 | 570 | ||
489 | dentry = debugfs_create_file(hcd->self.bus_name, S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci, &uhci_debug_operations); | 571 | dentry = debugfs_create_file(hcd->self.bus_name, |
572 | S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci, | ||
573 | &uhci_debug_operations); | ||
490 | if (!dentry) { | 574 | if (!dentry) { |
491 | dev_err(uhci_dev(uhci), "couldn't create uhci debugfs entry\n"); | 575 | dev_err(uhci_dev(uhci), |
576 | "couldn't create uhci debugfs entry\n"); | ||
492 | retval = -ENOMEM; | 577 | retval = -ENOMEM; |
493 | goto err_create_debug_entry; | 578 | goto err_create_debug_entry; |
494 | } | 579 | } |
@@ -510,6 +595,10 @@ static int uhci_start(struct usb_hcd *hcd) | |||
510 | 595 | ||
511 | init_waitqueue_head(&uhci->waitqh); | 596 | init_waitqueue_head(&uhci->waitqh); |
512 | 597 | ||
598 | init_timer(&uhci->stall_timer); | ||
599 | uhci->stall_timer.function = stall_callback; | ||
600 | uhci->stall_timer.data = (unsigned long) uhci; | ||
601 | |||
513 | uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), | 602 | uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), |
514 | &dma_handle, 0); | 603 | &dma_handle, 0); |
515 | if (!uhci->fl) { | 604 | if (!uhci->fl) { |
@@ -536,46 +625,14 @@ static int uhci_start(struct usb_hcd *hcd) | |||
536 | goto err_create_qh_pool; | 625 | goto err_create_qh_pool; |
537 | } | 626 | } |
538 | 627 | ||
539 | /* Initialize the root hub */ | 628 | uhci->term_td = uhci_alloc_td(uhci); |
540 | |||
541 | /* UHCI specs says devices must have 2 ports, but goes on to say */ | ||
542 | /* they may have more but give no way to determine how many they */ | ||
543 | /* have. However, according to the UHCI spec, Bit 7 is always set */ | ||
544 | /* to 1. So we try to use this to our advantage */ | ||
545 | for (port = 0; port < (io_size - 0x10) / 2; port++) { | ||
546 | unsigned int portstatus; | ||
547 | |||
548 | portstatus = inw(uhci->io_addr + 0x10 + (port * 2)); | ||
549 | if (!(portstatus & 0x0080)) | ||
550 | break; | ||
551 | } | ||
552 | if (debug) | ||
553 | dev_info(uhci_dev(uhci), "detected %d ports\n", port); | ||
554 | |||
555 | /* This is experimental so anything less than 2 or greater than 8 is */ | ||
556 | /* something weird and we'll ignore it */ | ||
557 | if (port < 2 || port > UHCI_RH_MAXCHILD) { | ||
558 | dev_info(uhci_dev(uhci), "port count misdetected? " | ||
559 | "forcing to 2 ports\n"); | ||
560 | port = 2; | ||
561 | } | ||
562 | |||
563 | uhci->rh_numports = port; | ||
564 | |||
565 | udev = usb_alloc_dev(NULL, &hcd->self, 0); | ||
566 | if (!udev) { | ||
567 | dev_err(uhci_dev(uhci), "unable to allocate root hub\n"); | ||
568 | goto err_alloc_root_hub; | ||
569 | } | ||
570 | |||
571 | uhci->term_td = uhci_alloc_td(uhci, udev); | ||
572 | if (!uhci->term_td) { | 629 | if (!uhci->term_td) { |
573 | dev_err(uhci_dev(uhci), "unable to allocate terminating TD\n"); | 630 | dev_err(uhci_dev(uhci), "unable to allocate terminating TD\n"); |
574 | goto err_alloc_term_td; | 631 | goto err_alloc_term_td; |
575 | } | 632 | } |
576 | 633 | ||
577 | for (i = 0; i < UHCI_NUM_SKELQH; i++) { | 634 | for (i = 0; i < UHCI_NUM_SKELQH; i++) { |
578 | uhci->skelqh[i] = uhci_alloc_qh(uhci, udev); | 635 | uhci->skelqh[i] = uhci_alloc_qh(uhci); |
579 | if (!uhci->skelqh[i]) { | 636 | if (!uhci->skelqh[i]) { |
580 | dev_err(uhci_dev(uhci), "unable to allocate QH\n"); | 637 | dev_err(uhci_dev(uhci), "unable to allocate QH\n"); |
581 | goto err_alloc_skelqh; | 638 | goto err_alloc_skelqh; |
@@ -641,32 +698,17 @@ static int uhci_start(struct usb_hcd *hcd) | |||
641 | 698 | ||
642 | /* | 699 | /* |
643 | * Some architectures require a full mb() to enforce completion of | 700 | * Some architectures require a full mb() to enforce completion of |
644 | * the memory writes above before the I/O transfers in start_hc(). | 701 | * the memory writes above before the I/O transfers in configure_hc(). |
645 | */ | 702 | */ |
646 | mb(); | 703 | mb(); |
647 | if ((retval = start_hc(uhci)) != 0) | ||
648 | goto err_alloc_skelqh; | ||
649 | |||
650 | init_stall_timer(hcd); | ||
651 | |||
652 | udev->speed = USB_SPEED_FULL; | ||
653 | |||
654 | if (usb_hcd_register_root_hub(udev, hcd) != 0) { | ||
655 | dev_err(uhci_dev(uhci), "unable to start root hub\n"); | ||
656 | retval = -ENOMEM; | ||
657 | goto err_start_root_hub; | ||
658 | } | ||
659 | 704 | ||
705 | configure_hc(uhci); | ||
706 | start_rh(uhci); | ||
660 | return 0; | 707 | return 0; |
661 | 708 | ||
662 | /* | 709 | /* |
663 | * error exits: | 710 | * error exits: |
664 | */ | 711 | */ |
665 | err_start_root_hub: | ||
666 | reset_hc(uhci); | ||
667 | |||
668 | del_timer_sync(&uhci->stall_timer); | ||
669 | |||
670 | err_alloc_skelqh: | 712 | err_alloc_skelqh: |
671 | for (i = 0; i < UHCI_NUM_SKELQH; i++) | 713 | for (i = 0; i < UHCI_NUM_SKELQH; i++) |
672 | if (uhci->skelqh[i]) { | 714 | if (uhci->skelqh[i]) { |
@@ -678,9 +720,6 @@ err_alloc_skelqh: | |||
678 | uhci->term_td = NULL; | 720 | uhci->term_td = NULL; |
679 | 721 | ||
680 | err_alloc_term_td: | 722 | err_alloc_term_td: |
681 | usb_put_dev(udev); | ||
682 | |||
683 | err_alloc_root_hub: | ||
684 | dma_pool_destroy(uhci->qh_pool); | 723 | dma_pool_destroy(uhci->qh_pool); |
685 | uhci->qh_pool = NULL; | 724 | uhci->qh_pool = NULL; |
686 | 725 | ||
@@ -705,73 +744,114 @@ static void uhci_stop(struct usb_hcd *hcd) | |||
705 | { | 744 | { |
706 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 745 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
707 | 746 | ||
708 | del_timer_sync(&uhci->stall_timer); | ||
709 | reset_hc(uhci); | ||
710 | |||
711 | spin_lock_irq(&uhci->lock); | 747 | spin_lock_irq(&uhci->lock); |
748 | reset_hc(uhci); | ||
712 | uhci_scan_schedule(uhci, NULL); | 749 | uhci_scan_schedule(uhci, NULL); |
713 | spin_unlock_irq(&uhci->lock); | 750 | spin_unlock_irq(&uhci->lock); |
714 | 751 | ||
752 | del_timer_sync(&uhci->stall_timer); | ||
715 | release_uhci(uhci); | 753 | release_uhci(uhci); |
716 | } | 754 | } |
717 | 755 | ||
718 | #ifdef CONFIG_PM | 756 | #ifdef CONFIG_PM |
757 | static int uhci_rh_suspend(struct usb_hcd *hcd) | ||
758 | { | ||
759 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | ||
760 | |||
761 | spin_lock_irq(&uhci->lock); | ||
762 | if (!uhci->hc_inaccessible) /* Not dead */ | ||
763 | suspend_rh(uhci, UHCI_RH_SUSPENDED); | ||
764 | spin_unlock_irq(&uhci->lock); | ||
765 | return 0; | ||
766 | } | ||
767 | |||
768 | static int uhci_rh_resume(struct usb_hcd *hcd) | ||
769 | { | ||
770 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | ||
771 | int rc = 0; | ||
772 | |||
773 | spin_lock_irq(&uhci->lock); | ||
774 | if (uhci->hc_inaccessible) { | ||
775 | if (uhci->rh_state == UHCI_RH_SUSPENDED) { | ||
776 | dev_warn(uhci_dev(uhci), "HC isn't running!\n"); | ||
777 | rc = -ENODEV; | ||
778 | } | ||
779 | /* Otherwise the HC is dead */ | ||
780 | } else | ||
781 | wakeup_rh(uhci); | ||
782 | spin_unlock_irq(&uhci->lock); | ||
783 | return rc; | ||
784 | } | ||
785 | |||
719 | static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) | 786 | static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) |
720 | { | 787 | { |
721 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 788 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
789 | int rc = 0; | ||
790 | |||
791 | dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); | ||
722 | 792 | ||
723 | spin_lock_irq(&uhci->lock); | 793 | spin_lock_irq(&uhci->lock); |
794 | if (uhci->hc_inaccessible) /* Dead or already suspended */ | ||
795 | goto done; | ||
724 | 796 | ||
725 | /* Don't try to suspend broken motherboards, reset instead */ | 797 | #ifndef CONFIG_USB_SUSPEND |
726 | if (suspend_allowed(uhci)) | 798 | /* Otherwise this would never happen */ |
727 | suspend_hc(uhci); | 799 | suspend_rh(uhci, UHCI_RH_SUSPENDED); |
728 | else { | 800 | #endif |
729 | spin_unlock_irq(&uhci->lock); | 801 | |
730 | reset_hc(uhci); | 802 | if (uhci->rh_state > UHCI_RH_SUSPENDED) { |
731 | spin_lock_irq(&uhci->lock); | 803 | dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n"); |
732 | uhci_scan_schedule(uhci, NULL); | 804 | hcd->state = HC_STATE_RUNNING; |
733 | } | 805 | rc = -EBUSY; |
806 | goto done; | ||
807 | }; | ||
734 | 808 | ||
809 | /* All PCI host controllers are required to disable IRQ generation | ||
810 | * at the source, so we must turn off PIRQ. | ||
811 | */ | ||
812 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); | ||
813 | uhci->hc_inaccessible = 1; | ||
814 | |||
815 | /* FIXME: Enable non-PME# remote wakeup? */ | ||
816 | |||
817 | done: | ||
735 | spin_unlock_irq(&uhci->lock); | 818 | spin_unlock_irq(&uhci->lock); |
736 | return 0; | 819 | if (rc == 0) |
820 | del_timer_sync(&hcd->rh_timer); | ||
821 | return rc; | ||
737 | } | 822 | } |
738 | 823 | ||
739 | static int uhci_resume(struct usb_hcd *hcd) | 824 | static int uhci_resume(struct usb_hcd *hcd) |
740 | { | 825 | { |
741 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 826 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
742 | int rc; | ||
743 | 827 | ||
744 | pci_set_master(to_pci_dev(uhci_dev(uhci))); | 828 | dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); |
745 | 829 | ||
830 | if (uhci->rh_state == UHCI_RH_RESET) /* Dead */ | ||
831 | return 0; | ||
746 | spin_lock_irq(&uhci->lock); | 832 | spin_lock_irq(&uhci->lock); |
747 | 833 | ||
748 | if (uhci->state == UHCI_SUSPENDED) { | 834 | /* FIXME: Disable non-PME# remote wakeup? */ |
749 | 835 | ||
750 | /* | 836 | uhci->hc_inaccessible = 0; |
751 | * Some systems don't maintain the UHCI register values | 837 | |
752 | * during a PM suspend/resume cycle, so reinitialize | 838 | /* The BIOS may have changed the controller settings during a |
753 | * the Frame Number, Framelist Base Address, Interrupt | 839 | * system wakeup. Check it and reconfigure to avoid problems. |
754 | * Enable, and Legacy Support registers. | 840 | */ |
755 | */ | 841 | check_and_reset_hc(uhci); |
756 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, | 842 | configure_hc(uhci); |
757 | 0); | 843 | |
758 | outw(uhci->frame_number, uhci->io_addr + USBFRNUM); | 844 | #ifndef CONFIG_USB_SUSPEND |
759 | outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD); | 845 | /* Otherwise this would never happen */ |
760 | outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | | 846 | wakeup_rh(uhci); |
761 | USBINTR_SP, uhci->io_addr + USBINTR); | 847 | #endif |
762 | uhci->resume_detect = 1; | 848 | if (uhci->rh_state == UHCI_RH_RESET) |
763 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, | 849 | suspend_rh(uhci, UHCI_RH_SUSPENDED); |
764 | USBLEGSUP_DEFAULT); | ||
765 | } else { | ||
766 | spin_unlock_irq(&uhci->lock); | ||
767 | reset_hc(uhci); | ||
768 | if ((rc = start_hc(uhci)) != 0) | ||
769 | return rc; | ||
770 | spin_lock_irq(&uhci->lock); | ||
771 | } | ||
772 | hcd->state = HC_STATE_RUNNING; | ||
773 | 850 | ||
774 | spin_unlock_irq(&uhci->lock); | 851 | spin_unlock_irq(&uhci->lock); |
852 | |||
853 | if (hcd->poll_rh) | ||
854 | usb_hcd_poll_rh_status(hcd); | ||
775 | return 0; | 855 | return 0; |
776 | } | 856 | } |
777 | #endif | 857 | #endif |
@@ -788,13 +868,15 @@ static void uhci_hcd_endpoint_disable(struct usb_hcd *hcd, | |||
788 | static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) | 868 | static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) |
789 | { | 869 | { |
790 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 870 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
791 | int frame_number; | ||
792 | unsigned long flags; | 871 | unsigned long flags; |
872 | int is_stopped; | ||
873 | int frame_number; | ||
793 | 874 | ||
794 | /* Minimize latency by avoiding the spinlock */ | 875 | /* Minimize latency by avoiding the spinlock */ |
795 | local_irq_save(flags); | 876 | local_irq_save(flags); |
796 | rmb(); | 877 | is_stopped = uhci->is_stopped; |
797 | frame_number = (uhci->is_stopped ? uhci->frame_number : | 878 | smp_rmb(); |
879 | frame_number = (is_stopped ? uhci->frame_number : | ||
798 | inw(uhci->io_addr + USBFRNUM)); | 880 | inw(uhci->io_addr + USBFRNUM)); |
799 | local_irq_restore(flags); | 881 | local_irq_restore(flags); |
800 | return frame_number; | 882 | return frame_number; |
@@ -817,6 +899,8 @@ static const struct hc_driver uhci_driver = { | |||
817 | #ifdef CONFIG_PM | 899 | #ifdef CONFIG_PM |
818 | .suspend = uhci_suspend, | 900 | .suspend = uhci_suspend, |
819 | .resume = uhci_resume, | 901 | .resume = uhci_resume, |
902 | .hub_suspend = uhci_rh_suspend, | ||
903 | .hub_resume = uhci_rh_resume, | ||
820 | #endif | 904 | #endif |
821 | .stop = uhci_stop, | 905 | .stop = uhci_stop, |
822 | 906 | ||
@@ -845,6 +929,7 @@ static struct pci_driver uhci_pci_driver = { | |||
845 | 929 | ||
846 | .probe = usb_hcd_pci_probe, | 930 | .probe = usb_hcd_pci_probe, |
847 | .remove = usb_hcd_pci_remove, | 931 | .remove = usb_hcd_pci_remove, |
932 | .shutdown = uhci_shutdown, | ||
848 | 933 | ||
849 | #ifdef CONFIG_PM | 934 | #ifdef CONFIG_PM |
850 | .suspend = usb_hcd_pci_suspend, | 935 | .suspend = usb_hcd_pci_suspend, |
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 02255d69e1fe..bf9c5f9b508b 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h | |||
@@ -41,6 +41,7 @@ | |||
41 | #define USBFRNUM 6 | 41 | #define USBFRNUM 6 |
42 | #define USBFLBASEADD 8 | 42 | #define USBFLBASEADD 8 |
43 | #define USBSOF 12 | 43 | #define USBSOF 12 |
44 | #define USBSOF_DEFAULT 64 /* Frame length is exactly 1 ms */ | ||
44 | 45 | ||
45 | /* USB port status and control registers */ | 46 | /* USB port status and control registers */ |
46 | #define USBPORTSC1 16 | 47 | #define USBPORTSC1 16 |
@@ -66,6 +67,8 @@ | |||
66 | /* Legacy support register */ | 67 | /* Legacy support register */ |
67 | #define USBLEGSUP 0xc0 | 68 | #define USBLEGSUP 0xc0 |
68 | #define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ | 69 | #define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ |
70 | #define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ | ||
71 | #define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ | ||
69 | 72 | ||
70 | #define UHCI_NULL_DATA_SIZE 0x7FF /* for UHCI controller TD */ | 73 | #define UHCI_NULL_DATA_SIZE 0x7FF /* for UHCI controller TD */ |
71 | 74 | ||
@@ -111,7 +114,6 @@ struct uhci_qh { | |||
111 | /* Software fields */ | 114 | /* Software fields */ |
112 | dma_addr_t dma_handle; | 115 | dma_addr_t dma_handle; |
113 | 116 | ||
114 | struct usb_device *dev; | ||
115 | struct urb_priv *urbp; | 117 | struct urb_priv *urbp; |
116 | 118 | ||
117 | struct list_head list; /* P: uhci->frame_list_lock */ | 119 | struct list_head list; /* P: uhci->frame_list_lock */ |
@@ -203,7 +205,6 @@ struct uhci_td { | |||
203 | /* Software fields */ | 205 | /* Software fields */ |
204 | dma_addr_t dma_handle; | 206 | dma_addr_t dma_handle; |
205 | 207 | ||
206 | struct usb_device *dev; | ||
207 | struct urb *urb; | 208 | struct urb *urb; |
208 | 209 | ||
209 | struct list_head list; /* P: urb->lock */ | 210 | struct list_head list; /* P: urb->lock */ |
@@ -314,26 +315,32 @@ static inline int __interval_to_skel(int interval) | |||
314 | } | 315 | } |
315 | 316 | ||
316 | /* | 317 | /* |
317 | * Device states for the host controller. | 318 | * States for the root hub. |
318 | * | 319 | * |
319 | * To prevent "bouncing" in the presence of electrical noise, | 320 | * To prevent "bouncing" in the presence of electrical noise, |
320 | * we insist on a 1-second "grace" period, before switching to | 321 | * when there are no devices attached we delay for 1 second in the |
321 | * the RUNNING or SUSPENDED states, during which the state is | 322 | * RUNNING_NODEVS state before switching to the AUTO_STOPPED state. |
322 | * not allowed to change. | 323 | * |
323 | * | 324 | * (Note that the AUTO_STOPPED state won't be necessary once the hub |
324 | * The resume process is divided into substates in order to avoid | 325 | * driver learns to autosuspend.) |
325 | * potentially length delays during the timer handler. | ||
326 | * | ||
327 | * States in which the host controller is halted must have values <= 0. | ||
328 | */ | 326 | */ |
329 | enum uhci_state { | 327 | enum uhci_rh_state { |
330 | UHCI_RESET, | 328 | /* In the following states the HC must be halted. |
331 | UHCI_RUNNING_GRACE, /* Before RUNNING */ | 329 | * These two must come first */ |
332 | UHCI_RUNNING, /* The normal state */ | 330 | UHCI_RH_RESET, |
333 | UHCI_SUSPENDING_GRACE, /* Before SUSPENDED */ | 331 | UHCI_RH_SUSPENDED, |
334 | UHCI_SUSPENDED = -10, /* When no devices are attached */ | 332 | |
335 | UHCI_RESUMING_1, | 333 | UHCI_RH_AUTO_STOPPED, |
336 | UHCI_RESUMING_2 | 334 | UHCI_RH_RESUMING, |
335 | |||
336 | /* In this state the HC changes from running to halted, | ||
337 | * so it can legally appear either way. */ | ||
338 | UHCI_RH_SUSPENDING, | ||
339 | |||
340 | /* In the following states it's an error if the HC is halted. | ||
341 | * These two must come last */ | ||
342 | UHCI_RH_RUNNING, /* The normal state */ | ||
343 | UHCI_RH_RUNNING_NODEVS, /* Running with no devices attached */ | ||
337 | }; | 344 | }; |
338 | 345 | ||
339 | /* | 346 | /* |
@@ -363,15 +370,16 @@ struct uhci_hcd { | |||
363 | int fsbr; /* Full-speed bandwidth reclamation */ | 370 | int fsbr; /* Full-speed bandwidth reclamation */ |
364 | unsigned long fsbrtimeout; /* FSBR delay */ | 371 | unsigned long fsbrtimeout; /* FSBR delay */ |
365 | 372 | ||
366 | enum uhci_state state; /* FIXME: needs a spinlock */ | 373 | enum uhci_rh_state rh_state; |
367 | unsigned long state_end; /* Time of next transition */ | 374 | unsigned long auto_stop_time; /* When to AUTO_STOP */ |
375 | |||
368 | unsigned int frame_number; /* As of last check */ | 376 | unsigned int frame_number; /* As of last check */ |
369 | unsigned int is_stopped; | 377 | unsigned int is_stopped; |
370 | #define UHCI_IS_STOPPED 9999 /* Larger than a frame # */ | 378 | #define UHCI_IS_STOPPED 9999 /* Larger than a frame # */ |
371 | 379 | ||
372 | unsigned int scan_in_progress:1; /* Schedule scan is running */ | 380 | unsigned int scan_in_progress:1; /* Schedule scan is running */ |
373 | unsigned int need_rescan:1; /* Redo the schedule scan */ | 381 | unsigned int need_rescan:1; /* Redo the schedule scan */ |
374 | unsigned int resume_detect:1; /* Need a Global Resume */ | 382 | unsigned int hc_inaccessible:1; /* HC is suspended or dead */ |
375 | 383 | ||
376 | /* Support for port suspend/resume/reset */ | 384 | /* Support for port suspend/resume/reset */ |
377 | unsigned long port_c_suspend; /* Bit-arrays of ports */ | 385 | unsigned long port_c_suspend; /* Bit-arrays of ports */ |
@@ -451,4 +459,11 @@ struct urb_priv { | |||
451 | * #2 urb->lock | 459 | * #2 urb->lock |
452 | */ | 460 | */ |
453 | 461 | ||
462 | |||
463 | /* Some special IDs */ | ||
464 | |||
465 | #define PCI_VENDOR_ID_GENESYS 0x17a0 | ||
466 | #define PCI_DEVICE_ID_GL880S_UHCI 0x8083 | ||
467 | #define PCI_DEVICE_ID_GL880S_EHCI 0x8084 | ||
468 | |||
454 | #endif | 469 | #endif |
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 4c45ba8390f8..4eace2b19ddb 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c | |||
@@ -33,9 +33,24 @@ static __u8 root_hub_hub_des[] = | |||
33 | /* status change bits: nonzero writes will clear */ | 33 | /* status change bits: nonzero writes will clear */ |
34 | #define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC) | 34 | #define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC) |
35 | 35 | ||
36 | static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) | 36 | /* A port that either is connected or has a changed-bit set will prevent |
37 | * us from AUTO_STOPPING. | ||
38 | */ | ||
39 | static int any_ports_active(struct uhci_hcd *uhci) | ||
40 | { | ||
41 | int port; | ||
42 | |||
43 | for (port = 0; port < uhci->rh_numports; ++port) { | ||
44 | if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & | ||
45 | (USBPORTSC_CCS | RWC_BITS)) || | ||
46 | test_bit(port, &uhci->port_c_suspend)) | ||
47 | return 1; | ||
48 | } | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf) | ||
37 | { | 53 | { |
38 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | ||
39 | int port; | 54 | int port; |
40 | 55 | ||
41 | *buf = 0; | 56 | *buf = 0; |
@@ -44,8 +59,6 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
44 | test_bit(port, &uhci->port_c_suspend)) | 59 | test_bit(port, &uhci->port_c_suspend)) |
45 | *buf |= (1 << (port + 1)); | 60 | *buf |= (1 << (port + 1)); |
46 | } | 61 | } |
47 | if (*buf && uhci->state == UHCI_SUSPENDED) | ||
48 | uhci->resume_detect = 1; | ||
49 | return !!*buf; | 62 | return !!*buf; |
50 | } | 63 | } |
51 | 64 | ||
@@ -115,6 +128,11 @@ static void uhci_check_ports(struct uhci_hcd *uhci) | |||
115 | set_bit(port, &uhci->resuming_ports); | 128 | set_bit(port, &uhci->resuming_ports); |
116 | uhci->ports_timeout = jiffies + | 129 | uhci->ports_timeout = jiffies + |
117 | msecs_to_jiffies(20); | 130 | msecs_to_jiffies(20); |
131 | |||
132 | /* Make sure we see the port again | ||
133 | * after the resuming period is over. */ | ||
134 | mod_timer(&uhci_to_hcd(uhci)->rh_timer, | ||
135 | uhci->ports_timeout); | ||
118 | } else if (time_after_eq(jiffies, | 136 | } else if (time_after_eq(jiffies, |
119 | uhci->ports_timeout)) { | 137 | uhci->ports_timeout)) { |
120 | uhci_finish_suspend(uhci, port, port_addr); | 138 | uhci_finish_suspend(uhci, port, port_addr); |
@@ -123,6 +141,60 @@ static void uhci_check_ports(struct uhci_hcd *uhci) | |||
123 | } | 141 | } |
124 | } | 142 | } |
125 | 143 | ||
144 | static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) | ||
145 | { | ||
146 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | ||
147 | unsigned long flags; | ||
148 | int status; | ||
149 | |||
150 | spin_lock_irqsave(&uhci->lock, flags); | ||
151 | if (uhci->hc_inaccessible) { | ||
152 | status = 0; | ||
153 | goto done; | ||
154 | } | ||
155 | |||
156 | uhci_check_ports(uhci); | ||
157 | status = get_hub_status_data(uhci, buf); | ||
158 | |||
159 | switch (uhci->rh_state) { | ||
160 | case UHCI_RH_SUSPENDING: | ||
161 | case UHCI_RH_SUSPENDED: | ||
162 | /* if port change, ask to be resumed */ | ||
163 | if (status) | ||
164 | usb_hcd_resume_root_hub(hcd); | ||
165 | break; | ||
166 | |||
167 | case UHCI_RH_AUTO_STOPPED: | ||
168 | /* if port change, auto start */ | ||
169 | if (status) | ||
170 | wakeup_rh(uhci); | ||
171 | break; | ||
172 | |||
173 | case UHCI_RH_RUNNING: | ||
174 | /* are any devices attached? */ | ||
175 | if (!any_ports_active(uhci)) { | ||
176 | uhci->rh_state = UHCI_RH_RUNNING_NODEVS; | ||
177 | uhci->auto_stop_time = jiffies + HZ; | ||
178 | } | ||
179 | break; | ||
180 | |||
181 | case UHCI_RH_RUNNING_NODEVS: | ||
182 | /* auto-stop if nothing connected for 1 second */ | ||
183 | if (any_ports_active(uhci)) | ||
184 | uhci->rh_state = UHCI_RH_RUNNING; | ||
185 | else if (time_after_eq(jiffies, uhci->auto_stop_time)) | ||
186 | suspend_rh(uhci, UHCI_RH_AUTO_STOPPED); | ||
187 | break; | ||
188 | |||
189 | default: | ||
190 | break; | ||
191 | } | ||
192 | |||
193 | done: | ||
194 | spin_unlock_irqrestore(&uhci->lock, flags); | ||
195 | return status; | ||
196 | } | ||
197 | |||
126 | /* size of returned buffer is part of USB spec */ | 198 | /* size of returned buffer is part of USB spec */ |
127 | static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | 199 | static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, |
128 | u16 wIndex, char *buf, u16 wLength) | 200 | u16 wIndex, char *buf, u16 wLength) |
@@ -134,6 +206,9 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
134 | u16 wPortChange, wPortStatus; | 206 | u16 wPortChange, wPortStatus; |
135 | unsigned long flags; | 207 | unsigned long flags; |
136 | 208 | ||
209 | if (uhci->hc_inaccessible) | ||
210 | return -ETIMEDOUT; | ||
211 | |||
137 | spin_lock_irqsave(&uhci->lock, flags); | 212 | spin_lock_irqsave(&uhci->lock, flags); |
138 | switch (typeReq) { | 213 | switch (typeReq) { |
139 | 214 | ||
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 2a7c19501f24..5f18084a116d 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
@@ -32,6 +32,8 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci); | |||
32 | */ | 32 | */ |
33 | static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci) | 33 | static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci) |
34 | { | 34 | { |
35 | if (uhci->is_stopped) | ||
36 | mod_timer(&uhci->stall_timer, jiffies); | ||
35 | uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); | 37 | uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); |
36 | } | 38 | } |
37 | 39 | ||
@@ -46,7 +48,7 @@ static inline void uhci_moveto_complete(struct uhci_hcd *uhci, | |||
46 | list_move_tail(&urbp->urb_list, &uhci->complete_list); | 48 | list_move_tail(&urbp->urb_list, &uhci->complete_list); |
47 | } | 49 | } |
48 | 50 | ||
49 | static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct usb_device *dev) | 51 | static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci) |
50 | { | 52 | { |
51 | dma_addr_t dma_handle; | 53 | dma_addr_t dma_handle; |
52 | struct uhci_td *td; | 54 | struct uhci_td *td; |
@@ -61,14 +63,11 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct usb_device *d | |||
61 | td->buffer = 0; | 63 | td->buffer = 0; |
62 | 64 | ||
63 | td->frame = -1; | 65 | td->frame = -1; |
64 | td->dev = dev; | ||
65 | 66 | ||
66 | INIT_LIST_HEAD(&td->list); | 67 | INIT_LIST_HEAD(&td->list); |
67 | INIT_LIST_HEAD(&td->remove_list); | 68 | INIT_LIST_HEAD(&td->remove_list); |
68 | INIT_LIST_HEAD(&td->fl_list); | 69 | INIT_LIST_HEAD(&td->fl_list); |
69 | 70 | ||
70 | usb_get_dev(dev); | ||
71 | |||
72 | return td; | 71 | return td; |
73 | } | 72 | } |
74 | 73 | ||
@@ -168,13 +167,10 @@ static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td) | |||
168 | if (!list_empty(&td->fl_list)) | 167 | if (!list_empty(&td->fl_list)) |
169 | dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td); | 168 | dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td); |
170 | 169 | ||
171 | if (td->dev) | ||
172 | usb_put_dev(td->dev); | ||
173 | |||
174 | dma_pool_free(uhci->td_pool, td, td->dma_handle); | 170 | dma_pool_free(uhci->td_pool, td, td->dma_handle); |
175 | } | 171 | } |
176 | 172 | ||
177 | static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *dev) | 173 | static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci) |
178 | { | 174 | { |
179 | dma_addr_t dma_handle; | 175 | dma_addr_t dma_handle; |
180 | struct uhci_qh *qh; | 176 | struct uhci_qh *qh; |
@@ -188,14 +184,11 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *d | |||
188 | qh->element = UHCI_PTR_TERM; | 184 | qh->element = UHCI_PTR_TERM; |
189 | qh->link = UHCI_PTR_TERM; | 185 | qh->link = UHCI_PTR_TERM; |
190 | 186 | ||
191 | qh->dev = dev; | ||
192 | qh->urbp = NULL; | 187 | qh->urbp = NULL; |
193 | 188 | ||
194 | INIT_LIST_HEAD(&qh->list); | 189 | INIT_LIST_HEAD(&qh->list); |
195 | INIT_LIST_HEAD(&qh->remove_list); | 190 | INIT_LIST_HEAD(&qh->remove_list); |
196 | 191 | ||
197 | usb_get_dev(dev); | ||
198 | |||
199 | return qh; | 192 | return qh; |
200 | } | 193 | } |
201 | 194 | ||
@@ -206,9 +199,6 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
206 | if (!list_empty(&qh->remove_list)) | 199 | if (!list_empty(&qh->remove_list)) |
207 | dev_warn(uhci_dev(uhci), "qh %p still in remove_list!\n", qh); | 200 | dev_warn(uhci_dev(uhci), "qh %p still in remove_list!\n", qh); |
208 | 201 | ||
209 | if (qh->dev) | ||
210 | usb_put_dev(qh->dev); | ||
211 | |||
212 | dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); | 202 | dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); |
213 | } | 203 | } |
214 | 204 | ||
@@ -597,7 +587,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur | |||
597 | /* | 587 | /* |
598 | * Build the TD for the control request setup packet | 588 | * Build the TD for the control request setup packet |
599 | */ | 589 | */ |
600 | td = uhci_alloc_td(uhci, urb->dev); | 590 | td = uhci_alloc_td(uhci); |
601 | if (!td) | 591 | if (!td) |
602 | return -ENOMEM; | 592 | return -ENOMEM; |
603 | 593 | ||
@@ -626,7 +616,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur | |||
626 | if (pktsze > maxsze) | 616 | if (pktsze > maxsze) |
627 | pktsze = maxsze; | 617 | pktsze = maxsze; |
628 | 618 | ||
629 | td = uhci_alloc_td(uhci, urb->dev); | 619 | td = uhci_alloc_td(uhci); |
630 | if (!td) | 620 | if (!td) |
631 | return -ENOMEM; | 621 | return -ENOMEM; |
632 | 622 | ||
@@ -644,7 +634,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur | |||
644 | /* | 634 | /* |
645 | * Build the final TD for control status | 635 | * Build the final TD for control status |
646 | */ | 636 | */ |
647 | td = uhci_alloc_td(uhci, urb->dev); | 637 | td = uhci_alloc_td(uhci); |
648 | if (!td) | 638 | if (!td) |
649 | return -ENOMEM; | 639 | return -ENOMEM; |
650 | 640 | ||
@@ -666,7 +656,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur | |||
666 | uhci_fill_td(td, status | TD_CTRL_IOC, | 656 | uhci_fill_td(td, status | TD_CTRL_IOC, |
667 | destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0); | 657 | destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0); |
668 | 658 | ||
669 | qh = uhci_alloc_qh(uhci, urb->dev); | 659 | qh = uhci_alloc_qh(uhci); |
670 | if (!qh) | 660 | if (!qh) |
671 | return -ENOMEM; | 661 | return -ENOMEM; |
672 | 662 | ||
@@ -865,7 +855,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb | |||
865 | status &= ~TD_CTRL_SPD; | 855 | status &= ~TD_CTRL_SPD; |
866 | } | 856 | } |
867 | 857 | ||
868 | td = uhci_alloc_td(uhci, urb->dev); | 858 | td = uhci_alloc_td(uhci); |
869 | if (!td) | 859 | if (!td) |
870 | return -ENOMEM; | 860 | return -ENOMEM; |
871 | 861 | ||
@@ -891,7 +881,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb | |||
891 | */ | 881 | */ |
892 | if (usb_pipeout(urb->pipe) && (urb->transfer_flags & URB_ZERO_PACKET) && | 882 | if (usb_pipeout(urb->pipe) && (urb->transfer_flags & URB_ZERO_PACKET) && |
893 | !len && urb->transfer_buffer_length) { | 883 | !len && urb->transfer_buffer_length) { |
894 | td = uhci_alloc_td(uhci, urb->dev); | 884 | td = uhci_alloc_td(uhci); |
895 | if (!td) | 885 | if (!td) |
896 | return -ENOMEM; | 886 | return -ENOMEM; |
897 | 887 | ||
@@ -913,7 +903,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb | |||
913 | * flag setting. */ | 903 | * flag setting. */ |
914 | td->status |= cpu_to_le32(TD_CTRL_IOC); | 904 | td->status |= cpu_to_le32(TD_CTRL_IOC); |
915 | 905 | ||
916 | qh = uhci_alloc_qh(uhci, urb->dev); | 906 | qh = uhci_alloc_qh(uhci); |
917 | if (!qh) | 907 | if (!qh) |
918 | return -ENOMEM; | 908 | return -ENOMEM; |
919 | 909 | ||
@@ -1096,7 +1086,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb) | |||
1096 | if (!urb->iso_frame_desc[i].length) | 1086 | if (!urb->iso_frame_desc[i].length) |
1097 | continue; | 1087 | continue; |
1098 | 1088 | ||
1099 | td = uhci_alloc_td(uhci, urb->dev); | 1089 | td = uhci_alloc_td(uhci); |
1100 | if (!td) | 1090 | if (!td) |
1101 | return -ENOMEM; | 1091 | return -ENOMEM; |
1102 | 1092 | ||
@@ -1497,6 +1487,7 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) | |||
1497 | rescan: | 1487 | rescan: |
1498 | uhci->need_rescan = 0; | 1488 | uhci->need_rescan = 0; |
1499 | 1489 | ||
1490 | uhci_clear_next_interrupt(uhci); | ||
1500 | uhci_get_current_frame_number(uhci); | 1491 | uhci_get_current_frame_number(uhci); |
1501 | 1492 | ||
1502 | if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age) | 1493 | if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age) |
@@ -1537,3 +1528,26 @@ static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) | |||
1537 | /* Wake up anyone waiting for an URB to complete */ | 1528 | /* Wake up anyone waiting for an URB to complete */ |
1538 | wake_up_all(&uhci->waitqh); | 1529 | wake_up_all(&uhci->waitqh); |
1539 | } | 1530 | } |
1531 | |||
1532 | static void check_fsbr(struct uhci_hcd *uhci) | ||
1533 | { | ||
1534 | struct urb_priv *up; | ||
1535 | |||
1536 | list_for_each_entry(up, &uhci->urb_list, urb_list) { | ||
1537 | struct urb *u = up->urb; | ||
1538 | |||
1539 | spin_lock(&u->lock); | ||
1540 | |||
1541 | /* Check if the FSBR timed out */ | ||
1542 | if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT)) | ||
1543 | uhci_fsbr_timeout(uhci, u); | ||
1544 | |||
1545 | spin_unlock(&u->lock); | ||
1546 | } | ||
1547 | |||
1548 | /* Really disable FSBR */ | ||
1549 | if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) { | ||
1550 | uhci->fsbrtimeout = 0; | ||
1551 | uhci->skel_term_qh->link = UHCI_PTR_TERM; | ||
1552 | } | ||
1553 | } | ||
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index d28e7eab6f98..fd59f6bdd67f 100644 --- a/drivers/usb/input/Kconfig +++ b/drivers/usb/input/Kconfig | |||
@@ -151,6 +151,18 @@ config USB_WACOM | |||
151 | To compile this driver as a module, choose M here: the | 151 | To compile this driver as a module, choose M here: the |
152 | module will be called wacom. | 152 | module will be called wacom. |
153 | 153 | ||
154 | config USB_ACECAD | ||
155 | tristate "Acecad Flair tablet support" | ||
156 | depends on USB && INPUT | ||
157 | help | ||
158 | Say Y here if you want to use the USB version of the Acecad Flair | ||
159 | tablet. Make sure to say Y to "Mouse support" | ||
160 | (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" | ||
161 | (CONFIG_INPUT_EVDEV) as well. | ||
162 | |||
163 | To compile this driver as a module, choose M here: the | ||
164 | module will be called acecad. | ||
165 | |||
154 | config USB_KBTAB | 166 | config USB_KBTAB |
155 | tristate "KB Gear JamStudio tablet support" | 167 | tristate "KB Gear JamStudio tablet support" |
156 | depends on USB && INPUT | 168 | depends on USB && INPUT |
@@ -190,6 +202,18 @@ config USB_MTOUCH | |||
190 | To compile this driver as a module, choose M here: the | 202 | To compile this driver as a module, choose M here: the |
191 | module will be called mtouchusb. | 203 | module will be called mtouchusb. |
192 | 204 | ||
205 | config USB_ITMTOUCH | ||
206 | tristate "ITM Touch USB Touchscreen Driver" | ||
207 | depends on USB && INPUT | ||
208 | ---help--- | ||
209 | Say Y here if you want to use a ITM Touch USB | ||
210 | Touchscreen controller. | ||
211 | |||
212 | This touchscreen is used in LG 1510SF monitors. | ||
213 | |||
214 | To compile this driver as a module, choose M here: the | ||
215 | module will be called itmtouch. | ||
216 | |||
193 | config USB_EGALAX | 217 | config USB_EGALAX |
194 | tristate "eGalax TouchKit USB Touchscreen Driver" | 218 | tristate "eGalax TouchKit USB Touchscreen Driver" |
195 | depends on USB && INPUT | 219 | depends on USB && INPUT |
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile index 6bcedd16b0a1..831b2b0f1f05 100644 --- a/drivers/usb/input/Makefile +++ b/drivers/usb/input/Makefile | |||
@@ -33,7 +33,9 @@ obj-$(CONFIG_USB_KBD) += usbkbd.o | |||
33 | obj-$(CONFIG_USB_KBTAB) += kbtab.o | 33 | obj-$(CONFIG_USB_KBTAB) += kbtab.o |
34 | obj-$(CONFIG_USB_MOUSE) += usbmouse.o | 34 | obj-$(CONFIG_USB_MOUSE) += usbmouse.o |
35 | obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o | 35 | obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o |
36 | obj-$(CONFIG_USB_ITMTOUCH) += itmtouch.o | ||
36 | obj-$(CONFIG_USB_EGALAX) += touchkitusb.o | 37 | obj-$(CONFIG_USB_EGALAX) += touchkitusb.o |
37 | obj-$(CONFIG_USB_POWERMATE) += powermate.o | 38 | obj-$(CONFIG_USB_POWERMATE) += powermate.o |
38 | obj-$(CONFIG_USB_WACOM) += wacom.o | 39 | obj-$(CONFIG_USB_WACOM) += wacom.o |
40 | obj-$(CONFIG_USB_ACECAD) += acecad.o | ||
39 | obj-$(CONFIG_USB_XPAD) += xpad.o | 41 | obj-$(CONFIG_USB_XPAD) += xpad.o |
diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c new file mode 100644 index 000000000000..ebcf7c955800 --- /dev/null +++ b/drivers/usb/input/acecad.c | |||
@@ -0,0 +1,285 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2001-2005 Edouard TISSERANT <edouard.tisserant@wanadoo.fr> | ||
3 | * Copyright (c) 2004-2005 Stephane VOLTZ <svoltz@numericable.fr> | ||
4 | * | ||
5 | * USB Acecad "Acecad Flair" tablet support | ||
6 | * | ||
7 | * Changelog: | ||
8 | * v3.2 - Added sysfs support | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/input.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/usb.h> | ||
34 | |||
35 | /* | ||
36 | * Version Information | ||
37 | */ | ||
38 | #define DRIVER_VERSION "v3.2" | ||
39 | #define DRIVER_DESC "USB Acecad Flair tablet driver" | ||
40 | #define DRIVER_LICENSE "GPL" | ||
41 | #define DRIVER_AUTHOR "Edouard TISSERANT <edouard.tisserant@wanadoo.fr>" | ||
42 | |||
43 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
44 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
45 | MODULE_LICENSE(DRIVER_LICENSE); | ||
46 | |||
47 | #define USB_VENDOR_ID_ACECAD 0x0460 | ||
48 | #define USB_DEVICE_ID_FLAIR 0x0004 | ||
49 | #define USB_DEVICE_ID_302 0x0008 | ||
50 | |||
51 | struct usb_acecad { | ||
52 | char name[128]; | ||
53 | char phys[64]; | ||
54 | struct usb_device *usbdev; | ||
55 | struct input_dev dev; | ||
56 | struct urb *irq; | ||
57 | |||
58 | signed char *data; | ||
59 | dma_addr_t data_dma; | ||
60 | }; | ||
61 | |||
62 | static void usb_acecad_irq(struct urb *urb, struct pt_regs *regs) | ||
63 | { | ||
64 | struct usb_acecad *acecad = urb->context; | ||
65 | unsigned char *data = acecad->data; | ||
66 | struct input_dev *dev = &acecad->dev; | ||
67 | int prox, status; | ||
68 | |||
69 | switch (urb->status) { | ||
70 | case 0: | ||
71 | /* success */ | ||
72 | break; | ||
73 | case -ECONNRESET: | ||
74 | case -ENOENT: | ||
75 | case -ESHUTDOWN: | ||
76 | /* this urb is terminated, clean up */ | ||
77 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
78 | return; | ||
79 | default: | ||
80 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
81 | goto resubmit; | ||
82 | } | ||
83 | |||
84 | prox = (data[0] & 0x04) >> 2; | ||
85 | input_report_key(dev, BTN_TOOL_PEN, prox); | ||
86 | |||
87 | if (prox) { | ||
88 | int x = data[1] | (data[2] << 8); | ||
89 | int y = data[3] | (data[4] << 8); | ||
90 | /*Pressure should compute the same way for flair and 302*/ | ||
91 | int pressure = data[5] | ((int)data[6] << 8); | ||
92 | int touch = data[0] & 0x01; | ||
93 | int stylus = (data[0] & 0x10) >> 4; | ||
94 | int stylus2 = (data[0] & 0x20) >> 5; | ||
95 | input_report_abs(dev, ABS_X, x); | ||
96 | input_report_abs(dev, ABS_Y, y); | ||
97 | input_report_abs(dev, ABS_PRESSURE, pressure); | ||
98 | input_report_key(dev, BTN_TOUCH, touch); | ||
99 | input_report_key(dev, BTN_STYLUS, stylus); | ||
100 | input_report_key(dev, BTN_STYLUS2, stylus2); | ||
101 | } | ||
102 | |||
103 | /* event termination */ | ||
104 | input_sync(dev); | ||
105 | |||
106 | resubmit: | ||
107 | status = usb_submit_urb (urb, GFP_ATOMIC); | ||
108 | if (status) | ||
109 | err ("can't resubmit intr, %s-%s/input0, status %d", | ||
110 | acecad->usbdev->bus->bus_name, acecad->usbdev->devpath, status); | ||
111 | } | ||
112 | |||
113 | static int usb_acecad_open(struct input_dev *dev) | ||
114 | { | ||
115 | struct usb_acecad *acecad = dev->private; | ||
116 | |||
117 | acecad->irq->dev = acecad->usbdev; | ||
118 | if (usb_submit_urb(acecad->irq, GFP_KERNEL)) | ||
119 | return -EIO; | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static void usb_acecad_close(struct input_dev *dev) | ||
125 | { | ||
126 | struct usb_acecad *acecad = dev->private; | ||
127 | |||
128 | usb_kill_urb(acecad->irq); | ||
129 | } | ||
130 | |||
131 | static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
132 | { | ||
133 | struct usb_device *dev = interface_to_usbdev(intf); | ||
134 | struct usb_host_interface *interface = intf->cur_altsetting; | ||
135 | struct usb_endpoint_descriptor *endpoint; | ||
136 | struct usb_acecad *acecad; | ||
137 | int pipe, maxp; | ||
138 | char path[64]; | ||
139 | |||
140 | if (interface->desc.bNumEndpoints != 1) | ||
141 | return -ENODEV; | ||
142 | |||
143 | endpoint = &interface->endpoint[0].desc; | ||
144 | |||
145 | if (!(endpoint->bEndpointAddress & 0x80)) | ||
146 | return -ENODEV; | ||
147 | |||
148 | if ((endpoint->bmAttributes & 3) != 3) | ||
149 | return -ENODEV; | ||
150 | |||
151 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | ||
152 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); | ||
153 | |||
154 | acecad = kcalloc(1, sizeof(struct usb_acecad), GFP_KERNEL); | ||
155 | if (!acecad) | ||
156 | return -ENOMEM; | ||
157 | |||
158 | acecad->data = usb_buffer_alloc(dev, 8, SLAB_KERNEL, &acecad->data_dma); | ||
159 | if (!acecad->data) | ||
160 | goto fail1; | ||
161 | |||
162 | acecad->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
163 | if (!acecad->irq) | ||
164 | goto fail2; | ||
165 | |||
166 | if (dev->manufacturer) | ||
167 | strlcpy(acecad->name, dev->manufacturer, sizeof(acecad->name)); | ||
168 | |||
169 | if (dev->product) { | ||
170 | if (dev->manufacturer) | ||
171 | strlcat(acecad->name, " ", sizeof(acecad->name)); | ||
172 | strlcat(acecad->name, dev->product, sizeof(acecad->name)); | ||
173 | } | ||
174 | |||
175 | usb_make_path(dev, path, sizeof(path)); | ||
176 | snprintf(acecad->phys, sizeof(acecad->phys), "%s/input0", path); | ||
177 | |||
178 | acecad->usbdev = dev; | ||
179 | |||
180 | acecad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
181 | acecad->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); | ||
182 | acecad->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
183 | acecad->dev.keybit[LONG(BTN_DIGI)] = BIT(BTN_TOOL_PEN) |BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2); | ||
184 | |||
185 | switch (id->driver_info) { | ||
186 | case 0: | ||
187 | acecad->dev.absmax[ABS_X] = 5000; | ||
188 | acecad->dev.absmax[ABS_Y] = 3750; | ||
189 | acecad->dev.absmax[ABS_PRESSURE] = 512; | ||
190 | if (!strlen(acecad->name)) | ||
191 | snprintf(acecad->name, sizeof(acecad->name), | ||
192 | "USB Acecad Flair Tablet %04x:%04x", | ||
193 | dev->descriptor.idVendor, dev->descriptor.idProduct); | ||
194 | break; | ||
195 | case 1: | ||
196 | acecad->dev.absmax[ABS_X] = 3000; | ||
197 | acecad->dev.absmax[ABS_Y] = 2250; | ||
198 | acecad->dev.absmax[ABS_PRESSURE] = 1024; | ||
199 | if (!strlen(acecad->name)) | ||
200 | snprintf(acecad->name, sizeof(acecad->name), | ||
201 | "USB Acecad 302 Tablet %04x:%04x", | ||
202 | dev->descriptor.idVendor, dev->descriptor.idProduct); | ||
203 | break; | ||
204 | } | ||
205 | |||
206 | acecad->dev.absfuzz[ABS_X] = 4; | ||
207 | acecad->dev.absfuzz[ABS_Y] = 4; | ||
208 | |||
209 | acecad->dev.private = acecad; | ||
210 | acecad->dev.open = usb_acecad_open; | ||
211 | acecad->dev.close = usb_acecad_close; | ||
212 | |||
213 | acecad->dev.name = acecad->name; | ||
214 | acecad->dev.phys = acecad->phys; | ||
215 | acecad->dev.id.bustype = BUS_USB; | ||
216 | acecad->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); | ||
217 | acecad->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); | ||
218 | acecad->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice); | ||
219 | acecad->dev.dev = &intf->dev; | ||
220 | |||
221 | usb_fill_int_urb(acecad->irq, dev, pipe, | ||
222 | acecad->data, maxp > 8 ? 8 : maxp, | ||
223 | usb_acecad_irq, acecad, endpoint->bInterval); | ||
224 | acecad->irq->transfer_dma = acecad->data_dma; | ||
225 | acecad->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
226 | |||
227 | input_register_device(&acecad->dev); | ||
228 | |||
229 | printk(KERN_INFO "input: %s with packet size %d on %s\n", | ||
230 | acecad->name, maxp, path); | ||
231 | |||
232 | usb_set_intfdata(intf, acecad); | ||
233 | |||
234 | return 0; | ||
235 | |||
236 | fail2: usb_buffer_free(dev, 8, acecad->data, acecad->data_dma); | ||
237 | fail1: kfree(acecad); | ||
238 | return -ENOMEM; | ||
239 | } | ||
240 | |||
241 | static void usb_acecad_disconnect(struct usb_interface *intf) | ||
242 | { | ||
243 | struct usb_acecad *acecad = usb_get_intfdata(intf); | ||
244 | |||
245 | usb_set_intfdata(intf, NULL); | ||
246 | if (acecad) { | ||
247 | usb_kill_urb(acecad->irq); | ||
248 | input_unregister_device(&acecad->dev); | ||
249 | usb_free_urb(acecad->irq); | ||
250 | usb_buffer_free(interface_to_usbdev(intf), 10, acecad->data, acecad->data_dma); | ||
251 | kfree(acecad); | ||
252 | } | ||
253 | } | ||
254 | |||
255 | static struct usb_device_id usb_acecad_id_table [] = { | ||
256 | { USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_FLAIR), .driver_info = 0 }, | ||
257 | { USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_302), .driver_info = 1 }, | ||
258 | { } | ||
259 | }; | ||
260 | |||
261 | MODULE_DEVICE_TABLE(usb, usb_acecad_id_table); | ||
262 | |||
263 | static struct usb_driver usb_acecad_driver = { | ||
264 | .owner = THIS_MODULE, | ||
265 | .name = "usb_acecad", | ||
266 | .probe = usb_acecad_probe, | ||
267 | .disconnect = usb_acecad_disconnect, | ||
268 | .id_table = usb_acecad_id_table, | ||
269 | }; | ||
270 | |||
271 | static int __init usb_acecad_init(void) | ||
272 | { | ||
273 | int result = usb_register(&usb_acecad_driver); | ||
274 | if (result == 0) | ||
275 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
276 | return result; | ||
277 | } | ||
278 | |||
279 | static void __exit usb_acecad_exit(void) | ||
280 | { | ||
281 | usb_deregister(&usb_acecad_driver); | ||
282 | } | ||
283 | |||
284 | module_init(usb_acecad_init); | ||
285 | module_exit(usb_acecad_exit); | ||
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c index e991f7ed7330..6bb0f25e8e93 100644 --- a/drivers/usb/input/aiptek.c +++ b/drivers/usb/input/aiptek.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Native support for the Aiptek HyperPen USB Tablets | 2 | * Native support for the Aiptek HyperPen USB Tablets |
3 | * (4000U/5000U/6000U/8000U/12000U) | 3 | * (4000U/5000U/6000U/8000U/12000U) |
4 | * | 4 | * |
5 | * Copyright (c) 2001 Chris Atenasio <chris@crud.net> | 5 | * Copyright (c) 2001 Chris Atenasio <chris@crud.net> |
6 | * Copyright (c) 2002-2004 Bryan W. Headley <bwheadley@earthlink.net> | 6 | * Copyright (c) 2002-2004 Bryan W. Headley <bwheadley@earthlink.net> |
7 | * | 7 | * |
@@ -31,7 +31,7 @@ | |||
31 | * - Added support for the sysfs interface, deprecating the | 31 | * - Added support for the sysfs interface, deprecating the |
32 | * procfs interface for 2.5.x kernel. Also added support for | 32 | * procfs interface for 2.5.x kernel. Also added support for |
33 | * Wheel command. Bryan W. Headley July-15-2003. | 33 | * Wheel command. Bryan W. Headley July-15-2003. |
34 | * v1.2 - Reworked jitter timer as a kernel thread. | 34 | * v1.2 - Reworked jitter timer as a kernel thread. |
35 | * Bryan W. Headley November-28-2003/Jan-10-2004. | 35 | * Bryan W. Headley November-28-2003/Jan-10-2004. |
36 | * v1.3 - Repaired issue of kernel thread going nuts on single-processor | 36 | * v1.3 - Repaired issue of kernel thread going nuts on single-processor |
37 | * machines, introduced programmableDelay as a command line | 37 | * machines, introduced programmableDelay as a command line |
@@ -49,10 +49,10 @@ | |||
49 | * NOTE: | 49 | * NOTE: |
50 | * This kernel driver is augmented by the "Aiptek" XFree86 input | 50 | * This kernel driver is augmented by the "Aiptek" XFree86 input |
51 | * driver for your X server, as well as the Gaiptek GUI Front-end | 51 | * driver for your X server, as well as the Gaiptek GUI Front-end |
52 | * "Tablet Manager". | 52 | * "Tablet Manager". |
53 | * These three products are highly interactive with one another, | 53 | * These three products are highly interactive with one another, |
54 | * so therefore it's easier to document them all as one subsystem. | 54 | * so therefore it's easier to document them all as one subsystem. |
55 | * Please visit the project's "home page", located at, | 55 | * Please visit the project's "home page", located at, |
56 | * http://aiptektablet.sourceforge.net. | 56 | * http://aiptektablet.sourceforge.net. |
57 | * | 57 | * |
58 | * This program is free software; you can redistribute it and/or modify | 58 | * This program is free software; you can redistribute it and/or modify |
@@ -156,7 +156,7 @@ | |||
156 | * Command/Data Description Return Bytes Return Value | 156 | * Command/Data Description Return Bytes Return Value |
157 | * 0x10/0x00 SwitchToMouse 0 | 157 | * 0x10/0x00 SwitchToMouse 0 |
158 | * 0x10/0x01 SwitchToTablet 0 | 158 | * 0x10/0x01 SwitchToTablet 0 |
159 | * 0x18/0x04 SetResolution 0 | 159 | * 0x18/0x04 SetResolution 0 |
160 | * 0x12/0xFF AutoGainOn 0 | 160 | * 0x12/0xFF AutoGainOn 0 |
161 | * 0x17/0x00 FilterOn 0 | 161 | * 0x17/0x00 FilterOn 0 |
162 | * 0x01/0x00 GetXExtension 2 MaxX | 162 | * 0x01/0x00 GetXExtension 2 MaxX |
@@ -247,7 +247,7 @@ | |||
247 | #define AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE 2 | 247 | #define AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE 2 |
248 | #define AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED 3 | 248 | #define AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED 3 |
249 | 249 | ||
250 | /* Time to wait (in ms) to help mask hand jittering | 250 | /* Time to wait (in ms) to help mask hand jittering |
251 | * when pressing the stylus buttons. | 251 | * when pressing the stylus buttons. |
252 | */ | 252 | */ |
253 | #define AIPTEK_JITTER_DELAY_DEFAULT 50 | 253 | #define AIPTEK_JITTER_DELAY_DEFAULT 50 |
@@ -324,7 +324,6 @@ struct aiptek { | |||
324 | struct aiptek_settings curSetting; /* tablet's current programmable */ | 324 | struct aiptek_settings curSetting; /* tablet's current programmable */ |
325 | struct aiptek_settings newSetting; /* ... and new param settings */ | 325 | struct aiptek_settings newSetting; /* ... and new param settings */ |
326 | unsigned int ifnum; /* interface number for IO */ | 326 | unsigned int ifnum; /* interface number for IO */ |
327 | int openCount; /* module use counter */ | ||
328 | int diagnostic; /* tablet diagnostic codes */ | 327 | int diagnostic; /* tablet diagnostic codes */ |
329 | unsigned long eventCount; /* event count */ | 328 | unsigned long eventCount; /* event count */ |
330 | int inDelay; /* jitter: in jitter delay? */ | 329 | int inDelay; /* jitter: in jitter delay? */ |
@@ -791,7 +790,7 @@ exit: | |||
791 | * specific Aiptek model numbers, because there has been overlaps, | 790 | * specific Aiptek model numbers, because there has been overlaps, |
792 | * use, and reuse of id's in existing models. Certain models have | 791 | * use, and reuse of id's in existing models. Certain models have |
793 | * been known to use more than one ID, indicative perhaps of | 792 | * been known to use more than one ID, indicative perhaps of |
794 | * manufacturing revisions. In any event, we consider these | 793 | * manufacturing revisions. In any event, we consider these |
795 | * IDs to not be model-specific nor unique. | 794 | * IDs to not be model-specific nor unique. |
796 | */ | 795 | */ |
797 | static const struct usb_device_id aiptek_ids[] = { | 796 | static const struct usb_device_id aiptek_ids[] = { |
@@ -814,15 +813,9 @@ static int aiptek_open(struct input_dev *inputdev) | |||
814 | { | 813 | { |
815 | struct aiptek *aiptek = inputdev->private; | 814 | struct aiptek *aiptek = inputdev->private; |
816 | 815 | ||
817 | if (aiptek->openCount++ > 0) { | ||
818 | return 0; | ||
819 | } | ||
820 | |||
821 | aiptek->urb->dev = aiptek->usbdev; | 816 | aiptek->urb->dev = aiptek->usbdev; |
822 | if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0) { | 817 | if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0) |
823 | aiptek->openCount--; | ||
824 | return -EIO; | 818 | return -EIO; |
825 | } | ||
826 | 819 | ||
827 | return 0; | 820 | return 0; |
828 | } | 821 | } |
@@ -834,13 +827,11 @@ static void aiptek_close(struct input_dev *inputdev) | |||
834 | { | 827 | { |
835 | struct aiptek *aiptek = inputdev->private; | 828 | struct aiptek *aiptek = inputdev->private; |
836 | 829 | ||
837 | if (--aiptek->openCount == 0) { | 830 | usb_kill_urb(aiptek->urb); |
838 | usb_kill_urb(aiptek->urb); | ||
839 | } | ||
840 | } | 831 | } |
841 | 832 | ||
842 | /*********************************************************************** | 833 | /*********************************************************************** |
843 | * aiptek_set_report and aiptek_get_report() are borrowed from Linux 2.4.x, | 834 | * aiptek_set_report and aiptek_get_report() are borrowed from Linux 2.4.x, |
844 | * where they were known as usb_set_report and usb_get_report. | 835 | * where they were known as usb_set_report and usb_get_report. |
845 | */ | 836 | */ |
846 | static int | 837 | static int |
@@ -2252,7 +2243,6 @@ static void aiptek_disconnect(struct usb_interface *intf) | |||
2252 | AIPTEK_PACKET_LENGTH, | 2243 | AIPTEK_PACKET_LENGTH, |
2253 | aiptek->data, aiptek->data_dma); | 2244 | aiptek->data, aiptek->data_dma); |
2254 | kfree(aiptek); | 2245 | kfree(aiptek); |
2255 | aiptek = NULL; | ||
2256 | } | 2246 | } |
2257 | } | 2247 | } |
2258 | 2248 | ||
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index 860df26323b1..654ac454744d 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c | |||
@@ -1,15 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * USB ATI Remote support | 2 | * USB ATI Remote support |
3 | * | 3 | * |
4 | * Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net> | 4 | * Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net> |
5 | * Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev | 5 | * Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev |
6 | * | 6 | * |
7 | * This 2.2.0 version is a rewrite / cleanup of the 2.1.1 driver, including | 7 | * This 2.2.0 version is a rewrite / cleanup of the 2.1.1 driver, including |
8 | * porting to the 2.6 kernel interfaces, along with other modification | 8 | * porting to the 2.6 kernel interfaces, along with other modification |
9 | * to better match the style of the existing usb/input drivers. However, the | 9 | * to better match the style of the existing usb/input drivers. However, the |
10 | * protocol and hardware handling is essentially unchanged from 2.1.1. | 10 | * protocol and hardware handling is essentially unchanged from 2.1.1. |
11 | * | 11 | * |
12 | * The 2.1.1 driver was derived from the usbati_remote and usbkbd drivers by | 12 | * The 2.1.1 driver was derived from the usbati_remote and usbkbd drivers by |
13 | * Vojtech Pavlik. | 13 | * Vojtech Pavlik. |
14 | * | 14 | * |
15 | * Changes: | 15 | * Changes: |
@@ -23,64 +23,64 @@ | |||
23 | * Added support for the "Lola" remote contributed by: | 23 | * Added support for the "Lola" remote contributed by: |
24 | * Seth Cohn <sethcohn@yahoo.com> | 24 | * Seth Cohn <sethcohn@yahoo.com> |
25 | * | 25 | * |
26 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | 26 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
27 | * | 27 | * |
28 | * This program is free software; you can redistribute it and/or modify | 28 | * This program is free software; you can redistribute it and/or modify |
29 | * it under the terms of the GNU General Public License as published by | 29 | * it under the terms of the GNU General Public License as published by |
30 | * the Free Software Foundation; either version 2 of the License, or | 30 | * the Free Software Foundation; either version 2 of the License, or |
31 | * (at your option) any later version. | 31 | * (at your option) any later version. |
32 | * | 32 | * |
33 | * This program is distributed in the hope that it will be useful, | 33 | * This program is distributed in the hope that it will be useful, |
34 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 34 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
35 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 35 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
36 | * GNU General Public License for more details. | 36 | * GNU General Public License for more details. |
37 | * | 37 | * |
38 | * You should have received a copy of the GNU General Public License | 38 | * You should have received a copy of the GNU General Public License |
39 | * along with this program; if not, write to the Free Software | 39 | * along with this program; if not, write to the Free Software |
40 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 40 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
41 | * | 41 | * |
42 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | 42 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
43 | * | 43 | * |
44 | * Hardware & software notes | 44 | * Hardware & software notes |
45 | * | 45 | * |
46 | * These remote controls are distributed by ATI as part of their | 46 | * These remote controls are distributed by ATI as part of their |
47 | * "All-In-Wonder" video card packages. The receiver self-identifies as a | 47 | * "All-In-Wonder" video card packages. The receiver self-identifies as a |
48 | * "USB Receiver" with manufacturer "X10 Wireless Technology Inc". | 48 | * "USB Receiver" with manufacturer "X10 Wireless Technology Inc". |
49 | * | 49 | * |
50 | * The "Lola" remote is available from X10. See: | 50 | * The "Lola" remote is available from X10. See: |
51 | * http://www.x10.com/products/lola_sg1.htm | 51 | * http://www.x10.com/products/lola_sg1.htm |
52 | * The Lola is similar to the ATI remote but has no mouse support, and slightly | 52 | * The Lola is similar to the ATI remote but has no mouse support, and slightly |
53 | * different keys. | 53 | * different keys. |
54 | * | 54 | * |
55 | * It is possible to use multiple receivers and remotes on multiple computers | 55 | * It is possible to use multiple receivers and remotes on multiple computers |
56 | * simultaneously by configuring them to use specific channels. | 56 | * simultaneously by configuring them to use specific channels. |
57 | * | 57 | * |
58 | * The RF protocol used by the remote supports 16 distinct channels, 1 to 16. | 58 | * The RF protocol used by the remote supports 16 distinct channels, 1 to 16. |
59 | * Actually, it may even support more, at least in some revisions of the | 59 | * Actually, it may even support more, at least in some revisions of the |
60 | * hardware. | 60 | * hardware. |
61 | * | 61 | * |
62 | * Each remote can be configured to transmit on one channel as follows: | 62 | * Each remote can be configured to transmit on one channel as follows: |
63 | * - Press and hold the "hand icon" button. | 63 | * - Press and hold the "hand icon" button. |
64 | * - When the red LED starts to blink, let go of the "hand icon" button. | 64 | * - When the red LED starts to blink, let go of the "hand icon" button. |
65 | * - When it stops blinking, input the channel code as two digits, from 01 | 65 | * - When it stops blinking, input the channel code as two digits, from 01 |
66 | * to 16, and press the hand icon again. | 66 | * to 16, and press the hand icon again. |
67 | * | 67 | * |
68 | * The timing can be a little tricky. Try loading the module with debug=1 | 68 | * The timing can be a little tricky. Try loading the module with debug=1 |
69 | * to have the kernel print out messages about the remote control number | 69 | * to have the kernel print out messages about the remote control number |
70 | * and mask. Note: debugging prints remote numbers as zero-based hexadecimal. | 70 | * and mask. Note: debugging prints remote numbers as zero-based hexadecimal. |
71 | * | 71 | * |
72 | * The driver has a "channel_mask" parameter. This bitmask specifies which | 72 | * The driver has a "channel_mask" parameter. This bitmask specifies which |
73 | * channels will be ignored by the module. To mask out channels, just add | 73 | * channels will be ignored by the module. To mask out channels, just add |
74 | * all the 2^channel_number values together. | 74 | * all the 2^channel_number values together. |
75 | * | 75 | * |
76 | * For instance, set channel_mask = 2^4 = 16 (binary 10000) to make ati_remote | 76 | * For instance, set channel_mask = 2^4 = 16 (binary 10000) to make ati_remote |
77 | * ignore signals coming from remote controls transmitting on channel 4, but | 77 | * ignore signals coming from remote controls transmitting on channel 4, but |
78 | * accept all other channels. | 78 | * accept all other channels. |
79 | * | 79 | * |
80 | * Or, set channel_mask = 65533, (0xFFFD), and all channels except 1 will be | 80 | * Or, set channel_mask = 65533, (0xFFFD), and all channels except 1 will be |
81 | * ignored. | 81 | * ignored. |
82 | * | 82 | * |
83 | * The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this | 83 | * The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this |
84 | * parameter are unused. | 84 | * parameter are unused. |
85 | * | 85 | * |
86 | */ | 86 | */ |
@@ -99,13 +99,13 @@ | |||
99 | /* | 99 | /* |
100 | * Module and Version Information, Module Parameters | 100 | * Module and Version Information, Module Parameters |
101 | */ | 101 | */ |
102 | 102 | ||
103 | #define ATI_REMOTE_VENDOR_ID 0x0bc7 | 103 | #define ATI_REMOTE_VENDOR_ID 0x0bc7 |
104 | #define ATI_REMOTE_PRODUCT_ID 0x004 | 104 | #define ATI_REMOTE_PRODUCT_ID 0x004 |
105 | #define LOLA_REMOTE_PRODUCT_ID 0x002 | 105 | #define LOLA_REMOTE_PRODUCT_ID 0x002 |
106 | #define MEDION_REMOTE_PRODUCT_ID 0x006 | 106 | #define MEDION_REMOTE_PRODUCT_ID 0x006 |
107 | 107 | ||
108 | #define DRIVER_VERSION "2.2.1" | 108 | #define DRIVER_VERSION "2.2.1" |
109 | #define DRIVER_AUTHOR "Torrey Hoffman <thoffman@arnor.net>" | 109 | #define DRIVER_AUTHOR "Torrey Hoffman <thoffman@arnor.net>" |
110 | #define DRIVER_DESC "ATI/X10 RF USB Remote Control" | 110 | #define DRIVER_DESC "ATI/X10 RF USB Remote Control" |
111 | 111 | ||
@@ -113,18 +113,18 @@ | |||
113 | #define DATA_BUFSIZE 63 /* size of URB data buffers */ | 113 | #define DATA_BUFSIZE 63 /* size of URB data buffers */ |
114 | #define ATI_INPUTNUM 1 /* Which input device to register as */ | 114 | #define ATI_INPUTNUM 1 /* Which input device to register as */ |
115 | 115 | ||
116 | static unsigned long channel_mask = 0; | 116 | static unsigned long channel_mask; |
117 | module_param(channel_mask, ulong, 0444); | 117 | module_param(channel_mask, ulong, 0444); |
118 | MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); | 118 | MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); |
119 | 119 | ||
120 | static int debug = 0; | 120 | static int debug; |
121 | module_param(debug, int, 0444); | 121 | module_param(debug, int, 0444); |
122 | MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); | 122 | MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); |
123 | 123 | ||
124 | #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) | 124 | #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) |
125 | #undef err | 125 | #undef err |
126 | #define err(format, arg...) printk(KERN_ERR format , ## arg) | 126 | #define err(format, arg...) printk(KERN_ERR format , ## arg) |
127 | 127 | ||
128 | static struct usb_device_id ati_remote_table[] = { | 128 | static struct usb_device_id ati_remote_table[] = { |
129 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, | 129 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, |
130 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, | 130 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, |
@@ -148,7 +148,7 @@ static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; | |||
148 | /* Acceleration curve for directional control pad */ | 148 | /* Acceleration curve for directional control pad */ |
149 | static char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; | 149 | static char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; |
150 | 150 | ||
151 | /* Duplicate event filtering time. | 151 | /* Duplicate event filtering time. |
152 | * Sequential, identical KIND_FILTERED inputs with less than | 152 | * Sequential, identical KIND_FILTERED inputs with less than |
153 | * FILTER_TIME jiffies between them are considered as repeat | 153 | * FILTER_TIME jiffies between them are considered as repeat |
154 | * events. The hardware generates 5 events for the first keypress | 154 | * events. The hardware generates 5 events for the first keypress |
@@ -161,10 +161,10 @@ static char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; | |||
161 | static DECLARE_MUTEX(disconnect_sem); | 161 | static DECLARE_MUTEX(disconnect_sem); |
162 | 162 | ||
163 | struct ati_remote { | 163 | struct ati_remote { |
164 | struct input_dev idev; | 164 | struct input_dev idev; |
165 | struct usb_device *udev; | 165 | struct usb_device *udev; |
166 | struct usb_interface *interface; | 166 | struct usb_interface *interface; |
167 | 167 | ||
168 | struct urb *irq_urb; | 168 | struct urb *irq_urb; |
169 | struct urb *out_urb; | 169 | struct urb *out_urb; |
170 | struct usb_endpoint_descriptor *endpoint_in; | 170 | struct usb_endpoint_descriptor *endpoint_in; |
@@ -174,13 +174,11 @@ struct ati_remote { | |||
174 | dma_addr_t inbuf_dma; | 174 | dma_addr_t inbuf_dma; |
175 | dma_addr_t outbuf_dma; | 175 | dma_addr_t outbuf_dma; |
176 | 176 | ||
177 | int open; /* open counter */ | ||
178 | |||
179 | unsigned char old_data[2]; /* Detect duplicate events */ | 177 | unsigned char old_data[2]; /* Detect duplicate events */ |
180 | unsigned long old_jiffies; | 178 | unsigned long old_jiffies; |
181 | unsigned long acc_jiffies; /* handle acceleration */ | 179 | unsigned long acc_jiffies; /* handle acceleration */ |
182 | unsigned int repeat_count; | 180 | unsigned int repeat_count; |
183 | 181 | ||
184 | char name[NAME_BUFSIZE]; | 182 | char name[NAME_BUFSIZE]; |
185 | char phys[NAME_BUFSIZE]; | 183 | char phys[NAME_BUFSIZE]; |
186 | 184 | ||
@@ -206,14 +204,14 @@ static struct | |||
206 | int type; | 204 | int type; |
207 | unsigned int code; | 205 | unsigned int code; |
208 | int value; | 206 | int value; |
209 | } ati_remote_tbl[] = | 207 | } ati_remote_tbl[] = |
210 | { | 208 | { |
211 | /* Directional control pad axes */ | 209 | /* Directional control pad axes */ |
212 | {KIND_ACCEL, 0x35, 0x70, EV_REL, REL_X, -1}, /* left */ | 210 | {KIND_ACCEL, 0x35, 0x70, EV_REL, REL_X, -1}, /* left */ |
213 | {KIND_ACCEL, 0x36, 0x71, EV_REL, REL_X, 1}, /* right */ | 211 | {KIND_ACCEL, 0x36, 0x71, EV_REL, REL_X, 1}, /* right */ |
214 | {KIND_ACCEL, 0x37, 0x72, EV_REL, REL_Y, -1}, /* up */ | 212 | {KIND_ACCEL, 0x37, 0x72, EV_REL, REL_Y, -1}, /* up */ |
215 | {KIND_ACCEL, 0x38, 0x73, EV_REL, REL_Y, 1}, /* down */ | 213 | {KIND_ACCEL, 0x38, 0x73, EV_REL, REL_Y, 1}, /* down */ |
216 | /* Directional control pad diagonals */ | 214 | /* Directional control pad diagonals */ |
217 | {KIND_LU, 0x39, 0x74, EV_REL, 0, 0}, /* left up */ | 215 | {KIND_LU, 0x39, 0x74, EV_REL, 0, 0}, /* left up */ |
218 | {KIND_RU, 0x3a, 0x75, EV_REL, 0, 0}, /* right up */ | 216 | {KIND_RU, 0x3a, 0x75, EV_REL, 0, 0}, /* right up */ |
219 | {KIND_LD, 0x3c, 0x77, EV_REL, 0, 0}, /* left down */ | 217 | {KIND_LD, 0x3c, 0x77, EV_REL, 0, 0}, /* left down */ |
@@ -225,7 +223,7 @@ static struct | |||
225 | {KIND_LITERAL, 0x41, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */ | 223 | {KIND_LITERAL, 0x41, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */ |
226 | {KIND_LITERAL, 0x42, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */ | 224 | {KIND_LITERAL, 0x42, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */ |
227 | 225 | ||
228 | /* Artificial "doubleclick" events are generated by the hardware. | 226 | /* Artificial "doubleclick" events are generated by the hardware. |
229 | * They are mapped to the "side" and "extra" mouse buttons here. */ | 227 | * They are mapped to the "side" and "extra" mouse buttons here. */ |
230 | {KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */ | 228 | {KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */ |
231 | {KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */ | 229 | {KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */ |
@@ -273,15 +271,15 @@ static struct | |||
273 | {KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAY, 1}, /* ( >) */ | 271 | {KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAY, 1}, /* ( >) */ |
274 | {KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1}, /* (<<) */ | 272 | {KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1}, /* (<<) */ |
275 | {KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1}, /* (>>) */ | 273 | {KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1}, /* (>>) */ |
276 | {KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1}, /* ([]) */ | 274 | {KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1}, /* ([]) */ |
277 | {KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PAUSE, 1}, /* ('') */ | 275 | {KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PAUSE, 1}, /* ('') */ |
278 | {KIND_FILTERED, 0xf0, 0x2b, EV_KEY, KEY_PREVIOUS, 1}, /* (<-) */ | 276 | {KIND_FILTERED, 0xf0, 0x2b, EV_KEY, KEY_PREVIOUS, 1}, /* (<-) */ |
279 | {KIND_FILTERED, 0xef, 0x2a, EV_KEY, KEY_NEXT, 1}, /* (>+) */ | 277 | {KIND_FILTERED, 0xef, 0x2a, EV_KEY, KEY_NEXT, 1}, /* (>+) */ |
280 | {KIND_FILTERED, 0xf2, 0x2D, EV_KEY, KEY_INFO, 1}, /* PLAYING */ | 278 | {KIND_FILTERED, 0xf2, 0x2D, EV_KEY, KEY_INFO, 1}, /* PLAYING */ |
281 | {KIND_FILTERED, 0xf3, 0x2E, EV_KEY, KEY_HOME, 1}, /* TOP */ | 279 | {KIND_FILTERED, 0xf3, 0x2E, EV_KEY, KEY_HOME, 1}, /* TOP */ |
282 | {KIND_FILTERED, 0xf4, 0x2F, EV_KEY, KEY_END, 1}, /* END */ | 280 | {KIND_FILTERED, 0xf4, 0x2F, EV_KEY, KEY_END, 1}, /* END */ |
283 | {KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_SELECT, 1}, /* SELECT */ | 281 | {KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_SELECT, 1}, /* SELECT */ |
284 | 282 | ||
285 | {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} | 283 | {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} |
286 | }; | 284 | }; |
287 | 285 | ||
@@ -315,7 +313,7 @@ static void ati_remote_dump(unsigned char *data, unsigned int len) | |||
315 | if ((len == 1) && (data[0] != (unsigned char)0xff) && (data[0] != 0x00)) | 313 | if ((len == 1) && (data[0] != (unsigned char)0xff) && (data[0] != 0x00)) |
316 | warn("Weird byte 0x%02x", data[0]); | 314 | warn("Weird byte 0x%02x", data[0]); |
317 | else if (len == 4) | 315 | else if (len == 4) |
318 | warn("Weird key %02x %02x %02x %02x", | 316 | warn("Weird key %02x %02x %02x %02x", |
319 | data[0], data[1], data[2], data[3]); | 317 | data[0], data[1], data[2], data[3]); |
320 | else | 318 | else |
321 | warn("Weird data, len=%d %02x %02x %02x %02x %02x %02x ...", | 319 | warn("Weird data, len=%d %02x %02x %02x %02x %02x %02x ...", |
@@ -328,25 +326,16 @@ static void ati_remote_dump(unsigned char *data, unsigned int len) | |||
328 | static int ati_remote_open(struct input_dev *inputdev) | 326 | static int ati_remote_open(struct input_dev *inputdev) |
329 | { | 327 | { |
330 | struct ati_remote *ati_remote = inputdev->private; | 328 | struct ati_remote *ati_remote = inputdev->private; |
331 | int retval = 0; | ||
332 | |||
333 | down(&disconnect_sem); | ||
334 | |||
335 | if (ati_remote->open++) | ||
336 | goto exit; | ||
337 | 329 | ||
338 | /* On first open, submit the read urb which was set up previously. */ | 330 | /* On first open, submit the read urb which was set up previously. */ |
339 | ati_remote->irq_urb->dev = ati_remote->udev; | 331 | ati_remote->irq_urb->dev = ati_remote->udev; |
340 | if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) { | 332 | if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) { |
341 | dev_err(&ati_remote->interface->dev, | 333 | dev_err(&ati_remote->interface->dev, |
342 | "%s: usb_submit_urb failed!\n", __FUNCTION__); | 334 | "%s: usb_submit_urb failed!\n", __FUNCTION__); |
343 | ati_remote->open--; | 335 | return -EIO; |
344 | retval = -EIO; | ||
345 | } | 336 | } |
346 | 337 | ||
347 | exit: | 338 | return 0; |
348 | up(&disconnect_sem); | ||
349 | return retval; | ||
350 | } | 339 | } |
351 | 340 | ||
352 | /* | 341 | /* |
@@ -355,9 +344,8 @@ exit: | |||
355 | static void ati_remote_close(struct input_dev *inputdev) | 344 | static void ati_remote_close(struct input_dev *inputdev) |
356 | { | 345 | { |
357 | struct ati_remote *ati_remote = inputdev->private; | 346 | struct ati_remote *ati_remote = inputdev->private; |
358 | 347 | ||
359 | if (!--ati_remote->open) | 348 | usb_kill_urb(ati_remote->irq_urb); |
360 | usb_kill_urb(ati_remote->irq_urb); | ||
361 | } | 349 | } |
362 | 350 | ||
363 | /* | 351 | /* |
@@ -366,13 +354,13 @@ static void ati_remote_close(struct input_dev *inputdev) | |||
366 | static void ati_remote_irq_out(struct urb *urb, struct pt_regs *regs) | 354 | static void ati_remote_irq_out(struct urb *urb, struct pt_regs *regs) |
367 | { | 355 | { |
368 | struct ati_remote *ati_remote = urb->context; | 356 | struct ati_remote *ati_remote = urb->context; |
369 | 357 | ||
370 | if (urb->status) { | 358 | if (urb->status) { |
371 | dev_dbg(&ati_remote->interface->dev, "%s: status %d\n", | 359 | dev_dbg(&ati_remote->interface->dev, "%s: status %d\n", |
372 | __FUNCTION__, urb->status); | 360 | __FUNCTION__, urb->status); |
373 | return; | 361 | return; |
374 | } | 362 | } |
375 | 363 | ||
376 | ati_remote->send_flags |= SEND_FLAG_COMPLETE; | 364 | ati_remote->send_flags |= SEND_FLAG_COMPLETE; |
377 | wmb(); | 365 | wmb(); |
378 | wake_up(&ati_remote->wait); | 366 | wake_up(&ati_remote->wait); |
@@ -380,16 +368,16 @@ static void ati_remote_irq_out(struct urb *urb, struct pt_regs *regs) | |||
380 | 368 | ||
381 | /* | 369 | /* |
382 | * ati_remote_sendpacket | 370 | * ati_remote_sendpacket |
383 | * | 371 | * |
384 | * Used to send device initialization strings | 372 | * Used to send device initialization strings |
385 | */ | 373 | */ |
386 | static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data) | 374 | static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data) |
387 | { | 375 | { |
388 | int retval = 0; | 376 | int retval = 0; |
389 | 377 | ||
390 | /* Set up out_urb */ | 378 | /* Set up out_urb */ |
391 | memcpy(ati_remote->out_urb->transfer_buffer + 1, data, LO(cmd)); | 379 | memcpy(ati_remote->out_urb->transfer_buffer + 1, data, LO(cmd)); |
392 | ((char *) ati_remote->out_urb->transfer_buffer)[0] = HI(cmd); | 380 | ((char *) ati_remote->out_urb->transfer_buffer)[0] = HI(cmd); |
393 | 381 | ||
394 | ati_remote->out_urb->transfer_buffer_length = LO(cmd) + 1; | 382 | ati_remote->out_urb->transfer_buffer_length = LO(cmd) + 1; |
395 | ati_remote->out_urb->dev = ati_remote->udev; | 383 | ati_remote->out_urb->dev = ati_remote->udev; |
@@ -397,17 +385,17 @@ static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigne | |||
397 | 385 | ||
398 | retval = usb_submit_urb(ati_remote->out_urb, GFP_ATOMIC); | 386 | retval = usb_submit_urb(ati_remote->out_urb, GFP_ATOMIC); |
399 | if (retval) { | 387 | if (retval) { |
400 | dev_dbg(&ati_remote->interface->dev, | 388 | dev_dbg(&ati_remote->interface->dev, |
401 | "sendpacket: usb_submit_urb failed: %d\n", retval); | 389 | "sendpacket: usb_submit_urb failed: %d\n", retval); |
402 | return retval; | 390 | return retval; |
403 | } | 391 | } |
404 | 392 | ||
405 | wait_event_timeout(ati_remote->wait, | 393 | wait_event_timeout(ati_remote->wait, |
406 | ((ati_remote->out_urb->status != -EINPROGRESS) || | 394 | ((ati_remote->out_urb->status != -EINPROGRESS) || |
407 | (ati_remote->send_flags & SEND_FLAG_COMPLETE)), | 395 | (ati_remote->send_flags & SEND_FLAG_COMPLETE)), |
408 | HZ); | 396 | HZ); |
409 | usb_kill_urb(ati_remote->out_urb); | 397 | usb_kill_urb(ati_remote->out_urb); |
410 | 398 | ||
411 | return retval; | 399 | return retval; |
412 | } | 400 | } |
413 | 401 | ||
@@ -419,15 +407,15 @@ static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) | |||
419 | int i; | 407 | int i; |
420 | 408 | ||
421 | for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) { | 409 | for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) { |
422 | /* | 410 | /* |
423 | * Decide if the table entry matches the remote input. | 411 | * Decide if the table entry matches the remote input. |
424 | */ | 412 | */ |
425 | if ((((ati_remote_tbl[i].data1 & 0x0f) == (d1 & 0x0f))) && | 413 | if ((((ati_remote_tbl[i].data1 & 0x0f) == (d1 & 0x0f))) && |
426 | ((((ati_remote_tbl[i].data1 >> 4) - | 414 | ((((ati_remote_tbl[i].data1 >> 4) - |
427 | (d1 >> 4) + rem) & 0x0f) == 0x0f) && | 415 | (d1 >> 4) + rem) & 0x0f) == 0x0f) && |
428 | (ati_remote_tbl[i].data2 == d2)) | 416 | (ati_remote_tbl[i].data2 == d2)) |
429 | return i; | 417 | return i; |
430 | 418 | ||
431 | } | 419 | } |
432 | return -1; | 420 | return -1; |
433 | } | 421 | } |
@@ -435,16 +423,16 @@ static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) | |||
435 | /* | 423 | /* |
436 | * ati_remote_report_input | 424 | * ati_remote_report_input |
437 | */ | 425 | */ |
438 | static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | 426 | static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) |
439 | { | 427 | { |
440 | struct ati_remote *ati_remote = urb->context; | 428 | struct ati_remote *ati_remote = urb->context; |
441 | unsigned char *data= ati_remote->inbuf; | 429 | unsigned char *data= ati_remote->inbuf; |
442 | struct input_dev *dev = &ati_remote->idev; | 430 | struct input_dev *dev = &ati_remote->idev; |
443 | int index, acc; | 431 | int index, acc; |
444 | int remote_num; | 432 | int remote_num; |
445 | 433 | ||
446 | /* Deal with strange looking inputs */ | 434 | /* Deal with strange looking inputs */ |
447 | if ( (urb->actual_length != 4) || (data[0] != 0x14) || | 435 | if ( (urb->actual_length != 4) || (data[0] != 0x14) || |
448 | ((data[3] & 0x0f) != 0x00) ) { | 436 | ((data[3] & 0x0f) != 0x00) ) { |
449 | ati_remote_dump(data, urb->actual_length); | 437 | ati_remote_dump(data, urb->actual_length); |
450 | return; | 438 | return; |
@@ -453,7 +441,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | |||
453 | /* Mask unwanted remote channels. */ | 441 | /* Mask unwanted remote channels. */ |
454 | /* note: remote_num is 0-based, channel 1 on remote == 0 here */ | 442 | /* note: remote_num is 0-based, channel 1 on remote == 0 here */ |
455 | remote_num = (data[3] >> 4) & 0x0f; | 443 | remote_num = (data[3] >> 4) & 0x0f; |
456 | if (channel_mask & (1 << (remote_num + 1))) { | 444 | if (channel_mask & (1 << (remote_num + 1))) { |
457 | dbginfo(&ati_remote->interface->dev, | 445 | dbginfo(&ati_remote->interface->dev, |
458 | "Masked input from channel 0x%02x: data %02x,%02x, mask= 0x%02lx\n", | 446 | "Masked input from channel 0x%02x: data %02x,%02x, mask= 0x%02lx\n", |
459 | remote_num, data[1], data[2], channel_mask); | 447 | remote_num, data[1], data[2], channel_mask); |
@@ -463,37 +451,36 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | |||
463 | /* Look up event code index in translation table */ | 451 | /* Look up event code index in translation table */ |
464 | index = ati_remote_event_lookup(remote_num, data[1], data[2]); | 452 | index = ati_remote_event_lookup(remote_num, data[1], data[2]); |
465 | if (index < 0) { | 453 | if (index < 0) { |
466 | dev_warn(&ati_remote->interface->dev, | 454 | dev_warn(&ati_remote->interface->dev, |
467 | "Unknown input from channel 0x%02x: data %02x,%02x\n", | 455 | "Unknown input from channel 0x%02x: data %02x,%02x\n", |
468 | remote_num, data[1], data[2]); | 456 | remote_num, data[1], data[2]); |
469 | return; | 457 | return; |
470 | } | 458 | } |
471 | dbginfo(&ati_remote->interface->dev, | 459 | dbginfo(&ati_remote->interface->dev, |
472 | "channel 0x%02x; data %02x,%02x; index %d; keycode %d\n", | 460 | "channel 0x%02x; data %02x,%02x; index %d; keycode %d\n", |
473 | remote_num, data[1], data[2], index, ati_remote_tbl[index].code); | 461 | remote_num, data[1], data[2], index, ati_remote_tbl[index].code); |
474 | 462 | ||
475 | if (ati_remote_tbl[index].kind == KIND_LITERAL) { | 463 | if (ati_remote_tbl[index].kind == KIND_LITERAL) { |
476 | input_regs(dev, regs); | 464 | input_regs(dev, regs); |
477 | input_event(dev, ati_remote_tbl[index].type, | 465 | input_event(dev, ati_remote_tbl[index].type, |
478 | ati_remote_tbl[index].code, | 466 | ati_remote_tbl[index].code, |
479 | ati_remote_tbl[index].value); | 467 | ati_remote_tbl[index].value); |
480 | input_sync(dev); | 468 | input_sync(dev); |
481 | 469 | ||
482 | ati_remote->old_jiffies = jiffies; | 470 | ati_remote->old_jiffies = jiffies; |
483 | return; | 471 | return; |
484 | } | 472 | } |
485 | 473 | ||
486 | if (ati_remote_tbl[index].kind == KIND_FILTERED) { | 474 | if (ati_remote_tbl[index].kind == KIND_FILTERED) { |
487 | /* Filter duplicate events which happen "too close" together. */ | 475 | /* Filter duplicate events which happen "too close" together. */ |
488 | if ((ati_remote->old_data[0] == data[1]) && | 476 | if ((ati_remote->old_data[0] == data[1]) && |
489 | (ati_remote->old_data[1] == data[2]) && | 477 | (ati_remote->old_data[1] == data[2]) && |
490 | ((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) { | 478 | ((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) { |
491 | ati_remote->repeat_count++; | 479 | ati_remote->repeat_count++; |
492 | } | 480 | } else { |
493 | else { | ||
494 | ati_remote->repeat_count = 0; | 481 | ati_remote->repeat_count = 0; |
495 | } | 482 | } |
496 | 483 | ||
497 | ati_remote->old_data[0] = data[1]; | 484 | ati_remote->old_data[0] = data[1]; |
498 | ati_remote->old_data[1] = data[2]; | 485 | ati_remote->old_data[1] = data[2]; |
499 | ati_remote->old_jiffies = jiffies; | 486 | ati_remote->old_jiffies = jiffies; |
@@ -501,7 +488,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | |||
501 | if ((ati_remote->repeat_count > 0) | 488 | if ((ati_remote->repeat_count > 0) |
502 | && (ati_remote->repeat_count < 5)) | 489 | && (ati_remote->repeat_count < 5)) |
503 | return; | 490 | return; |
504 | 491 | ||
505 | 492 | ||
506 | input_regs(dev, regs); | 493 | input_regs(dev, regs); |
507 | input_event(dev, ati_remote_tbl[index].type, | 494 | input_event(dev, ati_remote_tbl[index].type, |
@@ -511,13 +498,13 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | |||
511 | input_sync(dev); | 498 | input_sync(dev); |
512 | 499 | ||
513 | return; | 500 | return; |
514 | } | 501 | } |
515 | 502 | ||
516 | /* | 503 | /* |
517 | * Other event kinds are from the directional control pad, and have an | 504 | * Other event kinds are from the directional control pad, and have an |
518 | * acceleration factor applied to them. Without this acceleration, the | 505 | * acceleration factor applied to them. Without this acceleration, the |
519 | * control pad is mostly unusable. | 506 | * control pad is mostly unusable. |
520 | * | 507 | * |
521 | * If elapsed time since last event is > 1/4 second, user "stopped", | 508 | * If elapsed time since last event is > 1/4 second, user "stopped", |
522 | * so reset acceleration. Otherwise, user is probably holding the control | 509 | * so reset acceleration. Otherwise, user is probably holding the control |
523 | * pad down, so we increase acceleration, ramping up over two seconds to | 510 | * pad down, so we increase acceleration, ramping up over two seconds to |
@@ -559,7 +546,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | |||
559 | input_report_rel(dev, REL_Y, acc); | 546 | input_report_rel(dev, REL_Y, acc); |
560 | break; | 547 | break; |
561 | default: | 548 | default: |
562 | dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", | 549 | dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", |
563 | ati_remote_tbl[index].kind); | 550 | ati_remote_tbl[index].kind); |
564 | } | 551 | } |
565 | input_sync(dev); | 552 | input_sync(dev); |
@@ -586,12 +573,12 @@ static void ati_remote_irq_in(struct urb *urb, struct pt_regs *regs) | |||
586 | case -ESHUTDOWN: | 573 | case -ESHUTDOWN: |
587 | dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n", | 574 | dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n", |
588 | __FUNCTION__); | 575 | __FUNCTION__); |
589 | return; | 576 | return; |
590 | default: /* error */ | 577 | default: /* error */ |
591 | dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n", | 578 | dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n", |
592 | __FUNCTION__, urb->status); | 579 | __FUNCTION__, urb->status); |
593 | } | 580 | } |
594 | 581 | ||
595 | retval = usb_submit_urb(urb, SLAB_ATOMIC); | 582 | retval = usb_submit_urb(urb, SLAB_ATOMIC); |
596 | if (retval) | 583 | if (retval) |
597 | dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n", | 584 | dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n", |
@@ -603,8 +590,6 @@ static void ati_remote_irq_in(struct urb *urb, struct pt_regs *regs) | |||
603 | */ | 590 | */ |
604 | static void ati_remote_delete(struct ati_remote *ati_remote) | 591 | static void ati_remote_delete(struct ati_remote *ati_remote) |
605 | { | 592 | { |
606 | if (!ati_remote) return; | ||
607 | |||
608 | if (ati_remote->irq_urb) | 593 | if (ati_remote->irq_urb) |
609 | usb_kill_urb(ati_remote->irq_urb); | 594 | usb_kill_urb(ati_remote->irq_urb); |
610 | 595 | ||
@@ -614,16 +599,16 @@ static void ati_remote_delete(struct ati_remote *ati_remote) | |||
614 | input_unregister_device(&ati_remote->idev); | 599 | input_unregister_device(&ati_remote->idev); |
615 | 600 | ||
616 | if (ati_remote->inbuf) | 601 | if (ati_remote->inbuf) |
617 | usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, | 602 | usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, |
618 | ati_remote->inbuf, ati_remote->inbuf_dma); | 603 | ati_remote->inbuf, ati_remote->inbuf_dma); |
619 | 604 | ||
620 | if (ati_remote->outbuf) | 605 | if (ati_remote->outbuf) |
621 | usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, | 606 | usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, |
622 | ati_remote->outbuf, ati_remote->outbuf_dma); | 607 | ati_remote->outbuf, ati_remote->outbuf_dma); |
623 | 608 | ||
624 | if (ati_remote->irq_urb) | 609 | if (ati_remote->irq_urb) |
625 | usb_free_urb(ati_remote->irq_urb); | 610 | usb_free_urb(ati_remote->irq_urb); |
626 | 611 | ||
627 | if (ati_remote->out_urb) | 612 | if (ati_remote->out_urb) |
628 | usb_free_urb(ati_remote->out_urb); | 613 | usb_free_urb(ati_remote->out_urb); |
629 | 614 | ||
@@ -636,51 +621,52 @@ static void ati_remote_input_init(struct ati_remote *ati_remote) | |||
636 | int i; | 621 | int i; |
637 | 622 | ||
638 | idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | 623 | idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); |
639 | idev->keybit[LONG(BTN_MOUSE)] = ( BIT(BTN_LEFT) | BIT(BTN_RIGHT) | | 624 | idev->keybit[LONG(BTN_MOUSE)] = ( BIT(BTN_LEFT) | BIT(BTN_RIGHT) | |
640 | BIT(BTN_SIDE) | BIT(BTN_EXTRA) ); | 625 | BIT(BTN_SIDE) | BIT(BTN_EXTRA) ); |
641 | idev->relbit[0] = BIT(REL_X) | BIT(REL_Y); | 626 | idev->relbit[0] = BIT(REL_X) | BIT(REL_Y); |
642 | for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) | 627 | for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) |
643 | if (ati_remote_tbl[i].type == EV_KEY) | 628 | if (ati_remote_tbl[i].type == EV_KEY) |
644 | set_bit(ati_remote_tbl[i].code, idev->keybit); | 629 | set_bit(ati_remote_tbl[i].code, idev->keybit); |
645 | 630 | ||
646 | idev->private = ati_remote; | 631 | idev->private = ati_remote; |
647 | idev->open = ati_remote_open; | 632 | idev->open = ati_remote_open; |
648 | idev->close = ati_remote_close; | 633 | idev->close = ati_remote_close; |
649 | 634 | ||
650 | idev->name = ati_remote->name; | 635 | idev->name = ati_remote->name; |
651 | idev->phys = ati_remote->phys; | 636 | idev->phys = ati_remote->phys; |
652 | 637 | ||
653 | idev->id.bustype = BUS_USB; | 638 | idev->id.bustype = BUS_USB; |
654 | idev->id.vendor = le16_to_cpu(ati_remote->udev->descriptor.idVendor); | 639 | idev->id.vendor = le16_to_cpu(ati_remote->udev->descriptor.idVendor); |
655 | idev->id.product = le16_to_cpu(ati_remote->udev->descriptor.idProduct); | 640 | idev->id.product = le16_to_cpu(ati_remote->udev->descriptor.idProduct); |
656 | idev->id.version = le16_to_cpu(ati_remote->udev->descriptor.bcdDevice); | 641 | idev->id.version = le16_to_cpu(ati_remote->udev->descriptor.bcdDevice); |
642 | idev->dev = &(ati_remote->udev->dev); | ||
657 | } | 643 | } |
658 | 644 | ||
659 | static int ati_remote_initialize(struct ati_remote *ati_remote) | 645 | static int ati_remote_initialize(struct ati_remote *ati_remote) |
660 | { | 646 | { |
661 | struct usb_device *udev = ati_remote->udev; | 647 | struct usb_device *udev = ati_remote->udev; |
662 | int pipe, maxp; | 648 | int pipe, maxp; |
663 | 649 | ||
664 | init_waitqueue_head(&ati_remote->wait); | 650 | init_waitqueue_head(&ati_remote->wait); |
665 | 651 | ||
666 | /* Set up irq_urb */ | 652 | /* Set up irq_urb */ |
667 | pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress); | 653 | pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress); |
668 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | 654 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); |
669 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; | 655 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; |
670 | 656 | ||
671 | usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf, | 657 | usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf, |
672 | maxp, ati_remote_irq_in, ati_remote, | 658 | maxp, ati_remote_irq_in, ati_remote, |
673 | ati_remote->endpoint_in->bInterval); | 659 | ati_remote->endpoint_in->bInterval); |
674 | ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma; | 660 | ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma; |
675 | ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 661 | ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
676 | 662 | ||
677 | /* Set up out_urb */ | 663 | /* Set up out_urb */ |
678 | pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress); | 664 | pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress); |
679 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | 665 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); |
680 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; | 666 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; |
681 | 667 | ||
682 | usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf, | 668 | usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf, |
683 | maxp, ati_remote_irq_out, ati_remote, | 669 | maxp, ati_remote_irq_out, ati_remote, |
684 | ati_remote->endpoint_out->bInterval); | 670 | ati_remote->endpoint_out->bInterval); |
685 | ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma; | 671 | ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma; |
686 | ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 672 | ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
@@ -688,11 +674,11 @@ static int ati_remote_initialize(struct ati_remote *ati_remote) | |||
688 | /* send initialization strings */ | 674 | /* send initialization strings */ |
689 | if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) || | 675 | if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) || |
690 | (ati_remote_sendpacket(ati_remote, 0x8007, init2))) { | 676 | (ati_remote_sendpacket(ati_remote, 0x8007, init2))) { |
691 | dev_err(&ati_remote->interface->dev, | 677 | dev_err(&ati_remote->interface->dev, |
692 | "Initializing ati_remote hardware failed.\n"); | 678 | "Initializing ati_remote hardware failed.\n"); |
693 | return 1; | 679 | return 1; |
694 | } | 680 | } |
695 | 681 | ||
696 | return 0; | 682 | return 0; |
697 | } | 683 | } |
698 | 684 | ||
@@ -769,7 +755,7 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de | |||
769 | 755 | ||
770 | if (!strlen(ati_remote->name)) | 756 | if (!strlen(ati_remote->name)) |
771 | sprintf(ati_remote->name, DRIVER_DESC "(%04x,%04x)", | 757 | sprintf(ati_remote->name, DRIVER_DESC "(%04x,%04x)", |
772 | le16_to_cpu(ati_remote->udev->descriptor.idVendor), | 758 | le16_to_cpu(ati_remote->udev->descriptor.idVendor), |
773 | le16_to_cpu(ati_remote->udev->descriptor.idProduct)); | 759 | le16_to_cpu(ati_remote->udev->descriptor.idProduct)); |
774 | 760 | ||
775 | /* Device Hardware Initialization - fills in ati_remote->idev from udev. */ | 761 | /* Device Hardware Initialization - fills in ati_remote->idev from udev. */ |
@@ -781,11 +767,11 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de | |||
781 | ati_remote_input_init(ati_remote); | 767 | ati_remote_input_init(ati_remote); |
782 | input_register_device(&ati_remote->idev); | 768 | input_register_device(&ati_remote->idev); |
783 | 769 | ||
784 | dev_info(&ati_remote->interface->dev, "Input registered: %s on %s\n", | 770 | dev_info(&ati_remote->interface->dev, "Input registered: %s on %s\n", |
785 | ati_remote->name, path); | 771 | ati_remote->name, path); |
786 | 772 | ||
787 | usb_set_intfdata(interface, ati_remote); | 773 | usb_set_intfdata(interface, ati_remote); |
788 | 774 | ||
789 | error: | 775 | error: |
790 | if (retval) | 776 | if (retval) |
791 | ati_remote_delete(ati_remote); | 777 | ati_remote_delete(ati_remote); |
@@ -800,18 +786,14 @@ static void ati_remote_disconnect(struct usb_interface *interface) | |||
800 | { | 786 | { |
801 | struct ati_remote *ati_remote; | 787 | struct ati_remote *ati_remote; |
802 | 788 | ||
803 | down(&disconnect_sem); | ||
804 | |||
805 | ati_remote = usb_get_intfdata(interface); | 789 | ati_remote = usb_get_intfdata(interface); |
806 | usb_set_intfdata(interface, NULL); | 790 | usb_set_intfdata(interface, NULL); |
807 | if (!ati_remote) { | 791 | if (!ati_remote) { |
808 | warn("%s - null device?\n", __FUNCTION__); | 792 | warn("%s - null device?\n", __FUNCTION__); |
809 | return; | 793 | return; |
810 | } | 794 | } |
811 | |||
812 | ati_remote_delete(ati_remote); | ||
813 | 795 | ||
814 | up(&disconnect_sem); | 796 | ati_remote_delete(ati_remote); |
815 | } | 797 | } |
816 | 798 | ||
817 | /* | 799 | /* |
@@ -820,7 +802,7 @@ static void ati_remote_disconnect(struct usb_interface *interface) | |||
820 | static int __init ati_remote_init(void) | 802 | static int __init ati_remote_init(void) |
821 | { | 803 | { |
822 | int result; | 804 | int result; |
823 | 805 | ||
824 | result = usb_register(&ati_remote_driver); | 806 | result = usb_register(&ati_remote_driver); |
825 | if (result) | 807 | if (result) |
826 | err("usb_register error #%d\n", result); | 808 | err("usb_register error #%d\n", result); |
@@ -838,8 +820,8 @@ static void __exit ati_remote_exit(void) | |||
838 | usb_deregister(&ati_remote_driver); | 820 | usb_deregister(&ati_remote_driver); |
839 | } | 821 | } |
840 | 822 | ||
841 | /* | 823 | /* |
842 | * module specification | 824 | * module specification |
843 | */ | 825 | */ |
844 | 826 | ||
845 | module_init(ati_remote_init); | 827 | module_init(ati_remote_init); |
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 740dec1f521d..100b49bd1d3e 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c | |||
@@ -232,7 +232,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign | |||
232 | report->size += parser->global.report_size * parser->global.report_count; | 232 | report->size += parser->global.report_size * parser->global.report_count; |
233 | 233 | ||
234 | if (!parser->local.usage_index) /* Ignore padding fields */ | 234 | if (!parser->local.usage_index) /* Ignore padding fields */ |
235 | return 0; | 235 | return 0; |
236 | 236 | ||
237 | usages = max_t(int, parser->local.usage_index, parser->global.report_count); | 237 | usages = max_t(int, parser->local.usage_index, parser->global.report_count); |
238 | 238 | ||
@@ -765,7 +765,7 @@ static __inline__ __u32 s32ton(__s32 value, unsigned n) | |||
765 | static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) | 765 | static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) |
766 | { | 766 | { |
767 | report += (offset >> 5) << 2; offset &= 31; | 767 | report += (offset >> 5) << 2; offset &= 31; |
768 | return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1 << n) - 1); | 768 | return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1ULL << n) - 1); |
769 | } | 769 | } |
770 | 770 | ||
771 | static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) | 771 | static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) |
@@ -1233,6 +1233,13 @@ int hid_wait_io(struct hid_device *hid) | |||
1233 | return 0; | 1233 | return 0; |
1234 | } | 1234 | } |
1235 | 1235 | ||
1236 | static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle) | ||
1237 | { | ||
1238 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
1239 | HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (idle << 8) | report, | ||
1240 | ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
1241 | } | ||
1242 | |||
1236 | static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, | 1243 | static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, |
1237 | unsigned char type, void *buf, int size) | 1244 | unsigned char type, void *buf, int size) |
1238 | { | 1245 | { |
@@ -1301,10 +1308,6 @@ void hid_init_reports(struct hid_device *hid) | |||
1301 | 1308 | ||
1302 | if (err) | 1309 | if (err) |
1303 | warn("timeout initializing reports\n"); | 1310 | warn("timeout initializing reports\n"); |
1304 | |||
1305 | usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0), | ||
1306 | HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, | ||
1307 | hid->ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
1308 | } | 1311 | } |
1309 | 1312 | ||
1310 | #define USB_VENDOR_ID_WACOM 0x056a | 1313 | #define USB_VENDOR_ID_WACOM 0x056a |
@@ -1318,6 +1321,10 @@ void hid_init_reports(struct hid_device *hid) | |||
1318 | #define USB_DEVICE_ID_WACOM_INTUOS3 0x00B0 | 1321 | #define USB_DEVICE_ID_WACOM_INTUOS3 0x00B0 |
1319 | #define USB_DEVICE_ID_WACOM_CINTIQ 0x003F | 1322 | #define USB_DEVICE_ID_WACOM_CINTIQ 0x003F |
1320 | 1323 | ||
1324 | #define USB_VENDOR_ID_ACECAD 0x0460 | ||
1325 | #define USB_DEVICE_ID_ACECAD_FLAIR 0x0004 | ||
1326 | #define USB_DEVICE_ID_ACECAD_302 0x0008 | ||
1327 | |||
1321 | #define USB_VENDOR_ID_KBGEAR 0x084e | 1328 | #define USB_VENDOR_ID_KBGEAR 0x084e |
1322 | #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 | 1329 | #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 |
1323 | 1330 | ||
@@ -1502,6 +1509,9 @@ static struct hid_blacklist { | |||
1502 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, | 1509 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, |
1503 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, | 1510 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, |
1504 | 1511 | ||
1512 | { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE }, | ||
1513 | { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE }, | ||
1514 | |||
1505 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, | 1515 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, |
1506 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, | 1516 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, |
1507 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, | 1517 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, |
@@ -1590,6 +1600,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
1590 | return NULL; | 1600 | return NULL; |
1591 | } | 1601 | } |
1592 | 1602 | ||
1603 | hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0); | ||
1604 | |||
1593 | if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) { | 1605 | if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) { |
1594 | dbg("reading report descriptor failed"); | 1606 | dbg("reading report descriptor failed"); |
1595 | kfree(rdesc); | 1607 | kfree(rdesc); |
@@ -1635,7 +1647,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
1635 | /* Change the polling interval of mice. */ | 1647 | /* Change the polling interval of mice. */ |
1636 | if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) | 1648 | if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) |
1637 | interval = hid_mousepoll_interval; | 1649 | interval = hid_mousepoll_interval; |
1638 | 1650 | ||
1639 | if (endpoint->bEndpointAddress & USB_DIR_IN) { | 1651 | if (endpoint->bEndpointAddress & USB_DIR_IN) { |
1640 | if (hid->urbin) | 1652 | if (hid->urbin) |
1641 | continue; | 1653 | continue; |
diff --git a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h index 2b91705740a7..52437e5e2e78 100644 --- a/drivers/usb/input/hid-debug.h +++ b/drivers/usb/input/hid-debug.h | |||
@@ -67,7 +67,7 @@ static const struct hid_usage_entry hid_usage_table[] = { | |||
67 | {0, 0x44, "Vbry"}, | 67 | {0, 0x44, "Vbry"}, |
68 | {0, 0x45, "Vbrz"}, | 68 | {0, 0x45, "Vbrz"}, |
69 | {0, 0x46, "Vno"}, | 69 | {0, 0x46, "Vno"}, |
70 | {0, 0x80, "SystemControl"}, | 70 | {0, 0x80, "SystemControl"}, |
71 | {0, 0x81, "SystemPowerDown"}, | 71 | {0, 0x81, "SystemPowerDown"}, |
72 | {0, 0x82, "SystemSleep"}, | 72 | {0, 0x82, "SystemSleep"}, |
73 | {0, 0x83, "SystemWakeUp"}, | 73 | {0, 0x83, "SystemWakeUp"}, |
@@ -347,7 +347,7 @@ __inline__ static void tab(int n) { | |||
347 | 347 | ||
348 | static void hid_dump_field(struct hid_field *field, int n) { | 348 | static void hid_dump_field(struct hid_field *field, int n) { |
349 | int j; | 349 | int j; |
350 | 350 | ||
351 | if (field->physical) { | 351 | if (field->physical) { |
352 | tab(n); | 352 | tab(n); |
353 | printk("Physical("); | 353 | printk("Physical("); |
@@ -408,7 +408,7 @@ static void hid_dump_field(struct hid_field *field, int n) { | |||
408 | printk("%s", units[sys][i]); | 408 | printk("%s", units[sys][i]); |
409 | if(nibble != 1) { | 409 | if(nibble != 1) { |
410 | /* This is a _signed_ nibble(!) */ | 410 | /* This is a _signed_ nibble(!) */ |
411 | 411 | ||
412 | int val = nibble & 0x7; | 412 | int val = nibble & 0x7; |
413 | if(nibble & 0x08) | 413 | if(nibble & 0x08) |
414 | val = -((0x7 & ~val) +1); | 414 | val = -((0x7 & ~val) +1); |
@@ -443,7 +443,7 @@ static void __attribute__((unused)) hid_dump_device(struct hid_device *device) { | |||
443 | struct list_head *list; | 443 | struct list_head *list; |
444 | unsigned i,k; | 444 | unsigned i,k; |
445 | static char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; | 445 | static char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; |
446 | 446 | ||
447 | for (i = 0; i < HID_REPORT_TYPES; i++) { | 447 | for (i = 0; i < HID_REPORT_TYPES; i++) { |
448 | report_enum = device->report_enum + i; | 448 | report_enum = device->report_enum + i; |
449 | list = report_enum->report_list.next; | 449 | list = report_enum->report_list.next; |
@@ -664,8 +664,8 @@ static char *keys[KEY_MAX + 1] = { | |||
664 | static char *relatives[REL_MAX + 1] = { | 664 | static char *relatives[REL_MAX + 1] = { |
665 | [REL_X] = "X", [REL_Y] = "Y", | 665 | [REL_X] = "X", [REL_Y] = "Y", |
666 | [REL_Z] = "Z", [REL_HWHEEL] = "HWheel", | 666 | [REL_Z] = "Z", [REL_HWHEEL] = "HWheel", |
667 | [REL_DIAL] = "Dial", [REL_WHEEL] = "Wheel", | 667 | [REL_DIAL] = "Dial", [REL_WHEEL] = "Wheel", |
668 | [REL_MISC] = "Misc", | 668 | [REL_MISC] = "Misc", |
669 | }; | 669 | }; |
670 | 670 | ||
671 | static char *absolutes[ABS_MAX + 1] = { | 671 | static char *absolutes[ABS_MAX + 1] = { |
@@ -690,9 +690,9 @@ static char *misc[MSC_MAX + 1] = { | |||
690 | }; | 690 | }; |
691 | 691 | ||
692 | static char *leds[LED_MAX + 1] = { | 692 | static char *leds[LED_MAX + 1] = { |
693 | [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock", | 693 | [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock", |
694 | [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose", | 694 | [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose", |
695 | [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep", | 695 | [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep", |
696 | [LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute", | 696 | [LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute", |
697 | [LED_MISC] = "Misc", | 697 | [LED_MISC] = "Misc", |
698 | }; | 698 | }; |
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 5553c3553e9d..9ac1e9095334 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c | |||
@@ -164,7 +164,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
164 | case HID_GD_X: case HID_GD_Y: case HID_GD_Z: | 164 | case HID_GD_X: case HID_GD_Y: case HID_GD_Z: |
165 | case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ: | 165 | case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ: |
166 | case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL: | 166 | case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL: |
167 | if (field->flags & HID_MAIN_ITEM_RELATIVE) | 167 | if (field->flags & HID_MAIN_ITEM_RELATIVE) |
168 | map_rel(usage->hid & 0xf); | 168 | map_rel(usage->hid & 0xf); |
169 | else | 169 | else |
170 | map_abs(usage->hid & 0xf); | 170 | map_abs(usage->hid & 0xf); |
@@ -297,7 +297,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
297 | case HID_UP_MSVENDOR: | 297 | case HID_UP_MSVENDOR: |
298 | 298 | ||
299 | goto ignore; | 299 | goto ignore; |
300 | 300 | ||
301 | case HID_UP_PID: | 301 | case HID_UP_PID: |
302 | 302 | ||
303 | set_bit(EV_FF, input->evbit); | 303 | set_bit(EV_FF, input->evbit); |
@@ -349,7 +349,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
349 | goto ignore; | 349 | goto ignore; |
350 | 350 | ||
351 | if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) && | 351 | if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) && |
352 | (usage->type == EV_REL) && (usage->code == REL_WHEEL)) | 352 | (usage->type == EV_REL) && (usage->code == REL_WHEEL)) |
353 | set_bit(REL_HWHEEL, bit); | 353 | set_bit(REL_HWHEEL, bit); |
354 | 354 | ||
355 | if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005)) | 355 | if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005)) |
@@ -365,11 +365,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
365 | a = field->logical_minimum = 0; | 365 | a = field->logical_minimum = 0; |
366 | b = field->logical_maximum = 255; | 366 | b = field->logical_maximum = 255; |
367 | } | 367 | } |
368 | 368 | ||
369 | if (field->application == HID_GD_GAMEPAD || field->application == HID_GD_JOYSTICK) | 369 | if (field->application == HID_GD_GAMEPAD || field->application == HID_GD_JOYSTICK) |
370 | input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4); | 370 | input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4); |
371 | else input_set_abs_params(input, usage->code, a, b, 0, 0); | 371 | else input_set_abs_params(input, usage->code, a, b, 0, 0); |
372 | 372 | ||
373 | } | 373 | } |
374 | 374 | ||
375 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { | 375 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { |
@@ -420,7 +420,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct | |||
420 | return; | 420 | return; |
421 | } | 421 | } |
422 | 422 | ||
423 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { | 423 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { |
424 | int hat_dir = usage->hat_dir; | 424 | int hat_dir = usage->hat_dir; |
425 | if (!hat_dir) | 425 | if (!hat_dir) |
426 | hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; | 426 | hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; |
@@ -551,7 +551,7 @@ int hidinput_connect(struct hid_device *hid) | |||
551 | for (i = 0; i < hid->maxcollection; i++) | 551 | for (i = 0; i < hid->maxcollection; i++) |
552 | if (hid->collection[i].type == HID_COLLECTION_APPLICATION || | 552 | if (hid->collection[i].type == HID_COLLECTION_APPLICATION || |
553 | hid->collection[i].type == HID_COLLECTION_PHYSICAL) | 553 | hid->collection[i].type == HID_COLLECTION_PHYSICAL) |
554 | if (IS_INPUT_APPLICATION(hid->collection[i].usage)) | 554 | if (IS_INPUT_APPLICATION(hid->collection[i].usage)) |
555 | break; | 555 | break; |
556 | 556 | ||
557 | if (i == hid->maxcollection) | 557 | if (i == hid->maxcollection) |
@@ -592,7 +592,7 @@ int hidinput_connect(struct hid_device *hid) | |||
592 | for (j = 0; j < report->field[i]->maxusage; j++) | 592 | for (j = 0; j < report->field[i]->maxusage; j++) |
593 | hidinput_configure_usage(hidinput, report->field[i], | 593 | hidinput_configure_usage(hidinput, report->field[i], |
594 | report->field[i]->usage + j); | 594 | report->field[i]->usage + j); |
595 | 595 | ||
596 | if (hid->quirks & HID_QUIRK_MULTI_INPUT) { | 596 | if (hid->quirks & HID_QUIRK_MULTI_INPUT) { |
597 | /* This will leave hidinput NULL, so that it | 597 | /* This will leave hidinput NULL, so that it |
598 | * allocates another one if we have more inputs on | 598 | * allocates another one if we have more inputs on |
diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c index 0d7404bab92f..0c4c77aa31ea 100644 --- a/drivers/usb/input/hid-lgff.c +++ b/drivers/usb/input/hid-lgff.c | |||
@@ -94,7 +94,7 @@ struct lgff_device { | |||
94 | isn't really necessary */ | 94 | isn't really necessary */ |
95 | 95 | ||
96 | unsigned long flags[1]; /* Contains various information about the | 96 | unsigned long flags[1]; /* Contains various information about the |
97 | state of the driver for this device */ | 97 | state of the driver for this device */ |
98 | 98 | ||
99 | struct timer_list timer; | 99 | struct timer_list timer; |
100 | }; | 100 | }; |
@@ -234,7 +234,7 @@ static struct hid_report* hid_lgff_duplicate_report(struct hid_report* report) | |||
234 | kfree(ret); | 234 | kfree(ret); |
235 | return NULL; | 235 | return NULL; |
236 | } | 236 | } |
237 | memset(ret->field[0]->value, 0, sizeof(s32[8])); | 237 | memset(ret->field[0]->value, 0, sizeof(s32[8])); |
238 | 238 | ||
239 | return ret; | 239 | return ret; |
240 | } | 240 | } |
@@ -295,11 +295,11 @@ static int hid_lgff_event(struct hid_device *hid, struct input_dev* input, | |||
295 | unsigned long flags; | 295 | unsigned long flags; |
296 | 296 | ||
297 | if (type != EV_FF) return -EINVAL; | 297 | if (type != EV_FF) return -EINVAL; |
298 | if (!LGFF_CHECK_OWNERSHIP(code, lgff)) return -EACCES; | 298 | if (!LGFF_CHECK_OWNERSHIP(code, lgff)) return -EACCES; |
299 | if (value < 0) return -EINVAL; | 299 | if (value < 0) return -EINVAL; |
300 | 300 | ||
301 | spin_lock_irqsave(&lgff->lock, flags); | 301 | spin_lock_irqsave(&lgff->lock, flags); |
302 | 302 | ||
303 | if (value > 0) { | 303 | if (value > 0) { |
304 | if (test_bit(EFFECT_STARTED, effect->flags)) { | 304 | if (test_bit(EFFECT_STARTED, effect->flags)) { |
305 | spin_unlock_irqrestore(&lgff->lock, flags); | 305 | spin_unlock_irqrestore(&lgff->lock, flags); |
@@ -345,7 +345,7 @@ static int hid_lgff_flush(struct input_dev *dev, struct file *file) | |||
345 | and perform ioctls on the same fd all at the same time */ | 345 | and perform ioctls on the same fd all at the same time */ |
346 | if ( current->pid == lgff->effects[i].owner | 346 | if ( current->pid == lgff->effects[i].owner |
347 | && test_bit(EFFECT_USED, lgff->effects[i].flags)) { | 347 | && test_bit(EFFECT_USED, lgff->effects[i].flags)) { |
348 | 348 | ||
349 | if (hid_lgff_erase(dev, i)) | 349 | if (hid_lgff_erase(dev, i)) |
350 | warn("erase effect %d failed", i); | 350 | warn("erase effect %d failed", i); |
351 | } | 351 | } |
@@ -378,7 +378,7 @@ static int hid_lgff_upload_effect(struct input_dev* input, | |||
378 | struct lgff_effect new; | 378 | struct lgff_effect new; |
379 | int id; | 379 | int id; |
380 | unsigned long flags; | 380 | unsigned long flags; |
381 | 381 | ||
382 | dbg("ioctl rumble"); | 382 | dbg("ioctl rumble"); |
383 | 383 | ||
384 | if (!test_bit(effect->type, input->ffbit)) return -EINVAL; | 384 | if (!test_bit(effect->type, input->ffbit)) return -EINVAL; |
@@ -441,7 +441,7 @@ static void hid_lgff_timer(unsigned long timer_data) | |||
441 | 441 | ||
442 | spin_lock_irqsave(&lgff->lock, flags); | 442 | spin_lock_irqsave(&lgff->lock, flags); |
443 | 443 | ||
444 | for (i=0; i<LGFF_EFFECTS; ++i) { | 444 | for (i=0; i<LGFF_EFFECTS; ++i) { |
445 | struct lgff_effect* effect = lgff->effects +i; | 445 | struct lgff_effect* effect = lgff->effects +i; |
446 | 446 | ||
447 | if (test_bit(EFFECT_PLAYING, effect->flags)) { | 447 | if (test_bit(EFFECT_PLAYING, effect->flags)) { |
@@ -491,7 +491,7 @@ static void hid_lgff_timer(unsigned long timer_data) | |||
491 | set_bit(EFFECT_PLAYING, lgff->effects[i].flags); | 491 | set_bit(EFFECT_PLAYING, lgff->effects[i].flags); |
492 | } | 492 | } |
493 | } | 493 | } |
494 | } | 494 | } |
495 | 495 | ||
496 | #define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff | 496 | #define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff |
497 | 497 | ||
@@ -524,5 +524,5 @@ static void hid_lgff_timer(unsigned long timer_data) | |||
524 | add_timer(&lgff->timer); | 524 | add_timer(&lgff->timer); |
525 | } | 525 | } |
526 | 526 | ||
527 | spin_unlock_irqrestore(&lgff->lock, flags); | 527 | spin_unlock_irqrestore(&lgff->lock, flags); |
528 | } | 528 | } |
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index 6d9329c698d9..c1b6b69bc4a4 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h | |||
@@ -118,7 +118,7 @@ struct hid_item { | |||
118 | #define HID_MAIN_ITEM_CONSTANT 0x001 | 118 | #define HID_MAIN_ITEM_CONSTANT 0x001 |
119 | #define HID_MAIN_ITEM_VARIABLE 0x002 | 119 | #define HID_MAIN_ITEM_VARIABLE 0x002 |
120 | #define HID_MAIN_ITEM_RELATIVE 0x004 | 120 | #define HID_MAIN_ITEM_RELATIVE 0x004 |
121 | #define HID_MAIN_ITEM_WRAP 0x008 | 121 | #define HID_MAIN_ITEM_WRAP 0x008 |
122 | #define HID_MAIN_ITEM_NONLINEAR 0x010 | 122 | #define HID_MAIN_ITEM_NONLINEAR 0x010 |
123 | #define HID_MAIN_ITEM_NO_PREFERRED 0x020 | 123 | #define HID_MAIN_ITEM_NO_PREFERRED 0x020 |
124 | #define HID_MAIN_ITEM_NULL_STATE 0x040 | 124 | #define HID_MAIN_ITEM_NULL_STATE 0x040 |
@@ -172,14 +172,14 @@ struct hid_item { | |||
172 | #define HID_USAGE_PAGE 0xffff0000 | 172 | #define HID_USAGE_PAGE 0xffff0000 |
173 | 173 | ||
174 | #define HID_UP_UNDEFINED 0x00000000 | 174 | #define HID_UP_UNDEFINED 0x00000000 |
175 | #define HID_UP_GENDESK 0x00010000 | 175 | #define HID_UP_GENDESK 0x00010000 |
176 | #define HID_UP_KEYBOARD 0x00070000 | 176 | #define HID_UP_KEYBOARD 0x00070000 |
177 | #define HID_UP_LED 0x00080000 | 177 | #define HID_UP_LED 0x00080000 |
178 | #define HID_UP_BUTTON 0x00090000 | 178 | #define HID_UP_BUTTON 0x00090000 |
179 | #define HID_UP_ORDINAL 0x000a0000 | 179 | #define HID_UP_ORDINAL 0x000a0000 |
180 | #define HID_UP_CONSUMER 0x000c0000 | 180 | #define HID_UP_CONSUMER 0x000c0000 |
181 | #define HID_UP_DIGITIZER 0x000d0000 | 181 | #define HID_UP_DIGITIZER 0x000d0000 |
182 | #define HID_UP_PID 0x000f0000 | 182 | #define HID_UP_PID 0x000f0000 |
183 | #define HID_UP_HPVENDOR 0xff7f0000 | 183 | #define HID_UP_HPVENDOR 0xff7f0000 |
184 | #define HID_UP_MSVENDOR 0xff000000 | 184 | #define HID_UP_MSVENDOR 0xff000000 |
185 | 185 | ||
@@ -406,7 +406,7 @@ struct hid_device { /* device report descriptor */ | |||
406 | dma_addr_t outbuf_dma; /* Output buffer dma */ | 406 | dma_addr_t outbuf_dma; /* Output buffer dma */ |
407 | spinlock_t outlock; /* Output fifo spinlock */ | 407 | spinlock_t outlock; /* Output fifo spinlock */ |
408 | 408 | ||
409 | unsigned claimed; /* Claimed by hidinput, hiddev? */ | 409 | unsigned claimed; /* Claimed by hidinput, hiddev? */ |
410 | unsigned quirks; /* Various quirks the device can pull on us */ | 410 | unsigned quirks; /* Various quirks the device can pull on us */ |
411 | 411 | ||
412 | struct list_head inputs; /* The list of inputs */ | 412 | struct list_head inputs; /* The list of inputs */ |
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c index 96b7c9067951..4c13331b5f41 100644 --- a/drivers/usb/input/hiddev.c +++ b/drivers/usb/input/hiddev.c | |||
@@ -95,7 +95,7 @@ hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) | |||
95 | return NULL; | 95 | return NULL; |
96 | rinfo->report_id = ((struct hid_report *) list)->id; | 96 | rinfo->report_id = ((struct hid_report *) list)->id; |
97 | break; | 97 | break; |
98 | 98 | ||
99 | case HID_REPORT_ID_NEXT: | 99 | case HID_REPORT_ID_NEXT: |
100 | list = (struct list_head *) | 100 | list = (struct list_head *) |
101 | report_enum->report_id_hash[rinfo->report_id & HID_REPORT_ID_MASK]; | 101 | report_enum->report_id_hash[rinfo->report_id & HID_REPORT_ID_MASK]; |
@@ -106,7 +106,7 @@ hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) | |||
106 | return NULL; | 106 | return NULL; |
107 | rinfo->report_id = ((struct hid_report *) list)->id; | 107 | rinfo->report_id = ((struct hid_report *) list)->id; |
108 | break; | 108 | break; |
109 | 109 | ||
110 | default: | 110 | default: |
111 | return NULL; | 111 | return NULL; |
112 | } | 112 | } |
@@ -158,7 +158,7 @@ static void hiddev_send_event(struct hid_device *hid, | |||
158 | if (uref->field_index != HID_FIELD_INDEX_NONE || | 158 | if (uref->field_index != HID_FIELD_INDEX_NONE || |
159 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { | 159 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { |
160 | list->buffer[list->head] = *uref; | 160 | list->buffer[list->head] = *uref; |
161 | list->head = (list->head + 1) & | 161 | list->head = (list->head + 1) & |
162 | (HIDDEV_BUFFER_SIZE - 1); | 162 | (HIDDEV_BUFFER_SIZE - 1); |
163 | kill_fasync(&list->fasync, SIGIO, POLL_IN); | 163 | kill_fasync(&list->fasync, SIGIO, POLL_IN); |
164 | } | 164 | } |
@@ -179,9 +179,9 @@ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, | |||
179 | unsigned type = field->report_type; | 179 | unsigned type = field->report_type; |
180 | struct hiddev_usage_ref uref; | 180 | struct hiddev_usage_ref uref; |
181 | 181 | ||
182 | uref.report_type = | 182 | uref.report_type = |
183 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : | 183 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : |
184 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : | 184 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : |
185 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); | 185 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); |
186 | uref.report_id = field->report->id; | 186 | uref.report_id = field->report->id; |
187 | uref.field_index = field->index; | 187 | uref.field_index = field->index; |
@@ -199,9 +199,9 @@ void hiddev_report_event(struct hid_device *hid, struct hid_report *report) | |||
199 | struct hiddev_usage_ref uref; | 199 | struct hiddev_usage_ref uref; |
200 | 200 | ||
201 | memset(&uref, 0, sizeof(uref)); | 201 | memset(&uref, 0, sizeof(uref)); |
202 | uref.report_type = | 202 | uref.report_type = |
203 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : | 203 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : |
204 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : | 204 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : |
205 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); | 205 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); |
206 | uref.report_id = report->id; | 206 | uref.report_id = report->id; |
207 | uref.field_index = HID_FIELD_INDEX_NONE; | 207 | uref.field_index = HID_FIELD_INDEX_NONE; |
@@ -236,7 +236,7 @@ static int hiddev_release(struct inode * inode, struct file * file) | |||
236 | *listptr = (*listptr)->next; | 236 | *listptr = (*listptr)->next; |
237 | 237 | ||
238 | if (!--list->hiddev->open) { | 238 | if (!--list->hiddev->open) { |
239 | if (list->hiddev->exist) | 239 | if (list->hiddev->exist) |
240 | hid_close(list->hiddev->hid); | 240 | hid_close(list->hiddev->hid); |
241 | else | 241 | else |
242 | kfree(list->hiddev); | 242 | kfree(list->hiddev); |
@@ -303,7 +303,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun | |||
303 | if (list->head == list->tail) { | 303 | if (list->head == list->tail) { |
304 | add_wait_queue(&list->hiddev->wait, &wait); | 304 | add_wait_queue(&list->hiddev->wait, &wait); |
305 | set_current_state(TASK_INTERRUPTIBLE); | 305 | set_current_state(TASK_INTERRUPTIBLE); |
306 | 306 | ||
307 | while (list->head == list->tail) { | 307 | while (list->head == list->tail) { |
308 | if (file->f_flags & O_NONBLOCK) { | 308 | if (file->f_flags & O_NONBLOCK) { |
309 | retval = -EAGAIN; | 309 | retval = -EAGAIN; |
@@ -317,7 +317,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun | |||
317 | retval = -EIO; | 317 | retval = -EIO; |
318 | break; | 318 | break; |
319 | } | 319 | } |
320 | 320 | ||
321 | schedule(); | 321 | schedule(); |
322 | } | 322 | } |
323 | 323 | ||
@@ -329,7 +329,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun | |||
329 | return retval; | 329 | return retval; |
330 | 330 | ||
331 | 331 | ||
332 | while (list->head != list->tail && | 332 | while (list->head != list->tail && |
333 | retval + event_size <= count) { | 333 | retval + event_size <= count) { |
334 | if ((list->flags & HIDDEV_FLAG_UREF) == 0) { | 334 | if ((list->flags & HIDDEV_FLAG_UREF) == 0) { |
335 | if (list->buffer[list->tail].field_index != | 335 | if (list->buffer[list->tail].field_index != |
@@ -405,10 +405,10 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
405 | return -EINVAL; | 405 | return -EINVAL; |
406 | 406 | ||
407 | for (i = 0; i < hid->maxcollection; i++) | 407 | for (i = 0; i < hid->maxcollection; i++) |
408 | if (hid->collection[i].type == | 408 | if (hid->collection[i].type == |
409 | HID_COLLECTION_APPLICATION && arg-- == 0) | 409 | HID_COLLECTION_APPLICATION && arg-- == 0) |
410 | break; | 410 | break; |
411 | 411 | ||
412 | if (i == hid->maxcollection) | 412 | if (i == hid->maxcollection) |
413 | return -EINVAL; | 413 | return -EINVAL; |
414 | 414 | ||
@@ -562,7 +562,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
562 | if (!uref_multi) | 562 | if (!uref_multi) |
563 | return -ENOMEM; | 563 | return -ENOMEM; |
564 | uref = &uref_multi->uref; | 564 | uref = &uref_multi->uref; |
565 | if (copy_from_user(uref, user_arg, sizeof(*uref))) | 565 | if (copy_from_user(uref, user_arg, sizeof(*uref))) |
566 | goto fault; | 566 | goto fault; |
567 | 567 | ||
568 | rinfo.report_type = uref->report_type; | 568 | rinfo.report_type = uref->report_type; |
@@ -595,7 +595,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
595 | return -ENOMEM; | 595 | return -ENOMEM; |
596 | uref = &uref_multi->uref; | 596 | uref = &uref_multi->uref; |
597 | if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { | 597 | if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { |
598 | if (copy_from_user(uref_multi, user_arg, | 598 | if (copy_from_user(uref_multi, user_arg, |
599 | sizeof(*uref_multi))) | 599 | sizeof(*uref_multi))) |
600 | goto fault; | 600 | goto fault; |
601 | } else { | 601 | } else { |
@@ -603,7 +603,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
603 | goto fault; | 603 | goto fault; |
604 | } | 604 | } |
605 | 605 | ||
606 | if (cmd != HIDIOCGUSAGE && | 606 | if (cmd != HIDIOCGUSAGE && |
607 | cmd != HIDIOCGUSAGES && | 607 | cmd != HIDIOCGUSAGES && |
608 | uref->report_type == HID_REPORT_TYPE_INPUT) | 608 | uref->report_type == HID_REPORT_TYPE_INPUT) |
609 | goto inval; | 609 | goto inval; |
@@ -651,16 +651,16 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
651 | return field->usage[uref->usage_index].collection_index; | 651 | return field->usage[uref->usage_index].collection_index; |
652 | case HIDIOCGUSAGES: | 652 | case HIDIOCGUSAGES: |
653 | for (i = 0; i < uref_multi->num_values; i++) | 653 | for (i = 0; i < uref_multi->num_values; i++) |
654 | uref_multi->values[i] = | 654 | uref_multi->values[i] = |
655 | field->value[uref->usage_index + i]; | 655 | field->value[uref->usage_index + i]; |
656 | if (copy_to_user(user_arg, uref_multi, | 656 | if (copy_to_user(user_arg, uref_multi, |
657 | sizeof(*uref_multi))) | 657 | sizeof(*uref_multi))) |
658 | goto fault; | 658 | goto fault; |
659 | goto goodreturn; | 659 | goto goodreturn; |
660 | case HIDIOCSUSAGES: | 660 | case HIDIOCSUSAGES: |
661 | for (i = 0; i < uref_multi->num_values; i++) | 661 | for (i = 0; i < uref_multi->num_values; i++) |
662 | field->value[uref->usage_index + i] = | 662 | field->value[uref->usage_index + i] = |
663 | uref_multi->values[i]; | 663 | uref_multi->values[i]; |
664 | goto goodreturn; | 664 | goto goodreturn; |
665 | } | 665 | } |
666 | 666 | ||
@@ -670,7 +670,7 @@ goodreturn: | |||
670 | fault: | 670 | fault: |
671 | kfree(uref_multi); | 671 | kfree(uref_multi); |
672 | return -EFAULT; | 672 | return -EFAULT; |
673 | inval: | 673 | inval: |
674 | kfree(uref_multi); | 674 | kfree(uref_multi); |
675 | return -EINVAL; | 675 | return -EINVAL; |
676 | 676 | ||
@@ -734,7 +734,7 @@ static struct usb_class_driver hiddev_class = { | |||
734 | .name = "usb/hid/hiddev%d", | 734 | .name = "usb/hid/hiddev%d", |
735 | .fops = &hiddev_fops, | 735 | .fops = &hiddev_fops, |
736 | .mode = S_IFCHR | S_IRUGO | S_IWUSR, | 736 | .mode = S_IFCHR | S_IRUGO | S_IWUSR, |
737 | .minor_base = HIDDEV_MINOR_BASE, | 737 | .minor_base = HIDDEV_MINOR_BASE, |
738 | }; | 738 | }; |
739 | 739 | ||
740 | /* | 740 | /* |
@@ -747,7 +747,7 @@ int hiddev_connect(struct hid_device *hid) | |||
747 | int retval; | 747 | int retval; |
748 | 748 | ||
749 | for (i = 0; i < hid->maxcollection; i++) | 749 | for (i = 0; i < hid->maxcollection; i++) |
750 | if (hid->collection[i].type == | 750 | if (hid->collection[i].type == |
751 | HID_COLLECTION_APPLICATION && | 751 | HID_COLLECTION_APPLICATION && |
752 | !IS_INPUT_APPLICATION(hid->collection[i].usage)) | 752 | !IS_INPUT_APPLICATION(hid->collection[i].usage)) |
753 | break; | 753 | break; |
@@ -755,11 +755,11 @@ int hiddev_connect(struct hid_device *hid) | |||
755 | if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0) | 755 | if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0) |
756 | return -1; | 756 | return -1; |
757 | 757 | ||
758 | if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL))) | 758 | if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL))) |
759 | return -1; | 759 | return -1; |
760 | memset(hiddev, 0, sizeof(struct hiddev)); | 760 | memset(hiddev, 0, sizeof(struct hiddev)); |
761 | 761 | ||
762 | retval = usb_register_dev(hid->intf, &hiddev_class); | 762 | retval = usb_register_dev(hid->intf, &hiddev_class); |
763 | if (retval) { | 763 | if (retval) { |
764 | err("Not able to get a minor for this device."); | 764 | err("Not able to get a minor for this device."); |
765 | kfree(hiddev); | 765 | kfree(hiddev); |
@@ -768,12 +768,12 @@ int hiddev_connect(struct hid_device *hid) | |||
768 | 768 | ||
769 | init_waitqueue_head(&hiddev->wait); | 769 | init_waitqueue_head(&hiddev->wait); |
770 | 770 | ||
771 | hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; | 771 | hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; |
772 | 772 | ||
773 | hiddev->hid = hid; | 773 | hiddev->hid = hid; |
774 | hiddev->exist = 1; | 774 | hiddev->exist = 1; |
775 | 775 | ||
776 | hid->minor = hid->intf->minor; | 776 | hid->minor = hid->intf->minor; |
777 | hid->hiddev = hiddev; | 777 | hid->hiddev = hiddev; |
778 | 778 | ||
779 | return 0; | 779 | return 0; |
@@ -818,7 +818,7 @@ void hiddev_disconnect(struct hid_device *hid) | |||
818 | /* We never attach in this manner, and rely on HID to connect us. This | 818 | /* We never attach in this manner, and rely on HID to connect us. This |
819 | * is why there is no disconnect routine defined in the usb_driver either. | 819 | * is why there is no disconnect routine defined in the usb_driver either. |
820 | */ | 820 | */ |
821 | static int hiddev_usbd_probe(struct usb_interface *intf, | 821 | static int hiddev_usbd_probe(struct usb_interface *intf, |
822 | const struct usb_device_id *hiddev_info) | 822 | const struct usb_device_id *hiddev_info) |
823 | { | 823 | { |
824 | return -ENODEV; | 824 | return -ENODEV; |
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c new file mode 100644 index 000000000000..47dec6a1b344 --- /dev/null +++ b/drivers/usb/input/itmtouch.c | |||
@@ -0,0 +1,268 @@ | |||
1 | /****************************************************************************** | ||
2 | * itmtouch.c -- Driver for ITM touchscreen panel | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation; either version 2 of the | ||
7 | * License, or (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | * General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | * | ||
18 | * Based upon original work by Chris Collins <xfire-itmtouch@xware.cx>. | ||
19 | * | ||
20 | * Kudos to ITM for providing me with the datasheet for the panel, | ||
21 | * even though it was a day later than I had finished writing this | ||
22 | * driver. | ||
23 | * | ||
24 | * It has meant that I've been able to correct my interpretation of the | ||
25 | * protocol packets however. | ||
26 | * | ||
27 | * CC -- 2003/9/29 | ||
28 | * | ||
29 | * History | ||
30 | * 1.0 & 1.1 2003 (CC) vojtech@suse.cz | ||
31 | * Original version for 2.4.x kernels | ||
32 | * | ||
33 | * 1.2 02/03/2005 (HCE) hc@mivu.no | ||
34 | * Complete rewrite to support Linux 2.6.10, thanks to mtouchusb.c for hints. | ||
35 | * Unfortunately no calibration support at this time. | ||
36 | * | ||
37 | * 1.2.1 09/03/2005 (HCE) hc@mivu.no | ||
38 | * Code cleanup and adjusting syntax to start matching kernel standards | ||
39 | * | ||
40 | *****************************************************************************/ | ||
41 | |||
42 | #include <linux/config.h> | ||
43 | |||
44 | #ifdef CONFIG_USB_DEBUG | ||
45 | #define DEBUG | ||
46 | #else | ||
47 | #undef DEBUG | ||
48 | #endif | ||
49 | |||
50 | #include <linux/kernel.h> | ||
51 | #include <linux/slab.h> | ||
52 | #include <linux/input.h> | ||
53 | #include <linux/module.h> | ||
54 | #include <linux/init.h> | ||
55 | #include <linux/usb.h> | ||
56 | |||
57 | /* only an 8 byte buffer necessary for a single packet */ | ||
58 | #define ITM_BUFSIZE 8 | ||
59 | #define PATH_SIZE 64 | ||
60 | |||
61 | #define USB_VENDOR_ID_ITMINC 0x0403 | ||
62 | #define USB_PRODUCT_ID_TOUCHPANEL 0xf9e9 | ||
63 | |||
64 | #define DRIVER_AUTHOR "Hans-Christian Egtvedt <hc@mivu.no>" | ||
65 | #define DRIVER_VERSION "v1.2.1" | ||
66 | #define DRIVER_DESC "USB ITM Inc Touch Panel Driver" | ||
67 | #define DRIVER_LICENSE "GPL" | ||
68 | |||
69 | MODULE_AUTHOR( DRIVER_AUTHOR ); | ||
70 | MODULE_DESCRIPTION( DRIVER_DESC ); | ||
71 | MODULE_LICENSE( DRIVER_LICENSE ); | ||
72 | |||
73 | struct itmtouch_dev { | ||
74 | struct usb_device *usbdev; /* usb device */ | ||
75 | struct input_dev inputdev; /* input device */ | ||
76 | struct urb *readurb; /* urb */ | ||
77 | char rbuf[ITM_BUFSIZE]; /* data */ | ||
78 | int users; | ||
79 | char name[128]; | ||
80 | char phys[64]; | ||
81 | }; | ||
82 | |||
83 | static struct usb_device_id itmtouch_ids [] = { | ||
84 | { USB_DEVICE(USB_VENDOR_ID_ITMINC, USB_PRODUCT_ID_TOUCHPANEL) }, | ||
85 | { } | ||
86 | }; | ||
87 | |||
88 | static void itmtouch_irq(struct urb *urb, struct pt_regs *regs) | ||
89 | { | ||
90 | struct itmtouch_dev * itmtouch = urb->context; | ||
91 | unsigned char *data = urb->transfer_buffer; | ||
92 | struct input_dev *dev = &itmtouch->inputdev; | ||
93 | int retval; | ||
94 | |||
95 | switch (urb->status) { | ||
96 | case 0: | ||
97 | /* success */ | ||
98 | break; | ||
99 | case -ETIMEDOUT: | ||
100 | /* this urb is timing out */ | ||
101 | dbg("%s - urb timed out - was the device unplugged?", | ||
102 | __FUNCTION__); | ||
103 | return; | ||
104 | case -ECONNRESET: | ||
105 | case -ENOENT: | ||
106 | case -ESHUTDOWN: | ||
107 | /* this urb is terminated, clean up */ | ||
108 | dbg("%s - urb shutting down with status: %d", | ||
109 | __FUNCTION__, urb->status); | ||
110 | return; | ||
111 | default: | ||
112 | dbg("%s - nonzero urb status received: %d", | ||
113 | __FUNCTION__, urb->status); | ||
114 | goto exit; | ||
115 | } | ||
116 | |||
117 | input_regs(dev, regs); | ||
118 | |||
119 | /* if pressure has been released, then don't report X/Y */ | ||
120 | if (data[7] & 0x20) { | ||
121 | input_report_abs(dev, ABS_X, (data[0] & 0x1F) << 7 | (data[3] & 0x7F)); | ||
122 | input_report_abs(dev, ABS_Y, (data[1] & 0x1F) << 7 | (data[4] & 0x7F)); | ||
123 | } | ||
124 | |||
125 | input_report_abs(dev, ABS_PRESSURE, (data[2] & 1) << 7 | (data[5] & 0x7F)); | ||
126 | input_report_key(dev, BTN_TOUCH, ~data[7] & 0x20); | ||
127 | input_sync(dev); | ||
128 | |||
129 | exit: | ||
130 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
131 | if (retval) | ||
132 | printk(KERN_ERR "%s - usb_submit_urb failed with result: %d", | ||
133 | __FUNCTION__, retval); | ||
134 | } | ||
135 | |||
136 | static int itmtouch_open(struct input_dev *input) | ||
137 | { | ||
138 | struct itmtouch_dev *itmtouch = input->private; | ||
139 | |||
140 | itmtouch->readurb->dev = itmtouch->usbdev; | ||
141 | |||
142 | if (usb_submit_urb(itmtouch->readurb, GFP_KERNEL)) | ||
143 | return -EIO; | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static void itmtouch_close(struct input_dev *input) | ||
149 | { | ||
150 | struct itmtouch_dev *itmtouch = input->private; | ||
151 | |||
152 | usb_kill_urb(itmtouch->readurb); | ||
153 | } | ||
154 | |||
155 | static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
156 | { | ||
157 | struct itmtouch_dev *itmtouch; | ||
158 | struct usb_host_interface *interface; | ||
159 | struct usb_endpoint_descriptor *endpoint; | ||
160 | struct usb_device *udev = interface_to_usbdev(intf); | ||
161 | unsigned int pipe; | ||
162 | unsigned int maxp; | ||
163 | char path[PATH_SIZE]; | ||
164 | |||
165 | interface = intf->cur_altsetting; | ||
166 | endpoint = &interface->endpoint[0].desc; | ||
167 | |||
168 | if (!(itmtouch = kcalloc(1, sizeof(struct itmtouch_dev), GFP_KERNEL))) { | ||
169 | err("%s - Out of memory.", __FUNCTION__); | ||
170 | return -ENOMEM; | ||
171 | } | ||
172 | |||
173 | itmtouch->usbdev = udev; | ||
174 | |||
175 | itmtouch->inputdev.private = itmtouch; | ||
176 | itmtouch->inputdev.open = itmtouch_open; | ||
177 | itmtouch->inputdev.close = itmtouch_close; | ||
178 | |||
179 | usb_make_path(udev, path, PATH_SIZE); | ||
180 | |||
181 | itmtouch->inputdev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
182 | itmtouch->inputdev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); | ||
183 | itmtouch->inputdev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | ||
184 | |||
185 | itmtouch->inputdev.name = itmtouch->name; | ||
186 | itmtouch->inputdev.phys = itmtouch->phys; | ||
187 | itmtouch->inputdev.id.bustype = BUS_USB; | ||
188 | itmtouch->inputdev.id.vendor = udev->descriptor.idVendor; | ||
189 | itmtouch->inputdev.id.product = udev->descriptor.idProduct; | ||
190 | itmtouch->inputdev.id.version = udev->descriptor.bcdDevice; | ||
191 | itmtouch->inputdev.dev = &intf->dev; | ||
192 | |||
193 | if (!strlen(itmtouch->name)) | ||
194 | sprintf(itmtouch->name, "USB ITM touchscreen"); | ||
195 | |||
196 | /* device limits */ | ||
197 | /* as specified by the ITM datasheet, X and Y are 12bit, | ||
198 | * Z (pressure) is 8 bit. However, the fields are defined up | ||
199 | * to 14 bits for future possible expansion. | ||
200 | */ | ||
201 | input_set_abs_params(&itmtouch->inputdev, ABS_X, 0, 0x0FFF, 2, 0); | ||
202 | input_set_abs_params(&itmtouch->inputdev, ABS_Y, 0, 0x0FFF, 2, 0); | ||
203 | input_set_abs_params(&itmtouch->inputdev, ABS_PRESSURE, 0, 0xFF, 2, 0); | ||
204 | |||
205 | /* initialise the URB so we can read from the transport stream */ | ||
206 | pipe = usb_rcvintpipe(itmtouch->usbdev, endpoint->bEndpointAddress); | ||
207 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | ||
208 | |||
209 | if (maxp > ITM_BUFSIZE) | ||
210 | maxp = ITM_BUFSIZE; | ||
211 | |||
212 | itmtouch->readurb = usb_alloc_urb(0, GFP_KERNEL); | ||
213 | |||
214 | if (!itmtouch->readurb) { | ||
215 | dbg("%s - usb_alloc_urb failed: itmtouch->readurb", __FUNCTION__); | ||
216 | kfree(itmtouch); | ||
217 | return -ENOMEM; | ||
218 | } | ||
219 | |||
220 | usb_fill_int_urb(itmtouch->readurb, itmtouch->usbdev, pipe, itmtouch->rbuf, | ||
221 | maxp, itmtouch_irq, itmtouch, endpoint->bInterval); | ||
222 | |||
223 | input_register_device(&itmtouch->inputdev); | ||
224 | |||
225 | printk(KERN_INFO "itmtouch: %s registered on %s\n", itmtouch->name, path); | ||
226 | usb_set_intfdata(intf, itmtouch); | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static void itmtouch_disconnect(struct usb_interface *intf) | ||
232 | { | ||
233 | struct itmtouch_dev *itmtouch = usb_get_intfdata(intf); | ||
234 | |||
235 | usb_set_intfdata(intf, NULL); | ||
236 | |||
237 | if (itmtouch) { | ||
238 | input_unregister_device(&itmtouch->inputdev); | ||
239 | usb_kill_urb(itmtouch->readurb); | ||
240 | usb_free_urb(itmtouch->readurb); | ||
241 | kfree(itmtouch); | ||
242 | } | ||
243 | } | ||
244 | |||
245 | MODULE_DEVICE_TABLE(usb, itmtouch_ids); | ||
246 | |||
247 | static struct usb_driver itmtouch_driver = { | ||
248 | .owner = THIS_MODULE, | ||
249 | .name = "itmtouch", | ||
250 | .probe = itmtouch_probe, | ||
251 | .disconnect = itmtouch_disconnect, | ||
252 | .id_table = itmtouch_ids, | ||
253 | }; | ||
254 | |||
255 | static int __init itmtouch_init(void) | ||
256 | { | ||
257 | info(DRIVER_DESC " " DRIVER_VERSION); | ||
258 | info(DRIVER_AUTHOR); | ||
259 | return usb_register(&itmtouch_driver); | ||
260 | } | ||
261 | |||
262 | static void __exit itmtouch_exit(void) | ||
263 | { | ||
264 | usb_deregister(&itmtouch_driver); | ||
265 | } | ||
266 | |||
267 | module_init(itmtouch_init); | ||
268 | module_exit(itmtouch_exit); | ||
diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c index a68c5b4e7b37..d2f0f90a9bcd 100644 --- a/drivers/usb/input/kbtab.c +++ b/drivers/usb/input/kbtab.c | |||
@@ -36,7 +36,6 @@ struct kbtab { | |||
36 | struct input_dev dev; | 36 | struct input_dev dev; |
37 | struct usb_device *usbdev; | 37 | struct usb_device *usbdev; |
38 | struct urb *irq; | 38 | struct urb *irq; |
39 | int open; | ||
40 | int x, y; | 39 | int x, y; |
41 | int button; | 40 | int button; |
42 | int pressure; | 41 | int pressure; |
@@ -79,12 +78,12 @@ static void kbtab_irq(struct urb *urb, struct pt_regs *regs) | |||
79 | /*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/ | 78 | /*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/ |
80 | input_report_key(dev, BTN_RIGHT, data[0] & 0x02); | 79 | input_report_key(dev, BTN_RIGHT, data[0] & 0x02); |
81 | 80 | ||
82 | if( -1 == kb_pressure_click){ | 81 | if (-1 == kb_pressure_click) { |
83 | input_report_abs(dev, ABS_PRESSURE, kbtab->pressure); | 82 | input_report_abs(dev, ABS_PRESSURE, kbtab->pressure); |
84 | } else { | 83 | } else { |
85 | input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0); | 84 | input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0); |
86 | }; | 85 | }; |
87 | 86 | ||
88 | input_sync(dev); | 87 | input_sync(dev); |
89 | 88 | ||
90 | exit: | 89 | exit: |
@@ -105,14 +104,9 @@ static int kbtab_open(struct input_dev *dev) | |||
105 | { | 104 | { |
106 | struct kbtab *kbtab = dev->private; | 105 | struct kbtab *kbtab = dev->private; |
107 | 106 | ||
108 | if (kbtab->open++) | ||
109 | return 0; | ||
110 | |||
111 | kbtab->irq->dev = kbtab->usbdev; | 107 | kbtab->irq->dev = kbtab->usbdev; |
112 | if (usb_submit_urb(kbtab->irq, GFP_KERNEL)) { | 108 | if (usb_submit_urb(kbtab->irq, GFP_KERNEL)) |
113 | kbtab->open--; | ||
114 | return -EIO; | 109 | return -EIO; |
115 | } | ||
116 | 110 | ||
117 | return 0; | 111 | return 0; |
118 | } | 112 | } |
@@ -121,8 +115,7 @@ static void kbtab_close(struct input_dev *dev) | |||
121 | { | 115 | { |
122 | struct kbtab *kbtab = dev->private; | 116 | struct kbtab *kbtab = dev->private; |
123 | 117 | ||
124 | if (!--kbtab->open) | 118 | usb_kill_urb(kbtab->irq); |
125 | usb_kill_urb(kbtab->irq); | ||
126 | } | 119 | } |
127 | 120 | ||
128 | static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *id) | 121 | static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *id) |
@@ -161,7 +154,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
161 | kbtab->dev.absmax[ABS_X] = 0x2000; | 154 | kbtab->dev.absmax[ABS_X] = 0x2000; |
162 | kbtab->dev.absmax[ABS_Y] = 0x1750; | 155 | kbtab->dev.absmax[ABS_Y] = 0x1750; |
163 | kbtab->dev.absmax[ABS_PRESSURE] = 0xff; | 156 | kbtab->dev.absmax[ABS_PRESSURE] = 0xff; |
164 | 157 | ||
165 | kbtab->dev.absfuzz[ABS_X] = 4; | 158 | kbtab->dev.absfuzz[ABS_X] = 4; |
166 | kbtab->dev.absfuzz[ABS_Y] = 4; | 159 | kbtab->dev.absfuzz[ABS_Y] = 4; |
167 | 160 | ||
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c index ab1a2a30ce7c..09b5cc7c66de 100644 --- a/drivers/usb/input/mtouchusb.c +++ b/drivers/usb/input/mtouchusb.c | |||
@@ -42,9 +42,9 @@ | |||
42 | #include <linux/config.h> | 42 | #include <linux/config.h> |
43 | 43 | ||
44 | #ifdef CONFIG_USB_DEBUG | 44 | #ifdef CONFIG_USB_DEBUG |
45 | #define DEBUG | 45 | #define DEBUG |
46 | #else | 46 | #else |
47 | #undef DEBUG | 47 | #undef DEBUG |
48 | #endif | 48 | #endif |
49 | 49 | ||
50 | #include <linux/kernel.h> | 50 | #include <linux/kernel.h> |
@@ -93,275 +93,255 @@ module_param(raw_coordinates, bool, S_IRUGO | S_IWUSR); | |||
93 | MODULE_PARM_DESC(raw_coordinates, "report raw coordinate values (y, default) or hardware-calibrated coordinate values (n)"); | 93 | MODULE_PARM_DESC(raw_coordinates, "report raw coordinate values (y, default) or hardware-calibrated coordinate values (n)"); |
94 | 94 | ||
95 | struct mtouch_usb { | 95 | struct mtouch_usb { |
96 | unsigned char *data; | 96 | unsigned char *data; |
97 | dma_addr_t data_dma; | 97 | dma_addr_t data_dma; |
98 | struct urb *irq; | 98 | struct urb *irq; |
99 | struct usb_device *udev; | 99 | struct usb_device *udev; |
100 | struct input_dev input; | 100 | struct input_dev input; |
101 | int open; | 101 | char name[128]; |
102 | char name[128]; | 102 | char phys[64]; |
103 | char phys[64]; | ||
104 | }; | 103 | }; |
105 | 104 | ||
106 | static struct usb_device_id mtouchusb_devices [] = { | 105 | static struct usb_device_id mtouchusb_devices[] = { |
107 | { USB_DEVICE(0x0596, 0x0001) }, | 106 | { USB_DEVICE(0x0596, 0x0001) }, |
108 | { } | 107 | { } |
109 | }; | 108 | }; |
110 | 109 | ||
111 | static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs) | 110 | static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs) |
112 | { | 111 | { |
113 | struct mtouch_usb *mtouch = urb->context; | 112 | struct mtouch_usb *mtouch = urb->context; |
114 | int retval; | 113 | int retval; |
115 | 114 | ||
116 | switch (urb->status) { | 115 | switch (urb->status) { |
117 | case 0: | 116 | case 0: |
118 | /* success */ | 117 | /* success */ |
119 | break; | 118 | break; |
120 | case -ETIMEDOUT: | 119 | case -ETIMEDOUT: |
121 | /* this urb is timing out */ | 120 | /* this urb is timing out */ |
122 | dbg("%s - urb timed out - was the device unplugged?", | 121 | dbg("%s - urb timed out - was the device unplugged?", |
123 | __FUNCTION__); | 122 | __FUNCTION__); |
124 | return; | 123 | return; |
125 | case -ECONNRESET: | 124 | case -ECONNRESET: |
126 | case -ENOENT: | 125 | case -ENOENT: |
127 | case -ESHUTDOWN: | 126 | case -ESHUTDOWN: |
128 | /* this urb is terminated, clean up */ | 127 | /* this urb is terminated, clean up */ |
129 | dbg("%s - urb shutting down with status: %d", | 128 | dbg("%s - urb shutting down with status: %d", |
130 | __FUNCTION__, urb->status); | 129 | __FUNCTION__, urb->status); |
131 | return; | 130 | return; |
132 | default: | 131 | default: |
133 | dbg("%s - nonzero urb status received: %d", | 132 | dbg("%s - nonzero urb status received: %d", |
134 | __FUNCTION__, urb->status); | 133 | __FUNCTION__, urb->status); |
135 | goto exit; | 134 | goto exit; |
136 | } | 135 | } |
137 | 136 | ||
138 | input_regs(&mtouch->input, regs); | 137 | input_regs(&mtouch->input, regs); |
139 | input_report_key(&mtouch->input, BTN_TOUCH, | 138 | input_report_key(&mtouch->input, BTN_TOUCH, |
140 | MTOUCHUSB_GET_TOUCHED(mtouch->data)); | 139 | MTOUCHUSB_GET_TOUCHED(mtouch->data)); |
141 | input_report_abs(&mtouch->input, ABS_X, | 140 | input_report_abs(&mtouch->input, ABS_X, MTOUCHUSB_GET_XC(mtouch->data)); |
142 | MTOUCHUSB_GET_XC(mtouch->data)); | 141 | input_report_abs(&mtouch->input, ABS_Y, |
143 | input_report_abs(&mtouch->input, ABS_Y, | ||
144 | (raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC) | 142 | (raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC) |
145 | - MTOUCHUSB_GET_YC(mtouch->data)); | 143 | - MTOUCHUSB_GET_YC(mtouch->data)); |
146 | input_sync(&mtouch->input); | 144 | input_sync(&mtouch->input); |
147 | 145 | ||
148 | exit: | 146 | exit: |
149 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 147 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
150 | if (retval) | 148 | if (retval) |
151 | err ("%s - usb_submit_urb failed with result: %d", | 149 | err("%s - usb_submit_urb failed with result: %d", |
152 | __FUNCTION__, retval); | 150 | __FUNCTION__, retval); |
153 | } | 151 | } |
154 | 152 | ||
155 | static int mtouchusb_open (struct input_dev *input) | 153 | static int mtouchusb_open(struct input_dev *input) |
156 | { | 154 | { |
157 | struct mtouch_usb *mtouch = input->private; | 155 | struct mtouch_usb *mtouch = input->private; |
158 | 156 | ||
159 | if (mtouch->open++) | 157 | mtouch->irq->dev = mtouch->udev; |
160 | return 0; | ||
161 | 158 | ||
162 | mtouch->irq->dev = mtouch->udev; | 159 | if (usb_submit_urb(mtouch->irq, GFP_ATOMIC)) |
160 | return -EIO; | ||
163 | 161 | ||
164 | if (usb_submit_urb (mtouch->irq, GFP_ATOMIC)) { | 162 | return 0; |
165 | mtouch->open--; | ||
166 | return -EIO; | ||
167 | } | ||
168 | |||
169 | return 0; | ||
170 | } | 163 | } |
171 | 164 | ||
172 | static void mtouchusb_close (struct input_dev *input) | 165 | static void mtouchusb_close(struct input_dev *input) |
173 | { | 166 | { |
174 | struct mtouch_usb *mtouch = input->private; | 167 | struct mtouch_usb *mtouch = input->private; |
175 | 168 | ||
176 | if (!--mtouch->open) | 169 | usb_kill_urb(mtouch->irq); |
177 | usb_kill_urb (mtouch->irq); | ||
178 | } | 170 | } |
179 | 171 | ||
180 | static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) | 172 | static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) |
181 | { | 173 | { |
182 | dbg("%s - called", __FUNCTION__); | 174 | dbg("%s - called", __FUNCTION__); |
183 | 175 | ||
184 | mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_DATA_SIZE, | 176 | mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_DATA_SIZE, |
185 | SLAB_ATOMIC, &mtouch->data_dma); | 177 | SLAB_ATOMIC, &mtouch->data_dma); |
186 | 178 | ||
187 | if (!mtouch->data) | 179 | if (!mtouch->data) |
188 | return -1; | 180 | return -1; |
189 | 181 | ||
190 | return 0; | 182 | return 0; |
191 | } | 183 | } |
192 | 184 | ||
193 | static void mtouchusb_free_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) | 185 | static void mtouchusb_free_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) |
194 | { | 186 | { |
195 | dbg("%s - called", __FUNCTION__); | 187 | dbg("%s - called", __FUNCTION__); |
196 | 188 | ||
197 | if (mtouch->data) | 189 | if (mtouch->data) |
198 | usb_buffer_free(udev, MTOUCHUSB_REPORT_DATA_SIZE, | 190 | usb_buffer_free(udev, MTOUCHUSB_REPORT_DATA_SIZE, |
199 | mtouch->data, mtouch->data_dma); | 191 | mtouch->data, mtouch->data_dma); |
200 | } | 192 | } |
201 | 193 | ||
202 | static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id) | 194 | static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id) |
203 | { | 195 | { |
204 | struct mtouch_usb *mtouch; | 196 | struct mtouch_usb *mtouch; |
205 | struct usb_host_interface *interface; | 197 | struct usb_host_interface *interface; |
206 | struct usb_endpoint_descriptor *endpoint; | 198 | struct usb_endpoint_descriptor *endpoint; |
207 | struct usb_device *udev = interface_to_usbdev (intf); | 199 | struct usb_device *udev = interface_to_usbdev(intf); |
208 | char path[64]; | 200 | char path[64]; |
209 | int nRet; | 201 | int nRet; |
210 | 202 | ||
211 | dbg("%s - called", __FUNCTION__); | 203 | dbg("%s - called", __FUNCTION__); |
212 | 204 | ||
213 | dbg("%s - setting interface", __FUNCTION__); | 205 | dbg("%s - setting interface", __FUNCTION__); |
214 | interface = intf->cur_altsetting; | 206 | interface = intf->cur_altsetting; |
215 | 207 | ||
216 | dbg("%s - setting endpoint", __FUNCTION__); | 208 | dbg("%s - setting endpoint", __FUNCTION__); |
217 | endpoint = &interface->endpoint[0].desc; | 209 | endpoint = &interface->endpoint[0].desc; |
218 | 210 | ||
219 | if (!(mtouch = kmalloc (sizeof (struct mtouch_usb), GFP_KERNEL))) { | 211 | if (!(mtouch = kmalloc(sizeof(struct mtouch_usb), GFP_KERNEL))) { |
220 | err("%s - Out of memory.", __FUNCTION__); | 212 | err("%s - Out of memory.", __FUNCTION__); |
221 | return -ENOMEM; | 213 | return -ENOMEM; |
222 | } | 214 | } |
223 | 215 | ||
224 | memset(mtouch, 0, sizeof(struct mtouch_usb)); | 216 | memset(mtouch, 0, sizeof(struct mtouch_usb)); |
225 | mtouch->udev = udev; | 217 | mtouch->udev = udev; |
226 | 218 | ||
227 | dbg("%s - allocating buffers", __FUNCTION__); | 219 | dbg("%s - allocating buffers", __FUNCTION__); |
228 | if (mtouchusb_alloc_buffers(udev, mtouch)) { | 220 | if (mtouchusb_alloc_buffers(udev, mtouch)) { |
229 | mtouchusb_free_buffers(udev, mtouch); | 221 | mtouchusb_free_buffers(udev, mtouch); |
230 | kfree(mtouch); | 222 | kfree(mtouch); |
231 | return -ENOMEM; | 223 | return -ENOMEM; |
232 | } | 224 | } |
233 | 225 | ||
234 | mtouch->input.private = mtouch; | 226 | mtouch->input.private = mtouch; |
235 | mtouch->input.open = mtouchusb_open; | 227 | mtouch->input.open = mtouchusb_open; |
236 | mtouch->input.close = mtouchusb_close; | 228 | mtouch->input.close = mtouchusb_close; |
237 | 229 | ||
238 | usb_make_path(udev, path, 64); | 230 | usb_make_path(udev, path, 64); |
239 | sprintf(mtouch->phys, "%s/input0", path); | 231 | sprintf(mtouch->phys, "%s/input0", path); |
240 | 232 | ||
241 | mtouch->input.name = mtouch->name; | 233 | mtouch->input.name = mtouch->name; |
242 | mtouch->input.phys = mtouch->phys; | 234 | mtouch->input.phys = mtouch->phys; |
243 | mtouch->input.id.bustype = BUS_USB; | 235 | mtouch->input.id.bustype = BUS_USB; |
244 | mtouch->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor); | 236 | mtouch->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor); |
245 | mtouch->input.id.product = le16_to_cpu(udev->descriptor.idProduct); | 237 | mtouch->input.id.product = le16_to_cpu(udev->descriptor.idProduct); |
246 | mtouch->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); | 238 | mtouch->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); |
247 | mtouch->input.dev = &intf->dev; | 239 | mtouch->input.dev = &intf->dev; |
248 | 240 | ||
249 | mtouch->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | 241 | mtouch->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); |
250 | mtouch->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); | 242 | mtouch->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); |
251 | mtouch->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | 243 | mtouch->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); |
252 | 244 | ||
253 | /* Used to Scale Compensated Data and Flip Y */ | 245 | /* Used to Scale Compensated Data and Flip Y */ |
254 | mtouch->input.absmin[ABS_X] = MTOUCHUSB_MIN_XC; | 246 | mtouch->input.absmin[ABS_X] = MTOUCHUSB_MIN_XC; |
255 | mtouch->input.absmax[ABS_X] = raw_coordinates ? \ | 247 | mtouch->input.absmax[ABS_X] = raw_coordinates ? |
256 | MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC; | 248 | MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC; |
257 | mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ; | 249 | mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ; |
258 | mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT; | 250 | mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT; |
259 | mtouch->input.absmin[ABS_Y] = MTOUCHUSB_MIN_YC; | 251 | mtouch->input.absmin[ABS_Y] = MTOUCHUSB_MIN_YC; |
260 | mtouch->input.absmax[ABS_Y] = raw_coordinates ? \ | 252 | mtouch->input.absmax[ABS_Y] = raw_coordinates ? |
261 | MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC; | 253 | MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC; |
262 | mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ; | 254 | mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ; |
263 | mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT; | 255 | mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT; |
264 | 256 | ||
265 | if (udev->manufacturer) | 257 | if (udev->manufacturer) |
266 | strcat(mtouch->name, udev->manufacturer); | 258 | strcat(mtouch->name, udev->manufacturer); |
267 | if (udev->product) | 259 | if (udev->product) |
268 | sprintf(mtouch->name, "%s %s", mtouch->name, udev->product); | 260 | sprintf(mtouch->name, "%s %s", mtouch->name, udev->product); |
269 | 261 | ||
270 | if (!strlen(mtouch->name)) | 262 | if (!strlen(mtouch->name)) |
271 | sprintf(mtouch->name, "USB Touchscreen %04x:%04x", | 263 | sprintf(mtouch->name, "USB Touchscreen %04x:%04x", |
272 | mtouch->input.id.vendor, mtouch->input.id.product); | 264 | mtouch->input.id.vendor, mtouch->input.id.product); |
273 | 265 | ||
274 | nRet = usb_control_msg(mtouch->udev, | 266 | nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0), |
275 | usb_rcvctrlpipe(udev, 0), | 267 | MTOUCHUSB_RESET, |
276 | MTOUCHUSB_RESET, | 268 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
277 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 269 | 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); |
278 | 1, | 270 | dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", |
279 | 0, | 271 | __FUNCTION__, nRet); |
280 | NULL, | 272 | |
281 | 0, | 273 | dbg("%s - usb_alloc_urb: mtouch->irq", __FUNCTION__); |
282 | USB_CTRL_SET_TIMEOUT); | 274 | mtouch->irq = usb_alloc_urb(0, GFP_KERNEL); |
283 | dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", | 275 | if (!mtouch->irq) { |
284 | __FUNCTION__, nRet); | 276 | dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__); |
285 | 277 | mtouchusb_free_buffers(udev, mtouch); | |
286 | dbg("%s - usb_alloc_urb: mtouch->irq", __FUNCTION__); | 278 | kfree(mtouch); |
287 | mtouch->irq = usb_alloc_urb(0, GFP_KERNEL); | 279 | return -ENOMEM; |
288 | if (!mtouch->irq) { | 280 | } |
289 | dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__); | 281 | |
290 | mtouchusb_free_buffers(udev, mtouch); | 282 | dbg("%s - usb_fill_int_urb", __FUNCTION__); |
291 | kfree(mtouch); | 283 | usb_fill_int_urb(mtouch->irq, mtouch->udev, |
292 | return -ENOMEM; | 284 | usb_rcvintpipe(mtouch->udev, 0x81), |
293 | } | 285 | mtouch->data, MTOUCHUSB_REPORT_DATA_SIZE, |
294 | 286 | mtouchusb_irq, mtouch, endpoint->bInterval); | |
295 | dbg("%s - usb_fill_int_urb", __FUNCTION__); | 287 | |
296 | usb_fill_int_urb(mtouch->irq, | 288 | dbg("%s - input_register_device", __FUNCTION__); |
297 | mtouch->udev, | 289 | input_register_device(&mtouch->input); |
298 | usb_rcvintpipe(mtouch->udev, 0x81), | 290 | |
299 | mtouch->data, | 291 | nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0), |
300 | MTOUCHUSB_REPORT_DATA_SIZE, | 292 | MTOUCHUSB_ASYNC_REPORT, |
301 | mtouchusb_irq, | 293 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
302 | mtouch, | 294 | 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); |
303 | endpoint->bInterval); | 295 | dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", |
304 | 296 | __FUNCTION__, nRet); | |
305 | dbg("%s - input_register_device", __FUNCTION__); | 297 | |
306 | input_register_device(&mtouch->input); | 298 | printk(KERN_INFO "input: %s on %s\n", mtouch->name, path); |
307 | 299 | usb_set_intfdata(intf, mtouch); | |
308 | nRet = usb_control_msg(mtouch->udev, | 300 | |
309 | usb_rcvctrlpipe(udev, 0), | 301 | return 0; |
310 | MTOUCHUSB_ASYNC_REPORT, | ||
311 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
312 | 1, | ||
313 | 1, | ||
314 | NULL, | ||
315 | 0, | ||
316 | USB_CTRL_SET_TIMEOUT); | ||
317 | dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", | ||
318 | __FUNCTION__, nRet); | ||
319 | |||
320 | printk(KERN_INFO "input: %s on %s\n", mtouch->name, path); | ||
321 | usb_set_intfdata(intf, mtouch); | ||
322 | |||
323 | return 0; | ||
324 | } | 302 | } |
325 | 303 | ||
326 | static void mtouchusb_disconnect(struct usb_interface *intf) | 304 | static void mtouchusb_disconnect(struct usb_interface *intf) |
327 | { | 305 | { |
328 | struct mtouch_usb *mtouch = usb_get_intfdata (intf); | 306 | struct mtouch_usb *mtouch = usb_get_intfdata(intf); |
329 | 307 | ||
330 | dbg("%s - called", __FUNCTION__); | 308 | dbg("%s - called", __FUNCTION__); |
331 | usb_set_intfdata(intf, NULL); | 309 | usb_set_intfdata(intf, NULL); |
332 | if (mtouch) { | 310 | if (mtouch) { |
333 | dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__); | 311 | dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__); |
334 | usb_kill_urb(mtouch->irq); | 312 | usb_kill_urb(mtouch->irq); |
335 | input_unregister_device(&mtouch->input); | 313 | input_unregister_device(&mtouch->input); |
336 | usb_free_urb(mtouch->irq); | 314 | usb_free_urb(mtouch->irq); |
337 | mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch); | 315 | mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch); |
338 | kfree(mtouch); | 316 | kfree(mtouch); |
339 | } | 317 | } |
340 | } | 318 | } |
341 | 319 | ||
342 | MODULE_DEVICE_TABLE (usb, mtouchusb_devices); | 320 | MODULE_DEVICE_TABLE(usb, mtouchusb_devices); |
343 | 321 | ||
344 | static struct usb_driver mtouchusb_driver = { | 322 | static struct usb_driver mtouchusb_driver = { |
345 | .owner = THIS_MODULE, | 323 | .owner = THIS_MODULE, |
346 | .name = "mtouchusb", | 324 | .name = "mtouchusb", |
347 | .probe = mtouchusb_probe, | 325 | .probe = mtouchusb_probe, |
348 | .disconnect = mtouchusb_disconnect, | 326 | .disconnect = mtouchusb_disconnect, |
349 | .id_table = mtouchusb_devices, | 327 | .id_table = mtouchusb_devices, |
350 | }; | 328 | }; |
351 | 329 | ||
352 | static int __init mtouchusb_init(void) { | 330 | static int __init mtouchusb_init(void) |
353 | dbg("%s - called", __FUNCTION__); | 331 | { |
354 | return usb_register(&mtouchusb_driver); | 332 | dbg("%s - called", __FUNCTION__); |
333 | return usb_register(&mtouchusb_driver); | ||
355 | } | 334 | } |
356 | 335 | ||
357 | static void __exit mtouchusb_cleanup(void) { | 336 | static void __exit mtouchusb_cleanup(void) |
358 | dbg("%s - called", __FUNCTION__); | 337 | { |
359 | usb_deregister(&mtouchusb_driver); | 338 | dbg("%s - called", __FUNCTION__); |
339 | usb_deregister(&mtouchusb_driver); | ||
360 | } | 340 | } |
361 | 341 | ||
362 | module_init(mtouchusb_init); | 342 | module_init(mtouchusb_init); |
363 | module_exit(mtouchusb_cleanup); | 343 | module_exit(mtouchusb_cleanup); |
364 | 344 | ||
365 | MODULE_AUTHOR( DRIVER_AUTHOR ); | 345 | MODULE_AUTHOR(DRIVER_AUTHOR); |
366 | MODULE_DESCRIPTION( DRIVER_DESC ); | 346 | MODULE_DESCRIPTION(DRIVER_DESC); |
367 | MODULE_LICENSE("GPL"); | 347 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c index 7fa2f9b9fb69..3975b309d55f 100644 --- a/drivers/usb/input/powermate.c +++ b/drivers/usb/input/powermate.c | |||
@@ -10,7 +10,7 @@ | |||
10 | * back to the host when polled by the USB controller. | 10 | * back to the host when polled by the USB controller. |
11 | * | 11 | * |
12 | * Testing with the knob I have has shown that it measures approximately 94 "clicks" | 12 | * Testing with the knob I have has shown that it measures approximately 94 "clicks" |
13 | * for one full rotation. Testing with my High Speed Rotation Actuator (ok, it was | 13 | * for one full rotation. Testing with my High Speed Rotation Actuator (ok, it was |
14 | * a variable speed cordless electric drill) has shown that the device can measure | 14 | * a variable speed cordless electric drill) has shown that the device can measure |
15 | * speeds of up to 7 clicks either clockwise or anticlockwise between pollings from | 15 | * speeds of up to 7 clicks either clockwise or anticlockwise between pollings from |
16 | * the host. If it counts more than 7 clicks before it is polled, it will wrap back | 16 | * the host. If it counts more than 7 clicks before it is polled, it will wrap back |
@@ -120,9 +120,9 @@ exit: | |||
120 | /* Decide if we need to issue a control message and do so. Must be called with pm->lock taken */ | 120 | /* Decide if we need to issue a control message and do so. Must be called with pm->lock taken */ |
121 | static void powermate_sync_state(struct powermate_device *pm) | 121 | static void powermate_sync_state(struct powermate_device *pm) |
122 | { | 122 | { |
123 | if (pm->requires_update == 0) | 123 | if (pm->requires_update == 0) |
124 | return; /* no updates are required */ | 124 | return; /* no updates are required */ |
125 | if (pm->config->status == -EINPROGRESS) | 125 | if (pm->config->status == -EINPROGRESS) |
126 | return; /* an update is already in progress; it'll issue this update when it completes */ | 126 | return; /* an update is already in progress; it'll issue this update when it completes */ |
127 | 127 | ||
128 | if (pm->requires_update & UPDATE_PULSE_ASLEEP){ | 128 | if (pm->requires_update & UPDATE_PULSE_ASLEEP){ |
@@ -142,7 +142,7 @@ static void powermate_sync_state(struct powermate_device *pm) | |||
142 | 2: multiply the speed | 142 | 2: multiply the speed |
143 | the argument only has an effect for operations 0 and 2, and ranges between | 143 | the argument only has an effect for operations 0 and 2, and ranges between |
144 | 1 (least effect) to 255 (maximum effect). | 144 | 1 (least effect) to 255 (maximum effect). |
145 | 145 | ||
146 | thus, several states are equivalent and are coalesced into one state. | 146 | thus, several states are equivalent and are coalesced into one state. |
147 | 147 | ||
148 | we map this onto a range from 0 to 510, with: | 148 | we map this onto a range from 0 to 510, with: |
@@ -151,7 +151,7 @@ static void powermate_sync_state(struct powermate_device *pm) | |||
151 | 256 -- 510 -- use multiple (510 = fastest). | 151 | 256 -- 510 -- use multiple (510 = fastest). |
152 | 152 | ||
153 | Only values of 'arg' quite close to 255 are particularly useful/spectacular. | 153 | Only values of 'arg' quite close to 255 are particularly useful/spectacular. |
154 | */ | 154 | */ |
155 | if (pm->pulse_speed < 255){ | 155 | if (pm->pulse_speed < 255){ |
156 | op = 0; // divide | 156 | op = 0; // divide |
157 | arg = 255 - pm->pulse_speed; | 157 | arg = 255 - pm->pulse_speed; |
@@ -199,14 +199,14 @@ static void powermate_config_complete(struct urb *urb, struct pt_regs *regs) | |||
199 | 199 | ||
200 | if (urb->status) | 200 | if (urb->status) |
201 | printk(KERN_ERR "powermate: config urb returned %d\n", urb->status); | 201 | printk(KERN_ERR "powermate: config urb returned %d\n", urb->status); |
202 | 202 | ||
203 | spin_lock_irqsave(&pm->lock, flags); | 203 | spin_lock_irqsave(&pm->lock, flags); |
204 | powermate_sync_state(pm); | 204 | powermate_sync_state(pm); |
205 | spin_unlock_irqrestore(&pm->lock, flags); | 205 | spin_unlock_irqrestore(&pm->lock, flags); |
206 | } | 206 | } |
207 | 207 | ||
208 | /* Set the LED up as described and begin the sync with the hardware if required */ | 208 | /* Set the LED up as described and begin the sync with the hardware if required */ |
209 | static void powermate_pulse_led(struct powermate_device *pm, int static_brightness, int pulse_speed, | 209 | static void powermate_pulse_led(struct powermate_device *pm, int static_brightness, int pulse_speed, |
210 | int pulse_table, int pulse_asleep, int pulse_awake) | 210 | int pulse_table, int pulse_asleep, int pulse_awake) |
211 | { | 211 | { |
212 | unsigned long flags; | 212 | unsigned long flags; |
@@ -229,7 +229,7 @@ static void powermate_pulse_led(struct powermate_device *pm, int static_brightne | |||
229 | /* mark state updates which are required */ | 229 | /* mark state updates which are required */ |
230 | if (static_brightness != pm->static_brightness){ | 230 | if (static_brightness != pm->static_brightness){ |
231 | pm->static_brightness = static_brightness; | 231 | pm->static_brightness = static_brightness; |
232 | pm->requires_update |= UPDATE_STATIC_BRIGHTNESS; | 232 | pm->requires_update |= UPDATE_STATIC_BRIGHTNESS; |
233 | } | 233 | } |
234 | if (pulse_asleep != pm->pulse_asleep){ | 234 | if (pulse_asleep != pm->pulse_asleep){ |
235 | pm->pulse_asleep = pulse_asleep; | 235 | pm->pulse_asleep = pulse_asleep; |
@@ -246,7 +246,7 @@ static void powermate_pulse_led(struct powermate_device *pm, int static_brightne | |||
246 | } | 246 | } |
247 | 247 | ||
248 | powermate_sync_state(pm); | 248 | powermate_sync_state(pm); |
249 | 249 | ||
250 | spin_unlock_irqrestore(&pm->lock, flags); | 250 | spin_unlock_irqrestore(&pm->lock, flags); |
251 | } | 251 | } |
252 | 252 | ||
@@ -257,19 +257,19 @@ static int powermate_input_event(struct input_dev *dev, unsigned int type, unsig | |||
257 | struct powermate_device *pm = dev->private; | 257 | struct powermate_device *pm = dev->private; |
258 | 258 | ||
259 | if (type == EV_MSC && code == MSC_PULSELED){ | 259 | if (type == EV_MSC && code == MSC_PULSELED){ |
260 | /* | 260 | /* |
261 | bits 0- 7: 8 bits: LED brightness | 261 | bits 0- 7: 8 bits: LED brightness |
262 | bits 8-16: 9 bits: pulsing speed modifier (0 ... 510); 0-254 = slower, 255 = standard, 256-510 = faster. | 262 | bits 8-16: 9 bits: pulsing speed modifier (0 ... 510); 0-254 = slower, 255 = standard, 256-510 = faster. |
263 | bits 17-18: 2 bits: pulse table (0, 1, 2 valid) | 263 | bits 17-18: 2 bits: pulse table (0, 1, 2 valid) |
264 | bit 19: 1 bit : pulse whilst asleep? | 264 | bit 19: 1 bit : pulse whilst asleep? |
265 | bit 20: 1 bit : pulse constantly? | 265 | bit 20: 1 bit : pulse constantly? |
266 | */ | 266 | */ |
267 | int static_brightness = command & 0xFF; // bits 0-7 | 267 | int static_brightness = command & 0xFF; // bits 0-7 |
268 | int pulse_speed = (command >> 8) & 0x1FF; // bits 8-16 | 268 | int pulse_speed = (command >> 8) & 0x1FF; // bits 8-16 |
269 | int pulse_table = (command >> 17) & 0x3; // bits 17-18 | 269 | int pulse_table = (command >> 17) & 0x3; // bits 17-18 |
270 | int pulse_asleep = (command >> 19) & 0x1; // bit 19 | 270 | int pulse_asleep = (command >> 19) & 0x1; // bit 19 |
271 | int pulse_awake = (command >> 20) & 0x1; // bit 20 | 271 | int pulse_awake = (command >> 20) & 0x1; // bit 20 |
272 | 272 | ||
273 | powermate_pulse_led(pm, static_brightness, pulse_speed, pulse_table, pulse_asleep, pulse_awake); | 273 | powermate_pulse_led(pm, static_brightness, pulse_speed, pulse_table, pulse_asleep, pulse_awake); |
274 | } | 274 | } |
275 | 275 | ||
@@ -378,7 +378,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i | |||
378 | switch (le16_to_cpu(udev->descriptor.idProduct)) { | 378 | switch (le16_to_cpu(udev->descriptor.idProduct)) { |
379 | case POWERMATE_PRODUCT_NEW: pm->input.name = pm_name_powermate; break; | 379 | case POWERMATE_PRODUCT_NEW: pm->input.name = pm_name_powermate; break; |
380 | case POWERMATE_PRODUCT_OLD: pm->input.name = pm_name_soundknob; break; | 380 | case POWERMATE_PRODUCT_OLD: pm->input.name = pm_name_soundknob; break; |
381 | default: | 381 | default: |
382 | pm->input.name = pm_name_soundknob; | 382 | pm->input.name = pm_name_soundknob; |
383 | printk(KERN_WARNING "powermate: unknown product id %04x\n", | 383 | printk(KERN_WARNING "powermate: unknown product id %04x\n", |
384 | le16_to_cpu(udev->descriptor.idProduct)); | 384 | le16_to_cpu(udev->descriptor.idProduct)); |
@@ -402,11 +402,11 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i | |||
402 | usb_make_path(udev, path, 64); | 402 | usb_make_path(udev, path, 64); |
403 | snprintf(pm->phys, 64, "%s/input0", path); | 403 | snprintf(pm->phys, 64, "%s/input0", path); |
404 | printk(KERN_INFO "input: %s on %s\n", pm->input.name, pm->input.phys); | 404 | printk(KERN_INFO "input: %s on %s\n", pm->input.name, pm->input.phys); |
405 | 405 | ||
406 | /* force an update of everything */ | 406 | /* force an update of everything */ |
407 | pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS; | 407 | pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS; |
408 | powermate_pulse_led(pm, 0x80, 255, 0, 1, 0); // set default pulse parameters | 408 | powermate_pulse_led(pm, 0x80, 255, 0, 1, 0); // set default pulse parameters |
409 | 409 | ||
410 | usb_set_intfdata(intf, pm); | 410 | usb_set_intfdata(intf, pm); |
411 | return 0; | 411 | return 0; |
412 | } | 412 | } |
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c index a71f1bbd0a17..386595ee21c0 100644 --- a/drivers/usb/input/touchkitusb.c +++ b/drivers/usb/input/touchkitusb.c | |||
@@ -69,7 +69,6 @@ struct touchkit_usb { | |||
69 | struct urb *irq; | 69 | struct urb *irq; |
70 | struct usb_device *udev; | 70 | struct usb_device *udev; |
71 | struct input_dev input; | 71 | struct input_dev input; |
72 | int open; | ||
73 | char name[128]; | 72 | char name[128]; |
74 | char phys[64]; | 73 | char phys[64]; |
75 | }; | 74 | }; |
@@ -134,15 +133,10 @@ static int touchkit_open(struct input_dev *input) | |||
134 | { | 133 | { |
135 | struct touchkit_usb *touchkit = input->private; | 134 | struct touchkit_usb *touchkit = input->private; |
136 | 135 | ||
137 | if (touchkit->open++) | ||
138 | return 0; | ||
139 | |||
140 | touchkit->irq->dev = touchkit->udev; | 136 | touchkit->irq->dev = touchkit->udev; |
141 | 137 | ||
142 | if (usb_submit_urb(touchkit->irq, GFP_ATOMIC)) { | 138 | if (usb_submit_urb(touchkit->irq, GFP_ATOMIC)) |
143 | touchkit->open--; | ||
144 | return -EIO; | 139 | return -EIO; |
145 | } | ||
146 | 140 | ||
147 | return 0; | 141 | return 0; |
148 | } | 142 | } |
@@ -151,8 +145,7 @@ static void touchkit_close(struct input_dev *input) | |||
151 | { | 145 | { |
152 | struct touchkit_usb *touchkit = input->private; | 146 | struct touchkit_usb *touchkit = input->private; |
153 | 147 | ||
154 | if (!--touchkit->open) | 148 | usb_kill_urb(touchkit->irq); |
155 | usb_kill_urb(touchkit->irq); | ||
156 | } | 149 | } |
157 | 150 | ||
158 | static int touchkit_alloc_buffers(struct usb_device *udev, | 151 | static int touchkit_alloc_buffers(struct usb_device *udev, |
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c index 7038fb9d1ced..f35db1974c42 100644 --- a/drivers/usb/input/usbkbd.c +++ b/drivers/usb/input/usbkbd.c | |||
@@ -9,18 +9,18 @@ | |||
9 | /* | 9 | /* |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
12 | * the Free Software Foundation; either version 2 of the License, or | 12 | * the Free Software Foundation; either version 2 of the License, or |
13 | * (at your option) any later version. | 13 | * (at your option) any later version. |
14 | * | 14 | * |
15 | * This program is distributed in the hope that it will be useful, | 15 | * This program is distributed in the hope that it will be useful, |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | * GNU General Public License for more details. | 18 | * GNU General Public License for more details. |
19 | * | 19 | * |
20 | * You should have received a copy of the GNU General Public License | 20 | * You should have received a copy of the GNU General Public License |
21 | * along with this program; if not, write to the Free Software | 21 | * along with this program; if not, write to the Free Software |
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
23 | * | 23 | * |
24 | * Should you need to contact me, the author, you can do so either by | 24 | * Should you need to contact me, the author, you can do so either by |
25 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | 25 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: |
26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | 26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic |
@@ -72,7 +72,6 @@ struct usb_kbd { | |||
72 | unsigned char newleds; | 72 | unsigned char newleds; |
73 | char name[128]; | 73 | char name[128]; |
74 | char phys[64]; | 74 | char phys[64]; |
75 | int open; | ||
76 | 75 | ||
77 | unsigned char *new; | 76 | unsigned char *new; |
78 | struct usb_ctrlrequest *cr; | 77 | struct usb_ctrlrequest *cr; |
@@ -166,7 +165,7 @@ static void usb_kbd_led(struct urb *urb, struct pt_regs *regs) | |||
166 | 165 | ||
167 | if (urb->status) | 166 | if (urb->status) |
168 | warn("led urb status %d received", urb->status); | 167 | warn("led urb status %d received", urb->status); |
169 | 168 | ||
170 | if (*(kbd->leds) == kbd->newleds) | 169 | if (*(kbd->leds) == kbd->newleds) |
171 | return; | 170 | return; |
172 | 171 | ||
@@ -180,14 +179,9 @@ static int usb_kbd_open(struct input_dev *dev) | |||
180 | { | 179 | { |
181 | struct usb_kbd *kbd = dev->private; | 180 | struct usb_kbd *kbd = dev->private; |
182 | 181 | ||
183 | if (kbd->open++) | ||
184 | return 0; | ||
185 | |||
186 | kbd->irq->dev = kbd->usbdev; | 182 | kbd->irq->dev = kbd->usbdev; |
187 | if (usb_submit_urb(kbd->irq, GFP_KERNEL)) { | 183 | if (usb_submit_urb(kbd->irq, GFP_KERNEL)) |
188 | kbd->open--; | ||
189 | return -EIO; | 184 | return -EIO; |
190 | } | ||
191 | 185 | ||
192 | return 0; | 186 | return 0; |
193 | } | 187 | } |
@@ -196,8 +190,7 @@ static void usb_kbd_close(struct input_dev *dev) | |||
196 | { | 190 | { |
197 | struct usb_kbd *kbd = dev->private; | 191 | struct usb_kbd *kbd = dev->private; |
198 | 192 | ||
199 | if (!--kbd->open) | 193 | usb_kill_urb(kbd->irq); |
200 | usb_kill_urb(kbd->irq); | ||
201 | } | 194 | } |
202 | 195 | ||
203 | static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd) | 196 | static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd) |
@@ -230,7 +223,7 @@ static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd) | |||
230 | usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma); | 223 | usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma); |
231 | } | 224 | } |
232 | 225 | ||
233 | static int usb_kbd_probe(struct usb_interface *iface, | 226 | static int usb_kbd_probe(struct usb_interface *iface, |
234 | const struct usb_device_id *id) | 227 | const struct usb_device_id *id) |
235 | { | 228 | { |
236 | struct usb_device * dev = interface_to_usbdev(iface); | 229 | struct usb_device * dev = interface_to_usbdev(iface); |
@@ -272,7 +265,7 @@ static int usb_kbd_probe(struct usb_interface *iface, | |||
272 | for (i = 0; i < 255; i++) | 265 | for (i = 0; i < 255; i++) |
273 | set_bit(usb_kbd_keycode[i], kbd->dev.keybit); | 266 | set_bit(usb_kbd_keycode[i], kbd->dev.keybit); |
274 | clear_bit(0, kbd->dev.keybit); | 267 | clear_bit(0, kbd->dev.keybit); |
275 | 268 | ||
276 | kbd->dev.private = kbd; | 269 | kbd->dev.private = kbd; |
277 | kbd->dev.event = usb_kbd_event; | 270 | kbd->dev.event = usb_kbd_event; |
278 | kbd->dev.open = usb_kbd_open; | 271 | kbd->dev.open = usb_kbd_open; |
@@ -294,7 +287,7 @@ static int usb_kbd_probe(struct usb_interface *iface, | |||
294 | sprintf(kbd->phys, "%s/input0", path); | 287 | sprintf(kbd->phys, "%s/input0", path); |
295 | 288 | ||
296 | kbd->dev.name = kbd->name; | 289 | kbd->dev.name = kbd->name; |
297 | kbd->dev.phys = kbd->phys; | 290 | kbd->dev.phys = kbd->phys; |
298 | kbd->dev.id.bustype = BUS_USB; | 291 | kbd->dev.id.bustype = BUS_USB; |
299 | kbd->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); | 292 | kbd->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); |
300 | kbd->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); | 293 | kbd->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); |
@@ -329,7 +322,7 @@ static int usb_kbd_probe(struct usb_interface *iface, | |||
329 | static void usb_kbd_disconnect(struct usb_interface *intf) | 322 | static void usb_kbd_disconnect(struct usb_interface *intf) |
330 | { | 323 | { |
331 | struct usb_kbd *kbd = usb_get_intfdata (intf); | 324 | struct usb_kbd *kbd = usb_get_intfdata (intf); |
332 | 325 | ||
333 | usb_set_intfdata(intf, NULL); | 326 | usb_set_intfdata(intf, NULL); |
334 | if (kbd) { | 327 | if (kbd) { |
335 | usb_kill_urb(kbd->irq); | 328 | usb_kill_urb(kbd->irq); |
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c index 01155bbddd43..1ec41b5effe6 100644 --- a/drivers/usb/input/usbmouse.c +++ b/drivers/usb/input/usbmouse.c | |||
@@ -9,18 +9,18 @@ | |||
9 | /* | 9 | /* |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
12 | * the Free Software Foundation; either version 2 of the License, or | 12 | * the Free Software Foundation; either version 2 of the License, or |
13 | * (at your option) any later version. | 13 | * (at your option) any later version. |
14 | * | 14 | * |
15 | * This program is distributed in the hope that it will be useful, | 15 | * This program is distributed in the hope that it will be useful, |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | * GNU General Public License for more details. | 18 | * GNU General Public License for more details. |
19 | * | 19 | * |
20 | * You should have received a copy of the GNU General Public License | 20 | * You should have received a copy of the GNU General Public License |
21 | * along with this program; if not, write to the Free Software | 21 | * along with this program; if not, write to the Free Software |
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
23 | * | 23 | * |
24 | * Should you need to contact me, the author, you can do so either by | 24 | * Should you need to contact me, the author, you can do so either by |
25 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | 25 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: |
26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | 26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic |
@@ -51,7 +51,6 @@ struct usb_mouse { | |||
51 | struct usb_device *usbdev; | 51 | struct usb_device *usbdev; |
52 | struct input_dev dev; | 52 | struct input_dev dev; |
53 | struct urb *irq; | 53 | struct urb *irq; |
54 | int open; | ||
55 | 54 | ||
56 | signed char *data; | 55 | signed char *data; |
57 | dma_addr_t data_dma; | 56 | dma_addr_t data_dma; |
@@ -101,14 +100,9 @@ static int usb_mouse_open(struct input_dev *dev) | |||
101 | { | 100 | { |
102 | struct usb_mouse *mouse = dev->private; | 101 | struct usb_mouse *mouse = dev->private; |
103 | 102 | ||
104 | if (mouse->open++) | ||
105 | return 0; | ||
106 | |||
107 | mouse->irq->dev = mouse->usbdev; | 103 | mouse->irq->dev = mouse->usbdev; |
108 | if (usb_submit_urb(mouse->irq, GFP_KERNEL)) { | 104 | if (usb_submit_urb(mouse->irq, GFP_KERNEL)) |
109 | mouse->open--; | ||
110 | return -EIO; | 105 | return -EIO; |
111 | } | ||
112 | 106 | ||
113 | return 0; | 107 | return 0; |
114 | } | 108 | } |
@@ -117,8 +111,7 @@ static void usb_mouse_close(struct input_dev *dev) | |||
117 | { | 111 | { |
118 | struct usb_mouse *mouse = dev->private; | 112 | struct usb_mouse *mouse = dev->private; |
119 | 113 | ||
120 | if (!--mouse->open) | 114 | usb_kill_urb(mouse->irq); |
121 | usb_kill_urb(mouse->irq); | ||
122 | } | 115 | } |
123 | 116 | ||
124 | static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_id * id) | 117 | static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_id * id) |
@@ -132,19 +125,19 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_ | |||
132 | 125 | ||
133 | interface = intf->cur_altsetting; | 126 | interface = intf->cur_altsetting; |
134 | 127 | ||
135 | if (interface->desc.bNumEndpoints != 1) | 128 | if (interface->desc.bNumEndpoints != 1) |
136 | return -ENODEV; | 129 | return -ENODEV; |
137 | 130 | ||
138 | endpoint = &interface->endpoint[0].desc; | 131 | endpoint = &interface->endpoint[0].desc; |
139 | if (!(endpoint->bEndpointAddress & 0x80)) | 132 | if (!(endpoint->bEndpointAddress & 0x80)) |
140 | return -ENODEV; | 133 | return -ENODEV; |
141 | if ((endpoint->bmAttributes & 3) != 3) | 134 | if ((endpoint->bmAttributes & 3) != 3) |
142 | return -ENODEV; | 135 | return -ENODEV; |
143 | 136 | ||
144 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | 137 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); |
145 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); | 138 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); |
146 | 139 | ||
147 | if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) | 140 | if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) |
148 | return -ENOMEM; | 141 | return -ENOMEM; |
149 | memset(mouse, 0, sizeof(struct usb_mouse)); | 142 | memset(mouse, 0, sizeof(struct usb_mouse)); |
150 | 143 | ||
@@ -209,7 +202,7 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_ | |||
209 | static void usb_mouse_disconnect(struct usb_interface *intf) | 202 | static void usb_mouse_disconnect(struct usb_interface *intf) |
210 | { | 203 | { |
211 | struct usb_mouse *mouse = usb_get_intfdata (intf); | 204 | struct usb_mouse *mouse = usb_get_intfdata (intf); |
212 | 205 | ||
213 | usb_set_intfdata(intf, NULL); | 206 | usb_set_intfdata(intf, NULL); |
214 | if (mouse) { | 207 | if (mouse) { |
215 | usb_kill_urb(mouse->irq); | 208 | usb_kill_urb(mouse->irq); |
@@ -238,7 +231,7 @@ static struct usb_driver usb_mouse_driver = { | |||
238 | static int __init usb_mouse_init(void) | 231 | static int __init usb_mouse_init(void) |
239 | { | 232 | { |
240 | int retval = usb_register(&usb_mouse_driver); | 233 | int retval = usb_register(&usb_mouse_driver); |
241 | if (retval == 0) | 234 | if (retval == 0) |
242 | info(DRIVER_VERSION ":" DRIVER_DESC); | 235 | info(DRIVER_VERSION ":" DRIVER_DESC); |
243 | return retval; | 236 | return retval; |
244 | } | 237 | } |
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c index fec04dda088e..f6b34af66b3d 100644 --- a/drivers/usb/input/wacom.c +++ b/drivers/usb/input/wacom.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * Copyright (c) 2000 Daniel Egger <egger@suse.de> | 9 | * Copyright (c) 2000 Daniel Egger <egger@suse.de> |
10 | * Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com> | 10 | * Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com> |
11 | * Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be> | 11 | * Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be> |
12 | * Copyright (c) 2002-2004 Ping Cheng <pingc@wacom.com> | 12 | * Copyright (c) 2002-2005 Ping Cheng <pingc@wacom.com> |
13 | * | 13 | * |
14 | * ChangeLog: | 14 | * ChangeLog: |
15 | * v0.1 (vp) - Initial release | 15 | * v0.1 (vp) - Initial release |
@@ -18,7 +18,7 @@ | |||
18 | * v0.4 (sm) - Support for more Intuos models, menustrip | 18 | * v0.4 (sm) - Support for more Intuos models, menustrip |
19 | * relative mode, proximity. | 19 | * relative mode, proximity. |
20 | * v0.5 (vp) - Big cleanup, nifty features removed, | 20 | * v0.5 (vp) - Big cleanup, nifty features removed, |
21 | * they belong in userspace | 21 | * they belong in userspace |
22 | * v1.8 (vp) - Submit URB only when operating, moved to CVS, | 22 | * v1.8 (vp) - Submit URB only when operating, moved to CVS, |
23 | * use input_report_key instead of report_btn and | 23 | * use input_report_key instead of report_btn and |
24 | * other cleanups | 24 | * other cleanups |
@@ -51,6 +51,9 @@ | |||
51 | * - Cleanups here and there | 51 | * - Cleanups here and there |
52 | * v1.30.1 (pi) - Added Graphire3 support | 52 | * v1.30.1 (pi) - Added Graphire3 support |
53 | * v1.40 (pc) - Add support for several new devices, fix eraser reporting, ... | 53 | * v1.40 (pc) - Add support for several new devices, fix eraser reporting, ... |
54 | * v1.43 (pc) - Added support for Cintiq 21UX | ||
55 | - Fixed a Graphire bug | ||
56 | - Merged wacom_intuos3_irq into wacom_intuos_irq | ||
54 | */ | 57 | */ |
55 | 58 | ||
56 | /* | 59 | /* |
@@ -72,7 +75,7 @@ | |||
72 | /* | 75 | /* |
73 | * Version Information | 76 | * Version Information |
74 | */ | 77 | */ |
75 | #define DRIVER_VERSION "v1.40" | 78 | #define DRIVER_VERSION "v1.43" |
76 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" | 79 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" |
77 | #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" | 80 | #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" |
78 | #define DRIVER_LICENSE "GPL" | 81 | #define DRIVER_LICENSE "GPL" |
@@ -83,6 +86,16 @@ MODULE_LICENSE(DRIVER_LICENSE); | |||
83 | 86 | ||
84 | #define USB_VENDOR_ID_WACOM 0x056a | 87 | #define USB_VENDOR_ID_WACOM 0x056a |
85 | 88 | ||
89 | enum { | ||
90 | PENPARTNER = 0, | ||
91 | GRAPHIRE, | ||
92 | PL, | ||
93 | INTUOS, | ||
94 | INTUOS3, | ||
95 | CINTIQ, | ||
96 | MAX_TYPE | ||
97 | }; | ||
98 | |||
86 | struct wacom_features { | 99 | struct wacom_features { |
87 | char *name; | 100 | char *name; |
88 | int pktlen; | 101 | int pktlen; |
@@ -102,7 +115,6 @@ struct wacom { | |||
102 | struct urb *irq; | 115 | struct urb *irq; |
103 | struct wacom_features *features; | 116 | struct wacom_features *features; |
104 | int tool[2]; | 117 | int tool[2]; |
105 | int open; | ||
106 | __u32 serial[2]; | 118 | __u32 serial[2]; |
107 | char phys[32]; | 119 | char phys[32]; |
108 | }; | 120 | }; |
@@ -149,7 +161,7 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) | |||
149 | prox = data[1] & 0x40; | 161 | prox = data[1] & 0x40; |
150 | 162 | ||
151 | input_regs(dev, regs); | 163 | input_regs(dev, regs); |
152 | 164 | ||
153 | if (prox) { | 165 | if (prox) { |
154 | 166 | ||
155 | pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); | 167 | pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); |
@@ -166,8 +178,7 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) | |||
166 | if (!wacom->tool[0]) { | 178 | if (!wacom->tool[0]) { |
167 | /* Going into proximity select tool */ | 179 | /* Going into proximity select tool */ |
168 | wacom->tool[1] = (data[4] & 0x20)? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | 180 | wacom->tool[1] = (data[4] & 0x20)? BTN_TOOL_RUBBER : BTN_TOOL_PEN; |
169 | } | 181 | } else { |
170 | else { | ||
171 | /* was entered with stylus2 pressed */ | 182 | /* was entered with stylus2 pressed */ |
172 | if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20) ) { | 183 | if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20) ) { |
173 | /* report out proximity for previous tool */ | 184 | /* report out proximity for previous tool */ |
@@ -182,16 +193,15 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) | |||
182 | wacom->tool[1] = BTN_TOOL_PEN; | 193 | wacom->tool[1] = BTN_TOOL_PEN; |
183 | } | 194 | } |
184 | input_report_key(dev, wacom->tool[1], prox); /* report in proximity for tool */ | 195 | input_report_key(dev, wacom->tool[1], prox); /* report in proximity for tool */ |
185 | input_report_abs(dev, ABS_X, data[3] | ((__u32)data[2] << 7) | ((__u32)(data[1] & 0x03) << 14)); | 196 | input_report_abs(dev, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14)); |
186 | input_report_abs(dev, ABS_Y, data[6] | ((__u32)data[5] << 7) | ((__u32)(data[4] & 0x03) << 14)); | 197 | input_report_abs(dev, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14)); |
187 | input_report_abs(dev, ABS_PRESSURE, pressure); | 198 | input_report_abs(dev, ABS_PRESSURE, pressure); |
188 | 199 | ||
189 | input_report_key(dev, BTN_TOUCH, data[4] & 0x08); | 200 | input_report_key(dev, BTN_TOUCH, data[4] & 0x08); |
190 | input_report_key(dev, BTN_STYLUS, data[4] & 0x10); | 201 | input_report_key(dev, BTN_STYLUS, data[4] & 0x10); |
191 | /* Only allow the stylus2 button to be reported for the pen tool. */ | 202 | /* Only allow the stylus2 button to be reported for the pen tool. */ |
192 | input_report_key(dev, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20)); | 203 | input_report_key(dev, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20)); |
193 | } | 204 | } else { |
194 | else { | ||
195 | /* report proximity-out of a (valid) tool */ | 205 | /* report proximity-out of a (valid) tool */ |
196 | if (wacom->tool[1] != BTN_TOOL_RUBBER) { | 206 | if (wacom->tool[1] != BTN_TOOL_RUBBER) { |
197 | /* Unknown tool selected default to pen tool */ | 207 | /* Unknown tool selected default to pen tool */ |
@@ -203,7 +213,7 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) | |||
203 | wacom->tool[0] = prox; /* Save proximity state */ | 213 | wacom->tool[0] = prox; /* Save proximity state */ |
204 | input_sync(dev); | 214 | input_sync(dev); |
205 | 215 | ||
206 | exit: | 216 | exit: |
207 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 217 | retval = usb_submit_urb (urb, GFP_ATOMIC); |
208 | if (retval) | 218 | if (retval) |
209 | err ("%s - usb_submit_urb failed with result %d", | 219 | err ("%s - usb_submit_urb failed with result %d", |
@@ -232,20 +242,16 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs) | |||
232 | goto exit; | 242 | goto exit; |
233 | } | 243 | } |
234 | 244 | ||
235 | if (data[0] != 2) | 245 | if (data[0] != 2) { |
236 | { | ||
237 | printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); | 246 | printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); |
238 | goto exit; | 247 | goto exit; |
239 | } | 248 | } |
240 | 249 | ||
241 | input_regs(dev, regs); | 250 | input_regs(dev, regs); |
242 | if (data[1] & 0x04) | 251 | if (data[1] & 0x04) { |
243 | { | ||
244 | input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x20); | 252 | input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x20); |
245 | input_report_key(dev, BTN_TOUCH, data[1] & 0x08); | 253 | input_report_key(dev, BTN_TOUCH, data[1] & 0x08); |
246 | } | 254 | } else { |
247 | else | ||
248 | { | ||
249 | input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20); | 255 | input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20); |
250 | input_report_key(dev, BTN_TOUCH, data[1] & 0x01); | 256 | input_report_key(dev, BTN_TOUCH, data[1] & 0x01); |
251 | } | 257 | } |
@@ -257,7 +263,7 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs) | |||
257 | 263 | ||
258 | input_sync(dev); | 264 | input_sync(dev); |
259 | 265 | ||
260 | exit: | 266 | exit: |
261 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 267 | retval = usb_submit_urb (urb, GFP_ATOMIC); |
262 | if (retval) | 268 | if (retval) |
263 | err ("%s - usb_submit_urb failed with result %d", | 269 | err ("%s - usb_submit_urb failed with result %d", |
@@ -300,7 +306,7 @@ static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs) | |||
300 | input_report_key(dev, BTN_STYLUS, (data[5] & 0x40)); | 306 | input_report_key(dev, BTN_STYLUS, (data[5] & 0x40)); |
301 | input_sync(dev); | 307 | input_sync(dev); |
302 | 308 | ||
303 | exit: | 309 | exit: |
304 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 310 | retval = usb_submit_urb (urb, GFP_ATOMIC); |
305 | if (retval) | 311 | if (retval) |
306 | err ("%s - usb_submit_urb failed with result %d", | 312 | err ("%s - usb_submit_urb failed with result %d", |
@@ -340,47 +346,47 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | |||
340 | 346 | ||
341 | input_regs(dev, regs); | 347 | input_regs(dev, regs); |
342 | 348 | ||
343 | switch ((data[1] >> 5) & 3) { | 349 | if (data[1] & 0x10) { /* in prox */ |
344 | 350 | ||
345 | case 0: /* Pen */ | 351 | switch ((data[1] >> 5) & 3) { |
346 | input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x80); | ||
347 | break; | ||
348 | 352 | ||
349 | case 1: /* Rubber */ | 353 | case 0: /* Pen */ |
350 | input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x80); | 354 | wacom->tool[0] = BTN_TOOL_PEN; |
351 | break; | 355 | break; |
352 | |||
353 | case 2: /* Mouse with wheel */ | ||
354 | input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); | ||
355 | input_report_rel(dev, REL_WHEEL, (signed char) data[6]); | ||
356 | /* fall through */ | ||
357 | 356 | ||
358 | case 3: /* Mouse without wheel */ | 357 | case 1: /* Rubber */ |
359 | input_report_key(dev, BTN_TOOL_MOUSE, data[7] > 24); | 358 | wacom->tool[0] = BTN_TOOL_RUBBER; |
360 | input_report_key(dev, BTN_LEFT, data[1] & 0x01); | 359 | break; |
361 | input_report_key(dev, BTN_RIGHT, data[1] & 0x02); | ||
362 | input_report_abs(dev, ABS_DISTANCE, data[7]); | ||
363 | 360 | ||
364 | input_report_abs(dev, ABS_X, x); | 361 | case 2: /* Mouse with wheel */ |
365 | input_report_abs(dev, ABS_Y, y); | 362 | input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); |
363 | input_report_rel(dev, REL_WHEEL, (signed char) data[6]); | ||
364 | /* fall through */ | ||
366 | 365 | ||
367 | input_sync(dev); | 366 | case 3: /* Mouse without wheel */ |
368 | goto exit; | 367 | wacom->tool[0] = BTN_TOOL_MOUSE; |
368 | input_report_key(dev, BTN_LEFT, data[1] & 0x01); | ||
369 | input_report_key(dev, BTN_RIGHT, data[1] & 0x02); | ||
370 | input_report_abs(dev, ABS_DISTANCE, data[7]); | ||
371 | break; | ||
372 | } | ||
369 | } | 373 | } |
370 | 374 | ||
371 | if (data[1] & 0x80) { | 375 | if (data[1] & 0x80) { |
372 | input_report_abs(dev, ABS_X, x); | 376 | input_report_abs(dev, ABS_X, x); |
373 | input_report_abs(dev, ABS_Y, y); | 377 | input_report_abs(dev, ABS_Y, y); |
374 | } | 378 | } |
379 | if (wacom->tool[0] != BTN_TOOL_MOUSE) { | ||
380 | input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6])); | ||
381 | input_report_key(dev, BTN_TOUCH, data[1] & 0x01); | ||
382 | input_report_key(dev, BTN_STYLUS, data[1] & 0x02); | ||
383 | input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); | ||
384 | } | ||
375 | 385 | ||
376 | input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6])); | 386 | input_report_key(dev, wacom->tool[0], data[1] & 0x10); |
377 | input_report_key(dev, BTN_TOUCH, data[1] & 0x01); | ||
378 | input_report_key(dev, BTN_STYLUS, data[1] & 0x02); | ||
379 | input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); | ||
380 | |||
381 | input_sync(dev); | 387 | input_sync(dev); |
382 | 388 | ||
383 | exit: | 389 | exit: |
384 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 390 | retval = usb_submit_urb (urb, GFP_ATOMIC); |
385 | if (retval) | 391 | if (retval) |
386 | err ("%s - usb_submit_urb failed with result %d", | 392 | err ("%s - usb_submit_urb failed with result %d", |
@@ -398,14 +404,13 @@ static int wacom_intuos_inout(struct urb *urb) | |||
398 | idx = data[1] & 0x01; | 404 | idx = data[1] & 0x01; |
399 | 405 | ||
400 | /* Enter report */ | 406 | /* Enter report */ |
401 | if ((data[1] & 0xfc) == 0xc0) | 407 | if ((data[1] & 0xfc) == 0xc0) { |
402 | { | ||
403 | /* serial number of the tool */ | 408 | /* serial number of the tool */ |
404 | wacom->serial[idx] = ((__u32)(data[3] & 0x0f) << 28) + | 409 | wacom->serial[idx] = ((data[3] & 0x0f) << 28) + |
405 | ((__u32)data[4] << 20) + ((__u32)data[5] << 12) + | 410 | (data[4] << 20) + (data[5] << 12) + |
406 | ((__u32)data[6] << 4) + (data[7] >> 4); | 411 | (data[6] << 4) + (data[7] >> 4); |
407 | 412 | ||
408 | switch (((__u32)data[2] << 4) | (data[3] >> 4)) { | 413 | switch ((data[2] << 4) | (data[3] >> 4)) { |
409 | case 0x812: /* Inking pen */ | 414 | case 0x812: /* Inking pen */ |
410 | case 0x801: /* Intuos3 Inking pen */ | 415 | case 0x801: /* Intuos3 Inking pen */ |
411 | case 0x012: | 416 | case 0x012: |
@@ -449,7 +454,7 @@ static int wacom_intuos_inout(struct urb *urb) | |||
449 | case 0x112: | 454 | case 0x112: |
450 | case 0x913: /* Intuos3 Airbrush */ | 455 | case 0x913: /* Intuos3 Airbrush */ |
451 | wacom->tool[idx] = BTN_TOOL_AIRBRUSH; | 456 | wacom->tool[idx] = BTN_TOOL_AIRBRUSH; |
452 | break; /* Airbrush */ | 457 | break; |
453 | default: /* Unknown tool */ | 458 | default: /* Unknown tool */ |
454 | wacom->tool[idx] = BTN_TOOL_PEN; | 459 | wacom->tool[idx] = BTN_TOOL_PEN; |
455 | } | 460 | } |
@@ -478,9 +483,8 @@ static void wacom_intuos_general(struct urb *urb) | |||
478 | unsigned int t; | 483 | unsigned int t; |
479 | 484 | ||
480 | /* general pen packet */ | 485 | /* general pen packet */ |
481 | if ((data[1] & 0xb8) == 0xa0) | 486 | if ((data[1] & 0xb8) == 0xa0) { |
482 | { | 487 | t = (data[6] << 2) | ((data[7] >> 6) & 3); |
483 | t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3); | ||
484 | input_report_abs(dev, ABS_PRESSURE, t); | 488 | input_report_abs(dev, ABS_PRESSURE, t); |
485 | input_report_abs(dev, ABS_TILT_X, | 489 | input_report_abs(dev, ABS_TILT_X, |
486 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | 490 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); |
@@ -491,10 +495,9 @@ static void wacom_intuos_general(struct urb *urb) | |||
491 | } | 495 | } |
492 | 496 | ||
493 | /* airbrush second packet */ | 497 | /* airbrush second packet */ |
494 | if ((data[1] & 0xbc) == 0xb4) | 498 | if ((data[1] & 0xbc) == 0xb4) { |
495 | { | ||
496 | input_report_abs(dev, ABS_WHEEL, | 499 | input_report_abs(dev, ABS_WHEEL, |
497 | ((__u32)data[6] << 2) | ((data[7] >> 6) & 3)); | 500 | (data[6] << 2) | ((data[7] >> 6) & 3)); |
498 | input_report_abs(dev, ABS_TILT_X, | 501 | input_report_abs(dev, ABS_TILT_X, |
499 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | 502 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); |
500 | input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f); | 503 | input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f); |
@@ -526,7 +529,7 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) | |||
526 | goto exit; | 529 | goto exit; |
527 | } | 530 | } |
528 | 531 | ||
529 | if (data[0] != 2 && data[0] != 5 && data[0] != 6) { | 532 | if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) { |
530 | dbg("wacom_intuos_irq: received unknown report #%d", data[0]); | 533 | dbg("wacom_intuos_irq: received unknown report #%d", data[0]); |
531 | goto exit; | 534 | goto exit; |
532 | } | 535 | } |
@@ -536,107 +539,10 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) | |||
536 | /* tool number */ | 539 | /* tool number */ |
537 | idx = data[1] & 0x01; | 540 | idx = data[1] & 0x01; |
538 | 541 | ||
539 | /* process in/out prox events */ | ||
540 | if (wacom_intuos_inout(urb)) goto exit; | ||
541 | |||
542 | input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2])); | ||
543 | input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4])); | ||
544 | input_report_abs(dev, ABS_DISTANCE, data[9]); | ||
545 | |||
546 | /* process general packets */ | ||
547 | wacom_intuos_general(urb); | ||
548 | |||
549 | if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { /* 4D mouse or Lens cursor packets */ | ||
550 | |||
551 | if (data[1] & 0x02) { /* Rotation packet */ | ||
552 | |||
553 | t = ((__u32)data[6] << 3) | ((data[7] >> 5) & 7); | ||
554 | input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ? ((t - 1) / 2) : -t / 2); | ||
555 | |||
556 | } else { | ||
557 | |||
558 | if ((data[1] & 0x10) == 0) { /* 4D mouse packets */ | ||
559 | |||
560 | input_report_key(dev, BTN_LEFT, data[8] & 0x01); | ||
561 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); | ||
562 | input_report_key(dev, BTN_RIGHT, data[8] & 0x04); | ||
563 | |||
564 | input_report_key(dev, BTN_SIDE, data[8] & 0x20); | ||
565 | input_report_key(dev, BTN_EXTRA, data[8] & 0x10); | ||
566 | t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3); | ||
567 | input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); | ||
568 | |||
569 | } else { | ||
570 | if (wacom->tool[idx] == BTN_TOOL_MOUSE) { /* 2D mouse packets */ | ||
571 | input_report_key(dev, BTN_LEFT, data[8] & 0x04); | ||
572 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x08); | ||
573 | input_report_key(dev, BTN_RIGHT, data[8] & 0x10); | ||
574 | input_report_rel(dev, REL_WHEEL, | ||
575 | (-(__u32)(data[8] & 0x01) + (__u32)((data[8] & 0x02) >> 1))); | ||
576 | } | ||
577 | else { /* Lens cursor packets */ | ||
578 | input_report_key(dev, BTN_LEFT, data[8] & 0x01); | ||
579 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); | ||
580 | input_report_key(dev, BTN_RIGHT, data[8] & 0x04); | ||
581 | input_report_key(dev, BTN_SIDE, data[8] & 0x10); | ||
582 | input_report_key(dev, BTN_EXTRA, data[8] & 0x08); | ||
583 | } | ||
584 | } | ||
585 | } | ||
586 | } | ||
587 | |||
588 | input_report_key(dev, wacom->tool[idx], 1); | ||
589 | input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | ||
590 | input_sync(dev); | ||
591 | |||
592 | exit: | ||
593 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
594 | if (retval) | ||
595 | err ("%s - usb_submit_urb failed with result %d", | ||
596 | __FUNCTION__, retval); | ||
597 | } | ||
598 | |||
599 | static void wacom_intuos3_irq(struct urb *urb, struct pt_regs *regs) | ||
600 | { | ||
601 | struct wacom *wacom = urb->context; | ||
602 | unsigned char *data = wacom->data; | ||
603 | struct input_dev *dev = &wacom->dev; | ||
604 | unsigned int t; | ||
605 | int idx, retval; | ||
606 | |||
607 | switch (urb->status) { | ||
608 | case 0: | ||
609 | /* success */ | ||
610 | break; | ||
611 | case -ECONNRESET: | ||
612 | case -ENOENT: | ||
613 | case -ESHUTDOWN: | ||
614 | /* this urb is terminated, clean up */ | ||
615 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | ||
616 | return; | ||
617 | default: | ||
618 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | ||
619 | goto exit; | ||
620 | } | ||
621 | |||
622 | /* check for valid report */ | ||
623 | if (data[0] != 2 && data[0] != 5 && data[0] != 12) | ||
624 | { | ||
625 | printk(KERN_INFO "wacom_intuos3_irq: received unknown report #%d\n", data[0]); | ||
626 | goto exit; | ||
627 | } | ||
628 | |||
629 | input_regs(dev, regs); | ||
630 | |||
631 | /* tool index is always 0 here since there is no dual input tool */ | ||
632 | idx = data[1] & 0x01; | ||
633 | |||
634 | /* pad packets. Works as a second tool and is always in prox */ | 542 | /* pad packets. Works as a second tool and is always in prox */ |
635 | if (data[0] == 12) | 543 | if (data[0] == 12) { |
636 | { | ||
637 | /* initiate the pad as a device */ | 544 | /* initiate the pad as a device */ |
638 | if (wacom->tool[1] != BTN_TOOL_FINGER) | 545 | if (wacom->tool[1] != BTN_TOOL_FINGER) { |
639 | { | ||
640 | wacom->tool[1] = BTN_TOOL_FINGER; | 546 | wacom->tool[1] = BTN_TOOL_FINGER; |
641 | input_report_key(dev, wacom->tool[1], 1); | 547 | input_report_key(dev, wacom->tool[1], 1); |
642 | } | 548 | } |
@@ -656,37 +562,78 @@ static void wacom_intuos3_irq(struct urb *urb, struct pt_regs *regs) | |||
656 | } | 562 | } |
657 | 563 | ||
658 | /* process in/out prox events */ | 564 | /* process in/out prox events */ |
659 | if (wacom_intuos_inout(urb)) goto exit; | 565 | if (wacom_intuos_inout(urb)) |
566 | goto exit; | ||
660 | 567 | ||
661 | input_report_abs(dev, ABS_X, ((__u32)data[2] << 9) | ((__u32)data[3] << 1) | ((data[9] >> 1) & 1)); | 568 | /* Cintiq doesn't send data when RDY bit isn't set */ |
662 | input_report_abs(dev, ABS_Y, ((__u32)data[4] << 9) | ((__u32)data[5] << 1) | (data[9] & 1)); | 569 | if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40)) |
663 | input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); | 570 | return; |
571 | |||
572 | if (wacom->features->type >= INTUOS3) { | ||
573 | input_report_abs(dev, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1)); | ||
574 | input_report_abs(dev, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1)); | ||
575 | input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); | ||
576 | } else { | ||
577 | input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2])); | ||
578 | input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4])); | ||
579 | input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 3) & 0x1f)); | ||
580 | } | ||
664 | 581 | ||
665 | /* process general packets */ | 582 | /* process general packets */ |
666 | wacom_intuos_general(urb); | 583 | wacom_intuos_general(urb); |
667 | 584 | ||
668 | if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) | 585 | /* 4D mouse, 2D mouse, marker pen rotation, or Lens cursor packets */ |
669 | { | 586 | if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { |
670 | /* Marker pen rotation packet. Reported as wheel due to valuator limitation */ | 587 | |
671 | if (data[1] & 0x02) | 588 | if (data[1] & 0x02) { |
672 | { | 589 | /* Rotation packet */ |
673 | t = ((__u32)data[6] << 3) | ((data[7] >> 5) & 7); | 590 | if (wacom->features->type >= INTUOS3) { |
674 | t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : | 591 | /* I3 marker pen rotation reported as wheel |
675 | ((t-1) / 2 + 450)) : (450 - t / 2) ; | 592 | * due to valuator limitation |
676 | input_report_abs(dev, ABS_WHEEL, t); | 593 | */ |
677 | } | 594 | t = (data[6] << 3) | ((data[7] >> 5) & 7); |
595 | t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : | ||
596 | ((t-1) / 2 + 450)) : (450 - t / 2) ; | ||
597 | input_report_abs(dev, ABS_WHEEL, t); | ||
598 | } else { | ||
599 | /* 4D mouse rotation packet */ | ||
600 | t = (data[6] << 3) | ((data[7] >> 5) & 7); | ||
601 | input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ? | ||
602 | ((t - 1) / 2) : -t / 2); | ||
603 | } | ||
678 | 604 | ||
679 | /* 2D mouse packets */ | 605 | } else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3) { |
680 | if (wacom->tool[idx] == BTN_TOOL_MOUSE) | 606 | /* 4D mouse packet */ |
681 | { | 607 | input_report_key(dev, BTN_LEFT, data[8] & 0x01); |
608 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); | ||
609 | input_report_key(dev, BTN_RIGHT, data[8] & 0x04); | ||
610 | |||
611 | input_report_key(dev, BTN_SIDE, data[8] & 0x20); | ||
612 | input_report_key(dev, BTN_EXTRA, data[8] & 0x10); | ||
613 | t = (data[6] << 2) | ((data[7] >> 6) & 3); | ||
614 | input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); | ||
615 | |||
616 | } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { | ||
617 | /* 2D mouse packet */ | ||
682 | input_report_key(dev, BTN_LEFT, data[8] & 0x04); | 618 | input_report_key(dev, BTN_LEFT, data[8] & 0x04); |
683 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x08); | 619 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x08); |
684 | input_report_key(dev, BTN_RIGHT, data[8] & 0x10); | 620 | input_report_key(dev, BTN_RIGHT, data[8] & 0x10); |
685 | input_report_key(dev, BTN_SIDE, data[8] & 0x40); | 621 | input_report_rel(dev, REL_WHEEL, ((data[8] & 0x02) >> 1) |
686 | input_report_key(dev, BTN_EXTRA, data[8] & 0x20); | 622 | - (data[8] & 0x01)); |
687 | /* mouse wheel is positive when rolled backwards */ | 623 | |
688 | input_report_rel(dev, REL_WHEEL, ((__u32)((data[8] & 0x02) >> 1) | 624 | /* I3 2D mouse side buttons */ |
689 | - (__u32)(data[8] & 0x01))); | 625 | if (wacom->features->type == INTUOS3) { |
626 | input_report_key(dev, BTN_SIDE, data[8] & 0x40); | ||
627 | input_report_key(dev, BTN_EXTRA, data[8] & 0x20); | ||
628 | } | ||
629 | |||
630 | } else if (wacom->features->type < INTUOS3) { | ||
631 | /* Lens cursor packets */ | ||
632 | input_report_key(dev, BTN_LEFT, data[8] & 0x01); | ||
633 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); | ||
634 | input_report_key(dev, BTN_RIGHT, data[8] & 0x04); | ||
635 | input_report_key(dev, BTN_SIDE, data[8] & 0x10); | ||
636 | input_report_key(dev, BTN_EXTRA, data[8] & 0x08); | ||
690 | } | 637 | } |
691 | } | 638 | } |
692 | 639 | ||
@@ -702,35 +649,36 @@ exit: | |||
702 | } | 649 | } |
703 | 650 | ||
704 | static struct wacom_features wacom_features[] = { | 651 | static struct wacom_features wacom_features[] = { |
705 | { "Wacom Penpartner", 7, 5040, 3780, 255, 32, 0, wacom_penpartner_irq }, | 652 | { "Wacom Penpartner", 7, 5040, 3780, 255, 32, PENPARTNER, wacom_penpartner_irq }, |
706 | { "Wacom Graphire", 8, 10206, 7422, 511, 32, 1, wacom_graphire_irq }, | 653 | { "Wacom Graphire", 8, 10206, 7422, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
707 | { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 32, 1, wacom_graphire_irq }, | 654 | { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
708 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, 1, wacom_graphire_irq }, | 655 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
709 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, 1, wacom_graphire_irq }, | 656 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
710 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, 1, wacom_graphire_irq }, | 657 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
711 | { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 15, 2, wacom_intuos_irq }, | 658 | { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_intuos_irq }, |
712 | { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, | 659 | { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, |
713 | { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 15, 2, wacom_intuos_irq }, | 660 | { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_intuos_irq }, |
714 | { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 15, 2, wacom_intuos_irq }, | 661 | { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, |
715 | { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 15, 2, wacom_intuos_irq }, | 662 | { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, |
716 | { "Wacom PL400", 8, 5408, 4056, 255, 32, 3, wacom_pl_irq }, | 663 | { "Wacom PL400", 8, 5408, 4056, 255, 32, PL, wacom_pl_irq }, |
717 | { "Wacom PL500", 8, 6144, 4608, 255, 32, 3, wacom_pl_irq }, | 664 | { "Wacom PL500", 8, 6144, 4608, 255, 32, PL, wacom_pl_irq }, |
718 | { "Wacom PL600", 8, 6126, 4604, 255, 32, 3, wacom_pl_irq }, | 665 | { "Wacom PL600", 8, 6126, 4604, 255, 32, PL, wacom_pl_irq }, |
719 | { "Wacom PL600SX", 8, 6260, 5016, 255, 32, 3, wacom_pl_irq }, | 666 | { "Wacom PL600SX", 8, 6260, 5016, 255, 32, PL, wacom_pl_irq }, |
720 | { "Wacom PL550", 8, 6144, 4608, 511, 32, 3, wacom_pl_irq }, | 667 | { "Wacom PL550", 8, 6144, 4608, 511, 32, PL, wacom_pl_irq }, |
721 | { "Wacom PL800", 8, 7220, 5780, 511, 32, 3, wacom_pl_irq }, | 668 | { "Wacom PL800", 8, 7220, 5780, 511, 32, PL, wacom_pl_irq }, |
722 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, 2, wacom_intuos_irq }, | 669 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_intuos_irq }, |
723 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, | 670 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, |
724 | { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 15, 2, wacom_intuos_irq }, | 671 | { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_intuos_irq }, |
725 | { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, 2, wacom_intuos_irq }, | 672 | { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, |
726 | { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, 2, wacom_intuos_irq }, | 673 | { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, |
727 | { "Wacom Volito", 8, 5104, 3712, 511, 32, 1, wacom_graphire_irq }, | 674 | { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
728 | { "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, 3, wacom_ptu_irq }, | 675 | { "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, PL, wacom_ptu_irq }, |
729 | { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, 4, wacom_intuos3_irq }, | 676 | { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, INTUOS3, wacom_intuos_irq }, |
730 | { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, 4, wacom_intuos3_irq }, | 677 | { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, INTUOS3, wacom_intuos_irq }, |
731 | { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, 4, wacom_intuos3_irq }, | 678 | { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, INTUOS3, wacom_intuos_irq }, |
732 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, | 679 | { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 15, CINTIQ, wacom_intuos_irq }, |
733 | { } | 680 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, |
681 | { } | ||
734 | }; | 682 | }; |
735 | 683 | ||
736 | static struct usb_device_id wacom_ids[] = { | 684 | static struct usb_device_id wacom_ids[] = { |
@@ -761,6 +709,7 @@ static struct usb_device_id wacom_ids[] = { | |||
761 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) }, | 709 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) }, |
762 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) }, | 710 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) }, |
763 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) }, | 711 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) }, |
712 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) }, | ||
764 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, | 713 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, |
765 | { } | 714 | { } |
766 | }; | 715 | }; |
@@ -771,14 +720,9 @@ static int wacom_open(struct input_dev *dev) | |||
771 | { | 720 | { |
772 | struct wacom *wacom = dev->private; | 721 | struct wacom *wacom = dev->private; |
773 | 722 | ||
774 | if (wacom->open++) | ||
775 | return 0; | ||
776 | |||
777 | wacom->irq->dev = wacom->usbdev; | 723 | wacom->irq->dev = wacom->usbdev; |
778 | if (usb_submit_urb(wacom->irq, GFP_KERNEL)) { | 724 | if (usb_submit_urb(wacom->irq, GFP_KERNEL)) |
779 | wacom->open--; | ||
780 | return -EIO; | 725 | return -EIO; |
781 | } | ||
782 | 726 | ||
783 | return 0; | 727 | return 0; |
784 | } | 728 | } |
@@ -787,8 +731,7 @@ static void wacom_close(struct input_dev *dev) | |||
787 | { | 731 | { |
788 | struct wacom *wacom = dev->private; | 732 | struct wacom *wacom = dev->private; |
789 | 733 | ||
790 | if (!--wacom->open) | 734 | usb_kill_urb(wacom->irq); |
791 | usb_kill_urb(wacom->irq); | ||
792 | } | 735 | } |
793 | 736 | ||
794 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) | 737 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) |
@@ -823,32 +766,33 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
823 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS); | 766 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS); |
824 | 767 | ||
825 | switch (wacom->features->type) { | 768 | switch (wacom->features->type) { |
826 | case 1: | 769 | case GRAPHIRE: |
827 | wacom->dev.evbit[0] |= BIT(EV_REL); | 770 | wacom->dev.evbit[0] |= BIT(EV_REL); |
828 | wacom->dev.relbit[0] |= BIT(REL_WHEEL); | 771 | wacom->dev.relbit[0] |= BIT(REL_WHEEL); |
829 | wacom->dev.absbit[0] |= BIT(ABS_DISTANCE); | 772 | wacom->dev.absbit[0] |= BIT(ABS_DISTANCE); |
830 | wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | 773 | wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); |
831 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2); | 774 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2); |
832 | break; | 775 | break; |
833 | 776 | ||
834 | case 4: /* new functions for Intuos3 */ | 777 | case INTUOS3: |
778 | case CINTIQ: | ||
835 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); | 779 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); |
836 | wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); | 780 | wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); |
837 | wacom->dev.absbit[0] |= BIT(ABS_RX) | BIT(ABS_RY); | 781 | wacom->dev.absbit[0] |= BIT(ABS_RX) | BIT(ABS_RY); |
838 | /* fall through */ | 782 | /* fall through */ |
839 | 783 | ||
840 | case 2: | 784 | case INTUOS: |
841 | wacom->dev.evbit[0] |= BIT(EV_MSC) | BIT(EV_REL); | 785 | wacom->dev.evbit[0] |= BIT(EV_MSC) | BIT(EV_REL); |
842 | wacom->dev.mscbit[0] |= BIT(MSC_SERIAL); | 786 | wacom->dev.mscbit[0] |= BIT(MSC_SERIAL); |
843 | wacom->dev.relbit[0] |= BIT(REL_WHEEL); | 787 | wacom->dev.relbit[0] |= BIT(REL_WHEEL); |
844 | wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA); | 788 | wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA); |
845 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH) | 789 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH) |
846 | | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2); | 790 | | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2); |
847 | wacom->dev.absbit[0] |= BIT(ABS_DISTANCE) | BIT(ABS_WHEEL) | BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE); | 791 | wacom->dev.absbit[0] |= BIT(ABS_DISTANCE) | BIT(ABS_WHEEL) | BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE); |
848 | break; | 792 | break; |
849 | 793 | ||
850 | case 3: | 794 | case PL: |
851 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER); | 795 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER); |
852 | break; | 796 | break; |
853 | } | 797 | } |
854 | 798 | ||
diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c index d65edb22e545..a7fa1b17dcfe 100644 --- a/drivers/usb/input/xpad.c +++ b/drivers/usb/input/xpad.c | |||
@@ -104,13 +104,12 @@ MODULE_DEVICE_TABLE (usb, xpad_table); | |||
104 | struct usb_xpad { | 104 | struct usb_xpad { |
105 | struct input_dev dev; /* input device interface */ | 105 | struct input_dev dev; /* input device interface */ |
106 | struct usb_device *udev; /* usb device */ | 106 | struct usb_device *udev; /* usb device */ |
107 | 107 | ||
108 | struct urb *irq_in; /* urb for interrupt in report */ | 108 | struct urb *irq_in; /* urb for interrupt in report */ |
109 | unsigned char *idata; /* input data */ | 109 | unsigned char *idata; /* input data */ |
110 | dma_addr_t idata_dma; | 110 | dma_addr_t idata_dma; |
111 | 111 | ||
112 | char phys[65]; /* physical device path */ | 112 | char phys[65]; /* physical device path */ |
113 | int open_count; /* reference count */ | ||
114 | }; | 113 | }; |
115 | 114 | ||
116 | /* | 115 | /* |
@@ -128,35 +127,35 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d | |||
128 | struct input_dev *dev = &xpad->dev; | 127 | struct input_dev *dev = &xpad->dev; |
129 | 128 | ||
130 | input_regs(dev, regs); | 129 | input_regs(dev, regs); |
131 | 130 | ||
132 | /* left stick */ | 131 | /* left stick */ |
133 | input_report_abs(dev, ABS_X, (__s16) (((__s16)data[13] << 8) | data[12])); | 132 | input_report_abs(dev, ABS_X, (__s16) (((__s16)data[13] << 8) | data[12])); |
134 | input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[15] << 8) | data[14])); | 133 | input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[15] << 8) | data[14])); |
135 | 134 | ||
136 | /* right stick */ | 135 | /* right stick */ |
137 | input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[17] << 8) | data[16])); | 136 | input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[17] << 8) | data[16])); |
138 | input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[19] << 8) | data[18])); | 137 | input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[19] << 8) | data[18])); |
139 | 138 | ||
140 | /* triggers left/right */ | 139 | /* triggers left/right */ |
141 | input_report_abs(dev, ABS_Z, data[10]); | 140 | input_report_abs(dev, ABS_Z, data[10]); |
142 | input_report_abs(dev, ABS_RZ, data[11]); | 141 | input_report_abs(dev, ABS_RZ, data[11]); |
143 | 142 | ||
144 | /* digital pad */ | 143 | /* digital pad */ |
145 | input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); | 144 | input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); |
146 | input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); | 145 | input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); |
147 | 146 | ||
148 | /* start/back buttons and stick press left/right */ | 147 | /* start/back buttons and stick press left/right */ |
149 | input_report_key(dev, BTN_START, (data[2] & 0x10) >> 4); | 148 | input_report_key(dev, BTN_START, (data[2] & 0x10) >> 4); |
150 | input_report_key(dev, BTN_BACK, (data[2] & 0x20) >> 5); | 149 | input_report_key(dev, BTN_BACK, (data[2] & 0x20) >> 5); |
151 | input_report_key(dev, BTN_THUMBL, (data[2] & 0x40) >> 6); | 150 | input_report_key(dev, BTN_THUMBL, (data[2] & 0x40) >> 6); |
152 | input_report_key(dev, BTN_THUMBR, data[2] >> 7); | 151 | input_report_key(dev, BTN_THUMBR, data[2] >> 7); |
153 | 152 | ||
154 | /* "analog" buttons A, B, X, Y */ | 153 | /* "analog" buttons A, B, X, Y */ |
155 | input_report_key(dev, BTN_A, data[4]); | 154 | input_report_key(dev, BTN_A, data[4]); |
156 | input_report_key(dev, BTN_B, data[5]); | 155 | input_report_key(dev, BTN_B, data[5]); |
157 | input_report_key(dev, BTN_X, data[6]); | 156 | input_report_key(dev, BTN_X, data[6]); |
158 | input_report_key(dev, BTN_Y, data[7]); | 157 | input_report_key(dev, BTN_Y, data[7]); |
159 | 158 | ||
160 | /* "analog" buttons black, white */ | 159 | /* "analog" buttons black, white */ |
161 | input_report_key(dev, BTN_C, data[8]); | 160 | input_report_key(dev, BTN_C, data[8]); |
162 | input_report_key(dev, BTN_Z, data[9]); | 161 | input_report_key(dev, BTN_Z, data[9]); |
@@ -168,7 +167,7 @@ static void xpad_irq_in(struct urb *urb, struct pt_regs *regs) | |||
168 | { | 167 | { |
169 | struct usb_xpad *xpad = urb->context; | 168 | struct usb_xpad *xpad = urb->context; |
170 | int retval; | 169 | int retval; |
171 | 170 | ||
172 | switch (urb->status) { | 171 | switch (urb->status) { |
173 | case 0: | 172 | case 0: |
174 | /* success */ | 173 | /* success */ |
@@ -183,7 +182,7 @@ static void xpad_irq_in(struct urb *urb, struct pt_regs *regs) | |||
183 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | 182 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); |
184 | goto exit; | 183 | goto exit; |
185 | } | 184 | } |
186 | 185 | ||
187 | xpad_process_packet(xpad, 0, xpad->idata, regs); | 186 | xpad_process_packet(xpad, 0, xpad->idata, regs); |
188 | 187 | ||
189 | exit: | 188 | exit: |
@@ -196,25 +195,19 @@ exit: | |||
196 | static int xpad_open (struct input_dev *dev) | 195 | static int xpad_open (struct input_dev *dev) |
197 | { | 196 | { |
198 | struct usb_xpad *xpad = dev->private; | 197 | struct usb_xpad *xpad = dev->private; |
199 | 198 | ||
200 | if (xpad->open_count++) | ||
201 | return 0; | ||
202 | |||
203 | xpad->irq_in->dev = xpad->udev; | 199 | xpad->irq_in->dev = xpad->udev; |
204 | if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) { | 200 | if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) |
205 | xpad->open_count--; | ||
206 | return -EIO; | 201 | return -EIO; |
207 | } | 202 | |
208 | |||
209 | return 0; | 203 | return 0; |
210 | } | 204 | } |
211 | 205 | ||
212 | static void xpad_close (struct input_dev *dev) | 206 | static void xpad_close (struct input_dev *dev) |
213 | { | 207 | { |
214 | struct usb_xpad *xpad = dev->private; | 208 | struct usb_xpad *xpad = dev->private; |
215 | 209 | ||
216 | if (!--xpad->open_count) | 210 | usb_kill_urb(xpad->irq_in); |
217 | usb_kill_urb(xpad->irq_in); | ||
218 | } | 211 | } |
219 | 212 | ||
220 | static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) | 213 | static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) |
@@ -224,19 +217,19 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
224 | struct usb_endpoint_descriptor *ep_irq_in; | 217 | struct usb_endpoint_descriptor *ep_irq_in; |
225 | char path[64]; | 218 | char path[64]; |
226 | int i; | 219 | int i; |
227 | 220 | ||
228 | for (i = 0; xpad_device[i].idVendor; i++) { | 221 | for (i = 0; xpad_device[i].idVendor; i++) { |
229 | if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && | 222 | if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && |
230 | (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct)) | 223 | (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct)) |
231 | break; | 224 | break; |
232 | } | 225 | } |
233 | 226 | ||
234 | if ((xpad = kmalloc (sizeof(struct usb_xpad), GFP_KERNEL)) == NULL) { | 227 | if ((xpad = kmalloc (sizeof(struct usb_xpad), GFP_KERNEL)) == NULL) { |
235 | err("cannot allocate memory for new pad"); | 228 | err("cannot allocate memory for new pad"); |
236 | return -ENOMEM; | 229 | return -ENOMEM; |
237 | } | 230 | } |
238 | memset(xpad, 0, sizeof(struct usb_xpad)); | 231 | memset(xpad, 0, sizeof(struct usb_xpad)); |
239 | 232 | ||
240 | xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN, | 233 | xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN, |
241 | SLAB_ATOMIC, &xpad->idata_dma); | 234 | SLAB_ATOMIC, &xpad->idata_dma); |
242 | if (!xpad->idata) { | 235 | if (!xpad->idata) { |
@@ -251,18 +244,18 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
251 | kfree(xpad); | 244 | kfree(xpad); |
252 | return -ENOMEM; | 245 | return -ENOMEM; |
253 | } | 246 | } |
254 | 247 | ||
255 | ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; | 248 | ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; |
256 | 249 | ||
257 | usb_fill_int_urb(xpad->irq_in, udev, | 250 | usb_fill_int_urb(xpad->irq_in, udev, |
258 | usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), | 251 | usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), |
259 | xpad->idata, XPAD_PKT_LEN, xpad_irq_in, | 252 | xpad->idata, XPAD_PKT_LEN, xpad_irq_in, |
260 | xpad, ep_irq_in->bInterval); | 253 | xpad, ep_irq_in->bInterval); |
261 | xpad->irq_in->transfer_dma = xpad->idata_dma; | 254 | xpad->irq_in->transfer_dma = xpad->idata_dma; |
262 | xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 255 | xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
263 | 256 | ||
264 | xpad->udev = udev; | 257 | xpad->udev = udev; |
265 | 258 | ||
266 | xpad->dev.id.bustype = BUS_USB; | 259 | xpad->dev.id.bustype = BUS_USB; |
267 | xpad->dev.id.vendor = le16_to_cpu(udev->descriptor.idVendor); | 260 | xpad->dev.id.vendor = le16_to_cpu(udev->descriptor.idVendor); |
268 | xpad->dev.id.product = le16_to_cpu(udev->descriptor.idProduct); | 261 | xpad->dev.id.product = le16_to_cpu(udev->descriptor.idProduct); |
@@ -273,21 +266,21 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
273 | xpad->dev.phys = xpad->phys; | 266 | xpad->dev.phys = xpad->phys; |
274 | xpad->dev.open = xpad_open; | 267 | xpad->dev.open = xpad_open; |
275 | xpad->dev.close = xpad_close; | 268 | xpad->dev.close = xpad_close; |
276 | 269 | ||
277 | usb_make_path(udev, path, 64); | 270 | usb_make_path(udev, path, 64); |
278 | snprintf(xpad->phys, 64, "%s/input0", path); | 271 | snprintf(xpad->phys, 64, "%s/input0", path); |
279 | 272 | ||
280 | xpad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | 273 | xpad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); |
281 | 274 | ||
282 | for (i = 0; xpad_btn[i] >= 0; i++) | 275 | for (i = 0; xpad_btn[i] >= 0; i++) |
283 | set_bit(xpad_btn[i], xpad->dev.keybit); | 276 | set_bit(xpad_btn[i], xpad->dev.keybit); |
284 | 277 | ||
285 | for (i = 0; xpad_abs[i] >= 0; i++) { | 278 | for (i = 0; xpad_abs[i] >= 0; i++) { |
286 | 279 | ||
287 | signed short t = xpad_abs[i]; | 280 | signed short t = xpad_abs[i]; |
288 | 281 | ||
289 | set_bit(t, xpad->dev.absbit); | 282 | set_bit(t, xpad->dev.absbit); |
290 | 283 | ||
291 | switch (t) { | 284 | switch (t) { |
292 | case ABS_X: | 285 | case ABS_X: |
293 | case ABS_Y: | 286 | case ABS_Y: |
@@ -310,11 +303,11 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
310 | break; | 303 | break; |
311 | } | 304 | } |
312 | } | 305 | } |
313 | 306 | ||
314 | input_register_device(&xpad->dev); | 307 | input_register_device(&xpad->dev); |
315 | 308 | ||
316 | printk(KERN_INFO "input: %s on %s", xpad->dev.name, path); | 309 | printk(KERN_INFO "input: %s on %s", xpad->dev.name, path); |
317 | 310 | ||
318 | usb_set_intfdata(intf, xpad); | 311 | usb_set_intfdata(intf, xpad); |
319 | return 0; | 312 | return 0; |
320 | } | 313 | } |
@@ -322,7 +315,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
322 | static void xpad_disconnect(struct usb_interface *intf) | 315 | static void xpad_disconnect(struct usb_interface *intf) |
323 | { | 316 | { |
324 | struct usb_xpad *xpad = usb_get_intfdata (intf); | 317 | struct usb_xpad *xpad = usb_get_intfdata (intf); |
325 | 318 | ||
326 | usb_set_intfdata(intf, NULL); | 319 | usb_set_intfdata(intf, NULL); |
327 | if (xpad) { | 320 | if (xpad) { |
328 | usb_kill_urb(xpad->irq_in); | 321 | usb_kill_urb(xpad->irq_in); |
diff --git a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c index ae455c8e3702..7398a7f19c1e 100644 --- a/drivers/usb/media/stv680.c +++ b/drivers/usb/media/stv680.c | |||
@@ -1375,9 +1375,13 @@ static int stv680_probe (struct usb_interface *intf, const struct usb_device_id | |||
1375 | (le16_to_cpu(dev->descriptor.idProduct) == USB_PENCAM_PRODUCT_ID)) { | 1375 | (le16_to_cpu(dev->descriptor.idProduct) == USB_PENCAM_PRODUCT_ID)) { |
1376 | camera_name = "STV0680"; | 1376 | camera_name = "STV0680"; |
1377 | PDEBUG (0, "STV(i): STV0680 camera found."); | 1377 | PDEBUG (0, "STV(i): STV0680 camera found."); |
1378 | } else if ((le16_to_cpu(dev->descriptor.idVendor) == USB_CREATIVEGOMINI_VENDOR_ID) && | ||
1379 | (le16_to_cpu(dev->descriptor.idProduct) == USB_CREATIVEGOMINI_PRODUCT_ID)) { | ||
1380 | camera_name = "Creative WebCam Go Mini"; | ||
1381 | PDEBUG (0, "STV(i): Creative WebCam Go Mini found."); | ||
1378 | } else { | 1382 | } else { |
1379 | PDEBUG (0, "STV(e): Vendor/Product ID do not match STV0680 values."); | 1383 | PDEBUG (0, "STV(e): Vendor/Product ID do not match STV0680 or Creative WebCam Go Mini values."); |
1380 | PDEBUG (0, "STV(e): Check that the STV0680 camera is connected to the computer."); | 1384 | PDEBUG (0, "STV(e): Check that the STV0680 or Creative WebCam Go Mini camera is connected to the computer."); |
1381 | retval = -ENODEV; | 1385 | retval = -ENODEV; |
1382 | goto error; | 1386 | goto error; |
1383 | } | 1387 | } |
diff --git a/drivers/usb/media/stv680.h b/drivers/usb/media/stv680.h index 7e0e314dcf12..445940612603 100644 --- a/drivers/usb/media/stv680.h +++ b/drivers/usb/media/stv680.h | |||
@@ -41,12 +41,17 @@ | |||
41 | 41 | ||
42 | #define USB_PENCAM_VENDOR_ID 0x0553 | 42 | #define USB_PENCAM_VENDOR_ID 0x0553 |
43 | #define USB_PENCAM_PRODUCT_ID 0x0202 | 43 | #define USB_PENCAM_PRODUCT_ID 0x0202 |
44 | |||
45 | #define USB_CREATIVEGOMINI_VENDOR_ID 0x041e | ||
46 | #define USB_CREATIVEGOMINI_PRODUCT_ID 0x4007 | ||
47 | |||
44 | #define PENCAM_TIMEOUT 1000 | 48 | #define PENCAM_TIMEOUT 1000 |
45 | /* fmt 4 */ | 49 | /* fmt 4 */ |
46 | #define STV_VIDEO_PALETTE VIDEO_PALETTE_RGB24 | 50 | #define STV_VIDEO_PALETTE VIDEO_PALETTE_RGB24 |
47 | 51 | ||
48 | static struct usb_device_id device_table[] = { | 52 | static struct usb_device_id device_table[] = { |
49 | {USB_DEVICE (USB_PENCAM_VENDOR_ID, USB_PENCAM_PRODUCT_ID)}, | 53 | {USB_DEVICE (USB_PENCAM_VENDOR_ID, USB_PENCAM_PRODUCT_ID)}, |
54 | {USB_DEVICE (USB_CREATIVEGOMINI_VENDOR_ID, USB_CREATIVEGOMINI_PRODUCT_ID)}, | ||
50 | {} | 55 | {} |
51 | }; | 56 | }; |
52 | MODULE_DEVICE_TABLE (usb, device_table); | 57 | MODULE_DEVICE_TABLE (usb, device_table); |
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index ce030d1f1c1f..733acc213726 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Siemens ID Mouse driver v0.5 | 1 | /* Siemens ID Mouse driver v0.6 |
2 | 2 | ||
3 | This program is free software; you can redistribute it and/or | 3 | This program is free software; you can redistribute it and/or |
4 | modify it under the terms of the GNU General Public License as | 4 | modify it under the terms of the GNU General Public License as |
@@ -11,6 +11,9 @@ | |||
11 | Derived from the USB Skeleton driver 1.1, | 11 | Derived from the USB Skeleton driver 1.1, |
12 | Copyright (C) 2003 Greg Kroah-Hartman (greg@kroah.com) | 12 | Copyright (C) 2003 Greg Kroah-Hartman (greg@kroah.com) |
13 | 13 | ||
14 | Additional information provided by Martin Reising | ||
15 | <Martin.Reising@natural-computing.de> | ||
16 | |||
14 | */ | 17 | */ |
15 | 18 | ||
16 | #include <linux/config.h> | 19 | #include <linux/config.h> |
@@ -25,29 +28,44 @@ | |||
25 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
26 | #include <linux/usb.h> | 29 | #include <linux/usb.h> |
27 | 30 | ||
31 | /* image constants */ | ||
28 | #define WIDTH 225 | 32 | #define WIDTH 225 |
29 | #define HEIGHT 288 | 33 | #define HEIGHT 289 |
30 | #define HEADER "P5 225 288 255 " | 34 | #define HEADER "P5 225 289 255 " |
31 | #define IMGSIZE ((WIDTH * HEIGHT) + sizeof(HEADER)-1) | 35 | #define IMGSIZE ((WIDTH * HEIGHT) + sizeof(HEADER)-1) |
32 | 36 | ||
33 | /* Version Information */ | 37 | /* version information */ |
34 | #define DRIVER_VERSION "0.5" | 38 | #define DRIVER_VERSION "0.6" |
35 | #define DRIVER_SHORT "idmouse" | 39 | #define DRIVER_SHORT "idmouse" |
36 | #define DRIVER_AUTHOR "Florian 'Floe' Echtler <echtler@fs.tum.de>" | 40 | #define DRIVER_AUTHOR "Florian 'Floe' Echtler <echtler@fs.tum.de>" |
37 | #define DRIVER_DESC "Siemens ID Mouse FingerTIP Sensor Driver" | 41 | #define DRIVER_DESC "Siemens ID Mouse FingerTIP Sensor Driver" |
38 | 42 | ||
39 | /* Siemens ID Mouse */ | 43 | /* minor number for misc USB devices */ |
40 | #define USB_IDMOUSE_VENDOR_ID 0x0681 | ||
41 | #define USB_IDMOUSE_PRODUCT_ID 0x0005 | ||
42 | |||
43 | /* we still need a minor number */ | ||
44 | #define USB_IDMOUSE_MINOR_BASE 132 | 44 | #define USB_IDMOUSE_MINOR_BASE 132 |
45 | 45 | ||
46 | /* vendor and device IDs */ | ||
47 | #define ID_SIEMENS 0x0681 | ||
48 | #define ID_IDMOUSE 0x0005 | ||
49 | #define ID_CHERRY 0x0010 | ||
50 | |||
51 | /* device ID table */ | ||
46 | static struct usb_device_id idmouse_table[] = { | 52 | static struct usb_device_id idmouse_table[] = { |
47 | {USB_DEVICE(USB_IDMOUSE_VENDOR_ID, USB_IDMOUSE_PRODUCT_ID)}, | 53 | {USB_DEVICE(ID_SIEMENS, ID_IDMOUSE)}, /* Siemens ID Mouse (Professional) */ |
48 | {} /* null entry at the end */ | 54 | {USB_DEVICE(ID_SIEMENS, ID_CHERRY )}, /* Cherry FingerTIP ID Board */ |
55 | {} /* terminating null entry */ | ||
49 | }; | 56 | }; |
50 | 57 | ||
58 | /* sensor commands */ | ||
59 | #define FTIP_RESET 0x20 | ||
60 | #define FTIP_ACQUIRE 0x21 | ||
61 | #define FTIP_RELEASE 0x22 | ||
62 | #define FTIP_BLINK 0x23 /* LSB of value = blink pulse width */ | ||
63 | #define FTIP_SCROLL 0x24 | ||
64 | |||
65 | #define ftip_command(dev, command, value, index) \ | ||
66 | usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), command, \ | ||
67 | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, value, index, NULL, 0, 1000) | ||
68 | |||
51 | MODULE_DEVICE_TABLE(usb, idmouse_table); | 69 | MODULE_DEVICE_TABLE(usb, idmouse_table); |
52 | 70 | ||
53 | /* structure to hold all of our device specific stuff */ | 71 | /* structure to hold all of our device specific stuff */ |
@@ -57,7 +75,8 @@ struct usb_idmouse { | |||
57 | struct usb_interface *interface; /* the interface for this device */ | 75 | struct usb_interface *interface; /* the interface for this device */ |
58 | 76 | ||
59 | unsigned char *bulk_in_buffer; /* the buffer to receive data */ | 77 | unsigned char *bulk_in_buffer; /* the buffer to receive data */ |
60 | size_t bulk_in_size; /* the size of the receive buffer */ | 78 | size_t bulk_in_size; /* the maximum bulk packet size */ |
79 | size_t orig_bi_size; /* same as above, but reported by the device */ | ||
61 | __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ | 80 | __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ |
62 | 81 | ||
63 | int open; /* if the port is open or not */ | 82 | int open; /* if the port is open or not */ |
@@ -103,7 +122,7 @@ static struct usb_driver idmouse_driver = { | |||
103 | .id_table = idmouse_table, | 122 | .id_table = idmouse_table, |
104 | }; | 123 | }; |
105 | 124 | ||
106 | // prevent races between open() and disconnect() | 125 | /* prevent races between open() and disconnect() */ |
107 | static DECLARE_MUTEX(disconnect_sem); | 126 | static DECLARE_MUTEX(disconnect_sem); |
108 | 127 | ||
109 | static int idmouse_create_image(struct usb_idmouse *dev) | 128 | static int idmouse_create_image(struct usb_idmouse *dev) |
@@ -112,42 +131,34 @@ static int idmouse_create_image(struct usb_idmouse *dev) | |||
112 | int bulk_read = 0; | 131 | int bulk_read = 0; |
113 | int result = 0; | 132 | int result = 0; |
114 | 133 | ||
115 | if (dev->bulk_in_size < sizeof(HEADER)) | 134 | memcpy(dev->bulk_in_buffer, HEADER, sizeof(HEADER)-1); |
116 | return -ENOMEM; | ||
117 | |||
118 | memcpy(dev->bulk_in_buffer,HEADER,sizeof(HEADER)-1); | ||
119 | bytes_read += sizeof(HEADER)-1; | 135 | bytes_read += sizeof(HEADER)-1; |
120 | 136 | ||
121 | /* Dump the setup packets. Yes, they are uncommented, simply | 137 | /* reset the device and set a fast blink rate */ |
122 | because they were sniffed under Windows using SnoopyPro. | 138 | result = ftip_command(dev, FTIP_RELEASE, 0, 0); |
123 | I _guess_ that 0x22 is a kind of reset command and 0x21 | ||
124 | means init.. | ||
125 | */ | ||
126 | result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), | ||
127 | 0x21, 0x42, 0x0001, 0x0002, NULL, 0, 1000); | ||
128 | if (result < 0) | ||
129 | return result; | ||
130 | result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), | ||
131 | 0x20, 0x42, 0x0001, 0x0002, NULL, 0, 1000); | ||
132 | if (result < 0) | 139 | if (result < 0) |
133 | return result; | 140 | goto reset; |
134 | result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), | 141 | result = ftip_command(dev, FTIP_BLINK, 1, 0); |
135 | 0x22, 0x42, 0x0000, 0x0002, NULL, 0, 1000); | ||
136 | if (result < 0) | 142 | if (result < 0) |
137 | return result; | 143 | goto reset; |
138 | 144 | ||
139 | result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), | 145 | /* initialize the sensor - sending this command twice */ |
140 | 0x21, 0x42, 0x0001, 0x0002, NULL, 0, 1000); | 146 | /* significantly reduces the rate of failed reads */ |
147 | result = ftip_command(dev, FTIP_ACQUIRE, 0, 0); | ||
141 | if (result < 0) | 148 | if (result < 0) |
142 | return result; | 149 | goto reset; |
143 | result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), | 150 | result = ftip_command(dev, FTIP_ACQUIRE, 0, 0); |
144 | 0x20, 0x42, 0x0001, 0x0002, NULL, 0, 1000); | ||
145 | if (result < 0) | 151 | if (result < 0) |
146 | return result; | 152 | goto reset; |
147 | result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), | 153 | |
148 | 0x20, 0x42, 0x0000, 0x0002, NULL, 0, 1000); | 154 | /* start the readout - sending this command twice */ |
155 | /* presumably enables the high dynamic range mode */ | ||
156 | result = ftip_command(dev, FTIP_RESET, 0, 0); | ||
149 | if (result < 0) | 157 | if (result < 0) |
150 | return result; | 158 | goto reset; |
159 | result = ftip_command(dev, FTIP_RESET, 0, 0); | ||
160 | if (result < 0) | ||
161 | goto reset; | ||
151 | 162 | ||
152 | /* loop over a blocking bulk read to get data from the device */ | 163 | /* loop over a blocking bulk read to get data from the device */ |
153 | while (bytes_read < IMGSIZE) { | 164 | while (bytes_read < IMGSIZE) { |
@@ -155,22 +166,40 @@ static int idmouse_create_image(struct usb_idmouse *dev) | |||
155 | usb_rcvbulkpipe (dev->udev, dev->bulk_in_endpointAddr), | 166 | usb_rcvbulkpipe (dev->udev, dev->bulk_in_endpointAddr), |
156 | dev->bulk_in_buffer + bytes_read, | 167 | dev->bulk_in_buffer + bytes_read, |
157 | dev->bulk_in_size, &bulk_read, 5000); | 168 | dev->bulk_in_size, &bulk_read, 5000); |
158 | if (result < 0) | 169 | if (result < 0) { |
159 | return result; | 170 | /* Maybe this error was caused by the increased packet size? */ |
160 | if (signal_pending(current)) | 171 | /* Reset to the original value and tell userspace to retry. */ |
161 | return -EINTR; | 172 | if (dev->bulk_in_size != dev->orig_bi_size) { |
173 | dev->bulk_in_size = dev->orig_bi_size; | ||
174 | result = -EAGAIN; | ||
175 | } | ||
176 | break; | ||
177 | } | ||
178 | if (signal_pending(current)) { | ||
179 | result = -EINTR; | ||
180 | break; | ||
181 | } | ||
162 | bytes_read += bulk_read; | 182 | bytes_read += bulk_read; |
163 | } | 183 | } |
164 | 184 | ||
165 | /* reset the device */ | 185 | /* reset the device */ |
166 | result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0), | 186 | reset: |
167 | 0x22, 0x42, 0x0000, 0x0002, NULL, 0, 1000); | 187 | ftip_command(dev, FTIP_RELEASE, 0, 0); |
168 | if (result < 0) | 188 | |
169 | return result; | 189 | /* check for valid image */ |
190 | /* right border should be black (0x00) */ | ||
191 | for (bytes_read = sizeof(HEADER)-1 + WIDTH-1; bytes_read < IMGSIZE; bytes_read += WIDTH) | ||
192 | if (dev->bulk_in_buffer[bytes_read] != 0x00) | ||
193 | return -EAGAIN; | ||
170 | 194 | ||
171 | /* should be IMGSIZE == 64815 */ | 195 | /* lower border should be white (0xFF) */ |
196 | for (bytes_read = IMGSIZE-WIDTH; bytes_read < IMGSIZE-1; bytes_read++) | ||
197 | if (dev->bulk_in_buffer[bytes_read] != 0xFF) | ||
198 | return -EAGAIN; | ||
199 | |||
200 | /* should be IMGSIZE == 65040 */ | ||
172 | dbg("read %d bytes fingerprint data", bytes_read); | 201 | dbg("read %d bytes fingerprint data", bytes_read); |
173 | return 0; | 202 | return result; |
174 | } | 203 | } |
175 | 204 | ||
176 | static inline void idmouse_delete(struct usb_idmouse *dev) | 205 | static inline void idmouse_delete(struct usb_idmouse *dev) |
@@ -282,10 +311,10 @@ static ssize_t idmouse_read(struct file *file, char __user *buffer, size_t count | |||
282 | 311 | ||
283 | dev = (struct usb_idmouse *) file->private_data; | 312 | dev = (struct usb_idmouse *) file->private_data; |
284 | 313 | ||
285 | // lock this object | 314 | /* lock this object */ |
286 | down (&dev->sem); | 315 | down (&dev->sem); |
287 | 316 | ||
288 | // verify that the device wasn't unplugged | 317 | /* verify that the device wasn't unplugged */ |
289 | if (!dev->present) { | 318 | if (!dev->present) { |
290 | up (&dev->sem); | 319 | up (&dev->sem); |
291 | return -ENODEV; | 320 | return -ENODEV; |
@@ -296,8 +325,7 @@ static ssize_t idmouse_read(struct file *file, char __user *buffer, size_t count | |||
296 | return 0; | 325 | return 0; |
297 | } | 326 | } |
298 | 327 | ||
299 | if (count > IMGSIZE - *ppos) | 328 | count = min ((loff_t)count, IMGSIZE - (*ppos)); |
300 | count = IMGSIZE - *ppos; | ||
301 | 329 | ||
302 | if (copy_to_user (buffer, dev->bulk_in_buffer + *ppos, count)) { | 330 | if (copy_to_user (buffer, dev->bulk_in_buffer + *ppos, count)) { |
303 | result = -EFAULT; | 331 | result = -EFAULT; |
@@ -306,7 +334,7 @@ static ssize_t idmouse_read(struct file *file, char __user *buffer, size_t count | |||
306 | *ppos += count; | 334 | *ppos += count; |
307 | } | 335 | } |
308 | 336 | ||
309 | // unlock the device | 337 | /* unlock the device */ |
310 | up(&dev->sem); | 338 | up(&dev->sem); |
311 | return result; | 339 | return result; |
312 | } | 340 | } |
@@ -318,7 +346,6 @@ static int idmouse_probe(struct usb_interface *interface, | |||
318 | struct usb_idmouse *dev = NULL; | 346 | struct usb_idmouse *dev = NULL; |
319 | struct usb_host_interface *iface_desc; | 347 | struct usb_host_interface *iface_desc; |
320 | struct usb_endpoint_descriptor *endpoint; | 348 | struct usb_endpoint_descriptor *endpoint; |
321 | size_t buffer_size; | ||
322 | int result; | 349 | int result; |
323 | 350 | ||
324 | /* check if we have gotten the data or the hid interface */ | 351 | /* check if we have gotten the data or the hid interface */ |
@@ -344,11 +371,11 @@ static int idmouse_probe(struct usb_interface *interface, | |||
344 | USB_ENDPOINT_XFER_BULK)) { | 371 | USB_ENDPOINT_XFER_BULK)) { |
345 | 372 | ||
346 | /* we found a bulk in endpoint */ | 373 | /* we found a bulk in endpoint */ |
347 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); | 374 | dev->orig_bi_size = le16_to_cpu(endpoint->wMaxPacketSize); |
348 | dev->bulk_in_size = buffer_size; | 375 | dev->bulk_in_size = 0x200; /* works _much_ faster */ |
349 | dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; | 376 | dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; |
350 | dev->bulk_in_buffer = | 377 | dev->bulk_in_buffer = |
351 | kmalloc(IMGSIZE + buffer_size, GFP_KERNEL); | 378 | kmalloc(IMGSIZE + dev->bulk_in_size, GFP_KERNEL); |
352 | 379 | ||
353 | if (!dev->bulk_in_buffer) { | 380 | if (!dev->bulk_in_buffer) { |
354 | err("Unable to allocate input buffer."); | 381 | err("Unable to allocate input buffer."); |
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 3104f28f6aa8..cda7249a90b2 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c | |||
@@ -461,7 +461,7 @@ static int perform_sglist ( | |||
461 | 461 | ||
462 | static unsigned realworld = 1; | 462 | static unsigned realworld = 1; |
463 | module_param (realworld, uint, 0); | 463 | module_param (realworld, uint, 0); |
464 | MODULE_PARM_DESC (realworld, "clear to demand stricter ch9 compliance"); | 464 | MODULE_PARM_DESC (realworld, "clear to demand stricter spec compliance"); |
465 | 465 | ||
466 | static int get_altsetting (struct usbtest_dev *dev) | 466 | static int get_altsetting (struct usbtest_dev *dev) |
467 | { | 467 | { |
@@ -604,9 +604,8 @@ static int ch9_postconfig (struct usbtest_dev *dev) | |||
604 | USB_DIR_IN | USB_RECIP_DEVICE, | 604 | USB_DIR_IN | USB_RECIP_DEVICE, |
605 | 0, 0, dev->buf, 1, USB_CTRL_GET_TIMEOUT); | 605 | 0, 0, dev->buf, 1, USB_CTRL_GET_TIMEOUT); |
606 | if (retval != 1 || dev->buf [0] != expected) { | 606 | if (retval != 1 || dev->buf [0] != expected) { |
607 | dev_dbg (&iface->dev, | 607 | dev_dbg (&iface->dev, "get config --> %d %d (1 %d)\n", |
608 | "get config --> %d (%d)\n", retval, | 608 | retval, dev->buf[0], expected); |
609 | expected); | ||
610 | return (retval < 0) ? retval : -EDOM; | 609 | return (retval < 0) ? retval : -EDOM; |
611 | } | 610 | } |
612 | } | 611 | } |
@@ -1243,7 +1242,7 @@ static int ctrl_out (struct usbtest_dev *dev, | |||
1243 | char *what = "?"; | 1242 | char *what = "?"; |
1244 | struct usb_device *udev; | 1243 | struct usb_device *udev; |
1245 | 1244 | ||
1246 | if (length > 0xffff || vary >= length) | 1245 | if (length < 1 || length > 0xffff || vary >= length) |
1247 | return -EINVAL; | 1246 | return -EINVAL; |
1248 | 1247 | ||
1249 | buf = kmalloc(length, SLAB_KERNEL); | 1248 | buf = kmalloc(length, SLAB_KERNEL); |
@@ -1266,6 +1265,11 @@ static int ctrl_out (struct usbtest_dev *dev, | |||
1266 | 0, 0, buf, len, USB_CTRL_SET_TIMEOUT); | 1265 | 0, 0, buf, len, USB_CTRL_SET_TIMEOUT); |
1267 | if (retval != len) { | 1266 | if (retval != len) { |
1268 | what = "write"; | 1267 | what = "write"; |
1268 | if (retval >= 0) { | ||
1269 | INFO(dev, "ctrl_out, wlen %d (expected %d)\n", | ||
1270 | retval, len); | ||
1271 | retval = -EBADMSG; | ||
1272 | } | ||
1269 | break; | 1273 | break; |
1270 | } | 1274 | } |
1271 | 1275 | ||
@@ -1275,6 +1279,11 @@ static int ctrl_out (struct usbtest_dev *dev, | |||
1275 | 0, 0, buf, len, USB_CTRL_GET_TIMEOUT); | 1279 | 0, 0, buf, len, USB_CTRL_GET_TIMEOUT); |
1276 | if (retval != len) { | 1280 | if (retval != len) { |
1277 | what = "read"; | 1281 | what = "read"; |
1282 | if (retval >= 0) { | ||
1283 | INFO(dev, "ctrl_out, rlen %d (expected %d)\n", | ||
1284 | retval, len); | ||
1285 | retval = -EBADMSG; | ||
1286 | } | ||
1278 | break; | 1287 | break; |
1279 | } | 1288 | } |
1280 | 1289 | ||
@@ -1293,8 +1302,13 @@ static int ctrl_out (struct usbtest_dev *dev, | |||
1293 | } | 1302 | } |
1294 | 1303 | ||
1295 | len += vary; | 1304 | len += vary; |
1305 | |||
1306 | /* [real world] the "zero bytes IN" case isn't really used. | ||
1307 | * hardware can easily trip up in this wierd case, since its | ||
1308 | * status stage is IN, not OUT like other ep0in transfers. | ||
1309 | */ | ||
1296 | if (len > length) | 1310 | if (len > length) |
1297 | len = 0; | 1311 | len = realworld ? 1 : 0; |
1298 | } | 1312 | } |
1299 | 1313 | ||
1300 | if (retval < 0) | 1314 | if (retval < 0) |
@@ -1519,6 +1533,11 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) | |||
1519 | if (down_interruptible (&dev->sem)) | 1533 | if (down_interruptible (&dev->sem)) |
1520 | return -ERESTARTSYS; | 1534 | return -ERESTARTSYS; |
1521 | 1535 | ||
1536 | if (intf->dev.power.power_state != PMSG_ON) { | ||
1537 | up (&dev->sem); | ||
1538 | return -EHOSTUNREACH; | ||
1539 | } | ||
1540 | |||
1522 | /* some devices, like ez-usb default devices, need a non-default | 1541 | /* some devices, like ez-usb default devices, need a non-default |
1523 | * altsetting to have any active endpoints. some tests change | 1542 | * altsetting to have any active endpoints. some tests change |
1524 | * altsettings; force a default so most tests don't need to check. | 1543 | * altsettings; force a default so most tests don't need to check. |
@@ -1762,8 +1781,10 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) | |||
1762 | case 14: | 1781 | case 14: |
1763 | if (!dev->info->ctrl_out) | 1782 | if (!dev->info->ctrl_out) |
1764 | break; | 1783 | break; |
1765 | dev_dbg (&intf->dev, "TEST 14: %d ep0out, 0..%d vary %d\n", | 1784 | dev_dbg (&intf->dev, "TEST 14: %d ep0out, %d..%d vary %d\n", |
1766 | param->iterations, param->length, param->vary); | 1785 | param->iterations, |
1786 | realworld ? 1 : 0, param->length, | ||
1787 | param->vary); | ||
1767 | retval = ctrl_out (dev, param->iterations, | 1788 | retval = ctrl_out (dev, param->iterations, |
1768 | param->length, param->vary); | 1789 | param->length, param->vary); |
1769 | break; | 1790 | break; |
@@ -1927,6 +1948,27 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) | |||
1927 | return 0; | 1948 | return 0; |
1928 | } | 1949 | } |
1929 | 1950 | ||
1951 | static int usbtest_suspend (struct usb_interface *intf, pm_message_t message) | ||
1952 | { | ||
1953 | struct usbtest_dev *dev = usb_get_intfdata (intf); | ||
1954 | |||
1955 | down (&dev->sem); | ||
1956 | intf->dev.power.power_state = PMSG_SUSPEND; | ||
1957 | up (&dev->sem); | ||
1958 | return 0; | ||
1959 | } | ||
1960 | |||
1961 | static int usbtest_resume (struct usb_interface *intf) | ||
1962 | { | ||
1963 | struct usbtest_dev *dev = usb_get_intfdata (intf); | ||
1964 | |||
1965 | down (&dev->sem); | ||
1966 | intf->dev.power.power_state = PMSG_ON; | ||
1967 | up (&dev->sem); | ||
1968 | return 0; | ||
1969 | } | ||
1970 | |||
1971 | |||
1930 | static void usbtest_disconnect (struct usb_interface *intf) | 1972 | static void usbtest_disconnect (struct usb_interface *intf) |
1931 | { | 1973 | { |
1932 | struct usbtest_dev *dev = usb_get_intfdata (intf); | 1974 | struct usbtest_dev *dev = usb_get_intfdata (intf); |
@@ -2115,6 +2157,8 @@ static struct usb_driver usbtest_driver = { | |||
2115 | .probe = usbtest_probe, | 2157 | .probe = usbtest_probe, |
2116 | .ioctl = usbtest_ioctl, | 2158 | .ioctl = usbtest_ioctl, |
2117 | .disconnect = usbtest_disconnect, | 2159 | .disconnect = usbtest_disconnect, |
2160 | .suspend = usbtest_suspend, | ||
2161 | .resume = usbtest_resume, | ||
2118 | }; | 2162 | }; |
2119 | 2163 | ||
2120 | /*-------------------------------------------------------------------------*/ | 2164 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index d976790312aa..5f4496d8dbac 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c | |||
@@ -1166,7 +1166,7 @@ static void pegasus_set_multicast(struct net_device *net) | |||
1166 | pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS; | 1166 | pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS; |
1167 | if (netif_msg_link(pegasus)) | 1167 | if (netif_msg_link(pegasus)) |
1168 | pr_info("%s: Promiscuous mode enabled.\n", net->name); | 1168 | pr_info("%s: Promiscuous mode enabled.\n", net->name); |
1169 | } else if ((net->mc_count > multicast_filter_limit) || | 1169 | } else if (net->mc_count || |
1170 | (net->flags & IFF_ALLMULTI)) { | 1170 | (net->flags & IFF_ALLMULTI)) { |
1171 | pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST; | 1171 | pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST; |
1172 | pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS; | 1172 | pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS; |
diff --git a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h index 13ccedef5c7e..b98f2a833442 100644 --- a/drivers/usb/net/pegasus.h +++ b/drivers/usb/net/pegasus.h | |||
@@ -249,6 +249,8 @@ PEGASUS_DEV( "Kingston KNU101TX Ethernet", VENDOR_KINGSTON, 0x000a, | |||
249 | DEFAULT_GPIO_RESET) | 249 | DEFAULT_GPIO_RESET) |
250 | PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002, | 250 | PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002, |
251 | DEFAULT_GPIO_RESET ) | 251 | DEFAULT_GPIO_RESET ) |
252 | PEGASUS_DEV( "LANEED USB Ethernet LD-USBL/TX", VENDOR_LANEED, 0x4005, | ||
253 | DEFAULT_GPIO_RESET | PEGASUS_II) | ||
252 | PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x400b, | 254 | PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x400b, |
253 | DEFAULT_GPIO_RESET | PEGASUS_II ) | 255 | DEFAULT_GPIO_RESET | PEGASUS_II ) |
254 | PEGASUS_DEV( "LANEED USB Ethernet LD-USB/T", VENDOR_LANEED, 0xabc1, | 256 | PEGASUS_DEV( "LANEED USB Ethernet LD-USB/T", VENDOR_LANEED, 0xabc1, |
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c index 8fb223385f2f..626b016addff 100644 --- a/drivers/usb/net/rtl8150.c +++ b/drivers/usb/net/rtl8150.c | |||
@@ -667,7 +667,7 @@ static void rtl8150_set_multicast(struct net_device *netdev) | |||
667 | if (netdev->flags & IFF_PROMISC) { | 667 | if (netdev->flags & IFF_PROMISC) { |
668 | dev->rx_creg |= cpu_to_le16(0x0001); | 668 | dev->rx_creg |= cpu_to_le16(0x0001); |
669 | info("%s: promiscuous mode", netdev->name); | 669 | info("%s: promiscuous mode", netdev->name); |
670 | } else if ((netdev->mc_count > multicast_filter_limit) || | 670 | } else if (netdev->mc_count || |
671 | (netdev->flags & IFF_ALLMULTI)) { | 671 | (netdev->flags & IFF_ALLMULTI)) { |
672 | dev->rx_creg &= cpu_to_le16(0xfffe); | 672 | dev->rx_creg &= cpu_to_le16(0xfffe); |
673 | dev->rx_creg |= cpu_to_le16(0x0002); | 673 | dev->rx_creg |= cpu_to_le16(0x0002); |
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index 4cbb408af727..8a945f4f3693 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c | |||
@@ -1429,7 +1429,7 @@ static int generic_cdc_bind (struct usbnet *dev, struct usb_interface *intf) | |||
1429 | info->ether = (void *) buf; | 1429 | info->ether = (void *) buf; |
1430 | if (info->ether->bLength != sizeof *info->ether) { | 1430 | if (info->ether->bLength != sizeof *info->ether) { |
1431 | dev_dbg (&intf->dev, "CDC ether len %u\n", | 1431 | dev_dbg (&intf->dev, "CDC ether len %u\n", |
1432 | info->u->bLength); | 1432 | info->ether->bLength); |
1433 | goto bad_desc; | 1433 | goto bad_desc; |
1434 | } | 1434 | } |
1435 | dev->net->mtu = le16_to_cpup ( | 1435 | dev->net->mtu = le16_to_cpup ( |
diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c index 341ae5f732dd..3b387b005739 100644 --- a/drivers/usb/net/zd1201.c +++ b/drivers/usb/net/zd1201.c | |||
@@ -1884,12 +1884,53 @@ static void zd1201_disconnect(struct usb_interface *interface) | |||
1884 | kfree(zd); | 1884 | kfree(zd); |
1885 | } | 1885 | } |
1886 | 1886 | ||
1887 | #ifdef CONFIG_PM | ||
1888 | |||
1889 | static int zd1201_suspend(struct usb_interface *interface, | ||
1890 | pm_message_t message) | ||
1891 | { | ||
1892 | struct zd1201 *zd = usb_get_intfdata(interface); | ||
1893 | |||
1894 | netif_device_detach(zd->dev); | ||
1895 | |||
1896 | zd->was_enabled = zd->mac_enabled; | ||
1897 | |||
1898 | if (zd->was_enabled) | ||
1899 | return zd1201_disable(zd); | ||
1900 | else | ||
1901 | return 0; | ||
1902 | } | ||
1903 | |||
1904 | static int zd1201_resume(struct usb_interface *interface) | ||
1905 | { | ||
1906 | struct zd1201 *zd = usb_get_intfdata(interface); | ||
1907 | |||
1908 | if (!zd || !zd->dev) | ||
1909 | return -ENODEV; | ||
1910 | |||
1911 | netif_device_attach(zd->dev); | ||
1912 | |||
1913 | if (zd->was_enabled) | ||
1914 | return zd1201_enable(zd); | ||
1915 | else | ||
1916 | return 0; | ||
1917 | } | ||
1918 | |||
1919 | #else | ||
1920 | |||
1921 | #define zd1201_suspend NULL | ||
1922 | #define zd1201_resume NULL | ||
1923 | |||
1924 | #endif | ||
1925 | |||
1887 | static struct usb_driver zd1201_usb = { | 1926 | static struct usb_driver zd1201_usb = { |
1888 | .owner = THIS_MODULE, | 1927 | .owner = THIS_MODULE, |
1889 | .name = "zd1201", | 1928 | .name = "zd1201", |
1890 | .probe = zd1201_probe, | 1929 | .probe = zd1201_probe, |
1891 | .disconnect = zd1201_disconnect, | 1930 | .disconnect = zd1201_disconnect, |
1892 | .id_table = zd1201_table, | 1931 | .id_table = zd1201_table, |
1932 | .suspend = zd1201_suspend, | ||
1933 | .resume = zd1201_resume, | ||
1893 | }; | 1934 | }; |
1894 | 1935 | ||
1895 | static int __init zd1201_init(void) | 1936 | static int __init zd1201_init(void) |
diff --git a/drivers/usb/net/zd1201.h b/drivers/usb/net/zd1201.h index 1627c71e8052..235f0ee34b24 100644 --- a/drivers/usb/net/zd1201.h +++ b/drivers/usb/net/zd1201.h | |||
@@ -46,6 +46,7 @@ struct zd1201 { | |||
46 | char essid[IW_ESSID_MAX_SIZE+1]; | 46 | char essid[IW_ESSID_MAX_SIZE+1]; |
47 | int essidlen; | 47 | int essidlen; |
48 | int mac_enabled; | 48 | int mac_enabled; |
49 | int was_enabled; | ||
49 | int monitor; | 50 | int monitor; |
50 | int encode_enabled; | 51 | int encode_enabled; |
51 | int encode_restricted; | 52 | int encode_restricted; |
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 46a204cd40e1..b5b431067b08 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c | |||
@@ -213,10 +213,14 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b | |||
213 | return (0); | 213 | return (0); |
214 | } | 214 | } |
215 | 215 | ||
216 | if (port->write_urb->status == -EINPROGRESS) { | 216 | spin_lock(&port->lock); |
217 | if (port->write_urb_busy) { | ||
218 | spin_unlock(&port->lock); | ||
217 | dbg("%s - already writing", __FUNCTION__); | 219 | dbg("%s - already writing", __FUNCTION__); |
218 | return (0); | 220 | return 0; |
219 | } | 221 | } |
222 | port->write_urb_busy = 1; | ||
223 | spin_unlock(&port->lock); | ||
220 | 224 | ||
221 | spin_lock_irqsave(&priv->lock, flags); | 225 | spin_lock_irqsave(&priv->lock, flags); |
222 | 226 | ||
@@ -224,6 +228,7 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b | |||
224 | /* To much data for buffer. Reset buffer. */ | 228 | /* To much data for buffer. Reset buffer. */ |
225 | priv->wrfilled=0; | 229 | priv->wrfilled=0; |
226 | spin_unlock_irqrestore(&priv->lock, flags); | 230 | spin_unlock_irqrestore(&priv->lock, flags); |
231 | port->write_urb_busy = 0; | ||
227 | return (0); | 232 | return (0); |
228 | } | 233 | } |
229 | 234 | ||
@@ -268,6 +273,7 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b | |||
268 | priv->wrfilled=0; | 273 | priv->wrfilled=0; |
269 | priv->wrsent=0; | 274 | priv->wrsent=0; |
270 | spin_unlock_irqrestore(&priv->lock, flags); | 275 | spin_unlock_irqrestore(&priv->lock, flags); |
276 | port->write_urb_busy = 0; | ||
271 | return 0; | 277 | return 0; |
272 | } | 278 | } |
273 | 279 | ||
@@ -412,7 +418,8 @@ static void cyberjack_write_bulk_callback (struct urb *urb, struct pt_regs *regs | |||
412 | struct cyberjack_private *priv = usb_get_serial_port_data(port); | 418 | struct cyberjack_private *priv = usb_get_serial_port_data(port); |
413 | 419 | ||
414 | dbg("%s - port %d", __FUNCTION__, port->number); | 420 | dbg("%s - port %d", __FUNCTION__, port->number); |
415 | 421 | ||
422 | port->write_urb_busy = 0; | ||
416 | if (urb->status) { | 423 | if (urb->status) { |
417 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 424 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); |
418 | return; | 425 | return; |
@@ -424,12 +431,6 @@ static void cyberjack_write_bulk_callback (struct urb *urb, struct pt_regs *regs | |||
424 | if( priv->wrfilled ) { | 431 | if( priv->wrfilled ) { |
425 | int length, blksize, result; | 432 | int length, blksize, result; |
426 | 433 | ||
427 | if (port->write_urb->status == -EINPROGRESS) { | ||
428 | dbg("%s - already writing", __FUNCTION__); | ||
429 | spin_unlock(&priv->lock); | ||
430 | return; | ||
431 | } | ||
432 | |||
433 | dbg("%s - transmitting data (frame n)", __FUNCTION__); | 434 | dbg("%s - transmitting data (frame n)", __FUNCTION__); |
434 | 435 | ||
435 | length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ? | 436 | length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ? |
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 99214aa3cd19..ddde5fb13f6b 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -174,10 +174,14 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char * | |||
174 | 174 | ||
175 | /* only do something if we have a bulk out endpoint */ | 175 | /* only do something if we have a bulk out endpoint */ |
176 | if (serial->num_bulk_out) { | 176 | if (serial->num_bulk_out) { |
177 | if (port->write_urb->status == -EINPROGRESS) { | 177 | spin_lock(&port->lock); |
178 | if (port->write_urb_busy) { | ||
179 | spin_unlock(&port->lock); | ||
178 | dbg("%s - already writing", __FUNCTION__); | 180 | dbg("%s - already writing", __FUNCTION__); |
179 | return (0); | 181 | return 0; |
180 | } | 182 | } |
183 | port->write_urb_busy = 1; | ||
184 | spin_unlock(&port->lock); | ||
181 | 185 | ||
182 | count = (count > port->bulk_out_size) ? port->bulk_out_size : count; | 186 | count = (count > port->bulk_out_size) ? port->bulk_out_size : count; |
183 | 187 | ||
@@ -195,17 +199,20 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char * | |||
195 | usb_serial_generic_write_bulk_callback), port); | 199 | usb_serial_generic_write_bulk_callback), port); |
196 | 200 | ||
197 | /* send the data out the bulk port */ | 201 | /* send the data out the bulk port */ |
202 | port->write_urb_busy = 1; | ||
198 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | 203 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); |
199 | if (result) | 204 | if (result) { |
200 | dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); | 205 | dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); |
201 | else | 206 | /* don't have to grab the lock here, as we will retry if != 0 */ |
207 | port->write_urb_busy = 0; | ||
208 | } else | ||
202 | result = count; | 209 | result = count; |
203 | 210 | ||
204 | return result; | 211 | return result; |
205 | } | 212 | } |
206 | 213 | ||
207 | /* no bulk out, so return 0 bytes written */ | 214 | /* no bulk out, so return 0 bytes written */ |
208 | return (0); | 215 | return 0; |
209 | } | 216 | } |
210 | 217 | ||
211 | int usb_serial_generic_write_room (struct usb_serial_port *port) | 218 | int usb_serial_generic_write_room (struct usb_serial_port *port) |
@@ -214,9 +221,9 @@ int usb_serial_generic_write_room (struct usb_serial_port *port) | |||
214 | int room = 0; | 221 | int room = 0; |
215 | 222 | ||
216 | dbg("%s - port %d", __FUNCTION__, port->number); | 223 | dbg("%s - port %d", __FUNCTION__, port->number); |
217 | 224 | ||
218 | if (serial->num_bulk_out) { | 225 | if (serial->num_bulk_out) { |
219 | if (port->write_urb->status != -EINPROGRESS) | 226 | if (port->write_urb_busy) |
220 | room = port->bulk_out_size; | 227 | room = port->bulk_out_size; |
221 | } | 228 | } |
222 | 229 | ||
@@ -232,7 +239,7 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port) | |||
232 | dbg("%s - port %d", __FUNCTION__, port->number); | 239 | dbg("%s - port %d", __FUNCTION__, port->number); |
233 | 240 | ||
234 | if (serial->num_bulk_out) { | 241 | if (serial->num_bulk_out) { |
235 | if (port->write_urb->status == -EINPROGRESS) | 242 | if (port->write_urb_busy) |
236 | chars = port->write_urb->transfer_buffer_length; | 243 | chars = port->write_urb->transfer_buffer_length; |
237 | } | 244 | } |
238 | 245 | ||
@@ -291,6 +298,7 @@ void usb_serial_generic_write_bulk_callback (struct urb *urb, struct pt_regs *re | |||
291 | 298 | ||
292 | dbg("%s - port %d", __FUNCTION__, port->number); | 299 | dbg("%s - port %d", __FUNCTION__, port->number); |
293 | 300 | ||
301 | port->write_urb_busy = 0; | ||
294 | if (urb->status) { | 302 | if (urb->status) { |
295 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 303 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); |
296 | return; | 304 | return; |
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 3bd69c4ef24b..c05c2a2a0f31 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c | |||
@@ -818,11 +818,6 @@ static void ipaq_write_gather(struct usb_serial_port *port) | |||
818 | struct ipaq_packet *pkt, *tmp; | 818 | struct ipaq_packet *pkt, *tmp; |
819 | struct urb *urb = port->write_urb; | 819 | struct urb *urb = port->write_urb; |
820 | 820 | ||
821 | if (urb->status == -EINPROGRESS) { | ||
822 | /* Should never happen */ | ||
823 | err("%s - flushing while urb is active !", __FUNCTION__); | ||
824 | return; | ||
825 | } | ||
826 | room = URBDATA_SIZE; | 821 | room = URBDATA_SIZE; |
827 | list_for_each_entry_safe(pkt, tmp, &priv->queue, list) { | 822 | list_for_each_entry_safe(pkt, tmp, &priv->queue, list) { |
828 | count = min(room, (int)(pkt->len - pkt->written)); | 823 | count = min(room, (int)(pkt->len - pkt->written)); |
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 11105d74f461..85e242459c27 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c | |||
@@ -399,16 +399,21 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int | |||
399 | dbg("%s - write request of 0 bytes", __FUNCTION__); | 399 | dbg("%s - write request of 0 bytes", __FUNCTION__); |
400 | return 0; | 400 | return 0; |
401 | } | 401 | } |
402 | 402 | ||
403 | /* Racy and broken, FIXME properly! */ | 403 | spin_lock(&port->lock); |
404 | if (port->write_urb->status == -EINPROGRESS) | 404 | if (port->write_urb_busy) { |
405 | spin_unlock(&port->lock); | ||
406 | dbg("%s - already writing", __FUNCTION__); | ||
405 | return 0; | 407 | return 0; |
408 | } | ||
409 | port->write_urb_busy = 1; | ||
410 | spin_unlock(&port->lock); | ||
406 | 411 | ||
407 | count = min(count, port->bulk_out_size); | 412 | count = min(count, port->bulk_out_size); |
408 | memcpy(port->bulk_out_buffer, buf, count); | 413 | memcpy(port->bulk_out_buffer, buf, count); |
409 | 414 | ||
410 | dbg("%s count now:%d", __FUNCTION__, count); | 415 | dbg("%s count now:%d", __FUNCTION__, count); |
411 | 416 | ||
412 | usb_fill_bulk_urb(port->write_urb, dev, | 417 | usb_fill_bulk_urb(port->write_urb, dev, |
413 | usb_sndbulkpipe(dev, port->bulk_out_endpointAddress), | 418 | usb_sndbulkpipe(dev, port->bulk_out_endpointAddress), |
414 | port->write_urb->transfer_buffer, | 419 | port->write_urb->transfer_buffer, |
@@ -418,6 +423,7 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int | |||
418 | 423 | ||
419 | ret = usb_submit_urb(port->write_urb, GFP_ATOMIC); | 424 | ret = usb_submit_urb(port->write_urb, GFP_ATOMIC); |
420 | if (ret != 0) { | 425 | if (ret != 0) { |
426 | port->write_urb_busy = 0; | ||
421 | dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __FUNCTION__, ret); | 427 | dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __FUNCTION__, ret); |
422 | return ret; | 428 | return ret; |
423 | } | 429 | } |
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 59f234df5f89..937b2fdd7171 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c | |||
@@ -341,10 +341,14 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int | |||
341 | if (count == 0) | 341 | if (count == 0) |
342 | return 0; | 342 | return 0; |
343 | 343 | ||
344 | if (port->write_urb->status == -EINPROGRESS) { | 344 | spin_lock(&port->lock); |
345 | dbg ("%s - already writing", __FUNCTION__); | 345 | if (port->write_urb_busy) { |
346 | spin_unlock(&port->lock); | ||
347 | dbg("%s - already writing", __FUNCTION__); | ||
346 | return 0; | 348 | return 0; |
347 | } | 349 | } |
350 | port->write_urb_busy = 1; | ||
351 | spin_unlock(&port->lock); | ||
348 | 352 | ||
349 | transfer_buffer = port->write_urb->transfer_buffer; | 353 | transfer_buffer = port->write_urb->transfer_buffer; |
350 | transfer_size = min(count, port->bulk_out_size - 1); | 354 | transfer_size = min(count, port->bulk_out_size - 1); |
@@ -374,9 +378,10 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int | |||
374 | port->write_urb->transfer_flags = URB_ZERO_PACKET; | 378 | port->write_urb->transfer_flags = URB_ZERO_PACKET; |
375 | 379 | ||
376 | result = usb_submit_urb (port->write_urb, GFP_ATOMIC); | 380 | result = usb_submit_urb (port->write_urb, GFP_ATOMIC); |
377 | if (result) | 381 | if (result) { |
382 | port->write_urb_busy = 0; | ||
378 | dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); | 383 | dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); |
379 | else | 384 | } else |
380 | result = transfer_size; | 385 | result = transfer_size; |
381 | 386 | ||
382 | return result; | 387 | return result; |
@@ -387,7 +392,8 @@ static void ir_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
387 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 392 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
388 | 393 | ||
389 | dbg("%s - port %d", __FUNCTION__, port->number); | 394 | dbg("%s - port %d", __FUNCTION__, port->number); |
390 | 395 | ||
396 | port->write_urb_busy = 0; | ||
391 | if (urb->status) { | 397 | if (urb->status) { |
392 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 398 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); |
393 | return; | 399 | return; |
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 7fd0aa9eccf6..635c384cb15a 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c | |||
@@ -520,9 +520,13 @@ static int keyspan_pda_write(struct usb_serial_port *port, | |||
520 | the TX urb is in-flight (wait until it completes) | 520 | the TX urb is in-flight (wait until it completes) |
521 | the device is full (wait until it says there is room) | 521 | the device is full (wait until it says there is room) |
522 | */ | 522 | */ |
523 | if (port->write_urb->status == -EINPROGRESS || priv->tx_throttled ) { | 523 | spin_lock(&port->lock); |
524 | return( 0 ); | 524 | if (port->write_urb_busy || priv->tx_throttled) { |
525 | spin_unlock(&port->lock); | ||
526 | return 0; | ||
525 | } | 527 | } |
528 | port->write_urb_busy = 1; | ||
529 | spin_unlock(&port->lock); | ||
526 | 530 | ||
527 | /* At this point the URB is in our control, nobody else can submit it | 531 | /* At this point the URB is in our control, nobody else can submit it |
528 | again (the only sudden transition was the one from EINPROGRESS to | 532 | again (the only sudden transition was the one from EINPROGRESS to |
@@ -570,7 +574,7 @@ static int keyspan_pda_write(struct usb_serial_port *port, | |||
570 | memcpy (port->write_urb->transfer_buffer, buf, count); | 574 | memcpy (port->write_urb->transfer_buffer, buf, count); |
571 | /* send the data out the bulk port */ | 575 | /* send the data out the bulk port */ |
572 | port->write_urb->transfer_buffer_length = count; | 576 | port->write_urb->transfer_buffer_length = count; |
573 | 577 | ||
574 | priv->tx_room -= count; | 578 | priv->tx_room -= count; |
575 | 579 | ||
576 | port->write_urb->dev = port->serial->dev; | 580 | port->write_urb->dev = port->serial->dev; |
@@ -593,6 +597,8 @@ static int keyspan_pda_write(struct usb_serial_port *port, | |||
593 | 597 | ||
594 | rc = count; | 598 | rc = count; |
595 | exit: | 599 | exit: |
600 | if (rc < 0) | ||
601 | port->write_urb_busy = 0; | ||
596 | return rc; | 602 | return rc; |
597 | } | 603 | } |
598 | 604 | ||
@@ -602,6 +608,7 @@ static void keyspan_pda_write_bulk_callback (struct urb *urb, struct pt_regs *re | |||
602 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 608 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
603 | struct keyspan_pda_private *priv; | 609 | struct keyspan_pda_private *priv; |
604 | 610 | ||
611 | port->write_urb_busy = 0; | ||
605 | priv = usb_get_serial_port_data(port); | 612 | priv = usb_get_serial_port_data(port); |
606 | 613 | ||
607 | /* queue up a wakeup at scheduler time */ | 614 | /* queue up a wakeup at scheduler time */ |
@@ -626,12 +633,12 @@ static int keyspan_pda_write_room (struct usb_serial_port *port) | |||
626 | static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port) | 633 | static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port) |
627 | { | 634 | { |
628 | struct keyspan_pda_private *priv; | 635 | struct keyspan_pda_private *priv; |
629 | 636 | ||
630 | priv = usb_get_serial_port_data(port); | 637 | priv = usb_get_serial_port_data(port); |
631 | 638 | ||
632 | /* when throttled, return at least WAKEUP_CHARS to tell select() (via | 639 | /* when throttled, return at least WAKEUP_CHARS to tell select() (via |
633 | n_tty.c:normal_poll() ) that we're not writeable. */ | 640 | n_tty.c:normal_poll() ) that we're not writeable. */ |
634 | if( port->write_urb->status == -EINPROGRESS || priv->tx_throttled ) | 641 | if (port->write_urb_busy || priv->tx_throttled) |
635 | return 256; | 642 | return 256; |
636 | return 0; | 643 | return 0; |
637 | } | 644 | } |
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index b5f2c06d4f3e..6a99ae192df1 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c | |||
@@ -254,10 +254,15 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf | |||
254 | dbg("%s - write request of 0 bytes", __FUNCTION__); | 254 | dbg("%s - write request of 0 bytes", __FUNCTION__); |
255 | return (0); | 255 | return (0); |
256 | } | 256 | } |
257 | if (wport->write_urb->status == -EINPROGRESS) { | 257 | |
258 | spin_lock(&port->lock); | ||
259 | if (port->write_urb_busy) { | ||
260 | spin_unlock(&port->lock); | ||
258 | dbg("%s - already writing", __FUNCTION__); | 261 | dbg("%s - already writing", __FUNCTION__); |
259 | return (0); | 262 | return 0; |
260 | } | 263 | } |
264 | port->write_urb_busy = 1; | ||
265 | spin_unlock(&port->lock); | ||
261 | 266 | ||
262 | count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count; | 267 | count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count; |
263 | 268 | ||
@@ -275,9 +280,10 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf | |||
275 | 280 | ||
276 | wport->write_urb->dev = serial->dev; | 281 | wport->write_urb->dev = serial->dev; |
277 | result = usb_submit_urb(wport->write_urb, GFP_ATOMIC); | 282 | result = usb_submit_urb(wport->write_urb, GFP_ATOMIC); |
278 | if (result) | 283 | if (result) { |
284 | port->write_urb_busy = 0; | ||
279 | err("%s - failed submitting write urb, error %d", __FUNCTION__, result); | 285 | err("%s - failed submitting write urb, error %d", __FUNCTION__, result); |
280 | else | 286 | } else |
281 | result = count; | 287 | result = count; |
282 | 288 | ||
283 | return result; | 289 | return result; |
@@ -291,7 +297,7 @@ static int omninet_write_room (struct usb_serial_port *port) | |||
291 | 297 | ||
292 | int room = 0; // Default: no room | 298 | int room = 0; // Default: no room |
293 | 299 | ||
294 | if (wport->write_urb->status != -EINPROGRESS) | 300 | if (wport->write_urb_busy) |
295 | room = wport->bulk_out_size - OMNINET_HEADERLEN; | 301 | room = wport->bulk_out_size - OMNINET_HEADERLEN; |
296 | 302 | ||
297 | // dbg("omninet_write_room returns %d", room); | 303 | // dbg("omninet_write_room returns %d", room); |
@@ -306,6 +312,7 @@ static void omninet_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
306 | 312 | ||
307 | // dbg("omninet_write_bulk_callback, port %0x\n", port); | 313 | // dbg("omninet_write_bulk_callback, port %0x\n", port); |
308 | 314 | ||
315 | port->write_urb_busy = 0; | ||
309 | if (urb->status) { | 316 | if (urb->status) { |
310 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 317 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); |
311 | return; | 318 | return; |
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c index 0e85ed6c6c19..96a17568cbf1 100644 --- a/drivers/usb/serial/safe_serial.c +++ b/drivers/usb/serial/safe_serial.c | |||
@@ -299,10 +299,14 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i | |||
299 | dbg ("%s - write request of 0 bytes", __FUNCTION__); | 299 | dbg ("%s - write request of 0 bytes", __FUNCTION__); |
300 | return (0); | 300 | return (0); |
301 | } | 301 | } |
302 | if (port->write_urb->status == -EINPROGRESS) { | 302 | spin_lock(&port->lock); |
303 | dbg ("%s - already writing", __FUNCTION__); | 303 | if (port->write_urb_busy) { |
304 | return (0); | 304 | spin_unlock(&port->lock); |
305 | dbg("%s - already writing", __FUNCTION__); | ||
306 | return 0; | ||
305 | } | 307 | } |
308 | port->write_urb_busy = 1; | ||
309 | spin_unlock(&port->lock); | ||
306 | 310 | ||
307 | packet_length = port->bulk_out_size; // get max packetsize | 311 | packet_length = port->bulk_out_size; // get max packetsize |
308 | 312 | ||
@@ -354,6 +358,7 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i | |||
354 | #endif | 358 | #endif |
355 | port->write_urb->dev = port->serial->dev; | 359 | port->write_urb->dev = port->serial->dev; |
356 | if ((result = usb_submit_urb (port->write_urb, GFP_KERNEL))) { | 360 | if ((result = usb_submit_urb (port->write_urb, GFP_KERNEL))) { |
361 | port->write_urb_busy = 0; | ||
357 | err ("%s - failed submitting write urb, error %d", __FUNCTION__, result); | 362 | err ("%s - failed submitting write urb, error %d", __FUNCTION__, result); |
358 | return 0; | 363 | return 0; |
359 | } | 364 | } |
@@ -368,7 +373,7 @@ static int safe_write_room (struct usb_serial_port *port) | |||
368 | 373 | ||
369 | dbg ("%s", __FUNCTION__); | 374 | dbg ("%s", __FUNCTION__); |
370 | 375 | ||
371 | if (port->write_urb->status != -EINPROGRESS) | 376 | if (port->write_urb_busy) |
372 | room = port->bulk_out_size - (safe ? 2 : 0); | 377 | room = port->bulk_out_size - (safe ? 2 : 0); |
373 | 378 | ||
374 | if (room) { | 379 | if (room) { |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 5da76dd8fb28..0267b26dde18 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -1047,6 +1047,7 @@ int usb_serial_probe(struct usb_interface *interface, | |||
1047 | memset(port, 0x00, sizeof(struct usb_serial_port)); | 1047 | memset(port, 0x00, sizeof(struct usb_serial_port)); |
1048 | port->number = i + serial->minor; | 1048 | port->number = i + serial->minor; |
1049 | port->serial = serial; | 1049 | port->serial = serial; |
1050 | spin_lock_init(&port->lock); | ||
1050 | INIT_WORK(&port->work, usb_serial_port_softint, port); | 1051 | INIT_WORK(&port->work, usb_serial_port_softint, port); |
1051 | serial->port[i] = port; | 1052 | serial->port[i] = port; |
1052 | } | 1053 | } |
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h index d1f0c4057fa6..57f92f054c75 100644 --- a/drivers/usb/serial/usb-serial.h +++ b/drivers/usb/serial/usb-serial.h | |||
@@ -69,6 +69,7 @@ | |||
69 | * usb_serial_port: structure for the specific ports of a device. | 69 | * usb_serial_port: structure for the specific ports of a device. |
70 | * @serial: pointer back to the struct usb_serial owner of this port. | 70 | * @serial: pointer back to the struct usb_serial owner of this port. |
71 | * @tty: pointer to the corresponding tty for this port. | 71 | * @tty: pointer to the corresponding tty for this port. |
72 | * @lock: spinlock to grab when updating portions of this structure. | ||
72 | * @number: the number of the port (the minor number). | 73 | * @number: the number of the port (the minor number). |
73 | * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. | 74 | * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. |
74 | * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. | 75 | * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. |
@@ -98,6 +99,7 @@ | |||
98 | struct usb_serial_port { | 99 | struct usb_serial_port { |
99 | struct usb_serial * serial; | 100 | struct usb_serial * serial; |
100 | struct tty_struct * tty; | 101 | struct tty_struct * tty; |
102 | spinlock_t lock; | ||
101 | unsigned char number; | 103 | unsigned char number; |
102 | 104 | ||
103 | unsigned char * interrupt_in_buffer; | 105 | unsigned char * interrupt_in_buffer; |
@@ -117,6 +119,7 @@ struct usb_serial_port { | |||
117 | unsigned char * bulk_out_buffer; | 119 | unsigned char * bulk_out_buffer; |
118 | int bulk_out_size; | 120 | int bulk_out_size; |
119 | struct urb * write_urb; | 121 | struct urb * write_urb; |
122 | int write_urb_busy; | ||
120 | __u8 bulk_out_endpointAddress; | 123 | __u8 bulk_out_endpointAddress; |
121 | 124 | ||
122 | wait_queue_head_t write_wait; | 125 | wait_queue_head_t write_wait; |
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index e43eddc3d44b..af294bb68c35 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c | |||
@@ -155,6 +155,15 @@ static int slave_configure(struct scsi_device *sdev) | |||
155 | * If this device makes that mistake, tell the sd driver. */ | 155 | * If this device makes that mistake, tell the sd driver. */ |
156 | if (us->flags & US_FL_FIX_CAPACITY) | 156 | if (us->flags & US_FL_FIX_CAPACITY) |
157 | sdev->fix_capacity = 1; | 157 | sdev->fix_capacity = 1; |
158 | |||
159 | /* USB-IDE bridges tend to report SK = 0x04 (Non-recoverable | ||
160 | * Hardware Error) when any low-level error occurs, | ||
161 | * recoverable or not. Setting this flag tells the SCSI | ||
162 | * midlayer to retry such commands, which frequently will | ||
163 | * succeed and fix the error. The worst this can lead to | ||
164 | * is an occasional series of retries that will all fail. */ | ||
165 | sdev->retry_hwerror = 1; | ||
166 | |||
158 | } else { | 167 | } else { |
159 | 168 | ||
160 | /* Non-disk-type devices don't need to blacklist any pages | 169 | /* Non-disk-type devices don't need to blacklist any pages |
@@ -255,50 +264,23 @@ static int device_reset(struct scsi_cmnd *srb) | |||
255 | 264 | ||
256 | /* lock the device pointers and do the reset */ | 265 | /* lock the device pointers and do the reset */ |
257 | down(&(us->dev_semaphore)); | 266 | down(&(us->dev_semaphore)); |
258 | if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { | 267 | result = us->transport_reset(us); |
259 | result = FAILED; | ||
260 | US_DEBUGP("No reset during disconnect\n"); | ||
261 | } else | ||
262 | result = us->transport_reset(us); | ||
263 | up(&(us->dev_semaphore)); | 268 | up(&(us->dev_semaphore)); |
264 | 269 | ||
265 | return result; | 270 | return result < 0 ? FAILED : SUCCESS; |
266 | } | 271 | } |
267 | 272 | ||
268 | /* This resets the device's USB port. */ | 273 | /* Simulate a SCSI bus reset by resetting the device's USB port. */ |
269 | /* It refuses to work if there's more than one interface in | ||
270 | * the device, so that other users are not affected. */ | ||
271 | /* This is always called with scsi_lock(host) held */ | 274 | /* This is always called with scsi_lock(host) held */ |
272 | static int bus_reset(struct scsi_cmnd *srb) | 275 | static int bus_reset(struct scsi_cmnd *srb) |
273 | { | 276 | { |
274 | struct us_data *us = host_to_us(srb->device->host); | 277 | struct us_data *us = host_to_us(srb->device->host); |
275 | int result, rc; | 278 | int result; |
276 | 279 | ||
277 | US_DEBUGP("%s called\n", __FUNCTION__); | 280 | US_DEBUGP("%s called\n", __FUNCTION__); |
278 | 281 | ||
279 | /* The USB subsystem doesn't handle synchronisation between | ||
280 | * a device's several drivers. Therefore we reset only devices | ||
281 | * with just one interface, which we of course own. */ | ||
282 | |||
283 | down(&(us->dev_semaphore)); | 282 | down(&(us->dev_semaphore)); |
284 | if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { | 283 | result = usb_stor_port_reset(us); |
285 | result = -EIO; | ||
286 | US_DEBUGP("No reset during disconnect\n"); | ||
287 | } else if (us->pusb_dev->actconfig->desc.bNumInterfaces != 1) { | ||
288 | result = -EBUSY; | ||
289 | US_DEBUGP("Refusing to reset a multi-interface device\n"); | ||
290 | } else { | ||
291 | rc = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf); | ||
292 | if (rc < 0) { | ||
293 | US_DEBUGP("unable to lock device for reset: %d\n", rc); | ||
294 | result = rc; | ||
295 | } else { | ||
296 | result = usb_reset_device(us->pusb_dev); | ||
297 | if (rc) | ||
298 | usb_unlock_device(us->pusb_dev); | ||
299 | US_DEBUGP("usb_reset_device returns %d\n", result); | ||
300 | } | ||
301 | } | ||
302 | up(&(us->dev_semaphore)); | 284 | up(&(us->dev_semaphore)); |
303 | 285 | ||
304 | /* lock the host for the return */ | 286 | /* lock the host for the return */ |
@@ -320,6 +302,14 @@ void usb_stor_report_device_reset(struct us_data *us) | |||
320 | } | 302 | } |
321 | } | 303 | } |
322 | 304 | ||
305 | /* Report a driver-initiated bus reset to the SCSI layer. | ||
306 | * Calling this for a SCSI-initiated reset is unnecessary but harmless. | ||
307 | * The caller must own the SCSI host lock. */ | ||
308 | void usb_stor_report_bus_reset(struct us_data *us) | ||
309 | { | ||
310 | scsi_report_bus_reset(us_to_host(us), 0); | ||
311 | } | ||
312 | |||
323 | /*********************************************************************** | 313 | /*********************************************************************** |
324 | * /proc/scsi/ functions | 314 | * /proc/scsi/ functions |
325 | ***********************************************************************/ | 315 | ***********************************************************************/ |
diff --git a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h index d0a49af026c4..737e4fa6045f 100644 --- a/drivers/usb/storage/scsiglue.h +++ b/drivers/usb/storage/scsiglue.h | |||
@@ -42,6 +42,7 @@ | |||
42 | #define _SCSIGLUE_H_ | 42 | #define _SCSIGLUE_H_ |
43 | 43 | ||
44 | extern void usb_stor_report_device_reset(struct us_data *us); | 44 | extern void usb_stor_report_device_reset(struct us_data *us); |
45 | extern void usb_stor_report_bus_reset(struct us_data *us); | ||
45 | 46 | ||
46 | extern unsigned char usb_stor_sense_invalidCDB[18]; | 47 | extern unsigned char usb_stor_sense_invalidCDB[18]; |
47 | extern struct scsi_host_template usb_stor_host_template; | 48 | extern struct scsi_host_template usb_stor_host_template; |
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 9743e289cd3b..e6b1c6cf07f2 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c | |||
@@ -266,8 +266,9 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe) | |||
266 | NULL, 0, 3*HZ); | 266 | NULL, 0, 3*HZ); |
267 | 267 | ||
268 | /* reset the endpoint toggle */ | 268 | /* reset the endpoint toggle */ |
269 | usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe), | 269 | if (result >= 0) |
270 | usb_pipeout(pipe), 0); | 270 | usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe), |
271 | usb_pipeout(pipe), 0); | ||
271 | 272 | ||
272 | US_DEBUGP("%s: result = %d\n", __FUNCTION__, result); | 273 | US_DEBUGP("%s: result = %d\n", __FUNCTION__, result); |
273 | return result; | 274 | return result; |
@@ -540,15 +541,15 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
540 | */ | 541 | */ |
541 | if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { | 542 | if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { |
542 | US_DEBUGP("-- command was aborted\n"); | 543 | US_DEBUGP("-- command was aborted\n"); |
543 | goto Handle_Abort; | 544 | srb->result = DID_ABORT << 16; |
545 | goto Handle_Errors; | ||
544 | } | 546 | } |
545 | 547 | ||
546 | /* if there is a transport error, reset and don't auto-sense */ | 548 | /* if there is a transport error, reset and don't auto-sense */ |
547 | if (result == USB_STOR_TRANSPORT_ERROR) { | 549 | if (result == USB_STOR_TRANSPORT_ERROR) { |
548 | US_DEBUGP("-- transport indicates error, resetting\n"); | 550 | US_DEBUGP("-- transport indicates error, resetting\n"); |
549 | us->transport_reset(us); | ||
550 | srb->result = DID_ERROR << 16; | 551 | srb->result = DID_ERROR << 16; |
551 | return; | 552 | goto Handle_Errors; |
552 | } | 553 | } |
553 | 554 | ||
554 | /* if the transport provided its own sense data, don't auto-sense */ | 555 | /* if the transport provided its own sense data, don't auto-sense */ |
@@ -668,7 +669,8 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
668 | 669 | ||
669 | if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { | 670 | if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { |
670 | US_DEBUGP("-- auto-sense aborted\n"); | 671 | US_DEBUGP("-- auto-sense aborted\n"); |
671 | goto Handle_Abort; | 672 | srb->result = DID_ABORT << 16; |
673 | goto Handle_Errors; | ||
672 | } | 674 | } |
673 | if (temp_result != USB_STOR_TRANSPORT_GOOD) { | 675 | if (temp_result != USB_STOR_TRANSPORT_GOOD) { |
674 | US_DEBUGP("-- auto-sense failure\n"); | 676 | US_DEBUGP("-- auto-sense failure\n"); |
@@ -677,9 +679,9 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
677 | * multi-target device, since failure of an | 679 | * multi-target device, since failure of an |
678 | * auto-sense is perfectly valid | 680 | * auto-sense is perfectly valid |
679 | */ | 681 | */ |
680 | if (!(us->flags & US_FL_SCM_MULT_TARG)) | ||
681 | us->transport_reset(us); | ||
682 | srb->result = DID_ERROR << 16; | 682 | srb->result = DID_ERROR << 16; |
683 | if (!(us->flags & US_FL_SCM_MULT_TARG)) | ||
684 | goto Handle_Errors; | ||
683 | return; | 685 | return; |
684 | } | 686 | } |
685 | 687 | ||
@@ -720,12 +722,28 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
720 | 722 | ||
721 | return; | 723 | return; |
722 | 724 | ||
723 | /* abort processing: the bulk-only transport requires a reset | 725 | /* Error and abort processing: try to resynchronize with the device |
724 | * following an abort */ | 726 | * by issuing a port reset. If that fails, try a class-specific |
725 | Handle_Abort: | 727 | * device reset. */ |
726 | srb->result = DID_ABORT << 16; | 728 | Handle_Errors: |
727 | if (us->protocol == US_PR_BULK) | 729 | |
730 | /* Let the SCSI layer know we are doing a reset, set the | ||
731 | * RESETTING bit, and clear the ABORTING bit so that the reset | ||
732 | * may proceed. */ | ||
733 | scsi_lock(us_to_host(us)); | ||
734 | usb_stor_report_bus_reset(us); | ||
735 | set_bit(US_FLIDX_RESETTING, &us->flags); | ||
736 | clear_bit(US_FLIDX_ABORTING, &us->flags); | ||
737 | scsi_unlock(us_to_host(us)); | ||
738 | |||
739 | result = usb_stor_port_reset(us); | ||
740 | if (result < 0) { | ||
741 | scsi_lock(us_to_host(us)); | ||
742 | usb_stor_report_device_reset(us); | ||
743 | scsi_unlock(us_to_host(us)); | ||
728 | us->transport_reset(us); | 744 | us->transport_reset(us); |
745 | } | ||
746 | clear_bit(US_FLIDX_RESETTING, &us->flags); | ||
729 | } | 747 | } |
730 | 748 | ||
731 | /* Stop the current URB transfer */ | 749 | /* Stop the current URB transfer */ |
@@ -1124,7 +1142,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
1124 | * It's handy that every transport mechanism uses the control endpoint for | 1142 | * It's handy that every transport mechanism uses the control endpoint for |
1125 | * resets. | 1143 | * resets. |
1126 | * | 1144 | * |
1127 | * Basically, we send a reset with a 20-second timeout, so we don't get | 1145 | * Basically, we send a reset with a 5-second timeout, so we don't get |
1128 | * jammed attempting to do the reset. | 1146 | * jammed attempting to do the reset. |
1129 | */ | 1147 | */ |
1130 | static int usb_stor_reset_common(struct us_data *us, | 1148 | static int usb_stor_reset_common(struct us_data *us, |
@@ -1133,28 +1151,18 @@ static int usb_stor_reset_common(struct us_data *us, | |||
1133 | { | 1151 | { |
1134 | int result; | 1152 | int result; |
1135 | int result2; | 1153 | int result2; |
1136 | int rc = FAILED; | ||
1137 | 1154 | ||
1138 | /* Let the SCSI layer know we are doing a reset, set the | 1155 | if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { |
1139 | * RESETTING bit, and clear the ABORTING bit so that the reset | 1156 | US_DEBUGP("No reset during disconnect\n"); |
1140 | * may proceed. | 1157 | return -EIO; |
1141 | */ | 1158 | } |
1142 | scsi_lock(us_to_host(us)); | ||
1143 | usb_stor_report_device_reset(us); | ||
1144 | set_bit(US_FLIDX_RESETTING, &us->flags); | ||
1145 | clear_bit(US_FLIDX_ABORTING, &us->flags); | ||
1146 | scsi_unlock(us_to_host(us)); | ||
1147 | 1159 | ||
1148 | /* A 20-second timeout may seem rather long, but a LaCie | ||
1149 | * StudioDrive USB2 device takes 16+ seconds to get going | ||
1150 | * following a powerup or USB attach event. | ||
1151 | */ | ||
1152 | result = usb_stor_control_msg(us, us->send_ctrl_pipe, | 1160 | result = usb_stor_control_msg(us, us->send_ctrl_pipe, |
1153 | request, requesttype, value, index, data, size, | 1161 | request, requesttype, value, index, data, size, |
1154 | 20*HZ); | 1162 | 5*HZ); |
1155 | if (result < 0) { | 1163 | if (result < 0) { |
1156 | US_DEBUGP("Soft reset failed: %d\n", result); | 1164 | US_DEBUGP("Soft reset failed: %d\n", result); |
1157 | goto Done; | 1165 | return result; |
1158 | } | 1166 | } |
1159 | 1167 | ||
1160 | /* Give the device some time to recover from the reset, | 1168 | /* Give the device some time to recover from the reset, |
@@ -1164,7 +1172,7 @@ static int usb_stor_reset_common(struct us_data *us, | |||
1164 | HZ*6); | 1172 | HZ*6); |
1165 | if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { | 1173 | if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { |
1166 | US_DEBUGP("Reset interrupted by disconnect\n"); | 1174 | US_DEBUGP("Reset interrupted by disconnect\n"); |
1167 | goto Done; | 1175 | return -EIO; |
1168 | } | 1176 | } |
1169 | 1177 | ||
1170 | US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n"); | 1178 | US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n"); |
@@ -1173,17 +1181,14 @@ static int usb_stor_reset_common(struct us_data *us, | |||
1173 | US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n"); | 1181 | US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n"); |
1174 | result2 = usb_stor_clear_halt(us, us->send_bulk_pipe); | 1182 | result2 = usb_stor_clear_halt(us, us->send_bulk_pipe); |
1175 | 1183 | ||
1176 | /* return a result code based on the result of the control message */ | 1184 | /* return a result code based on the result of the clear-halts */ |
1177 | if (result < 0 || result2 < 0) { | 1185 | if (result >= 0) |
1186 | result = result2; | ||
1187 | if (result < 0) | ||
1178 | US_DEBUGP("Soft reset failed\n"); | 1188 | US_DEBUGP("Soft reset failed\n"); |
1179 | goto Done; | 1189 | else |
1180 | } | 1190 | US_DEBUGP("Soft reset done\n"); |
1181 | US_DEBUGP("Soft reset done\n"); | 1191 | return result; |
1182 | rc = SUCCESS; | ||
1183 | |||
1184 | Done: | ||
1185 | clear_bit(US_FLIDX_RESETTING, &us->flags); | ||
1186 | return rc; | ||
1187 | } | 1192 | } |
1188 | 1193 | ||
1189 | /* This issues a CB[I] Reset to the device in question | 1194 | /* This issues a CB[I] Reset to the device in question |
@@ -1213,3 +1218,32 @@ int usb_stor_Bulk_reset(struct us_data *us) | |||
1213 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | 1218 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, |
1214 | 0, us->ifnum, NULL, 0); | 1219 | 0, us->ifnum, NULL, 0); |
1215 | } | 1220 | } |
1221 | |||
1222 | /* Issue a USB port reset to the device. But don't do anything if | ||
1223 | * there's more than one interface in the device, so that other users | ||
1224 | * are not affected. */ | ||
1225 | int usb_stor_port_reset(struct us_data *us) | ||
1226 | { | ||
1227 | int result, rc; | ||
1228 | |||
1229 | if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { | ||
1230 | result = -EIO; | ||
1231 | US_DEBUGP("No reset during disconnect\n"); | ||
1232 | } else if (us->pusb_dev->actconfig->desc.bNumInterfaces != 1) { | ||
1233 | result = -EBUSY; | ||
1234 | US_DEBUGP("Refusing to reset a multi-interface device\n"); | ||
1235 | } else { | ||
1236 | result = rc = | ||
1237 | usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf); | ||
1238 | if (result < 0) { | ||
1239 | US_DEBUGP("unable to lock device for reset: %d\n", | ||
1240 | result); | ||
1241 | } else { | ||
1242 | result = usb_reset_device(us->pusb_dev); | ||
1243 | if (rc) | ||
1244 | usb_unlock_device(us->pusb_dev); | ||
1245 | US_DEBUGP("usb_reset_device returns %d\n", result); | ||
1246 | } | ||
1247 | } | ||
1248 | return result; | ||
1249 | } | ||
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h index e25f8d8fc741..8d9e0663f8fe 100644 --- a/drivers/usb/storage/transport.h +++ b/drivers/usb/storage/transport.h | |||
@@ -171,4 +171,5 @@ extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe, | |||
171 | extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe, | 171 | extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe, |
172 | void *buf, unsigned int length, int use_sg, int *residual); | 172 | void *buf, unsigned int length, int use_sg, int *residual); |
173 | 173 | ||
174 | extern int usb_stor_port_reset(struct us_data *us); | ||
174 | #endif | 175 | #endif |