Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+928
+2
drivers/staging/Kconfig
··· 85 85 86 86 source "drivers/staging/rspiusb/Kconfig" 87 87 88 + source "drivers/staging/mimio/Kconfig" 89 + 88 90 endif # !STAGING_EXCLUDE_BUILD 89 91 endif # STAGING
+1
drivers/staging/Makefile
··· 25 25 obj-$(CONFIG_ALTERA_PCIE_CHDMA) += altpciechdma/ 26 26 obj-$(CONFIG_RTL8187SE) += rtl8187se/ 27 27 obj-$(CONFIG_USB_RSPI) += rspiusb/ 28 + obj-$(CONFIG_INPUT_MIMIO) += mimio/
+10
drivers/staging/mimio/Kconfig
··· 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.
+1
drivers/staging/mimio/Makefile
··· 1 + obj-$(CONFIG_INPUT_MIMIO) += mimio.o
+914
drivers/staging/mimio/mimio.c
··· 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");