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

Staging: add frontier tranzport and alphatrack drivers

Adds the tranzport and alphatrack drivers to the staging tree.

Cc: David Taht <d@teklibre.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

David Taht and committed by
Greg Kroah-Hartman
8da3dc28 1242c70d

+2525
+2
drivers/staging/Kconfig
··· 89 89 90 90 source "drivers/staging/mimio/Kconfig" 91 91 92 + source "drivers/staging/frontier/Kconfig" 93 + 92 94 endif # !STAGING_EXCLUDE_BUILD 93 95 endif # STAGING
+1
drivers/staging/Makefile
··· 27 27 obj-$(CONFIG_RTL8187SE) += rtl8187se/ 28 28 obj-$(CONFIG_USB_RSPI) += rspiusb/ 29 29 obj-$(CONFIG_INPUT_MIMIO) += mimio/ 30 + obj-$(CONFIG_TRANZPORT) += frontier/
+6
drivers/staging/frontier/Kconfig
··· 1 + config TRANZPORT 2 + tristate "Frontier Tranzport and Alphatrack support" 3 + depends on USB 4 + default N 5 + ---help--- 6 + Enable support for the Frontier Tranzport and Alphatrack devices.
+2
drivers/staging/frontier/Makefile
··· 1 + obj-$(CONFIG_TRANZPORT) += tranzport.o 2 + obj-$(CONFIG_TRANZPORT) += alphatrack.o
+28
drivers/staging/frontier/README
··· 1 + This directory contains the USB Tranzport and Alphatrack Kernel drivers for Linux. 2 + 3 + At present the tranzport does reads/writes of 8 byte cmds to /dev/tranzport0 to control 4 + the lights and screen and wheel 5 + 6 + At present the alphatrack accepts reads/writes of 12 byte cmds to /dev/tranzport0 to control 7 + the lights and screen and fader. 8 + 9 + Both drivers also have some sysfs hooks that are non-functional at the moment. 10 + 11 + The API is currently closely tied to the ardour revision and WILL change. 12 + 13 + A sysfs interface is PERFECT for simple userspace apps to do fun things with the 14 + lights and screen. It's fairly lousy for handling input events and very lousy 15 + for watching the state of the shuttle wheel. 16 + 17 + A linux input events interface is great for the input events and shuttle wheel. It's 18 + theoretically OK on LEDs. A Fader can be mapped to an absolute mouse device. 19 + But there is no LCD support at all. 20 + 21 + In the end this is going to be driven by a midi layer, which handles all those 22 + cases via a defined API, but - among other things - is slow, doesn't do 23 + flow control, and is a LOT of extra work. Frankly, I'd like to keep the 24 + core driver simple because the only realtime work really required is 25 + the bottom half interrupt handler and the output overlapping. 26 + 27 + Exposing some sort of clean aio api to userspace would be perfect. What that 28 + API looks like? Gah. beats me.
+9
drivers/staging/frontier/TODO
··· 1 + TODO: 2 + - checkpatch.pl clean 3 + - sparse clean 4 + - fix userspace interface to be sane 5 + - possibly just port to userspace with libusb 6 + - review by the USB developer community 7 + 8 + Please send any patches for this driver to Greg Kroah-Hartman <greg@kroah.com> 9 + and David Taht <d@teklibre.com>.
+901
drivers/staging/frontier/alphatrack.c
··· 1 + /* 2 + * Frontier Designs Alphatrack driver 3 + * 4 + * Copyright (C) 2007 Michael Taht (m@taht.net) 5 + * 6 + * Based on the usbled driver and ldusb drivers by 7 + * 8 + * Copyright (C) 2004 Greg Kroah-Hartman (greg@kroah.com) 9 + * Copyright (C) 2005 Michael Hund <mhund@ld-didactic.de> 10 + * 11 + * The ldusb driver was, in turn, derived from Lego USB Tower driver 12 + * Copyright (C) 2003 David Glance <advidgsf@sourceforge.net> 13 + * 2001-2004 Juergen Stuber <starblue@users.sourceforge.net> 14 + * 15 + * This program is free software; you can redistribute it and/or 16 + * modify it under the terms of the GNU General Public License as 17 + * published by the Free Software Foundation, version 2. 18 + * 19 + */ 20 + 21 + /** 22 + * This driver uses a ring buffer for time critical reading of 23 + * interrupt in reports and provides read and write methods for 24 + * raw interrupt reports. 25 + */ 26 + 27 + /* Note: this currently uses a dumb ringbuffer for reads and writes. 28 + * A more optimal driver would cache and kill off outstanding urbs that are 29 + * now invalid, and ignore ones that already were in the queue but valid 30 + * as we only have 30 commands for the alphatrack. In particular this is 31 + * key for getting lights to flash in time as otherwise many commands 32 + * can be buffered up before the light change makes it to the interface. 33 + */ 34 + 35 + #include <linux/kernel.h> 36 + #include <linux/errno.h> 37 + #include <linux/init.h> 38 + #include <linux/slab.h> 39 + #include <linux/module.h> 40 + #include <linux/kobject.h> 41 + #include <linux/mutex.h> 42 + #include <linux/version.h> 43 + 44 + #include <asm/uaccess.h> 45 + #include <linux/input.h> 46 + #include <linux/usb.h> 47 + #include <linux/poll.h> 48 + 49 + #include "surface_sysfs.h" 50 + 51 + /* make this work on older kernel versions */ 52 + 53 + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) 54 + #include "frontier_compat.h" 55 + #endif /* older kernel versions */ 56 + 57 + #include "alphatrack.h" 58 + 59 + #define VENDOR_ID 0x165b 60 + #define PRODUCT_ID 0xfad1 61 + 62 + #ifdef CONFIG_USB_DYNAMIC_MINORS 63 + #define USB_ALPHATRACK_MINOR_BASE 0 64 + #else 65 + // FIXME 176 - is another driver's minor - apply for that 66 + // #define USB_ALPHATRACK_MINOR_BASE 177 67 + #define USB_ALPHATRACK_MINOR_BASE 176 68 + #endif 69 + 70 + /* table of devices that work with this driver */ 71 + static struct usb_device_id usb_alphatrack_table [] = { 72 + { USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, 73 + { } /* Terminating entry */ 74 + }; 75 + 76 + MODULE_DEVICE_TABLE(usb, usb_alphatrack_table); 77 + MODULE_VERSION("0.40"); 78 + MODULE_AUTHOR("Mike Taht <m@taht.net>"); 79 + MODULE_DESCRIPTION("Alphatrack USB Driver"); 80 + MODULE_LICENSE("GPL"); 81 + MODULE_SUPPORTED_DEVICE("Frontier Designs Alphatrack Control Surface"); 82 + 83 + /* These aren't done yet */ 84 + 85 + #define ALPHATRACK_HAVE_SYSFS 0 86 + #define SUPPRESS_EXTRA_ONLINE_EVENTS 0 87 + #define BUFFERED_WRITES 0 88 + #define SUPPRESS_EXTRA_OFFLINE_EVENTS 0 89 + #define COMPRESS_FADER_EVENTS 0 90 + 91 + #define BUFFERED_READS 1 92 + #define RING_BUFFER_SIZE 512 93 + #define WRITE_BUFFER_SIZE 34 94 + #define ALPHATRACK_USB_TIMEOUT 10 95 + #define OUTPUT_CMD_SIZE 8 96 + #define INPUT_CMD_SIZE 12 97 + 98 + 99 + static int debug = 0; 100 + 101 + /* Use our own dbg macro */ 102 + #define dbg_info(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) 103 + 104 + #if 0 105 + #define alphatrack_ocmd_info(dev, cmd, format, arg...) do { if (debug) ocmd_info(dev , cmd , format, ## arg); } while (0) 106 + 107 + #define alphatrack_icmd_info(dev, cmd, format, arg...) do { if (debug) icmd_info(dev , cmd, format, ## arg); } while (0) 108 + #else 109 + #define alphatrack_ocmd_info(dev, cmd, format, arg...) 110 + 111 + #define alphatrack_icmd_info(dev, cmd, format, arg...) 112 + 113 + #endif 114 + 115 + /* Module parameters */ 116 + 117 + module_param(debug, int, S_IRUGO | S_IWUSR); 118 + MODULE_PARM_DESC(debug, "Debug enabled or not"); 119 + 120 + /* All interrupt in transfers are collected in a ring buffer to 121 + * avoid racing conditions and get better performance of the driver. 122 + */ 123 + 124 + static int ring_buffer_size = RING_BUFFER_SIZE; 125 + 126 + module_param(ring_buffer_size, int, S_IRUGO); 127 + MODULE_PARM_DESC(ring_buffer_size, "Read ring buffer size"); 128 + 129 + /* The write_buffer can one day contain more than one interrupt out transfer. 130 + */ 131 + 132 + static int write_buffer_size = WRITE_BUFFER_SIZE; 133 + module_param(write_buffer_size, int, S_IRUGO); 134 + MODULE_PARM_DESC(write_buffer_size, "Write buffer size"); 135 + 136 + /* 137 + * Increase the interval for debugging purposes. 138 + * or set to 1 to use the standard interval from the endpoint descriptors. 139 + */ 140 + 141 + static int min_interrupt_in_interval = ALPHATRACK_USB_TIMEOUT; 142 + module_param(min_interrupt_in_interval, int, 0); 143 + MODULE_PARM_DESC(min_interrupt_in_interval, "Minimum interrupt in interval in ms"); 144 + 145 + static int min_interrupt_out_interval = ALPHATRACK_USB_TIMEOUT; 146 + module_param(min_interrupt_out_interval, int, 0); 147 + MODULE_PARM_DESC(min_interrupt_out_interval, "Minimum interrupt out interval in ms"); 148 + 149 + 150 + 151 + /* Structure to hold all of our device specific stuff */ 152 + 153 + struct usb_alphatrack { 154 + struct semaphore sem; /* locks this structure */ 155 + struct usb_interface* intf; /* save off the usb interface pointer */ 156 + int open_count; /* number of times this port has been opened */ 157 + 158 + struct alphatrack_icmd (*ring_buffer)[RING_BUFFER_SIZE]; /* just make c happy */ 159 + struct alphatrack_ocmd (*write_buffer)[WRITE_BUFFER_SIZE]; /* just make c happy */ 160 + unsigned int ring_head; 161 + unsigned int ring_tail; 162 + 163 + wait_queue_head_t read_wait; 164 + wait_queue_head_t write_wait; 165 + 166 + unsigned char* interrupt_in_buffer; 167 + unsigned char* oldi_buffer; 168 + struct usb_endpoint_descriptor* interrupt_in_endpoint; 169 + struct urb* interrupt_in_urb; 170 + int interrupt_in_interval; 171 + size_t interrupt_in_endpoint_size; 172 + int interrupt_in_running; 173 + int interrupt_in_done; 174 + 175 + char* interrupt_out_buffer; 176 + struct usb_endpoint_descriptor* interrupt_out_endpoint; 177 + struct urb* interrupt_out_urb; 178 + int interrupt_out_interval; 179 + size_t interrupt_out_endpoint_size; 180 + int interrupt_out_busy; 181 + 182 + atomic_t writes_pending; 183 + int event; /* alternate interface to events */ 184 + int fader; /* 10 bits */ 185 + int lights; /* 23 bits */ 186 + unsigned char dump_state; /* 0 if disabled 1 if enabled */ 187 + unsigned char enable; /* 0 if disabled 1 if enabled */ 188 + unsigned char offline; /* if the device is out of range or asleep */ 189 + unsigned char verbose; /* be verbose in error reporting */ 190 + unsigned char last_cmd[OUTPUT_CMD_SIZE]; 191 + unsigned char screen[32]; 192 + }; 193 + 194 + /* prevent races between open() and disconnect() */ 195 + static DEFINE_MUTEX(disconnect_mutex); 196 + 197 + /* forward declaration */ 198 + 199 + static struct usb_driver usb_alphatrack_driver; 200 + 201 + static void icmd_info(struct usb_alphatrack *dev, char *cmd, char *str, char *a) { 202 + /* 203 + if (dev->verbose) { 204 + } else { 205 + } 206 + */ 207 + } 208 + 209 + static void ocmd_info(struct usb_alphatrack *dev, char *cmd, char *str, char* a) { 210 + /* 211 + if (dev->verbose) { 212 + } else { 213 + } 214 + */ 215 + } 216 + 217 + 218 + /** 219 + * usb_alphatrack_abort_transfers 220 + * aborts transfers and frees associated data structures 221 + */ 222 + static void usb_alphatrack_abort_transfers(struct usb_alphatrack *dev) 223 + { 224 + /* shutdown transfer */ 225 + if (dev->interrupt_in_running) { 226 + dev->interrupt_in_running = 0; 227 + if (dev->intf) 228 + usb_kill_urb(dev->interrupt_in_urb); 229 + } 230 + if (dev->interrupt_out_busy) 231 + if (dev->intf) 232 + usb_kill_urb(dev->interrupt_out_urb); 233 + } 234 + 235 + #if ALPHATRACK_HAVE_SYSFS 236 + /* lots and lots and lots of sysfs stuff */ 237 + /* Currently borked, probably useless */ 238 + #include "alphatrack_sysfs.c" 239 + #endif 240 + 241 + /** 242 + * usb_alphatrack_delete 243 + */ 244 + static void usb_alphatrack_delete(struct usb_alphatrack *dev) 245 + { 246 + usb_alphatrack_abort_transfers(dev); 247 + usb_free_urb(dev->interrupt_in_urb); 248 + usb_free_urb(dev->interrupt_out_urb); 249 + kfree(dev->ring_buffer); 250 + kfree(dev->interrupt_in_buffer); 251 + kfree(dev->interrupt_out_buffer); 252 + kfree(dev); // fixme oldi_buffer 253 + } 254 + 255 + /** 256 + * usb_alphatrack_interrupt_in_callback 257 + */ 258 + 259 + static void usb_alphatrack_interrupt_in_callback(struct urb *urb) 260 + { 261 + struct usb_alphatrack *dev = urb->context; 262 + unsigned int next_ring_head; 263 + int retval = -1; 264 + int *iptr; 265 + 266 + if (urb->status) { 267 + if (urb->status == -ENOENT || 268 + urb->status == -ECONNRESET || 269 + urb->status == -ESHUTDOWN) { 270 + goto exit; 271 + } else { 272 + dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n", 273 + __FUNCTION__, urb->status); 274 + goto resubmit; /* maybe we can recover */ 275 + } 276 + } 277 + 278 + if (urb->actual_length != INPUT_CMD_SIZE) { 279 + dev_warn(&dev->intf->dev, 280 + "Urb length was %d bytes!! Do something intelligent \n", urb->actual_length); 281 + } else { 282 + alphatrack_ocmd_info(&dev->intf->dev,&(*dev->ring_buffer)[dev->ring_tail].cmd,"%s", "bla"); 283 + if(memcmp(dev->interrupt_in_buffer,dev->oldi_buffer,INPUT_CMD_SIZE)==0) { 284 + goto resubmit; 285 + } 286 + memcpy(dev->oldi_buffer,dev->interrupt_in_buffer,INPUT_CMD_SIZE); 287 + 288 + #if SUPPRESS_EXTRA_OFFLINE_EVENTS 289 + if(dev->offline == 2 && dev->interrupt_in_buffer[1] == 0xff) { goto resubmit; } 290 + if(dev->offline == 1 && dev->interrupt_in_buffer[1] == 0xff) { dev->offline = 2; goto resubmit; } 291 + /* Always pass one offline event up the stack */ 292 + if(dev->offline > 0 && dev->interrupt_in_buffer[1] != 0xff) { dev->offline = 0; } 293 + if(dev->offline == 0 && dev->interrupt_in_buffer[1] == 0xff) { dev->offline = 1; } 294 + #endif 295 + dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __FUNCTION__,dev->ring_head,dev->ring_tail); 296 + next_ring_head = (dev->ring_head+1) % ring_buffer_size; 297 + 298 + if (next_ring_head != dev->ring_tail) { 299 + memcpy(&((*dev->ring_buffer)[dev->ring_head]), 300 + dev->interrupt_in_buffer, urb->actual_length); 301 + dev->ring_head = next_ring_head; 302 + retval = 0; 303 + memset(dev->interrupt_in_buffer, 0, urb->actual_length); 304 + } else { 305 + dev_warn(&dev->intf->dev, 306 + "Ring buffer overflow, %d bytes dropped\n", 307 + urb->actual_length); 308 + memset(dev->interrupt_in_buffer, 0, urb->actual_length); 309 + } 310 + } 311 + 312 + resubmit: 313 + /* resubmit if we're still running */ 314 + if (dev->interrupt_in_running && dev->intf) { 315 + retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC); 316 + if (retval) 317 + dev_err(&dev->intf->dev, 318 + "usb_submit_urb failed (%d)\n", retval); 319 + } 320 + 321 + exit: 322 + dev->interrupt_in_done = 1; 323 + wake_up_interruptible(&dev->read_wait); 324 + } 325 + 326 + /** 327 + * usb_alphatrack_interrupt_out_callback 328 + */ 329 + static void usb_alphatrack_interrupt_out_callback(struct urb *urb) 330 + { 331 + struct usb_alphatrack *dev = urb->context; 332 + 333 + /* sync/async unlink faults aren't errors */ 334 + if (urb->status && !(urb->status == -ENOENT || 335 + urb->status == -ECONNRESET || 336 + urb->status == -ESHUTDOWN)) 337 + dbg_info(&dev->intf->dev, 338 + "%s - nonzero write interrupt status received: %d\n", 339 + __FUNCTION__, urb->status); 340 + atomic_dec(&dev->writes_pending); 341 + dev->interrupt_out_busy = 0; 342 + wake_up_interruptible(&dev->write_wait); 343 + } 344 + 345 + /** 346 + * usb_alphatrack_open 347 + */ 348 + static int usb_alphatrack_open(struct inode *inode, struct file *file) 349 + { 350 + struct usb_alphatrack *dev; 351 + int subminor; 352 + int retval = 0; 353 + struct usb_interface *interface; 354 + 355 + nonseekable_open(inode, file); 356 + subminor = iminor(inode); 357 + 358 + mutex_lock(&disconnect_mutex); 359 + 360 + interface = usb_find_interface(&usb_alphatrack_driver, subminor); 361 + 362 + if (!interface) { 363 + err("%s - error, can't find device for minor %d\n", 364 + __FUNCTION__, subminor); 365 + retval = -ENODEV; 366 + goto unlock_disconnect_exit; 367 + } 368 + 369 + dev = usb_get_intfdata(interface); 370 + 371 + if (!dev) { 372 + retval = -ENODEV; 373 + goto unlock_disconnect_exit; 374 + } 375 + 376 + /* lock this device */ 377 + if (down_interruptible(&dev->sem)) { 378 + retval = -ERESTARTSYS; 379 + goto unlock_disconnect_exit; 380 + } 381 + 382 + /* allow opening only once */ 383 + if (dev->open_count) { 384 + retval = -EBUSY; 385 + goto unlock_exit; 386 + } 387 + dev->open_count = 1; 388 + 389 + /* initialize in direction */ 390 + dev->ring_head = 0; 391 + dev->ring_tail = 0; 392 + usb_fill_int_urb(dev->interrupt_in_urb, 393 + interface_to_usbdev(interface), 394 + usb_rcvintpipe(interface_to_usbdev(interface), 395 + dev->interrupt_in_endpoint->bEndpointAddress), 396 + dev->interrupt_in_buffer, 397 + dev->interrupt_in_endpoint_size, 398 + usb_alphatrack_interrupt_in_callback, 399 + dev, 400 + dev->interrupt_in_interval); 401 + 402 + dev->interrupt_in_running = 1; 403 + dev->interrupt_in_done = 0; 404 + dev->enable = 1; 405 + dev->offline = 0; 406 + 407 + retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); 408 + if (retval) { 409 + dev_err(&interface->dev, "Couldn't submit interrupt_in_urb %d\n", retval); 410 + dev->interrupt_in_running = 0; 411 + dev->open_count = 0; 412 + goto unlock_exit; 413 + } 414 + 415 + /* save device in the file's private structure */ 416 + file->private_data = dev; 417 + 418 + 419 + unlock_exit: 420 + up(&dev->sem); 421 + 422 + unlock_disconnect_exit: 423 + mutex_unlock(&disconnect_mutex); 424 + 425 + return retval; 426 + } 427 + 428 + /** 429 + * usb_alphatrack_release 430 + */ 431 + static int usb_alphatrack_release(struct inode *inode, struct file *file) 432 + { 433 + struct usb_alphatrack *dev; 434 + int retval = 0; 435 + 436 + dev = file->private_data; 437 + 438 + if (dev == NULL) { 439 + retval = -ENODEV; 440 + goto exit; 441 + } 442 + 443 + if (down_interruptible(&dev->sem)) { 444 + retval = -ERESTARTSYS; 445 + goto exit; 446 + } 447 + 448 + if (dev->open_count != 1) { 449 + retval = -ENODEV; 450 + goto unlock_exit; 451 + } 452 + 453 + if (dev->intf == NULL) { 454 + /* the device was unplugged before the file was released */ 455 + up(&dev->sem); 456 + /* unlock here as usb_alphatrack_delete frees dev */ 457 + usb_alphatrack_delete(dev); 458 + retval = -ENODEV; 459 + goto exit; 460 + } 461 + 462 + /* wait until write transfer is finished */ 463 + if (dev->interrupt_out_busy) 464 + wait_event_interruptible_timeout(dev->write_wait, !dev->interrupt_out_busy, 2 * HZ); 465 + usb_alphatrack_abort_transfers(dev); 466 + dev->open_count = 0; 467 + 468 + unlock_exit: 469 + up(&dev->sem); 470 + 471 + exit: 472 + return retval; 473 + } 474 + 475 + /** 476 + * usb_alphatrack_poll 477 + */ 478 + static unsigned int usb_alphatrack_poll(struct file *file, poll_table *wait) 479 + { 480 + struct usb_alphatrack *dev; 481 + unsigned int mask = 0; 482 + 483 + dev = file->private_data; 484 + 485 + poll_wait(file, &dev->read_wait, wait); 486 + poll_wait(file, &dev->write_wait, wait); 487 + 488 + if (dev->ring_head != dev->ring_tail) 489 + mask |= POLLIN | POLLRDNORM; 490 + if (!dev->interrupt_out_busy) 491 + mask |= POLLOUT | POLLWRNORM; 492 + 493 + return mask; 494 + } 495 + 496 + /** 497 + * usb_alphatrack_read 498 + */ 499 + static ssize_t usb_alphatrack_read(struct file *file, char __user *buffer, size_t count, 500 + loff_t *ppos) 501 + { 502 + struct usb_alphatrack *dev; 503 + int retval = 0; 504 + 505 + int c = 0; 506 + 507 + dev = file->private_data; 508 + 509 + /* verify that we actually have some data to read */ 510 + if (count == 0) 511 + goto exit; 512 + 513 + /* lock this object */ 514 + if (down_interruptible(&dev->sem)) { 515 + retval = -ERESTARTSYS; 516 + goto exit; 517 + } 518 + 519 + /* verify that the device wasn't unplugged */ 520 + if (dev->intf == NULL) { 521 + retval = -ENODEV; 522 + err("No device or device unplugged %d\n", retval); 523 + goto unlock_exit; 524 + } 525 + 526 + while (dev->ring_head == dev->ring_tail) { 527 + if (file->f_flags & O_NONBLOCK) { 528 + retval = -EAGAIN; 529 + goto unlock_exit; 530 + } 531 + dev->interrupt_in_done = 0 ; 532 + retval = wait_event_interruptible(dev->read_wait, dev->interrupt_in_done); 533 + if (retval < 0) { 534 + goto unlock_exit; 535 + } 536 + } 537 + 538 + alphatrack_ocmd_info(&dev->intf->dev, &(*dev->ring_buffer)[dev->ring_tail].cmd, "%s", ": copying to userspace"); 539 + 540 + c = 0; 541 + while((c < count) && (dev->ring_tail != dev->ring_head)) { 542 + if (copy_to_user(&buffer[c], &(*dev->ring_buffer)[dev->ring_tail], INPUT_CMD_SIZE)) { 543 + retval = -EFAULT; 544 + goto unlock_exit; 545 + } 546 + dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size; 547 + c+=INPUT_CMD_SIZE; 548 + dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __FUNCTION__,dev->ring_head,dev->ring_tail); 549 + } 550 + retval = c; 551 + 552 + unlock_exit: 553 + /* unlock the device */ 554 + up(&dev->sem); 555 + 556 + exit: 557 + return retval; 558 + } 559 + 560 + /** 561 + * usb_alphatrack_write 562 + */ 563 + static ssize_t usb_alphatrack_write(struct file *file, const char __user *buffer, 564 + size_t count, loff_t *ppos) 565 + { 566 + struct usb_alphatrack *dev; 567 + size_t bytes_to_write; 568 + int retval = 0; 569 + 570 + dev = file->private_data; 571 + 572 + /* verify that we actually have some data to write */ 573 + if (count == 0) 574 + goto exit; 575 + 576 + /* lock this object */ 577 + if (down_interruptible(&dev->sem)) { 578 + retval = -ERESTARTSYS; 579 + goto exit; 580 + } 581 + 582 + /* verify that the device wasn't unplugged */ 583 + if (dev->intf == NULL) { 584 + retval = -ENODEV; 585 + err("No device or device unplugged %d\n", retval); 586 + goto unlock_exit; 587 + } 588 + 589 + /* wait until previous transfer is finished */ 590 + if (dev->interrupt_out_busy) { 591 + if (file->f_flags & O_NONBLOCK) { 592 + retval = -EAGAIN; 593 + goto unlock_exit; 594 + } 595 + retval = wait_event_interruptible(dev->write_wait, !dev->interrupt_out_busy); 596 + if (retval < 0) { 597 + goto unlock_exit; 598 + } 599 + } 600 + 601 + /* write the data into interrupt_out_buffer from userspace */ 602 + /* FIXME - if you write more than 12 bytes this breaks */ 603 + bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size); 604 + if (bytes_to_write < count) 605 + dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n",count-bytes_to_write); 606 + 607 + dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", __FUNCTION__, count, bytes_to_write); 608 + 609 + if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) { 610 + retval = -EFAULT; 611 + goto unlock_exit; 612 + } 613 + 614 + if (dev->interrupt_out_endpoint == NULL) { 615 + err("Endpoint should not be be null! \n"); 616 + goto unlock_exit; 617 + } 618 + 619 + /* send off the urb */ 620 + usb_fill_int_urb(dev->interrupt_out_urb, 621 + interface_to_usbdev(dev->intf), 622 + usb_sndintpipe(interface_to_usbdev(dev->intf), 623 + dev->interrupt_out_endpoint->bEndpointAddress), 624 + dev->interrupt_out_buffer, 625 + bytes_to_write, 626 + usb_alphatrack_interrupt_out_callback, 627 + dev, 628 + dev->interrupt_out_interval); 629 + dev->interrupt_out_busy = 1; 630 + atomic_inc(&dev->writes_pending); 631 + wmb(); 632 + 633 + retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL); 634 + if (retval) { 635 + dev->interrupt_out_busy = 0; 636 + err("Couldn't submit interrupt_out_urb %d\n", retval); 637 + atomic_dec(&dev->writes_pending); 638 + goto unlock_exit; 639 + } 640 + retval = bytes_to_write; 641 + 642 + unlock_exit: 643 + /* unlock the device */ 644 + up(&dev->sem); 645 + 646 + exit: 647 + return retval; 648 + } 649 + 650 + /* file operations needed when we register this driver */ 651 + static const struct file_operations usb_alphatrack_fops = { 652 + .owner = THIS_MODULE, 653 + .read = usb_alphatrack_read, 654 + .write = usb_alphatrack_write, 655 + .open = usb_alphatrack_open, 656 + .release = usb_alphatrack_release, 657 + .poll = usb_alphatrack_poll, 658 + }; 659 + 660 + /* 661 + * usb class driver info in order to get a minor number from the usb core, 662 + * and to have the device registered with the driver core 663 + */ 664 + 665 + static struct usb_class_driver usb_alphatrack_class = { 666 + .name = "alphatrack%d", 667 + .fops = &usb_alphatrack_fops, 668 + .minor_base = USB_ALPHATRACK_MINOR_BASE, 669 + }; 670 + 671 + 672 + /** 673 + * usb_alphatrack_probe 674 + * 675 + * Called by the usb core when a new device is connected that it thinks 676 + * this driver might be interested in. 677 + */ 678 + static int usb_alphatrack_probe(struct usb_interface *intf, const struct usb_device_id *id) 679 + { 680 + struct usb_device *udev = interface_to_usbdev(intf); 681 + struct usb_alphatrack *dev = NULL; 682 + struct usb_host_interface *iface_desc; 683 + struct usb_endpoint_descriptor *endpoint; 684 + int i; 685 + int true_size; 686 + int retval = -ENOMEM; 687 + 688 + /* allocate memory for our device state and intialize it */ 689 + 690 + dev = kzalloc(sizeof(*dev), GFP_KERNEL); 691 + if (dev == NULL) { 692 + dev_err(&intf->dev, "Out of memory\n"); 693 + goto exit; 694 + } 695 + init_MUTEX(&dev->sem); 696 + dev->intf = intf; 697 + init_waitqueue_head(&dev->read_wait); 698 + init_waitqueue_head(&dev->write_wait); 699 + 700 + iface_desc = intf->cur_altsetting; 701 + 702 + /* set up the endpoint information */ 703 + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { 704 + endpoint = &iface_desc->endpoint[i].desc; 705 + 706 + if (usb_endpoint_is_int_in(endpoint)) 707 + dev->interrupt_in_endpoint = endpoint; 708 + 709 + if (usb_endpoint_is_int_out(endpoint)) 710 + dev->interrupt_out_endpoint = endpoint; 711 + } 712 + if (dev->interrupt_in_endpoint == NULL) { 713 + dev_err(&intf->dev, "Interrupt in endpoint not found\n"); 714 + goto error; 715 + } 716 + if (dev->interrupt_out_endpoint == NULL) 717 + dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n"); 718 + 719 + dev->interrupt_in_endpoint_size = le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize); 720 + 721 + if (dev->interrupt_in_endpoint_size != 64) 722 + dev_warn(&intf->dev, "Interrupt in endpoint size is not 64!\n"); 723 + 724 + if(ring_buffer_size == 0) { ring_buffer_size = RING_BUFFER_SIZE; } 725 + 726 + true_size = min(ring_buffer_size,RING_BUFFER_SIZE); 727 + 728 + /* FIXME - there are more usb_alloc routines for dma correctness. Needed? */ 729 + 730 + // dev->ring_buffer = kmalloc((true_size*sizeof(struct alphatrack_icmd))+12, GFP_KERNEL); 731 + dev->ring_buffer = kmalloc((true_size*sizeof(struct alphatrack_icmd)), GFP_KERNEL); 732 + 733 + if (!dev->ring_buffer) { 734 + dev_err(&intf->dev, "Couldn't allocate input ring_buffer of size %d\n",true_size); 735 + goto error; 736 + } 737 + 738 + dev->interrupt_in_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL); 739 + 740 + if (!dev->interrupt_in_buffer) { 741 + dev_err(&intf->dev, "Couldn't allocate interrupt_in_buffer\n"); 742 + goto error; 743 + } 744 + dev->oldi_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL); 745 + if (!dev->oldi_buffer) { 746 + dev_err(&intf->dev, "Couldn't allocate old buffer\n"); 747 + goto error; 748 + } 749 + dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); 750 + if (!dev->interrupt_in_urb) { 751 + dev_err(&intf->dev, "Couldn't allocate interrupt_in_urb\n"); 752 + goto error; 753 + } 754 + 755 + dev->interrupt_out_endpoint_size = dev->interrupt_out_endpoint ? le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize) : 756 + udev->descriptor.bMaxPacketSize0; 757 + 758 + if (dev->interrupt_out_endpoint_size !=64) 759 + dev_warn(&intf->dev, "Interrupt out endpoint size is not 64!)\n"); 760 + 761 + if(write_buffer_size == 0) { write_buffer_size = WRITE_BUFFER_SIZE; } 762 + true_size = min(write_buffer_size,WRITE_BUFFER_SIZE); 763 + 764 + dev->interrupt_out_buffer = kmalloc(true_size*dev->interrupt_out_endpoint_size, GFP_KERNEL); 765 + 766 + if (!dev->interrupt_out_buffer) { 767 + dev_err(&intf->dev, "Couldn't allocate interrupt_out_buffer\n"); 768 + goto error; 769 + } 770 + 771 + dev->write_buffer = kmalloc(sizeof(struct alphatrack_ocmd)*true_size, GFP_KERNEL); 772 + 773 + if (!dev->write_buffer) { 774 + dev_err(&intf->dev, "Couldn't allocate write_buffer \n"); 775 + goto error; 776 + } 777 + 778 + dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); 779 + if (!dev->interrupt_out_urb) { 780 + dev_err(&intf->dev, "Couldn't allocate interrupt_out_urb\n"); 781 + goto error; 782 + } 783 + dev->interrupt_in_interval = min_interrupt_in_interval > dev->interrupt_in_endpoint->bInterval ? min_interrupt_in_interval : dev->interrupt_in_endpoint->bInterval; 784 + if (dev->interrupt_out_endpoint) 785 + dev->interrupt_out_interval = min_interrupt_out_interval > dev->interrupt_out_endpoint->bInterval ? min_interrupt_out_interval : dev->interrupt_out_endpoint->bInterval; 786 + 787 + /* we can register the device now, as it is ready */ 788 + usb_set_intfdata(intf, dev); 789 + 790 + atomic_set(&dev->writes_pending,0); 791 + retval = usb_register_dev(intf, &usb_alphatrack_class); 792 + if (retval) { 793 + /* something prevented us from registering this driver */ 794 + dev_err(&intf->dev, "Not able to get a minor for this device.\n"); 795 + usb_set_intfdata(intf, NULL); 796 + goto error; 797 + } 798 + 799 + /* let the user know what node this device is now attached to */ 800 + dev_info(&intf->dev, "Alphatrack Device #%d now attached to major %d minor %d\n", 801 + (intf->minor - USB_ALPHATRACK_MINOR_BASE), USB_MAJOR, intf->minor); 802 + 803 + #if ALPHATRACK_HAVE_SYSFS 804 + if((retval = device_create_file(&intf->dev, &dev_attr_event))) goto error; 805 + if((retval = device_create_file(&intf->dev, &dev_attr_dump_state))) goto error; 806 + if((retval = device_create_file(&intf->dev, &dev_attr_enable))) goto error; 807 + if((retval = device_create_file(&intf->dev, &dev_attr_offline))) goto error; 808 + 809 + /* exercise sysfs */ 810 + 811 + set_lights("32767"); // turn on all the lights 812 + set_fader0("1023"); // Move fader to max 813 + set_screen("INITIALIZING ALPHATRACK..."); 814 + set_lights("0"); 815 + set_fader0("0"); 816 + set_screen(" "); 817 + 818 + #endif 819 + 820 + exit: 821 + return retval; 822 + 823 + error: 824 + usb_alphatrack_delete(dev); 825 + 826 + return retval; 827 + } 828 + 829 + /** 830 + * usb_alphatrack_disconnect 831 + * 832 + * Called by the usb core when the device is removed from the system. 833 + */ 834 + static void usb_alphatrack_disconnect(struct usb_interface *intf) 835 + { 836 + struct usb_alphatrack *dev; 837 + int minor; 838 + 839 + mutex_lock(&disconnect_mutex); 840 + 841 + dev = usb_get_intfdata(intf); 842 + usb_set_intfdata(intf, NULL); 843 + 844 + down(&dev->sem); 845 + 846 + minor = intf->minor; 847 + 848 + /* give back our minor */ 849 + usb_deregister_dev(intf, &usb_alphatrack_class); 850 + 851 + /* if the device is not opened, then we clean up right now */ 852 + if (!dev->open_count) { 853 + up(&dev->sem); 854 + usb_alphatrack_delete(dev); 855 + } else { 856 + dev->intf = NULL; 857 + up(&dev->sem); 858 + } 859 + 860 + atomic_set(&dev->writes_pending,0); 861 + mutex_unlock(&disconnect_mutex); 862 + 863 + dev_info(&intf->dev, "Alphatrack Surface #%d now disconnected\n", 864 + (minor - USB_ALPHATRACK_MINOR_BASE)); 865 + } 866 + 867 + /* usb specific object needed to register this driver with the usb subsystem */ 868 + static struct usb_driver usb_alphatrack_driver = { 869 + .name = "alphatrack", 870 + .probe = usb_alphatrack_probe, 871 + .disconnect = usb_alphatrack_disconnect, 872 + .id_table = usb_alphatrack_table, 873 + }; 874 + 875 + /** 876 + * usb_alphatrack_init 877 + */ 878 + static int __init usb_alphatrack_init(void) 879 + { 880 + int retval; 881 + 882 + /* register this driver with the USB subsystem */ 883 + retval = usb_register(&usb_alphatrack_driver); 884 + if (retval) 885 + err("usb_register failed for the "__FILE__" driver. Error number %d\n", retval); 886 + 887 + return retval; 888 + } 889 + 890 + /** 891 + * usb_alphatrack_exit 892 + */ 893 + static void __exit usb_alphatrack_exit(void) 894 + { 895 + /* deregister this driver with the USB subsystem */ 896 + usb_deregister(&usb_alphatrack_driver); 897 + } 898 + 899 + module_init(usb_alphatrack_init); 900 + module_exit(usb_alphatrack_exit); 901 +
+117
drivers/staging/frontier/alphatrack.h
··· 1 + #define show_set_bit(a) show_set_mbit(alphatrack,a) 2 + #define show_set_cmd(a) show_set_mcmd(alphatrack,a) 3 + #define show_set_int(a) show_set_mint(alphatrack,a) 4 + #define show_set_char(a) show_set_mchar(alphatrack,a) 5 + #define show_set_light(a) show_set_ebit(alphatrack,LightID,lights,a) 6 + #define show_set_button(a) show_set_ebit(alphatrack,ButtonID,button,a) 7 + 8 + struct alphatrack_icmd { 9 + unsigned char cmd[12]; 10 + }; 11 + 12 + struct alphatrack_ocmd { 13 + unsigned char cmd[8]; 14 + }; 15 + 16 + enum LightID { 17 + LIGHT_EQ = 0, 18 + LIGHT_OUT, 19 + LIGHT_F2, 20 + LIGHT_SEND, 21 + LIGHT_IN, 22 + LIGHT_F1, 23 + LIGHT_PAN, 24 + LIGHT_UNDEF1, 25 + LIGHT_UNDEF2, 26 + LIGHT_SHIFT, 27 + LIGHT_TRACKMUTE, 28 + LIGHT_TRACKSOLO, 29 + LIGHT_TRACKREC, 30 + LIGHT_READ, 31 + LIGHT_WRITE, 32 + LIGHT_ANYSOLO, 33 + LIGHT_AUTO, 34 + LIGHT_F4, 35 + LIGHT_RECORD, 36 + LIGHT_WINDOW, 37 + LIGHT_PLUGIN, 38 + LIGHT_F3, 39 + LIGHT_LOOP 40 + }; 41 + 42 + static const char *Lightname[] = { "eq", 43 + "out", 44 + "f2", 45 + "send", 46 + "in", 47 + "f1", 48 + "pan", 49 + "undef1", 50 + "undef2", 51 + "shift", 52 + "mute", 53 + "tracksolo", 54 + "trackrec", 55 + "read", 56 + "write", 57 + "anysolo", 58 + "auto", 59 + "f4", 60 + "record", 61 + "window", 62 + "plugin", 63 + "f3", 64 + "loop", 65 + NULL }; 66 + 67 + #define BUTTONMASK_BATTERY 0x00004000 68 + #define BUTTONMASK_BACKLIGHT 0x00008000 69 + #define BUTTONMASK_FASTFORWARD 0x04000000 70 + #define BUTTONMASK_TRACKMUTE 0x00040000 71 + #define BUTTONMASK_TRACKSOLO 0x00800000 72 + #define BUTTONMASK_TRACKLEFT 0x80000000 73 + #define BUTTONMASK_RECORD 0x02000000 74 + #define BUTTONMASK_SHIFT 0x20000000 75 + #define BUTTONMASK_PUNCH 0x00800000 76 + #define BUTTONMASK_TRACKRIGHT 0x00020000 77 + #define BUTTONMASK_REWIND 0x01000000 78 + #define BUTTONMASK_STOP 0x10000000 79 + #define BUTTONMASK_LOOP 0x00010000 80 + #define BUTTONMASK_TRACKREC 0x00001000 81 + #define BUTTONMASK_PLAY 0x08000000 82 + #define BUTTONMASK_TOUCH1 0x00000008 83 + #define BUTTONMASK_TOUCH2 0x00000010 84 + #define BUTTONMASK_TOUCH3 0x00000020 85 + 86 + #define BUTTONMASK_PRESS1 0x00000009 87 + #define BUTTONMASK_PRESS2 0x00008010 88 + #define BUTTONMASK_PRESS3 0x00002020 89 + 90 + // last 3 bytes are the slider position 91 + // 40 is the actual slider moving, the most sig bits, and 3 lsb 92 + 93 + #define BUTTONMASK_FLIP 0x40000000 94 + #define BUTTONMASK_F1 0x00100000 95 + #define BUTTONMASK_F2 0x00400000 96 + #define BUTTONMASK_F3 0x00200000 97 + #define BUTTONMASK_F4 0x00080000 98 + #define BUTTONMASK_PAN 0x00000200 99 + #define BUTTONMASK_SEND 0x00000800 100 + #define BUTTONMASK_EQ 0x00004000 101 + #define BUTTONMASK_PLUGIN 0x00000400 102 + #define BUTTONMASK_AUTO 0x00000100 103 + 104 + 105 + // #define BUTTONMASK_FOOTSWITCH FIXME 106 + 107 + // Lookup. name. midi out. midi in. 108 + 109 + struct buttonmap_t { 110 + u32 mask; 111 + short midi_in; 112 + short midi_out; 113 + char *name; 114 + // void (*function) (buttonmap_t *); 115 + void (*function) (void); 116 + }; 117 +
+279
drivers/staging/frontier/alphatrack_sysfs.c
··· 1 + /* This was an attempt - ultimately proved pointless - at making a full fledged sysfs interface to the alphatrack */ 2 + /* won't even compile at present */ 3 + 4 + char *alphatrack_sys_margs; 5 + spinlock_t alphatrack_sys_margs_lock; 6 + 7 + struct alphatrack_attr { 8 + struct attribute attr; 9 + ssize_t (*show)(struct device *, char *); 10 + ssize_t (*store)(struct device *, const char *, size_t); 11 + }; 12 + 13 + #define ALPHATRACK_ATTR(name, mode, show, store) \ 14 + static struct alphatrack_attr alphatrack_attr_##name = __ATTR(name, mode, show, store) 15 + 16 + /* now a great deal of callback code generation */ 17 + 18 + // FOREACH_LIGHT(show_set_light) 19 + // FOREACH_BUTTON(show_set_button) 20 + 21 + show_set_light(LIGHT_RECORD); show_set_light(LIGHT_EQ); show_set_light(LIGHT_OUT); 22 + show_set_light(LIGHT_F2); show_set_light(LIGHT_SEND); show_set_light(LIGHT_IN); 23 + show_set_light(LIGHT_F1); show_set_light(LIGHT_PAN); show_set_light(LIGHT_UNDEF1); 24 + show_set_light(LIGHT_UNDEF2); show_set_light(LIGHT_SHIFT); show_set_light(LIGHT_TRACKMUTE); 25 + show_set_light(LIGHT_TRACKSOLO); show_set_light(LIGHT_TRACKREC); show_set_light(LIGHT_READ); 26 + show_set_light(LIGHT_WRITE); show_set_light(LIGHT_ANYSOLO); show_set_light(LIGHT_AUTO); 27 + show_set_light(LIGHT_F4); show_set_light(LIGHT_RECORD); show_set_light(LIGHT_WINDOW); 28 + show_set_light(LIGHT_PLUGIN); show_set_light(LIGHT_F3); show_set_light(LIGHT_LOOP); 29 + 30 + show_set_opt(enable); show_set_opt(offline); show_set_opt(compress_fader); show_set_opt(dump_state); 31 + show_set_int(fader); show_set_int(event); 32 + 33 + 34 + static ssize_t show_lights(struct device *dev, struct device_attribute *attr, char *buf) 35 + { 36 + struct usb_interface *intf = to_usb_interface(dev); 37 + struct usb_alphatrack *t = usb_get_intfdata(intf); 38 + return sprintf(buf, "%d\n", t->lights); 39 + } 40 + 41 + static ssize_t set_lights(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 42 + { 43 + struct usb_interface *intf = to_usb_interface(dev); 44 + struct usb_alphatrack *t = usb_get_intfdata(intf); 45 + int temp = simple_strtoul(buf, NULL, 10); 46 + t->lights = temp; 47 + return count; 48 + } 49 + 50 + static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_lights, set_lights); 51 + 52 + 53 + ALPHATRACK_ATTR(LightRecord, 0200, NULL, LightRecord_store); 54 + 55 + static struct attribute *alphatrack_attrs[] = { 56 + &alphatrack_attr_LightRecord.attr, 57 + NULL, 58 + }; 59 + 60 + static ssize_t alphatrack_attr_show(struct kobject *kobj, struct attribute *attr, 61 + char *buf) 62 + { 63 + struct device *sdp = container_of(kobj, struct device, kobj); 64 + struct alphatrack_attr *a = container_of(attr, struct alphatrack_attr, attr); 65 + return a->show ? a->show(sdp, buf) : 0; 66 + } 67 + 68 + static ssize_t alphatrack_attr_store(struct kobject *kobj, struct attribute *attr, 69 + const char *buf, size_t len) 70 + { 71 + struct device *sdp = container_of(kobj, struct device, kobj); 72 + struct alphatrack_attr *a = container_of(attr, struct alphatrack_attr, attr); 73 + return a->store ? a->store(sdp, buf, len) : len; 74 + } 75 + 76 + static struct sysfs_ops alphatrack_attr_ops = { 77 + .show = alphatrack_attr_show, 78 + .store = alphatrack_attr_store, 79 + }; 80 + 81 + static struct kobj_type alphatrack_ktype = { 82 + .default_attrs = alphatrack_attrs, 83 + .sysfs_ops = &alphatrack_attr_ops, 84 + }; 85 + 86 + static struct kset alphatrack_kset = { 87 + .subsys = &fs_subsys, 88 + .kobj = {.name = "alphatrack"}, 89 + .ktype = &alphatrack_ktype, 90 + }; 91 + 92 + 93 + static struct attribute *lights_attrs[] = { 94 + &tune_attr_demote_secs.attr, 95 + NULL, 96 + }; 97 + 98 + 99 + static struct attribute_group leds_group = { 100 + .name = "leds", 101 + .attrs = lights_attrs, 102 + }; 103 + 104 + static struct attribute_group faders_group = { 105 + .name = "faders", 106 + .attrs = faders_attrs, 107 + }; 108 + 109 + static struct attribute_group lcds_group = { 110 + .name = "lcds", 111 + .attrs = lcds_attrs, 112 + }; 113 + 114 + static struct attribute_group wheels_group = { 115 + .name = "wheels", 116 + .attrs = wheels_attrs, 117 + }; 118 + 119 + static struct attribute_group touchsurfaces_group = { 120 + .name = "touchsurfaces", 121 + .attrs = touchsurfaces_attrs, 122 + }; 123 + 124 + static struct attribute_group buttons_group = { 125 + .name = "buttons", 126 + .attrs = buttons_attrs, 127 + }; 128 + 129 + 130 + int alphatrack_sys_fs_add(struct device *sdp) 131 + { 132 + int error; 133 + 134 + sdp->kobj.kset = &alphatrack_kset; 135 + sdp->kobj.ktype = &alphatrack_ktype; 136 + 137 + // error = kobject_set_name(&sdp->kobj, "%s", sdp->sd_table_name); 138 + error = kobject_set_name(&sdp->kobj, "%s", "alphatrack"); 139 + if (error) 140 + goto fail; 141 + 142 + error = kobject_register(&sdp->kobj); 143 + if (error) 144 + goto fail; 145 + 146 + error = sysfs_create_group(&sdp->kobj, &lcds_group); 147 + if (error) 148 + goto fail_reg; 149 + 150 + error = sysfs_create_group(&sdp->kobj, &leds_group); 151 + if (error) 152 + goto fail_leds; 153 + 154 + error = sysfs_create_group(&sdp->kobj, &wheels_group); 155 + if (error) 156 + goto fail_wheels; 157 + 158 + error = sysfs_create_group(&sdp->kobj, &faders_group); 159 + if (error) 160 + goto fail_lcds; 161 + 162 + error = sysfs_create_group(&sdp->kobj, &buttons_group); 163 + if (error) 164 + goto fail_faders; 165 + 166 + error = sysfs_create_group(&sdp->kobj, &touchsurfaces_group); 167 + if (error) 168 + goto fail_buttons; 169 + 170 + return 0; 171 + 172 + 173 + fail_buttons: 174 + sysfs_remove_group(&sdp->kobj, &buttons_group); 175 + fail_faders: 176 + sysfs_remove_group(&sdp->kobj, &faders_group); 177 + fail_wheels: 178 + sysfs_remove_group(&sdp->kobj, &wheels_group); 179 + fail_lcds: 180 + sysfs_remove_group(&sdp->kobj, &lcds_group); 181 + fail_leds: 182 + sysfs_remove_group(&sdp->kobj, &leds_group); 183 + 184 + 185 + 186 + fail_reg: 187 + kobject_unregister(&sdp->kobj); 188 + fail: 189 + fs_err(sdp, "error %d adding sysfs files", error); 190 + return error; 191 + } 192 + 193 + // int sysfs_create_link(struct kobject *kobj, 194 + // struct kobject *target, 195 + // char *name); 196 + 197 + void alphatrack_sys_fs_del(struct device *sdp) 198 + { 199 + sysfs_remove_group(&sdp->kobj, &touchsurfaces_group); 200 + sysfs_remove_group(&sdp->kobj, &buttons_group); 201 + sysfs_remove_group(&sdp->kobj, &faders_group); 202 + sysfs_remove_group(&sdp->kobj, &lcds_group); 203 + sysfs_remove_group(&sdp->kobj, &wheels_group); 204 + sysfs_remove_group(&sdp->kobj, &leds_group) 205 + //void sysfs_remove_link(struct kobject *kobj, char *name); 206 + kobject_unregister(&sdp->kobj); 207 + } 208 + 209 + int alphatrack_sys_init(void) 210 + { 211 + alphatrack_sys_margs = NULL; 212 + spin_lock_init(&alphatrack_sys_margs_lock); 213 + return kset_register(&alphatrack_kset); 214 + } 215 + 216 + void alphatrack_sys_uninit(void) 217 + { 218 + kfree(alphatrack_sys_margs); 219 + kset_unregister(&alphatrack_kset); 220 + } 221 + 222 + 223 + //decl_subsys(char *name, struct kobj_type *type, 224 + // struct kset_hotplug_ops *hotplug_ops); 225 + 226 + /* End of all the crazy sysfs stuff */ 227 + 228 + #define SYSEX_INQUIRE signed char *SYSEX_INQUIRE[] = { 0xf0,0x7e,0x00,0x06,0x01,0x17 }; 229 + 230 + #define COMMAND(NAME,CONT_NAME) { BUTTONMASK_##NAME, ((0x90 << 8) | CONT_NAME), ((0x90 << 8) | CONT_NAME), #NAME, NAME ## _set } 231 + #define ROTARY(NAME,CONT_NAME) { FADER_##NAME, ((0xb0 << 8) | CONT_NAME), ((0xb0 << 8) | CONT_NAME), #NAME, NAME ## _set } 232 + #define SPOSITION(NAME,CONT_NAME) { BUTTON_##NAME ((0xe9 << 8) | CONT_NAME), #NAME, NAME ## _set } 233 + #define ENDCOMMAND { 0,NULL,0,NULL,NULL} 234 + 235 + /* Now that we've generated all our callbacks */ 236 + 237 + static struct buttonmap_t buttonmap[] = 238 + { 239 + COMMAND (REWIND,0x5b), 240 + COMMAND (FASTFORWARD,0x5c), 241 + COMMAND (STOP,0x5d), 242 + COMMAND (PLAY,0x5e), 243 + COMMAND (RECORD,0x5f), 244 + COMMAND (SHIFT,0x46), 245 + COMMAND (TRACKLEFT,0x57), 246 + COMMAND (TRACKRIGHT,0x58), 247 + COMMAND (LOOP,0x56), 248 + COMMAND (FLIP,0x32), 249 + COMMAND (MUTE,0x10), 250 + COMMAND (F1,0x36), 251 + COMMAND (F2,0x37), 252 + COMMAND (F3,0x38), 253 + COMMAND (F4,0x39), 254 + COMMAND (SOLO,0x08), 255 + COMMAND (ANY,0x73), 256 + COMMAND (PAN,0x2a), 257 + COMMAND (SEND,0x29), 258 + COMMAND (EQ,0x2c), 259 + COMMAND (PLUGIN,0x2b), 260 + COMMAND (AUTO,0x4a), 261 + COMMAND (TRACKREC,0x00), 262 + COMMAND (FOOTSWITCH1,0x67), 263 + COMMAND (KNOBTOUCH1,0x78), 264 + COMMAND (KNOBPUSH1,0x20), 265 + ROTARY (KNOBTURN1,0x10), 266 + COMMAND (KNOBTOUCH2,0x79), 267 + COMMAND (KNOBPUSH2,0x21), 268 + ROTARY (KNOBTURN2,0x11), 269 + COMMAND (KNOBTOUCH3,0x7a), 270 + COMMAND (KNOBPUSH3,0x22), 271 + ROTARY (KNOBTURN3,0x12), 272 + COMMAND (FADERTOUCH1,0x68), 273 + COMMAND (STRIPTOUCH1,0x74), 274 + COMMAND (STRIPTOUCH2,0x6b), 275 + SPOSITION (STRIPPOS1,0x00), 276 + ENDCOMMAND 277 + }; 278 + 279 +
+63
drivers/staging/frontier/frontier_compat.h
··· 1 + /* USB defines for older kernels */ 2 + 3 + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) 4 + 5 + /** 6 + * usb_endpoint_dir_out - check if the endpoint has OUT direction 7 + * @epd: endpoint to be checked 8 + * 9 + * Returns true if the endpoint is of type OUT, otherwise it returns false. 10 + */ 11 + 12 + static inline int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd) 13 + { 14 + return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); 15 + } 16 + 17 + static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd) 18 + { 19 + return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN); 20 + } 21 + 22 + 23 + /** 24 + * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type 25 + * @epd: endpoint to be checked 26 + * 27 + * Returns true if the endpoint is of type interrupt, otherwise it returns 28 + * false. 29 + */ 30 + static inline int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd) 31 + { 32 + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == 33 + USB_ENDPOINT_XFER_INT); 34 + } 35 + 36 + 37 + /** 38 + * usb_endpoint_is_int_in - check if the endpoint is interrupt IN 39 + * @epd: endpoint to be checked 40 + * 41 + * Returns true if the endpoint has interrupt transfer type and IN direction, 42 + * otherwise it returns false. 43 + */ 44 + 45 + static inline int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd) 46 + { 47 + return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd)); 48 + } 49 + 50 + /** 51 + * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT 52 + * @epd: endpoint to be checked 53 + * 54 + * Returns true if the endpoint has interrupt transfer type and OUT direction, 55 + * otherwise it returns false. 56 + */ 57 + 58 + static inline int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd) 59 + { 60 + return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd)); 61 + } 62 + 63 + #endif /* older kernel versions */
+100
drivers/staging/frontier/surface_sysfs.h
··· 1 + /* If you are going to abuse the preprocessor, why not ABUSE the preprocessor? 2 + I stuck this header in a separate file so I don't have to look at it */ 3 + 4 + // FIXME Need locking or atomic ops 5 + 6 + #define show_set_mbit(dname,value,bit) \ 7 + static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ 8 + { \ 9 + struct usb_interface *intf = to_usb_interface(dev); \ 10 + struct usb_##dname *t = usb_get_intfdata(intf); \ 11 + int temp = (1 && (t->value & (1 << bit))); \ 12 + return sprintf(buf, "%d\n", temp); \ 13 + } \ 14 + static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ 15 + { \ 16 + struct usb_interface *intf = to_usb_interface(dev); \ 17 + struct usb_##dname *t = usb_get_intfdata(intf); \ 18 + int temp = simple_strtoul(buf, NULL, 10); \ 19 + if(temp > 0) { long b = 1 << bit; t->value |= b; } \ 20 + else { long b = ~(1 << bit); t->value &= b ; \ 21 + return count; \ 22 + } \ 23 + static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); 24 + 25 + #define show_set_ebit(dname,enumname,value,bit) \ 26 + static ssize_t show_##bit(struct device *dev, struct device_attribute *attr, char *buf) \ 27 + { \ 28 + struct usb_interface *intf = to_usb_interface(dev); \ 29 + struct usb_##dname *t = usb_get_intfdata(intf); \ 30 + enum enumname l = bit; \ 31 + int temp = t->value & (1 << l); \ 32 + return sprintf(buf, "%d\n", temp); \ 33 + } \ 34 + static ssize_t set_##bit(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ 35 + { \ 36 + struct usb_interface *intf = to_usb_interface(dev); \ 37 + struct usb_##dname *t = usb_get_intfdata(intf); \ 38 + int temp = simple_strtoul(buf, NULL, 10); \ 39 + enum enumname l = bit;\ 40 + long b = 1 << l; \ 41 + if(temp > 0) { t->value |= b; } \ 42 + else { t->value &= ~b ; \ 43 + return count; \ 44 + } \ 45 + static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); 46 + 47 + // FIXME FOR CORRECTLY SETTING HEX from a string 48 + #define show_set_mcmd(dname,value) \ 49 + static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ 50 + { \ 51 + struct usb_interface *intf = to_usb_interface(dev); \ 52 + struct usb_##dname *t = usb_get_intfdata(intf); \ 53 + int count = 0;\ 54 + int i; \ 55 + for (i = 0,i<sizeof(dname); i++) count += snprintf(buf, "%02x",t->dname[i]); \ 56 + return(count);\ 57 + } \ 58 + static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ 59 + { \ 60 + struct usb_interface *intf = to_usb_interface(dev); \ 61 + struct usb_##dname *t = usb_get_intfdata(intf); \ 62 + int temp = simple_strtoul(buf, NULL, 10); \ 63 + t->value = temp; \ 64 + return count; \ 65 + } \ 66 + static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); 67 + 68 + #define show_set_mint(dname,value) \ 69 + static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ 70 + { \ 71 + struct usb_interface *intf = to_usb_interface(dev); \ 72 + struct usb_##dname *t = usb_get_intfdata(intf); \ 73 + return sprintf(buf, "%d\n", t->value); \ 74 + } \ 75 + static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ 76 + { \ 77 + struct usb_interface *intf = to_usb_interface(dev); \ 78 + struct usb_##dname *t = usb_get_intfdata(intf); \ 79 + int temp = simple_strtoul(buf, NULL, 10); \ 80 + t->value = temp; \ 81 + return count; \ 82 + } \ 83 + static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); 84 + 85 + #define show_set_mchar(dname,value) \ 86 + static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ 87 + { \ 88 + struct usb_interface *intf = to_usb_interface(dev); \ 89 + struct usb_##dname *t = usb_get_intfdata(intf); \ 90 + return sprintf(buf, "%c\n", t->value); \ 91 + } \ 92 + static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ 93 + { \ 94 + struct usb_interface *intf = to_usb_interface(dev); \ 95 + struct usb_##dname *t = usb_get_intfdata(intf); \ 96 + int temp = simple_strtoul(buf, NULL, 10); \ 97 + t->value = temp; \ 98 + return count; \ 99 + } \ 100 + static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
+1017
drivers/staging/frontier/tranzport.c
··· 1 + /* 2 + * Frontier Designs Tranzport driver 3 + * 4 + * Copyright (C) 2007 Michael Taht (m@taht.net) 5 + * 6 + * Based on the usbled driver and ldusb drivers by 7 + * 8 + * Copyright (C) 2004 Greg Kroah-Hartman (greg@kroah.com) 9 + * Copyright (C) 2005 Michael Hund <mhund@ld-didactic.de> 10 + * 11 + * The ldusb driver was, in turn, derived from Lego USB Tower driver 12 + * Copyright (C) 2003 David Glance <advidgsf@sourceforge.net> 13 + * 2001-2004 Juergen Stuber <starblue@users.sourceforge.net> 14 + * 15 + * This program is free software; you can redistribute it and/or 16 + * modify it under the terms of the GNU General Public License as 17 + * published by the Free Software Foundation, version 2. 18 + * 19 + */ 20 + 21 + /** 22 + * This driver uses a ring buffer for time critical reading of 23 + * interrupt in reports and provides read and write methods for 24 + * raw interrupt reports. 25 + */ 26 + 27 + /* Note: this currently uses a dumb ringbuffer for reads and writes. 28 + * A more optimal driver would cache and kill off outstanding urbs that are 29 + * now invalid, and ignore ones that already were in the queue but valid 30 + * as we only have 17 commands for the tranzport. In particular this is 31 + * key for getting lights to flash in time as otherwise many commands 32 + * can be buffered up before the light change makes it to the interface. 33 + */ 34 + 35 + #include <linux/kernel.h> 36 + #include <linux/errno.h> 37 + #include <linux/init.h> 38 + #include <linux/slab.h> 39 + #include <linux/module.h> 40 + #include <linux/mutex.h> 41 + #include <linux/version.h> 42 + 43 + #include <asm/uaccess.h> 44 + #include <linux/input.h> 45 + #include <linux/usb.h> 46 + #include <linux/poll.h> 47 + 48 + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) 49 + #include frontier_compat.h 50 + #endif 51 + 52 + /* Define these values to match your devices */ 53 + #define VENDOR_ID 0x165b 54 + #define PRODUCT_ID 0x8101 55 + 56 + #ifdef CONFIG_USB_DYNAMIC_MINORS 57 + #define USB_TRANZPORT_MINOR_BASE 0 58 + #else 59 + // FIXME 176 - is the ldusb driver's minor - apply for a minor soon 60 + #define USB_TRANZPORT_MINOR_BASE 177 61 + #endif 62 + 63 + /* table of devices that work with this driver */ 64 + static struct usb_device_id usb_tranzport_table [] = { 65 + { USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, 66 + { } /* Terminating entry */ 67 + }; 68 + 69 + MODULE_DEVICE_TABLE(usb, usb_tranzport_table); 70 + MODULE_VERSION("0.33"); 71 + MODULE_AUTHOR("Mike Taht <m@taht.net>"); 72 + MODULE_DESCRIPTION("Tranzport USB Driver"); 73 + MODULE_LICENSE("GPL"); 74 + MODULE_SUPPORTED_DEVICE("Frontier Designs Tranzport Control Surface"); 75 + 76 + /* These two aren't done yet */ 77 + 78 + #define SUPPRESS_EXTRA_ONLINE_EVENTS 0 79 + #define BUFFERED_WRITES 0 80 + 81 + #define SUPPRESS_EXTRA_OFFLINE_EVENTS 1 82 + #define COMPRESS_WHEEL_EVENTS 1 83 + #define BUFFERED_READS 1 84 + #define RING_BUFFER_SIZE 1000 85 + #define WRITE_BUFFER_SIZE 34 86 + #define TRANZPORT_USB_TIMEOUT 10 87 + 88 + 89 + static int debug = 0; 90 + 91 + /* Use our own dbg macro */ 92 + #define dbg_info(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) 93 + 94 + /* Module parameters */ 95 + 96 + module_param(debug, int, S_IRUGO | S_IWUSR); 97 + MODULE_PARM_DESC(debug, "Debug enabled or not"); 98 + 99 + /* All interrupt in transfers are collected in a ring buffer to 100 + * avoid racing conditions and get better performance of the driver. 101 + */ 102 + 103 + static int ring_buffer_size = RING_BUFFER_SIZE; 104 + 105 + module_param(ring_buffer_size, int, S_IRUGO); 106 + MODULE_PARM_DESC(ring_buffer_size, "Read ring buffer size in reports"); 107 + 108 + /* The write_buffer can one day contain more than one interrupt out transfer. 109 + */ 110 + static int write_buffer_size = WRITE_BUFFER_SIZE; 111 + module_param(write_buffer_size, int, S_IRUGO); 112 + MODULE_PARM_DESC(write_buffer_size, "Write buffer size"); 113 + 114 + /* 115 + * Increase the interval for debugging purposes. 116 + * or set to 1 to use the standard interval from the endpoint descriptors. 117 + */ 118 + 119 + static int min_interrupt_in_interval = TRANZPORT_USB_TIMEOUT; 120 + module_param(min_interrupt_in_interval, int, 0); 121 + MODULE_PARM_DESC(min_interrupt_in_interval, "Minimum interrupt in interval in ms"); 122 + 123 + static int min_interrupt_out_interval = TRANZPORT_USB_TIMEOUT; 124 + module_param(min_interrupt_out_interval, int, 0); 125 + MODULE_PARM_DESC(min_interrupt_out_interval, "Minimum interrupt out interval in ms"); 126 + 127 + struct tranzport_cmd { 128 + unsigned char cmd[8]; 129 + }; 130 + 131 + enum LightID { 132 + LightRecord = 0, 133 + LightTrackrec, 134 + LightTrackmute, 135 + LightTracksolo, 136 + LightAnysolo, 137 + LightLoop, 138 + LightPunch 139 + }; 140 + 141 + static const char *Lightname[8] = { "LightRecord", 142 + "LightTracrec", 143 + "LightTrackmute", 144 + "LightTrackSolo", 145 + "LightAnySolo", 146 + "LightLoop", 147 + "LightPunch", 148 + NULL }; 149 + 150 + 151 + /* Structure to hold all of our device specific stuff */ 152 + 153 + struct usb_tranzport { 154 + struct semaphore sem; /* locks this structure */ 155 + struct usb_interface* intf; /* save off the usb interface pointer */ 156 + 157 + int open_count; /* number of times this port has been opened */ 158 + 159 + struct tranzport_cmd (*ring_buffer)[RING_BUFFER_SIZE]; /* just make c happy */ 160 + unsigned int ring_head; 161 + unsigned int ring_tail; 162 + 163 + wait_queue_head_t read_wait; 164 + wait_queue_head_t write_wait; 165 + 166 + unsigned char* interrupt_in_buffer; 167 + struct usb_endpoint_descriptor* interrupt_in_endpoint; 168 + struct urb* interrupt_in_urb; 169 + int interrupt_in_interval; 170 + size_t interrupt_in_endpoint_size; 171 + int interrupt_in_running; 172 + int interrupt_in_done; 173 + 174 + char* interrupt_out_buffer; 175 + struct usb_endpoint_descriptor* interrupt_out_endpoint; 176 + struct urb* interrupt_out_urb; 177 + int interrupt_out_interval; 178 + size_t interrupt_out_endpoint_size; 179 + int interrupt_out_busy; 180 + 181 + /* Sysfs and translation support */ 182 + 183 + int event; /* alternate interface to events */ 184 + int wheel; /* - for negative, 0 for none, + for positive */ 185 + unsigned char dump_state; /* 0 if disabled 1 if enabled */ 186 + unsigned char enable; /* 0 if disabled 1 if enabled */ 187 + unsigned char offline; /* if the device is out of range or asleep */ 188 + unsigned char compress_wheel; /* flag to compress wheel events */ 189 + unsigned char light; /* 7 bits used */ 190 + unsigned char last_cmd[8]; 191 + unsigned char last_input[8]; 192 + unsigned char screen[40]; // We'll also have cells 193 + 194 + }; 195 + 196 + /* prevent races between open() and disconnect() */ 197 + static DEFINE_MUTEX(disconnect_mutex); 198 + 199 + static struct usb_driver usb_tranzport_driver; 200 + 201 + /** 202 + * usb_tranzport_abort_transfers 203 + * aborts transfers and frees associated data structures 204 + */ 205 + static void usb_tranzport_abort_transfers(struct usb_tranzport *dev) 206 + { 207 + /* shutdown transfer */ 208 + if (dev->interrupt_in_running) { 209 + dev->interrupt_in_running = 0; 210 + if (dev->intf) 211 + usb_kill_urb(dev->interrupt_in_urb); 212 + } 213 + if (dev->interrupt_out_busy) 214 + if (dev->intf) 215 + usb_kill_urb(dev->interrupt_out_urb); 216 + } 217 + 218 + // FIXME ~light not good enough or correct - need atomic set_bit 219 + 220 + #define show_set_light(value) \ 221 + static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ 222 + { \ 223 + struct usb_interface *intf = to_usb_interface(dev); \ 224 + struct usb_tranzport *t = usb_get_intfdata(intf); \ 225 + enum LightID light = value; \ 226 + int temp = (1 && (t->light & (1 << light))); \ 227 + return sprintf(buf, "%d\n", temp ); \ 228 + } \ 229 + static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ 230 + { \ 231 + struct usb_interface *intf = to_usb_interface(dev); \ 232 + struct usb_tranzport *t = usb_get_intfdata(intf); \ 233 + int temp = simple_strtoul(buf, NULL, 10); \ 234 + enum LightID light = (temp << value) & (t->light << value); \ 235 + t->light = (t->light & ~light) ; \ 236 + return count; \ 237 + } \ 238 + static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); 239 + 240 + show_set_light(LightRecord); 241 + show_set_light(LightTrackrec); 242 + show_set_light(LightTrackmute); 243 + show_set_light(LightTracksolo); 244 + show_set_light(LightAnysolo); 245 + show_set_light(LightLoop); 246 + show_set_light(LightPunch); 247 + 248 + 249 + #define show_set_int(value) \ 250 + static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ 251 + { \ 252 + struct usb_interface *intf = to_usb_interface(dev); \ 253 + struct usb_tranzport *t = usb_get_intfdata(intf); \ 254 + \ 255 + return sprintf(buf, "%d\n", t->value); \ 256 + } \ 257 + static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ 258 + { \ 259 + struct usb_interface *intf = to_usb_interface(dev); \ 260 + struct usb_tranzport *t = usb_get_intfdata(intf); \ 261 + int temp = simple_strtoul(buf, NULL, 10); \ 262 + \ 263 + t->value = temp; \ 264 + return count; \ 265 + } \ 266 + static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); 267 + 268 + show_set_int(enable); 269 + show_set_int(offline); 270 + show_set_int(compress_wheel); 271 + show_set_int(dump_state); 272 + show_set_int(wheel); 273 + show_set_int(event); 274 + 275 + #define show_set_cmd(value) \ 276 + static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ 277 + { \ 278 + struct usb_interface *intf = to_usb_interface(dev); \ 279 + struct usb_tranzport *t = usb_get_intfdata(intf); \ 280 + \ 281 + return sprintf(buf, "%d\n", t->value); \ 282 + } \ 283 + static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ 284 + { \ 285 + struct usb_interface *intf = to_usb_interface(dev); \ 286 + struct usb_tranzport *t = usb_get_intfdata(intf); \ 287 + int temp = simple_strtoul(buf, NULL, 10); \ 288 + \ 289 + t->value = temp; \ 290 + return count; \ 291 + } \ 292 + static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value); 293 + 294 + 295 + 296 + 297 + /** 298 + * usb_tranzport_delete 299 + */ 300 + static void usb_tranzport_delete(struct usb_tranzport *dev) 301 + { 302 + usb_tranzport_abort_transfers(dev); 303 + /* This is just too twisted to be correct */ 304 + if(dev->intf != NULL) { 305 + device_remove_file(&dev->intf->dev, &dev_attr_LightRecord); 306 + device_remove_file(&dev->intf->dev, &dev_attr_LightTrackrec); 307 + device_remove_file(&dev->intf->dev, &dev_attr_LightTrackmute); 308 + device_remove_file(&dev->intf->dev, &dev_attr_LightTracksolo); 309 + device_remove_file(&dev->intf->dev, &dev_attr_LightTrackmute); 310 + device_remove_file(&dev->intf->dev, &dev_attr_LightAnysolo); 311 + device_remove_file(&dev->intf->dev, &dev_attr_LightLoop); 312 + device_remove_file(&dev->intf->dev, &dev_attr_LightPunch); 313 + device_remove_file(&dev->intf->dev, &dev_attr_wheel); 314 + device_remove_file(&dev->intf->dev, &dev_attr_enable); 315 + device_remove_file(&dev->intf->dev, &dev_attr_event); 316 + device_remove_file(&dev->intf->dev, &dev_attr_offline); 317 + device_remove_file(&dev->intf->dev, &dev_attr_compress_wheel); 318 + 319 + device_remove_file(&dev->intf->dev, &dev_attr_dump_state); 320 + } 321 + 322 + /* free data structures */ 323 + usb_free_urb(dev->interrupt_in_urb); 324 + usb_free_urb(dev->interrupt_out_urb); 325 + kfree(dev->ring_buffer); 326 + kfree(dev->interrupt_in_buffer); 327 + kfree(dev->interrupt_out_buffer); 328 + kfree(dev); 329 + } 330 + 331 + /** 332 + * usb_tranzport_interrupt_in_callback 333 + */ 334 + 335 + static void usb_tranzport_interrupt_in_callback(struct urb *urb) 336 + { 337 + struct usb_tranzport *dev = urb->context; 338 + unsigned int next_ring_head; 339 + int retval = -1; 340 + 341 + if (urb->status) { 342 + if (urb->status == -ENOENT || 343 + urb->status == -ECONNRESET || 344 + urb->status == -ESHUTDOWN) { 345 + goto exit; 346 + } else { 347 + dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n", 348 + __FUNCTION__, urb->status); 349 + goto resubmit; /* maybe we can recover */ 350 + } 351 + } 352 + 353 + if (urb->actual_length != 8) { 354 + dev_warn(&dev->intf->dev, 355 + "Urb length was %d bytes!! Do something intelligent \n", urb->actual_length); 356 + } else { 357 + dbg_info(&dev->intf->dev, "%s: received: %02x%02x%02x%02x%02x%02x%02x%02x\n", 358 + __FUNCTION__, dev->interrupt_in_buffer[0],dev->interrupt_in_buffer[1],dev->interrupt_in_buffer[2],dev->interrupt_in_buffer[3],dev->interrupt_in_buffer[4],dev->interrupt_in_buffer[5],dev->interrupt_in_buffer[6],dev->interrupt_in_buffer[7]); 359 + #if SUPPRESS_EXTRA_OFFLINE_EVENTS 360 + if(dev->offline == 2 && dev->interrupt_in_buffer[1] == 0xff) { goto resubmit; } 361 + if(dev->offline == 1 && dev->interrupt_in_buffer[1] == 0xff) { dev->offline = 2; goto resubmit; } 362 + 363 + /* Always pass one offline event up the stack */ 364 + if(dev->offline > 0 && dev->interrupt_in_buffer[1] != 0xff) { dev->offline = 0; } 365 + if(dev->offline == 0 && dev->interrupt_in_buffer[1] == 0xff) { dev->offline = 1; } 366 + 367 + #endif 368 + dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __FUNCTION__,dev->ring_head,dev->ring_tail); 369 + 370 + next_ring_head = (dev->ring_head+1) % ring_buffer_size; 371 + 372 + if (next_ring_head != dev->ring_tail) { 373 + memcpy(&((*dev->ring_buffer)[dev->ring_head]), dev->interrupt_in_buffer, urb->actual_length); 374 + dev->ring_head = next_ring_head; 375 + retval = 0; 376 + memset(dev->interrupt_in_buffer, 0, urb->actual_length); 377 + } else { 378 + dev_warn(&dev->intf->dev, 379 + "Ring buffer overflow, %d bytes dropped\n", 380 + urb->actual_length); 381 + memset(dev->interrupt_in_buffer, 0, urb->actual_length); 382 + } 383 + } 384 + 385 + resubmit: 386 + /* resubmit if we're still running */ 387 + if (dev->interrupt_in_running && dev->intf) { 388 + retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC); 389 + if (retval) 390 + dev_err(&dev->intf->dev, 391 + "usb_submit_urb failed (%d)\n", retval); 392 + } 393 + 394 + exit: 395 + dev->interrupt_in_done = 1; 396 + wake_up_interruptible(&dev->read_wait); 397 + } 398 + 399 + /** 400 + * usb_tranzport_interrupt_out_callback 401 + */ 402 + static void usb_tranzport_interrupt_out_callback(struct urb *urb) 403 + { 404 + struct usb_tranzport *dev = urb->context; 405 + 406 + /* sync/async unlink faults aren't errors */ 407 + if (urb->status && !(urb->status == -ENOENT || 408 + urb->status == -ECONNRESET || 409 + urb->status == -ESHUTDOWN)) 410 + dbg_info(&dev->intf->dev, 411 + "%s - nonzero write interrupt status received: %d\n", 412 + __FUNCTION__, urb->status); 413 + 414 + dev->interrupt_out_busy = 0; 415 + wake_up_interruptible(&dev->write_wait); 416 + } 417 + 418 + /** 419 + * usb_tranzport_open 420 + */ 421 + static int usb_tranzport_open(struct inode *inode, struct file *file) 422 + { 423 + struct usb_tranzport *dev; 424 + int subminor; 425 + int retval = 0; 426 + struct usb_interface *interface; 427 + 428 + nonseekable_open(inode, file); 429 + subminor = iminor(inode); 430 + 431 + mutex_lock(&disconnect_mutex); 432 + 433 + interface = usb_find_interface(&usb_tranzport_driver, subminor); 434 + 435 + if (!interface) { 436 + err("%s - error, can't find device for minor %d\n", 437 + __FUNCTION__, subminor); 438 + retval = -ENODEV; 439 + goto unlock_disconnect_exit; 440 + } 441 + 442 + dev = usb_get_intfdata(interface); 443 + 444 + if (!dev) { 445 + retval = -ENODEV; 446 + goto unlock_disconnect_exit; 447 + } 448 + 449 + /* lock this device */ 450 + if (down_interruptible(&dev->sem)) { 451 + retval = -ERESTARTSYS; 452 + goto unlock_disconnect_exit; 453 + } 454 + 455 + /* allow opening only once */ 456 + if (dev->open_count) { 457 + retval = -EBUSY; 458 + goto unlock_exit; 459 + } 460 + dev->open_count = 1; 461 + 462 + /* initialize in direction */ 463 + dev->ring_head = 0; 464 + dev->ring_tail = 0; 465 + usb_fill_int_urb(dev->interrupt_in_urb, 466 + interface_to_usbdev(interface), 467 + usb_rcvintpipe(interface_to_usbdev(interface), 468 + dev->interrupt_in_endpoint->bEndpointAddress), 469 + dev->interrupt_in_buffer, 470 + dev->interrupt_in_endpoint_size, 471 + usb_tranzport_interrupt_in_callback, 472 + dev, 473 + dev->interrupt_in_interval); 474 + 475 + dev->interrupt_in_running = 1; 476 + dev->interrupt_in_done = 0; 477 + dev->enable = 1; 478 + dev->offline = 0; 479 + dev->compress_wheel = 1; 480 + 481 + retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); 482 + if (retval) { 483 + dev_err(&interface->dev, "Couldn't submit interrupt_in_urb %d\n", retval); 484 + dev->interrupt_in_running = 0; 485 + dev->open_count = 0; 486 + goto unlock_exit; 487 + } 488 + 489 + /* save device in the file's private structure */ 490 + file->private_data = dev; 491 + 492 + 493 + unlock_exit: 494 + up(&dev->sem); 495 + 496 + unlock_disconnect_exit: 497 + mutex_unlock(&disconnect_mutex); 498 + 499 + return retval; 500 + } 501 + 502 + /** 503 + * usb_tranzport_release 504 + */ 505 + static int usb_tranzport_release(struct inode *inode, struct file *file) 506 + { 507 + struct usb_tranzport *dev; 508 + int retval = 0; 509 + 510 + dev = file->private_data; 511 + 512 + if (dev == NULL) { 513 + retval = -ENODEV; 514 + goto exit; 515 + } 516 + 517 + if (down_interruptible(&dev->sem)) { 518 + retval = -ERESTARTSYS; 519 + goto exit; 520 + } 521 + 522 + if (dev->open_count != 1) { 523 + retval = -ENODEV; 524 + goto unlock_exit; 525 + } 526 + 527 + if (dev->intf == NULL) { 528 + /* the device was unplugged before the file was released */ 529 + up(&dev->sem); 530 + /* unlock here as usb_tranzport_delete frees dev */ 531 + usb_tranzport_delete(dev); 532 + retval = -ENODEV; 533 + goto exit; 534 + } 535 + 536 + /* wait until write transfer is finished */ 537 + if (dev->interrupt_out_busy) 538 + wait_event_interruptible_timeout(dev->write_wait, !dev->interrupt_out_busy, 2 * HZ); 539 + usb_tranzport_abort_transfers(dev); 540 + dev->open_count = 0; 541 + 542 + unlock_exit: 543 + up(&dev->sem); 544 + 545 + exit: 546 + return retval; 547 + } 548 + 549 + /** 550 + * usb_tranzport_poll 551 + */ 552 + static unsigned int usb_tranzport_poll(struct file *file, poll_table *wait) 553 + { 554 + struct usb_tranzport *dev; 555 + unsigned int mask = 0; 556 + 557 + dev = file->private_data; 558 + 559 + poll_wait(file, &dev->read_wait, wait); 560 + poll_wait(file, &dev->write_wait, wait); 561 + 562 + if (dev->ring_head != dev->ring_tail) 563 + mask |= POLLIN | POLLRDNORM; 564 + if (!dev->interrupt_out_busy) 565 + mask |= POLLOUT | POLLWRNORM; 566 + 567 + return mask; 568 + } 569 + 570 + /** 571 + * usb_tranzport_read 572 + */ 573 + static ssize_t usb_tranzport_read(struct file *file, char __user *buffer, size_t count, 574 + loff_t *ppos) 575 + { 576 + struct usb_tranzport *dev; 577 + size_t bytes_to_read; 578 + int retval = 0; 579 + 580 + #if BUFFERED_READS 581 + int c = 0; 582 + #endif 583 + 584 + #if COMPRESS_WHEEL_EVENTS 585 + signed char oldwheel; 586 + signed char newwheel; 587 + int cancompress = 1; 588 + int next_tail; 589 + #endif 590 + 591 + /* do I have such a thing as a null event? */ 592 + 593 + dev = file->private_data; 594 + 595 + /* verify that we actually have some data to read */ 596 + if (count == 0) 597 + goto exit; 598 + 599 + /* lock this object */ 600 + if (down_interruptible(&dev->sem)) { 601 + retval = -ERESTARTSYS; 602 + goto exit; 603 + } 604 + 605 + /* verify that the device wasn't unplugged */ 606 + if (dev->intf == NULL) { 607 + retval = -ENODEV; 608 + err("No device or device unplugged %d\n", retval); 609 + goto unlock_exit; 610 + } 611 + 612 + while (dev->ring_head == dev->ring_tail) { 613 + 614 + if (file->f_flags & O_NONBLOCK) { 615 + retval = -EAGAIN; 616 + goto unlock_exit; 617 + } 618 + // atomic_cmp_exchange(&dev->interrupt_in_done,0,0); 619 + dev->interrupt_in_done = 0 ; /* tiny race - FIXME: make atomic? */ 620 + retval = wait_event_interruptible(dev->read_wait, dev->interrupt_in_done); 621 + if (retval < 0) { 622 + goto unlock_exit; 623 + } 624 + } 625 + 626 + dbg_info(&dev->intf->dev, "%s: copying to userspace: %02x%02x%02x%02x%02x%02x%02x%02x\n", 627 + __FUNCTION__, (*dev->ring_buffer)[dev->ring_tail].cmd[0],(*dev->ring_buffer)[dev->ring_tail].cmd[1],(*dev->ring_buffer)[dev->ring_tail].cmd[2],(*dev->ring_buffer)[dev->ring_tail].cmd[3],(*dev->ring_buffer)[dev->ring_tail].cmd[4],(*dev->ring_buffer)[dev->ring_tail].cmd[5],(*dev->ring_buffer)[dev->ring_tail].cmd[6],(*dev->ring_buffer)[dev->ring_tail].cmd[7]); 628 + 629 + #if BUFFERED_READS 630 + c = 0; 631 + while((c < count) && (dev->ring_tail != dev->ring_head)) { 632 + 633 + /* This started off in the lower level service routine, and I moved it here. Then my brain died. Not done yet. */ 634 + #if COMPRESS_WHEEL_EVENTS 635 + next_tail = (dev->ring_tail+1) % ring_buffer_size; 636 + if(dev->compress_wheel) cancompress = 1; 637 + while(dev->ring_head != next_tail && cancompress == 1 ) { 638 + newwheel = (*dev->ring_buffer)[next_tail].cmd[6]; 639 + oldwheel = (*dev->ring_buffer)[dev->ring_tail].cmd[6]; 640 + // if both are wheel events, and no buttons have changes (FIXME, do I have to check?), 641 + // and we are the same sign, we can compress +- 7F 642 + // FIXME: saner check for overflow! - max of +- 7F 643 + // FIXME the math is wrong for going in reverse, actually, as the midi spec doesn't allow signed chars 644 + 645 + dbg_info(&dev->intf->dev, "%s: trying to compress: %02x%02x%02x%02x%02x %02x %02x %02x\n", 646 + __FUNCTION__, (*dev->ring_buffer)[dev->ring_tail].cmd[0],(*dev->ring_buffer)[dev->ring_tail].cmd[1],(*dev->ring_buffer)[dev->ring_tail].cmd[2],(*dev->ring_buffer)[dev->ring_tail].cmd[3],(*dev->ring_buffer)[dev->ring_tail].cmd[4],(*dev->ring_buffer)[dev->ring_tail].cmd[5],(*dev->ring_buffer)[dev->ring_tail].cmd[6],(*dev->ring_buffer)[dev->ring_tail].cmd[7]); 647 + 648 + 649 + if(((*dev->ring_buffer)[dev->ring_tail].cmd[6] != 0 && 650 + (*dev->ring_buffer)[next_tail].cmd[6] != 0 ) && 651 + ((newwheel > 0 && oldwheel > 0) || 652 + (newwheel < 0 && oldwheel < 0)) && 653 + ((*dev->ring_buffer)[dev->ring_tail].cmd[2] == (*dev->ring_buffer)[next_tail].cmd[2]) && 654 + ((*dev->ring_buffer)[dev->ring_tail].cmd[3] == (*dev->ring_buffer)[next_tail].cmd[3]) && 655 + ((*dev->ring_buffer)[dev->ring_tail].cmd[4] == (*dev->ring_buffer)[next_tail].cmd[4]) && 656 + ((*dev->ring_buffer)[dev->ring_tail].cmd[5] == (*dev->ring_buffer)[next_tail].cmd[5])) 657 + { 658 + dbg_info(&dev->intf->dev, "%s: should compress: %02x%02x%02x%02x%02x%02x%02x%02x\n", 659 + __FUNCTION__, (*dev->ring_buffer)[dev->ring_tail].cmd[0],(*dev->ring_buffer)[dev->ring_tail].cmd[1],(*dev->ring_buffer)[dev->ring_tail].cmd[2],(*dev->ring_buffer)[dev->ring_tail].cmd[3],(*dev->ring_buffer)[dev->ring_tail].cmd[4],(*dev->ring_buffer)[dev->ring_tail].cmd[5],(*dev->ring_buffer)[dev->ring_tail].cmd[6],(*dev->ring_buffer)[dev->ring_tail].cmd[7]); 660 + 661 + newwheel += oldwheel; 662 + if(oldwheel > 0 && !(newwheel > 0)) { 663 + newwheel = 0x7f; 664 + cancompress = 0; 665 + } 666 + if(oldwheel < 0 && !(newwheel < 0)) { 667 + newwheel = 0x80; 668 + cancompress = 0; 669 + } 670 + 671 + (*dev->ring_buffer)[next_tail].cmd[6] = newwheel; 672 + dev->ring_tail = next_tail; 673 + next_tail = (dev->ring_tail+1) % ring_buffer_size; 674 + } else { 675 + cancompress = 0; 676 + } 677 + } 678 + #endif /* COMPRESS_WHEEL_EVENTS */ 679 + 680 + if (copy_to_user(&buffer[c], &(*dev->ring_buffer)[dev->ring_tail], 8)) { 681 + retval = -EFAULT; 682 + goto unlock_exit; 683 + } 684 + 685 + dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size; 686 + c+=8; 687 + dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __FUNCTION__,dev->ring_head,dev->ring_tail); 688 + } 689 + retval = c; 690 + 691 + #else 692 + if (copy_to_user(buffer, &(*dev->ring_buffer)[dev->ring_tail], 8)) { 693 + retval = -EFAULT; 694 + goto unlock_exit; 695 + } 696 + 697 + dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size; 698 + dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __FUNCTION__,dev->ring_head,dev->ring_tail); 699 + 700 + retval = 8; 701 + #endif /* BUFFERED_READS */ 702 + 703 + unlock_exit: 704 + /* unlock the device */ 705 + up(&dev->sem); 706 + 707 + exit: 708 + return retval; 709 + } 710 + 711 + /** 712 + * usb_tranzport_write 713 + */ 714 + static ssize_t usb_tranzport_write(struct file *file, const char __user *buffer, 715 + size_t count, loff_t *ppos) 716 + { 717 + struct usb_tranzport *dev; 718 + size_t bytes_to_write; 719 + int retval = 0; 720 + 721 + dev = file->private_data; 722 + 723 + /* verify that we actually have some data to write */ 724 + if (count == 0) 725 + goto exit; 726 + 727 + /* lock this object */ 728 + if (down_interruptible(&dev->sem)) { 729 + retval = -ERESTARTSYS; 730 + goto exit; 731 + } 732 + 733 + /* verify that the device wasn't unplugged */ 734 + if (dev->intf == NULL) { 735 + retval = -ENODEV; 736 + err("No device or device unplugged %d\n", retval); 737 + goto unlock_exit; 738 + } 739 + 740 + /* wait until previous transfer is finished */ 741 + if (dev->interrupt_out_busy) { 742 + if (file->f_flags & O_NONBLOCK) { 743 + retval = -EAGAIN; 744 + goto unlock_exit; 745 + } 746 + retval = wait_event_interruptible(dev->write_wait, !dev->interrupt_out_busy); 747 + if (retval < 0) { 748 + goto unlock_exit; 749 + } 750 + } 751 + 752 + /* write the data into interrupt_out_buffer from userspace */ 753 + bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size); 754 + if (bytes_to_write < count) 755 + dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n",count-bytes_to_write); 756 + 757 + dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", __FUNCTION__, count, bytes_to_write); 758 + 759 + if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) { 760 + retval = -EFAULT; 761 + goto unlock_exit; 762 + } 763 + 764 + if (dev->interrupt_out_endpoint == NULL) { 765 + err("Endpoint should not be be null! \n"); 766 + goto unlock_exit; 767 + } 768 + 769 + /* send off the urb */ 770 + usb_fill_int_urb(dev->interrupt_out_urb, 771 + interface_to_usbdev(dev->intf), 772 + usb_sndintpipe(interface_to_usbdev(dev->intf), 773 + dev->interrupt_out_endpoint->bEndpointAddress), 774 + dev->interrupt_out_buffer, 775 + bytes_to_write, 776 + usb_tranzport_interrupt_out_callback, 777 + dev, 778 + dev->interrupt_out_interval); 779 + 780 + dev->interrupt_out_busy = 1; 781 + wmb(); 782 + 783 + retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL); 784 + if (retval) { 785 + dev->interrupt_out_busy = 0; 786 + err("Couldn't submit interrupt_out_urb %d\n", retval); 787 + goto unlock_exit; 788 + } 789 + retval = bytes_to_write; 790 + 791 + unlock_exit: 792 + /* unlock the device */ 793 + up(&dev->sem); 794 + 795 + exit: 796 + return retval; 797 + } 798 + 799 + /* file operations needed when we register this driver */ 800 + static const struct file_operations usb_tranzport_fops = { 801 + .owner = THIS_MODULE, 802 + .read = usb_tranzport_read, 803 + .write = usb_tranzport_write, 804 + .open = usb_tranzport_open, 805 + .release = usb_tranzport_release, 806 + .poll = usb_tranzport_poll, 807 + }; 808 + 809 + /* 810 + * usb class driver info in order to get a minor number from the usb core, 811 + * and to have the device registered with the driver core 812 + */ 813 + static struct usb_class_driver usb_tranzport_class = { 814 + .name = "tranzport%d", 815 + .fops = &usb_tranzport_fops, 816 + .minor_base = USB_TRANZPORT_MINOR_BASE, 817 + }; 818 + 819 + 820 + /** 821 + * usb_tranzport_probe 822 + * 823 + * Called by the usb core when a new device is connected that it thinks 824 + * this driver might be interested in. 825 + */ 826 + static int usb_tranzport_probe(struct usb_interface *intf, const struct usb_device_id *id) 827 + { 828 + struct usb_device *udev = interface_to_usbdev(intf); 829 + struct usb_tranzport *dev = NULL; 830 + struct usb_host_interface *iface_desc; 831 + struct usb_endpoint_descriptor *endpoint; 832 + int i; 833 + int true_size; 834 + int retval = -ENOMEM; 835 + 836 + /* allocate memory for our device state and intialize it */ 837 + 838 + dev = kzalloc(sizeof(*dev), GFP_KERNEL); 839 + if (dev == NULL) { 840 + dev_err(&intf->dev, "Out of memory\n"); 841 + goto exit; 842 + } 843 + init_MUTEX(&dev->sem); 844 + dev->intf = intf; 845 + init_waitqueue_head(&dev->read_wait); 846 + init_waitqueue_head(&dev->write_wait); 847 + 848 + iface_desc = intf->cur_altsetting; 849 + 850 + /* set up the endpoint information */ 851 + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { 852 + endpoint = &iface_desc->endpoint[i].desc; 853 + 854 + if (usb_endpoint_is_int_in(endpoint)) 855 + dev->interrupt_in_endpoint = endpoint; 856 + 857 + if (usb_endpoint_is_int_out(endpoint)) 858 + dev->interrupt_out_endpoint = endpoint; 859 + } 860 + if (dev->interrupt_in_endpoint == NULL) { 861 + dev_err(&intf->dev, "Interrupt in endpoint not found\n"); 862 + goto error; 863 + } 864 + if (dev->interrupt_out_endpoint == NULL) 865 + dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n"); 866 + 867 + 868 + dev->interrupt_in_endpoint_size = le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize); 869 + 870 + if (dev->interrupt_in_endpoint_size != 8) 871 + dev_warn(&intf->dev, "Interrupt in endpoint size is not 8!\n"); 872 + 873 + if(ring_buffer_size == 0) { ring_buffer_size = RING_BUFFER_SIZE; } 874 + true_size = min(ring_buffer_size,RING_BUFFER_SIZE); 875 + /* FIXME - there are more usb_alloc routines for dma correctness. Needed? */ 876 + 877 + dev->ring_buffer = kmalloc((true_size*sizeof(struct tranzport_cmd))+8, GFP_KERNEL); 878 + 879 + if (!dev->ring_buffer) { 880 + dev_err(&intf->dev, "Couldn't allocate ring_buffer of size %d\n",true_size); 881 + goto error; 882 + } 883 + dev->interrupt_in_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL); 884 + if (!dev->interrupt_in_buffer) { 885 + dev_err(&intf->dev, "Couldn't allocate interrupt_in_buffer\n"); 886 + goto error; 887 + } 888 + dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); 889 + if (!dev->interrupt_in_urb) { 890 + dev_err(&intf->dev, "Couldn't allocate interrupt_in_urb\n"); 891 + goto error; 892 + } 893 + dev->interrupt_out_endpoint_size = dev->interrupt_out_endpoint ? le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize) : 894 + udev->descriptor.bMaxPacketSize0; 895 + 896 + if (dev->interrupt_out_endpoint_size !=8) 897 + dev_warn(&intf->dev, "Interrupt out endpoint size is not 8!)\n"); 898 + 899 + dev->interrupt_out_buffer = kmalloc(write_buffer_size*dev->interrupt_out_endpoint_size, GFP_KERNEL); 900 + if (!dev->interrupt_out_buffer) { 901 + dev_err(&intf->dev, "Couldn't allocate interrupt_out_buffer\n"); 902 + goto error; 903 + } 904 + dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); 905 + if (!dev->interrupt_out_urb) { 906 + dev_err(&intf->dev, "Couldn't allocate interrupt_out_urb\n"); 907 + goto error; 908 + } 909 + dev->interrupt_in_interval = min_interrupt_in_interval > dev->interrupt_in_endpoint->bInterval ? min_interrupt_in_interval : dev->interrupt_in_endpoint->bInterval; 910 + if (dev->interrupt_out_endpoint) 911 + dev->interrupt_out_interval = min_interrupt_out_interval > dev->interrupt_out_endpoint->bInterval ? min_interrupt_out_interval : dev->interrupt_out_endpoint->bInterval; 912 + 913 + /* we can register the device now, as it is ready */ 914 + usb_set_intfdata(intf, dev); 915 + 916 + retval = usb_register_dev(intf, &usb_tranzport_class); 917 + if (retval) { 918 + /* something prevented us from registering this driver */ 919 + dev_err(&intf->dev, "Not able to get a minor for this device.\n"); 920 + usb_set_intfdata(intf, NULL); 921 + goto error; 922 + } 923 + 924 + if((retval = device_create_file(&intf->dev, &dev_attr_LightRecord))) goto error; 925 + if((retval = device_create_file(&intf->dev, &dev_attr_LightTrackrec))) goto error; 926 + if((retval = device_create_file(&intf->dev, &dev_attr_LightTrackmute))) goto error; 927 + if((retval = device_create_file(&intf->dev, &dev_attr_LightTracksolo))) goto error; 928 + if((retval = device_create_file(&intf->dev, &dev_attr_LightAnysolo))) goto error; 929 + if((retval = device_create_file(&intf->dev, &dev_attr_LightLoop))) goto error; 930 + if((retval = device_create_file(&intf->dev, &dev_attr_LightPunch))) goto error; 931 + if((retval = device_create_file(&intf->dev, &dev_attr_wheel))) goto error; 932 + if((retval = device_create_file(&intf->dev, &dev_attr_event))) goto error; 933 + if((retval = device_create_file(&intf->dev, &dev_attr_dump_state))) goto error; 934 + if((retval = device_create_file(&intf->dev, &dev_attr_compress_wheel))) goto error; 935 + if((retval = device_create_file(&intf->dev, &dev_attr_enable))) goto error; 936 + if((retval = device_create_file(&intf->dev, &dev_attr_offline))) goto error; 937 + 938 + /* let the user know what node this device is now attached to */ 939 + dev_info(&intf->dev, "Tranzport Device #%d now attached to major %d minor %d\n", 940 + (intf->minor - USB_TRANZPORT_MINOR_BASE), USB_MAJOR, intf->minor); 941 + 942 + exit: 943 + return retval; 944 + 945 + error: 946 + usb_tranzport_delete(dev); 947 + 948 + return retval; 949 + } 950 + 951 + /** 952 + * usb_tranzport_disconnect 953 + * 954 + * Called by the usb core when the device is removed from the system. 955 + */ 956 + static void usb_tranzport_disconnect(struct usb_interface *intf) 957 + { 958 + struct usb_tranzport *dev; 959 + int minor; 960 + mutex_lock(&disconnect_mutex); 961 + dev = usb_get_intfdata(intf); 962 + usb_set_intfdata(intf, NULL); 963 + down(&dev->sem); 964 + minor = intf->minor; 965 + /* give back our minor */ 966 + usb_deregister_dev(intf, &usb_tranzport_class); 967 + 968 + /* if the device is not opened, then we clean up right now */ 969 + if (!dev->open_count) { 970 + up(&dev->sem); 971 + usb_tranzport_delete(dev); 972 + } else { 973 + dev->intf = NULL; 974 + up(&dev->sem); 975 + } 976 + 977 + mutex_unlock(&disconnect_mutex); 978 + 979 + dev_info(&intf->dev, "Tranzport Surface #%d now disconnected\n", 980 + (minor - USB_TRANZPORT_MINOR_BASE)); 981 + } 982 + 983 + /* usb specific object needed to register this driver with the usb subsystem */ 984 + static struct usb_driver usb_tranzport_driver = { 985 + .name = "tranzport", 986 + .probe = usb_tranzport_probe, 987 + .disconnect = usb_tranzport_disconnect, 988 + .id_table = usb_tranzport_table, 989 + }; 990 + 991 + /** 992 + * usb_tranzport_init 993 + */ 994 + static int __init usb_tranzport_init(void) 995 + { 996 + int retval; 997 + 998 + /* register this driver with the USB subsystem */ 999 + retval = usb_register(&usb_tranzport_driver); 1000 + if (retval) 1001 + err("usb_register failed for the "__FILE__" driver. Error number %d\n", retval); 1002 + 1003 + return retval; 1004 + } 1005 + 1006 + /** 1007 + * usb_tranzport_exit 1008 + */ 1009 + static void __exit usb_tranzport_exit(void) 1010 + { 1011 + /* deregister this driver with the USB subsystem */ 1012 + usb_deregister(&usb_tranzport_driver); 1013 + } 1014 + 1015 + module_init(usb_tranzport_init); 1016 + module_exit(usb_tranzport_exit); 1017 +