| Start/ | End/ | |||
| True | False | - | Line | Source |
| 1 | /* | |||
| 2 | * Digi AccelePort USB-4 and USB-2 Serial Converters | |||
| 3 | * | |||
| 4 | * Copyright 2000 by Digi International | |||
| 5 | * | |||
| 6 | * This program is free software; you can redistribute it and/or modify | |||
| 7 | * it under the terms of the GNU General Public License as published by | |||
| 8 | * the Free Software Foundation; either version 2 of the License, or | |||
| 9 | * (at your option) any later version. | |||
| 10 | * | |||
| 11 | * Shamelessly based on Brian Warner's keyspan_pda.c and Greg Kroah-Hartman's | |||
| 12 | * usb-serial driver. | |||
| 13 | * | |||
| 14 | * Peter Berger (pberger@brimson.com) | |||
| 15 | * Al Borchers (borchers@steinerpoint.com) | |||
| 16 | * | |||
| 17 | * (12/03/2001) gkh | |||
| 18 | * switched to using port->open_count instead of private version. | |||
| 19 | * Removed port->active | |||
| 20 | * | |||
| 21 | * (04/08/2001) gb | |||
| 22 | * Identify version on module load. | |||
| 23 | * | |||
| 24 | * (11/01/2000) Adam J. Richter | |||
| 25 | * usb_device_id table support | |||
| 26 | * | |||
| 27 | * (11/01/2000) pberger and borchers | |||
| 28 | * -- Turned off the USB_DISABLE_SPD flag for write bulk urbs--it caused | |||
| 29 | * USB 4 ports to hang on startup. | |||
| 30 | * -- Serialized access to write urbs by adding the dp_write_urb_in_use | |||
| 31 | * flag; otherwise, the driver caused SMP system hangs. Watching the | |||
| 32 | * urb status is not sufficient. | |||
| 33 | * | |||
| 34 | * (10/05/2000) gkh | |||
| 35 | * -- Fixed bug with urb->dev not being set properly, now that the usb | |||
| 36 | * core needs it. | |||
| 37 | * | |||
| 38 | * (8/8/2000) pberger and borchers | |||
| 39 | * -- Fixed close so that | |||
| 40 | * - it can timeout while waiting for transmit idle, if needed; | |||
| 41 | * - it ignores interrupts when flushing the port, turning | |||
| 42 | * of modem signalling, and so on; | |||
| 43 | * - it waits for the flush to really complete before returning. | |||
| 44 | * -- Read_bulk_callback and write_bulk_callback check for a closed | |||
| 45 | * port before using the tty struct or writing to the port. | |||
| 46 | * -- The two changes above fix the oops caused by interrupted closes. | |||
| 47 | * -- Added interruptible args to write_oob_command and set_modem_signals | |||
| 48 | * and added a timeout arg to transmit_idle; needed for fixes to | |||
| 49 | * close. | |||
| 50 | * -- Added code for rx_throttle and rx_unthrottle so that input flow | |||
| 51 | * control works. | |||
| 52 | * -- Added code to set overrun, parity, framing, and break errors | |||
| 53 | * (untested). | |||
| 54 | * -- Set USB_DISABLE_SPD flag for write bulk urbs, so no 0 length | |||
| 55 | * bulk writes are done. These hung the Digi USB device. The | |||
| 56 | * 0 length bulk writes were a new feature of usb-uhci added in | |||
| 57 | * the 2.4.0-test6 kernels. | |||
| 58 | * -- Fixed mod inc race in open; do mod inc before sleeping to wait | |||
| 59 | * for a close to finish. | |||
| 60 | * | |||
| 61 | * (7/31/2000) pberger | |||
| 62 | * -- Fixed bugs with hardware handshaking: | |||
| 63 | * - Added code to set/clear tty->hw_stopped in digi_read_oob_callback() | |||
| 64 | * and digi_set_termios() | |||
| 65 | * -- Added code in digi_set_termios() to | |||
| 66 | * - add conditional in code handling transition from B0 to only | |||
| 67 | * set RTS if RTS/CTS flow control is either not in use or if | |||
| 68 | * the port is not currently throttled. | |||
| 69 | * - handle turning off CRTSCTS. | |||
| 70 | * | |||
| 71 | * (7/30/2000) borchers | |||
| 72 | * -- Added support for more than one Digi USB device by moving | |||
| 73 | * globals to a private structure in the pointed to from the | |||
| 74 | * usb_serial structure. | |||
| 75 | * -- Moved the modem change and transmit idle wait queues into | |||
| 76 | * the port private structure, so each port has its own queue | |||
| 77 | * rather than sharing global queues. | |||
| 78 | * -- Added support for break signals. | |||
| 79 | * | |||
| 80 | * (7/25/2000) pberger | |||
| 81 | * -- Added USB-2 support. Note: the USB-2 supports 3 devices: two | |||
| 82 | * serial and a parallel port. The parallel port is implemented | |||
| 83 | * as a serial-to-parallel converter. That is, the driver actually | |||
| 84 | * presents all three USB-2 interfaces as serial ports, but the third | |||
| 85 | * one physically connects to a parallel device. Thus, for example, | |||
| 86 | * one could plug a parallel printer into the USB-2's third port, | |||
| 87 | * but from the kernel's (and userland's) point of view what's | |||
| 88 | * actually out there is a serial device. | |||
| 89 | * | |||
| 90 | * (7/15/2000) borchers | |||
| 91 | * -- Fixed race in open when a close is in progress. | |||
| 92 | * -- Keep count of opens and dec the module use count for each | |||
| 93 | * outstanding open when shutdown is called (on disconnect). | |||
| 94 | * -- Fixed sanity checks in read_bulk_callback and write_bulk_callback | |||
| 95 | * so pointers are checked before use. | |||
| 96 | * -- Split read bulk callback into in band and out of band | |||
| 97 | * callbacks, and no longer restart read chains if there is | |||
| 98 | * a status error or a sanity error. This fixed the seg | |||
| 99 | * faults and other errors we used to get on disconnect. | |||
| 100 | * -- Port->active is once again a flag as usb-serial intended it | |||
| 101 | * to be, not a count. Since it was only a char it would | |||
| 102 | * have been limited to 256 simultaneous opens. Now the open | |||
| 103 | * count is kept in the port private structure in dp_open_count. | |||
| 104 | * -- Added code for modularization of the digi_acceleport driver. | |||
| 105 | * | |||
| 106 | * (6/27/2000) pberger and borchers | |||
| 107 | * -- Zeroed out sync field in the wakeup_task before first use; | |||
| 108 | * otherwise the uninitialized value might prevent the task from | |||
| 109 | * being scheduled. | |||
| 110 | * -- Initialized ret value to 0 in write_bulk_callback, otherwise | |||
| 111 | * the uninitialized value could cause a spurious debugging message. | |||
| 112 | * | |||
| 113 | * (6/22/2000) pberger and borchers | |||
| 114 | * -- Made cond_wait_... inline--apparently on SPARC the flags arg | |||
| 115 | * to spin_lock_irqsave cannot be passed to another function | |||
| 116 | * to call spin_unlock_irqrestore. Thanks to Pauline Middelink. | |||
| 117 | * -- In digi_set_modem_signals the inner nested spin locks use just | |||
| 118 | * spin_lock() rather than spin_lock_irqsave(). The old code | |||
| 119 | * mistakenly left interrupts off. Thanks to Pauline Middelink. | |||
| 120 | * -- copy_from_user (which can sleep) is no longer called while a | |||
| 121 | * spinlock is held. We copy to a local buffer before getting | |||
| 122 | * the spinlock--don't like the extra copy but the code is simpler. | |||
| 123 | * -- Printk and dbg are no longer called while a spin lock is held. | |||
| 124 | * | |||
| 125 | * (6/4/2000) pberger and borchers | |||
| 126 | * -- Replaced separate calls to spin_unlock_irqrestore and | |||
| 127 | * interruptible_sleep_on_timeout with a new function | |||
| 128 | * cond_wait_interruptible_timeout_irqrestore. This eliminates | |||
| 129 | * the race condition where the wake up could happen after | |||
| 130 | * the unlock and before the sleep. | |||
| 131 | * -- Close now waits for output to drain. | |||
| 132 | * -- Open waits until any close in progress is finished. | |||
| 133 | * -- All out of band responses are now processed, not just the | |||
| 134 | * first in a USB packet. | |||
| 135 | * -- Fixed a bug that prevented the driver from working when the | |||
| 136 | * first Digi port was not the first USB serial port--the driver | |||
| 137 | * was mistakenly using the external USB serial port number to | |||
| 138 | * try to index into its internal ports. | |||
| 139 | * -- Fixed an SMP bug -- write_bulk_callback is called directly from | |||
| 140 | * an interrupt, so spin_lock_irqsave/spin_unlock_irqrestore are | |||
| 141 | * needed for locks outside write_bulk_callback that are also | |||
| 142 | * acquired by write_bulk_callback to prevent deadlocks. | |||
| 143 | * -- Fixed support for select() by making digi_chars_in_buffer() | |||
| 144 | * return 256 when -EINPROGRESS is set, as the line discipline | |||
| 145 | * code in n_tty.c expects. | |||
| 146 | * -- Fixed an include file ordering problem that prevented debugging | |||
| 147 | * messages from working. | |||
| 148 | * -- Fixed an intermittent timeout problem that caused writes to | |||
| 149 | * sometimes get stuck on some machines on some kernels. It turns | |||
| 150 | * out in these circumstances write_chan() (in n_tty.c) was | |||
| 151 | * asleep waiting for our wakeup call. Even though we call | |||
| 152 | * wake_up_interruptible() in digi_write_bulk_callback(), there is | |||
| 153 | * a race condition that could cause the wakeup to fail: if our | |||
| 154 | * wake_up_interruptible() call occurs between the time that our | |||
| 155 | * driver write routine finishes and write_chan() sets current->state | |||
| 156 | * to TASK_INTERRUPTIBLE, the effect of our wakeup setting the state | |||
| 157 | * to TASK_RUNNING will be lost and write_chan's subsequent call to | |||
| 158 | * schedule() will never return (unless it catches a signal). | |||
| 159 | * This race condition occurs because write_bulk_callback() (and thus | |||
| 160 | * the wakeup) are called asynchonously from an interrupt, rather than | |||
| 161 | * from the scheduler. We can avoid the race by calling the wakeup | |||
| 162 | * from the scheduler queue and that's our fix: Now, at the end of | |||
| 163 | * write_bulk_callback() we queue up a wakeup call on the scheduler | |||
| 164 | * task queue. We still also invoke the wakeup directly since that | |||
| 165 | * squeezes a bit more performance out of the driver, and any lost | |||
| 166 | * race conditions will get cleaned up at the next scheduler run. | |||
| 167 | * | |||
| 168 | * NOTE: The problem also goes away if you comment out | |||
| 169 | * the two code lines in write_chan() where current->state | |||
| 170 | * is set to TASK_RUNNING just before calling driver.write() and to | |||
| 171 | * TASK_INTERRUPTIBLE immediately afterwards. This is why the | |||
| 172 | * problem did not show up with the 2.2 kernels -- they do not | |||
| 173 | * include that code. | |||
| 174 | * | |||
| 175 | * (5/16/2000) pberger and borchers | |||
| 176 | * -- Added timeouts to sleeps, to defend against lost wake ups. | |||
| 177 | * -- Handle transition to/from B0 baud rate in digi_set_termios. | |||
| 178 | * | |||
| 179 | * (5/13/2000) pberger and borchers | |||
| 180 | * -- All commands now sent on out of band port, using | |||
| 181 | * digi_write_oob_command. | |||
| 182 | * -- Get modem control signals whenever they change, support TIOCMGET/ | |||
| 183 | * SET/BIS/BIC ioctls. | |||
| 184 | * -- digi_set_termios now supports parity, word size, stop bits, and | |||
| 185 | * receive enable. | |||
| 186 | * -- Cleaned up open and close, use digi_set_termios and | |||
| 187 | * digi_write_oob_command to set port parameters. | |||
| 188 | * -- Added digi_startup_device to start read chains on all ports. | |||
| 189 | * -- Write buffer is only used when count==1, to be sure put_char can | |||
| 190 | * write a char (unless the buffer is full). | |||
| 191 | * | |||
| 192 | * (5/10/2000) pberger and borchers | |||
| 193 | * -- Added MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT calls on open/close. | |||
| 194 | * -- Fixed problem where the first incoming character is lost on | |||
| 195 | * port opens after the first close on that port. Now we keep | |||
| 196 | * the read_urb chain open until shutdown. | |||
| 197 | * -- Added more port conditioning calls in digi_open and digi_close. | |||
| 198 | * -- Convert port->active to a use count so that we can deal with multiple | |||
| 199 | * opens and closes properly. | |||
| 200 | * -- Fixed some problems with the locking code. | |||
| 201 | * | |||
| 202 | * (5/3/2000) pberger and borchers | |||
| 203 | * -- First alpha version of the driver--many known limitations and bugs. | |||
| 204 | * | |||
| 205 | * | |||
| 206 | * Locking and SMP | |||
| 207 | * | |||
| 208 | * - Each port, including the out-of-band port, has a lock used to | |||
| 209 | * serialize all access to the port's private structure. | |||
| 210 | * - The port lock is also used to serialize all writes and access to | |||
| 211 | * the port's URB. | |||
| 212 | * - The port lock is also used for the port write_wait condition | |||
| 213 | * variable. Holding the port lock will prevent a wake up on the | |||
| 214 | * port's write_wait; this can be used with cond_wait_... to be sure | |||
| 215 | * the wake up is not lost in a race when dropping the lock and | |||
| 216 | * sleeping waiting for the wakeup. | |||
| 217 | * - digi_write() does not sleep, since it is sometimes called on | |||
| 218 | * interrupt time. | |||
| 219 | * - digi_write_bulk_callback() and digi_read_bulk_callback() are | |||
| 220 | * called directly from interrupts. Hence spin_lock_irqsave() | |||
| 221 | * and spin_unlock_irqrestore() are used in the rest of the code | |||
| 222 | * for any locks they acquire. | |||
| 223 | * - digi_write_bulk_callback() gets the port lock before waking up | |||
| 224 | * processes sleeping on the port write_wait. It also schedules | |||
| 225 | * wake ups so they happen from the scheduler, because the tty | |||
| 226 | * system can miss wake ups from interrupts. | |||
| 227 | * - All sleeps use a timeout of DIGI_RETRY_TIMEOUT before looping to | |||
| 228 | * recheck the condition they are sleeping on. This is defensive, | |||
| 229 | * in case a wake up is lost. | |||
| 230 | * - Following Documentation/DocBook/kernel-locking.pdf no spin locks | |||
| 231 | * are held when calling copy_to/from_user or printk. | |||
| 232 | * | |||
| 233 | * $Id: digi_acceleport.c,v 1.80.1.2 2000/11/02 05:45:08 root Exp $ | |||
| 234 | */ | |||
| 235 | ||||
| 236 | #include <linux/config.h> | |||
| 237 | #include <linux/kernel.h> | |||
| 238 | #include <linux/errno.h> | |||
| 239 | #include <linux/init.h> | |||
| 240 | #include <linux/slab.h> | |||
| 241 | #include <linux/tty.h> | |||
| 242 | #include <linux/tty_driver.h> | |||
| 243 | #include <linux/tty_flip.h> | |||
| 244 | #include <linux/module.h> | |||
| 245 | #include <linux/spinlock.h> | |||
| 246 | #include <linux/workqueue.h> | |||
| 247 | #include <asm/uaccess.h> | |||
| 248 | #include <linux/usb.h> | |||
| 249 | #include <linux/wait.h> | |||
| 250 | #include "usb-serial.h" | |||
| 251 | ||||
| 252 | /* Defines */ | |||
| 253 | ||||
| 254 | /* | |||
| 255 | * Version Information | |||
| 256 | */ | |||
| 257 | #define DRIVER_VERSION "v1.80.1.2" | |||
| 258 | #define DRIVER_AUTHOR "Peter Berger <pberger@brimson.com>, Al Borchers <borchers@steinerpoint.com>" | |||
| 259 | #define DRIVER_DESC "Digi AccelePort USB-2/USB-4 Serial Converter driver" | |||
| 260 | ||||
| 261 | /* port output buffer length -- must be <= transfer buffer length - 2 */ | |||
| 262 | /* so we can be sure to send the full buffer in one urb */ | |||
| 263 | #define DIGI_OUT_BUF_SIZE 8 | |||
| 264 | ||||
| 265 | /* port input buffer length -- must be >= transfer buffer length - 3 */ | |||
| 266 | /* so we can be sure to hold at least one full buffer from one urb */ | |||
| 267 | #define DIGI_IN_BUF_SIZE 64 | |||
| 268 | ||||
| 269 | /* retry timeout while sleeping */ | |||
| 270 | #define DIGI_RETRY_TIMEOUT (HZ/10) | |||
| 271 | ||||
| 272 | /* timeout while waiting for tty output to drain in close */ | |||
| 273 | /* this delay is used twice in close, so the total delay could */ | |||
| 274 | /* be twice this value */ | |||
| 275 | #define DIGI_CLOSE_TIMEOUT (5*HZ) | |||
| 276 | ||||
| 277 | ||||
| 278 | /* AccelePort USB Defines */ | |||
| 279 | ||||
| 280 | /* ids */ | |||
| 281 | #define DIGI_VENDOR_ID 0x05c5 | |||
| 282 | #define DIGI_2_ID 0x0002 /* USB-2 */ | |||
| 283 | #define DIGI_4_ID 0x0004 /* USB-4 */ | |||
| 284 | ||||
| 285 | /* commands | |||
| 286 | * "INB": can be used on the in-band endpoint | |||
| 287 | * "OOB": can be used on the out-of-band endpoint | |||
| 288 | */ | |||
| 289 | #define DIGI_CMD_SET_BAUD_RATE 0 /* INB, OOB */ | |||
| 290 | #define DIGI_CMD_SET_WORD_SIZE 1 /* INB, OOB */ | |||
| 291 | #define DIGI_CMD_SET_PARITY 2 /* INB, OOB */ | |||
| 292 | #define DIGI_CMD_SET_STOP_BITS 3 /* INB, OOB */ | |||
| 293 | #define DIGI_CMD_SET_INPUT_FLOW_CONTROL 4 /* INB, OOB */ | |||
| 294 | #define DIGI_CMD_SET_OUTPUT_FLOW_CONTROL 5 /* INB, OOB */ | |||
| 295 | #define DIGI_CMD_SET_DTR_SIGNAL 6 /* INB, OOB */ | |||
| 296 | #define DIGI_CMD_SET_RTS_SIGNAL 7 /* INB, OOB */ | |||
| 297 | #define DIGI_CMD_READ_INPUT_SIGNALS 8 /* OOB */ | |||
| 298 | #define DIGI_CMD_IFLUSH_FIFO 9 /* OOB */ | |||
| 299 | #define DIGI_CMD_RECEIVE_ENABLE 10 /* INB, OOB */ | |||
| 300 | #define DIGI_CMD_BREAK_CONTROL 11 /* INB, OOB */ | |||
| 301 | #define DIGI_CMD_LOCAL_LOOPBACK 12 /* INB, OOB */ | |||
| 302 | #define DIGI_CMD_TRANSMIT_IDLE 13 /* INB, OOB */ | |||
| 303 | #define DIGI_CMD_READ_UART_REGISTER 14 /* OOB */ | |||
| 304 | #define DIGI_CMD_WRITE_UART_REGISTER 15 /* INB, OOB */ | |||
| 305 | #define DIGI_CMD_AND_UART_REGISTER 16 /* INB, OOB */ | |||
| 306 | #define DIGI_CMD_OR_UART_REGISTER 17 /* INB, OOB */ | |||
| 307 | #define DIGI_CMD_SEND_DATA 18 /* INB */ | |||
| 308 | #define DIGI_CMD_RECEIVE_DATA 19 /* INB */ | |||
| 309 | #define DIGI_CMD_RECEIVE_DISABLE 20 /* INB */ | |||
| 310 | #define DIGI_CMD_GET_PORT_TYPE 21 /* OOB */ | |||
| 311 | ||||
| 312 | /* baud rates */ | |||
| 313 | #define DIGI_BAUD_50 0 | |||
| 314 | #define DIGI_BAUD_75 1 | |||
| 315 | #define DIGI_BAUD_110 2 | |||
| 316 | #define DIGI_BAUD_150 3 | |||
| 317 | #define DIGI_BAUD_200 4 | |||
| 318 | #define DIGI_BAUD_300 5 | |||
| 319 | #define DIGI_BAUD_600 6 | |||
| 320 | #define DIGI_BAUD_1200 7 | |||
| 321 | #define DIGI_BAUD_1800 8 | |||
| 322 | #define DIGI_BAUD_2400 9 | |||
| 323 | #define DIGI_BAUD_4800 10 | |||
| 324 | #define DIGI_BAUD_7200 11 | |||
| 325 | #define DIGI_BAUD_9600 12 | |||
| 326 | #define DIGI_BAUD_14400 13 | |||
| 327 | #define DIGI_BAUD_19200 14 | |||
| 328 | #define DIGI_BAUD_28800 15 | |||
| 329 | #define DIGI_BAUD_38400 16 | |||
| 330 | #define DIGI_BAUD_57600 17 | |||
| 331 | #define DIGI_BAUD_76800 18 | |||
| 332 | #define DIGI_BAUD_115200 19 | |||
| 333 | #define DIGI_BAUD_153600 20 | |||
| 334 | #define DIGI_BAUD_230400 21 | |||
| 335 | #define DIGI_BAUD_460800 22 | |||
| 336 | ||||
| 337 | /* arguments */ | |||
| 338 | #define DIGI_WORD_SIZE_5 0 | |||
| 339 | #define DIGI_WORD_SIZE_6 1 | |||
| 340 | #define DIGI_WORD_SIZE_7 2 | |||
| 341 | #define DIGI_WORD_SIZE_8 3 | |||
| 342 | ||||
| 343 | #define DIGI_PARITY_NONE 0 | |||
| 344 | #define DIGI_PARITY_ODD 1 | |||
| 345 | #define DIGI_PARITY_EVEN 2 | |||
| 346 | #define DIGI_PARITY_MARK 3 | |||
| 347 | #define DIGI_PARITY_SPACE 4 | |||
| 348 | ||||
| 349 | #define DIGI_STOP_BITS_1 0 | |||
| 350 | #define DIGI_STOP_BITS_2 1 | |||
| 351 | ||||
| 352 | #define DIGI_INPUT_FLOW_CONTROL_XON_XOFF 1 | |||
| 353 | #define DIGI_INPUT_FLOW_CONTROL_RTS 2 | |||
| 354 | #define DIGI_INPUT_FLOW_CONTROL_DTR 4 | |||
| 355 | ||||
| 356 | #define DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF 1 | |||
| 357 | #define DIGI_OUTPUT_FLOW_CONTROL_CTS 2 | |||
| 358 | #define DIGI_OUTPUT_FLOW_CONTROL_DSR 4 | |||
| 359 | ||||
| 360 | #define DIGI_DTR_INACTIVE 0 | |||
| 361 | #define DIGI_DTR_ACTIVE 1 | |||
| 362 | #define DIGI_DTR_INPUT_FLOW_CONTROL 2 | |||
| 363 | ||||
| 364 | #define DIGI_RTS_INACTIVE 0 | |||
| 365 | #define DIGI_RTS_ACTIVE 1 | |||
| 366 | #define DIGI_RTS_INPUT_FLOW_CONTROL 2 | |||
| 367 | #define DIGI_RTS_TOGGLE 3 | |||
| 368 | ||||
| 369 | #define DIGI_FLUSH_TX 1 | |||
| 370 | #define DIGI_FLUSH_RX 2 | |||
| 371 | #define DIGI_RESUME_TX 4 /* clears xoff condition */ | |||
| 372 | ||||
| 373 | #define DIGI_TRANSMIT_NOT_IDLE 0 | |||
| 374 | #define DIGI_TRANSMIT_IDLE 1 | |||
| 375 | ||||
| 376 | #define DIGI_DISABLE 0 | |||
| 377 | #define DIGI_ENABLE 1 | |||
| 378 | ||||
| 379 | #define DIGI_DEASSERT 0 | |||
| 380 | #define DIGI_ASSERT 1 | |||
| 381 | ||||
| 382 | /* in band status codes */ | |||
| 383 | #define DIGI_OVERRUN_ERROR 4 | |||
| 384 | #define DIGI_PARITY_ERROR 8 | |||
| 385 | #define DIGI_FRAMING_ERROR 16 | |||
| 386 | #define DIGI_BREAK_ERROR 32 | |||
| 387 | ||||
| 388 | /* out of band status */ | |||
| 389 | #define DIGI_NO_ERROR 0 | |||
| 390 | #define DIGI_BAD_FIRST_PARAMETER 1 | |||
| 391 | #define DIGI_BAD_SECOND_PARAMETER 2 | |||
| 392 | #define DIGI_INVALID_LINE 3 | |||
| 393 | #define DIGI_INVALID_OPCODE 4 | |||
| 394 | ||||
| 395 | /* input signals */ | |||
| 396 | #define DIGI_READ_INPUT_SIGNALS_SLOT 1 | |||
| 397 | #define DIGI_READ_INPUT_SIGNALS_ERR 2 | |||
| 398 | #define DIGI_READ_INPUT_SIGNALS_BUSY 4 | |||
| 399 | #define DIGI_READ_INPUT_SIGNALS_PE 8 | |||
| 400 | #define DIGI_READ_INPUT_SIGNALS_CTS 16 | |||
| 401 | #define DIGI_READ_INPUT_SIGNALS_DSR 32 | |||
| 402 | #define DIGI_READ_INPUT_SIGNALS_RI 64 | |||
| 403 | #define DIGI_READ_INPUT_SIGNALS_DCD 128 | |||
| 404 | ||||
| 405 | ||||
| 406 | /* Structures */ | |||
| 407 | ||||
| 408 | struct digi_serial { | |||
| 409 | spinlock_t ds_serial_lock; | |||
| 410 | struct usb_serial_port *ds_oob_port; /* out-of-band port */ | |||
| 411 | int ds_oob_port_num; /* index of out-of-band port */ | |||
| 412 | int ds_device_started; | |||
| 413 | }; | |||
| 414 | ||||
| 415 | struct digi_port { | |||
| 416 | spinlock_t dp_port_lock; | |||
| 417 | int dp_port_num; | |||
| 418 | int dp_out_buf_len; | |||
| 419 | unsigned char dp_out_buf[DIGI_OUT_BUF_SIZE]; | |||
| 420 | int dp_in_buf_len; | |||
| 421 | unsigned char dp_in_buf[DIGI_IN_BUF_SIZE]; | |||
| 422 | unsigned char dp_in_flag_buf[DIGI_IN_BUF_SIZE]; | |||
| 423 | int dp_write_urb_in_use; | |||
| 424 | unsigned int dp_modem_signals; | |||
| 425 | wait_queue_head_t dp_modem_change_wait; | |||
| 426 | int dp_transmit_idle; | |||
| 427 | wait_queue_head_t dp_transmit_idle_wait; | |||
| 428 | int dp_throttled; | |||
| 429 | int dp_throttle_restart; | |||
| 430 | wait_queue_head_t dp_flush_wait; | |||
| 431 | int dp_in_close; /* close in progress */ | |||
| 432 | wait_queue_head_t dp_close_wait; /* wait queue for close */ | |||
| 433 | struct work_struct dp_wakeup_work; | |||
| 434 | }; | |||
| 435 | ||||
| 436 | ||||
| 437 | /* Local Function Declarations */ | |||
| 438 | ||||
| 439 | static void digi_wakeup_write( struct usb_serial_port *port ); | |||
| 440 | static void digi_wakeup_write_lock(void *); | |||
| 441 | static int digi_write_oob_command( struct usb_serial_port *port, | |||
| 442 | unsigned char *buf, int count, int interruptible ); | |||
| 443 | static int digi_write_inb_command( struct usb_serial_port *port, | |||
| 444 | unsigned char *buf, int count, unsigned long timeout ); | |||
| 445 | static int digi_set_modem_signals( struct usb_serial_port *port, | |||
| 446 | unsigned int modem_signals, int interruptible ); | |||
| 447 | static int digi_transmit_idle( struct usb_serial_port *port, | |||
| 448 | unsigned long timeout ); | |||
| 449 | static void digi_rx_throttle (struct usb_serial_port *port); | |||
| 450 | static void digi_rx_unthrottle (struct usb_serial_port *port); | |||
| 451 | static void digi_set_termios( struct usb_serial_port *port, | |||
| 452 | struct termios *old_termios ); | |||
| 453 | static void digi_break_ctl( struct usb_serial_port *port, int break_state ); | |||
| 454 | static int digi_ioctl( struct usb_serial_port *port, struct file *file, | |||
| 455 | unsigned int cmd, unsigned long arg ); | |||
| 456 | static int digi_tiocmget( struct usb_serial_port *port, struct file *file ); | |||
| 457 | static int digi_tiocmset( struct usb_serial_port *port, struct file *file, | |||
| 458 | unsigned int set, unsigned int clear ); | |||
| 459 | static int digi_write( struct usb_serial_port *port, const unsigned char *buf, int count ); | |||
| 460 | static void digi_write_bulk_callback( struct urb *urb, struct pt_regs *regs ); | |||
| 461 | static int digi_write_room( struct usb_serial_port *port ); | |||
| 462 | static int digi_chars_in_buffer( struct usb_serial_port *port ); | |||
| 463 | static int digi_open( struct usb_serial_port *port, struct file *filp ); | |||
| 464 | static void digi_close( struct usb_serial_port *port, struct file *filp ); | |||
| 465 | static int digi_startup_device( struct usb_serial *serial ); | |||
| 466 | static int digi_startup( struct usb_serial *serial ); | |||
| 467 | static void digi_shutdown( struct usb_serial *serial ); | |||
| 468 | static void digi_read_bulk_callback( struct urb *urb, struct pt_regs *regs ); | |||
| 469 | static int digi_read_inb_callback( struct urb *urb ); | |||
| 470 | static int digi_read_oob_callback( struct urb *urb ); | |||
| 471 | ||||
| 472 | ||||
| 473 | /* Statics */ | |||
| 474 | ||||
| 475 | static int debug; | |||
| 476 | ||||
| 477 | static struct usb_device_id id_table_combined [] = { | |||
| 478 | { USB_DEVICE(DIGI_VENDOR_ID, DIGI_2_ID) }, | |||
| 479 | { USB_DEVICE(DIGI_VENDOR_ID, DIGI_4_ID) }, | |||
| 480 | { } /* Terminating entry */ | |||
| 481 | }; | |||
| 482 | ||||
| 483 | static struct usb_device_id id_table_2 [] = { | |||
| 484 | { USB_DEVICE(DIGI_VENDOR_ID, DIGI_2_ID) }, | |||
| 485 | { } /* Terminating entry */ | |||
| 486 | }; | |||
| 487 | ||||
| 488 | static struct usb_device_id id_table_4 [] = { | |||
| 489 | { USB_DEVICE(DIGI_VENDOR_ID, DIGI_4_ID) }, | |||
| 490 | { } /* Terminating entry */ | |||
| 491 | }; | |||
| 492 | ||||
| 493 | MODULE_DEVICE_TABLE (usb, id_table_combined); | |||
| 494 | ||||
| 495 | static struct usb_driver digi_driver = { | |||
| 496 | .name = "digi_acceleport", | |||
| 497 | .probe = usb_serial_probe, | |||
| 498 | .disconnect = usb_serial_disconnect, | |||
| 499 | .id_table = id_table_combined, | |||
| 500 | .no_dynamic_id = 1, | |||
| 501 | }; | |||
| 502 | ||||
| 503 | ||||
| 504 | /* device info needed for the Digi serial converter */ | |||
| 505 | ||||
| 506 | static struct usb_serial_driver digi_acceleport_2_device = { | |||
| 507 | .driver = { | |||
| 508 | .owner = THIS_MODULE, | |||
| 509 | .name = "digi_2", | |||
| 510 | }, | |||
| 511 | .description = "Digi 2 port USB adapter", | |||
| 512 | .id_table = id_table_2, | |||
| 513 | .num_interrupt_in = 0, | |||
| 514 | .num_bulk_in = 4, | |||
| 515 | .num_bulk_out = 4, | |||
| 516 | .num_ports = 3, | |||
| 517 | .open = digi_open, | |||
| 518 | .close = digi_close, | |||
| 519 | .write = digi_write, | |||
| 520 | .write_room = digi_write_room, | |||
| 521 | .write_bulk_callback = digi_write_bulk_callback, | |||
| 522 | .read_bulk_callback = digi_read_bulk_callback, | |||
| 523 | .chars_in_buffer = digi_chars_in_buffer, | |||
| 524 | .throttle = digi_rx_throttle, | |||
| 525 | .unthrottle = digi_rx_unthrottle, | |||
| 526 | .ioctl = digi_ioctl, | |||
| 527 | .set_termios = digi_set_termios, | |||
| 528 | .break_ctl = digi_break_ctl, | |||
| 529 | .tiocmget = digi_tiocmget, | |||
| 530 | .tiocmset = digi_tiocmset, | |||
| 531 | .attach = digi_startup, | |||
| 532 | .shutdown = digi_shutdown, | |||
| 533 | }; | |||
| 534 | ||||
| 535 | static struct usb_serial_driver digi_acceleport_4_device = { | |||
| 536 | .driver = { | |||
| 537 | .owner = THIS_MODULE, | |||
| 538 | .name = "digi_4", | |||
| 539 | }, | |||
| 540 | .description = "Digi 4 port USB adapter", | |||
| 541 | .id_table = id_table_4, | |||
| 542 | .num_interrupt_in = 0, | |||
| 543 | .num_bulk_in = 5, | |||
| 544 | .num_bulk_out = 5, | |||
| 545 | .num_ports = 4, | |||
| 546 | .open = digi_open, | |||
| 547 | .close = digi_close, | |||
| 548 | .write = digi_write, | |||
| 549 | .write_room = &n | |||