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.

at v2.6.26 1659 lines 48 kB view raw
1/* 2 * USB Cypress M8 driver 3 * 4 * Copyright (C) 2004 5 * Lonnie Mendez (dignome@gmail.com) 6 * Copyright (C) 2003,2004 7 * Neil Whelchel (koyama@firstlight.net) 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * See Documentation/usb/usb-serial.txt for more information on using this driver 15 * 16 * See http://geocities.com/i0xox0i for information on this driver and the 17 * earthmate usb device. 18 * 19 * Lonnie Mendez <dignome@gmail.com> 20 * 4-29-2005 21 * Fixed problem where setting or retreiving the serial config would fail with 22 * EPIPE. Removed CRTS toggling so the driver behaves more like other usbserial 23 * adapters. Issued new interval of 1ms instead of the default 10ms. As a 24 * result, transfer speed has been substantially increased. From avg. 850bps to 25 * avg. 3300bps. initial termios has also been modified. Cleaned up code and 26 * formatting issues so it is more readable. Replaced the C++ style comments. 27 * 28 * Lonnie Mendez <dignome@gmail.com> 29 * 12-15-2004 30 * Incorporated write buffering from pl2303 driver. Fixed bug with line 31 * handling so both lines are raised in cypress_open. (was dropping rts) 32 * Various code cleanups made as well along with other misc bug fixes. 33 * 34 * Lonnie Mendez <dignome@gmail.com> 35 * 04-10-2004 36 * Driver modified to support dynamic line settings. Various improvments 37 * and features. 38 * 39 * Neil Whelchel 40 * 10-2003 41 * Driver first released. 42 * 43 */ 44 45/* Thanks to Neil Whelchel for writing the first cypress m8 implementation for linux. */ 46/* Thanks to cypress for providing references for the hid reports. */ 47/* Thanks to Jiang Zhang for providing links and for general help. */ 48/* Code originates and was built up from ftdi_sio, belkin, pl2303 and others. */ 49 50 51#include <linux/kernel.h> 52#include <linux/errno.h> 53#include <linux/init.h> 54#include <linux/slab.h> 55#include <linux/tty.h> 56#include <linux/tty_driver.h> 57#include <linux/tty_flip.h> 58#include <linux/module.h> 59#include <linux/moduleparam.h> 60#include <linux/spinlock.h> 61#include <linux/usb.h> 62#include <linux/usb/serial.h> 63#include <linux/serial.h> 64#include <linux/delay.h> 65#include <asm/uaccess.h> 66 67#include "cypress_m8.h" 68 69 70#ifdef CONFIG_USB_SERIAL_DEBUG 71 static int debug = 1; 72#else 73 static int debug; 74#endif 75static int stats; 76static int interval; 77 78/* 79 * Version Information 80 */ 81#define DRIVER_VERSION "v1.09" 82#define DRIVER_AUTHOR "Lonnie Mendez <dignome@gmail.com>, Neil Whelchel <koyama@firstlight.net>" 83#define DRIVER_DESC "Cypress USB to Serial Driver" 84 85/* write buffer size defines */ 86#define CYPRESS_BUF_SIZE 1024 87#define CYPRESS_CLOSING_WAIT (30*HZ) 88 89static struct usb_device_id id_table_earthmate [] = { 90 { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) }, 91 { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) }, 92 { } /* Terminating entry */ 93}; 94 95static struct usb_device_id id_table_cyphidcomrs232 [] = { 96 { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) }, 97 { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) }, 98 { } /* Terminating entry */ 99}; 100 101static struct usb_device_id id_table_nokiaca42v2 [] = { 102 { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) }, 103 { } /* Terminating entry */ 104}; 105 106static struct usb_device_id id_table_combined [] = { 107 { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) }, 108 { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) }, 109 { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) }, 110 { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) }, 111 { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) }, 112 { } /* Terminating entry */ 113}; 114 115MODULE_DEVICE_TABLE (usb, id_table_combined); 116 117static struct usb_driver cypress_driver = { 118 .name = "cypress", 119 .probe = usb_serial_probe, 120 .disconnect = usb_serial_disconnect, 121 .id_table = id_table_combined, 122 .no_dynamic_id = 1, 123}; 124 125enum packet_format { 126 packet_format_1, /* b0:status, b1:payload count */ 127 packet_format_2 /* b0[7:3]:status, b0[2:0]:payload count */ 128}; 129 130struct cypress_private { 131 spinlock_t lock; /* private lock */ 132 int chiptype; /* identifier of device, for quirks/etc */ 133 int bytes_in; /* used for statistics */ 134 int bytes_out; /* used for statistics */ 135 int cmd_count; /* used for statistics */ 136 int cmd_ctrl; /* always set this to 1 before issuing a command */ 137 struct cypress_buf *buf; /* write buffer */ 138 int write_urb_in_use; /* write urb in use indicator */ 139 int write_urb_interval; /* interval to use for write urb */ 140 int read_urb_interval; /* interval to use for read urb */ 141 int comm_is_ok; /* true if communication is (still) ok */ 142 int termios_initialized; 143 __u8 line_control; /* holds dtr / rts value */ 144 __u8 current_status; /* received from last read - info on dsr,cts,cd,ri,etc */ 145 __u8 current_config; /* stores the current configuration byte */ 146 __u8 rx_flags; /* throttling - used from whiteheat/ftdi_sio */ 147 enum packet_format pkt_fmt; /* format to use for packet send / receive */ 148 int get_cfg_unsafe; /* If true, the CYPRESS_GET_CONFIG is unsafe */ 149 int baud_rate; /* stores current baud rate in integer form */ 150 int isthrottled; /* if throttled, discard reads */ 151 wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */ 152 char prev_status, diff_status; /* used for TIOCMIWAIT */ 153 /* we pass a pointer to this as the arguement sent to cypress_set_termios old_termios */ 154 struct ktermios tmp_termios; /* stores the old termios settings */ 155}; 156 157/* write buffer structure */ 158struct cypress_buf { 159 unsigned int buf_size; 160 char *buf_buf; 161 char *buf_get; 162 char *buf_put; 163}; 164 165/* function prototypes for the Cypress USB to serial device */ 166static int cypress_earthmate_startup (struct usb_serial *serial); 167static int cypress_hidcom_startup (struct usb_serial *serial); 168static int cypress_ca42v2_startup (struct usb_serial *serial); 169static void cypress_shutdown (struct usb_serial *serial); 170static int cypress_open (struct usb_serial_port *port, struct file *filp); 171static void cypress_close (struct usb_serial_port *port, struct file *filp); 172static int cypress_write (struct usb_serial_port *port, const unsigned char *buf, int count); 173static void cypress_send (struct usb_serial_port *port); 174static int cypress_write_room (struct usb_serial_port *port); 175static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); 176static void cypress_set_termios (struct usb_serial_port *port, struct ktermios * old); 177static int cypress_tiocmget (struct usb_serial_port *port, struct file *file); 178static int cypress_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); 179static int cypress_chars_in_buffer (struct usb_serial_port *port); 180static void cypress_throttle (struct usb_serial_port *port); 181static void cypress_unthrottle (struct usb_serial_port *port); 182static void cypress_set_dead (struct usb_serial_port *port); 183static void cypress_read_int_callback (struct urb *urb); 184static void cypress_write_int_callback (struct urb *urb); 185/* write buffer functions */ 186static struct cypress_buf *cypress_buf_alloc(unsigned int size); 187static void cypress_buf_free(struct cypress_buf *cb); 188static void cypress_buf_clear(struct cypress_buf *cb); 189static unsigned int cypress_buf_data_avail(struct cypress_buf *cb); 190static unsigned int cypress_buf_space_avail(struct cypress_buf *cb); 191static unsigned int cypress_buf_put(struct cypress_buf *cb, const char *buf, unsigned int count); 192static unsigned int cypress_buf_get(struct cypress_buf *cb, char *buf, unsigned int count); 193 194 195static struct usb_serial_driver cypress_earthmate_device = { 196 .driver = { 197 .owner = THIS_MODULE, 198 .name = "earthmate", 199 }, 200 .description = "DeLorme Earthmate USB", 201 .usb_driver = &cypress_driver, 202 .id_table = id_table_earthmate, 203 .num_ports = 1, 204 .attach = cypress_earthmate_startup, 205 .shutdown = cypress_shutdown, 206 .open = cypress_open, 207 .close = cypress_close, 208 .write = cypress_write, 209 .write_room = cypress_write_room, 210 .ioctl = cypress_ioctl, 211 .set_termios = cypress_set_termios, 212 .tiocmget = cypress_tiocmget, 213 .tiocmset = cypress_tiocmset, 214 .chars_in_buffer = cypress_chars_in_buffer, 215 .throttle = cypress_throttle, 216 .unthrottle = cypress_unthrottle, 217 .read_int_callback = cypress_read_int_callback, 218 .write_int_callback = cypress_write_int_callback, 219}; 220 221static struct usb_serial_driver cypress_hidcom_device = { 222 .driver = { 223 .owner = THIS_MODULE, 224 .name = "cyphidcom", 225 }, 226 .description = "HID->COM RS232 Adapter", 227 .usb_driver = &cypress_driver, 228 .id_table = id_table_cyphidcomrs232, 229 .num_ports = 1, 230 .attach = cypress_hidcom_startup, 231 .shutdown = cypress_shutdown, 232 .open = cypress_open, 233 .close = cypress_close, 234 .write = cypress_write, 235 .write_room = cypress_write_room, 236 .ioctl = cypress_ioctl, 237 .set_termios = cypress_set_termios, 238 .tiocmget = cypress_tiocmget, 239 .tiocmset = cypress_tiocmset, 240 .chars_in_buffer = cypress_chars_in_buffer, 241 .throttle = cypress_throttle, 242 .unthrottle = cypress_unthrottle, 243 .read_int_callback = cypress_read_int_callback, 244 .write_int_callback = cypress_write_int_callback, 245}; 246 247static struct usb_serial_driver cypress_ca42v2_device = { 248 .driver = { 249 .owner = THIS_MODULE, 250 .name = "nokiaca42v2", 251 }, 252 .description = "Nokia CA-42 V2 Adapter", 253 .usb_driver = &cypress_driver, 254 .id_table = id_table_nokiaca42v2, 255 .num_ports = 1, 256 .attach = cypress_ca42v2_startup, 257 .shutdown = cypress_shutdown, 258 .open = cypress_open, 259 .close = cypress_close, 260 .write = cypress_write, 261 .write_room = cypress_write_room, 262 .ioctl = cypress_ioctl, 263 .set_termios = cypress_set_termios, 264 .tiocmget = cypress_tiocmget, 265 .tiocmset = cypress_tiocmset, 266 .chars_in_buffer = cypress_chars_in_buffer, 267 .throttle = cypress_throttle, 268 .unthrottle = cypress_unthrottle, 269 .read_int_callback = cypress_read_int_callback, 270 .write_int_callback = cypress_write_int_callback, 271}; 272 273/***************************************************************************** 274 * Cypress serial helper functions 275 *****************************************************************************/ 276 277 278static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate) 279{ 280 struct cypress_private *priv; 281 priv = usb_get_serial_port_data(port); 282 283 /* 284 * The general purpose firmware for the Cypress M8 allows for 285 * a maximum speed of 57600bps (I have no idea whether DeLorme 286 * chose to use the general purpose firmware or not), if you 287 * need to modify this speed setting for your own project 288 * please add your own chiptype and modify the code likewise. 289 * The Cypress HID->COM device will work successfully up to 290 * 115200bps (but the actual throughput is around 3kBps). 291 */ 292 if (port->serial->dev->speed == USB_SPEED_LOW) { 293 /* 294 * Mike Isely <isely@pobox.com> 2-Feb-2008: The 295 * Cypress app note that describes this mechanism 296 * states the the low-speed part can't handle more 297 * than 800 bytes/sec, in which case 4800 baud is the 298 * safest speed for a part like that. 299 */ 300 if (new_rate > 4800) { 301 dbg("%s - failed setting baud rate, device incapable " 302 "speed %d", __func__, new_rate); 303 return -1; 304 } 305 } 306 switch (priv->chiptype) { 307 case CT_EARTHMATE: 308 if (new_rate <= 600) { 309 /* 300 and 600 baud rates are supported under 310 * the generic firmware, but are not used with 311 * NMEA and SiRF protocols */ 312 dbg("%s - failed setting baud rate, unsupported speed " 313 "of %d on Earthmate GPS", __func__, new_rate); 314 return -1; 315 } 316 break; 317 default: 318 break; 319 } 320 return new_rate; 321} 322 323 324/* This function can either set or retrieve the current serial line settings */ 325static int cypress_serial_control (struct usb_serial_port *port, speed_t baud_rate, int data_bits, int stop_bits, 326 int parity_enable, int parity_type, int reset, int cypress_request_type) 327{ 328 int new_baudrate = 0, retval = 0, tries = 0; 329 struct cypress_private *priv; 330 __u8 feature_buffer[5]; 331 unsigned long flags; 332 333 dbg("%s", __func__); 334 335 priv = usb_get_serial_port_data(port); 336 337 if (!priv->comm_is_ok) 338 return -ENODEV; 339 340 switch(cypress_request_type) { 341 case CYPRESS_SET_CONFIG: 342 new_baudrate = priv->baud_rate; 343 /* 0 means 'Hang up' so doesn't change the true bit rate */ 344 if (baud_rate == 0) 345 new_baudrate = priv->baud_rate; 346 /* Change of speed ? */ 347 else if (baud_rate != priv->baud_rate) { 348 dbg("%s - baud rate is changing", __func__); 349 retval = analyze_baud_rate(port, baud_rate); 350 if (retval >= 0) { 351 new_baudrate = retval; 352 dbg("%s - New baud rate set to %d", 353 __func__, new_baudrate); 354 } 355 } 356 dbg("%s - baud rate is being sent as %d", __func__, new_baudrate); 357 358 memset(feature_buffer, 0, sizeof(feature_buffer)); 359 /* fill the feature_buffer with new configuration */ 360 *((u_int32_t *)feature_buffer) = new_baudrate; 361 362 feature_buffer[4] |= data_bits; /* assign data bits in 2 bit space ( max 3 ) */ 363 /* 1 bit gap */ 364 feature_buffer[4] |= (stop_bits << 3); /* assign stop bits in 1 bit space */ 365 feature_buffer[4] |= (parity_enable << 4); /* assign parity flag in 1 bit space */ 366 feature_buffer[4] |= (parity_type << 5); /* assign parity type in 1 bit space */ 367 /* 1 bit gap */ 368 feature_buffer[4] |= (reset << 7); /* assign reset at end of byte, 1 bit space */ 369 370 dbg("%s - device is being sent this feature report:", __func__); 371 dbg("%s - %02X - %02X - %02X - %02X - %02X", __func__, feature_buffer[0], feature_buffer[1], 372 feature_buffer[2], feature_buffer[3], feature_buffer[4]); 373 374 do { 375 retval = usb_control_msg(port->serial->dev, 376 usb_sndctrlpipe(port->serial->dev, 0), 377 HID_REQ_SET_REPORT, 378 USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS, 379 0x0300, 0, feature_buffer, 380 sizeof(feature_buffer), 500); 381 382 if (tries++ >= 3) 383 break; 384 385 } while (retval != sizeof(feature_buffer) && 386 retval != -ENODEV); 387 388 if (retval != sizeof(feature_buffer)) { 389 err("%s - failed sending serial line settings - %d", __func__, retval); 390 cypress_set_dead(port); 391 } else { 392 spin_lock_irqsave(&priv->lock, flags); 393 priv->baud_rate = new_baudrate; 394 priv->current_config = feature_buffer[4]; 395 spin_unlock_irqrestore(&priv->lock, flags); 396 /* If we asked for a speed change encode it */ 397 if (baud_rate) 398 tty_encode_baud_rate(port->tty, 399 new_baudrate, new_baudrate); 400 } 401 break; 402 case CYPRESS_GET_CONFIG: 403 if (priv->get_cfg_unsafe) { 404 /* Not implemented for this device, 405 and if we try to do it we're likely 406 to crash the hardware. */ 407 return -ENOTTY; 408 } 409 dbg("%s - retreiving serial line settings", __func__); 410 /* set initial values in feature buffer */ 411 memset(feature_buffer, 0, sizeof(feature_buffer)); 412 413 do { 414 retval = usb_control_msg(port->serial->dev, 415 usb_rcvctrlpipe(port->serial->dev, 0), 416 HID_REQ_GET_REPORT, 417 USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS, 418 0x0300, 0, feature_buffer, 419 sizeof(feature_buffer), 500); 420 421 if (tries++ >= 3) 422 break; 423 424 } while (retval != sizeof(feature_buffer) && 425 retval != -ENODEV); 426 427 if (retval != sizeof(feature_buffer)) { 428 err("%s - failed to retrieve serial line settings - %d", __func__, retval); 429 cypress_set_dead(port); 430 return retval; 431 } else { 432 spin_lock_irqsave(&priv->lock, flags); 433 434 /* store the config in one byte, and later use bit masks to check values */ 435 priv->current_config = feature_buffer[4]; 436 priv->baud_rate = *((u_int32_t *)feature_buffer); 437 spin_unlock_irqrestore(&priv->lock, flags); 438 } 439 } 440 spin_lock_irqsave(&priv->lock, flags); 441 ++priv->cmd_count; 442 spin_unlock_irqrestore(&priv->lock, flags); 443 444 return retval; 445} /* cypress_serial_control */ 446 447 448static void cypress_set_dead(struct usb_serial_port *port) 449{ 450 struct cypress_private *priv = usb_get_serial_port_data(port); 451 unsigned long flags; 452 453 spin_lock_irqsave(&priv->lock, flags); 454 if (!priv->comm_is_ok) { 455 spin_unlock_irqrestore(&priv->lock, flags); 456 return; 457 } 458 priv->comm_is_ok = 0; 459 spin_unlock_irqrestore(&priv->lock, flags); 460 461 err("cypress_m8 suspending failing port %d - interval might be too short", 462 port->number); 463} 464 465 466/***************************************************************************** 467 * Cypress serial driver functions 468 *****************************************************************************/ 469 470 471static int generic_startup (struct usb_serial *serial) 472{ 473 struct cypress_private *priv; 474 struct usb_serial_port *port = serial->port[0]; 475 476 dbg("%s - port %d", __func__, port->number); 477 478 priv = kzalloc(sizeof (struct cypress_private), GFP_KERNEL); 479 if (!priv) 480 return -ENOMEM; 481 482 priv->comm_is_ok = !0; 483 spin_lock_init(&priv->lock); 484 priv->buf = cypress_buf_alloc(CYPRESS_BUF_SIZE); 485 if (priv->buf == NULL) { 486 kfree(priv); 487 return -ENOMEM; 488 } 489 init_waitqueue_head(&priv->delta_msr_wait); 490 491 usb_reset_configuration (serial->dev); 492 493 priv->cmd_ctrl = 0; 494 priv->line_control = 0; 495 priv->termios_initialized = 0; 496 priv->rx_flags = 0; 497 /* Default packet format setting is determined by packet size. 498 Anything with a size larger then 9 must have a separate 499 count field since the 3 bit count field is otherwise too 500 small. Otherwise we can use the slightly more compact 501 format. This is in accordance with the cypress_m8 serial 502 converter app note. */ 503 if (port->interrupt_out_size > 9) { 504 priv->pkt_fmt = packet_format_1; 505 } else { 506 priv->pkt_fmt = packet_format_2; 507 } 508 if (interval > 0) { 509 priv->write_urb_interval = interval; 510 priv->read_urb_interval = interval; 511 dbg("%s - port %d read & write intervals forced to %d", 512 __func__,port->number,interval); 513 } else { 514 priv->write_urb_interval = port->interrupt_out_urb->interval; 515 priv->read_urb_interval = port->interrupt_in_urb->interval; 516 dbg("%s - port %d intervals: read=%d write=%d", 517 __func__,port->number, 518 priv->read_urb_interval,priv->write_urb_interval); 519 } 520 usb_set_serial_port_data(port, priv); 521 522 return 0; 523} 524 525 526static int cypress_earthmate_startup (struct usb_serial *serial) 527{ 528 struct cypress_private *priv; 529 struct usb_serial_port *port = serial->port[0]; 530 531 dbg("%s", __func__); 532 533 if (generic_startup(serial)) { 534 dbg("%s - Failed setting up port %d", __func__, 535 port->number); 536 return 1; 537 } 538 539 priv = usb_get_serial_port_data(port); 540 priv->chiptype = CT_EARTHMATE; 541 /* All Earthmate devices use the separated-count packet 542 format! Idiotic. */ 543 priv->pkt_fmt = packet_format_1; 544 if (serial->dev->descriptor.idProduct != cpu_to_le16(PRODUCT_ID_EARTHMATEUSB)) { 545 /* The old original USB Earthmate seemed able to 546 handle GET_CONFIG requests; everything they've 547 produced since that time crashes if this command is 548 attempted :-( */ 549 dbg("%s - Marking this device as unsafe for GET_CONFIG " 550 "commands", __func__); 551 priv->get_cfg_unsafe = !0; 552 } 553 554 return 0; 555} /* cypress_earthmate_startup */ 556 557 558static int cypress_hidcom_startup (struct usb_serial *serial) 559{ 560 struct cypress_private *priv; 561 562 dbg("%s", __func__); 563 564 if (generic_startup(serial)) { 565 dbg("%s - Failed setting up port %d", __func__, 566 serial->port[0]->number); 567 return 1; 568 } 569 570 priv = usb_get_serial_port_data(serial->port[0]); 571 priv->chiptype = CT_CYPHIDCOM; 572 573 return 0; 574} /* cypress_hidcom_startup */ 575 576 577static int cypress_ca42v2_startup (struct usb_serial *serial) 578{ 579 struct cypress_private *priv; 580 581 dbg("%s", __func__); 582 583 if (generic_startup(serial)) { 584 dbg("%s - Failed setting up port %d", __func__, 585 serial->port[0]->number); 586 return 1; 587 } 588 589 priv = usb_get_serial_port_data(serial->port[0]); 590 priv->chiptype = CT_CA42V2; 591 592 return 0; 593} /* cypress_ca42v2_startup */ 594 595 596static void cypress_shutdown (struct usb_serial *serial) 597{ 598 struct cypress_private *priv; 599 600 dbg ("%s - port %d", __func__, serial->port[0]->number); 601 602 /* all open ports are closed at this point */ 603 604 priv = usb_get_serial_port_data(serial->port[0]); 605 606 if (priv) { 607 cypress_buf_free(priv->buf); 608 kfree(priv); 609 usb_set_serial_port_data(serial->port[0], NULL); 610 } 611} 612 613 614static int cypress_open (struct usb_serial_port *port, struct file *filp) 615{ 616 struct cypress_private *priv = usb_get_serial_port_data(port); 617 struct usb_serial *serial = port->serial; 618 unsigned long flags; 619 int result = 0; 620 621 dbg("%s - port %d", __func__, port->number); 622 623 if (!priv->comm_is_ok) 624 return -EIO; 625 626 /* clear halts before open */ 627 usb_clear_halt(serial->dev, 0x81); 628 usb_clear_halt(serial->dev, 0x02); 629 630 spin_lock_irqsave(&priv->lock, flags); 631 /* reset read/write statistics */ 632 priv->bytes_in = 0; 633 priv->bytes_out = 0; 634 priv->cmd_count = 0; 635 priv->rx_flags = 0; 636 spin_unlock_irqrestore(&priv->lock, flags); 637 638 /* setting to zero could cause data loss */ 639 port->tty->low_latency = 1; 640 641 /* raise both lines and set termios */ 642 spin_lock_irqsave(&priv->lock, flags); 643 priv->line_control = CONTROL_DTR | CONTROL_RTS; 644 priv->cmd_ctrl = 1; 645 spin_unlock_irqrestore(&priv->lock, flags); 646 result = cypress_write(port, NULL, 0); 647 648 if (result) { 649 dev_err(&port->dev, "%s - failed setting the control lines - error %d\n", __func__, result); 650 return result; 651 } else 652 dbg("%s - success setting the control lines", __func__); 653 654 cypress_set_termios(port, &priv->tmp_termios); 655 656 /* setup the port and start reading from the device */ 657 if(!port->interrupt_in_urb){ 658 err("%s - interrupt_in_urb is empty!", __func__); 659 return(-1); 660 } 661 662 usb_fill_int_urb(port->interrupt_in_urb, serial->dev, 663 usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress), 664 port->interrupt_in_urb->transfer_buffer, port->interrupt_in_urb->transfer_buffer_length, 665 cypress_read_int_callback, port, priv->read_urb_interval); 666 result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); 667 668 if (result){ 669 dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result); 670 cypress_set_dead(port); 671 } 672 673 return result; 674} /* cypress_open */ 675 676 677static void cypress_close(struct usb_serial_port *port, struct file * filp) 678{ 679 struct cypress_private *priv = usb_get_serial_port_data(port); 680 unsigned int c_cflag; 681 int bps; 682 long timeout; 683 wait_queue_t wait; 684 685 dbg("%s - port %d", __func__, port->number); 686 687 /* wait for data to drain from buffer */ 688 spin_lock_irq(&priv->lock); 689 timeout = CYPRESS_CLOSING_WAIT; 690 init_waitqueue_entry(&wait, current); 691 add_wait_queue(&port->tty->write_wait, &wait); 692 for (;;) { 693 set_current_state(TASK_INTERRUPTIBLE); 694 if (cypress_buf_data_avail(priv->buf) == 0 695 || timeout == 0 || signal_pending(current) 696 /* without mutex, allowed due to harmless failure mode */ 697 || port->serial->disconnected) 698 break; 699 spin_unlock_irq(&priv->lock); 700 timeout = schedule_timeout(timeout); 701 spin_lock_irq(&priv->lock); 702 } 703 set_current_state(TASK_RUNNING); 704 remove_wait_queue(&port->tty->write_wait, &wait); 705 /* clear out any remaining data in the buffer */ 706 cypress_buf_clear(priv->buf); 707 spin_unlock_irq(&priv->lock); 708 709 /* writing is potentially harmful, lock must be taken */ 710 mutex_lock(&port->serial->disc_mutex); 711 if (port->serial->disconnected) { 712 mutex_unlock(&port->serial->disc_mutex); 713 return; 714 } 715 /* wait for characters to drain from device */ 716 bps = tty_get_baud_rate(port->tty); 717 if (bps > 1200) 718 timeout = max((HZ*2560)/bps,HZ/10); 719 else 720 timeout = 2*HZ; 721 schedule_timeout_interruptible(timeout); 722 723 dbg("%s - stopping urbs", __func__); 724 usb_kill_urb (port->interrupt_in_urb); 725 usb_kill_urb (port->interrupt_out_urb); 726 727 if (port->tty) { 728 c_cflag = port->tty->termios->c_cflag; 729 if (c_cflag & HUPCL) { 730 /* drop dtr and rts */ 731 priv = usb_get_serial_port_data(port); 732 spin_lock_irq(&priv->lock); 733 priv->line_control = 0; 734 priv->cmd_ctrl = 1; 735 spin_unlock_irq(&priv->lock); 736 cypress_write(port, NULL, 0); 737 } 738 } 739 740 if (stats) 741 dev_info (&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n", 742 priv->bytes_in, priv->bytes_out, priv->cmd_count); 743 mutex_unlock(&port->serial->disc_mutex); 744} /* cypress_close */ 745 746 747static int cypress_write(struct usb_serial_port *port, const unsigned char *buf, int count) 748{ 749 struct cypress_private *priv = usb_get_serial_port_data(port); 750 unsigned long flags; 751 752 dbg("%s - port %d, %d bytes", __func__, port->number, count); 753 754 /* line control commands, which need to be executed immediately, 755 are not put into the buffer for obvious reasons. 756 */ 757 if (priv->cmd_ctrl) { 758 count = 0; 759 goto finish; 760 } 761 762 if (!count) 763 return count; 764 765 spin_lock_irqsave(&priv->lock, flags); 766 count = cypress_buf_put(priv->buf, buf, count); 767 spin_unlock_irqrestore(&priv->lock, flags); 768 769finish: 770 cypress_send(port); 771 772 return count; 773} /* cypress_write */ 774 775 776static void cypress_send(struct usb_serial_port *port) 777{ 778 int count = 0, result, offset, actual_size; 779 struct cypress_private *priv = usb_get_serial_port_data(port); 780 unsigned long flags; 781 782 if (!priv->comm_is_ok) 783 return; 784 785 dbg("%s - port %d", __func__, port->number); 786 dbg("%s - interrupt out size is %d", __func__, port->interrupt_out_size); 787 788 spin_lock_irqsave(&priv->lock, flags); 789 if (priv->write_urb_in_use) { 790 dbg("%s - can't write, urb in use", __func__); 791 spin_unlock_irqrestore(&priv->lock, flags); 792 return; 793 } 794 spin_unlock_irqrestore(&priv->lock, flags); 795 796 /* clear buffer */ 797 memset(port->interrupt_out_urb->transfer_buffer, 0, port->interrupt_out_size); 798 799 spin_lock_irqsave(&priv->lock, flags); 800 switch (priv->pkt_fmt) { 801 default: 802 case packet_format_1: 803 /* this is for the CY7C64013... */ 804 offset = 2; 805 port->interrupt_out_buffer[0] = priv->line_control; 806 break; 807 case packet_format_2: 808 /* this is for the CY7C63743... */ 809 offset = 1; 810 port->interrupt_out_buffer[0] = priv->line_control; 811 break; 812 } 813 814 if (priv->line_control & CONTROL_RESET) 815 priv->line_control &= ~CONTROL_RESET; 816 817 if (priv->cmd_ctrl) { 818 priv->cmd_count++; 819 dbg("%s - line control command being issued", __func__); 820 spin_unlock_irqrestore(&priv->lock, flags); 821 goto send; 822 } else 823 spin_unlock_irqrestore(&priv->lock, flags); 824 825 count = cypress_buf_get(priv->buf, &port->interrupt_out_buffer[offset], 826 port->interrupt_out_size-offset); 827 828 if (count == 0) { 829 return; 830 } 831 832 switch (priv->pkt_fmt) { 833 default: 834 case packet_format_1: 835 port->interrupt_out_buffer[1] = count; 836 break; 837 case packet_format_2: 838 port->interrupt_out_buffer[0] |= count; 839 } 840 841 dbg("%s - count is %d", __func__, count); 842 843send: 844 spin_lock_irqsave(&priv->lock, flags); 845 priv->write_urb_in_use = 1; 846 spin_unlock_irqrestore(&priv->lock, flags); 847 848 if (priv->cmd_ctrl) 849 actual_size = 1; 850 else 851 actual_size = count + 852 (priv->pkt_fmt == packet_format_1 ? 2 : 1); 853 854 usb_serial_debug_data(debug, &port->dev, __func__, port->interrupt_out_size, 855 port->interrupt_out_urb->transfer_buffer); 856 857 usb_fill_int_urb(port->interrupt_out_urb, port->serial->dev, 858 usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress), 859 port->interrupt_out_buffer, port->interrupt_out_size, 860 cypress_write_int_callback, port, priv->write_urb_interval); 861 result = usb_submit_urb (port->interrupt_out_urb, GFP_ATOMIC); 862 if (result) { 863 dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, 864 result); 865 priv->write_urb_in_use = 0; 866 cypress_set_dead(port); 867 } 868 869 spin_lock_irqsave(&priv->lock, flags); 870 if (priv->cmd_ctrl) { 871 priv->cmd_ctrl = 0; 872 } 873 priv->bytes_out += count; /* do not count the line control and size bytes */ 874 spin_unlock_irqrestore(&priv->lock, flags); 875 876 usb_serial_port_softint(port); 877} /* cypress_send */ 878 879 880/* returns how much space is available in the soft buffer */ 881static int cypress_write_room(struct usb_serial_port *port) 882{ 883 struct cypress_private *priv = usb_get_serial_port_data(port); 884 int room = 0; 885 unsigned long flags; 886 887 dbg("%s - port %d", __func__, port->number); 888 889 spin_lock_irqsave(&priv->lock, flags); 890 room = cypress_buf_space_avail(priv->buf); 891 spin_unlock_irqrestore(&priv->lock, flags); 892 893 dbg("%s - returns %d", __func__, room); 894 return room; 895} 896 897 898static int cypress_tiocmget (struct usb_serial_port *port, struct file *file) 899{ 900 struct cypress_private *priv = usb_get_serial_port_data(port); 901 __u8 status, control; 902 unsigned int result = 0; 903 unsigned long flags; 904 905 dbg("%s - port %d", __func__, port->number); 906 907 spin_lock_irqsave(&priv->lock, flags); 908 control = priv->line_control; 909 status = priv->current_status; 910 spin_unlock_irqrestore(&priv->lock, flags); 911 912 result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0) 913 | ((control & CONTROL_RTS) ? TIOCM_RTS : 0) 914 | ((status & UART_CTS) ? TIOCM_CTS : 0) 915 | ((status & UART_DSR) ? TIOCM_DSR : 0) 916 | ((status & UART_RI) ? TIOCM_RI : 0) 917 | ((status & UART_CD) ? TIOCM_CD : 0); 918 919 dbg("%s - result = %x", __func__, result); 920 921 return result; 922} 923 924 925static int cypress_tiocmset (struct usb_serial_port *port, struct file *file, 926 unsigned int set, unsigned int clear) 927{ 928 struct cypress_private *priv = usb_get_serial_port_data(port); 929 unsigned long flags; 930 931 dbg("%s - port %d", __func__, port->number); 932 933 spin_lock_irqsave(&priv->lock, flags); 934 if (set & TIOCM_RTS) 935 priv->line_control |= CONTROL_RTS; 936 if (set & TIOCM_DTR) 937 priv->line_control |= CONTROL_DTR; 938 if (clear & TIOCM_RTS) 939 priv->line_control &= ~CONTROL_RTS; 940 if (clear & TIOCM_DTR) 941 priv->line_control &= ~CONTROL_DTR; 942 priv->cmd_ctrl = 1; 943 spin_unlock_irqrestore(&priv->lock, flags); 944 945 return cypress_write(port, NULL, 0); 946} 947 948 949static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) 950{ 951 struct cypress_private *priv = usb_get_serial_port_data(port); 952 953 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd); 954 955 switch (cmd) { 956 /* This code comes from drivers/char/serial.c and ftdi_sio.c */ 957 case TIOCMIWAIT: 958 while (priv != NULL) { 959 interruptible_sleep_on(&priv->delta_msr_wait); 960 /* see if a signal did it */ 961 if (signal_pending(current)) 962 return -ERESTARTSYS; 963 else { 964 char diff = priv->diff_status; 965 966 if (diff == 0) { 967 return -EIO; /* no change => error */ 968 } 969 970 /* consume all events */ 971 priv->diff_status = 0; 972 973 /* return 0 if caller wanted to know about these bits */ 974 if ( ((arg & TIOCM_RNG) && (diff & UART_RI)) || 975 ((arg & TIOCM_DSR) && (diff & UART_DSR)) || 976 ((arg & TIOCM_CD) && (diff & UART_CD)) || 977 ((arg & TIOCM_CTS) && (diff & UART_CTS)) ) { 978 return 0; 979 } 980 /* otherwise caller can't care less about what happened, 981 * and so we continue to wait for more events. 982 */ 983 } 984 } 985 return 0; 986 break; 987 default: 988 break; 989 } 990 991 dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __func__, cmd); 992 993 return -ENOIOCTLCMD; 994} /* cypress_ioctl */ 995 996 997static void cypress_set_termios (struct usb_serial_port *port, 998 struct ktermios *old_termios) 999{ 1000 struct cypress_private *priv = usb_get_serial_port_data(port); 1001 struct tty_struct *tty; 1002 int data_bits, stop_bits, parity_type, parity_enable; 1003 unsigned cflag, iflag; 1004 unsigned long flags; 1005 __u8 oldlines; 1006 int linechange = 0; 1007 1008 dbg("%s - port %d", __func__, port->number); 1009 1010 tty = port->tty; 1011 1012 spin_lock_irqsave(&priv->lock, flags); 1013 if (!priv->termios_initialized) { 1014 if (priv->chiptype == CT_EARTHMATE) { 1015 *(tty->termios) = tty_std_termios; 1016 tty->termios->c_cflag = B4800 | CS8 | CREAD | HUPCL | 1017 CLOCAL; 1018 tty->termios->c_ispeed = 4800; 1019 tty->termios->c_ospeed = 4800; 1020 } else if (priv->chiptype == CT_CYPHIDCOM) { 1021 *(tty->termios) = tty_std_termios; 1022 tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | 1023 CLOCAL; 1024 tty->termios->c_ispeed = 9600; 1025 tty->termios->c_ospeed = 9600; 1026 } else if (priv->chiptype == CT_CA42V2) { 1027 *(tty->termios) = tty_std_termios; 1028 tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | 1029 CLOCAL; 1030 tty->termios->c_ispeed = 9600; 1031 tty->termios->c_ospeed = 9600; 1032 } 1033 priv->termios_initialized = 1; 1034 } 1035 spin_unlock_irqrestore(&priv->lock, flags); 1036 1037 /* Unsupported features need clearing */ 1038 tty->termios->c_cflag &= ~(CMSPAR|CRTSCTS); 1039 1040 cflag = tty->termios->c_cflag; 1041 iflag = tty->termios->c_iflag; 1042 1043 /* check if there are new settings */ 1044 if (old_termios) { 1045 spin_lock_irqsave(&priv->lock, flags); 1046 priv->tmp_termios = *(tty->termios); 1047 spin_unlock_irqrestore(&priv->lock, flags); 1048 } 1049 1050 /* set number of data bits, parity, stop bits */ 1051 /* when parity is disabled the parity type bit is ignored */ 1052 1053 /* 1 means 2 stop bits, 0 means 1 stop bit */ 1054 stop_bits = cflag & CSTOPB ? 1 : 0; 1055 1056 if (cflag & PARENB) { 1057 parity_enable = 1; 1058 /* 1 means odd parity, 0 means even parity */ 1059 parity_type = cflag & PARODD ? 1 : 0; 1060 } else 1061 parity_enable = parity_type = 0; 1062 1063 if (cflag & CSIZE) { 1064 switch (cflag & CSIZE) { 1065 case CS5: 1066 data_bits = 0; 1067 break; 1068 case CS6: 1069 data_bits = 1; 1070 break; 1071 case CS7: 1072 data_bits = 2; 1073 break; 1074 case CS8: 1075 data_bits = 3; 1076 break; 1077 default: 1078 err("%s - CSIZE was set, but not CS5-CS8", 1079 __func__); 1080 data_bits = 3; 1081 } 1082 } else 1083 data_bits = 3; 1084 1085 spin_lock_irqsave(&priv->lock, flags); 1086 oldlines = priv->line_control; 1087 if ((cflag & CBAUD) == B0) { 1088 /* drop dtr and rts */ 1089 dbg("%s - dropping the lines, baud rate 0bps", __func__); 1090 priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); 1091 } else 1092 priv->line_control = (CONTROL_DTR | CONTROL_RTS); 1093 spin_unlock_irqrestore(&priv->lock, flags); 1094 1095 dbg("%s - sending %d stop_bits, %d parity_enable, %d parity_type, " 1096 "%d data_bits (+5)", __func__, stop_bits, 1097 parity_enable, parity_type, data_bits); 1098 1099 cypress_serial_control(port, tty_get_baud_rate(tty), data_bits, stop_bits, 1100 parity_enable, parity_type, 0, CYPRESS_SET_CONFIG); 1101 1102 /* we perform a CYPRESS_GET_CONFIG so that the current settings are 1103 * filled into the private structure this should confirm that all is 1104 * working if it returns what we just set */ 1105 cypress_serial_control(port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG); 1106 1107 /* Here we can define custom tty settings for devices; the main tty 1108 * termios flag base comes from empeg.c */ 1109 1110 spin_lock_irqsave(&priv->lock, flags); 1111 if ( (priv->chiptype == CT_EARTHMATE) && (priv->baud_rate == 4800) ) { 1112 dbg("Using custom termios settings for a baud rate of " 1113 "4800bps."); 1114 /* define custom termios settings for NMEA protocol */ 1115 1116 tty->termios->c_iflag /* input modes - */ 1117 &= ~(IGNBRK /* disable ignore break */ 1118 | BRKINT /* disable break causes interrupt */ 1119 | PARMRK /* disable mark parity errors */ 1120 | ISTRIP /* disable clear high bit of input char */ 1121 | INLCR /* disable translate NL to CR */ 1122 | IGNCR /* disable ignore CR */ 1123 | ICRNL /* disable translate CR to NL */ 1124 | IXON); /* disable enable XON/XOFF flow control */ 1125 1126 tty->termios->c_oflag /* output modes */ 1127 &= ~OPOST; /* disable postprocess output char */ 1128 1129 tty->termios->c_lflag /* line discipline modes */ 1130 &= ~(ECHO /* disable echo input characters */ 1131 | ECHONL /* disable echo new line */ 1132 | ICANON /* disable erase, kill, werase, and rprnt 1133 special characters */ 1134 | ISIG /* disable interrupt, quit, and suspend 1135 special characters */ 1136 | IEXTEN); /* disable non-POSIX special characters */ 1137 } /* CT_CYPHIDCOM: Application should handle this for device */ 1138 1139 linechange = (priv->line_control != oldlines); 1140 spin_unlock_irqrestore(&priv->lock, flags); 1141 1142 /* if necessary, set lines */ 1143 if (linechange) { 1144 priv->cmd_ctrl = 1; 1145 cypress_write(port, NULL, 0); 1146 } 1147} /* cypress_set_termios */ 1148 1149 1150/* returns amount of data still left in soft buffer */ 1151static int cypress_chars_in_buffer(struct usb_serial_port *port) 1152{ 1153 struct cypress_private *priv = usb_get_serial_port_data(port); 1154 int chars = 0; 1155 unsigned long flags; 1156 1157 dbg("%s - port %d", __func__, port->number); 1158 1159 spin_lock_irqsave(&priv->lock, flags); 1160 chars = cypress_buf_data_avail(priv->buf); 1161 spin_unlock_irqrestore(&priv->lock, flags); 1162 1163 dbg("%s - returns %d", __func__, chars); 1164 return chars; 1165} 1166 1167 1168static void cypress_throttle (struct usb_serial_port *port) 1169{ 1170 struct cypress_private *priv = usb_get_serial_port_data(port); 1171 unsigned long flags; 1172 1173 dbg("%s - port %d", __func__, port->number); 1174 1175 spin_lock_irqsave(&priv->lock, flags); 1176 priv->rx_flags = THROTTLED; 1177 spin_unlock_irqrestore(&priv->lock, flags); 1178} 1179 1180 1181static void cypress_unthrottle (struct usb_serial_port *port) 1182{ 1183 struct cypress_private *priv = usb_get_serial_port_data(port); 1184 int actually_throttled, result; 1185 unsigned long flags; 1186 1187 dbg("%s - port %d", __func__, port->number); 1188 1189 spin_lock_irqsave(&priv->lock, flags); 1190 actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED; 1191 priv->rx_flags = 0; 1192 spin_unlock_irqrestore(&priv->lock, flags); 1193 1194 if (!priv->comm_is_ok) 1195 return; 1196 1197 if (actually_throttled) { 1198 port->interrupt_in_urb->dev = port->serial->dev; 1199 1200 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); 1201 if (result) { 1202 dev_err(&port->dev, "%s - failed submitting read urb, " 1203 "error %d\n", __func__, result); 1204 cypress_set_dead(port); 1205 } 1206 } 1207} 1208 1209 1210static void cypress_read_int_callback(struct urb *urb) 1211{ 1212 struct usb_serial_port *port = urb->context; 1213 struct cypress_private *priv = usb_get_serial_port_data(port); 1214 struct tty_struct *tty; 1215 unsigned char *data = urb->transfer_buffer; 1216 unsigned long flags; 1217 char tty_flag = TTY_NORMAL; 1218 int havedata = 0; 1219 int bytes = 0; 1220 int result; 1221 int i = 0; 1222 int status = urb->status; 1223 1224 dbg("%s - port %d", __func__, port->number); 1225 1226 switch (status) { 1227 case 0: /* success */ 1228 break; 1229 case -ECONNRESET: 1230 case -ENOENT: 1231 case -ESHUTDOWN: 1232 /* precursor to disconnect so just go away */ 1233 return; 1234 case -EPIPE: 1235 usb_clear_halt(port->serial->dev,0x81); 1236 break; 1237 default: 1238 /* something ugly is going on... */ 1239 dev_err(&urb->dev->dev,"%s - unexpected nonzero read status received: %d\n", 1240 __func__, status); 1241 cypress_set_dead(port); 1242 return; 1243 } 1244 1245 spin_lock_irqsave(&priv->lock, flags); 1246 if (priv->rx_flags & THROTTLED) { 1247 dbg("%s - now throttling", __func__); 1248 priv->rx_flags |= ACTUALLY_THROTTLED; 1249 spin_unlock_irqrestore(&priv->lock, flags); 1250 return; 1251 } 1252 spin_unlock_irqrestore(&priv->lock, flags); 1253 1254 tty = port->tty; 1255 if (!tty) { 1256 dbg("%s - bad tty pointer - exiting", __func__); 1257 return; 1258 } 1259 1260 spin_lock_irqsave(&priv->lock, flags); 1261 result = urb->actual_length; 1262 switch (priv->pkt_fmt) { 1263 default: 1264 case packet_format_1: 1265 /* This is for the CY7C64013... */ 1266 priv->current_status = data[0] & 0xF8; 1267 bytes = data[1] + 2; 1268 i = 2; 1269 if (bytes > 2) 1270 havedata = 1; 1271 break; 1272 case packet_format_2: 1273 /* This is for the CY7C63743... */ 1274 priv->current_status = data[0] & 0xF8; 1275 bytes = (data[0] & 0x07) + 1; 1276 i = 1; 1277 if (bytes > 1) 1278 havedata = 1; 1279 break; 1280 } 1281 spin_unlock_irqrestore(&priv->lock, flags); 1282 if (result < bytes) { 1283 dbg("%s - wrong packet size - received %d bytes but packet " 1284 "said %d bytes", __func__, result, bytes); 1285 goto continue_read; 1286 } 1287 1288 usb_serial_debug_data (debug, &port->dev, __func__, 1289 urb->actual_length, data); 1290 1291 spin_lock_irqsave(&priv->lock, flags); 1292 /* check to see if status has changed */ 1293 if (priv->current_status != priv->prev_status) { 1294 priv->diff_status |= priv->current_status ^ 1295 priv->prev_status; 1296 wake_up_interruptible(&priv->delta_msr_wait); 1297 priv->prev_status = priv->current_status; 1298 } 1299 spin_unlock_irqrestore(&priv->lock, flags); 1300 1301 /* hangup, as defined in acm.c... this might be a bad place for it 1302 * though */ 1303 if (tty && !(tty->termios->c_cflag & CLOCAL) && 1304 !(priv->current_status & UART_CD)) { 1305 dbg("%s - calling hangup", __func__); 1306 tty_hangup(tty); 1307 goto continue_read; 1308 } 1309 1310 /* There is one error bit... I'm assuming it is a parity error 1311 * indicator as the generic firmware will set this bit to 1 if a 1312 * parity error occurs. 1313 * I can not find reference to any other error events. */ 1314 spin_lock_irqsave(&priv->lock, flags); 1315 if (priv->current_status & CYP_ERROR) { 1316 spin_unlock_irqrestore(&priv->lock, flags); 1317 tty_flag = TTY_PARITY; 1318 dbg("%s - Parity Error detected", __func__); 1319 } else 1320 spin_unlock_irqrestore(&priv->lock, flags); 1321 1322 /* process read if there is data other than line status */ 1323 if (tty && (bytes > i)) { 1324 bytes = tty_buffer_request_room(tty, bytes); 1325 for (; i < bytes ; ++i) { 1326 dbg("pushing byte number %d - %d - %c", i, data[i], 1327 data[i]); 1328 tty_insert_flip_char(tty, data[i], tty_flag); 1329 } 1330 tty_flip_buffer_push(port->tty); 1331 } 1332 1333 spin_lock_irqsave(&priv->lock, flags); 1334 /* control and status byte(s) are also counted */ 1335 priv->bytes_in += bytes; 1336 spin_unlock_irqrestore(&priv->lock, flags); 1337 1338continue_read: 1339 1340 /* Continue trying to always read... unless the port has closed. */ 1341 1342 if (port->open_count > 0 && priv->comm_is_ok) { 1343 usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev, 1344 usb_rcvintpipe(port->serial->dev, 1345 port->interrupt_in_endpointAddress), 1346 port->interrupt_in_urb->transfer_buffer, 1347 port->interrupt_in_urb->transfer_buffer_length, 1348 cypress_read_int_callback, port, priv->read_urb_interval); 1349 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); 1350 if (result) { 1351 dev_err(&urb->dev->dev, "%s - failed resubmitting " 1352 "read urb, error %d\n", __func__, 1353 result); 1354 cypress_set_dead(port); 1355 } 1356 } 1357 1358 return; 1359} /* cypress_read_int_callback */ 1360 1361 1362static void cypress_write_int_callback(struct urb *urb) 1363{ 1364 struct usb_serial_port *port = urb->context; 1365 struct cypress_private *priv = usb_get_serial_port_data(port); 1366 int result; 1367 int status = urb->status; 1368 1369 dbg("%s - port %d", __func__, port->number); 1370 1371 switch (status) { 1372 case 0: 1373 /* success */ 1374 break; 1375 case -ECONNRESET: 1376 case -ENOENT: 1377 case -ESHUTDOWN: 1378 /* this urb is terminated, clean up */ 1379 dbg("%s - urb shutting down with status: %d", 1380 __func__, status); 1381 priv->write_urb_in_use = 0; 1382 return; 1383 case -EPIPE: /* no break needed; clear halt and resubmit */ 1384 if (!priv->comm_is_ok) 1385 break; 1386 usb_clear_halt(port->serial->dev, 0x02); 1387 /* error in the urb, so we have to resubmit it */ 1388 dbg("%s - nonzero write bulk status received: %d", 1389 __func__, status); 1390 port->interrupt_out_urb->transfer_buffer_length = 1; 1391 port->interrupt_out_urb->dev = port->serial->dev; 1392 result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC); 1393 if (!result) 1394 return; 1395 dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n", 1396 __func__, result); 1397 cypress_set_dead(port); 1398 break; 1399 default: 1400 dev_err(&urb->dev->dev,"%s - unexpected nonzero write status received: %d\n", 1401 __func__, status); 1402 cypress_set_dead(port); 1403 break; 1404 } 1405 1406 priv->write_urb_in_use = 0; 1407 1408 /* send any buffered data */ 1409 cypress_send(port); 1410} 1411 1412 1413/***************************************************************************** 1414 * Write buffer functions - buffering code from pl2303 used 1415 *****************************************************************************/ 1416 1417/* 1418 * cypress_buf_alloc 1419 * 1420 * Allocate a circular buffer and all associated memory. 1421 */ 1422 1423static struct cypress_buf *cypress_buf_alloc(unsigned int size) 1424{ 1425 1426 struct cypress_buf *cb; 1427 1428 1429 if (size == 0) 1430 return NULL; 1431 1432 cb = kmalloc(sizeof(struct cypress_buf), GFP_KERNEL); 1433 if (cb == NULL) 1434 return NULL; 1435 1436 cb->buf_buf = kmalloc(size, GFP_KERNEL); 1437 if (cb->buf_buf == NULL) { 1438 kfree(cb); 1439 return NULL; 1440 } 1441 1442 cb->buf_size = size; 1443 cb->buf_get = cb->buf_put = cb->buf_buf; 1444 1445 return cb; 1446 1447} 1448 1449 1450/* 1451 * cypress_buf_free 1452 * 1453 * Free the buffer and all associated memory. 1454 */ 1455 1456static void cypress_buf_free(struct cypress_buf *cb) 1457{ 1458 if (cb) { 1459 kfree(cb->buf_buf); 1460 kfree(cb); 1461 } 1462} 1463 1464 1465/* 1466 * cypress_buf_clear 1467 * 1468 * Clear out all data in the circular buffer. 1469 */ 1470 1471static void cypress_buf_clear(struct cypress_buf *cb) 1472{ 1473 if (cb != NULL) 1474 cb->buf_get = cb->buf_put; 1475 /* equivalent to a get of all data available */ 1476} 1477 1478 1479/* 1480 * cypress_buf_data_avail 1481 * 1482 * Return the number of bytes of data available in the circular 1483 * buffer. 1484 */ 1485 1486static unsigned int cypress_buf_data_avail(struct cypress_buf *cb) 1487{ 1488 if (cb != NULL) 1489 return ((cb->buf_size + cb->buf_put - cb->buf_get) % cb->buf_size); 1490 else 1491 return 0; 1492} 1493 1494 1495/* 1496 * cypress_buf_space_avail 1497 * 1498 * Return the number of bytes of space available in the circular 1499 * buffer. 1500 */ 1501 1502static unsigned int cypress_buf_space_avail(struct cypress_buf *cb) 1503{ 1504 if (cb != NULL) 1505 return ((cb->buf_size + cb->buf_get - cb->buf_put - 1) % cb->buf_size); 1506 else 1507 return 0; 1508} 1509 1510 1511/* 1512 * cypress_buf_put 1513 * 1514 * Copy data data from a user buffer and put it into the circular buffer. 1515 * Restrict to the amount of space available. 1516 * 1517 * Return the number of bytes copied. 1518 */ 1519 1520static unsigned int cypress_buf_put(struct cypress_buf *cb, const char *buf, 1521 unsigned int count) 1522{ 1523 1524 unsigned int len; 1525 1526 1527 if (cb == NULL) 1528 return 0; 1529 1530 len = cypress_buf_space_avail(cb); 1531 if (count > len) 1532 count = len; 1533 1534 if (count == 0) 1535 return 0; 1536 1537 len = cb->buf_buf + cb->buf_size - cb->buf_put; 1538 if (count > len) { 1539 memcpy(cb->buf_put, buf, len); 1540 memcpy(cb->buf_buf, buf+len, count - len); 1541 cb->buf_put = cb->buf_buf + count - len; 1542 } else { 1543 memcpy(cb->buf_put, buf, count); 1544 if (count < len) 1545 cb->buf_put += count; 1546 else /* count == len */ 1547 cb->buf_put = cb->buf_buf; 1548 } 1549 1550 return count; 1551 1552} 1553 1554 1555/* 1556 * cypress_buf_get 1557 * 1558 * Get data from the circular buffer and copy to the given buffer. 1559 * Restrict to the amount of data available. 1560 * 1561 * Return the number of bytes copied. 1562 */ 1563 1564static unsigned int cypress_buf_get(struct cypress_buf *cb, char *buf, 1565 unsigned int count) 1566{ 1567 1568 unsigned int len; 1569 1570 1571 if (cb == NULL) 1572 return 0; 1573 1574 len = cypress_buf_data_avail(cb); 1575 if (count > len) 1576 count = len; 1577 1578 if (count == 0) 1579 return 0; 1580 1581 len = cb->buf_buf + cb->buf_size - cb->buf_get; 1582 if (count > len) { 1583 memcpy(buf, cb->buf_get, len); 1584 memcpy(buf+len, cb->buf_buf, count - len); 1585 cb->buf_get = cb->buf_buf + count - len; 1586 } else { 1587 memcpy(buf, cb->buf_get, count); 1588 if (count < len) 1589 cb->buf_get += count; 1590 else /* count == len */ 1591 cb->buf_get = cb->buf_buf; 1592 } 1593 1594 return count; 1595 1596} 1597 1598/***************************************************************************** 1599 * Module functions 1600 *****************************************************************************/ 1601 1602static int __init cypress_init(void) 1603{ 1604 int retval; 1605 1606 dbg("%s", __func__); 1607 1608 retval = usb_serial_register(&cypress_earthmate_device); 1609 if (retval) 1610 goto failed_em_register; 1611 retval = usb_serial_register(&cypress_hidcom_device); 1612 if (retval) 1613 goto failed_hidcom_register; 1614 retval = usb_serial_register(&cypress_ca42v2_device); 1615 if (retval) 1616 goto failed_ca42v2_register; 1617 retval = usb_register(&cypress_driver); 1618 if (retval) 1619 goto failed_usb_register; 1620 1621 info(DRIVER_DESC " " DRIVER_VERSION); 1622 return 0; 1623 1624failed_usb_register: 1625 usb_serial_deregister(&cypress_ca42v2_device); 1626failed_ca42v2_register: 1627 usb_serial_deregister(&cypress_hidcom_device); 1628failed_hidcom_register: 1629 usb_serial_deregister(&cypress_earthmate_device); 1630failed_em_register: 1631 return retval; 1632} 1633 1634 1635static void __exit cypress_exit (void) 1636{ 1637 dbg("%s", __func__); 1638 1639 usb_deregister (&cypress_driver); 1640 usb_serial_deregister (&cypress_earthmate_device); 1641 usb_serial_deregister (&cypress_hidcom_device); 1642 usb_serial_deregister (&cypress_ca42v2_device); 1643} 1644 1645 1646module_init(cypress_init); 1647module_exit(cypress_exit); 1648 1649MODULE_AUTHOR( DRIVER_AUTHOR ); 1650MODULE_DESCRIPTION( DRIVER_DESC ); 1651MODULE_VERSION( DRIVER_VERSION ); 1652MODULE_LICENSE("GPL"); 1653 1654module_param(debug, bool, S_IRUGO | S_IWUSR); 1655MODULE_PARM_DESC(debug, "Debug enabled or not"); 1656module_param(stats, bool, S_IRUGO | S_IWUSR); 1657MODULE_PARM_DESC(stats, "Enable statistics or not"); 1658module_param(interval, int, S_IRUGO | S_IWUSR); 1659MODULE_PARM_DESC(interval, "Overrides interrupt interval");