blob: fbce1ba333b027f085f8b31975e33430164da0e1 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Prolific PL2303 USB to serial adaptor driver
3 *
Greg Kroah-Hartman4d0dce32007-06-12 11:43:37 -07004 * Copyright (C) 2001-2007 Greg Kroah-Hartman (greg@kroah.com)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Copyright (C) 2003 IBM Corp.
6 *
7 * Original driver for 2.2.x by anonymous
8 *
Greg Kroah-Hartman4d0dce32007-06-12 11:43:37 -07009 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License version
11 * 2 as published by the Free Software Foundation.
Linus Torvalds1da177e2005-04-16 15:20:36 -070012 *
13 * See Documentation/usb/usb-serial.txt for more information on using this driver
14 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070015 */
16
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include <linux/kernel.h>
18#include <linux/errno.h>
19#include <linux/init.h>
20#include <linux/slab.h>
21#include <linux/tty.h>
22#include <linux/tty_driver.h>
23#include <linux/tty_flip.h>
24#include <linux/serial.h>
25#include <linux/module.h>
26#include <linux/moduleparam.h>
27#include <linux/spinlock.h>
28#include <asm/uaccess.h>
29#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070030#include <linux/usb/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include "pl2303.h"
32
33/*
34 * Version Information
35 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver"
37
38static int debug;
39
40#define PL2303_CLOSING_WAIT (30*HZ)
41
42#define PL2303_BUF_SIZE 1024
43#define PL2303_TMP_BUF_SIZE 1024
44
Linus Torvalds1da177e2005-04-16 15:20:36 -070045struct pl2303_buf {
46 unsigned int buf_size;
47 char *buf_buf;
48 char *buf_get;
49 char *buf_put;
50};
51
52static struct usb_device_id id_table [] = {
53 { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) },
54 { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) },
Peter Moulder3d861492006-06-19 22:47:49 +100055 { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11) },
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) },
57 { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) },
58 { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
Masakazu Mokuno8a28dea2007-10-23 13:51:57 +090059 { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
Linus Torvalds1da177e2005-04-16 15:20:36 -070060 { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
61 { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) },
62 { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) },
63 { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) },
64 { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) },
Wang Jun58381712006-04-19 16:32:07 +080065 { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID_2080) },
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) },
67 { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) },
68 { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) },
69 { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) },
70 { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) },
71 { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) },
72 { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) },
73 { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) },
Luiz Fernando Capitulinoa8310f32005-11-17 09:47:32 -080074 { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1) },
Linus Torvalds1da177e2005-04-16 15:20:36 -070075 { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) },
Luiz Fernando Capitulinoa8310f32005-11-17 09:47:32 -080076 { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) },
Andreas Loible7beb662007-08-24 01:51:11 +020077 { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_EF81) },
Peter Favrholdtacbb36f2005-04-18 17:39:32 -070078 { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) },
Christian Lindnerc6c27722006-02-01 14:10:52 +010079 { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) },
80 { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID) },
Denis MONTERRAT6cceb052006-01-19 14:52:38 +010081 { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) },
Christian Lindnerc6c27722006-02-01 14:10:52 +010082 { USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) },
Dick Streefland491b04c2006-03-01 00:53:33 -080083 { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) },
Matthew Meno3b928472006-06-21 15:25:53 -040084 { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) },
Kim Oldfieldb7aa94b2006-07-25 15:54:59 +100085 { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) },
Johannes Steingraeber8fd80132006-09-16 16:17:34 +020086 { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) },
Wesley PA4WDHb697f702006-09-28 20:45:38 +020087 { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) },
YOSHIFUJI Hideaki2d94b982007-01-26 22:51:38 +090088 { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) },
Magnus Damm9e3285d2007-11-08 16:45:46 +090089 { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) },
Piotr Roszatycki002e8f22008-01-02 11:16:57 +010090 { USB_DEVICE(HL340_VENDOR_ID, HL340_PRODUCT_ID) },
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 { } /* Terminating entry */
92};
93
Thiago Galesi372db8a2006-07-31 15:39:27 -030094MODULE_DEVICE_TABLE(usb, id_table);
Linus Torvalds1da177e2005-04-16 15:20:36 -070095
96static struct usb_driver pl2303_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 .name = "pl2303",
98 .probe = usb_serial_probe,
99 .disconnect = usb_serial_disconnect,
100 .id_table = id_table,
Greg Kroah-Hartmanba9dc652005-11-16 13:41:28 -0800101 .no_dynamic_id = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102};
103
104#define SET_LINE_REQUEST_TYPE 0x21
105#define SET_LINE_REQUEST 0x20
106
107#define SET_CONTROL_REQUEST_TYPE 0x21
108#define SET_CONTROL_REQUEST 0x22
109#define CONTROL_DTR 0x01
110#define CONTROL_RTS 0x02
111
112#define BREAK_REQUEST_TYPE 0x21
113#define BREAK_REQUEST 0x23
114#define BREAK_ON 0xffff
115#define BREAK_OFF 0x0000
116
117#define GET_LINE_REQUEST_TYPE 0xa1
118#define GET_LINE_REQUEST 0x21
119
120#define VENDOR_WRITE_REQUEST_TYPE 0x40
121#define VENDOR_WRITE_REQUEST 0x01
122
123#define VENDOR_READ_REQUEST_TYPE 0xc0
124#define VENDOR_READ_REQUEST 0x01
125
126#define UART_STATE 0x08
127#define UART_STATE_TRANSIENT_MASK 0x74
128#define UART_DCD 0x01
129#define UART_DSR 0x02
130#define UART_BREAK_ERROR 0x04
131#define UART_RING 0x08
132#define UART_FRAME_ERROR 0x10
133#define UART_PARITY_ERROR 0x20
134#define UART_OVERRUN_ERROR 0x40
135#define UART_CTS 0x80
136
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
138enum pl2303_type {
139 type_0, /* don't know the difference between type 0 and */
140 type_1, /* type 1, until someone from prolific tells us... */
141 HX, /* HX version of the pl2303 chip */
142};
143
144struct pl2303_private {
145 spinlock_t lock;
146 struct pl2303_buf *buf;
147 int write_urb_in_use;
148 wait_queue_head_t delta_msr_wait;
149 u8 line_control;
150 u8 line_status;
151 u8 termios_initialized;
152 enum pl2303_type type;
153};
154
Thiago Galesi572d3132006-07-29 10:46:37 -0300155/*
156 * pl2303_buf_alloc
157 *
158 * Allocate a circular buffer and all associated memory.
159 */
160static struct pl2303_buf *pl2303_buf_alloc(unsigned int size)
161{
162 struct pl2303_buf *pb;
163
164 if (size == 0)
165 return NULL;
166
Robert P. J. Day5cbded52006-12-13 00:35:56 -0800167 pb = kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
Thiago Galesi572d3132006-07-29 10:46:37 -0300168 if (pb == NULL)
169 return NULL;
170
171 pb->buf_buf = kmalloc(size, GFP_KERNEL);
172 if (pb->buf_buf == NULL) {
173 kfree(pb);
174 return NULL;
175 }
176
177 pb->buf_size = size;
178 pb->buf_get = pb->buf_put = pb->buf_buf;
179
180 return pb;
181}
182
183/*
184 * pl2303_buf_free
185 *
186 * Free the buffer and all associated memory.
187 */
188static void pl2303_buf_free(struct pl2303_buf *pb)
189{
190 if (pb) {
191 kfree(pb->buf_buf);
192 kfree(pb);
193 }
194}
195
196/*
197 * pl2303_buf_clear
198 *
199 * Clear out all data in the circular buffer.
200 */
201static void pl2303_buf_clear(struct pl2303_buf *pb)
202{
203 if (pb != NULL)
204 pb->buf_get = pb->buf_put;
205 /* equivalent to a get of all data available */
206}
207
208/*
209 * pl2303_buf_data_avail
210 *
211 * Return the number of bytes of data available in the circular
212 * buffer.
213 */
214static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb)
215{
216 if (pb == NULL)
217 return 0;
218
219 return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
220}
221
222/*
223 * pl2303_buf_space_avail
224 *
225 * Return the number of bytes of space available in the circular
226 * buffer.
227 */
228static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb)
229{
230 if (pb == NULL)
231 return 0;
232
233 return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
234}
235
236/*
237 * pl2303_buf_put
238 *
239 * Copy data data from a user buffer and put it into the circular buffer.
240 * Restrict to the amount of space available.
241 *
242 * Return the number of bytes copied.
243 */
244static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
245 unsigned int count)
246{
247 unsigned int len;
248
249 if (pb == NULL)
250 return 0;
251
252 len = pl2303_buf_space_avail(pb);
253 if (count > len)
254 count = len;
255
256 if (count == 0)
257 return 0;
258
259 len = pb->buf_buf + pb->buf_size - pb->buf_put;
260 if (count > len) {
261 memcpy(pb->buf_put, buf, len);
262 memcpy(pb->buf_buf, buf+len, count - len);
263 pb->buf_put = pb->buf_buf + count - len;
264 } else {
265 memcpy(pb->buf_put, buf, count);
266 if (count < len)
267 pb->buf_put += count;
268 else /* count == len */
269 pb->buf_put = pb->buf_buf;
270 }
271
272 return count;
273}
274
275/*
276 * pl2303_buf_get
277 *
278 * Get data from the circular buffer and copy to the given buffer.
279 * Restrict to the amount of data available.
280 *
281 * Return the number of bytes copied.
282 */
283static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
284 unsigned int count)
285{
286 unsigned int len;
287
288 if (pb == NULL)
289 return 0;
290
291 len = pl2303_buf_data_avail(pb);
292 if (count > len)
293 count = len;
294
295 if (count == 0)
296 return 0;
297
298 len = pb->buf_buf + pb->buf_size - pb->buf_get;
299 if (count > len) {
300 memcpy(buf, pb->buf_get, len);
301 memcpy(buf+len, pb->buf_buf, count - len);
302 pb->buf_get = pb->buf_buf + count - len;
303 } else {
304 memcpy(buf, pb->buf_get, count);
305 if (count < len)
306 pb->buf_get += count;
307 else /* count == len */
308 pb->buf_get = pb->buf_buf;
309 }
310
311 return count;
312}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313
Thiago Galesi372db8a2006-07-31 15:39:27 -0300314static int pl2303_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315{
316 struct pl2303_private *priv;
317 enum pl2303_type type = type_0;
318 int i;
319
320 if (serial->dev->descriptor.bDeviceClass == 0x02)
321 type = type_0;
322 else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40)
323 type = HX;
324 else if (serial->dev->descriptor.bDeviceClass == 0x00)
325 type = type_1;
326 else if (serial->dev->descriptor.bDeviceClass == 0xFF)
327 type = type_1;
328 dbg("device type: %d", type);
329
330 for (i = 0; i < serial->num_ports; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100331 priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 if (!priv)
333 goto cleanup;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 spin_lock_init(&priv->lock);
335 priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE);
336 if (priv->buf == NULL) {
337 kfree(priv);
338 goto cleanup;
339 }
340 init_waitqueue_head(&priv->delta_msr_wait);
341 priv->type = type;
342 usb_set_serial_port_data(serial->port[i], priv);
343 }
344 return 0;
345
346cleanup:
347 for (--i; i>=0; --i) {
348 priv = usb_get_serial_port_data(serial->port[i]);
349 pl2303_buf_free(priv->buf);
350 kfree(priv);
351 usb_set_serial_port_data(serial->port[i], NULL);
352 }
353 return -ENOMEM;
354}
355
Thiago Galesi372db8a2006-07-31 15:39:27 -0300356static int set_control_lines(struct usb_device *dev, u8 value)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357{
358 int retval;
359
Thiago Galesi372db8a2006-07-31 15:39:27 -0300360 retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
361 SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
362 value, 0, NULL, 0, 100);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 dbg("%s - value = %d, retval = %d", __FUNCTION__, value, retval);
364 return retval;
365}
366
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367static void pl2303_send(struct usb_serial_port *port)
368{
369 int count, result;
370 struct pl2303_private *priv = usb_get_serial_port_data(port);
371 unsigned long flags;
372
373 dbg("%s - port %d", __FUNCTION__, port->number);
374
375 spin_lock_irqsave(&priv->lock, flags);
376
377 if (priv->write_urb_in_use) {
378 spin_unlock_irqrestore(&priv->lock, flags);
379 return;
380 }
381
382 count = pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer,
Thiago Galesi372db8a2006-07-31 15:39:27 -0300383 port->bulk_out_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384
385 if (count == 0) {
386 spin_unlock_irqrestore(&priv->lock, flags);
387 return;
388 }
389
390 priv->write_urb_in_use = 1;
391
392 spin_unlock_irqrestore(&priv->lock, flags);
393
Thiago Galesi372db8a2006-07-31 15:39:27 -0300394 usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count,
395 port->write_urb->transfer_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
397 port->write_urb->transfer_buffer_length = count;
398 port->write_urb->dev = port->serial->dev;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300399 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 if (result) {
Thiago Galesi372db8a2006-07-31 15:39:27 -0300401 dev_err(&port->dev, "%s - failed submitting write urb,"
402 " error %d\n", __FUNCTION__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 priv->write_urb_in_use = 0;
404 // TODO: reschedule pl2303_send
405 }
406
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700407 usb_serial_port_softint(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408}
409
Thiago Galesi572d3132006-07-29 10:46:37 -0300410static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf,
411 int count)
412{
413 struct pl2303_private *priv = usb_get_serial_port_data(port);
414 unsigned long flags;
415
416 dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
417
418 if (!count)
419 return count;
420
421 spin_lock_irqsave(&priv->lock, flags);
422 count = pl2303_buf_put(priv->buf, buf, count);
423 spin_unlock_irqrestore(&priv->lock, flags);
424
425 pl2303_send(port);
426
427 return count;
428}
429
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430static int pl2303_write_room(struct usb_serial_port *port)
431{
432 struct pl2303_private *priv = usb_get_serial_port_data(port);
433 int room = 0;
434 unsigned long flags;
435
436 dbg("%s - port %d", __FUNCTION__, port->number);
437
438 spin_lock_irqsave(&priv->lock, flags);
439 room = pl2303_buf_space_avail(priv->buf);
440 spin_unlock_irqrestore(&priv->lock, flags);
441
442 dbg("%s - returns %d", __FUNCTION__, room);
443 return room;
444}
445
446static int pl2303_chars_in_buffer(struct usb_serial_port *port)
447{
448 struct pl2303_private *priv = usb_get_serial_port_data(port);
449 int chars = 0;
450 unsigned long flags;
451
452 dbg("%s - port %d", __FUNCTION__, port->number);
453
454 spin_lock_irqsave(&priv->lock, flags);
455 chars = pl2303_buf_data_avail(priv->buf);
456 spin_unlock_irqrestore(&priv->lock, flags);
457
458 dbg("%s - returns %d", __FUNCTION__, chars);
459 return chars;
460}
461
Thiago Galesi372db8a2006-07-31 15:39:27 -0300462static void pl2303_set_termios(struct usb_serial_port *port,
Alan Cox606d0992006-12-08 02:38:45 -0800463 struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464{
465 struct usb_serial *serial = port->serial;
466 struct pl2303_private *priv = usb_get_serial_port_data(port);
467 unsigned long flags;
468 unsigned int cflag;
469 unsigned char *buf;
470 int baud;
471 int i;
472 u8 control;
473
474 dbg("%s - port %d", __FUNCTION__, port->number);
475
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 spin_lock_irqsave(&priv->lock, flags);
477 if (!priv->termios_initialized) {
478 *(port->tty->termios) = tty_std_termios;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300479 port->tty->termios->c_cflag = B9600 | CS8 | CREAD |
480 HUPCL | CLOCAL;
Alan Coxdf64c472007-10-15 20:54:47 +0100481 port->tty->termios->c_ispeed = 9600;
482 port->tty->termios->c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 priv->termios_initialized = 1;
484 }
485 spin_unlock_irqrestore(&priv->lock, flags);
486
Alan Coxbf5e5832008-01-08 14:55:51 +0000487 /* The PL2303 is reported to lose bytes if you change
488 serial settings even to the same values as before. Thus
489 we actually need to filter in this specific case */
490
491 if (!tty_termios_hw_change(port->tty->termios, old_termios))
492 return;
493
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 cflag = port->tty->termios->c_cflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495
Thiago Galesi372db8a2006-07-31 15:39:27 -0300496 buf = kzalloc(7, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 if (!buf) {
498 dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__);
499 return;
500 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
Thiago Galesi372db8a2006-07-31 15:39:27 -0300502 i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
503 GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
504 0, 0, buf, 7, 100);
505 dbg("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i,
506 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
508 if (cflag & CSIZE) {
509 switch (cflag & CSIZE) {
510 case CS5: buf[6] = 5; break;
511 case CS6: buf[6] = 6; break;
512 case CS7: buf[6] = 7; break;
513 default:
514 case CS8: buf[6] = 8; break;
515 }
516 dbg("%s - data bits = %d", __FUNCTION__, buf[6]);
517 }
518
Alan Coxe0c79f52007-07-09 12:03:10 -0700519 baud = tty_get_baud_rate(port->tty);;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 dbg("%s - baud = %d", __FUNCTION__, baud);
521 if (baud) {
522 buf[0] = baud & 0xff;
523 buf[1] = (baud >> 8) & 0xff;
524 buf[2] = (baud >> 16) & 0xff;
525 buf[3] = (baud >> 24) & 0xff;
526 }
527
528 /* For reference buf[4]=0 is 1 stop bits */
529 /* For reference buf[4]=1 is 1.5 stop bits */
530 /* For reference buf[4]=2 is 2 stop bits */
531 if (cflag & CSTOPB) {
532 buf[4] = 2;
533 dbg("%s - stop bits = 2", __FUNCTION__);
534 } else {
535 buf[4] = 0;
536 dbg("%s - stop bits = 1", __FUNCTION__);
537 }
538
539 if (cflag & PARENB) {
540 /* For reference buf[5]=0 is none parity */
541 /* For reference buf[5]=1 is odd parity */
542 /* For reference buf[5]=2 is even parity */
543 /* For reference buf[5]=3 is mark parity */
544 /* For reference buf[5]=4 is space parity */
545 if (cflag & PARODD) {
546 buf[5] = 1;
547 dbg("%s - parity = odd", __FUNCTION__);
548 } else {
549 buf[5] = 2;
550 dbg("%s - parity = even", __FUNCTION__);
551 }
552 } else {
553 buf[5] = 0;
554 dbg("%s - parity = none", __FUNCTION__);
555 }
556
Thiago Galesi372db8a2006-07-31 15:39:27 -0300557 i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
558 SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE,
559 0, 0, buf, 7, 100);
560 dbg("0x21:0x20:0:0 %d", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561
562 /* change control lines if we are switching to or from B0 */
563 spin_lock_irqsave(&priv->lock, flags);
564 control = priv->line_control;
565 if ((cflag & CBAUD) == B0)
566 priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
567 else
568 priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
569 if (control != priv->line_control) {
570 control = priv->line_control;
571 spin_unlock_irqrestore(&priv->lock, flags);
572 set_control_lines(serial->dev, control);
573 } else {
574 spin_unlock_irqrestore(&priv->lock, flags);
575 }
Thiago Galesi372db8a2006-07-31 15:39:27 -0300576
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
578
Thiago Galesi372db8a2006-07-31 15:39:27 -0300579 i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
580 GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
581 0, 0, buf, 7, 100);
582 dbg("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
584
585 if (cflag & CRTSCTS) {
586 __u16 index;
587 if (priv->type == HX)
588 index = 0x61;
589 else
590 index = 0x41;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300591 i = usb_control_msg(serial->dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 usb_sndctrlpipe(serial->dev, 0),
593 VENDOR_WRITE_REQUEST,
594 VENDOR_WRITE_REQUEST_TYPE,
595 0x0, index, NULL, 0, 100);
Thiago Galesi372db8a2006-07-31 15:39:27 -0300596 dbg("0x40:0x1:0x0:0x%x %d", index, i);
t.sefzick715f9522007-04-25 15:05:22 +0200597 } else {
598 i = usb_control_msg(serial->dev,
599 usb_sndctrlpipe(serial->dev, 0),
600 VENDOR_WRITE_REQUEST,
601 VENDOR_WRITE_REQUEST_TYPE,
602 0x0, 0x0, NULL, 0, 100);
603 dbg ("0x40:0x1:0x0:0x0 %d", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 }
605
Alan Coxdf64c472007-10-15 20:54:47 +0100606 /* FIXME: Need to read back resulting baud rate */
607 if (baud)
608 tty_encode_baud_rate(port->tty, baud, baud);
609
Thiago Galesi372db8a2006-07-31 15:39:27 -0300610 kfree(buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611}
612
Thiago Galesi572d3132006-07-29 10:46:37 -0300613static void pl2303_close(struct usb_serial_port *port, struct file *filp)
614{
615 struct pl2303_private *priv = usb_get_serial_port_data(port);
616 unsigned long flags;
617 unsigned int c_cflag;
618 int bps;
619 long timeout;
620 wait_queue_t wait;
621
622 dbg("%s - port %d", __FUNCTION__, port->number);
623
624 /* wait for data to drain from the buffer */
625 spin_lock_irqsave(&priv->lock, flags);
626 timeout = PL2303_CLOSING_WAIT;
627 init_waitqueue_entry(&wait, current);
628 add_wait_queue(&port->tty->write_wait, &wait);
629 for (;;) {
630 set_current_state(TASK_INTERRUPTIBLE);
631 if (pl2303_buf_data_avail(priv->buf) == 0 ||
632 timeout == 0 || signal_pending(current) ||
633 !usb_get_intfdata(port->serial->interface)) /* disconnect */
634 break;
635 spin_unlock_irqrestore(&priv->lock, flags);
636 timeout = schedule_timeout(timeout);
637 spin_lock_irqsave(&priv->lock, flags);
638 }
639 set_current_state(TASK_RUNNING);
640 remove_wait_queue(&port->tty->write_wait, &wait);
641 /* clear out any remaining data in the buffer */
642 pl2303_buf_clear(priv->buf);
643 spin_unlock_irqrestore(&priv->lock, flags);
644
645 /* wait for characters to drain from the device */
646 /* (this is long enough for the entire 256 byte */
647 /* pl2303 hardware buffer to drain with no flow */
648 /* control for data rates of 1200 bps or more, */
649 /* for lower rates we should really know how much */
650 /* data is in the buffer to compute a delay */
651 /* that is not unnecessarily long) */
652 bps = tty_get_baud_rate(port->tty);
653 if (bps > 1200)
654 timeout = max((HZ*2560)/bps,HZ/10);
655 else
656 timeout = 2*HZ;
657 schedule_timeout_interruptible(timeout);
658
659 /* shutdown our urbs */
660 dbg("%s - shutting down urbs", __FUNCTION__);
661 usb_kill_urb(port->write_urb);
662 usb_kill_urb(port->read_urb);
663 usb_kill_urb(port->interrupt_in_urb);
664
665 if (port->tty) {
666 c_cflag = port->tty->termios->c_cflag;
667 if (c_cflag & HUPCL) {
668 /* drop DTR and RTS */
669 spin_lock_irqsave(&priv->lock, flags);
670 priv->line_control = 0;
671 spin_unlock_irqrestore(&priv->lock, flags);
672 set_control_lines(port->serial->dev, 0);
673 }
674 }
675}
676
Thiago Galesi372db8a2006-07-31 15:39:27 -0300677static int pl2303_open(struct usb_serial_port *port, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678{
Alan Cox606d0992006-12-08 02:38:45 -0800679 struct ktermios tmp_termios;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 struct usb_serial *serial = port->serial;
681 struct pl2303_private *priv = usb_get_serial_port_data(port);
682 unsigned char *buf;
683 int result;
684
685 dbg("%s - port %d", __FUNCTION__, port->number);
686
Dariusz M16948992005-07-28 18:06:13 +0200687 if (priv->type != HX) {
688 usb_clear_halt(serial->dev, port->write_urb->pipe);
689 usb_clear_halt(serial->dev, port->read_urb->pipe);
690 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
692 buf = kmalloc(10, GFP_KERNEL);
693 if (buf==NULL)
694 return -ENOMEM;
695
696#define FISH(a,b,c,d) \
697 result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0), \
698 b, a, c, d, buf, 1, 100); \
699 dbg("0x%x:0x%x:0x%x:0x%x %d - %x",a,b,c,d,result,buf[0]);
700
701#define SOUP(a,b,c,d) \
702 result=usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev,0), \
703 b, a, c, d, NULL, 0, 100); \
704 dbg("0x%x:0x%x:0x%x:0x%x %d",a,b,c,d,result);
705
706 FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
707 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 0);
708 FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
709 FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0);
710 FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
711 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 1);
712 FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
713 FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0);
714 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0, 1);
715 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 1, 0);
716
717 if (priv->type == HX) {
718 /* HX chip */
719 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x44);
720 /* reset upstream data pipes */
721 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 8, 0);
722 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 9, 0);
723 } else {
724 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x24);
725 }
726
727 kfree(buf);
728
729 /* Setup termios */
730 if (port->tty) {
Thiago Galesi372db8a2006-07-31 15:39:27 -0300731 pl2303_set_termios(port, &tmp_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 }
733
734 //FIXME: need to assert RTS and DTR if CRTSCTS off
735
736 dbg("%s - submitting read urb", __FUNCTION__);
737 port->read_urb->dev = serial->dev;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300738 result = usb_submit_urb(port->read_urb, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 if (result) {
Thiago Galesi372db8a2006-07-31 15:39:27 -0300740 dev_err(&port->dev, "%s - failed submitting read urb,"
741 " error %d\n", __FUNCTION__, result);
742 pl2303_close(port, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 return -EPROTO;
744 }
745
746 dbg("%s - submitting interrupt urb", __FUNCTION__);
747 port->interrupt_in_urb->dev = serial->dev;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300748 result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 if (result) {
Thiago Galesi372db8a2006-07-31 15:39:27 -0300750 dev_err(&port->dev, "%s - failed submitting interrupt urb,"
751 " error %d\n", __FUNCTION__, result);
752 pl2303_close(port, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 return -EPROTO;
754 }
755 return 0;
756}
757
Thiago Galesi372db8a2006-07-31 15:39:27 -0300758static int pl2303_tiocmset(struct usb_serial_port *port, struct file *file,
759 unsigned int set, unsigned int clear)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760{
761 struct pl2303_private *priv = usb_get_serial_port_data(port);
762 unsigned long flags;
763 u8 control;
764
Flavio Leitner6fdd8e82005-04-18 17:39:31 -0700765 if (!usb_get_intfdata(port->serial->interface))
766 return -ENODEV;
767
Thiago Galesi372db8a2006-07-31 15:39:27 -0300768 spin_lock_irqsave(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 if (set & TIOCM_RTS)
770 priv->line_control |= CONTROL_RTS;
771 if (set & TIOCM_DTR)
772 priv->line_control |= CONTROL_DTR;
773 if (clear & TIOCM_RTS)
774 priv->line_control &= ~CONTROL_RTS;
775 if (clear & TIOCM_DTR)
776 priv->line_control &= ~CONTROL_DTR;
777 control = priv->line_control;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300778 spin_unlock_irqrestore(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779
Thiago Galesi372db8a2006-07-31 15:39:27 -0300780 return set_control_lines(port->serial->dev, control);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781}
782
Thiago Galesi372db8a2006-07-31 15:39:27 -0300783static int pl2303_tiocmget(struct usb_serial_port *port, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784{
785 struct pl2303_private *priv = usb_get_serial_port_data(port);
786 unsigned long flags;
787 unsigned int mcr;
788 unsigned int status;
789 unsigned int result;
790
791 dbg("%s (%d)", __FUNCTION__, port->number);
792
Flavio Leitner6fdd8e82005-04-18 17:39:31 -0700793 if (!usb_get_intfdata(port->serial->interface))
794 return -ENODEV;
795
Thiago Galesi372db8a2006-07-31 15:39:27 -0300796 spin_lock_irqsave(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 mcr = priv->line_control;
798 status = priv->line_status;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300799 spin_unlock_irqrestore(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800
801 result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0)
802 | ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0)
803 | ((status & UART_CTS) ? TIOCM_CTS : 0)
804 | ((status & UART_DSR) ? TIOCM_DSR : 0)
805 | ((status & UART_RING) ? TIOCM_RI : 0)
806 | ((status & UART_DCD) ? TIOCM_CD : 0);
807
808 dbg("%s - result = %x", __FUNCTION__, result);
809
810 return result;
811}
812
813static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
814{
815 struct pl2303_private *priv = usb_get_serial_port_data(port);
816 unsigned long flags;
817 unsigned int prevstatus;
818 unsigned int status;
819 unsigned int changed;
820
Thiago Galesi372db8a2006-07-31 15:39:27 -0300821 spin_lock_irqsave(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 prevstatus = priv->line_status;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300823 spin_unlock_irqrestore(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824
825 while (1) {
826 interruptible_sleep_on(&priv->delta_msr_wait);
827 /* see if a signal did it */
828 if (signal_pending(current))
829 return -ERESTARTSYS;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300830
831 spin_lock_irqsave(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 status = priv->line_status;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300833 spin_unlock_irqrestore(&priv->lock, flags);
834
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 changed=prevstatus^status;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300836
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 if (((arg & TIOCM_RNG) && (changed & UART_RING)) ||
838 ((arg & TIOCM_DSR) && (changed & UART_DSR)) ||
839 ((arg & TIOCM_CD) && (changed & UART_DCD)) ||
840 ((arg & TIOCM_CTS) && (changed & UART_CTS)) ) {
841 return 0;
842 }
843 prevstatus = status;
844 }
845 /* NOTREACHED */
846 return 0;
847}
848
Thiago Galesi372db8a2006-07-31 15:39:27 -0300849static int pl2303_ioctl(struct usb_serial_port *port, struct file *file,
850 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851{
852 dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd);
853
854 switch (cmd) {
855 case TIOCMIWAIT:
856 dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number);
857 return wait_modem_info(port, arg);
858
859 default:
860 dbg("%s not supported = 0x%04x", __FUNCTION__, cmd);
861 break;
862 }
863
864 return -ENOIOCTLCMD;
865}
866
Thiago Galesi372db8a2006-07-31 15:39:27 -0300867static void pl2303_break_ctl(struct usb_serial_port *port, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868{
869 struct usb_serial *serial = port->serial;
870 u16 state;
871 int result;
872
873 dbg("%s - port %d", __FUNCTION__, port->number);
874
875 if (break_state == 0)
876 state = BREAK_OFF;
877 else
878 state = BREAK_ON;
879 dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on");
880
Thiago Galesi372db8a2006-07-31 15:39:27 -0300881 result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
882 BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
883 0, NULL, 0, 100);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 if (result)
885 dbg("%s - error sending break = %d", __FUNCTION__, result);
886}
887
Thiago Galesi372db8a2006-07-31 15:39:27 -0300888static void pl2303_shutdown(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889{
890 int i;
891 struct pl2303_private *priv;
892
893 dbg("%s", __FUNCTION__);
894
895 for (i = 0; i < serial->num_ports; ++i) {
896 priv = usb_get_serial_port_data(serial->port[i]);
897 if (priv) {
898 pl2303_buf_free(priv->buf);
899 kfree(priv);
900 usb_set_serial_port_data(serial->port[i], NULL);
901 }
Thiago Galesi372db8a2006-07-31 15:39:27 -0300902 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903}
904
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700905static void pl2303_update_line_status(struct usb_serial_port *port,
906 unsigned char *data,
907 unsigned int actual_length)
908{
909
910 struct pl2303_private *priv = usb_get_serial_port_data(port);
911 unsigned long flags;
912 u8 status_idx = UART_STATE;
Horst Schirmeier95f209f2005-07-28 15:32:20 +0200913 u8 length = UART_STATE + 1;
Thiago Galesi9c537612006-07-29 10:47:12 -0300914 u16 idv, idp;
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700915
Thiago Galesi9c537612006-07-29 10:47:12 -0300916 idv = le16_to_cpu(port->serial->dev->descriptor.idVendor);
917 idp = le16_to_cpu(port->serial->dev->descriptor.idProduct);
918
919
920 if (idv == SIEMENS_VENDOR_ID) {
921 if (idp == SIEMENS_PRODUCT_ID_X65 ||
922 idp == SIEMENS_PRODUCT_ID_SX1 ||
923 idp == SIEMENS_PRODUCT_ID_X75) {
924
925 length = 1;
926 status_idx = 0;
927 }
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700928 }
929
930 if (actual_length < length)
Luiz Fernando N. Capitulinoa009b752006-07-25 16:58:30 -0300931 return;
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700932
933 /* Save off the uart status for others to look at */
934 spin_lock_irqsave(&priv->lock, flags);
935 priv->line_status = data[status_idx];
936 spin_unlock_irqrestore(&priv->lock, flags);
Thiago Galesi372db8a2006-07-31 15:39:27 -0300937 wake_up_interruptible(&priv->delta_msr_wait);
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700938}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939
David Howells7d12e782006-10-05 14:55:46 +0100940static void pl2303_read_int_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941{
942 struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 unsigned char *data = urb->transfer_buffer;
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700944 unsigned int actual_length = urb->actual_length;
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700945 int status = urb->status;
946 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947
948 dbg("%s (%d)", __FUNCTION__, port->number);
949
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700950 switch (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 case 0:
952 /* success */
953 break;
954 case -ECONNRESET:
955 case -ENOENT:
956 case -ESHUTDOWN:
957 /* this urb is terminated, clean up */
Thiago Galesi372db8a2006-07-31 15:39:27 -0300958 dbg("%s - urb shutting down with status: %d", __FUNCTION__,
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700959 status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 return;
961 default:
Thiago Galesi372db8a2006-07-31 15:39:27 -0300962 dbg("%s - nonzero urb status received: %d", __FUNCTION__,
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700963 status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 goto exit;
965 }
966
Thiago Galesi372db8a2006-07-31 15:39:27 -0300967 usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
968 urb->actual_length, urb->transfer_buffer);
969
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700970 pl2303_update_line_status(port, data, actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972exit:
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700973 retval = usb_submit_urb(urb, GFP_ATOMIC);
974 if (retval)
Thiago Galesi372db8a2006-07-31 15:39:27 -0300975 dev_err(&urb->dev->dev,
976 "%s - usb_submit_urb failed with result %d\n",
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700977 __FUNCTION__, retval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978}
979
David Howells7d12e782006-10-05 14:55:46 +0100980static void pl2303_read_bulk_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981{
982 struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
983 struct pl2303_private *priv = usb_get_serial_port_data(port);
984 struct tty_struct *tty;
985 unsigned char *data = urb->transfer_buffer;
986 unsigned long flags;
987 int i;
988 int result;
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700989 int status = urb->status;
990 u8 line_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 char tty_flag;
992
993 dbg("%s - port %d", __FUNCTION__, port->number);
994
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700995 if (status) {
996 dbg("%s - urb status = %d", __FUNCTION__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 if (!port->open_count) {
998 dbg("%s - port is closed, exiting.", __FUNCTION__);
999 return;
1000 }
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001001 if (status == -EPROTO) {
Thiago Galesi372db8a2006-07-31 15:39:27 -03001002 /* PL2303 mysteriously fails with -EPROTO reschedule
1003 * the read */
1004 dbg("%s - caught -EPROTO, resubmitting the urb",
1005 __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 urb->dev = port->serial->dev;
1007 result = usb_submit_urb(urb, GFP_ATOMIC);
1008 if (result)
Thiago Galesi372db8a2006-07-31 15:39:27 -03001009 dev_err(&urb->dev->dev, "%s - failed"
1010 " resubmitting read urb, error %d\n",
1011 __FUNCTION__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 return;
1013 }
1014 dbg("%s - unable to handle the error, exiting.", __FUNCTION__);
1015 return;
1016 }
1017
Thiago Galesi372db8a2006-07-31 15:39:27 -03001018 usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
1019 urb->actual_length, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020
1021 /* get tty_flag from status */
1022 tty_flag = TTY_NORMAL;
1023
1024 spin_lock_irqsave(&priv->lock, flags);
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001025 line_status = priv->line_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
1027 spin_unlock_irqrestore(&priv->lock, flags);
Thiago Galesi372db8a2006-07-31 15:39:27 -03001028 wake_up_interruptible(&priv->delta_msr_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029
1030 /* break takes precedence over parity, */
1031 /* which takes precedence over framing errors */
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001032 if (line_status & UART_BREAK_ERROR )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 tty_flag = TTY_BREAK;
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001034 else if (line_status & UART_PARITY_ERROR)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 tty_flag = TTY_PARITY;
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001036 else if (line_status & UART_FRAME_ERROR)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 tty_flag = TTY_FRAME;
1038 dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag);
1039
1040 tty = port->tty;
1041 if (tty && urb->actual_length) {
Alan Cox33f0f882006-01-09 20:54:13 -08001042 tty_buffer_request_room(tty, urb->actual_length + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 /* overrun is special, not associated with a char */
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001044 if (line_status & UART_OVERRUN_ERROR)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
Alan Cox33f0f882006-01-09 20:54:13 -08001046 for (i = 0; i < urb->actual_length; ++i)
Thiago Galesi372db8a2006-07-31 15:39:27 -03001047 tty_insert_flip_char(tty, data[i], tty_flag);
1048 tty_flip_buffer_push(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 }
1050
1051 /* Schedule the next read _if_ we are still open */
1052 if (port->open_count) {
1053 urb->dev = port->serial->dev;
1054 result = usb_submit_urb(urb, GFP_ATOMIC);
1055 if (result)
Thiago Galesi372db8a2006-07-31 15:39:27 -03001056 dev_err(&urb->dev->dev, "%s - failed resubmitting"
1057 " read urb, error %d\n", __FUNCTION__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 }
1059
1060 return;
1061}
1062
David Howells7d12e782006-10-05 14:55:46 +01001063static void pl2303_write_bulk_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064{
1065 struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
1066 struct pl2303_private *priv = usb_get_serial_port_data(port);
1067 int result;
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001068 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
1070 dbg("%s - port %d", __FUNCTION__, port->number);
1071
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001072 switch (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 case 0:
1074 /* success */
1075 break;
1076 case -ECONNRESET:
1077 case -ENOENT:
1078 case -ESHUTDOWN:
1079 /* this urb is terminated, clean up */
Thiago Galesi372db8a2006-07-31 15:39:27 -03001080 dbg("%s - urb shutting down with status: %d", __FUNCTION__,
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001081 status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 priv->write_urb_in_use = 0;
1083 return;
1084 default:
1085 /* error in the urb, so we have to resubmit it */
1086 dbg("%s - Overflow in write", __FUNCTION__);
Thiago Galesi372db8a2006-07-31 15:39:27 -03001087 dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001088 status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 port->write_urb->transfer_buffer_length = 1;
1090 port->write_urb->dev = port->serial->dev;
Thiago Galesi372db8a2006-07-31 15:39:27 -03001091 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 if (result)
Thiago Galesi372db8a2006-07-31 15:39:27 -03001093 dev_err(&urb->dev->dev, "%s - failed resubmitting write"
1094 " urb, error %d\n", __FUNCTION__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 else
1096 return;
1097 }
1098
1099 priv->write_urb_in_use = 0;
1100
1101 /* send any buffered data */
1102 pl2303_send(port);
1103}
1104
Thiago Galesi572d3132006-07-29 10:46:37 -03001105/* All of the device info needed for the PL2303 SIO serial converter */
1106static struct usb_serial_driver pl2303_device = {
1107 .driver = {
1108 .owner = THIS_MODULE,
1109 .name = "pl2303",
1110 },
1111 .id_table = id_table,
Johannes Hölzld9b1b782006-12-17 21:50:24 +01001112 .usb_driver = &pl2303_driver,
Thiago Galesi572d3132006-07-29 10:46:37 -03001113 .num_interrupt_in = NUM_DONT_CARE,
1114 .num_bulk_in = 1,
1115 .num_bulk_out = 1,
1116 .num_ports = 1,
1117 .open = pl2303_open,
1118 .close = pl2303_close,
1119 .write = pl2303_write,
1120 .ioctl = pl2303_ioctl,
1121 .break_ctl = pl2303_break_ctl,
1122 .set_termios = pl2303_set_termios,
1123 .tiocmget = pl2303_tiocmget,
1124 .tiocmset = pl2303_tiocmset,
1125 .read_bulk_callback = pl2303_read_bulk_callback,
1126 .read_int_callback = pl2303_read_int_callback,
1127 .write_bulk_callback = pl2303_write_bulk_callback,
1128 .write_room = pl2303_write_room,
1129 .chars_in_buffer = pl2303_chars_in_buffer,
1130 .attach = pl2303_startup,
1131 .shutdown = pl2303_shutdown,
1132};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133
Thiago Galesi372db8a2006-07-31 15:39:27 -03001134static int __init pl2303_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135{
1136 int retval;
Thiago Galesi372db8a2006-07-31 15:39:27 -03001137
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 retval = usb_serial_register(&pl2303_device);
1139 if (retval)
1140 goto failed_usb_serial_register;
1141 retval = usb_register(&pl2303_driver);
1142 if (retval)
1143 goto failed_usb_register;
Greg Kroah-Hartman17a882f2005-06-20 21:15:16 -07001144 info(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 return 0;
1146failed_usb_register:
1147 usb_serial_deregister(&pl2303_device);
1148failed_usb_serial_register:
1149 return retval;
1150}
1151
Thiago Galesi372db8a2006-07-31 15:39:27 -03001152static void __exit pl2303_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153{
Thiago Galesi372db8a2006-07-31 15:39:27 -03001154 usb_deregister(&pl2303_driver);
1155 usb_serial_deregister(&pl2303_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156}
1157
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158module_init(pl2303_init);
1159module_exit(pl2303_exit);
1160
1161MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162MODULE_LICENSE("GPL");
1163
1164module_param(debug, bool, S_IRUGO | S_IWUSR);
1165MODULE_PARM_DESC(debug, "Debug enabled or not");
1166