blob: 0da1df9c79bf044677e703c125212a0dd5f0f52f [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) },
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 { } /* Terminating entry */
91};
92
Thiago Galesi372db8a2006-07-31 15:39:27 -030093MODULE_DEVICE_TABLE(usb, id_table);
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
95static struct usb_driver pl2303_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 .name = "pl2303",
97 .probe = usb_serial_probe,
98 .disconnect = usb_serial_disconnect,
99 .id_table = id_table,
Greg Kroah-Hartmanba9dc652005-11-16 13:41:28 -0800100 .no_dynamic_id = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101};
102
103#define SET_LINE_REQUEST_TYPE 0x21
104#define SET_LINE_REQUEST 0x20
105
106#define SET_CONTROL_REQUEST_TYPE 0x21
107#define SET_CONTROL_REQUEST 0x22
108#define CONTROL_DTR 0x01
109#define CONTROL_RTS 0x02
110
111#define BREAK_REQUEST_TYPE 0x21
112#define BREAK_REQUEST 0x23
113#define BREAK_ON 0xffff
114#define BREAK_OFF 0x0000
115
116#define GET_LINE_REQUEST_TYPE 0xa1
117#define GET_LINE_REQUEST 0x21
118
119#define VENDOR_WRITE_REQUEST_TYPE 0x40
120#define VENDOR_WRITE_REQUEST 0x01
121
122#define VENDOR_READ_REQUEST_TYPE 0xc0
123#define VENDOR_READ_REQUEST 0x01
124
125#define UART_STATE 0x08
126#define UART_STATE_TRANSIENT_MASK 0x74
127#define UART_DCD 0x01
128#define UART_DSR 0x02
129#define UART_BREAK_ERROR 0x04
130#define UART_RING 0x08
131#define UART_FRAME_ERROR 0x10
132#define UART_PARITY_ERROR 0x20
133#define UART_OVERRUN_ERROR 0x40
134#define UART_CTS 0x80
135
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136
137enum pl2303_type {
138 type_0, /* don't know the difference between type 0 and */
139 type_1, /* type 1, until someone from prolific tells us... */
140 HX, /* HX version of the pl2303 chip */
141};
142
143struct pl2303_private {
144 spinlock_t lock;
145 struct pl2303_buf *buf;
146 int write_urb_in_use;
147 wait_queue_head_t delta_msr_wait;
148 u8 line_control;
149 u8 line_status;
150 u8 termios_initialized;
151 enum pl2303_type type;
152};
153
Thiago Galesi572d3132006-07-29 10:46:37 -0300154/*
155 * pl2303_buf_alloc
156 *
157 * Allocate a circular buffer and all associated memory.
158 */
159static struct pl2303_buf *pl2303_buf_alloc(unsigned int size)
160{
161 struct pl2303_buf *pb;
162
163 if (size == 0)
164 return NULL;
165
Robert P. J. Day5cbded52006-12-13 00:35:56 -0800166 pb = kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
Thiago Galesi572d3132006-07-29 10:46:37 -0300167 if (pb == NULL)
168 return NULL;
169
170 pb->buf_buf = kmalloc(size, GFP_KERNEL);
171 if (pb->buf_buf == NULL) {
172 kfree(pb);
173 return NULL;
174 }
175
176 pb->buf_size = size;
177 pb->buf_get = pb->buf_put = pb->buf_buf;
178
179 return pb;
180}
181
182/*
183 * pl2303_buf_free
184 *
185 * Free the buffer and all associated memory.
186 */
187static void pl2303_buf_free(struct pl2303_buf *pb)
188{
189 if (pb) {
190 kfree(pb->buf_buf);
191 kfree(pb);
192 }
193}
194
195/*
196 * pl2303_buf_clear
197 *
198 * Clear out all data in the circular buffer.
199 */
200static void pl2303_buf_clear(struct pl2303_buf *pb)
201{
202 if (pb != NULL)
203 pb->buf_get = pb->buf_put;
204 /* equivalent to a get of all data available */
205}
206
207/*
208 * pl2303_buf_data_avail
209 *
210 * Return the number of bytes of data available in the circular
211 * buffer.
212 */
213static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb)
214{
215 if (pb == NULL)
216 return 0;
217
218 return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
219}
220
221/*
222 * pl2303_buf_space_avail
223 *
224 * Return the number of bytes of space available in the circular
225 * buffer.
226 */
227static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb)
228{
229 if (pb == NULL)
230 return 0;
231
232 return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
233}
234
235/*
236 * pl2303_buf_put
237 *
238 * Copy data data from a user buffer and put it into the circular buffer.
239 * Restrict to the amount of space available.
240 *
241 * Return the number of bytes copied.
242 */
243static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
244 unsigned int count)
245{
246 unsigned int len;
247
248 if (pb == NULL)
249 return 0;
250
251 len = pl2303_buf_space_avail(pb);
252 if (count > len)
253 count = len;
254
255 if (count == 0)
256 return 0;
257
258 len = pb->buf_buf + pb->buf_size - pb->buf_put;
259 if (count > len) {
260 memcpy(pb->buf_put, buf, len);
261 memcpy(pb->buf_buf, buf+len, count - len);
262 pb->buf_put = pb->buf_buf + count - len;
263 } else {
264 memcpy(pb->buf_put, buf, count);
265 if (count < len)
266 pb->buf_put += count;
267 else /* count == len */
268 pb->buf_put = pb->buf_buf;
269 }
270
271 return count;
272}
273
274/*
275 * pl2303_buf_get
276 *
277 * Get data from the circular buffer and copy to the given buffer.
278 * Restrict to the amount of data available.
279 *
280 * Return the number of bytes copied.
281 */
282static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
283 unsigned int count)
284{
285 unsigned int len;
286
287 if (pb == NULL)
288 return 0;
289
290 len = pl2303_buf_data_avail(pb);
291 if (count > len)
292 count = len;
293
294 if (count == 0)
295 return 0;
296
297 len = pb->buf_buf + pb->buf_size - pb->buf_get;
298 if (count > len) {
299 memcpy(buf, pb->buf_get, len);
300 memcpy(buf+len, pb->buf_buf, count - len);
301 pb->buf_get = pb->buf_buf + count - len;
302 } else {
303 memcpy(buf, pb->buf_get, count);
304 if (count < len)
305 pb->buf_get += count;
306 else /* count == len */
307 pb->buf_get = pb->buf_buf;
308 }
309
310 return count;
311}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312
Thiago Galesi372db8a2006-07-31 15:39:27 -0300313static int pl2303_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314{
315 struct pl2303_private *priv;
316 enum pl2303_type type = type_0;
317 int i;
318
319 if (serial->dev->descriptor.bDeviceClass == 0x02)
320 type = type_0;
321 else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40)
322 type = HX;
323 else if (serial->dev->descriptor.bDeviceClass == 0x00)
324 type = type_1;
325 else if (serial->dev->descriptor.bDeviceClass == 0xFF)
326 type = type_1;
327 dbg("device type: %d", type);
328
329 for (i = 0; i < serial->num_ports; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100330 priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 if (!priv)
332 goto cleanup;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 spin_lock_init(&priv->lock);
334 priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE);
335 if (priv->buf == NULL) {
336 kfree(priv);
337 goto cleanup;
338 }
339 init_waitqueue_head(&priv->delta_msr_wait);
340 priv->type = type;
341 usb_set_serial_port_data(serial->port[i], priv);
342 }
343 return 0;
344
345cleanup:
346 for (--i; i>=0; --i) {
347 priv = usb_get_serial_port_data(serial->port[i]);
348 pl2303_buf_free(priv->buf);
349 kfree(priv);
350 usb_set_serial_port_data(serial->port[i], NULL);
351 }
352 return -ENOMEM;
353}
354
Thiago Galesi372db8a2006-07-31 15:39:27 -0300355static int set_control_lines(struct usb_device *dev, u8 value)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356{
357 int retval;
358
Thiago Galesi372db8a2006-07-31 15:39:27 -0300359 retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
360 SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
361 value, 0, NULL, 0, 100);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 dbg("%s - value = %d, retval = %d", __FUNCTION__, value, retval);
363 return retval;
364}
365
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366static void pl2303_send(struct usb_serial_port *port)
367{
368 int count, result;
369 struct pl2303_private *priv = usb_get_serial_port_data(port);
370 unsigned long flags;
371
372 dbg("%s - port %d", __FUNCTION__, port->number);
373
374 spin_lock_irqsave(&priv->lock, flags);
375
376 if (priv->write_urb_in_use) {
377 spin_unlock_irqrestore(&priv->lock, flags);
378 return;
379 }
380
381 count = pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer,
Thiago Galesi372db8a2006-07-31 15:39:27 -0300382 port->bulk_out_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
384 if (count == 0) {
385 spin_unlock_irqrestore(&priv->lock, flags);
386 return;
387 }
388
389 priv->write_urb_in_use = 1;
390
391 spin_unlock_irqrestore(&priv->lock, flags);
392
Thiago Galesi372db8a2006-07-31 15:39:27 -0300393 usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count,
394 port->write_urb->transfer_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
396 port->write_urb->transfer_buffer_length = count;
397 port->write_urb->dev = port->serial->dev;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300398 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 if (result) {
Thiago Galesi372db8a2006-07-31 15:39:27 -0300400 dev_err(&port->dev, "%s - failed submitting write urb,"
401 " error %d\n", __FUNCTION__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 priv->write_urb_in_use = 0;
403 // TODO: reschedule pl2303_send
404 }
405
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700406 usb_serial_port_softint(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407}
408
Thiago Galesi572d3132006-07-29 10:46:37 -0300409static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf,
410 int count)
411{
412 struct pl2303_private *priv = usb_get_serial_port_data(port);
413 unsigned long flags;
414
415 dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
416
417 if (!count)
418 return count;
419
420 spin_lock_irqsave(&priv->lock, flags);
421 count = pl2303_buf_put(priv->buf, buf, count);
422 spin_unlock_irqrestore(&priv->lock, flags);
423
424 pl2303_send(port);
425
426 return count;
427}
428
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429static int pl2303_write_room(struct usb_serial_port *port)
430{
431 struct pl2303_private *priv = usb_get_serial_port_data(port);
432 int room = 0;
433 unsigned long flags;
434
435 dbg("%s - port %d", __FUNCTION__, port->number);
436
437 spin_lock_irqsave(&priv->lock, flags);
438 room = pl2303_buf_space_avail(priv->buf);
439 spin_unlock_irqrestore(&priv->lock, flags);
440
441 dbg("%s - returns %d", __FUNCTION__, room);
442 return room;
443}
444
445static int pl2303_chars_in_buffer(struct usb_serial_port *port)
446{
447 struct pl2303_private *priv = usb_get_serial_port_data(port);
448 int chars = 0;
449 unsigned long flags;
450
451 dbg("%s - port %d", __FUNCTION__, port->number);
452
453 spin_lock_irqsave(&priv->lock, flags);
454 chars = pl2303_buf_data_avail(priv->buf);
455 spin_unlock_irqrestore(&priv->lock, flags);
456
457 dbg("%s - returns %d", __FUNCTION__, chars);
458 return chars;
459}
460
Thiago Galesi372db8a2006-07-31 15:39:27 -0300461static void pl2303_set_termios(struct usb_serial_port *port,
Alan Cox606d0992006-12-08 02:38:45 -0800462 struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463{
464 struct usb_serial *serial = port->serial;
465 struct pl2303_private *priv = usb_get_serial_port_data(port);
466 unsigned long flags;
467 unsigned int cflag;
468 unsigned char *buf;
469 int baud;
470 int i;
471 u8 control;
472
473 dbg("%s - port %d", __FUNCTION__, port->number);
474
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 spin_lock_irqsave(&priv->lock, flags);
476 if (!priv->termios_initialized) {
477 *(port->tty->termios) = tty_std_termios;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300478 port->tty->termios->c_cflag = B9600 | CS8 | CREAD |
479 HUPCL | CLOCAL;
Alan Coxdf64c472007-10-15 20:54:47 +0100480 port->tty->termios->c_ispeed = 9600;
481 port->tty->termios->c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 priv->termios_initialized = 1;
483 }
484 spin_unlock_irqrestore(&priv->lock, flags);
485
Alan Coxbf5e5832008-01-08 14:55:51 +0000486 /* The PL2303 is reported to lose bytes if you change
487 serial settings even to the same values as before. Thus
488 we actually need to filter in this specific case */
489
490 if (!tty_termios_hw_change(port->tty->termios, old_termios))
491 return;
492
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 cflag = port->tty->termios->c_cflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494
Thiago Galesi372db8a2006-07-31 15:39:27 -0300495 buf = kzalloc(7, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 if (!buf) {
497 dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__);
498 return;
499 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500
Thiago Galesi372db8a2006-07-31 15:39:27 -0300501 i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
502 GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
503 0, 0, buf, 7, 100);
504 dbg("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i,
505 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
507 if (cflag & CSIZE) {
508 switch (cflag & CSIZE) {
509 case CS5: buf[6] = 5; break;
510 case CS6: buf[6] = 6; break;
511 case CS7: buf[6] = 7; break;
512 default:
513 case CS8: buf[6] = 8; break;
514 }
515 dbg("%s - data bits = %d", __FUNCTION__, buf[6]);
516 }
517
Alan Coxe0c79f52007-07-09 12:03:10 -0700518 baud = tty_get_baud_rate(port->tty);;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 dbg("%s - baud = %d", __FUNCTION__, baud);
520 if (baud) {
521 buf[0] = baud & 0xff;
522 buf[1] = (baud >> 8) & 0xff;
523 buf[2] = (baud >> 16) & 0xff;
524 buf[3] = (baud >> 24) & 0xff;
525 }
526
527 /* For reference buf[4]=0 is 1 stop bits */
528 /* For reference buf[4]=1 is 1.5 stop bits */
529 /* For reference buf[4]=2 is 2 stop bits */
530 if (cflag & CSTOPB) {
531 buf[4] = 2;
532 dbg("%s - stop bits = 2", __FUNCTION__);
533 } else {
534 buf[4] = 0;
535 dbg("%s - stop bits = 1", __FUNCTION__);
536 }
537
538 if (cflag & PARENB) {
539 /* For reference buf[5]=0 is none parity */
540 /* For reference buf[5]=1 is odd parity */
541 /* For reference buf[5]=2 is even parity */
542 /* For reference buf[5]=3 is mark parity */
543 /* For reference buf[5]=4 is space parity */
544 if (cflag & PARODD) {
545 buf[5] = 1;
546 dbg("%s - parity = odd", __FUNCTION__);
547 } else {
548 buf[5] = 2;
549 dbg("%s - parity = even", __FUNCTION__);
550 }
551 } else {
552 buf[5] = 0;
553 dbg("%s - parity = none", __FUNCTION__);
554 }
555
Thiago Galesi372db8a2006-07-31 15:39:27 -0300556 i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
557 SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE,
558 0, 0, buf, 7, 100);
559 dbg("0x21:0x20:0:0 %d", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560
561 /* change control lines if we are switching to or from B0 */
562 spin_lock_irqsave(&priv->lock, flags);
563 control = priv->line_control;
564 if ((cflag & CBAUD) == B0)
565 priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
566 else
567 priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
568 if (control != priv->line_control) {
569 control = priv->line_control;
570 spin_unlock_irqrestore(&priv->lock, flags);
571 set_control_lines(serial->dev, control);
572 } else {
573 spin_unlock_irqrestore(&priv->lock, flags);
574 }
Thiago Galesi372db8a2006-07-31 15:39:27 -0300575
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
577
Thiago Galesi372db8a2006-07-31 15:39:27 -0300578 i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
579 GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
580 0, 0, buf, 7, 100);
581 dbg("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
583
584 if (cflag & CRTSCTS) {
585 __u16 index;
586 if (priv->type == HX)
587 index = 0x61;
588 else
589 index = 0x41;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300590 i = usb_control_msg(serial->dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 usb_sndctrlpipe(serial->dev, 0),
592 VENDOR_WRITE_REQUEST,
593 VENDOR_WRITE_REQUEST_TYPE,
594 0x0, index, NULL, 0, 100);
Thiago Galesi372db8a2006-07-31 15:39:27 -0300595 dbg("0x40:0x1:0x0:0x%x %d", index, i);
t.sefzick715f9522007-04-25 15:05:22 +0200596 } else {
597 i = usb_control_msg(serial->dev,
598 usb_sndctrlpipe(serial->dev, 0),
599 VENDOR_WRITE_REQUEST,
600 VENDOR_WRITE_REQUEST_TYPE,
601 0x0, 0x0, NULL, 0, 100);
602 dbg ("0x40:0x1:0x0:0x0 %d", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 }
604
Alan Coxdf64c472007-10-15 20:54:47 +0100605 /* FIXME: Need to read back resulting baud rate */
606 if (baud)
607 tty_encode_baud_rate(port->tty, baud, baud);
608
Thiago Galesi372db8a2006-07-31 15:39:27 -0300609 kfree(buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610}
611
Thiago Galesi572d3132006-07-29 10:46:37 -0300612static void pl2303_close(struct usb_serial_port *port, struct file *filp)
613{
614 struct pl2303_private *priv = usb_get_serial_port_data(port);
615 unsigned long flags;
616 unsigned int c_cflag;
617 int bps;
618 long timeout;
619 wait_queue_t wait;
620
621 dbg("%s - port %d", __FUNCTION__, port->number);
622
623 /* wait for data to drain from the buffer */
624 spin_lock_irqsave(&priv->lock, flags);
625 timeout = PL2303_CLOSING_WAIT;
626 init_waitqueue_entry(&wait, current);
627 add_wait_queue(&port->tty->write_wait, &wait);
628 for (;;) {
629 set_current_state(TASK_INTERRUPTIBLE);
630 if (pl2303_buf_data_avail(priv->buf) == 0 ||
631 timeout == 0 || signal_pending(current) ||
632 !usb_get_intfdata(port->serial->interface)) /* disconnect */
633 break;
634 spin_unlock_irqrestore(&priv->lock, flags);
635 timeout = schedule_timeout(timeout);
636 spin_lock_irqsave(&priv->lock, flags);
637 }
638 set_current_state(TASK_RUNNING);
639 remove_wait_queue(&port->tty->write_wait, &wait);
640 /* clear out any remaining data in the buffer */
641 pl2303_buf_clear(priv->buf);
642 spin_unlock_irqrestore(&priv->lock, flags);
643
644 /* wait for characters to drain from the device */
645 /* (this is long enough for the entire 256 byte */
646 /* pl2303 hardware buffer to drain with no flow */
647 /* control for data rates of 1200 bps or more, */
648 /* for lower rates we should really know how much */
649 /* data is in the buffer to compute a delay */
650 /* that is not unnecessarily long) */
651 bps = tty_get_baud_rate(port->tty);
652 if (bps > 1200)
653 timeout = max((HZ*2560)/bps,HZ/10);
654 else
655 timeout = 2*HZ;
656 schedule_timeout_interruptible(timeout);
657
658 /* shutdown our urbs */
659 dbg("%s - shutting down urbs", __FUNCTION__);
660 usb_kill_urb(port->write_urb);
661 usb_kill_urb(port->read_urb);
662 usb_kill_urb(port->interrupt_in_urb);
663
664 if (port->tty) {
665 c_cflag = port->tty->termios->c_cflag;
666 if (c_cflag & HUPCL) {
667 /* drop DTR and RTS */
668 spin_lock_irqsave(&priv->lock, flags);
669 priv->line_control = 0;
670 spin_unlock_irqrestore(&priv->lock, flags);
671 set_control_lines(port->serial->dev, 0);
672 }
673 }
674}
675
Thiago Galesi372db8a2006-07-31 15:39:27 -0300676static int pl2303_open(struct usb_serial_port *port, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677{
Alan Cox606d0992006-12-08 02:38:45 -0800678 struct ktermios tmp_termios;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 struct usb_serial *serial = port->serial;
680 struct pl2303_private *priv = usb_get_serial_port_data(port);
681 unsigned char *buf;
682 int result;
683
684 dbg("%s - port %d", __FUNCTION__, port->number);
685
Dariusz M16948992005-07-28 18:06:13 +0200686 if (priv->type != HX) {
687 usb_clear_halt(serial->dev, port->write_urb->pipe);
688 usb_clear_halt(serial->dev, port->read_urb->pipe);
689 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690
691 buf = kmalloc(10, GFP_KERNEL);
692 if (buf==NULL)
693 return -ENOMEM;
694
695#define FISH(a,b,c,d) \
696 result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0), \
697 b, a, c, d, buf, 1, 100); \
698 dbg("0x%x:0x%x:0x%x:0x%x %d - %x",a,b,c,d,result,buf[0]);
699
700#define SOUP(a,b,c,d) \
701 result=usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev,0), \
702 b, a, c, d, NULL, 0, 100); \
703 dbg("0x%x:0x%x:0x%x:0x%x %d",a,b,c,d,result);
704
705 FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
706 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 0);
707 FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
708 FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0);
709 FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
710 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 1);
711 FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
712 FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0);
713 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0, 1);
714 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 1, 0);
715
716 if (priv->type == HX) {
717 /* HX chip */
718 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x44);
719 /* reset upstream data pipes */
720 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 8, 0);
721 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 9, 0);
722 } else {
723 SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x24);
724 }
725
726 kfree(buf);
727
728 /* Setup termios */
729 if (port->tty) {
Thiago Galesi372db8a2006-07-31 15:39:27 -0300730 pl2303_set_termios(port, &tmp_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 }
732
733 //FIXME: need to assert RTS and DTR if CRTSCTS off
734
735 dbg("%s - submitting read urb", __FUNCTION__);
736 port->read_urb->dev = serial->dev;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300737 result = usb_submit_urb(port->read_urb, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 if (result) {
Thiago Galesi372db8a2006-07-31 15:39:27 -0300739 dev_err(&port->dev, "%s - failed submitting read urb,"
740 " error %d\n", __FUNCTION__, result);
741 pl2303_close(port, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 return -EPROTO;
743 }
744
745 dbg("%s - submitting interrupt urb", __FUNCTION__);
746 port->interrupt_in_urb->dev = serial->dev;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300747 result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 if (result) {
Thiago Galesi372db8a2006-07-31 15:39:27 -0300749 dev_err(&port->dev, "%s - failed submitting interrupt urb,"
750 " error %d\n", __FUNCTION__, result);
751 pl2303_close(port, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 return -EPROTO;
753 }
754 return 0;
755}
756
Thiago Galesi372db8a2006-07-31 15:39:27 -0300757static int pl2303_tiocmset(struct usb_serial_port *port, struct file *file,
758 unsigned int set, unsigned int clear)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759{
760 struct pl2303_private *priv = usb_get_serial_port_data(port);
761 unsigned long flags;
762 u8 control;
763
Flavio Leitner6fdd8e82005-04-18 17:39:31 -0700764 if (!usb_get_intfdata(port->serial->interface))
765 return -ENODEV;
766
Thiago Galesi372db8a2006-07-31 15:39:27 -0300767 spin_lock_irqsave(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 if (set & TIOCM_RTS)
769 priv->line_control |= CONTROL_RTS;
770 if (set & TIOCM_DTR)
771 priv->line_control |= CONTROL_DTR;
772 if (clear & TIOCM_RTS)
773 priv->line_control &= ~CONTROL_RTS;
774 if (clear & TIOCM_DTR)
775 priv->line_control &= ~CONTROL_DTR;
776 control = priv->line_control;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300777 spin_unlock_irqrestore(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778
Thiago Galesi372db8a2006-07-31 15:39:27 -0300779 return set_control_lines(port->serial->dev, control);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780}
781
Thiago Galesi372db8a2006-07-31 15:39:27 -0300782static int pl2303_tiocmget(struct usb_serial_port *port, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783{
784 struct pl2303_private *priv = usb_get_serial_port_data(port);
785 unsigned long flags;
786 unsigned int mcr;
787 unsigned int status;
788 unsigned int result;
789
790 dbg("%s (%d)", __FUNCTION__, port->number);
791
Flavio Leitner6fdd8e82005-04-18 17:39:31 -0700792 if (!usb_get_intfdata(port->serial->interface))
793 return -ENODEV;
794
Thiago Galesi372db8a2006-07-31 15:39:27 -0300795 spin_lock_irqsave(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 mcr = priv->line_control;
797 status = priv->line_status;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300798 spin_unlock_irqrestore(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799
800 result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0)
801 | ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0)
802 | ((status & UART_CTS) ? TIOCM_CTS : 0)
803 | ((status & UART_DSR) ? TIOCM_DSR : 0)
804 | ((status & UART_RING) ? TIOCM_RI : 0)
805 | ((status & UART_DCD) ? TIOCM_CD : 0);
806
807 dbg("%s - result = %x", __FUNCTION__, result);
808
809 return result;
810}
811
812static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
813{
814 struct pl2303_private *priv = usb_get_serial_port_data(port);
815 unsigned long flags;
816 unsigned int prevstatus;
817 unsigned int status;
818 unsigned int changed;
819
Thiago Galesi372db8a2006-07-31 15:39:27 -0300820 spin_lock_irqsave(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 prevstatus = priv->line_status;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300822 spin_unlock_irqrestore(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823
824 while (1) {
825 interruptible_sleep_on(&priv->delta_msr_wait);
826 /* see if a signal did it */
827 if (signal_pending(current))
828 return -ERESTARTSYS;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300829
830 spin_lock_irqsave(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 status = priv->line_status;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300832 spin_unlock_irqrestore(&priv->lock, flags);
833
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 changed=prevstatus^status;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300835
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 if (((arg & TIOCM_RNG) && (changed & UART_RING)) ||
837 ((arg & TIOCM_DSR) && (changed & UART_DSR)) ||
838 ((arg & TIOCM_CD) && (changed & UART_DCD)) ||
839 ((arg & TIOCM_CTS) && (changed & UART_CTS)) ) {
840 return 0;
841 }
842 prevstatus = status;
843 }
844 /* NOTREACHED */
845 return 0;
846}
847
Thiago Galesi372db8a2006-07-31 15:39:27 -0300848static int pl2303_ioctl(struct usb_serial_port *port, struct file *file,
849 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850{
851 dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd);
852
853 switch (cmd) {
854 case TIOCMIWAIT:
855 dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number);
856 return wait_modem_info(port, arg);
857
858 default:
859 dbg("%s not supported = 0x%04x", __FUNCTION__, cmd);
860 break;
861 }
862
863 return -ENOIOCTLCMD;
864}
865
Thiago Galesi372db8a2006-07-31 15:39:27 -0300866static void pl2303_break_ctl(struct usb_serial_port *port, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867{
868 struct usb_serial *serial = port->serial;
869 u16 state;
870 int result;
871
872 dbg("%s - port %d", __FUNCTION__, port->number);
873
874 if (break_state == 0)
875 state = BREAK_OFF;
876 else
877 state = BREAK_ON;
878 dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on");
879
Thiago Galesi372db8a2006-07-31 15:39:27 -0300880 result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
881 BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
882 0, NULL, 0, 100);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 if (result)
884 dbg("%s - error sending break = %d", __FUNCTION__, result);
885}
886
Thiago Galesi372db8a2006-07-31 15:39:27 -0300887static void pl2303_shutdown(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888{
889 int i;
890 struct pl2303_private *priv;
891
892 dbg("%s", __FUNCTION__);
893
894 for (i = 0; i < serial->num_ports; ++i) {
895 priv = usb_get_serial_port_data(serial->port[i]);
896 if (priv) {
897 pl2303_buf_free(priv->buf);
898 kfree(priv);
899 usb_set_serial_port_data(serial->port[i], NULL);
900 }
Thiago Galesi372db8a2006-07-31 15:39:27 -0300901 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902}
903
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700904static void pl2303_update_line_status(struct usb_serial_port *port,
905 unsigned char *data,
906 unsigned int actual_length)
907{
908
909 struct pl2303_private *priv = usb_get_serial_port_data(port);
910 unsigned long flags;
911 u8 status_idx = UART_STATE;
Horst Schirmeier95f209f2005-07-28 15:32:20 +0200912 u8 length = UART_STATE + 1;
Thiago Galesi9c537612006-07-29 10:47:12 -0300913 u16 idv, idp;
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700914
Thiago Galesi9c537612006-07-29 10:47:12 -0300915 idv = le16_to_cpu(port->serial->dev->descriptor.idVendor);
916 idp = le16_to_cpu(port->serial->dev->descriptor.idProduct);
917
918
919 if (idv == SIEMENS_VENDOR_ID) {
920 if (idp == SIEMENS_PRODUCT_ID_X65 ||
921 idp == SIEMENS_PRODUCT_ID_SX1 ||
922 idp == SIEMENS_PRODUCT_ID_X75) {
923
924 length = 1;
925 status_idx = 0;
926 }
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700927 }
928
929 if (actual_length < length)
Luiz Fernando N. Capitulinoa009b752006-07-25 16:58:30 -0300930 return;
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700931
932 /* Save off the uart status for others to look at */
933 spin_lock_irqsave(&priv->lock, flags);
934 priv->line_status = data[status_idx];
935 spin_unlock_irqrestore(&priv->lock, flags);
Thiago Galesi372db8a2006-07-31 15:39:27 -0300936 wake_up_interruptible(&priv->delta_msr_wait);
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700937}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938
David Howells7d12e782006-10-05 14:55:46 +0100939static void pl2303_read_int_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940{
941 struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 unsigned char *data = urb->transfer_buffer;
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700943 unsigned int actual_length = urb->actual_length;
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700944 int status = urb->status;
945 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946
947 dbg("%s (%d)", __FUNCTION__, port->number);
948
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700949 switch (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 case 0:
951 /* success */
952 break;
953 case -ECONNRESET:
954 case -ENOENT:
955 case -ESHUTDOWN:
956 /* this urb is terminated, clean up */
Thiago Galesi372db8a2006-07-31 15:39:27 -0300957 dbg("%s - urb shutting down with status: %d", __FUNCTION__,
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700958 status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 return;
960 default:
Thiago Galesi372db8a2006-07-31 15:39:27 -0300961 dbg("%s - nonzero urb status received: %d", __FUNCTION__,
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700962 status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 goto exit;
964 }
965
Thiago Galesi372db8a2006-07-31 15:39:27 -0300966 usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
967 urb->actual_length, urb->transfer_buffer);
968
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700969 pl2303_update_line_status(port, data, actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971exit:
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700972 retval = usb_submit_urb(urb, GFP_ATOMIC);
973 if (retval)
Thiago Galesi372db8a2006-07-31 15:39:27 -0300974 dev_err(&urb->dev->dev,
975 "%s - usb_submit_urb failed with result %d\n",
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700976 __FUNCTION__, retval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977}
978
David Howells7d12e782006-10-05 14:55:46 +0100979static void pl2303_read_bulk_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980{
981 struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
982 struct pl2303_private *priv = usb_get_serial_port_data(port);
983 struct tty_struct *tty;
984 unsigned char *data = urb->transfer_buffer;
985 unsigned long flags;
986 int i;
987 int result;
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700988 int status = urb->status;
989 u8 line_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 char tty_flag;
991
992 dbg("%s - port %d", __FUNCTION__, port->number);
993
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700994 if (status) {
995 dbg("%s - urb status = %d", __FUNCTION__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 if (!port->open_count) {
997 dbg("%s - port is closed, exiting.", __FUNCTION__);
998 return;
999 }
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001000 if (status == -EPROTO) {
Thiago Galesi372db8a2006-07-31 15:39:27 -03001001 /* PL2303 mysteriously fails with -EPROTO reschedule
1002 * the read */
1003 dbg("%s - caught -EPROTO, resubmitting the urb",
1004 __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 urb->dev = port->serial->dev;
1006 result = usb_submit_urb(urb, GFP_ATOMIC);
1007 if (result)
Thiago Galesi372db8a2006-07-31 15:39:27 -03001008 dev_err(&urb->dev->dev, "%s - failed"
1009 " resubmitting read urb, error %d\n",
1010 __FUNCTION__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 return;
1012 }
1013 dbg("%s - unable to handle the error, exiting.", __FUNCTION__);
1014 return;
1015 }
1016
Thiago Galesi372db8a2006-07-31 15:39:27 -03001017 usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
1018 urb->actual_length, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019
1020 /* get tty_flag from status */
1021 tty_flag = TTY_NORMAL;
1022
1023 spin_lock_irqsave(&priv->lock, flags);
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001024 line_status = priv->line_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
1026 spin_unlock_irqrestore(&priv->lock, flags);
Thiago Galesi372db8a2006-07-31 15:39:27 -03001027 wake_up_interruptible(&priv->delta_msr_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
1029 /* break takes precedence over parity, */
1030 /* which takes precedence over framing errors */
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001031 if (line_status & UART_BREAK_ERROR )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 tty_flag = TTY_BREAK;
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001033 else if (line_status & UART_PARITY_ERROR)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 tty_flag = TTY_PARITY;
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001035 else if (line_status & UART_FRAME_ERROR)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 tty_flag = TTY_FRAME;
1037 dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag);
1038
1039 tty = port->tty;
1040 if (tty && urb->actual_length) {
Alan Cox33f0f882006-01-09 20:54:13 -08001041 tty_buffer_request_room(tty, urb->actual_length + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 /* overrun is special, not associated with a char */
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001043 if (line_status & UART_OVERRUN_ERROR)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
Alan Cox33f0f882006-01-09 20:54:13 -08001045 for (i = 0; i < urb->actual_length; ++i)
Thiago Galesi372db8a2006-07-31 15:39:27 -03001046 tty_insert_flip_char(tty, data[i], tty_flag);
1047 tty_flip_buffer_push(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 }
1049
1050 /* Schedule the next read _if_ we are still open */
1051 if (port->open_count) {
1052 urb->dev = port->serial->dev;
1053 result = usb_submit_urb(urb, GFP_ATOMIC);
1054 if (result)
Thiago Galesi372db8a2006-07-31 15:39:27 -03001055 dev_err(&urb->dev->dev, "%s - failed resubmitting"
1056 " read urb, error %d\n", __FUNCTION__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 }
1058
1059 return;
1060}
1061
David Howells7d12e782006-10-05 14:55:46 +01001062static void pl2303_write_bulk_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063{
1064 struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
1065 struct pl2303_private *priv = usb_get_serial_port_data(port);
1066 int result;
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001067 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068
1069 dbg("%s - port %d", __FUNCTION__, port->number);
1070
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001071 switch (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 case 0:
1073 /* success */
1074 break;
1075 case -ECONNRESET:
1076 case -ENOENT:
1077 case -ESHUTDOWN:
1078 /* this urb is terminated, clean up */
Thiago Galesi372db8a2006-07-31 15:39:27 -03001079 dbg("%s - urb shutting down with status: %d", __FUNCTION__,
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001080 status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 priv->write_urb_in_use = 0;
1082 return;
1083 default:
1084 /* error in the urb, so we have to resubmit it */
1085 dbg("%s - Overflow in write", __FUNCTION__);
Thiago Galesi372db8a2006-07-31 15:39:27 -03001086 dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001087 status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 port->write_urb->transfer_buffer_length = 1;
1089 port->write_urb->dev = port->serial->dev;
Thiago Galesi372db8a2006-07-31 15:39:27 -03001090 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 if (result)
Thiago Galesi372db8a2006-07-31 15:39:27 -03001092 dev_err(&urb->dev->dev, "%s - failed resubmitting write"
1093 " urb, error %d\n", __FUNCTION__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 else
1095 return;
1096 }
1097
1098 priv->write_urb_in_use = 0;
1099
1100 /* send any buffered data */
1101 pl2303_send(port);
1102}
1103
Thiago Galesi572d3132006-07-29 10:46:37 -03001104/* All of the device info needed for the PL2303 SIO serial converter */
1105static struct usb_serial_driver pl2303_device = {
1106 .driver = {
1107 .owner = THIS_MODULE,
1108 .name = "pl2303",
1109 },
1110 .id_table = id_table,
Johannes Hölzld9b1b782006-12-17 21:50:24 +01001111 .usb_driver = &pl2303_driver,
Thiago Galesi572d3132006-07-29 10:46:37 -03001112 .num_interrupt_in = NUM_DONT_CARE,
1113 .num_bulk_in = 1,
1114 .num_bulk_out = 1,
1115 .num_ports = 1,
1116 .open = pl2303_open,
1117 .close = pl2303_close,
1118 .write = pl2303_write,
1119 .ioctl = pl2303_ioctl,
1120 .break_ctl = pl2303_break_ctl,
1121 .set_termios = pl2303_set_termios,
1122 .tiocmget = pl2303_tiocmget,
1123 .tiocmset = pl2303_tiocmset,
1124 .read_bulk_callback = pl2303_read_bulk_callback,
1125 .read_int_callback = pl2303_read_int_callback,
1126 .write_bulk_callback = pl2303_write_bulk_callback,
1127 .write_room = pl2303_write_room,
1128 .chars_in_buffer = pl2303_chars_in_buffer,
1129 .attach = pl2303_startup,
1130 .shutdown = pl2303_shutdown,
1131};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132
Thiago Galesi372db8a2006-07-31 15:39:27 -03001133static int __init pl2303_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134{
1135 int retval;
Thiago Galesi372db8a2006-07-31 15:39:27 -03001136
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 retval = usb_serial_register(&pl2303_device);
1138 if (retval)
1139 goto failed_usb_serial_register;
1140 retval = usb_register(&pl2303_driver);
1141 if (retval)
1142 goto failed_usb_register;
Greg Kroah-Hartman17a882f2005-06-20 21:15:16 -07001143 info(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 return 0;
1145failed_usb_register:
1146 usb_serial_deregister(&pl2303_device);
1147failed_usb_serial_register:
1148 return retval;
1149}
1150
Thiago Galesi372db8a2006-07-31 15:39:27 -03001151static void __exit pl2303_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152{
Thiago Galesi372db8a2006-07-31 15:39:27 -03001153 usb_deregister(&pl2303_driver);
1154 usb_serial_deregister(&pl2303_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155}
1156
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157module_init(pl2303_init);
1158module_exit(pl2303_exit);
1159
1160MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161MODULE_LICENSE("GPL");
1162
1163module_param(debug, bool, S_IRUGO | S_IWUSR);
1164MODULE_PARM_DESC(debug, "Debug enabled or not");
1165