X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fusb%2Fserial%2Fcypress_m8.c;h=22837a3f2f899e963f0d944814d222bcd2e494f5;hb=18dd36af0010dd70c8634cdca0f99b47b5036c60;hp=32121794808dd5f964ca61143503bc92b6b5b016;hpb=cf867ac375cea7c7a834eaddaf373e2662d9e260;p=linux-2.6-omap-h63xx.git diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 32121794808..22837a3f2f8 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -2,7 +2,7 @@ * USB Cypress M8 driver * * Copyright (C) 2004 - * Lonnie Mendez (dignome@gmail.com) + * Lonnie Mendez (dignome@gmail.com) * Copyright (C) 2003,2004 * Neil Whelchel (koyama@firstlight.net) * @@ -11,19 +11,21 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * See Documentation/usb/usb-serial.txt for more information on using this driver + * See Documentation/usb/usb-serial.txt for more information on using this + * driver * * See http://geocities.com/i0xox0i for information on this driver and the * earthmate usb device. * * Lonnie Mendez * 4-29-2005 - * Fixed problem where setting or retreiving the serial config would fail with - * EPIPE. Removed CRTS toggling so the driver behaves more like other usbserial - * adapters. Issued new interval of 1ms instead of the default 10ms. As a - * result, transfer speed has been substantially increased. From avg. 850bps to - * avg. 3300bps. initial termios has also been modified. Cleaned up code and - * formatting issues so it is more readable. Replaced the C++ style comments. + * Fixed problem where setting or retreiving the serial config would fail + * with EPIPE. Removed CRTS toggling so the driver behaves more like + * other usbserial adapters. Issued new interval of 1ms instead of the + * default 10ms. As a result, transfer speed has been substantially + * increased from avg. 850bps to avg. 3300bps. initial termios has also + * been modified. Cleaned up code and formatting issues so it is more + * readable. Replaced the C++ style comments. * * Lonnie Mendez * 12-15-2004 @@ -42,10 +44,11 @@ * */ -/* Thanks to Neil Whelchel for writing the first cypress m8 implementation for linux. */ +/* Thanks to Neil Whelchel for writing the first cypress m8 implementation + for linux. */ /* Thanks to cypress for providing references for the hid reports. */ /* Thanks to Jiang Zhang for providing links and for general help. */ -/* Code originates and was built up from ftdi_sio, belkin, pl2303 and others. */ +/* Code originates and was built up from ftdi_sio, belkin, pl2303 and others.*/ #include @@ -62,7 +65,7 @@ #include #include #include -#include +#include #include "cypress_m8.h" @@ -112,7 +115,7 @@ static struct usb_device_id id_table_combined [] = { { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, id_table_combined); +MODULE_DEVICE_TABLE(usb, id_table_combined); static struct usb_driver cypress_driver = { .name = "cypress", @@ -146,11 +149,13 @@ struct cypress_private { __u8 rx_flags; /* throttling - used from whiteheat/ftdi_sio */ enum packet_format pkt_fmt; /* format to use for packet send / receive */ int get_cfg_unsafe; /* If true, the CYPRESS_GET_CONFIG is unsafe */ - int baud_rate; /* stores current baud rate in integer form */ + int baud_rate; /* stores current baud rate in + integer form */ int isthrottled; /* if throttled, discard reads */ wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */ char prev_status, diff_status; /* used for TIOCMIWAIT */ - /* we pass a pointer to this as the arguement sent to cypress_set_termios old_termios */ + /* we pass a pointer to this as the arguement sent to + cypress_set_termios old_termios */ struct ktermios tmp_termios; /* stores the old termios settings */ }; @@ -163,33 +168,41 @@ struct cypress_buf { }; /* function prototypes for the Cypress USB to serial device */ -static int cypress_earthmate_startup (struct usb_serial *serial); -static int cypress_hidcom_startup (struct usb_serial *serial); -static int cypress_ca42v2_startup (struct usb_serial *serial); -static void cypress_shutdown (struct usb_serial *serial); -static int cypress_open (struct usb_serial_port *port, struct file *filp); -static void cypress_close (struct usb_serial_port *port, struct file *filp); -static int cypress_write (struct usb_serial_port *port, const unsigned char *buf, int count); -static void cypress_send (struct usb_serial_port *port); -static int cypress_write_room (struct usb_serial_port *port); -static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); -static void cypress_set_termios (struct usb_serial_port *port, struct ktermios * old); -static int cypress_tiocmget (struct usb_serial_port *port, struct file *file); -static int cypress_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); -static int cypress_chars_in_buffer (struct usb_serial_port *port); -static void cypress_throttle (struct usb_serial_port *port); -static void cypress_unthrottle (struct usb_serial_port *port); -static void cypress_set_dead (struct usb_serial_port *port); -static void cypress_read_int_callback (struct urb *urb); -static void cypress_write_int_callback (struct urb *urb); +static int cypress_earthmate_startup(struct usb_serial *serial); +static int cypress_hidcom_startup(struct usb_serial *serial); +static int cypress_ca42v2_startup(struct usb_serial *serial); +static void cypress_shutdown(struct usb_serial *serial); +static int cypress_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static void cypress_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp); +static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count); +static void cypress_send(struct usb_serial_port *port); +static int cypress_write_room(struct tty_struct *tty); +static int cypress_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg); +static void cypress_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old); +static int cypress_tiocmget(struct tty_struct *tty, struct file *file); +static int cypress_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear); +static int cypress_chars_in_buffer(struct tty_struct *tty); +static void cypress_throttle(struct tty_struct *tty); +static void cypress_unthrottle(struct tty_struct *tty); +static void cypress_set_dead(struct usb_serial_port *port); +static void cypress_read_int_callback(struct urb *urb); +static void cypress_write_int_callback(struct urb *urb); /* write buffer functions */ static struct cypress_buf *cypress_buf_alloc(unsigned int size); -static void cypress_buf_free(struct cypress_buf *cb); -static void cypress_buf_clear(struct cypress_buf *cb); -static unsigned int cypress_buf_data_avail(struct cypress_buf *cb); -static unsigned int cypress_buf_space_avail(struct cypress_buf *cb); -static unsigned int cypress_buf_put(struct cypress_buf *cb, const char *buf, unsigned int count); -static unsigned int cypress_buf_get(struct cypress_buf *cb, char *buf, unsigned int count); +static void cypress_buf_free(struct cypress_buf *cb); +static void cypress_buf_clear(struct cypress_buf *cb); +static unsigned int cypress_buf_data_avail(struct cypress_buf *cb); +static unsigned int cypress_buf_space_avail(struct cypress_buf *cb); +static unsigned int cypress_buf_put(struct cypress_buf *cb, + const char *buf, unsigned int count); +static unsigned int cypress_buf_get(struct cypress_buf *cb, + char *buf, unsigned int count); static struct usb_serial_driver cypress_earthmate_device = { @@ -247,7 +260,7 @@ static struct usb_serial_driver cypress_hidcom_device = { static struct usb_serial_driver cypress_ca42v2_device = { .driver = { .owner = THIS_MODULE, - .name = "nokiaca42v2", + .name = "nokiaca42v2", }, .description = "Nokia CA-42 V2 Adapter", .usb_driver = &cypress_driver, @@ -322,8 +335,10 @@ static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate) /* This function can either set or retrieve the current serial line settings */ -static int cypress_serial_control (struct usb_serial_port *port, speed_t baud_rate, int data_bits, int stop_bits, - int parity_enable, int parity_type, int reset, int cypress_request_type) +static int cypress_serial_control(struct tty_struct *tty, + struct usb_serial_port *port, speed_t baud_rate, int data_bits, + int stop_bits, int parity_enable, int parity_type, int reset, + int cypress_request_type) { int new_baudrate = 0, retval = 0, tries = 0; struct cypress_private *priv; @@ -331,111 +346,114 @@ static int cypress_serial_control (struct usb_serial_port *port, speed_t baud_ra unsigned long flags; dbg("%s", __func__); - + priv = usb_get_serial_port_data(port); if (!priv->comm_is_ok) return -ENODEV; - switch(cypress_request_type) { - case CYPRESS_SET_CONFIG: + switch (cypress_request_type) { + case CYPRESS_SET_CONFIG: + new_baudrate = priv->baud_rate; + /* 0 means 'Hang up' so doesn't change the true bit rate */ + if (baud_rate == 0) new_baudrate = priv->baud_rate; - /* 0 means 'Hang up' so doesn't change the true bit rate */ - if (baud_rate == 0) - new_baudrate = priv->baud_rate; - /* Change of speed ? */ - else if (baud_rate != priv->baud_rate) { - dbg("%s - baud rate is changing", __func__); - retval = analyze_baud_rate(port, baud_rate); - if (retval >= 0) { - new_baudrate = retval; - dbg("%s - New baud rate set to %d", - __func__, new_baudrate); - } - } - dbg("%s - baud rate is being sent as %d", __func__, new_baudrate); - - memset(feature_buffer, 0, sizeof(feature_buffer)); - /* fill the feature_buffer with new configuration */ - *((u_int32_t *)feature_buffer) = new_baudrate; - - feature_buffer[4] |= data_bits; /* assign data bits in 2 bit space ( max 3 ) */ - /* 1 bit gap */ - feature_buffer[4] |= (stop_bits << 3); /* assign stop bits in 1 bit space */ - feature_buffer[4] |= (parity_enable << 4); /* assign parity flag in 1 bit space */ - feature_buffer[4] |= (parity_type << 5); /* assign parity type in 1 bit space */ - /* 1 bit gap */ - feature_buffer[4] |= (reset << 7); /* assign reset at end of byte, 1 bit space */ - - dbg("%s - device is being sent this feature report:", __func__); - dbg("%s - %02X - %02X - %02X - %02X - %02X", __func__, feature_buffer[0], feature_buffer[1], - feature_buffer[2], feature_buffer[3], feature_buffer[4]); - - do { - retval = usb_control_msg(port->serial->dev, - usb_sndctrlpipe(port->serial->dev, 0), - HID_REQ_SET_REPORT, - USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS, - 0x0300, 0, feature_buffer, - sizeof(feature_buffer), 500); - - if (tries++ >= 3) - break; - - } while (retval != sizeof(feature_buffer) && - retval != -ENODEV); - - if (retval != sizeof(feature_buffer)) { - err("%s - failed sending serial line settings - %d", __func__, retval); - cypress_set_dead(port); - } else { - spin_lock_irqsave(&priv->lock, flags); - priv->baud_rate = new_baudrate; - priv->current_config = feature_buffer[4]; - spin_unlock_irqrestore(&priv->lock, flags); - /* If we asked for a speed change encode it */ - if (baud_rate) - tty_encode_baud_rate(port->tty, - new_baudrate, new_baudrate); - } - break; - case CYPRESS_GET_CONFIG: - if (priv->get_cfg_unsafe) { - /* Not implemented for this device, - and if we try to do it we're likely - to crash the hardware. */ - return -ENOTTY; - } - dbg("%s - retreiving serial line settings", __func__); - /* set initial values in feature buffer */ - memset(feature_buffer, 0, sizeof(feature_buffer)); - - do { - retval = usb_control_msg(port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0), - HID_REQ_GET_REPORT, - USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS, - 0x0300, 0, feature_buffer, - sizeof(feature_buffer), 500); - - if (tries++ >= 3) - break; - - } while (retval != sizeof(feature_buffer) && - retval != -ENODEV); - - if (retval != sizeof(feature_buffer)) { - err("%s - failed to retrieve serial line settings - %d", __func__, retval); - cypress_set_dead(port); - return retval; - } else { - spin_lock_irqsave(&priv->lock, flags); - - /* store the config in one byte, and later use bit masks to check values */ - priv->current_config = feature_buffer[4]; - priv->baud_rate = *((u_int32_t *)feature_buffer); - spin_unlock_irqrestore(&priv->lock, flags); + /* Change of speed ? */ + else if (baud_rate != priv->baud_rate) { + dbg("%s - baud rate is changing", __func__); + retval = analyze_baud_rate(port, baud_rate); + if (retval >= 0) { + new_baudrate = retval; + dbg("%s - New baud rate set to %d", + __func__, new_baudrate); } + } + dbg("%s - baud rate is being sent as %d", + __func__, new_baudrate); + + memset(feature_buffer, 0, sizeof(feature_buffer)); + /* fill the feature_buffer with new configuration */ + *((u_int32_t *)feature_buffer) = new_baudrate; + feature_buffer[4] |= data_bits; /* assign data bits in 2 bit space ( max 3 ) */ + /* 1 bit gap */ + feature_buffer[4] |= (stop_bits << 3); /* assign stop bits in 1 bit space */ + feature_buffer[4] |= (parity_enable << 4); /* assign parity flag in 1 bit space */ + feature_buffer[4] |= (parity_type << 5); /* assign parity type in 1 bit space */ + /* 1 bit gap */ + feature_buffer[4] |= (reset << 7); /* assign reset at end of byte, 1 bit space */ + + dbg("%s - device is being sent this feature report:", + __func__); + dbg("%s - %02X - %02X - %02X - %02X - %02X", __func__, + feature_buffer[0], feature_buffer[1], + feature_buffer[2], feature_buffer[3], + feature_buffer[4]); + + do { + retval = usb_control_msg(port->serial->dev, + usb_sndctrlpipe(port->serial->dev, 0), + HID_REQ_SET_REPORT, + USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS, + 0x0300, 0, feature_buffer, + sizeof(feature_buffer), 500); + + if (tries++ >= 3) + break; + + } while (retval != sizeof(feature_buffer) && + retval != -ENODEV); + + if (retval != sizeof(feature_buffer)) { + err("%s - failed sending serial line settings - %d", + __func__, retval); + cypress_set_dead(port); + } else { + spin_lock_irqsave(&priv->lock, flags); + priv->baud_rate = new_baudrate; + priv->current_config = feature_buffer[4]; + spin_unlock_irqrestore(&priv->lock, flags); + /* If we asked for a speed change encode it */ + if (baud_rate) + tty_encode_baud_rate(tty, + new_baudrate, new_baudrate); + } + break; + case CYPRESS_GET_CONFIG: + if (priv->get_cfg_unsafe) { + /* Not implemented for this device, + and if we try to do it we're likely + to crash the hardware. */ + return -ENOTTY; + } + dbg("%s - retreiving serial line settings", __func__); + /* set initial values in feature buffer */ + memset(feature_buffer, 0, sizeof(feature_buffer)); + + do { + retval = usb_control_msg(port->serial->dev, + usb_rcvctrlpipe(port->serial->dev, 0), + HID_REQ_GET_REPORT, + USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS, + 0x0300, 0, feature_buffer, + sizeof(feature_buffer), 500); + + if (tries++ >= 3) + break; + } while (retval != sizeof(feature_buffer) + && retval != -ENODEV); + + if (retval != sizeof(feature_buffer)) { + err("%s - failed to retrieve serial line settings - %d", __func__, retval); + cypress_set_dead(port); + return retval; + } else { + spin_lock_irqsave(&priv->lock, flags); + /* store the config in one byte, and later + use bit masks to check values */ + priv->current_config = feature_buffer[4]; + priv->baud_rate = *((u_int32_t *)feature_buffer); + spin_unlock_irqrestore(&priv->lock, flags); + } } spin_lock_irqsave(&priv->lock, flags); ++priv->cmd_count; @@ -468,14 +486,14 @@ static void cypress_set_dead(struct usb_serial_port *port) *****************************************************************************/ -static int generic_startup (struct usb_serial *serial) +static int generic_startup(struct usb_serial *serial) { struct cypress_private *priv; struct usb_serial_port *port = serial->port[0]; dbg("%s - port %d", __func__, port->number); - priv = kzalloc(sizeof (struct cypress_private), GFP_KERNEL); + priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -487,9 +505,9 @@ static int generic_startup (struct usb_serial *serial) return -ENOMEM; } init_waitqueue_head(&priv->delta_msr_wait); - - usb_reset_configuration (serial->dev); - + + usb_reset_configuration(serial->dev); + priv->cmd_ctrl = 0; priv->line_control = 0; priv->termios_initialized = 0; @@ -500,30 +518,30 @@ static int generic_startup (struct usb_serial *serial) small. Otherwise we can use the slightly more compact format. This is in accordance with the cypress_m8 serial converter app note. */ - if (port->interrupt_out_size > 9) { + if (port->interrupt_out_size > 9) priv->pkt_fmt = packet_format_1; - } else { + else priv->pkt_fmt = packet_format_2; - } + if (interval > 0) { priv->write_urb_interval = interval; priv->read_urb_interval = interval; dbg("%s - port %d read & write intervals forced to %d", - __func__,port->number,interval); + __func__, port->number, interval); } else { priv->write_urb_interval = port->interrupt_out_urb->interval; priv->read_urb_interval = port->interrupt_in_urb->interval; dbg("%s - port %d intervals: read=%d write=%d", - __func__,port->number, - priv->read_urb_interval,priv->write_urb_interval); + __func__, port->number, + priv->read_urb_interval, priv->write_urb_interval); } usb_set_serial_port_data(port, priv); - + return 0; } -static int cypress_earthmate_startup (struct usb_serial *serial) +static int cypress_earthmate_startup(struct usb_serial *serial) { struct cypress_private *priv; struct usb_serial_port *port = serial->port[0]; @@ -541,7 +559,8 @@ static int cypress_earthmate_startup (struct usb_serial *serial) /* All Earthmate devices use the separated-count packet format! Idiotic. */ priv->pkt_fmt = packet_format_1; - if (serial->dev->descriptor.idProduct != PRODUCT_ID_EARTHMATEUSB) { + if (serial->dev->descriptor.idProduct != + cpu_to_le16(PRODUCT_ID_EARTHMATEUSB)) { /* The old original USB Earthmate seemed able to handle GET_CONFIG requests; everything they've produced since that time crashes if this command is @@ -555,7 +574,7 @@ static int cypress_earthmate_startup (struct usb_serial *serial) } /* cypress_earthmate_startup */ -static int cypress_hidcom_startup (struct usb_serial *serial) +static int cypress_hidcom_startup(struct usb_serial *serial) { struct cypress_private *priv; @@ -569,12 +588,12 @@ static int cypress_hidcom_startup (struct usb_serial *serial) priv = usb_get_serial_port_data(serial->port[0]); priv->chiptype = CT_CYPHIDCOM; - + return 0; } /* cypress_hidcom_startup */ -static int cypress_ca42v2_startup (struct usb_serial *serial) +static int cypress_ca42v2_startup(struct usb_serial *serial) { struct cypress_private *priv; @@ -593,11 +612,11 @@ static int cypress_ca42v2_startup (struct usb_serial *serial) } /* cypress_ca42v2_startup */ -static void cypress_shutdown (struct usb_serial *serial) +static void cypress_shutdown(struct usb_serial *serial) { struct cypress_private *priv; - dbg ("%s - port %d", __func__, serial->port[0]->number); + dbg("%s - port %d", __func__, serial->port[0]->number); /* all open ports are closed at this point */ @@ -611,7 +630,8 @@ static void cypress_shutdown (struct usb_serial *serial) } -static int cypress_open (struct usb_serial_port *port, struct file *filp) +static int cypress_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct cypress_private *priv = usb_get_serial_port_data(port); struct usb_serial *serial = port->serial; @@ -636,37 +656,44 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp) spin_unlock_irqrestore(&priv->lock, flags); /* setting to zero could cause data loss */ - port->tty->low_latency = 1; + if (tty) + tty->low_latency = 1; /* raise both lines and set termios */ spin_lock_irqsave(&priv->lock, flags); priv->line_control = CONTROL_DTR | CONTROL_RTS; priv->cmd_ctrl = 1; spin_unlock_irqrestore(&priv->lock, flags); - result = cypress_write(port, NULL, 0); + result = cypress_write(tty, port, NULL, 0); if (result) { - dev_err(&port->dev, "%s - failed setting the control lines - error %d\n", __func__, result); + dev_err(&port->dev, + "%s - failed setting the control lines - error %d\n", + __func__, result); return result; } else dbg("%s - success setting the control lines", __func__); - cypress_set_termios(port, &priv->tmp_termios); + if (tty) + cypress_set_termios(tty, port, &priv->tmp_termios); /* setup the port and start reading from the device */ - if(!port->interrupt_in_urb){ + if (!port->interrupt_in_urb) { err("%s - interrupt_in_urb is empty!", __func__); - return(-1); + return -1; } usb_fill_int_urb(port->interrupt_in_urb, serial->dev, usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress), - port->interrupt_in_urb->transfer_buffer, port->interrupt_in_urb->transfer_buffer_length, + port->interrupt_in_urb->transfer_buffer, + port->interrupt_in_urb->transfer_buffer_length, cypress_read_int_callback, port, priv->read_urb_interval); result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); - if (result){ - dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result); + if (result) { + dev_err(&port->dev, + "%s - failed submitting read urb, error %d\n", + __func__, result); cypress_set_dead(port); } @@ -674,7 +701,8 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp) } /* cypress_open */ -static void cypress_close(struct usb_serial_port *port, struct file * filp) +static void cypress_close(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) { struct cypress_private *priv = usb_get_serial_port_data(port); unsigned int c_cflag; @@ -688,7 +716,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp) spin_lock_irq(&priv->lock); timeout = CYPRESS_CLOSING_WAIT; init_waitqueue_entry(&wait, current); - add_wait_queue(&port->tty->write_wait, &wait); + add_wait_queue(&tty->write_wait, &wait); for (;;) { set_current_state(TASK_INTERRUPTIBLE); if (cypress_buf_data_avail(priv->buf) == 0 @@ -701,7 +729,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp) spin_lock_irq(&priv->lock); } set_current_state(TASK_RUNNING); - remove_wait_queue(&port->tty->write_wait, &wait); + remove_wait_queue(&tty->write_wait, &wait); /* clear out any remaining data in the buffer */ cypress_buf_clear(priv->buf); spin_unlock_irq(&priv->lock); @@ -713,19 +741,21 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp) return; } /* wait for characters to drain from device */ - bps = tty_get_baud_rate(port->tty); - if (bps > 1200) - timeout = max((HZ*2560)/bps,HZ/10); - else - timeout = 2*HZ; - schedule_timeout_interruptible(timeout); + if (tty) { + bps = tty_get_baud_rate(tty); + if (bps > 1200) + timeout = max((HZ * 2560) / bps, HZ / 10); + else + timeout = 2 * HZ; + schedule_timeout_interruptible(timeout); + } dbg("%s - stopping urbs", __func__); - usb_kill_urb (port->interrupt_in_urb); - usb_kill_urb (port->interrupt_out_urb); + usb_kill_urb(port->interrupt_in_urb); + usb_kill_urb(port->interrupt_out_urb); - if (port->tty) { - c_cflag = port->tty->termios->c_cflag; + if (tty) { + c_cflag = tty->termios->c_cflag; if (c_cflag & HUPCL) { /* drop dtr and rts */ priv = usb_get_serial_port_data(port); @@ -733,22 +763,23 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp) priv->line_control = 0; priv->cmd_ctrl = 1; spin_unlock_irq(&priv->lock); - cypress_write(port, NULL, 0); + cypress_write(tty, port, NULL, 0); } } if (stats) - dev_info (&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n", - priv->bytes_in, priv->bytes_out, priv->cmd_count); + dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n", + priv->bytes_in, priv->bytes_out, priv->cmd_count); mutex_unlock(&port->serial->disc_mutex); } /* cypress_close */ -static int cypress_write(struct usb_serial_port *port, const unsigned char *buf, int count) +static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) { struct cypress_private *priv = usb_get_serial_port_data(port); unsigned long flags; - + dbg("%s - port %d, %d bytes", __func__, port->number, count); /* line control commands, which need to be executed immediately, @@ -758,10 +789,10 @@ static int cypress_write(struct usb_serial_port *port, const unsigned char *buf, count = 0; goto finish; } - + if (!count) return count; - + spin_lock_irqsave(&priv->lock, flags); count = cypress_buf_put(priv->buf, buf, count); spin_unlock_irqrestore(&priv->lock, flags); @@ -778,13 +809,14 @@ static void cypress_send(struct usb_serial_port *port) int count = 0, result, offset, actual_size; struct cypress_private *priv = usb_get_serial_port_data(port); unsigned long flags; - + if (!priv->comm_is_ok) return; dbg("%s - port %d", __func__, port->number); - dbg("%s - interrupt out size is %d", __func__, port->interrupt_out_size); - + dbg("%s - interrupt out size is %d", __func__, + port->interrupt_out_size); + spin_lock_irqsave(&priv->lock, flags); if (priv->write_urb_in_use) { dbg("%s - can't write, urb in use", __func__); @@ -794,7 +826,8 @@ static void cypress_send(struct usb_serial_port *port) spin_unlock_irqrestore(&priv->lock, flags); /* clear buffer */ - memset(port->interrupt_out_urb->transfer_buffer, 0, port->interrupt_out_size); + memset(port->interrupt_out_urb->transfer_buffer, 0, + port->interrupt_out_size); spin_lock_irqsave(&priv->lock, flags); switch (priv->pkt_fmt) { @@ -825,9 +858,8 @@ static void cypress_send(struct usb_serial_port *port) count = cypress_buf_get(priv->buf, &port->interrupt_out_buffer[offset], port->interrupt_out_size-offset); - if (count == 0) { + if (count == 0) return; - } switch (priv->pkt_fmt) { default: @@ -851,26 +883,29 @@ send: actual_size = count + (priv->pkt_fmt == packet_format_1 ? 2 : 1); - usb_serial_debug_data(debug, &port->dev, __func__, port->interrupt_out_size, - port->interrupt_out_urb->transfer_buffer); + usb_serial_debug_data(debug, &port->dev, __func__, + port->interrupt_out_size, + port->interrupt_out_urb->transfer_buffer); usb_fill_int_urb(port->interrupt_out_urb, port->serial->dev, usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress), port->interrupt_out_buffer, port->interrupt_out_size, cypress_write_int_callback, port, priv->write_urb_interval); - result = usb_submit_urb (port->interrupt_out_urb, GFP_ATOMIC); + result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC); if (result) { - dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, - result); + dev_err(&port->dev, + "%s - failed submitting write urb, error %d\n", + __func__, result); priv->write_urb_in_use = 0; cypress_set_dead(port); } spin_lock_irqsave(&priv->lock, flags); - if (priv->cmd_ctrl) { + if (priv->cmd_ctrl) priv->cmd_ctrl = 0; - } - priv->bytes_out += count; /* do not count the line control and size bytes */ + + /* do not count the line control and size bytes */ + priv->bytes_out += count; spin_unlock_irqrestore(&priv->lock, flags); usb_serial_port_softint(port); @@ -878,8 +913,9 @@ send: /* returns how much space is available in the soft buffer */ -static int cypress_write_room(struct usb_serial_port *port) +static int cypress_write_room(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); int room = 0; unsigned long flags; @@ -895,13 +931,14 @@ static int cypress_write_room(struct usb_serial_port *port) } -static int cypress_tiocmget (struct usb_serial_port *port, struct file *file) +static int cypress_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); __u8 status, control; unsigned int result = 0; unsigned long flags; - + dbg("%s - port %d", __func__, port->number); spin_lock_irqsave(&priv->lock, flags); @@ -922,12 +959,13 @@ static int cypress_tiocmget (struct usb_serial_port *port, struct file *file) } -static int cypress_tiocmset (struct usb_serial_port *port, struct file *file, +static int cypress_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { + struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); unsigned long flags; - + dbg("%s - port %d", __func__, port->number); spin_lock_irqsave(&priv->lock, flags); @@ -942,63 +980,60 @@ static int cypress_tiocmset (struct usb_serial_port *port, struct file *file, priv->cmd_ctrl = 1; spin_unlock_irqrestore(&priv->lock, flags); - return cypress_write(port, NULL, 0); + return cypress_write(tty, port, NULL, 0); } -static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) +static int cypress_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) { + struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd); switch (cmd) { - /* This code comes from drivers/char/serial.c and ftdi_sio.c */ - case TIOCMIWAIT: - while (priv != NULL) { - interruptible_sleep_on(&priv->delta_msr_wait); - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - else { - char diff = priv->diff_status; - - if (diff == 0) { - return -EIO; /* no change => error */ - } - - /* consume all events */ - priv->diff_status = 0; - - /* return 0 if caller wanted to know about these bits */ - if ( ((arg & TIOCM_RNG) && (diff & UART_RI)) || - ((arg & TIOCM_DSR) && (diff & UART_DSR)) || - ((arg & TIOCM_CD) && (diff & UART_CD)) || - ((arg & TIOCM_CTS) && (diff & UART_CTS)) ) { - return 0; - } - /* otherwise caller can't care less about what happened, - * and so we continue to wait for more events. - */ - } + /* This code comes from drivers/char/serial.c and ftdi_sio.c */ + case TIOCMIWAIT: + while (priv != NULL) { + interruptible_sleep_on(&priv->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + else { + char diff = priv->diff_status; + if (diff == 0) + return -EIO; /* no change => error */ + + /* consume all events */ + priv->diff_status = 0; + + /* return 0 if caller wanted to know about + these bits */ + if (((arg & TIOCM_RNG) && (diff & UART_RI)) || + ((arg & TIOCM_DSR) && (diff & UART_DSR)) || + ((arg & TIOCM_CD) && (diff & UART_CD)) || + ((arg & TIOCM_CTS) && (diff & UART_CTS))) + return 0; + /* otherwise caller can't care less about what + * happened, and so we continue to wait for + * more events. + */ } - return 0; - break; - default: - break; + } + return 0; + default: + break; } - dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __func__, cmd); - return -ENOIOCTLCMD; } /* cypress_ioctl */ -static void cypress_set_termios (struct usb_serial_port *port, - struct ktermios *old_termios) +static void cypress_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { struct cypress_private *priv = usb_get_serial_port_data(port); - struct tty_struct *tty; int data_bits, stop_bits, parity_type, parity_enable; unsigned cflag, iflag; unsigned long flags; @@ -1007,8 +1042,6 @@ static void cypress_set_termios (struct usb_serial_port *port, dbg("%s - port %d", __func__, port->number); - tty = port->tty; - spin_lock_irqsave(&priv->lock, flags); if (!priv->termios_initialized) { if (priv->chiptype == CT_EARTHMATE) { @@ -1060,28 +1093,24 @@ static void cypress_set_termios (struct usb_serial_port *port, } else parity_enable = parity_type = 0; - if (cflag & CSIZE) { - switch (cflag & CSIZE) { - case CS5: - data_bits = 0; - break; - case CS6: - data_bits = 1; - break; - case CS7: - data_bits = 2; - break; - case CS8: - data_bits = 3; - break; - default: - err("%s - CSIZE was set, but not CS5-CS8", - __func__); - data_bits = 3; - } - } else + switch (cflag & CSIZE) { + case CS5: + data_bits = 0; + break; + case CS6: + data_bits = 1; + break; + case CS7: + data_bits = 2; + break; + case CS8: data_bits = 3; - + break; + default: + err("%s - CSIZE was set, but not CS5-CS8", + __func__); + data_bits = 3; + } spin_lock_irqsave(&priv->lock, flags); oldlines = priv->line_control; if ((cflag & CBAUD) == B0) { @@ -1096,19 +1125,21 @@ static void cypress_set_termios (struct usb_serial_port *port, "%d data_bits (+5)", __func__, stop_bits, parity_enable, parity_type, data_bits); - cypress_serial_control(port, tty_get_baud_rate(tty), data_bits, stop_bits, - parity_enable, parity_type, 0, CYPRESS_SET_CONFIG); + cypress_serial_control(tty, port, tty_get_baud_rate(tty), + data_bits, stop_bits, + parity_enable, parity_type, + 0, CYPRESS_SET_CONFIG); /* we perform a CYPRESS_GET_CONFIG so that the current settings are * filled into the private structure this should confirm that all is * working if it returns what we just set */ - cypress_serial_control(port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG); + cypress_serial_control(tty, port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG); /* Here we can define custom tty settings for devices; the main tty * termios flag base comes from empeg.c */ spin_lock_irqsave(&priv->lock, flags); - if ( (priv->chiptype == CT_EARTHMATE) && (priv->baud_rate == 4800) ) { + if (priv->chiptype == CT_EARTHMATE && priv->baud_rate == 4800) { dbg("Using custom termios settings for a baud rate of " "4800bps."); /* define custom termios settings for NMEA protocol */ @@ -1142,20 +1173,21 @@ static void cypress_set_termios (struct usb_serial_port *port, /* if necessary, set lines */ if (linechange) { priv->cmd_ctrl = 1; - cypress_write(port, NULL, 0); + cypress_write(tty, port, NULL, 0); } } /* cypress_set_termios */ /* returns amount of data still left in soft buffer */ -static int cypress_chars_in_buffer(struct usb_serial_port *port) +static int cypress_chars_in_buffer(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); int chars = 0; unsigned long flags; dbg("%s - port %d", __func__, port->number); - + spin_lock_irqsave(&priv->lock, flags); chars = cypress_buf_data_avail(priv->buf); spin_unlock_irqrestore(&priv->lock, flags); @@ -1165,8 +1197,9 @@ static int cypress_chars_in_buffer(struct usb_serial_port *port) } -static void cypress_throttle (struct usb_serial_port *port) +static void cypress_throttle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); unsigned long flags; @@ -1178,8 +1211,9 @@ static void cypress_throttle (struct usb_serial_port *port) } -static void cypress_unthrottle (struct usb_serial_port *port) +static void cypress_unthrottle(struct tty_struct *tty) { + struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); int actually_throttled, result; unsigned long flags; @@ -1232,12 +1266,13 @@ static void cypress_read_int_callback(struct urb *urb) /* precursor to disconnect so just go away */ return; case -EPIPE: - usb_clear_halt(port->serial->dev,0x81); + usb_clear_halt(port->serial->dev, 0x81); break; default: /* something ugly is going on... */ - dev_err(&urb->dev->dev,"%s - unexpected nonzero read status received: %d\n", - __func__, status); + dev_err(&urb->dev->dev, + "%s - unexpected nonzero read status received: %d\n", + __func__, status); cypress_set_dead(port); return; } @@ -1251,7 +1286,7 @@ static void cypress_read_int_callback(struct urb *urb) } spin_unlock_irqrestore(&priv->lock, flags); - tty = port->tty; + tty = port->port.tty; if (!tty) { dbg("%s - bad tty pointer - exiting", __func__); return; @@ -1285,8 +1320,8 @@ static void cypress_read_int_callback(struct urb *urb) goto continue_read; } - usb_serial_debug_data (debug, &port->dev, __func__, - urb->actual_length, data); + usb_serial_debug_data(debug, &port->dev, __func__, + urb->actual_length, data); spin_lock_irqsave(&priv->lock, flags); /* check to see if status has changed */ @@ -1327,7 +1362,7 @@ static void cypress_read_int_callback(struct urb *urb) data[i]); tty_insert_flip_char(tty, data[i], tty_flag); } - tty_flip_buffer_push(port->tty); + tty_flip_buffer_push(port->port.tty); } spin_lock_irqsave(&priv->lock, flags); @@ -1339,13 +1374,14 @@ continue_read: /* Continue trying to always read... unless the port has closed. */ - if (port->open_count > 0 && priv->comm_is_ok) { + if (port->port.count > 0 && priv->comm_is_ok) { usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev, usb_rcvintpipe(port->serial->dev, port->interrupt_in_endpointAddress), port->interrupt_in_urb->transfer_buffer, port->interrupt_in_urb->transfer_buffer_length, - cypress_read_int_callback, port, priv->read_urb_interval); + cypress_read_int_callback, port, + priv->read_urb_interval); result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); if (result) { dev_err(&urb->dev->dev, "%s - failed resubmitting " @@ -1369,42 +1405,43 @@ static void cypress_write_int_callback(struct urb *urb) dbg("%s - port %d", __func__, port->number); switch (status) { - case 0: - /* success */ + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", + __func__, status); + priv->write_urb_in_use = 0; + return; + case -EPIPE: /* no break needed; clear halt and resubmit */ + if (!priv->comm_is_ok) break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __func__, status); - priv->write_urb_in_use = 0; + usb_clear_halt(port->serial->dev, 0x02); + /* error in the urb, so we have to resubmit it */ + dbg("%s - nonzero write bulk status received: %d", + __func__, status); + port->interrupt_out_urb->transfer_buffer_length = 1; + port->interrupt_out_urb->dev = port->serial->dev; + result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC); + if (!result) return; - case -EPIPE: /* no break needed; clear halt and resubmit */ - if (!priv->comm_is_ok) - break; - usb_clear_halt(port->serial->dev, 0x02); - /* error in the urb, so we have to resubmit it */ - dbg("%s - nonzero write bulk status received: %d", - __func__, status); - port->interrupt_out_urb->transfer_buffer_length = 1; - port->interrupt_out_urb->dev = port->serial->dev; - result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC); - if (!result) - return; - dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n", - __func__, result); - cypress_set_dead(port); - break; - default: - dev_err(&urb->dev->dev,"%s - unexpected nonzero write status received: %d\n", - __func__, status); - cypress_set_dead(port); - break; + dev_err(&urb->dev->dev, + "%s - failed resubmitting write urb, error %d\n", + __func__, result); + cypress_set_dead(port); + break; + default: + dev_err(&urb->dev->dev, + "%s - unexpected nonzero write status received: %d\n", + __func__, status); + cypress_set_dead(port); + break; } - priv->write_urb_in_use = 0; - + /* send any buffered data */ cypress_send(port); } @@ -1486,7 +1523,8 @@ static void cypress_buf_clear(struct cypress_buf *cb) static unsigned int cypress_buf_data_avail(struct cypress_buf *cb) { if (cb != NULL) - return ((cb->buf_size + cb->buf_put - cb->buf_get) % cb->buf_size); + return (cb->buf_size + cb->buf_put - cb->buf_get) + % cb->buf_size; else return 0; } @@ -1502,7 +1540,8 @@ static unsigned int cypress_buf_data_avail(struct cypress_buf *cb) static unsigned int cypress_buf_space_avail(struct cypress_buf *cb) { if (cb != NULL) - return ((cb->buf_size + cb->buf_get - cb->buf_put - 1) % cb->buf_size); + return (cb->buf_size + cb->buf_get - cb->buf_put - 1) + % cb->buf_size; else return 0; } @@ -1602,9 +1641,9 @@ static unsigned int cypress_buf_get(struct cypress_buf *cb, char *buf, static int __init cypress_init(void) { int retval; - + dbg("%s", __func__); - + retval = usb_serial_register(&cypress_earthmate_device); if (retval) goto failed_em_register; @@ -1632,23 +1671,23 @@ failed_em_register: } -static void __exit cypress_exit (void) +static void __exit cypress_exit(void) { dbg("%s", __func__); - usb_deregister (&cypress_driver); - usb_serial_deregister (&cypress_earthmate_device); - usb_serial_deregister (&cypress_hidcom_device); - usb_serial_deregister (&cypress_ca42v2_device); + usb_deregister(&cypress_driver); + usb_serial_deregister(&cypress_earthmate_device); + usb_serial_deregister(&cypress_hidcom_device); + usb_serial_deregister(&cypress_ca42v2_device); } module_init(cypress_init); module_exit(cypress_exit); -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_VERSION( DRIVER_VERSION ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); module_param(debug, bool, S_IRUGO | S_IWUSR);