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

Configure Feed

Select the types of activity you want to include in your feed.

[PATCH] USB: add Option Card driver

This patch adds a new driver for "Option" cards. This is a GSM data card,
controlled by three "serial ports" which are connected via an OHCI adapter,
all located on an oversized PC-Card. It's sold by several GSM service
providers.

Traditionally, this card has been accessed via the standard serial driver
and appropriate vendor= and product= options. However, testing has
revealed several problems with this approach, including hung data transfers
and lost data blocks when receiving.

Therefore, I've written a separate driver.

Signed-off-by: Matthias Urlichs <smurf@smurf.noris.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Matthias Urlichs and committed by
Greg KH
58cfe911 4871d3be

+741
+11
drivers/usb/serial/Kconfig
··· 455 455 To compile this driver as a module, choose M here: the 456 456 module will be called keyspan_pda. 457 457 458 + config USB_SERIAL_OPTION 459 + tristate "USB Option PCMCIA serial driver" 460 + depends on USB_SERIAL && USB_OHCI_HCD && PCCARD 461 + help 462 + Say Y here if you want to use an Option card. This is a 463 + GSM card, controlled by three serial ports which are connected 464 + via an OHCI adapter located on a PC card. 465 + 466 + To compile this driver as a module, choose M here: the 467 + module will be called option. 468 + 458 469 config USB_SERIAL_OMNINET 459 470 tristate "USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)" 460 471 depends on USB_SERIAL && EXPERIMENTAL
+1
drivers/usb/serial/Makefile
··· 32 32 obj-$(CONFIG_USB_SERIAL_KOBIL_SCT) += kobil_sct.o 33 33 obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o 34 34 obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o 35 + obj-$(CONFIG_USB_SERIAL_OPTION) += option.o 35 36 obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o 36 37 obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o 37 38 obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o
+729
drivers/usb/serial/option.c
··· 1 + /* 2 + Option Card (PCMCIA to) USB to Serial Driver 3 + 4 + Copyright (C) 2005 Matthias Urlichs <smurf@smurf.noris.de> 5 + 6 + This driver is free software; you can redistribute it and/or modify 7 + it under the terms of Version 2 of the GNU General Public License as 8 + published by the Free Software Foundation. 9 + 10 + Portions copied from the Keyspan driver by Hugh Blemings <hugh@blemings.org> 11 + 12 + History: 13 + 14 + 2005-05-19 v0.1 Initial version, based on incomplete docs 15 + and analysis of misbehavior of the standard driver 16 + 2005-05-20 v0.2 Extended the input buffer to avoid losing 17 + random 64-byte chunks of data 18 + 2005-05-21 v0.3 implemented chars_in_buffer() 19 + turned on low_latency 20 + simplified the code somewhat 21 + */ 22 + #define DRIVER_VERSION "v0.3" 23 + #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>" 24 + #define DRIVER_DESC "Option Card (PC-Card to) USB to Serial Driver" 25 + 26 + #include <linux/config.h> 27 + #include <linux/kernel.h> 28 + #include <linux/jiffies.h> 29 + #include <linux/errno.h> 30 + #include <linux/tty.h> 31 + #include <linux/tty_flip.h> 32 + #include <linux/module.h> 33 + #include <linux/usb.h> 34 + #include "usb-serial.h" 35 + 36 + /* Function prototypes */ 37 + static int option_open (struct usb_serial_port *port, struct file *filp); 38 + static void option_close (struct usb_serial_port *port, struct file *filp); 39 + static int option_startup (struct usb_serial *serial); 40 + static void option_shutdown (struct usb_serial *serial); 41 + static void option_rx_throttle (struct usb_serial_port *port); 42 + static void option_rx_unthrottle (struct usb_serial_port *port); 43 + static int option_write_room (struct usb_serial_port *port); 44 + 45 + static void option_instat_callback(struct urb *urb, struct pt_regs *regs); 46 + 47 + 48 + static int option_write (struct usb_serial_port *port, 49 + const unsigned char *buf, int count); 50 + 51 + static int option_chars_in_buffer (struct usb_serial_port *port); 52 + static int option_ioctl (struct usb_serial_port *port, struct file *file, 53 + unsigned int cmd, unsigned long arg); 54 + static void option_set_termios (struct usb_serial_port *port, 55 + struct termios *old); 56 + static void option_break_ctl (struct usb_serial_port *port, int break_state); 57 + static int option_tiocmget (struct usb_serial_port *port, struct file *file); 58 + static int option_tiocmset (struct usb_serial_port *port, struct file *file, 59 + unsigned int set, unsigned int clear); 60 + static int option_send_setup (struct usb_serial_port *port); 61 + 62 + /* Vendor and product IDs */ 63 + #define OPTION_VENDOR_ID 0x0AF0 64 + 65 + #define OPTION_PRODUCT_OLD 0x5000 66 + #define OPTION_PRODUCT_WLAN 0x6000 67 + 68 + static struct usb_device_id option_ids[] = { 69 + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, 70 + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_WLAN) }, 71 + { } /* Terminating entry */ 72 + }; 73 + 74 + MODULE_DEVICE_TABLE(usb, option_ids); 75 + 76 + static struct usb_driver option_driver = { 77 + .owner = THIS_MODULE, 78 + .name = "option", 79 + .probe = usb_serial_probe, 80 + .disconnect = usb_serial_disconnect, 81 + .id_table = option_ids, 82 + }; 83 + 84 + /* The card has three separate interfaces, wich the serial driver 85 + * recognizes separately, thus num_port=1. 86 + */ 87 + static struct usb_serial_device_type option_3port_device = { 88 + .owner = THIS_MODULE, 89 + .name = "Option 3-port card", 90 + .short_name = "option", 91 + .id_table = option_ids, 92 + .num_interrupt_in = NUM_DONT_CARE, 93 + .num_bulk_in = NUM_DONT_CARE, 94 + .num_bulk_out = NUM_DONT_CARE, 95 + .num_ports = 1, /* 3 */ 96 + .open = option_open, 97 + .close = option_close, 98 + .write = option_write, 99 + .write_room = option_write_room, 100 + .chars_in_buffer = option_chars_in_buffer, 101 + .throttle = option_rx_throttle, 102 + .unthrottle = option_rx_unthrottle, 103 + .ioctl = option_ioctl, 104 + .set_termios = option_set_termios, 105 + .break_ctl = option_break_ctl, 106 + .tiocmget = option_tiocmget, 107 + .tiocmset = option_tiocmset, 108 + .attach = option_startup, 109 + .shutdown = option_shutdown, 110 + .read_int_callback = option_instat_callback, 111 + }; 112 + 113 + static int debug; 114 + 115 + /* per port private data */ 116 + 117 + #define N_IN_URB 4 118 + #define N_OUT_URB 1 119 + #define IN_BUFLEN 1024 120 + #define OUT_BUFLEN 1024 121 + 122 + struct option_port_private { 123 + /* Input endpoints and buffer for this port */ 124 + struct urb *in_urbs[N_IN_URB]; 125 + char in_buffer[N_IN_URB][IN_BUFLEN]; 126 + /* Output endpoints and buffer for this port */ 127 + struct urb *out_urbs[N_OUT_URB]; 128 + char out_buffer[N_OUT_URB][OUT_BUFLEN]; 129 + 130 + /* Settings for the port */ 131 + int rts_state; /* Handshaking pins (outputs) */ 132 + int dtr_state; 133 + int cts_state; /* Handshaking pins (inputs) */ 134 + int dsr_state; 135 + int dcd_state; 136 + int ri_state; 137 + // int break_on; 138 + 139 + unsigned long tx_start_time[N_OUT_URB]; 140 + }; 141 + 142 + 143 + /* Functions used by new usb-serial code. */ 144 + static int __init 145 + option_init (void) 146 + { 147 + int retval; 148 + retval = usb_serial_register(&option_3port_device); 149 + if (retval) 150 + goto failed_3port_device_register; 151 + retval = usb_register(&option_driver); 152 + if (retval) 153 + goto failed_driver_register; 154 + 155 + info(DRIVER_DESC ": " DRIVER_VERSION); 156 + 157 + return 0; 158 + 159 + failed_driver_register: 160 + usb_serial_deregister (&option_3port_device); 161 + failed_3port_device_register: 162 + return retval; 163 + } 164 + 165 + static void __exit 166 + option_exit (void) 167 + { 168 + usb_deregister (&option_driver); 169 + usb_serial_deregister (&option_3port_device); 170 + } 171 + 172 + module_init(option_init); 173 + module_exit(option_exit); 174 + 175 + static void 176 + option_rx_throttle (struct usb_serial_port *port) 177 + { 178 + dbg("%s", __FUNCTION__); 179 + } 180 + 181 + 182 + static void 183 + option_rx_unthrottle (struct usb_serial_port *port) 184 + { 185 + dbg("%s", __FUNCTION__); 186 + } 187 + 188 + 189 + static void 190 + option_break_ctl (struct usb_serial_port *port, int break_state) 191 + { 192 + /* Unfortunately, I don't know how to send a break */ 193 + dbg("%s", __FUNCTION__); 194 + } 195 + 196 + 197 + static void 198 + option_set_termios (struct usb_serial_port *port, 199 + struct termios *old_termios) 200 + { 201 + dbg("%s", __FUNCTION__); 202 + 203 + option_send_setup(port); 204 + } 205 + 206 + static int 207 + option_tiocmget(struct usb_serial_port *port, struct file *file) 208 + { 209 + unsigned int value; 210 + struct option_port_private *portdata; 211 + 212 + portdata = usb_get_serial_port_data(port); 213 + 214 + value = ((portdata->rts_state) ? TIOCM_RTS : 0) | 215 + ((portdata->dtr_state) ? TIOCM_DTR : 0) | 216 + ((portdata->cts_state) ? TIOCM_CTS : 0) | 217 + ((portdata->dsr_state) ? TIOCM_DSR : 0) | 218 + ((portdata->dcd_state) ? TIOCM_CAR : 0) | 219 + ((portdata->ri_state) ? TIOCM_RNG : 0); 220 + 221 + return value; 222 + } 223 + 224 + static int 225 + option_tiocmset (struct usb_serial_port *port, struct file *file, 226 + unsigned int set, unsigned int clear) 227 + { 228 + struct option_port_private *portdata; 229 + 230 + portdata = usb_get_serial_port_data(port); 231 + 232 + if (set & TIOCM_RTS) 233 + portdata->rts_state = 1; 234 + if (set & TIOCM_DTR) 235 + portdata->dtr_state = 1; 236 + 237 + if (clear & TIOCM_RTS) 238 + portdata->rts_state = 0; 239 + if (clear & TIOCM_DTR) 240 + portdata->dtr_state = 0; 241 + return option_send_setup(port); 242 + } 243 + 244 + static int 245 + option_ioctl (struct usb_serial_port *port, struct file *file, 246 + unsigned int cmd, unsigned long arg) 247 + { 248 + return -ENOIOCTLCMD; 249 + } 250 + 251 + /* Write */ 252 + static int 253 + option_write(struct usb_serial_port *port, 254 + const unsigned char *buf, int count) 255 + { 256 + struct option_port_private *portdata; 257 + int i; 258 + int left, todo; 259 + struct urb *this_urb = NULL; /* spurious */ 260 + int err; 261 + 262 + portdata = usb_get_serial_port_data(port); 263 + 264 + dbg("%s: write (%d chars)", __FUNCTION__, count); 265 + 266 + #if 0 267 + spin_lock(&port->lock); 268 + if (port->write_urb_busy) { 269 + spin_unlock(&port->lock); 270 + dbg("%s: already writing", __FUNCTION__); 271 + return 0; 272 + } 273 + port->write_urb_busy = 1; 274 + spin_unlock(&port->lock); 275 + #endif 276 + 277 + i = 0; 278 + left = count; 279 + while (left>0) { 280 + todo = left; 281 + if (todo > OUT_BUFLEN) 282 + todo = OUT_BUFLEN; 283 + 284 + for (;i < N_OUT_URB; i++) { 285 + /* Check we have a valid urb/endpoint before we use it... */ 286 + this_urb = portdata->out_urbs[i]; 287 + if (this_urb->status != -EINPROGRESS) 288 + break; 289 + if (this_urb->transfer_flags & URB_ASYNC_UNLINK) 290 + continue; 291 + if (time_before(jiffies, portdata->tx_start_time[i] + 10 * HZ)) 292 + continue; 293 + this_urb->transfer_flags |= URB_ASYNC_UNLINK; 294 + usb_unlink_urb(this_urb); 295 + } 296 + 297 + if (i == N_OUT_URB) { 298 + /* no bulk out free! */ 299 + dbg("%s: no output urb -- left %d", __FUNCTION__,count-left); 300 + #if 0 301 + port->write_urb_busy = 0; 302 + #endif 303 + return count-left; 304 + } 305 + 306 + dbg("%s: endpoint %d buf %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe), i); 307 + 308 + memcpy (this_urb->transfer_buffer, buf, todo); 309 + 310 + /* send the data out the bulk port */ 311 + this_urb->transfer_buffer_length = todo; 312 + 313 + this_urb->transfer_flags &= ~URB_ASYNC_UNLINK; 314 + this_urb->dev = port->serial->dev; 315 + err = usb_submit_urb(this_urb, GFP_ATOMIC); 316 + if (err) { 317 + dbg("usb_submit_urb %p (write bulk) failed (%d,, has %d)", this_urb, err, this_urb->status); 318 + continue; 319 + } 320 + portdata->tx_start_time[i] = jiffies; 321 + buf += todo; 322 + left -= todo; 323 + } 324 + 325 + count -= left; 326 + #if 0 327 + port->write_urb_busy = 0; 328 + #endif 329 + dbg("%s: wrote (did %d)", __FUNCTION__, count); 330 + return count; 331 + } 332 + 333 + static void 334 + option_indat_callback (struct urb *urb, struct pt_regs *regs) 335 + { 336 + int i, err; 337 + int endpoint; 338 + struct usb_serial_port *port; 339 + struct tty_struct *tty; 340 + unsigned char *data = urb->transfer_buffer; 341 + 342 + dbg("%s: %p", __FUNCTION__, urb); 343 + 344 + endpoint = usb_pipeendpoint(urb->pipe); 345 + port = (struct usb_serial_port *) urb->context; 346 + 347 + if (urb->status) { 348 + dbg("%s: nonzero status: %d on endpoint %02x.", 349 + __FUNCTION__, urb->status, endpoint); 350 + } else { 351 + tty = port->tty; 352 + if (urb->actual_length) { 353 + for (i = 0; i < urb->actual_length ; ++i) { 354 + if (tty->flip.count >= TTY_FLIPBUF_SIZE) 355 + tty_flip_buffer_push(tty); 356 + tty_insert_flip_char(tty, data[i], 0); 357 + } 358 + tty_flip_buffer_push(tty); 359 + } else { 360 + dbg("%s: empty read urb received", __FUNCTION__); 361 + } 362 + 363 + /* Resubmit urb so we continue receiving */ 364 + if (port->open_count && urb->status != -ESHUTDOWN) { 365 + err = usb_submit_urb(urb, GFP_ATOMIC); 366 + if (err) 367 + printk(KERN_ERR "%s: resubmit read urb failed. (%d)", __FUNCTION__, err); 368 + } 369 + } 370 + return; 371 + } 372 + 373 + static void 374 + option_outdat_callback (struct urb *urb, struct pt_regs *regs) 375 + { 376 + struct usb_serial_port *port; 377 + 378 + dbg("%s", __FUNCTION__); 379 + 380 + port = (struct usb_serial_port *) urb->context; 381 + 382 + if (port->open_count) 383 + schedule_work(&port->work); 384 + } 385 + 386 + static void 387 + option_instat_callback (struct urb *urb, struct pt_regs *regs) 388 + { 389 + int err; 390 + struct usb_serial_port *port = (struct usb_serial_port *) urb->context; 391 + struct option_port_private *portdata = usb_get_serial_port_data(port); 392 + struct usb_serial *serial = port->serial; 393 + 394 + dbg("%s", __FUNCTION__); 395 + dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata); 396 + 397 + if (urb->status == 0) { 398 + struct usb_ctrlrequest *req_pkt = 399 + (struct usb_ctrlrequest *)urb->transfer_buffer; 400 + 401 + if (!req_pkt) { 402 + dbg("%s: NULL req_pkt\n", __FUNCTION__); 403 + return; 404 + } 405 + if ((req_pkt->bRequestType == 0xA1) && (req_pkt->bRequest == 0x20)) { 406 + int old_dcd_state; 407 + unsigned char signals = *((unsigned char *) 408 + urb->transfer_buffer + sizeof(struct usb_ctrlrequest)); 409 + 410 + dbg("%s: signal x%x", __FUNCTION__, signals); 411 + 412 + old_dcd_state = portdata->dcd_state; 413 + portdata->cts_state = 1; 414 + portdata->dcd_state = ((signals & 0x01) ? 1 : 0); 415 + portdata->dsr_state = ((signals & 0x02) ? 1 : 0); 416 + portdata->ri_state = ((signals & 0x08) ? 1 : 0); 417 + 418 + if (port->tty && !C_CLOCAL(port->tty) 419 + && old_dcd_state && !portdata->dcd_state) { 420 + tty_hangup(port->tty); 421 + } 422 + } else 423 + dbg("%s: type %x req %x", __FUNCTION__, req_pkt->bRequestType,req_pkt->bRequest); 424 + } else 425 + dbg("%s: error %d", __FUNCTION__, urb->status); 426 + 427 + /* Resubmit urb so we continue receiving IRQ data */ 428 + if (urb->status != -ESHUTDOWN) { 429 + urb->dev = serial->dev; 430 + err = usb_submit_urb(urb, GFP_ATOMIC); 431 + if (err) 432 + dbg("%s: resubmit intr urb failed. (%d)", __FUNCTION__, err); 433 + } 434 + } 435 + 436 + 437 + static int 438 + option_write_room (struct usb_serial_port *port) 439 + { 440 + struct option_port_private *portdata; 441 + int i; 442 + int data_len = 0; 443 + struct urb *this_urb; 444 + 445 + portdata = usb_get_serial_port_data(port); 446 + 447 + for (i=0; i < N_OUT_URB; i++) 448 + this_urb = portdata->out_urbs[i]; 449 + if (this_urb && this_urb->status != -EINPROGRESS) 450 + data_len += OUT_BUFLEN; 451 + 452 + dbg("%s: %d", __FUNCTION__, data_len); 453 + return data_len; 454 + } 455 + 456 + 457 + static int 458 + option_chars_in_buffer (struct usb_serial_port *port) 459 + { 460 + struct option_port_private *portdata; 461 + int i; 462 + int data_len = 0; 463 + struct urb *this_urb; 464 + 465 + portdata = usb_get_serial_port_data(port); 466 + 467 + for (i=0; i < N_OUT_URB; i++) 468 + this_urb = portdata->out_urbs[i]; 469 + if (this_urb && this_urb->status == -EINPROGRESS) 470 + data_len += this_urb->transfer_buffer_length; 471 + 472 + dbg("%s: %d", __FUNCTION__, data_len); 473 + return data_len; 474 + } 475 + 476 + 477 + static int 478 + option_open (struct usb_serial_port *port, struct file *filp) 479 + { 480 + struct option_port_private *portdata; 481 + struct usb_serial *serial = port->serial; 482 + int i, err; 483 + struct urb *urb; 484 + 485 + portdata = usb_get_serial_port_data(port); 486 + 487 + dbg("%s", __FUNCTION__); 488 + 489 + /* Set some sane defaults */ 490 + portdata->rts_state = 1; 491 + portdata->dtr_state = 1; 492 + 493 + /* Reset low level data toggle and start reading from endpoints */ 494 + for (i = 0; i < N_IN_URB; i++) { 495 + urb = portdata->in_urbs[i]; 496 + if (! urb) 497 + continue; 498 + if (urb->dev != serial->dev) { 499 + dbg("%s: dev %p != %p", __FUNCTION__, urb->dev, serial->dev); 500 + continue; 501 + } 502 + 503 + /* make sure endpoint data toggle is synchronized with the device */ 504 + 505 + usb_clear_halt(urb->dev, urb->pipe); 506 + 507 + err = usb_submit_urb(urb, GFP_KERNEL); 508 + if (err) { 509 + dbg("%s: submit urb %d failed (%d) %d", __FUNCTION__, i, err, 510 + urb->transfer_buffer_length); 511 + } 512 + } 513 + 514 + /* Reset low level data toggle on out endpoints */ 515 + for (i = 0; i < N_OUT_URB; i++) { 516 + urb = portdata->out_urbs[i]; 517 + if (! urb) 518 + continue; 519 + urb->dev = serial->dev; 520 + /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */ 521 + } 522 + 523 + port->tty->low_latency = 1; 524 + 525 + option_send_setup(port); 526 + 527 + return (0); 528 + } 529 + 530 + static inline void 531 + stop_urb(struct urb *urb) 532 + { 533 + if (urb && urb->status == -EINPROGRESS) { 534 + urb->transfer_flags &= ~URB_ASYNC_UNLINK; 535 + usb_kill_urb(urb); 536 + } 537 + } 538 + 539 + static void 540 + option_close(struct usb_serial_port *port, struct file *filp) 541 + { 542 + int i; 543 + struct usb_serial *serial = port->serial; 544 + struct option_port_private *portdata; 545 + 546 + dbg("%s", __FUNCTION__); 547 + portdata = usb_get_serial_port_data(port); 548 + 549 + portdata->rts_state = 0; 550 + portdata->dtr_state = 0; 551 + 552 + if (serial->dev) { 553 + option_send_setup(port); 554 + 555 + /* Stop reading/writing urbs */ 556 + for (i = 0; i < N_IN_URB; i++) 557 + stop_urb(portdata->in_urbs[i]); 558 + for (i = 0; i < N_OUT_URB; i++) 559 + stop_urb(portdata->out_urbs[i]); 560 + } 561 + port->tty = NULL; 562 + } 563 + 564 + 565 + /* Helper functions used by option_setup_urbs */ 566 + static struct urb * 567 + option_setup_urb (struct usb_serial *serial, int endpoint, 568 + int dir, void *ctx, char *buf, int len, 569 + void (*callback)(struct urb *, struct pt_regs *regs)) 570 + { 571 + struct urb *urb; 572 + 573 + if (endpoint == -1) 574 + return NULL; /* endpoint not needed */ 575 + 576 + urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */ 577 + if (urb == NULL) { 578 + dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint); 579 + return NULL; 580 + } 581 + 582 + /* Fill URB using supplied data. */ 583 + usb_fill_bulk_urb(urb, serial->dev, 584 + usb_sndbulkpipe(serial->dev, endpoint) | dir, 585 + buf, len, callback, ctx); 586 + 587 + return urb; 588 + } 589 + 590 + /* Setup urbs */ 591 + static void 592 + option_setup_urbs(struct usb_serial *serial) 593 + { 594 + int j; 595 + struct usb_serial_port *port; 596 + struct option_port_private *portdata; 597 + 598 + dbg("%s", __FUNCTION__); 599 + 600 + port = serial->port[0]; 601 + portdata = usb_get_serial_port_data(port); 602 + 603 + /* Do indat endpoints first */ 604 + for (j = 0; j <= N_IN_URB; ++j) { 605 + portdata->in_urbs[j] = option_setup_urb (serial, 606 + port->bulk_in_endpointAddress, USB_DIR_IN, port, 607 + portdata->in_buffer[j], IN_BUFLEN, option_indat_callback); 608 + } 609 + 610 + /* outdat endpoints */ 611 + for (j = 0; j <= N_OUT_URB; ++j) { 612 + portdata->out_urbs[j] = option_setup_urb (serial, 613 + port->bulk_out_endpointAddress, USB_DIR_OUT, port, 614 + portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback); 615 + } 616 + } 617 + 618 + 619 + static int 620 + option_send_setup(struct usb_serial_port *port) 621 + { 622 + struct usb_serial *serial = port->serial; 623 + struct option_port_private *portdata; 624 + 625 + dbg("%s", __FUNCTION__); 626 + 627 + portdata = usb_get_serial_port_data(port); 628 + 629 + if (port->tty) { 630 + int val = 0; 631 + if (portdata->dtr_state) 632 + val |= 0x01; 633 + if (portdata->rts_state) 634 + val |= 0x02; 635 + 636 + return usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 637 + 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT); 638 + } 639 + 640 + return 0; 641 + } 642 + 643 + 644 + static int 645 + option_startup (struct usb_serial *serial) 646 + { 647 + int i, err; 648 + struct usb_serial_port *port; 649 + struct option_port_private *portdata; 650 + 651 + dbg("%s", __FUNCTION__); 652 + 653 + /* Now setup per port private data */ 654 + for (i = 0; i < serial->num_ports; i++) { 655 + port = serial->port[i]; 656 + portdata = kmalloc(sizeof(struct option_port_private), GFP_KERNEL); 657 + if (!portdata) { 658 + dbg("%s: kmalloc for option_port_private (%d) failed!.", __FUNCTION__, i); 659 + return (1); 660 + } 661 + memset(portdata, 0, sizeof(struct option_port_private)); 662 + 663 + usb_set_serial_port_data(port, portdata); 664 + 665 + if (! port->interrupt_in_urb) 666 + continue; 667 + err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); 668 + if (err) 669 + dbg("%s: submit irq_in urb failed %d", __FUNCTION__, err); 670 + } 671 + 672 + option_setup_urbs(serial); 673 + 674 + return (0); 675 + } 676 + 677 + static void 678 + option_shutdown (struct usb_serial *serial) 679 + { 680 + int i, j; 681 + struct usb_serial_port *port; 682 + struct option_port_private *portdata; 683 + 684 + dbg("%s", __FUNCTION__); 685 + 686 + /* Stop reading/writing urbs */ 687 + for (i = 0; i < serial->num_ports; ++i) { 688 + port = serial->port[i]; 689 + portdata = usb_get_serial_port_data(port); 690 + for (j = 0; j < N_IN_URB; j++) 691 + stop_urb(portdata->in_urbs[j]); 692 + for (j = 0; j < N_OUT_URB; j++) 693 + stop_urb(portdata->out_urbs[j]); 694 + } 695 + 696 + /* Now free them */ 697 + for (i = 0; i < serial->num_ports; ++i) { 698 + port = serial->port[i]; 699 + portdata = usb_get_serial_port_data(port); 700 + 701 + for (j = 0; j < N_IN_URB; j++) { 702 + if (portdata->in_urbs[j]) { 703 + usb_free_urb(portdata->in_urbs[j]); 704 + portdata->in_urbs[j] = NULL; 705 + } 706 + } 707 + for (j = 0; j < N_OUT_URB; j++) { 708 + if (portdata->out_urbs[j]) { 709 + usb_free_urb(portdata->out_urbs[j]); 710 + portdata->out_urbs[j] = NULL; 711 + } 712 + } 713 + } 714 + 715 + /* Now free per port private data */ 716 + for (i = 0; i < serial->num_ports; i++) { 717 + port = serial->port[i]; 718 + kfree(usb_get_serial_port_data(port)); 719 + } 720 + } 721 + 722 + MODULE_AUTHOR(DRIVER_AUTHOR); 723 + MODULE_DESCRIPTION(DRIVER_DESC); 724 + MODULE_VERSION(DRIVER_VERSION); 725 + MODULE_LICENSE("GPL"); 726 + 727 + module_param(debug, bool, S_IRUGO | S_IWUSR); 728 + MODULE_PARM_DESC(debug, "Debug messages"); 729 +