diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2008-06-24 10:19:47 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-01-06 16:52:34 -0500 |
commit | 6e16aee60c815dac2d6c3b875769a79d09df6f91 (patch) | |
tree | e370996d9dc5f57462d7bbedb1811b0e651b718f | |
parent | 28397ffef14255ba45b99570d366fcd2b454c8f3 (diff) |
Staging: add mimio xi driver
This patch adds the Mimio Xi interactive whiteboard driver to the tree.
It was originally written by mwilder@cs.nmsu.edu, but cleaned up and
forward ported by me to the latest kernel version.
Cc: Phil Hannent <phil@hannent.co.uk>
Cc: <mwilder@cs.nmsu.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/staging/Kconfig | 2 | ||||
-rw-r--r-- | drivers/staging/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/mimio/Kconfig | 10 | ||||
-rw-r--r-- | drivers/staging/mimio/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/mimio/mimio.c | 914 |
5 files changed, 928 insertions, 0 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index fe3b23e43567..9845eab9ebfe 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig | |||
@@ -85,5 +85,7 @@ source "drivers/staging/rtl8187se/Kconfig" | |||
85 | 85 | ||
86 | source "drivers/staging/rspiusb/Kconfig" | 86 | source "drivers/staging/rspiusb/Kconfig" |
87 | 87 | ||
88 | source "drivers/staging/mimio/Kconfig" | ||
89 | |||
88 | endif # !STAGING_EXCLUDE_BUILD | 90 | endif # !STAGING_EXCLUDE_BUILD |
89 | endif # STAGING | 91 | endif # STAGING |
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index bd4cb9285a2f..968f333a659b 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile | |||
@@ -25,3 +25,4 @@ obj-$(CONFIG_PANEL) += panel/ | |||
25 | obj-$(CONFIG_ALTERA_PCIE_CHDMA) += altpciechdma/ | 25 | obj-$(CONFIG_ALTERA_PCIE_CHDMA) += altpciechdma/ |
26 | obj-$(CONFIG_RTL8187SE) += rtl8187se/ | 26 | obj-$(CONFIG_RTL8187SE) += rtl8187se/ |
27 | obj-$(CONFIG_USB_RSPI) += rspiusb/ | 27 | obj-$(CONFIG_USB_RSPI) += rspiusb/ |
28 | obj-$(CONFIG_INPUT_MIMIO) += mimio/ | ||
diff --git a/drivers/staging/mimio/Kconfig b/drivers/staging/mimio/Kconfig new file mode 100644 index 000000000000..c0ba4c800dff --- /dev/null +++ b/drivers/staging/mimio/Kconfig | |||
@@ -0,0 +1,10 @@ | |||
1 | config INPUT_MIMIO | ||
2 | tristate "Mimio Xi interactive whiteboard support" | ||
3 | depends on USB | ||
4 | default N | ||
5 | help | ||
6 | Say Y here if you want to use a Mimio Xi interactive | ||
7 | whiteboard device. | ||
8 | |||
9 | To compile this driver as a module, choose M here: the | ||
10 | module will be called mimio. | ||
diff --git a/drivers/staging/mimio/Makefile b/drivers/staging/mimio/Makefile new file mode 100644 index 000000000000..77807ee0450e --- /dev/null +++ b/drivers/staging/mimio/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_INPUT_MIMIO) += mimio.o | |||
diff --git a/drivers/staging/mimio/mimio.c b/drivers/staging/mimio/mimio.c new file mode 100644 index 000000000000..1ba8103f5003 --- /dev/null +++ b/drivers/staging/mimio/mimio.c | |||
@@ -0,0 +1,914 @@ | |||
1 | /* | ||
2 | * Hardware event => input event mapping: | ||
3 | * | ||
4 | * | ||
5 | * | ||
6 | input.h:#define BTN_TOOL_PEN 0x140 black | ||
7 | input.h:#define BTN_TOOL_RUBBER 0x141 blue | ||
8 | input.h:#define BTN_TOOL_BRUSH 0x142 green | ||
9 | input.h:#define BTN_TOOL_PENCIL 0x143 red | ||
10 | input.h:#define BTN_TOOL_AIRBRUSH 0x144 eraser | ||
11 | input.h:#define BTN_TOOL_FINGER 0x145 small eraser | ||
12 | input.h:#define BTN_TOOL_MOUSE 0x146 mimio interactive | ||
13 | input.h:#define BTN_TOOL_LENS 0x147 mimio interactive but1 | ||
14 | input.h:#define LOCALBTN_TOOL_EXTRA1 0x14a mimio interactive but2 == BTN_TOUCH | ||
15 | input.h:#define LOCALBTN_TOOL_EXTRA2 0x14b mimio extra pens (orange, brown, yellow, purple) == BTN_STYLUS | ||
16 | input.h:#define LOCALBTN_TOOL_EXTRA3 0x14c unused == BTN_STYLUS2 | ||
17 | input.h:#define BTN_TOOL_DOUBLETAP 0x14d unused | ||
18 | input.h:#define BTN_TOOL_TRIPLETAP 0x14e unused | ||
19 | * | ||
20 | * MIMIO_EV_PENDOWN(MIMIO_PEN_K) => EV_KEY BIT(BTN_TOOL_PEN) | ||
21 | * MIMIO_EV_PENDOWN(MIMIO_PEN_B) => EV_KEY BIT(BTN_TOOL_RUBBER) | ||
22 | * MIMIO_EV_PENDOWN(MIMIO_PEN_G) => EV_KEY BIT(BTN_TOOL_BRUSH) | ||
23 | * MIMIO_EV_PENDOWN(MIMIO_PEN_R) => EV_KEY BIT(BTN_TOOL_PENCIL) | ||
24 | * MIMIO_EV_PENDOWN(MIMIO_PEN_E) => EV_KEY BIT(BTN_TOOL_AIRBRUSH) | ||
25 | * MIMIO_EV_PENDOWN(MIMIO_PEN_ES) => EV_KEY BIT(BTN_TOOL_FINGER) | ||
26 | * MIMIO_EV_PENDOWN(MIMIO_PEN_I) => EV_KEY BIT(BTN_TOOL_MOUSE) | ||
27 | * MIMIO_EV_PENDOWN(MIMIO_PEN_IL) => EV_KEY BIT(BTN_TOOL_LENS) | ||
28 | * MIMIO_EV_PENDOWN(MIMIO_PEN_IR) => EV_KEY BIT(BTN_TOOL_DOUBLETAP) | ||
29 | * MIMIO_EV_PENDOWN(MIMIO_PEN_EX) => EV_KEY BIT(BTN_TOOL_TRIPLETAP) | ||
30 | * MIMIO_EV_PENDATA => EV_ABS BIT(ABS_X), BIT(ABS_Y) | ||
31 | * MIMIO_EV_MEMRESET => EV_KEY BIT(BTN_0) | ||
32 | * MIMIO_EV_ACC(ACC_NEWPAGE) => EV_KEY BIT(BTN_1) | ||
33 | * MIMIO_EV_ACC(ACC_TAGPAGE) => EV_KEY BIT(BTN_2) | ||
34 | * MIMIO_EV_ACC(ACC_PRINTPAGE) => EV_KEY BIT(BTN_3) | ||
35 | * MIMIO_EV_ACC(ACC_MAXIMIZE) => EV_KEY BIT(BTN_4) | ||
36 | * MIMIO_EV_ACC(ACC_FINDCTLPNL) => EV_KEY BIT(BTN_5) | ||
37 | * | ||
38 | * | ||
39 | * open issues: | ||
40 | * - cold-load of data captured when mimio in standalone mode not yet | ||
41 | * supported; need to snoop Win32 box to see datastream for this. | ||
42 | * - mimio mouse not yet supported; need to snoop Win32 box to see the | ||
43 | * datastream for this. | ||
44 | */ | ||
45 | #include <linux/kernel.h> | ||
46 | #include <linux/init.h> | ||
47 | #include <linux/slab.h> | ||
48 | #include <linux/spinlock.h> | ||
49 | #include <linux/input.h> | ||
50 | #include <linux/usb.h> | ||
51 | |||
52 | #define DRIVER_VERSION "v0.031" | ||
53 | #define DRIVER_AUTHOR "mwilder@cs.nmsu.edu" | ||
54 | #define DRIVER_DESC "USB mimio-xi driver" | ||
55 | |||
56 | enum {UPVALUE, DOWNVALUE, MOVEVALUE}; | ||
57 | |||
58 | #define MIMIO_XRANGE_MAX 9600 | ||
59 | #define MIMIO_YRANGE_MAX 4800 | ||
60 | |||
61 | #define LOCALBTN_TOOL_EXTRA1 BTN_TOUCH | ||
62 | #define LOCALBTN_TOOL_EXTRA2 BTN_STYLUS | ||
63 | #define LOCALBTN_TOOL_EXTRA3 BTN_STYLUS2 | ||
64 | |||
65 | #define MIMIO_VENDOR_ID 0x08d3 | ||
66 | #define MIMIO_PRODUCT_ID 0x0001 | ||
67 | #define MIMIO_MAXPAYLOAD (8) | ||
68 | #define MIMIO_MAXNAMELEN (64) | ||
69 | #define MIMIO_TXWAIT (1) | ||
70 | #define MIMIO_TXDONE (2) | ||
71 | |||
72 | #define MIMIO_EV_PENDOWN (0x22) | ||
73 | #define MIMIO_EV_PENDATA (0x24) | ||
74 | #define MIMIO_EV_PENUP (0x51) | ||
75 | #define MIMIO_EV_MEMRESET (0x45) | ||
76 | #define MIMIO_EV_ACC (0xb2) | ||
77 | |||
78 | #define MIMIO_PEN_K (1) /* black pen */ | ||
79 | #define MIMIO_PEN_B (2) /* blue pen */ | ||
80 | #define MIMIO_PEN_G (3) /* green pen */ | ||
81 | #define MIMIO_PEN_R (4) /* red pen */ | ||
82 | /* 5, 6, 7, 8 are extra pens */ | ||
83 | #define MIMIO_PEN_E (9) /* big eraser */ | ||
84 | #define MIMIO_PEN_ES (10) /* lil eraser */ | ||
85 | #define MIMIO_PENJUMP_START (10) | ||
86 | #define MIMIO_PENJUMP (6) | ||
87 | #define MIMIO_PEN_I (17) /* mimio interactive */ | ||
88 | #define MIMIO_PEN_IL (18) /* mimio interactive button 1 */ | ||
89 | #define MIMIO_PEN_IR (19) /* mimio interactive button 2 */ | ||
90 | |||
91 | #define MIMIO_PEN_MAX (MIMIO_PEN_IR) | ||
92 | |||
93 | #define ACC_DONE (0) | ||
94 | #define ACC_NEWPAGE (1) | ||
95 | #define ACC_TAGPAGE (2) | ||
96 | #define ACC_PRINTPAGE (4) | ||
97 | #define ACC_MAXIMIZE (8) | ||
98 | #define ACC_FINDCTLPNL (16) | ||
99 | |||
100 | #define isvalidtxsize(n) ((n) > 0 && (n) <= MIMIO_MAXPAYLOAD) | ||
101 | |||
102 | |||
103 | struct pktbuf { | ||
104 | unsigned char instr; | ||
105 | unsigned char buf[16]; | ||
106 | unsigned char *p; | ||
107 | unsigned char *q; | ||
108 | }; | ||
109 | |||
110 | struct usbintendpt { | ||
111 | dma_addr_t dma; | ||
112 | struct urb *urb; | ||
113 | unsigned char *buf; | ||
114 | struct usb_endpoint_descriptor *desc; | ||
115 | }; | ||
116 | |||
117 | struct mimio { | ||
118 | struct input_dev *idev; | ||
119 | struct usb_device *udev; | ||
120 | struct usb_interface *uifc; | ||
121 | int open; | ||
122 | int present; | ||
123 | int greeted; | ||
124 | int txflags; | ||
125 | char phys[MIMIO_MAXNAMELEN]; | ||
126 | struct usbintendpt in; | ||
127 | struct usbintendpt out; | ||
128 | struct pktbuf pktbuf; | ||
129 | unsigned char minor; | ||
130 | wait_queue_head_t waitq; | ||
131 | spinlock_t txlock; | ||
132 | void (*rxhandler)(struct mimio *, unsigned char *, unsigned int); | ||
133 | int last_pen_down; | ||
134 | }; | ||
135 | |||
136 | static void mimio_close(struct input_dev *); | ||
137 | static void mimio_dealloc(struct mimio *); | ||
138 | static void mimio_disconnect(struct usb_interface *); | ||
139 | static int mimio_greet(struct mimio *); | ||
140 | static void mimio_irq_in(struct urb *); | ||
141 | static void mimio_irq_out(struct urb *); | ||
142 | static int mimio_open(struct input_dev *); | ||
143 | static int mimio_probe(struct usb_interface *, const struct usb_device_id *); | ||
144 | static void mimio_rx_handler(struct mimio *, unsigned char *, unsigned int); | ||
145 | static int mimio_tx(struct mimio *, const char *, int); | ||
146 | |||
147 | static char mimio_name[] = "VirtualInk mimio-Xi"; | ||
148 | static struct usb_device_id mimio_table [] = { | ||
149 | { USB_DEVICE(MIMIO_VENDOR_ID, MIMIO_PRODUCT_ID) }, | ||
150 | { USB_DEVICE(0x0525, 0xa4a0) }, /* gadget zero firmware */ | ||
151 | { } | ||
152 | }; | ||
153 | |||
154 | MODULE_DEVICE_TABLE(usb, mimio_table); | ||
155 | |||
156 | static struct usb_driver mimio_driver = { | ||
157 | .name = "mimio", | ||
158 | .probe = mimio_probe, | ||
159 | .disconnect = mimio_disconnect, | ||
160 | .id_table = mimio_table, | ||
161 | }; | ||
162 | |||
163 | static DECLARE_MUTEX(disconnect_sem); | ||
164 | |||
165 | static void mimio_close(struct input_dev *idev) | ||
166 | { | ||
167 | struct mimio *mimio; | ||
168 | |||
169 | mimio = input_get_drvdata(idev); | ||
170 | if (!mimio) { | ||
171 | dev_err(&idev->dev, "null mimio attached to input device\n"); | ||
172 | return; | ||
173 | } | ||
174 | |||
175 | if (mimio->open <= 0) | ||
176 | dev_err(&idev->dev, "mimio not open.\n"); | ||
177 | else | ||
178 | mimio->open--; | ||
179 | |||
180 | if (mimio->present == 0 && mimio->open == 0) | ||
181 | mimio_dealloc(mimio); | ||
182 | } | ||
183 | |||
184 | static void mimio_dealloc(struct mimio *mimio) | ||
185 | { | ||
186 | if (mimio == NULL) | ||
187 | return; | ||
188 | |||
189 | usb_kill_urb(mimio->in.urb); | ||
190 | |||
191 | usb_kill_urb(mimio->out.urb); | ||
192 | |||
193 | if (mimio->idev) { | ||
194 | input_unregister_device(mimio->idev); | ||
195 | if (mimio->idev->grab) | ||
196 | input_close_device(mimio->idev->grab); | ||
197 | else | ||
198 | dev_dbg(&mimio->idev->dev, "mimio->idev->grab == NULL" | ||
199 | " -- didn't call input_close_device\n"); | ||
200 | } | ||
201 | |||
202 | usb_free_urb(mimio->in.urb); | ||
203 | |||
204 | usb_free_urb(mimio->out.urb); | ||
205 | |||
206 | if (mimio->in.buf) { | ||
207 | usb_buffer_free(mimio->udev, MIMIO_MAXPAYLOAD, mimio->in.buf, | ||
208 | mimio->in.dma); | ||
209 | } | ||
210 | |||
211 | if (mimio->out.buf) | ||
212 | usb_buffer_free(mimio->udev, MIMIO_MAXPAYLOAD, mimio->out.buf, | ||
213 | mimio->out.dma); | ||
214 | |||
215 | if (mimio->idev) | ||
216 | input_free_device(mimio->idev); | ||
217 | |||
218 | kfree(mimio); | ||
219 | } | ||
220 | |||
221 | static void mimio_disconnect(struct usb_interface *ifc) | ||
222 | { | ||
223 | struct mimio *mimio; | ||
224 | |||
225 | down(&disconnect_sem); | ||
226 | |||
227 | mimio = usb_get_intfdata(ifc); | ||
228 | usb_set_intfdata(ifc, NULL); | ||
229 | dev_dbg(&mimio->idev->dev, "disconnect\n"); | ||
230 | |||
231 | if (mimio) { | ||
232 | mimio->present = 0; | ||
233 | |||
234 | if (mimio->open <= 0) | ||
235 | mimio_dealloc(mimio); | ||
236 | } | ||
237 | |||
238 | up(&disconnect_sem); | ||
239 | } | ||
240 | |||
241 | static int mimio_greet(struct mimio *mimio) | ||
242 | { | ||
243 | const struct grtpkt { | ||
244 | int nbytes; | ||
245 | unsigned delay; | ||
246 | char data[8]; | ||
247 | } grtpkts[] = { | ||
248 | { 3, 0, { 0x11, 0x55, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00 } }, | ||
249 | { 5, 0, { 0x53, 0x55, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00 } }, | ||
250 | { 5, 0, { 0x43, 0x55, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00 } }, | ||
251 | { 5, 0, { 0x33, 0x55, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00 } }, | ||
252 | { 5, 0, { 0x13, 0x00, 0x5e, 0x02, 0x4f, 0x00, 0x00, 0x00 } }, | ||
253 | { 5, 0, { 0x13, 0x00, 0x04, 0x03, 0x14, 0x00, 0x00, 0x00 } }, | ||
254 | { 5, 2, { 0x13, 0x00, 0x00, 0x04, 0x17, 0x00, 0x00, 0x00 } }, | ||
255 | { 5, 0, { 0x13, 0x00, 0x0d, 0x08, 0x16, 0x00, 0x00, 0x00 } }, | ||
256 | { 5, 0, { 0x13, 0x00, 0x4d, 0x01, 0x5f, 0x00, 0x00, 0x00 } }, | ||
257 | { 3, 0, { 0xf1, 0x55, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00 } }, | ||
258 | { 7, 2, { 0x52, 0x55, 0x00, 0x07, 0x31, 0x55, 0x64, 0x00 } }, | ||
259 | { 0, 0, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, | ||
260 | }; | ||
261 | int rslt; | ||
262 | const struct grtpkt *pkt; | ||
263 | |||
264 | for (pkt = grtpkts; pkt->nbytes; pkt++) { | ||
265 | rslt = mimio_tx(mimio, pkt->data, pkt->nbytes); | ||
266 | if (rslt) | ||
267 | return rslt; | ||
268 | if (pkt->delay) | ||
269 | msleep(pkt->delay); | ||
270 | } | ||
271 | |||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | static void mimio_irq_in(struct urb *urb) | ||
276 | { | ||
277 | int rslt; | ||
278 | char *data; | ||
279 | const char *reason = "going down"; | ||
280 | struct mimio *mimio; | ||
281 | |||
282 | mimio = urb->context; | ||
283 | |||
284 | if (mimio == NULL) | ||
285 | /* paranoia */ | ||
286 | return; | ||
287 | |||
288 | switch (urb->status) { | ||
289 | case 0: | ||
290 | /* success */ | ||
291 | break; | ||
292 | case -ETIMEDOUT: | ||
293 | reason = "timeout -- unplugged?"; | ||
294 | case -ECONNRESET: | ||
295 | case -ENOENT: | ||
296 | case -ESHUTDOWN: | ||
297 | dev_dbg(&mimio->idev->dev, "%s.\n", reason); | ||
298 | return; | ||
299 | default: | ||
300 | dev_dbg(&mimio->idev->dev, "unknown urb-status: %d.\n", | ||
301 | urb->status); | ||
302 | goto exit; | ||
303 | } | ||
304 | data = mimio->in.buf; | ||
305 | |||
306 | if (mimio->rxhandler) | ||
307 | mimio->rxhandler(mimio, data, urb->actual_length); | ||
308 | exit: | ||
309 | /* | ||
310 | * Keep listening to device on same urb. | ||
311 | */ | ||
312 | rslt = usb_submit_urb(urb, GFP_ATOMIC); | ||
313 | if (rslt) | ||
314 | dev_err(&mimio->idev->dev, "usb_submit_urb failure: %d.\n", | ||
315 | rslt); | ||
316 | } | ||
317 | |||
318 | static void mimio_irq_out(struct urb *urb) | ||
319 | { | ||
320 | unsigned long flags; | ||
321 | struct mimio *mimio; | ||
322 | |||
323 | mimio = urb->context; | ||
324 | |||
325 | if (urb->status) | ||
326 | dev_dbg(&mimio->idev->dev, "urb-status: %d.\n", urb->status); | ||
327 | |||
328 | spin_lock_irqsave(&mimio->txlock, flags); | ||
329 | mimio->txflags |= MIMIO_TXDONE; | ||
330 | spin_unlock_irqrestore(&mimio->txlock, flags); | ||
331 | wmb(); | ||
332 | wake_up(&mimio->waitq); | ||
333 | } | ||
334 | |||
335 | static int mimio_open(struct input_dev *idev) | ||
336 | { | ||
337 | int rslt; | ||
338 | struct mimio *mimio; | ||
339 | |||
340 | rslt = 0; | ||
341 | down(&disconnect_sem); | ||
342 | mimio = input_get_drvdata(idev); | ||
343 | dev_dbg(&idev->dev, "mimio_open\n"); | ||
344 | |||
345 | if (mimio == NULL) { | ||
346 | dev_err(&idev->dev, "null mimio.\n"); | ||
347 | rslt = -ENODEV; | ||
348 | goto exit; | ||
349 | } | ||
350 | |||
351 | if (mimio->open++) | ||
352 | goto exit; | ||
353 | |||
354 | if (mimio->present && !mimio->greeted) { | ||
355 | struct urb *urb = mimio->in.urb; | ||
356 | mimio->in.urb->dev = mimio->udev; | ||
357 | rslt = usb_submit_urb(mimio->in.urb, GFP_KERNEL); | ||
358 | if (rslt) { | ||
359 | dev_err(&idev->dev, "usb_submit_urb failure " | ||
360 | "(res = %d: %s). Not greeting.\n", | ||
361 | rslt, | ||
362 | (!urb ? "urb is NULL" : | ||
363 | (urb->hcpriv ? "urb->hcpriv is non-NULL" : | ||
364 | (!urb->complete ? "urb is not complete" : | ||
365 | (urb->number_of_packets <= 0 ? "urb has no packets" : | ||
366 | (urb->interval <= 0 ? "urb interval too small" : | ||
367 | "urb interval too large or some other error")))))); | ||
368 | rslt = -EIO; | ||
369 | goto exit; | ||
370 | } | ||
371 | rslt = mimio_greet(mimio); | ||
372 | if (rslt == 0) { | ||
373 | dev_dbg(&idev->dev, "Mimio greeted OK.\n"); | ||
374 | mimio->greeted = 1; | ||
375 | } else { | ||
376 | dev_dbg(&idev->dev, "Mimio greet Failure (%d)\n", | ||
377 | rslt); | ||
378 | } | ||
379 | } | ||
380 | |||
381 | exit: | ||
382 | up(&disconnect_sem); | ||
383 | return rslt; | ||
384 | } | ||
385 | |||
386 | static int mimio_probe(struct usb_interface *ifc, | ||
387 | const struct usb_device_id *id) | ||
388 | { | ||
389 | char path[64]; | ||
390 | int pipe, maxp; | ||
391 | struct mimio *mimio; | ||
392 | struct usb_device *udev; | ||
393 | struct usb_host_interface *hostifc; | ||
394 | struct input_dev *input_dev; | ||
395 | int res = 0; | ||
396 | int i; | ||
397 | |||
398 | udev = interface_to_usbdev(ifc); | ||
399 | |||
400 | mimio = kzalloc(sizeof(struct mimio), GFP_KERNEL); | ||
401 | if (!mimio) | ||
402 | return -ENOMEM; | ||
403 | |||
404 | input_dev = input_allocate_device(); | ||
405 | if (!input_dev) { | ||
406 | mimio_dealloc(mimio); | ||
407 | return -ENOMEM; | ||
408 | } | ||
409 | |||
410 | mimio->uifc = ifc; | ||
411 | mimio->udev = udev; | ||
412 | mimio->pktbuf.p = mimio->pktbuf.buf; | ||
413 | mimio->pktbuf.q = mimio->pktbuf.buf; | ||
414 | /* init_input_dev(mimio->idev); */ | ||
415 | mimio->idev = input_dev; | ||
416 | init_waitqueue_head(&mimio->waitq); | ||
417 | spin_lock_init(&mimio->txlock); | ||
418 | hostifc = ifc->cur_altsetting; | ||
419 | |||
420 | if (hostifc->desc.bNumEndpoints != 2) { | ||
421 | dev_err(&udev->dev, "Unexpected endpoint count: %d.\n", | ||
422 | hostifc->desc.bNumEndpoints); | ||
423 | mimio_dealloc(mimio); | ||
424 | return -ENODEV; | ||
425 | } | ||
426 | |||
427 | mimio->in.desc = &(hostifc->endpoint[0].desc); | ||
428 | mimio->out.desc = &(hostifc->endpoint[1].desc); | ||
429 | |||
430 | mimio->in.buf = usb_buffer_alloc(udev, MIMIO_MAXPAYLOAD, GFP_KERNEL, | ||
431 | &mimio->in.dma); | ||
432 | mimio->out.buf = usb_buffer_alloc(udev, MIMIO_MAXPAYLOAD, GFP_KERNEL, | ||
433 | &mimio->out.dma); | ||
434 | |||
435 | if (mimio->in.buf == NULL || mimio->out.buf == NULL) { | ||
436 | dev_err(&udev->dev, "usb_buffer_alloc failure.\n"); | ||
437 | mimio_dealloc(mimio); | ||
438 | return -ENOMEM; | ||
439 | } | ||
440 | |||
441 | mimio->in.urb = usb_alloc_urb(0, GFP_KERNEL); | ||
442 | mimio->out.urb = usb_alloc_urb(0, GFP_KERNEL); | ||
443 | |||
444 | if (mimio->in.urb == NULL || mimio->out.urb == NULL) { | ||
445 | dev_err(&udev->dev, "usb_alloc_urb failure.\n"); | ||
446 | mimio_dealloc(mimio); | ||
447 | return -ENOMEM; | ||
448 | } | ||
449 | |||
450 | /* | ||
451 | * Build the input urb. | ||
452 | */ | ||
453 | pipe = usb_rcvintpipe(udev, mimio->in.desc->bEndpointAddress); | ||
454 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | ||
455 | if (maxp > MIMIO_MAXPAYLOAD) | ||
456 | maxp = MIMIO_MAXPAYLOAD; | ||
457 | usb_fill_int_urb(mimio->in.urb, udev, pipe, mimio->in.buf, maxp, | ||
458 | mimio_irq_in, mimio, mimio->in.desc->bInterval); | ||
459 | mimio->in.urb->transfer_dma = mimio->in.dma; | ||
460 | mimio->in.urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
461 | |||
462 | /* | ||
463 | * Build the output urb. | ||
464 | */ | ||
465 | pipe = usb_sndintpipe(udev, mimio->out.desc->bEndpointAddress); | ||
466 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | ||
467 | if (maxp > MIMIO_MAXPAYLOAD) | ||
468 | maxp = MIMIO_MAXPAYLOAD; | ||
469 | usb_fill_int_urb(mimio->out.urb, udev, pipe, mimio->out.buf, maxp, | ||
470 | mimio_irq_out, mimio, mimio->out.desc->bInterval); | ||
471 | mimio->out.urb->transfer_dma = mimio->out.dma; | ||
472 | mimio->out.urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
473 | |||
474 | /* | ||
475 | * Build input device info | ||
476 | */ | ||
477 | usb_make_path(udev, path, 64); | ||
478 | snprintf(mimio->phys, MIMIO_MAXNAMELEN, "%s/input0", path); | ||
479 | input_set_drvdata(input_dev, mimio); | ||
480 | /* input_dev->dev = &ifc->dev; */ | ||
481 | input_dev->open = mimio_open; | ||
482 | input_dev->close = mimio_close; | ||
483 | input_dev->name = mimio_name; | ||
484 | input_dev->phys = mimio->phys; | ||
485 | input_dev->dev.parent = &ifc->dev; | ||
486 | |||
487 | input_dev->id.bustype = BUS_USB; | ||
488 | input_dev->id.vendor = le16_to_cpu(udev->descriptor.idVendor); | ||
489 | input_dev->id.product = le16_to_cpu(udev->descriptor.idProduct); | ||
490 | input_dev->id.version = le16_to_cpu(udev->descriptor.bcdDevice); | ||
491 | |||
492 | input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS); | ||
493 | for (i = BTN_TOOL_PEN; i <= LOCALBTN_TOOL_EXTRA2; ++i) | ||
494 | set_bit(i, input_dev->keybit); | ||
495 | |||
496 | input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) | | ||
497 | BIT_MASK(BTN_1) | | ||
498 | BIT_MASK(BTN_2) | | ||
499 | BIT_MASK(BTN_3) | | ||
500 | BIT_MASK(BTN_4) | | ||
501 | BIT_MASK(BTN_5); | ||
502 | /* input_dev->keybit[BTN_MOUSE] |= BIT(BTN_LEFT); */ | ||
503 | input_dev->absbit[0] |= BIT_MASK(ABS_X) | BIT_MASK(ABS_Y); | ||
504 | input_set_abs_params(input_dev, ABS_X, 0, MIMIO_XRANGE_MAX, 0, 0); | ||
505 | input_set_abs_params(input_dev, ABS_Y, 0, MIMIO_YRANGE_MAX, 0, 0); | ||
506 | input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC); | ||
507 | |||
508 | #if 0 | ||
509 | input_dev->absmin[ABS_X] = 0; | ||
510 | input_dev->absmin[ABS_Y] = 0; | ||
511 | input_dev->absmax[ABS_X] = 9600; | ||
512 | input_dev->absmax[ABS_Y] = 4800; | ||
513 | input_dev->absfuzz[ABS_X] = 0; | ||
514 | input_dev->absfuzz[ABS_Y] = 0; | ||
515 | input_dev->absflat[ABS_X] = 0; | ||
516 | input_dev->absflat[ABS_Y] = 0; | ||
517 | #endif | ||
518 | |||
519 | #if 0 | ||
520 | /* this will just reduce the precision */ | ||
521 | input_dev->absfuzz[ABS_X] = 8; /* experimental; may need to change */ | ||
522 | input_dev->absfuzz[ABS_Y] = 8; /* experimental; may need to change */ | ||
523 | #endif | ||
524 | |||
525 | /* | ||
526 | * Register the input device. | ||
527 | */ | ||
528 | res = input_register_device(mimio->idev); | ||
529 | if (res) { | ||
530 | dev_err(&udev->dev, "input_register_device failure (%d)\n", | ||
531 | res); | ||
532 | mimio_dealloc(mimio); | ||
533 | return -EIO; | ||
534 | } | ||
535 | dev_dbg(&mimio->idev->dev, "input: %s on %s (res = %d).\n", | ||
536 | input_dev->name, input_dev->phys, res); | ||
537 | |||
538 | usb_set_intfdata(ifc, mimio); | ||
539 | mimio->present = 1; | ||
540 | |||
541 | /* | ||
542 | * Submit the input urb to the usb subsystem. | ||
543 | */ | ||
544 | mimio->in.urb->dev = mimio->udev; | ||
545 | res = usb_submit_urb(mimio->in.urb, GFP_KERNEL); | ||
546 | if (res) { | ||
547 | dev_err(&mimio->idev->dev, "usb_submit_urb failure (%d)\n", | ||
548 | res); | ||
549 | mimio_dealloc(mimio); | ||
550 | return -EIO; | ||
551 | } | ||
552 | |||
553 | /* | ||
554 | * Attempt to greet the mimio after giving | ||
555 | * it some post-init settling time. | ||
556 | * | ||
557 | * note: sometimes this sleep interval isn't | ||
558 | * long enough to permit the device to re-init | ||
559 | * after a hot-swap; maybe need to bump it up. | ||
560 | * | ||
561 | * As it is, this probably breaks module unloading support! | ||
562 | */ | ||
563 | msleep(1024); | ||
564 | |||
565 | res = mimio_greet(mimio); | ||
566 | if (res == 0) { | ||
567 | dev_dbg(&mimio->idev->dev, "Mimio greeted OK.\n"); | ||
568 | mimio->greeted = 1; | ||
569 | mimio->rxhandler = mimio_rx_handler; | ||
570 | } else { | ||
571 | dev_dbg(&mimio->idev->dev, "Mimio greet Failure (%d)\n", res); | ||
572 | } | ||
573 | |||
574 | return 0; | ||
575 | } | ||
576 | |||
577 | static int handle_mimio_rx_penupdown(struct mimio *mimio, | ||
578 | int down, | ||
579 | const char *const instr[], | ||
580 | const int instr_ofst[]) | ||
581 | { | ||
582 | int penid, x; | ||
583 | if (mimio->pktbuf.q - mimio->pktbuf.p < (down ? 4 : 3)) | ||
584 | return 1; /* partial pkt */ | ||
585 | |||
586 | if (down) { | ||
587 | x = *mimio->pktbuf.p ^ *(mimio->pktbuf.p + 1) ^ | ||
588 | *(mimio->pktbuf.p + 2); | ||
589 | if (x != *(mimio->pktbuf.p + 3)) { | ||
590 | dev_dbg(&mimio->idev->dev, "EV_PEN%s: bad xsum.\n", | ||
591 | down ? "DOWN":"UP"); | ||
592 | /* skip this event data */ | ||
593 | mimio->pktbuf.p += 4; | ||
594 | /* decode any remaining events */ | ||
595 | return 0; | ||
596 | } | ||
597 | penid = mimio->pktbuf.instr = *(mimio->pktbuf.p + 2); | ||
598 | if (penid > MIMIO_PEN_MAX) { | ||
599 | dev_dbg(&mimio->idev->dev, | ||
600 | "Unmapped penID (not in [0, %d]): %d\n", | ||
601 | MIMIO_PEN_MAX, (int)mimio->pktbuf.instr); | ||
602 | penid = mimio->pktbuf.instr = 0; | ||
603 | } | ||
604 | mimio->last_pen_down = penid; | ||
605 | } else { | ||
606 | penid = mimio->last_pen_down; | ||
607 | } | ||
608 | dev_dbg(&mimio->idev->dev, "%s (id %d, code %d) %s.\n", instr[penid], | ||
609 | instr_ofst[penid], penid, down ? "down" : "up"); | ||
610 | |||
611 | if (instr_ofst[penid] >= 0) { | ||
612 | int code = BTN_TOOL_PEN + instr_ofst[penid]; | ||
613 | int value = down ? DOWNVALUE : UPVALUE; | ||
614 | if (code > KEY_MAX) | ||
615 | dev_dbg(&mimio->idev->dev, "input_event will ignore " | ||
616 | "-- code (%d) > KEY_MAX\n", code); | ||
617 | if (!test_bit(code, mimio->idev->keybit)) | ||
618 | dev_dbg(&mimio->idev->dev, "input_event will ignore " | ||
619 | "-- bit for code (%d) not enabled\n", code); | ||
620 | if (!!test_bit(code, mimio->idev->key) == value) | ||
621 | dev_dbg(&mimio->idev->dev, "input_event will ignore " | ||
622 | "-- bit for code (%d) already set to %d\n", | ||
623 | code, value); | ||
624 | if (value != DOWNVALUE) { | ||
625 | /* input_regs(mimio->idev, regs); */ | ||
626 | input_report_key(mimio->idev, code, value); | ||
627 | input_sync(mimio->idev); | ||
628 | } else { | ||
629 | /* wait until we get some coordinates */ | ||
630 | } | ||
631 | } else { | ||
632 | dev_dbg(&mimio->idev->dev, "penID offset[%d] == %d is < 0 " | ||
633 | "- not sending\n", penid, instr_ofst[penid]); | ||
634 | } | ||
635 | mimio->pktbuf.p += down ? 4 : 3; /* 3 for up, 4 for down */ | ||
636 | return 0; | ||
637 | } | ||
638 | |||
639 | /* | ||
640 | * Stay tuned for partial-packet excitement. | ||
641 | * | ||
642 | * This routine buffers data packets received from the mimio device | ||
643 | * in the mimio's data space. This buffering is necessary because | ||
644 | * the mimio's in endpoint can serve us partial packets of data, and | ||
645 | * we want the driver to support the servicing of multiple mimios. | ||
646 | * Empirical evidence gathered so far suggests that the method of | ||
647 | * buffering packet data in the mimio's data space works. Previous | ||
648 | * versions of this driver did not buffer packet data in each mimio's | ||
649 | * data-space, and were therefore not able to service multiple mimios. | ||
650 | * Note that since the caller of this routine is running in interrupt | ||
651 | * context, care needs to be taken to ensure that this routine does not | ||
652 | * become bloated, and it may be that another spinlock is needed in each | ||
653 | * mimio to guard the buffered packet data properly. | ||
654 | */ | ||
655 | static void mimio_rx_handler(struct mimio *mimio, | ||
656 | unsigned char *data, | ||
657 | unsigned int nbytes) | ||
658 | { | ||
659 | struct device *dev = &mimio->idev->dev; | ||
660 | unsigned int x; | ||
661 | unsigned int y; | ||
662 | static const char * const instr[] = { | ||
663 | "?0", | ||
664 | "black pen", "blue pen", "green pen", "red pen", | ||
665 | "brown pen", "orange pen", "purple pen", "yellow pen", | ||
666 | "big eraser", "lil eraser", | ||
667 | "?11", "?12", "?13", "?14", "?15", "?16", | ||
668 | "mimio interactive", "interactive button1", | ||
669 | "interactive button2" | ||
670 | }; | ||
671 | |||
672 | /* Mimio Interactive gives: | ||
673 | * down: [0x22 0x01 0x11 0x32 0x24] | ||
674 | * b1 : [0x22 0x01 0x12 0x31 0x24] | ||
675 | * b2 : [0x22 0x01 0x13 0x30 0x24] | ||
676 | */ | ||
677 | static const int instr_ofst[] = { | ||
678 | -1, | ||
679 | 0, 1, 2, 3, | ||
680 | 9, 9, 9, 9, | ||
681 | 4, 5, | ||
682 | -1, -1, -1, -1, -1, -1, | ||
683 | 6, 7, 8, | ||
684 | }; | ||
685 | |||
686 | memcpy(mimio->pktbuf.q, data, nbytes); | ||
687 | mimio->pktbuf.q += nbytes; | ||
688 | |||
689 | while (mimio->pktbuf.p < mimio->pktbuf.q) { | ||
690 | int t = *mimio->pktbuf.p; | ||
691 | switch (t) { | ||
692 | case MIMIO_EV_PENUP: | ||
693 | case MIMIO_EV_PENDOWN: | ||
694 | if (handle_mimio_rx_penupdown(mimio, | ||
695 | t == MIMIO_EV_PENDOWN, | ||
696 | instr, instr_ofst)) | ||
697 | return; /* partial packet */ | ||
698 | break; | ||
699 | |||
700 | case MIMIO_EV_PENDATA: | ||
701 | if (mimio->pktbuf.q - mimio->pktbuf.p < 6) | ||
702 | /* partial pkt */ | ||
703 | return; | ||
704 | x = *mimio->pktbuf.p ^ *(mimio->pktbuf.p + 1) ^ | ||
705 | *(mimio->pktbuf.p + 2) ^ | ||
706 | *(mimio->pktbuf.p + 3) ^ | ||
707 | *(mimio->pktbuf.p + 4); | ||
708 | if (x != *(mimio->pktbuf.p + 5)) { | ||
709 | dev_dbg(dev, "EV_PENDATA: bad xsum.\n"); | ||
710 | mimio->pktbuf.p += 6; /* skip this event data */ | ||
711 | break; /* decode any remaining events */ | ||
712 | } | ||
713 | x = *(mimio->pktbuf.p + 1); | ||
714 | x <<= 8; | ||
715 | x |= *(mimio->pktbuf.p + 2); | ||
716 | y = *(mimio->pktbuf.p + 3); | ||
717 | y <<= 8; | ||
718 | y |= *(mimio->pktbuf.p + 4); | ||
719 | dev_dbg(dev, "coord: (%d, %d)\n", x, y); | ||
720 | if (instr_ofst[mimio->pktbuf.instr] >= 0) { | ||
721 | int code = BTN_TOOL_PEN + | ||
722 | instr_ofst[mimio->last_pen_down]; | ||
723 | #if 0 | ||
724 | /* Utter hack to ensure we get forwarded _AND_ | ||
725 | * so we can identify when a complete signal is | ||
726 | * received */ | ||
727 | mimio->idev->abs[ABS_Y] = -1; | ||
728 | mimio->idev->abs[ABS_X] = -1; | ||
729 | #endif | ||
730 | /* input_regs(mimio->idev, regs); */ | ||
731 | input_report_abs(mimio->idev, ABS_X, x); | ||
732 | input_report_abs(mimio->idev, ABS_Y, y); | ||
733 | /* fake a penup */ | ||
734 | change_bit(code, mimio->idev->key); | ||
735 | input_report_key(mimio->idev, | ||
736 | code, | ||
737 | DOWNVALUE); | ||
738 | /* always sync here */ | ||
739 | mimio->idev->sync = 0; | ||
740 | input_sync(mimio->idev); | ||
741 | } | ||
742 | mimio->pktbuf.p += 6; | ||
743 | break; | ||
744 | case MIMIO_EV_MEMRESET: | ||
745 | if (mimio->pktbuf.q - mimio->pktbuf.p < 7) | ||
746 | /* partial pkt */ | ||
747 | return; | ||
748 | dev_dbg(dev, "mem-reset.\n"); | ||
749 | /* input_regs(mimio->idev, regs); */ | ||
750 | input_event(mimio->idev, EV_KEY, BTN_0, 1); | ||
751 | input_event(mimio->idev, EV_KEY, BTN_0, 0); | ||
752 | input_sync(mimio->idev); | ||
753 | mimio->pktbuf.p += 7; | ||
754 | break; | ||
755 | case MIMIO_EV_ACC: | ||
756 | if (mimio->pktbuf.q - mimio->pktbuf.p < 4) | ||
757 | /* partial pkt */ | ||
758 | return; | ||
759 | x = *mimio->pktbuf.p ^ *(mimio->pktbuf.p + 1) ^ | ||
760 | *(mimio->pktbuf.p + 2); | ||
761 | if (x != *(mimio->pktbuf.p + 3)) { | ||
762 | dev_dbg(dev, "EV_ACC: bad xsum.\n"); | ||
763 | mimio->pktbuf.p += 4; /* skip this event data */ | ||
764 | break; /* decode any remaining events */ | ||
765 | } | ||
766 | switch (*(mimio->pktbuf.p + 2)) { | ||
767 | case ACC_NEWPAGE: | ||
768 | dev_dbg(&mimio->idev->dev, "new-page.\n"); | ||
769 | /* input_regs(mimio->idev, regs); */ | ||
770 | input_event(mimio->idev, EV_KEY, BTN_1, 1); | ||
771 | input_event(mimio->idev, EV_KEY, BTN_1, 0); | ||
772 | input_sync(mimio->idev); | ||
773 | break; | ||
774 | case ACC_TAGPAGE: | ||
775 | dev_dbg(&mimio->idev->dev, "tag-page.\n"); | ||
776 | /* input_regs(mimio->idev, regs); */ | ||
777 | input_event(mimio->idev, EV_KEY, BTN_2, 1); | ||
778 | input_event(mimio->idev, EV_KEY, BTN_2, 0); | ||
779 | input_sync(mimio->idev); | ||
780 | break; | ||
781 | case ACC_PRINTPAGE: | ||
782 | dev_dbg(&mimio->idev->dev, "print-page.\n"); | ||
783 | /* input_regs(mimio->idev, regs);*/ | ||
784 | input_event(mimio->idev, EV_KEY, BTN_3, 1); | ||
785 | input_event(mimio->idev, EV_KEY, BTN_3, 0); | ||
786 | input_sync(mimio->idev); | ||
787 | break; | ||
788 | case ACC_MAXIMIZE: | ||
789 | dev_dbg(&mimio->idev->dev, | ||
790 | "maximize-window.\n"); | ||
791 | /* input_regs(mimio->idev, regs); */ | ||
792 | input_event(mimio->idev, EV_KEY, BTN_4, 1); | ||
793 | input_event(mimio->idev, EV_KEY, BTN_4, 0); | ||
794 | input_sync(mimio->idev); | ||
795 | break; | ||
796 | case ACC_FINDCTLPNL: | ||
797 | dev_dbg(&mimio->idev->dev, "find-ctl-panel.\n"); | ||
798 | /* input_regs(mimio->idev, regs); */ | ||
799 | input_event(mimio->idev, EV_KEY, BTN_5, 1); | ||
800 | input_event(mimio->idev, EV_KEY, BTN_5, 0); | ||
801 | input_sync(mimio->idev); | ||
802 | break; | ||
803 | case ACC_DONE: | ||
804 | dev_dbg(&mimio->idev->dev, "acc-done.\n"); | ||
805 | /* no event is dispatched to the input | ||
806 | * subsystem for this device event. | ||
807 | */ | ||
808 | break; | ||
809 | default: | ||
810 | dev_dbg(dev, "unknown acc event.\n"); | ||
811 | break; | ||
812 | } | ||
813 | mimio->pktbuf.p += 4; | ||
814 | break; | ||
815 | default: | ||
816 | mimio->pktbuf.p++; | ||
817 | break; | ||
818 | } | ||
819 | } | ||
820 | |||
821 | /* | ||
822 | * No partial event was received, so reset mimio's pktbuf ptrs. | ||
823 | */ | ||
824 | mimio->pktbuf.p = mimio->pktbuf.q = mimio->pktbuf.buf; | ||
825 | } | ||
826 | |||
827 | static int mimio_tx(struct mimio *mimio, const char *buf, int nbytes) | ||
828 | { | ||
829 | int rslt; | ||
830 | int timeout; | ||
831 | unsigned long flags; | ||
832 | DECLARE_WAITQUEUE(wait, current); | ||
833 | |||
834 | if (!(isvalidtxsize(nbytes))) { | ||
835 | dev_err(&mimio->idev->dev, "invalid arg: nbytes: %d.\n", | ||
836 | nbytes); | ||
837 | return -EINVAL; | ||
838 | } | ||
839 | |||
840 | /* | ||
841 | * Init the out urb and copy the data to send. | ||
842 | */ | ||
843 | mimio->out.urb->dev = mimio->udev; | ||
844 | mimio->out.urb->transfer_buffer_length = nbytes; | ||
845 | memcpy(mimio->out.urb->transfer_buffer, buf, nbytes); | ||
846 | |||
847 | /* | ||
848 | * Send the data. | ||
849 | */ | ||
850 | spin_lock_irqsave(&mimio->txlock, flags); | ||
851 | mimio->txflags = MIMIO_TXWAIT; | ||
852 | rslt = usb_submit_urb(mimio->out.urb, GFP_ATOMIC); | ||
853 | spin_unlock_irqrestore(&mimio->txlock, flags); | ||
854 | dev_dbg(&mimio->idev->dev, "rslt: %d.\n", rslt); | ||
855 | |||
856 | if (rslt) { | ||
857 | dev_err(&mimio->idev->dev, "usb_submit_urb failure: %d.\n", | ||
858 | rslt); | ||
859 | return rslt; | ||
860 | } | ||
861 | |||
862 | /* | ||
863 | * Wait for completion to be signalled (the mimio_irq_out | ||
864 | * completion routine will or MIMIO_TXDONE in with txflags). | ||
865 | */ | ||
866 | timeout = HZ; | ||
867 | set_current_state(TASK_INTERRUPTIBLE); | ||
868 | add_wait_queue(&mimio->waitq, &wait); | ||
869 | |||
870 | while (timeout && ((mimio->txflags & MIMIO_TXDONE) == 0)) { | ||
871 | timeout = schedule_timeout(timeout); | ||
872 | rmb(); | ||
873 | } | ||
874 | |||
875 | if ((mimio->txflags & MIMIO_TXDONE) == 0) | ||
876 | dev_dbg(&mimio->idev->dev, "tx timed out.\n"); | ||
877 | |||
878 | /* | ||
879 | * Now that completion has been signalled, | ||
880 | * unlink the urb so that it can be recycled. | ||
881 | */ | ||
882 | set_current_state(TASK_RUNNING); | ||
883 | remove_wait_queue(&mimio->waitq, &wait); | ||
884 | usb_unlink_urb(mimio->out.urb); | ||
885 | |||
886 | return rslt; | ||
887 | } | ||
888 | |||
889 | static int __init mimio_init(void) | ||
890 | { | ||
891 | int rslt; | ||
892 | |||
893 | rslt = usb_register(&mimio_driver); | ||
894 | if (rslt != 0) { | ||
895 | err("%s: usb_register failure: %d", __func__, rslt); | ||
896 | return rslt; | ||
897 | } | ||
898 | |||
899 | printk(KERN_INFO KBUILD_MODNAME ":" | ||
900 | DRIVER_DESC " " DRIVER_VERSION "\n"); | ||
901 | return rslt; | ||
902 | } | ||
903 | |||
904 | static void __exit mimio_exit(void) | ||
905 | { | ||
906 | usb_deregister(&mimio_driver); | ||
907 | } | ||
908 | |||
909 | module_init(mimio_init); | ||
910 | module_exit(mimio_exit); | ||
911 | |||
912 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
913 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
914 | MODULE_LICENSE("GPL"); | ||