2 * USB Cypress M8 driver
5 * Lonnie Mendez (dignome@gmail.com)
6 * Copyright (C) 2003,2004
7 * Neil Whelchel (koyama@firstlight.net)
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.
14 * See Documentation/usb/usb-serial.txt for more information on using this
17 * See http://geocities.com/i0xox0i for information on this driver and the
18 * earthmate usb device.
20 * Lonnie Mendez <dignome@gmail.com>
22 * Fixed problem where setting or retreiving the serial config would fail
23 * with EPIPE. Removed CRTS toggling so the driver behaves more like
24 * other usbserial adapters. Issued new interval of 1ms instead of the
25 * default 10ms. As a result, transfer speed has been substantially
26 * increased from avg. 850bps to avg. 3300bps. initial termios has also
27 * been modified. Cleaned up code and formatting issues so it is more
28 * readable. Replaced the C++ style comments.
30 * Lonnie Mendez <dignome@gmail.com>
32 * Incorporated write buffering from pl2303 driver. Fixed bug with line
33 * handling so both lines are raised in cypress_open. (was dropping rts)
34 * Various code cleanups made as well along with other misc bug fixes.
36 * Lonnie Mendez <dignome@gmail.com>
38 * Driver modified to support dynamic line settings. Various improvments
43 * Driver first released.
47 /* Thanks to Neil Whelchel for writing the first cypress m8 implementation
49 /* Thanks to cypress for providing references for the hid reports. */
50 /* Thanks to Jiang Zhang for providing links and for general help. */
51 /* Code originates and was built up from ftdi_sio, belkin, pl2303 and others.*/
54 #include <linux/kernel.h>
55 #include <linux/errno.h>
56 #include <linux/init.h>
57 #include <linux/slab.h>
58 #include <linux/tty.h>
59 #include <linux/tty_driver.h>
60 #include <linux/tty_flip.h>
61 #include <linux/module.h>
62 #include <linux/moduleparam.h>
63 #include <linux/spinlock.h>
64 #include <linux/usb.h>
65 #include <linux/usb/serial.h>
66 #include <linux/serial.h>
67 #include <linux/delay.h>
68 #include <linux/uaccess.h>
70 #include "cypress_m8.h"
73 #ifdef CONFIG_USB_SERIAL_DEBUG
84 #define DRIVER_VERSION "v1.09"
85 #define DRIVER_AUTHOR "Lonnie Mendez <dignome@gmail.com>, Neil Whelchel <koyama@firstlight.net>"
86 #define DRIVER_DESC "Cypress USB to Serial Driver"
88 /* write buffer size defines */
89 #define CYPRESS_BUF_SIZE 1024
90 #define CYPRESS_CLOSING_WAIT (30*HZ)
92 static struct usb_device_id id_table_earthmate
[] = {
93 { USB_DEVICE(VENDOR_ID_DELORME
, PRODUCT_ID_EARTHMATEUSB
) },
94 { USB_DEVICE(VENDOR_ID_DELORME
, PRODUCT_ID_EARTHMATEUSB_LT20
) },
95 { } /* Terminating entry */
98 static struct usb_device_id id_table_cyphidcomrs232
[] = {
99 { USB_DEVICE(VENDOR_ID_CYPRESS
, PRODUCT_ID_CYPHIDCOM
) },
100 { USB_DEVICE(VENDOR_ID_POWERCOM
, PRODUCT_ID_UPS
) },
101 { } /* Terminating entry */
104 static struct usb_device_id id_table_nokiaca42v2
[] = {
105 { USB_DEVICE(VENDOR_ID_DAZZLE
, PRODUCT_ID_CA42
) },
106 { } /* Terminating entry */
109 static struct usb_device_id id_table_combined
[] = {
110 { USB_DEVICE(VENDOR_ID_DELORME
, PRODUCT_ID_EARTHMATEUSB
) },
111 { USB_DEVICE(VENDOR_ID_DELORME
, PRODUCT_ID_EARTHMATEUSB_LT20
) },
112 { USB_DEVICE(VENDOR_ID_CYPRESS
, PRODUCT_ID_CYPHIDCOM
) },
113 { USB_DEVICE(VENDOR_ID_POWERCOM
, PRODUCT_ID_UPS
) },
114 { USB_DEVICE(VENDOR_ID_DAZZLE
, PRODUCT_ID_CA42
) },
115 { } /* Terminating entry */
118 MODULE_DEVICE_TABLE(usb
, id_table_combined
);
120 static struct usb_driver cypress_driver
= {
122 .probe
= usb_serial_probe
,
123 .disconnect
= usb_serial_disconnect
,
124 .id_table
= id_table_combined
,
129 packet_format_1
, /* b0:status, b1:payload count */
130 packet_format_2
/* b0[7:3]:status, b0[2:0]:payload count */
133 struct cypress_private
{
134 spinlock_t lock
; /* private lock */
135 int chiptype
; /* identifier of device, for quirks/etc */
136 int bytes_in
; /* used for statistics */
137 int bytes_out
; /* used for statistics */
138 int cmd_count
; /* used for statistics */
139 int cmd_ctrl
; /* always set this to 1 before issuing a command */
140 struct cypress_buf
*buf
; /* write buffer */
141 int write_urb_in_use
; /* write urb in use indicator */
142 int write_urb_interval
; /* interval to use for write urb */
143 int read_urb_interval
; /* interval to use for read urb */
144 int comm_is_ok
; /* true if communication is (still) ok */
145 int termios_initialized
;
146 __u8 line_control
; /* holds dtr / rts value */
147 __u8 current_status
; /* received from last read - info on dsr,cts,cd,ri,etc */
148 __u8 current_config
; /* stores the current configuration byte */
149 __u8 rx_flags
; /* throttling - used from whiteheat/ftdi_sio */
150 enum packet_format pkt_fmt
; /* format to use for packet send / receive */
151 int get_cfg_unsafe
; /* If true, the CYPRESS_GET_CONFIG is unsafe */
152 int baud_rate
; /* stores current baud rate in
154 int isthrottled
; /* if throttled, discard reads */
155 wait_queue_head_t delta_msr_wait
; /* used for TIOCMIWAIT */
156 char prev_status
, diff_status
; /* used for TIOCMIWAIT */
157 /* we pass a pointer to this as the arguement sent to
158 cypress_set_termios old_termios */
159 struct ktermios tmp_termios
; /* stores the old termios settings */
162 /* write buffer structure */
164 unsigned int buf_size
;
170 /* function prototypes for the Cypress USB to serial device */
171 static int cypress_earthmate_startup(struct usb_serial
*serial
);
172 static int cypress_hidcom_startup(struct usb_serial
*serial
);
173 static int cypress_ca42v2_startup(struct usb_serial
*serial
);
174 static void cypress_shutdown(struct usb_serial
*serial
);
175 static int cypress_open(struct tty_struct
*tty
,
176 struct usb_serial_port
*port
, struct file
*filp
);
177 static void cypress_close(struct tty_struct
*tty
,
178 struct usb_serial_port
*port
, struct file
*filp
);
179 static int cypress_write(struct tty_struct
*tty
, struct usb_serial_port
*port
,
180 const unsigned char *buf
, int count
);
181 static void cypress_send(struct usb_serial_port
*port
);
182 static int cypress_write_room(struct tty_struct
*tty
);
183 static int cypress_ioctl(struct tty_struct
*tty
, struct file
*file
,
184 unsigned int cmd
, unsigned long arg
);
185 static void cypress_set_termios(struct tty_struct
*tty
,
186 struct usb_serial_port
*port
, struct ktermios
*old
);
187 static int cypress_tiocmget(struct tty_struct
*tty
, struct file
*file
);
188 static int cypress_tiocmset(struct tty_struct
*tty
, struct file
*file
,
189 unsigned int set
, unsigned int clear
);
190 static int cypress_chars_in_buffer(struct tty_struct
*tty
);
191 static void cypress_throttle(struct tty_struct
*tty
);
192 static void cypress_unthrottle(struct tty_struct
*tty
);
193 static void cypress_set_dead(struct usb_serial_port
*port
);
194 static void cypress_read_int_callback(struct urb
*urb
);
195 static void cypress_write_int_callback(struct urb
*urb
);
196 /* write buffer functions */
197 static struct cypress_buf
*cypress_buf_alloc(unsigned int size
);
198 static void cypress_buf_free(struct cypress_buf
*cb
);
199 static void cypress_buf_clear(struct cypress_buf
*cb
);
200 static unsigned int cypress_buf_data_avail(struct cypress_buf
*cb
);
201 static unsigned int cypress_buf_space_avail(struct cypress_buf
*cb
);
202 static unsigned int cypress_buf_put(struct cypress_buf
*cb
,
203 const char *buf
, unsigned int count
);
204 static unsigned int cypress_buf_get(struct cypress_buf
*cb
,
205 char *buf
, unsigned int count
);
208 static struct usb_serial_driver cypress_earthmate_device
= {
210 .owner
= THIS_MODULE
,
213 .description
= "DeLorme Earthmate USB",
214 .usb_driver
= &cypress_driver
,
215 .id_table
= id_table_earthmate
,
217 .attach
= cypress_earthmate_startup
,
218 .shutdown
= cypress_shutdown
,
219 .open
= cypress_open
,
220 .close
= cypress_close
,
221 .write
= cypress_write
,
222 .write_room
= cypress_write_room
,
223 .ioctl
= cypress_ioctl
,
224 .set_termios
= cypress_set_termios
,
225 .tiocmget
= cypress_tiocmget
,
226 .tiocmset
= cypress_tiocmset
,
227 .chars_in_buffer
= cypress_chars_in_buffer
,
228 .throttle
= cypress_throttle
,
229 .unthrottle
= cypress_unthrottle
,
230 .read_int_callback
= cypress_read_int_callback
,
231 .write_int_callback
= cypress_write_int_callback
,
234 static struct usb_serial_driver cypress_hidcom_device
= {
236 .owner
= THIS_MODULE
,
239 .description
= "HID->COM RS232 Adapter",
240 .usb_driver
= &cypress_driver
,
241 .id_table
= id_table_cyphidcomrs232
,
243 .attach
= cypress_hidcom_startup
,
244 .shutdown
= cypress_shutdown
,
245 .open
= cypress_open
,
246 .close
= cypress_close
,
247 .write
= cypress_write
,
248 .write_room
= cypress_write_room
,
249 .ioctl
= cypress_ioctl
,
250 .set_termios
= cypress_set_termios
,
251 .tiocmget
= cypress_tiocmget
,
252 .tiocmset
= cypress_tiocmset
,
253 .chars_in_buffer
= cypress_chars_in_buffer
,
254 .throttle
= cypress_throttle
,
255 .unthrottle
= cypress_unthrottle
,
256 .read_int_callback
= cypress_read_int_callback
,
257 .write_int_callback
= cypress_write_int_callback
,
260 static struct usb_serial_driver cypress_ca42v2_device
= {
262 .owner
= THIS_MODULE
,
263 .name
= "nokiaca42v2",
265 .description
= "Nokia CA-42 V2 Adapter",
266 .usb_driver
= &cypress_driver
,
267 .id_table
= id_table_nokiaca42v2
,
269 .attach
= cypress_ca42v2_startup
,
270 .shutdown
= cypress_shutdown
,
271 .open
= cypress_open
,
272 .close
= cypress_close
,
273 .write
= cypress_write
,
274 .write_room
= cypress_write_room
,
275 .ioctl
= cypress_ioctl
,
276 .set_termios
= cypress_set_termios
,
277 .tiocmget
= cypress_tiocmget
,
278 .tiocmset
= cypress_tiocmset
,
279 .chars_in_buffer
= cypress_chars_in_buffer
,
280 .throttle
= cypress_throttle
,
281 .unthrottle
= cypress_unthrottle
,
282 .read_int_callback
= cypress_read_int_callback
,
283 .write_int_callback
= cypress_write_int_callback
,
286 /*****************************************************************************
287 * Cypress serial helper functions
288 *****************************************************************************/
291 static int analyze_baud_rate(struct usb_serial_port
*port
, speed_t new_rate
)
293 struct cypress_private
*priv
;
294 priv
= usb_get_serial_port_data(port
);
297 * The general purpose firmware for the Cypress M8 allows for
298 * a maximum speed of 57600bps (I have no idea whether DeLorme
299 * chose to use the general purpose firmware or not), if you
300 * need to modify this speed setting for your own project
301 * please add your own chiptype and modify the code likewise.
302 * The Cypress HID->COM device will work successfully up to
303 * 115200bps (but the actual throughput is around 3kBps).
305 if (port
->serial
->dev
->speed
== USB_SPEED_LOW
) {
307 * Mike Isely <isely@pobox.com> 2-Feb-2008: The
308 * Cypress app note that describes this mechanism
309 * states the the low-speed part can't handle more
310 * than 800 bytes/sec, in which case 4800 baud is the
311 * safest speed for a part like that.
313 if (new_rate
> 4800) {
314 dbg("%s - failed setting baud rate, device incapable "
315 "speed %d", __func__
, new_rate
);
319 switch (priv
->chiptype
) {
321 if (new_rate
<= 600) {
322 /* 300 and 600 baud rates are supported under
323 * the generic firmware, but are not used with
324 * NMEA and SiRF protocols */
325 dbg("%s - failed setting baud rate, unsupported speed "
326 "of %d on Earthmate GPS", __func__
, new_rate
);
337 /* This function can either set or retrieve the current serial line settings */
338 static int cypress_serial_control(struct tty_struct
*tty
,
339 struct usb_serial_port
*port
, speed_t baud_rate
, int data_bits
,
340 int stop_bits
, int parity_enable
, int parity_type
, int reset
,
341 int cypress_request_type
)
343 int new_baudrate
= 0, retval
= 0, tries
= 0;
344 struct cypress_private
*priv
;
345 __u8 feature_buffer
[5];
350 priv
= usb_get_serial_port_data(port
);
352 if (!priv
->comm_is_ok
)
355 switch (cypress_request_type
) {
356 case CYPRESS_SET_CONFIG
:
357 new_baudrate
= priv
->baud_rate
;
358 /* 0 means 'Hang up' so doesn't change the true bit rate */
360 new_baudrate
= priv
->baud_rate
;
361 /* Change of speed ? */
362 else if (baud_rate
!= priv
->baud_rate
) {
363 dbg("%s - baud rate is changing", __func__
);
364 retval
= analyze_baud_rate(port
, baud_rate
);
366 new_baudrate
= retval
;
367 dbg("%s - New baud rate set to %d",
368 __func__
, new_baudrate
);
371 dbg("%s - baud rate is being sent as %d",
372 __func__
, new_baudrate
);
374 memset(feature_buffer
, 0, sizeof(feature_buffer
));
375 /* fill the feature_buffer with new configuration */
376 *((u_int32_t
*)feature_buffer
) = new_baudrate
;
377 feature_buffer
[4] |= data_bits
; /* assign data bits in 2 bit space ( max 3 ) */
379 feature_buffer
[4] |= (stop_bits
<< 3); /* assign stop bits in 1 bit space */
380 feature_buffer
[4] |= (parity_enable
<< 4); /* assign parity flag in 1 bit space */
381 feature_buffer
[4] |= (parity_type
<< 5); /* assign parity type in 1 bit space */
383 feature_buffer
[4] |= (reset
<< 7); /* assign reset at end of byte, 1 bit space */
385 dbg("%s - device is being sent this feature report:",
387 dbg("%s - %02X - %02X - %02X - %02X - %02X", __func__
,
388 feature_buffer
[0], feature_buffer
[1],
389 feature_buffer
[2], feature_buffer
[3],
393 retval
= usb_control_msg(port
->serial
->dev
,
394 usb_sndctrlpipe(port
->serial
->dev
, 0),
396 USB_DIR_OUT
| USB_RECIP_INTERFACE
| USB_TYPE_CLASS
,
397 0x0300, 0, feature_buffer
,
398 sizeof(feature_buffer
), 500);
403 } while (retval
!= sizeof(feature_buffer
) &&
406 if (retval
!= sizeof(feature_buffer
)) {
407 err("%s - failed sending serial line settings - %d",
409 cypress_set_dead(port
);
411 spin_lock_irqsave(&priv
->lock
, flags
);
412 priv
->baud_rate
= new_baudrate
;
413 priv
->current_config
= feature_buffer
[4];
414 spin_unlock_irqrestore(&priv
->lock
, flags
);
415 /* If we asked for a speed change encode it */
417 tty_encode_baud_rate(tty
,
418 new_baudrate
, new_baudrate
);
421 case CYPRESS_GET_CONFIG
:
422 if (priv
->get_cfg_unsafe
) {
423 /* Not implemented for this device,
424 and if we try to do it we're likely
425 to crash the hardware. */
428 dbg("%s - retreiving serial line settings", __func__
);
429 /* set initial values in feature buffer */
430 memset(feature_buffer
, 0, sizeof(feature_buffer
));
433 retval
= usb_control_msg(port
->serial
->dev
,
434 usb_rcvctrlpipe(port
->serial
->dev
, 0),
436 USB_DIR_IN
| USB_RECIP_INTERFACE
| USB_TYPE_CLASS
,
437 0x0300, 0, feature_buffer
,
438 sizeof(feature_buffer
), 500);
442 } while (retval
!= sizeof(feature_buffer
)
443 && retval
!= -ENODEV
);
445 if (retval
!= sizeof(feature_buffer
)) {
446 err("%s - failed to retrieve serial line settings - %d", __func__
, retval
);
447 cypress_set_dead(port
);
450 spin_lock_irqsave(&priv
->lock
, flags
);
451 /* store the config in one byte, and later
452 use bit masks to check values */
453 priv
->current_config
= feature_buffer
[4];
454 priv
->baud_rate
= *((u_int32_t
*)feature_buffer
);
455 spin_unlock_irqrestore(&priv
->lock
, flags
);
458 spin_lock_irqsave(&priv
->lock
, flags
);
460 spin_unlock_irqrestore(&priv
->lock
, flags
);
463 } /* cypress_serial_control */
466 static void cypress_set_dead(struct usb_serial_port
*port
)
468 struct cypress_private
*priv
= usb_get_serial_port_data(port
);
471 spin_lock_irqsave(&priv
->lock
, flags
);
472 if (!priv
->comm_is_ok
) {
473 spin_unlock_irqrestore(&priv
->lock
, flags
);
476 priv
->comm_is_ok
= 0;
477 spin_unlock_irqrestore(&priv
->lock
, flags
);
479 err("cypress_m8 suspending failing port %d - interval might be too short",
484 /*****************************************************************************
485 * Cypress serial driver functions
486 *****************************************************************************/
489 static int generic_startup(struct usb_serial
*serial
)
491 struct cypress_private
*priv
;
492 struct usb_serial_port
*port
= serial
->port
[0];
494 dbg("%s - port %d", __func__
, port
->number
);
496 priv
= kzalloc(sizeof(struct cypress_private
), GFP_KERNEL
);
500 priv
->comm_is_ok
= !0;
501 spin_lock_init(&priv
->lock
);
502 priv
->buf
= cypress_buf_alloc(CYPRESS_BUF_SIZE
);
503 if (priv
->buf
== NULL
) {
507 init_waitqueue_head(&priv
->delta_msr_wait
);
509 usb_reset_configuration(serial
->dev
);
512 priv
->line_control
= 0;
513 priv
->termios_initialized
= 0;
515 /* Default packet format setting is determined by packet size.
516 Anything with a size larger then 9 must have a separate
517 count field since the 3 bit count field is otherwise too
518 small. Otherwise we can use the slightly more compact
519 format. This is in accordance with the cypress_m8 serial
520 converter app note. */
521 if (port
->interrupt_out_size
> 9)
522 priv
->pkt_fmt
= packet_format_1
;
524 priv
->pkt_fmt
= packet_format_2
;
527 priv
->write_urb_interval
= interval
;
528 priv
->read_urb_interval
= interval
;
529 dbg("%s - port %d read & write intervals forced to %d",
530 __func__
, port
->number
, interval
);
532 priv
->write_urb_interval
= port
->interrupt_out_urb
->interval
;
533 priv
->read_urb_interval
= port
->interrupt_in_urb
->interval
;
534 dbg("%s - port %d intervals: read=%d write=%d",
535 __func__
, port
->number
,
536 priv
->read_urb_interval
, priv
->write_urb_interval
);
538 usb_set_serial_port_data(port
, priv
);
544 static int cypress_earthmate_startup(struct usb_serial
*serial
)
546 struct cypress_private
*priv
;
547 struct usb_serial_port
*port
= serial
->port
[0];
551 if (generic_startup(serial
)) {
552 dbg("%s - Failed setting up port %d", __func__
,
557 priv
= usb_get_serial_port_data(port
);
558 priv
->chiptype
= CT_EARTHMATE
;
559 /* All Earthmate devices use the separated-count packet
561 priv
->pkt_fmt
= packet_format_1
;
562 if (serial
->dev
->descriptor
.idProduct
!=
563 cpu_to_le16(PRODUCT_ID_EARTHMATEUSB
)) {
564 /* The old original USB Earthmate seemed able to
565 handle GET_CONFIG requests; everything they've
566 produced since that time crashes if this command is
568 dbg("%s - Marking this device as unsafe for GET_CONFIG "
569 "commands", __func__
);
570 priv
->get_cfg_unsafe
= !0;
574 } /* cypress_earthmate_startup */
577 static int cypress_hidcom_startup(struct usb_serial
*serial
)
579 struct cypress_private
*priv
;
583 if (generic_startup(serial
)) {
584 dbg("%s - Failed setting up port %d", __func__
,
585 serial
->port
[0]->number
);
589 priv
= usb_get_serial_port_data(serial
->port
[0]);
590 priv
->chiptype
= CT_CYPHIDCOM
;
593 } /* cypress_hidcom_startup */
596 static int cypress_ca42v2_startup(struct usb_serial
*serial
)
598 struct cypress_private
*priv
;
602 if (generic_startup(serial
)) {
603 dbg("%s - Failed setting up port %d", __func__
,
604 serial
->port
[0]->number
);
608 priv
= usb_get_serial_port_data(serial
->port
[0]);
609 priv
->chiptype
= CT_CA42V2
;
612 } /* cypress_ca42v2_startup */
615 static void cypress_shutdown(struct usb_serial
*serial
)
617 struct cypress_private
*priv
;
619 dbg("%s - port %d", __func__
, serial
->port
[0]->number
);
621 /* all open ports are closed at this point */
623 priv
= usb_get_serial_port_data(serial
->port
[0]);
626 cypress_buf_free(priv
->buf
);
628 usb_set_serial_port_data(serial
->port
[0], NULL
);
633 static int cypress_open(struct tty_struct
*tty
,
634 struct usb_serial_port
*port
, struct file
*filp
)
636 struct cypress_private
*priv
= usb_get_serial_port_data(port
);
637 struct usb_serial
*serial
= port
->serial
;
641 dbg("%s - port %d", __func__
, port
->number
);
643 if (!priv
->comm_is_ok
)
646 /* clear halts before open */
647 usb_clear_halt(serial
->dev
, 0x81);
648 usb_clear_halt(serial
->dev
, 0x02);
650 spin_lock_irqsave(&priv
->lock
, flags
);
651 /* reset read/write statistics */
656 spin_unlock_irqrestore(&priv
->lock
, flags
);
658 /* setting to zero could cause data loss */
660 tty
->low_latency
= 1;
662 /* raise both lines and set termios */
663 spin_lock_irqsave(&priv
->lock
, flags
);
664 priv
->line_control
= CONTROL_DTR
| CONTROL_RTS
;
666 spin_unlock_irqrestore(&priv
->lock
, flags
);
667 result
= cypress_write(tty
, port
, NULL
, 0);
671 "%s - failed setting the control lines - error %d\n",
675 dbg("%s - success setting the control lines", __func__
);
678 cypress_set_termios(tty
, port
, &priv
->tmp_termios
);
680 /* setup the port and start reading from the device */
681 if (!port
->interrupt_in_urb
) {
682 err("%s - interrupt_in_urb is empty!", __func__
);
686 usb_fill_int_urb(port
->interrupt_in_urb
, serial
->dev
,
687 usb_rcvintpipe(serial
->dev
, port
->interrupt_in_endpointAddress
),
688 port
->interrupt_in_urb
->transfer_buffer
,
689 port
->interrupt_in_urb
->transfer_buffer_length
,
690 cypress_read_int_callback
, port
, priv
->read_urb_interval
);
691 result
= usb_submit_urb(port
->interrupt_in_urb
, GFP_KERNEL
);
695 "%s - failed submitting read urb, error %d\n",
697 cypress_set_dead(port
);
704 static void cypress_close(struct tty_struct
*tty
,
705 struct usb_serial_port
*port
, struct file
*filp
)
707 struct cypress_private
*priv
= usb_get_serial_port_data(port
);
708 unsigned int c_cflag
;
713 dbg("%s - port %d", __func__
, port
->number
);
715 /* wait for data to drain from buffer */
716 spin_lock_irq(&priv
->lock
);
717 timeout
= CYPRESS_CLOSING_WAIT
;
718 init_waitqueue_entry(&wait
, current
);
719 add_wait_queue(&tty
->write_wait
, &wait
);
721 set_current_state(TASK_INTERRUPTIBLE
);
722 if (cypress_buf_data_avail(priv
->buf
) == 0
723 || timeout
== 0 || signal_pending(current
)
724 /* without mutex, allowed due to harmless failure mode */
725 || port
->serial
->disconnected
)
727 spin_unlock_irq(&priv
->lock
);
728 timeout
= schedule_timeout(timeout
);
729 spin_lock_irq(&priv
->lock
);
731 set_current_state(TASK_RUNNING
);
732 remove_wait_queue(&tty
->write_wait
, &wait
);
733 /* clear out any remaining data in the buffer */
734 cypress_buf_clear(priv
->buf
);
735 spin_unlock_irq(&priv
->lock
);
737 /* writing is potentially harmful, lock must be taken */
738 mutex_lock(&port
->serial
->disc_mutex
);
739 if (port
->serial
->disconnected
) {
740 mutex_unlock(&port
->serial
->disc_mutex
);
743 /* wait for characters to drain from device */
745 bps
= tty_get_baud_rate(tty
);
747 timeout
= max((HZ
* 2560) / bps
, HZ
/ 10);
750 schedule_timeout_interruptible(timeout
);
753 dbg("%s - stopping urbs", __func__
);
754 usb_kill_urb(port
->interrupt_in_urb
);
755 usb_kill_urb(port
->interrupt_out_urb
);
758 c_cflag
= tty
->termios
->c_cflag
;
759 if (c_cflag
& HUPCL
) {
760 /* drop dtr and rts */
761 priv
= usb_get_serial_port_data(port
);
762 spin_lock_irq(&priv
->lock
);
763 priv
->line_control
= 0;
765 spin_unlock_irq(&priv
->lock
);
766 cypress_write(tty
, port
, NULL
, 0);
771 dev_info(&port
->dev
, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
772 priv
->bytes_in
, priv
->bytes_out
, priv
->cmd_count
);
773 mutex_unlock(&port
->serial
->disc_mutex
);
774 } /* cypress_close */
777 static int cypress_write(struct tty_struct
*tty
, struct usb_serial_port
*port
,
778 const unsigned char *buf
, int count
)
780 struct cypress_private
*priv
= usb_get_serial_port_data(port
);
783 dbg("%s - port %d, %d bytes", __func__
, port
->number
, count
);
785 /* line control commands, which need to be executed immediately,
786 are not put into the buffer for obvious reasons.
788 if (priv
->cmd_ctrl
) {
796 spin_lock_irqsave(&priv
->lock
, flags
);
797 count
= cypress_buf_put(priv
->buf
, buf
, count
);
798 spin_unlock_irqrestore(&priv
->lock
, flags
);
804 } /* cypress_write */
807 static void cypress_send(struct usb_serial_port
*port
)
809 int count
= 0, result
, offset
, actual_size
;
810 struct cypress_private
*priv
= usb_get_serial_port_data(port
);
813 if (!priv
->comm_is_ok
)
816 dbg("%s - port %d", __func__
, port
->number
);
817 dbg("%s - interrupt out size is %d", __func__
,
818 port
->interrupt_out_size
);
820 spin_lock_irqsave(&priv
->lock
, flags
);
821 if (priv
->write_urb_in_use
) {
822 dbg("%s - can't write, urb in use", __func__
);
823 spin_unlock_irqrestore(&priv
->lock
, flags
);
826 spin_unlock_irqrestore(&priv
->lock
, flags
);
829 memset(port
->interrupt_out_urb
->transfer_buffer
, 0,
830 port
->interrupt_out_size
);
832 spin_lock_irqsave(&priv
->lock
, flags
);
833 switch (priv
->pkt_fmt
) {
835 case packet_format_1
:
836 /* this is for the CY7C64013... */
838 port
->interrupt_out_buffer
[0] = priv
->line_control
;
840 case packet_format_2
:
841 /* this is for the CY7C63743... */
843 port
->interrupt_out_buffer
[0] = priv
->line_control
;
847 if (priv
->line_control
& CONTROL_RESET
)
848 priv
->line_control
&= ~CONTROL_RESET
;
850 if (priv
->cmd_ctrl
) {
852 dbg("%s - line control command being issued", __func__
);
853 spin_unlock_irqrestore(&priv
->lock
, flags
);
856 spin_unlock_irqrestore(&priv
->lock
, flags
);
858 count
= cypress_buf_get(priv
->buf
, &port
->interrupt_out_buffer
[offset
],
859 port
->interrupt_out_size
-offset
);
864 switch (priv
->pkt_fmt
) {
866 case packet_format_1
:
867 port
->interrupt_out_buffer
[1] = count
;
869 case packet_format_2
:
870 port
->interrupt_out_buffer
[0] |= count
;
873 dbg("%s - count is %d", __func__
, count
);
876 spin_lock_irqsave(&priv
->lock
, flags
);
877 priv
->write_urb_in_use
= 1;
878 spin_unlock_irqrestore(&priv
->lock
, flags
);
883 actual_size
= count
+
884 (priv
->pkt_fmt
== packet_format_1
? 2 : 1);
886 usb_serial_debug_data(debug
, &port
->dev
, __func__
,
887 port
->interrupt_out_size
,
888 port
->interrupt_out_urb
->transfer_buffer
);
890 usb_fill_int_urb(port
->interrupt_out_urb
, port
->serial
->dev
,
891 usb_sndintpipe(port
->serial
->dev
, port
->interrupt_out_endpointAddress
),
892 port
->interrupt_out_buffer
, port
->interrupt_out_size
,
893 cypress_write_int_callback
, port
, priv
->write_urb_interval
);
894 result
= usb_submit_urb(port
->interrupt_out_urb
, GFP_ATOMIC
);
897 "%s - failed submitting write urb, error %d\n",
899 priv
->write_urb_in_use
= 0;
900 cypress_set_dead(port
);
903 spin_lock_irqsave(&priv
->lock
, flags
);
907 /* do not count the line control and size bytes */
908 priv
->bytes_out
+= count
;
909 spin_unlock_irqrestore(&priv
->lock
, flags
);
911 usb_serial_port_softint(port
);
915 /* returns how much space is available in the soft buffer */
916 static int cypress_write_room(struct tty_struct
*tty
)
918 struct usb_serial_port
*port
= tty
->driver_data
;
919 struct cypress_private
*priv
= usb_get_serial_port_data(port
);
923 dbg("%s - port %d", __func__
, port
->number
);
925 spin_lock_irqsave(&priv
->lock
, flags
);
926 room
= cypress_buf_space_avail(priv
->buf
);
927 spin_unlock_irqrestore(&priv
->lock
, flags
);
929 dbg("%s - returns %d", __func__
, room
);
934 static int cypress_tiocmget(struct tty_struct
*tty
, struct file
*file
)
936 struct usb_serial_port
*port
= tty
->driver_data
;
937 struct cypress_private
*priv
= usb_get_serial_port_data(port
);
938 __u8 status
, control
;
939 unsigned int result
= 0;
942 dbg("%s - port %d", __func__
, port
->number
);
944 spin_lock_irqsave(&priv
->lock
, flags
);
945 control
= priv
->line_control
;
946 status
= priv
->current_status
;
947 spin_unlock_irqrestore(&priv
->lock
, flags
);
949 result
= ((control
& CONTROL_DTR
) ? TIOCM_DTR
: 0)
950 | ((control
& CONTROL_RTS
) ? TIOCM_RTS
: 0)
951 | ((status
& UART_CTS
) ? TIOCM_CTS
: 0)
952 | ((status
& UART_DSR
) ? TIOCM_DSR
: 0)
953 | ((status
& UART_RI
) ? TIOCM_RI
: 0)
954 | ((status
& UART_CD
) ? TIOCM_CD
: 0);
956 dbg("%s - result = %x", __func__
, result
);
962 static int cypress_tiocmset(struct tty_struct
*tty
, struct file
*file
,
963 unsigned int set
, unsigned int clear
)
965 struct usb_serial_port
*port
= tty
->driver_data
;
966 struct cypress_private
*priv
= usb_get_serial_port_data(port
);
969 dbg("%s - port %d", __func__
, port
->number
);
971 spin_lock_irqsave(&priv
->lock
, flags
);
973 priv
->line_control
|= CONTROL_RTS
;
975 priv
->line_control
|= CONTROL_DTR
;
976 if (clear
& TIOCM_RTS
)
977 priv
->line_control
&= ~CONTROL_RTS
;
978 if (clear
& TIOCM_DTR
)
979 priv
->line_control
&= ~CONTROL_DTR
;
981 spin_unlock_irqrestore(&priv
->lock
, flags
);
983 return cypress_write(tty
, port
, NULL
, 0);
987 static int cypress_ioctl(struct tty_struct
*tty
, struct file
*file
,
988 unsigned int cmd
, unsigned long arg
)
990 struct usb_serial_port
*port
= tty
->driver_data
;
991 struct cypress_private
*priv
= usb_get_serial_port_data(port
);
993 dbg("%s - port %d, cmd 0x%.4x", __func__
, port
->number
, cmd
);
996 /* This code comes from drivers/char/serial.c and ftdi_sio.c */
998 while (priv
!= NULL
) {
999 interruptible_sleep_on(&priv
->delta_msr_wait
);
1000 /* see if a signal did it */
1001 if (signal_pending(current
))
1002 return -ERESTARTSYS
;
1004 char diff
= priv
->diff_status
;
1006 return -EIO
; /* no change => error */
1008 /* consume all events */
1009 priv
->diff_status
= 0;
1011 /* return 0 if caller wanted to know about
1013 if (((arg
& TIOCM_RNG
) && (diff
& UART_RI
)) ||
1014 ((arg
& TIOCM_DSR
) && (diff
& UART_DSR
)) ||
1015 ((arg
& TIOCM_CD
) && (diff
& UART_CD
)) ||
1016 ((arg
& TIOCM_CTS
) && (diff
& UART_CTS
)))
1018 /* otherwise caller can't care less about what
1019 * happened, and so we continue to wait for
1028 dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __func__
, cmd
);
1029 return -ENOIOCTLCMD
;
1030 } /* cypress_ioctl */
1033 static void cypress_set_termios(struct tty_struct
*tty
,
1034 struct usb_serial_port
*port
, struct ktermios
*old_termios
)
1036 struct cypress_private
*priv
= usb_get_serial_port_data(port
);
1037 int data_bits
, stop_bits
, parity_type
, parity_enable
;
1038 unsigned cflag
, iflag
;
1039 unsigned long flags
;
1043 dbg("%s - port %d", __func__
, port
->number
);
1045 spin_lock_irqsave(&priv
->lock
, flags
);
1046 if (!priv
->termios_initialized
) {
1047 if (priv
->chiptype
== CT_EARTHMATE
) {
1048 *(tty
->termios
) = tty_std_termios
;
1049 tty
->termios
->c_cflag
= B4800
| CS8
| CREAD
| HUPCL
|
1051 tty
->termios
->c_ispeed
= 4800;
1052 tty
->termios
->c_ospeed
= 4800;
1053 } else if (priv
->chiptype
== CT_CYPHIDCOM
) {
1054 *(tty
->termios
) = tty_std_termios
;
1055 tty
->termios
->c_cflag
= B9600
| CS8
| CREAD
| HUPCL
|
1057 tty
->termios
->c_ispeed
= 9600;
1058 tty
->termios
->c_ospeed
= 9600;
1059 } else if (priv
->chiptype
== CT_CA42V2
) {
1060 *(tty
->termios
) = tty_std_termios
;
1061 tty
->termios
->c_cflag
= B9600
| CS8
| CREAD
| HUPCL
|
1063 tty
->termios
->c_ispeed
= 9600;
1064 tty
->termios
->c_ospeed
= 9600;
1066 priv
->termios_initialized
= 1;
1068 spin_unlock_irqrestore(&priv
->lock
, flags
);
1070 /* Unsupported features need clearing */
1071 tty
->termios
->c_cflag
&= ~(CMSPAR
|CRTSCTS
);
1073 cflag
= tty
->termios
->c_cflag
;
1074 iflag
= tty
->termios
->c_iflag
;
1076 /* check if there are new settings */
1078 spin_lock_irqsave(&priv
->lock
, flags
);
1079 priv
->tmp_termios
= *(tty
->termios
);
1080 spin_unlock_irqrestore(&priv
->lock
, flags
);
1083 /* set number of data bits, parity, stop bits */
1084 /* when parity is disabled the parity type bit is ignored */
1086 /* 1 means 2 stop bits, 0 means 1 stop bit */
1087 stop_bits
= cflag
& CSTOPB
? 1 : 0;
1089 if (cflag
& PARENB
) {
1091 /* 1 means odd parity, 0 means even parity */
1092 parity_type
= cflag
& PARODD
? 1 : 0;
1094 parity_enable
= parity_type
= 0;
1096 switch (cflag
& CSIZE
) {
1110 err("%s - CSIZE was set, but not CS5-CS8",
1114 spin_lock_irqsave(&priv
->lock
, flags
);
1115 oldlines
= priv
->line_control
;
1116 if ((cflag
& CBAUD
) == B0
) {
1117 /* drop dtr and rts */
1118 dbg("%s - dropping the lines, baud rate 0bps", __func__
);
1119 priv
->line_control
&= ~(CONTROL_DTR
| CONTROL_RTS
);
1121 priv
->line_control
= (CONTROL_DTR
| CONTROL_RTS
);
1122 spin_unlock_irqrestore(&priv
->lock
, flags
);
1124 dbg("%s - sending %d stop_bits, %d parity_enable, %d parity_type, "
1125 "%d data_bits (+5)", __func__
, stop_bits
,
1126 parity_enable
, parity_type
, data_bits
);
1128 cypress_serial_control(tty
, port
, tty_get_baud_rate(tty
),
1129 data_bits
, stop_bits
,
1130 parity_enable
, parity_type
,
1131 0, CYPRESS_SET_CONFIG
);
1133 /* we perform a CYPRESS_GET_CONFIG so that the current settings are
1134 * filled into the private structure this should confirm that all is
1135 * working if it returns what we just set */
1136 cypress_serial_control(tty
, port
, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG
);
1138 /* Here we can define custom tty settings for devices; the main tty
1139 * termios flag base comes from empeg.c */
1141 spin_lock_irqsave(&priv
->lock
, flags
);
1142 if (priv
->chiptype
== CT_EARTHMATE
&& priv
->baud_rate
== 4800) {
1143 dbg("Using custom termios settings for a baud rate of "
1145 /* define custom termios settings for NMEA protocol */
1147 tty
->termios
->c_iflag
/* input modes - */
1148 &= ~(IGNBRK
/* disable ignore break */
1149 | BRKINT
/* disable break causes interrupt */
1150 | PARMRK
/* disable mark parity errors */
1151 | ISTRIP
/* disable clear high bit of input char */
1152 | INLCR
/* disable translate NL to CR */
1153 | IGNCR
/* disable ignore CR */
1154 | ICRNL
/* disable translate CR to NL */
1155 | IXON
); /* disable enable XON/XOFF flow control */
1157 tty
->termios
->c_oflag
/* output modes */
1158 &= ~OPOST
; /* disable postprocess output char */
1160 tty
->termios
->c_lflag
/* line discipline modes */
1161 &= ~(ECHO
/* disable echo input characters */
1162 | ECHONL
/* disable echo new line */
1163 | ICANON
/* disable erase, kill, werase, and rprnt
1164 special characters */
1165 | ISIG
/* disable interrupt, quit, and suspend
1166 special characters */
1167 | IEXTEN
); /* disable non-POSIX special characters */
1168 } /* CT_CYPHIDCOM: Application should handle this for device */
1170 linechange
= (priv
->line_control
!= oldlines
);
1171 spin_unlock_irqrestore(&priv
->lock
, flags
);
1173 /* if necessary, set lines */
1176 cypress_write(tty
, port
, NULL
, 0);
1178 } /* cypress_set_termios */
1181 /* returns amount of data still left in soft buffer */
1182 static int cypress_chars_in_buffer(struct tty_struct
*tty
)
1184 struct usb_serial_port
*port
= tty
->driver_data
;
1185 struct cypress_private
*priv
= usb_get_serial_port_data(port
);
1187 unsigned long flags
;
1189 dbg("%s - port %d", __func__
, port
->number
);
1191 spin_lock_irqsave(&priv
->lock
, flags
);
1192 chars
= cypress_buf_data_avail(priv
->buf
);
1193 spin_unlock_irqrestore(&priv
->lock
, flags
);
1195 dbg("%s - returns %d", __func__
, chars
);
1200 static void cypress_throttle(struct tty_struct
*tty
)
1202 struct usb_serial_port
*port
= tty
->driver_data
;
1203 struct cypress_private
*priv
= usb_get_serial_port_data(port
);
1204 unsigned long flags
;
1206 dbg("%s - port %d", __func__
, port
->number
);
1208 spin_lock_irqsave(&priv
->lock
, flags
);
1209 priv
->rx_flags
= THROTTLED
;
1210 spin_unlock_irqrestore(&priv
->lock
, flags
);
1214 static void cypress_unthrottle(struct tty_struct
*tty
)
1216 struct usb_serial_port
*port
= tty
->driver_data
;
1217 struct cypress_private
*priv
= usb_get_serial_port_data(port
);
1218 int actually_throttled
, result
;
1219 unsigned long flags
;
1221 dbg("%s - port %d", __func__
, port
->number
);
1223 spin_lock_irqsave(&priv
->lock
, flags
);
1224 actually_throttled
= priv
->rx_flags
& ACTUALLY_THROTTLED
;
1226 spin_unlock_irqrestore(&priv
->lock
, flags
);
1228 if (!priv
->comm_is_ok
)
1231 if (actually_throttled
) {
1232 port
->interrupt_in_urb
->dev
= port
->serial
->dev
;
1234 result
= usb_submit_urb(port
->interrupt_in_urb
, GFP_ATOMIC
);
1236 dev_err(&port
->dev
, "%s - failed submitting read urb, "
1237 "error %d\n", __func__
, result
);
1238 cypress_set_dead(port
);
1244 static void cypress_read_int_callback(struct urb
*urb
)
1246 struct usb_serial_port
*port
= urb
->context
;
1247 struct cypress_private
*priv
= usb_get_serial_port_data(port
);
1248 struct tty_struct
*tty
;
1249 unsigned char *data
= urb
->transfer_buffer
;
1250 unsigned long flags
;
1251 char tty_flag
= TTY_NORMAL
;
1256 int status
= urb
->status
;
1258 dbg("%s - port %d", __func__
, port
->number
);
1261 case 0: /* success */
1266 /* precursor to disconnect so just go away */
1269 usb_clear_halt(port
->serial
->dev
, 0x81);
1272 /* something ugly is going on... */
1273 dev_err(&urb
->dev
->dev
,
1274 "%s - unexpected nonzero read status received: %d\n",
1276 cypress_set_dead(port
);
1280 spin_lock_irqsave(&priv
->lock
, flags
);
1281 if (priv
->rx_flags
& THROTTLED
) {
1282 dbg("%s - now throttling", __func__
);
1283 priv
->rx_flags
|= ACTUALLY_THROTTLED
;
1284 spin_unlock_irqrestore(&priv
->lock
, flags
);
1287 spin_unlock_irqrestore(&priv
->lock
, flags
);
1289 tty
= port
->port
.tty
;
1291 dbg("%s - bad tty pointer - exiting", __func__
);
1295 spin_lock_irqsave(&priv
->lock
, flags
);
1296 result
= urb
->actual_length
;
1297 switch (priv
->pkt_fmt
) {
1299 case packet_format_1
:
1300 /* This is for the CY7C64013... */
1301 priv
->current_status
= data
[0] & 0xF8;
1302 bytes
= data
[1] + 2;
1307 case packet_format_2
:
1308 /* This is for the CY7C63743... */
1309 priv
->current_status
= data
[0] & 0xF8;
1310 bytes
= (data
[0] & 0x07) + 1;
1316 spin_unlock_irqrestore(&priv
->lock
, flags
);
1317 if (result
< bytes
) {
1318 dbg("%s - wrong packet size - received %d bytes but packet "
1319 "said %d bytes", __func__
, result
, bytes
);
1323 usb_serial_debug_data(debug
, &port
->dev
, __func__
,
1324 urb
->actual_length
, data
);
1326 spin_lock_irqsave(&priv
->lock
, flags
);
1327 /* check to see if status has changed */
1328 if (priv
->current_status
!= priv
->prev_status
) {
1329 priv
->diff_status
|= priv
->current_status
^
1331 wake_up_interruptible(&priv
->delta_msr_wait
);
1332 priv
->prev_status
= priv
->current_status
;
1334 spin_unlock_irqrestore(&priv
->lock
, flags
);
1336 /* hangup, as defined in acm.c... this might be a bad place for it
1338 if (tty
&& !(tty
->termios
->c_cflag
& CLOCAL
) &&
1339 !(priv
->current_status
& UART_CD
)) {
1340 dbg("%s - calling hangup", __func__
);
1345 /* There is one error bit... I'm assuming it is a parity error
1346 * indicator as the generic firmware will set this bit to 1 if a
1347 * parity error occurs.
1348 * I can not find reference to any other error events. */
1349 spin_lock_irqsave(&priv
->lock
, flags
);
1350 if (priv
->current_status
& CYP_ERROR
) {
1351 spin_unlock_irqrestore(&priv
->lock
, flags
);
1352 tty_flag
= TTY_PARITY
;
1353 dbg("%s - Parity Error detected", __func__
);
1355 spin_unlock_irqrestore(&priv
->lock
, flags
);
1357 /* process read if there is data other than line status */
1358 if (tty
&& (bytes
> i
)) {
1359 bytes
= tty_buffer_request_room(tty
, bytes
);
1360 for (; i
< bytes
; ++i
) {
1361 dbg("pushing byte number %d - %d - %c", i
, data
[i
],
1363 tty_insert_flip_char(tty
, data
[i
], tty_flag
);
1365 tty_flip_buffer_push(port
->port
.tty
);
1368 spin_lock_irqsave(&priv
->lock
, flags
);
1369 /* control and status byte(s) are also counted */
1370 priv
->bytes_in
+= bytes
;
1371 spin_unlock_irqrestore(&priv
->lock
, flags
);
1375 /* Continue trying to always read... unless the port has closed. */
1377 if (port
->port
.count
> 0 && priv
->comm_is_ok
) {
1378 usb_fill_int_urb(port
->interrupt_in_urb
, port
->serial
->dev
,
1379 usb_rcvintpipe(port
->serial
->dev
,
1380 port
->interrupt_in_endpointAddress
),
1381 port
->interrupt_in_urb
->transfer_buffer
,
1382 port
->interrupt_in_urb
->transfer_buffer_length
,
1383 cypress_read_int_callback
, port
,
1384 priv
->read_urb_interval
);
1385 result
= usb_submit_urb(port
->interrupt_in_urb
, GFP_ATOMIC
);
1387 dev_err(&urb
->dev
->dev
, "%s - failed resubmitting "
1388 "read urb, error %d\n", __func__
,
1390 cypress_set_dead(port
);
1395 } /* cypress_read_int_callback */
1398 static void cypress_write_int_callback(struct urb
*urb
)
1400 struct usb_serial_port
*port
= urb
->context
;
1401 struct cypress_private
*priv
= usb_get_serial_port_data(port
);
1403 int status
= urb
->status
;
1405 dbg("%s - port %d", __func__
, port
->number
);
1414 /* this urb is terminated, clean up */
1415 dbg("%s - urb shutting down with status: %d",
1417 priv
->write_urb_in_use
= 0;
1419 case -EPIPE
: /* no break needed; clear halt and resubmit */
1420 if (!priv
->comm_is_ok
)
1422 usb_clear_halt(port
->serial
->dev
, 0x02);
1423 /* error in the urb, so we have to resubmit it */
1424 dbg("%s - nonzero write bulk status received: %d",
1426 port
->interrupt_out_urb
->transfer_buffer_length
= 1;
1427 port
->interrupt_out_urb
->dev
= port
->serial
->dev
;
1428 result
= usb_submit_urb(port
->interrupt_out_urb
, GFP_ATOMIC
);
1431 dev_err(&urb
->dev
->dev
,
1432 "%s - failed resubmitting write urb, error %d\n",
1434 cypress_set_dead(port
);
1437 dev_err(&urb
->dev
->dev
,
1438 "%s - unexpected nonzero write status received: %d\n",
1440 cypress_set_dead(port
);
1443 priv
->write_urb_in_use
= 0;
1445 /* send any buffered data */
1450 /*****************************************************************************
1451 * Write buffer functions - buffering code from pl2303 used
1452 *****************************************************************************/
1457 * Allocate a circular buffer and all associated memory.
1460 static struct cypress_buf
*cypress_buf_alloc(unsigned int size
)
1463 struct cypress_buf
*cb
;
1469 cb
= kmalloc(sizeof(struct cypress_buf
), GFP_KERNEL
);
1473 cb
->buf_buf
= kmalloc(size
, GFP_KERNEL
);
1474 if (cb
->buf_buf
== NULL
) {
1479 cb
->buf_size
= size
;
1480 cb
->buf_get
= cb
->buf_put
= cb
->buf_buf
;
1490 * Free the buffer and all associated memory.
1493 static void cypress_buf_free(struct cypress_buf
*cb
)
1505 * Clear out all data in the circular buffer.
1508 static void cypress_buf_clear(struct cypress_buf
*cb
)
1511 cb
->buf_get
= cb
->buf_put
;
1512 /* equivalent to a get of all data available */
1517 * cypress_buf_data_avail
1519 * Return the number of bytes of data available in the circular
1523 static unsigned int cypress_buf_data_avail(struct cypress_buf
*cb
)
1526 return (cb
->buf_size
+ cb
->buf_put
- cb
->buf_get
)
1534 * cypress_buf_space_avail
1536 * Return the number of bytes of space available in the circular
1540 static unsigned int cypress_buf_space_avail(struct cypress_buf
*cb
)
1543 return (cb
->buf_size
+ cb
->buf_get
- cb
->buf_put
- 1)
1553 * Copy data data from a user buffer and put it into the circular buffer.
1554 * Restrict to the amount of space available.
1556 * Return the number of bytes copied.
1559 static unsigned int cypress_buf_put(struct cypress_buf
*cb
, const char *buf
,
1569 len
= cypress_buf_space_avail(cb
);
1576 len
= cb
->buf_buf
+ cb
->buf_size
- cb
->buf_put
;
1578 memcpy(cb
->buf_put
, buf
, len
);
1579 memcpy(cb
->buf_buf
, buf
+len
, count
- len
);
1580 cb
->buf_put
= cb
->buf_buf
+ count
- len
;
1582 memcpy(cb
->buf_put
, buf
, count
);
1584 cb
->buf_put
+= count
;
1585 else /* count == len */
1586 cb
->buf_put
= cb
->buf_buf
;
1597 * Get data from the circular buffer and copy to the given buffer.
1598 * Restrict to the amount of data available.
1600 * Return the number of bytes copied.
1603 static unsigned int cypress_buf_get(struct cypress_buf
*cb
, char *buf
,
1613 len
= cypress_buf_data_avail(cb
);
1620 len
= cb
->buf_buf
+ cb
->buf_size
- cb
->buf_get
;
1622 memcpy(buf
, cb
->buf_get
, len
);
1623 memcpy(buf
+len
, cb
->buf_buf
, count
- len
);
1624 cb
->buf_get
= cb
->buf_buf
+ count
- len
;
1626 memcpy(buf
, cb
->buf_get
, count
);
1628 cb
->buf_get
+= count
;
1629 else /* count == len */
1630 cb
->buf_get
= cb
->buf_buf
;
1637 /*****************************************************************************
1639 *****************************************************************************/
1641 static int __init
cypress_init(void)
1645 dbg("%s", __func__
);
1647 retval
= usb_serial_register(&cypress_earthmate_device
);
1649 goto failed_em_register
;
1650 retval
= usb_serial_register(&cypress_hidcom_device
);
1652 goto failed_hidcom_register
;
1653 retval
= usb_serial_register(&cypress_ca42v2_device
);
1655 goto failed_ca42v2_register
;
1656 retval
= usb_register(&cypress_driver
);
1658 goto failed_usb_register
;
1660 info(DRIVER_DESC
" " DRIVER_VERSION
);
1663 failed_usb_register
:
1664 usb_serial_deregister(&cypress_ca42v2_device
);
1665 failed_ca42v2_register
:
1666 usb_serial_deregister(&cypress_hidcom_device
);
1667 failed_hidcom_register
:
1668 usb_serial_deregister(&cypress_earthmate_device
);
1674 static void __exit
cypress_exit(void)
1676 dbg("%s", __func__
);
1678 usb_deregister(&cypress_driver
);
1679 usb_serial_deregister(&cypress_earthmate_device
);
1680 usb_serial_deregister(&cypress_hidcom_device
);
1681 usb_serial_deregister(&cypress_ca42v2_device
);
1685 module_init(cypress_init
);
1686 module_exit(cypress_exit
);
1688 MODULE_AUTHOR(DRIVER_AUTHOR
);
1689 MODULE_DESCRIPTION(DRIVER_DESC
);
1690 MODULE_VERSION(DRIVER_VERSION
);
1691 MODULE_LICENSE("GPL");
1693 module_param(debug
, bool, S_IRUGO
| S_IWUSR
);
1694 MODULE_PARM_DESC(debug
, "Debug enabled or not");
1695 module_param(stats
, bool, S_IRUGO
| S_IWUSR
);
1696 MODULE_PARM_DESC(stats
, "Enable statistics or not");
1697 module_param(interval
, int, S_IRUGO
| S_IWUSR
);
1698 MODULE_PARM_DESC(interval
, "Overrides interrupt interval");