blob: fd8c09fd32888c7154a85947b7af2ff3f775f6fa [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) },
Akira Tsukamoto57833ea2008-01-18 18:58:28 +090068 { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
Linus Torvalds1da177e2005-04-16 15:20:36 -070069 { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) },
70 { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) },
71 { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) },
72 { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) },
73 { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) },
74 { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) },
Luiz Fernando Capitulinoa8310f32005-11-17 09:47:32 -080075 { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1) },
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) },
Luiz Fernando Capitulinoa8310f32005-11-17 09:47:32 -080077 { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) },
Andreas Loible7beb662007-08-24 01:51:11 +020078 { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_EF81) },
Peter Favrholdtacbb36f2005-04-18 17:39:32 -070079 { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) },
Christian Lindnerc6c27722006-02-01 14:10:52 +010080 { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) },
81 { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID) },
Denis MONTERRAT6cceb052006-01-19 14:52:38 +010082 { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) },
Christian Lindnerc6c27722006-02-01 14:10:52 +010083 { USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) },
Dick Streefland491b04c2006-03-01 00:53:33 -080084 { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) },
Matthew Meno3b928472006-06-21 15:25:53 -040085 { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) },
Kim Oldfieldb7aa94b2006-07-25 15:54:59 +100086 { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) },
Johannes Steingraeber8fd80132006-09-16 16:17:34 +020087 { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_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) },
Damien Stuartcc311ee2008-01-06 13:51:39 -050091 { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) },
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 { } /* Terminating entry */
93};
94
Thiago Galesi372db8a2006-07-31 15:39:27 -030095MODULE_DEVICE_TABLE(usb, id_table);
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
97static struct usb_driver pl2303_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 .name = "pl2303",
99 .probe = usb_serial_probe,
100 .disconnect = usb_serial_disconnect,
101 .id_table = id_table,
Greg Kroah-Hartmanba9dc652005-11-16 13:41:28 -0800102 .no_dynamic_id = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103};
104
105#define SET_LINE_REQUEST_TYPE 0x21
106#define SET_LINE_REQUEST 0x20
107
108#define SET_CONTROL_REQUEST_TYPE 0x21
109#define SET_CONTROL_REQUEST 0x22
110#define CONTROL_DTR 0x01
111#define CONTROL_RTS 0x02
112
113#define BREAK_REQUEST_TYPE 0x21
114#define BREAK_REQUEST 0x23
115#define BREAK_ON 0xffff
116#define BREAK_OFF 0x0000
117
118#define GET_LINE_REQUEST_TYPE 0xa1
119#define GET_LINE_REQUEST 0x21
120
121#define VENDOR_WRITE_REQUEST_TYPE 0x40
122#define VENDOR_WRITE_REQUEST 0x01
123
124#define VENDOR_READ_REQUEST_TYPE 0xc0
125#define VENDOR_READ_REQUEST 0x01
126
127#define UART_STATE 0x08
128#define UART_STATE_TRANSIENT_MASK 0x74
129#define UART_DCD 0x01
130#define UART_DSR 0x02
131#define UART_BREAK_ERROR 0x04
132#define UART_RING 0x08
133#define UART_FRAME_ERROR 0x10
134#define UART_PARITY_ERROR 0x20
135#define UART_OVERRUN_ERROR 0x40
136#define UART_CTS 0x80
137
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
139enum pl2303_type {
140 type_0, /* don't know the difference between type 0 and */
141 type_1, /* type 1, until someone from prolific tells us... */
142 HX, /* HX version of the pl2303 chip */
143};
144
145struct pl2303_private {
146 spinlock_t lock;
147 struct pl2303_buf *buf;
148 int write_urb_in_use;
149 wait_queue_head_t delta_msr_wait;
150 u8 line_control;
151 u8 line_status;
152 u8 termios_initialized;
153 enum pl2303_type type;
154};
155
Thiago Galesi572d3132006-07-29 10:46:37 -0300156/*
157 * pl2303_buf_alloc
158 *
159 * Allocate a circular buffer and all associated memory.
160 */
161static struct pl2303_buf *pl2303_buf_alloc(unsigned int size)
162{
163 struct pl2303_buf *pb;
164
165 if (size == 0)
166 return NULL;
167
Robert P. J. Day5cbded52006-12-13 00:35:56 -0800168 pb = kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
Thiago Galesi572d3132006-07-29 10:46:37 -0300169 if (pb == NULL)
170 return NULL;
171
172 pb->buf_buf = kmalloc(size, GFP_KERNEL);
173 if (pb->buf_buf == NULL) {
174 kfree(pb);
175 return NULL;
176 }
177
178 pb->buf_size = size;
179 pb->buf_get = pb->buf_put = pb->buf_buf;
180
181 return pb;
182}
183
184/*
185 * pl2303_buf_free
186 *
187 * Free the buffer and all associated memory.
188 */
189static void pl2303_buf_free(struct pl2303_buf *pb)
190{
191 if (pb) {
192 kfree(pb->buf_buf);
193 kfree(pb);
194 }
195}
196
197/*
198 * pl2303_buf_clear
199 *
200 * Clear out all data in the circular buffer.
201 */
202static void pl2303_buf_clear(struct pl2303_buf *pb)
203{
204 if (pb != NULL)
205 pb->buf_get = pb->buf_put;
206 /* equivalent to a get of all data available */
207}
208
209/*
210 * pl2303_buf_data_avail
211 *
212 * Return the number of bytes of data available in the circular
213 * buffer.
214 */
215static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb)
216{
217 if (pb == NULL)
218 return 0;
219
220 return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
221}
222
223/*
224 * pl2303_buf_space_avail
225 *
226 * Return the number of bytes of space available in the circular
227 * buffer.
228 */
229static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb)
230{
231 if (pb == NULL)
232 return 0;
233
234 return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
235}
236
237/*
238 * pl2303_buf_put
239 *
240 * Copy data data from a user buffer and put it into the circular buffer.
241 * Restrict to the amount of space available.
242 *
243 * Return the number of bytes copied.
244 */
245static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
246 unsigned int count)
247{
248 unsigned int len;
249
250 if (pb == NULL)
251 return 0;
252
253 len = pl2303_buf_space_avail(pb);
254 if (count > len)
255 count = len;
256
257 if (count == 0)
258 return 0;
259
260 len = pb->buf_buf + pb->buf_size - pb->buf_put;
261 if (count > len) {
262 memcpy(pb->buf_put, buf, len);
263 memcpy(pb->buf_buf, buf+len, count - len);
264 pb->buf_put = pb->buf_buf + count - len;
265 } else {
266 memcpy(pb->buf_put, buf, count);
267 if (count < len)
268 pb->buf_put += count;
269 else /* count == len */
270 pb->buf_put = pb->buf_buf;
271 }
272
273 return count;
274}
275
276/*
277 * pl2303_buf_get
278 *
279 * Get data from the circular buffer and copy to the given buffer.
280 * Restrict to the amount of data available.
281 *
282 * Return the number of bytes copied.
283 */
284static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
285 unsigned int count)
286{
287 unsigned int len;
288
289 if (pb == NULL)
290 return 0;
291
292 len = pl2303_buf_data_avail(pb);
293 if (count > len)
294 count = len;
295
296 if (count == 0)
297 return 0;
298
299 len = pb->buf_buf + pb->buf_size - pb->buf_get;
300 if (count > len) {
301 memcpy(buf, pb->buf_get, len);
302 memcpy(buf+len, pb->buf_buf, count - len);
303 pb->buf_get = pb->buf_buf + count - len;
304 } else {
305 memcpy(buf, pb->buf_get, count);
306 if (count < len)
307 pb->buf_get += count;
308 else /* count == len */
309 pb->buf_get = pb->buf_buf;
310 }
311
312 return count;
313}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314
Sarah Sharpeb44da02007-12-14 14:08:00 -0800315static int pl2303_vendor_read(__u16 value, __u16 index,
316 struct usb_serial *serial, unsigned char *buf)
317{
318 int res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
319 VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE,
320 value, index, buf, 1, 100);
321 dbg("0x%x:0x%x:0x%x:0x%x %d - %x", VENDOR_READ_REQUEST_TYPE,
322 VENDOR_READ_REQUEST, value, index, res, buf[0]);
323 return res;
324}
325
326static int pl2303_vendor_write(__u16 value, __u16 index,
327 struct usb_serial *serial)
328{
329 int res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
330 VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE,
331 value, index, NULL, 0, 100);
332 dbg("0x%x:0x%x:0x%x:0x%x %d", VENDOR_WRITE_REQUEST_TYPE,
333 VENDOR_WRITE_REQUEST, value, index, res);
334 return res;
335}
336
Thiago Galesi372db8a2006-07-31 15:39:27 -0300337static int pl2303_startup(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338{
339 struct pl2303_private *priv;
340 enum pl2303_type type = type_0;
341 int i;
342
343 if (serial->dev->descriptor.bDeviceClass == 0x02)
344 type = type_0;
345 else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40)
346 type = HX;
347 else if (serial->dev->descriptor.bDeviceClass == 0x00)
348 type = type_1;
349 else if (serial->dev->descriptor.bDeviceClass == 0xFF)
350 type = type_1;
351 dbg("device type: %d", type);
352
353 for (i = 0; i < serial->num_ports; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100354 priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 if (!priv)
356 goto cleanup;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 spin_lock_init(&priv->lock);
358 priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE);
359 if (priv->buf == NULL) {
360 kfree(priv);
361 goto cleanup;
362 }
363 init_waitqueue_head(&priv->delta_msr_wait);
364 priv->type = type;
365 usb_set_serial_port_data(serial->port[i], priv);
366 }
367 return 0;
368
369cleanup:
370 for (--i; i>=0; --i) {
371 priv = usb_get_serial_port_data(serial->port[i]);
372 pl2303_buf_free(priv->buf);
373 kfree(priv);
374 usb_set_serial_port_data(serial->port[i], NULL);
375 }
376 return -ENOMEM;
377}
378
Thiago Galesi372db8a2006-07-31 15:39:27 -0300379static int set_control_lines(struct usb_device *dev, u8 value)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380{
381 int retval;
382
Thiago Galesi372db8a2006-07-31 15:39:27 -0300383 retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
384 SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
385 value, 0, NULL, 0, 100);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 dbg("%s - value = %d, retval = %d", __FUNCTION__, value, retval);
387 return retval;
388}
389
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390static void pl2303_send(struct usb_serial_port *port)
391{
392 int count, result;
393 struct pl2303_private *priv = usb_get_serial_port_data(port);
394 unsigned long flags;
395
396 dbg("%s - port %d", __FUNCTION__, port->number);
397
398 spin_lock_irqsave(&priv->lock, flags);
399
400 if (priv->write_urb_in_use) {
401 spin_unlock_irqrestore(&priv->lock, flags);
402 return;
403 }
404
405 count = pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer,
Thiago Galesi372db8a2006-07-31 15:39:27 -0300406 port->bulk_out_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407
408 if (count == 0) {
409 spin_unlock_irqrestore(&priv->lock, flags);
410 return;
411 }
412
413 priv->write_urb_in_use = 1;
414
415 spin_unlock_irqrestore(&priv->lock, flags);
416
Thiago Galesi372db8a2006-07-31 15:39:27 -0300417 usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count,
418 port->write_urb->transfer_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
420 port->write_urb->transfer_buffer_length = count;
421 port->write_urb->dev = port->serial->dev;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300422 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 if (result) {
Thiago Galesi372db8a2006-07-31 15:39:27 -0300424 dev_err(&port->dev, "%s - failed submitting write urb,"
425 " error %d\n", __FUNCTION__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 priv->write_urb_in_use = 0;
427 // TODO: reschedule pl2303_send
428 }
429
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700430 usb_serial_port_softint(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431}
432
Thiago Galesi572d3132006-07-29 10:46:37 -0300433static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf,
434 int count)
435{
436 struct pl2303_private *priv = usb_get_serial_port_data(port);
437 unsigned long flags;
438
439 dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
440
441 if (!count)
442 return count;
443
444 spin_lock_irqsave(&priv->lock, flags);
445 count = pl2303_buf_put(priv->buf, buf, count);
446 spin_unlock_irqrestore(&priv->lock, flags);
447
448 pl2303_send(port);
449
450 return count;
451}
452
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453static int pl2303_write_room(struct usb_serial_port *port)
454{
455 struct pl2303_private *priv = usb_get_serial_port_data(port);
456 int room = 0;
457 unsigned long flags;
458
459 dbg("%s - port %d", __FUNCTION__, port->number);
460
461 spin_lock_irqsave(&priv->lock, flags);
462 room = pl2303_buf_space_avail(priv->buf);
463 spin_unlock_irqrestore(&priv->lock, flags);
464
465 dbg("%s - returns %d", __FUNCTION__, room);
466 return room;
467}
468
469static int pl2303_chars_in_buffer(struct usb_serial_port *port)
470{
471 struct pl2303_private *priv = usb_get_serial_port_data(port);
472 int chars = 0;
473 unsigned long flags;
474
475 dbg("%s - port %d", __FUNCTION__, port->number);
476
477 spin_lock_irqsave(&priv->lock, flags);
478 chars = pl2303_buf_data_avail(priv->buf);
479 spin_unlock_irqrestore(&priv->lock, flags);
480
481 dbg("%s - returns %d", __FUNCTION__, chars);
482 return chars;
483}
484
Thiago Galesi372db8a2006-07-31 15:39:27 -0300485static void pl2303_set_termios(struct usb_serial_port *port,
Alan Cox606d0992006-12-08 02:38:45 -0800486 struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487{
488 struct usb_serial *serial = port->serial;
489 struct pl2303_private *priv = usb_get_serial_port_data(port);
490 unsigned long flags;
491 unsigned int cflag;
492 unsigned char *buf;
493 int baud;
494 int i;
495 u8 control;
496
497 dbg("%s - port %d", __FUNCTION__, port->number);
498
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 spin_lock_irqsave(&priv->lock, flags);
500 if (!priv->termios_initialized) {
501 *(port->tty->termios) = tty_std_termios;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300502 port->tty->termios->c_cflag = B9600 | CS8 | CREAD |
503 HUPCL | CLOCAL;
Alan Coxdf64c472007-10-15 20:54:47 +0100504 port->tty->termios->c_ispeed = 9600;
505 port->tty->termios->c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 priv->termios_initialized = 1;
507 }
508 spin_unlock_irqrestore(&priv->lock, flags);
509
Alan Coxbf5e5832008-01-08 14:55:51 +0000510 /* The PL2303 is reported to lose bytes if you change
511 serial settings even to the same values as before. Thus
512 we actually need to filter in this specific case */
513
514 if (!tty_termios_hw_change(port->tty->termios, old_termios))
515 return;
516
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 cflag = port->tty->termios->c_cflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518
Thiago Galesi372db8a2006-07-31 15:39:27 -0300519 buf = kzalloc(7, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 if (!buf) {
521 dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__);
522 return;
523 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
Thiago Galesi372db8a2006-07-31 15:39:27 -0300525 i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
526 GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
527 0, 0, buf, 7, 100);
528 dbg("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i,
529 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530
531 if (cflag & CSIZE) {
532 switch (cflag & CSIZE) {
533 case CS5: buf[6] = 5; break;
534 case CS6: buf[6] = 6; break;
535 case CS7: buf[6] = 7; break;
536 default:
537 case CS8: buf[6] = 8; break;
538 }
539 dbg("%s - data bits = %d", __FUNCTION__, buf[6]);
540 }
541
Alan Coxe0c79f52007-07-09 12:03:10 -0700542 baud = tty_get_baud_rate(port->tty);;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 dbg("%s - baud = %d", __FUNCTION__, baud);
544 if (baud) {
545 buf[0] = baud & 0xff;
546 buf[1] = (baud >> 8) & 0xff;
547 buf[2] = (baud >> 16) & 0xff;
548 buf[3] = (baud >> 24) & 0xff;
549 }
550
551 /* For reference buf[4]=0 is 1 stop bits */
552 /* For reference buf[4]=1 is 1.5 stop bits */
553 /* For reference buf[4]=2 is 2 stop bits */
554 if (cflag & CSTOPB) {
555 buf[4] = 2;
556 dbg("%s - stop bits = 2", __FUNCTION__);
557 } else {
558 buf[4] = 0;
559 dbg("%s - stop bits = 1", __FUNCTION__);
560 }
561
562 if (cflag & PARENB) {
563 /* For reference buf[5]=0 is none parity */
564 /* For reference buf[5]=1 is odd parity */
565 /* For reference buf[5]=2 is even parity */
566 /* For reference buf[5]=3 is mark parity */
567 /* For reference buf[5]=4 is space parity */
568 if (cflag & PARODD) {
569 buf[5] = 1;
570 dbg("%s - parity = odd", __FUNCTION__);
571 } else {
572 buf[5] = 2;
573 dbg("%s - parity = even", __FUNCTION__);
574 }
575 } else {
576 buf[5] = 0;
577 dbg("%s - parity = none", __FUNCTION__);
578 }
579
Thiago Galesi372db8a2006-07-31 15:39:27 -0300580 i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
581 SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE,
582 0, 0, buf, 7, 100);
583 dbg("0x21:0x20:0:0 %d", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584
585 /* change control lines if we are switching to or from B0 */
586 spin_lock_irqsave(&priv->lock, flags);
587 control = priv->line_control;
588 if ((cflag & CBAUD) == B0)
589 priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
590 else
591 priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
592 if (control != priv->line_control) {
593 control = priv->line_control;
594 spin_unlock_irqrestore(&priv->lock, flags);
595 set_control_lines(serial->dev, control);
596 } else {
597 spin_unlock_irqrestore(&priv->lock, flags);
598 }
Thiago Galesi372db8a2006-07-31 15:39:27 -0300599
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
601
Thiago Galesi372db8a2006-07-31 15:39:27 -0300602 i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
603 GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
604 0, 0, buf, 7, 100);
605 dbg("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
607
608 if (cflag & CRTSCTS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 if (priv->type == HX)
Sarah Sharpeb44da02007-12-14 14:08:00 -0800610 pl2303_vendor_write(0x0, 0x61, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 else
Sarah Sharpeb44da02007-12-14 14:08:00 -0800612 pl2303_vendor_write(0x0, 0x41, serial);
t.sefzick715f9522007-04-25 15:05:22 +0200613 } else {
Sarah Sharpeb44da02007-12-14 14:08:00 -0800614 pl2303_vendor_write(0x0, 0x0, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 }
616
Alan Coxdf64c472007-10-15 20:54:47 +0100617 /* FIXME: Need to read back resulting baud rate */
618 if (baud)
619 tty_encode_baud_rate(port->tty, baud, baud);
620
Thiago Galesi372db8a2006-07-31 15:39:27 -0300621 kfree(buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622}
623
Thiago Galesi572d3132006-07-29 10:46:37 -0300624static void pl2303_close(struct usb_serial_port *port, struct file *filp)
625{
626 struct pl2303_private *priv = usb_get_serial_port_data(port);
627 unsigned long flags;
628 unsigned int c_cflag;
629 int bps;
630 long timeout;
631 wait_queue_t wait;
632
633 dbg("%s - port %d", __FUNCTION__, port->number);
634
635 /* wait for data to drain from the buffer */
636 spin_lock_irqsave(&priv->lock, flags);
637 timeout = PL2303_CLOSING_WAIT;
638 init_waitqueue_entry(&wait, current);
639 add_wait_queue(&port->tty->write_wait, &wait);
640 for (;;) {
641 set_current_state(TASK_INTERRUPTIBLE);
642 if (pl2303_buf_data_avail(priv->buf) == 0 ||
643 timeout == 0 || signal_pending(current) ||
644 !usb_get_intfdata(port->serial->interface)) /* disconnect */
645 break;
646 spin_unlock_irqrestore(&priv->lock, flags);
647 timeout = schedule_timeout(timeout);
648 spin_lock_irqsave(&priv->lock, flags);
649 }
650 set_current_state(TASK_RUNNING);
651 remove_wait_queue(&port->tty->write_wait, &wait);
652 /* clear out any remaining data in the buffer */
653 pl2303_buf_clear(priv->buf);
654 spin_unlock_irqrestore(&priv->lock, flags);
655
656 /* wait for characters to drain from the device */
657 /* (this is long enough for the entire 256 byte */
658 /* pl2303 hardware buffer to drain with no flow */
659 /* control for data rates of 1200 bps or more, */
660 /* for lower rates we should really know how much */
661 /* data is in the buffer to compute a delay */
662 /* that is not unnecessarily long) */
663 bps = tty_get_baud_rate(port->tty);
664 if (bps > 1200)
665 timeout = max((HZ*2560)/bps,HZ/10);
666 else
667 timeout = 2*HZ;
668 schedule_timeout_interruptible(timeout);
669
670 /* shutdown our urbs */
671 dbg("%s - shutting down urbs", __FUNCTION__);
672 usb_kill_urb(port->write_urb);
673 usb_kill_urb(port->read_urb);
674 usb_kill_urb(port->interrupt_in_urb);
675
676 if (port->tty) {
677 c_cflag = port->tty->termios->c_cflag;
678 if (c_cflag & HUPCL) {
679 /* drop DTR and RTS */
680 spin_lock_irqsave(&priv->lock, flags);
681 priv->line_control = 0;
682 spin_unlock_irqrestore(&priv->lock, flags);
683 set_control_lines(port->serial->dev, 0);
684 }
685 }
686}
687
Thiago Galesi372db8a2006-07-31 15:39:27 -0300688static int pl2303_open(struct usb_serial_port *port, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689{
Alan Cox606d0992006-12-08 02:38:45 -0800690 struct ktermios tmp_termios;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 struct usb_serial *serial = port->serial;
692 struct pl2303_private *priv = usb_get_serial_port_data(port);
693 unsigned char *buf;
694 int result;
695
696 dbg("%s - port %d", __FUNCTION__, port->number);
697
Dariusz M16948992005-07-28 18:06:13 +0200698 if (priv->type != HX) {
699 usb_clear_halt(serial->dev, port->write_urb->pipe);
700 usb_clear_halt(serial->dev, port->read_urb->pipe);
701 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702
703 buf = kmalloc(10, GFP_KERNEL);
704 if (buf==NULL)
705 return -ENOMEM;
706
Sarah Sharpeb44da02007-12-14 14:08:00 -0800707 pl2303_vendor_read(0x8484, 0, serial, buf);
708 pl2303_vendor_write(0x0404, 0, serial);
709 pl2303_vendor_read(0x8484, 0, serial, buf);
710 pl2303_vendor_read(0x8383, 0, serial, buf);
711 pl2303_vendor_read(0x8484, 0, serial, buf);
712 pl2303_vendor_write(0x0404, 1, serial);
713 pl2303_vendor_read(0x8484, 0, serial, buf);
714 pl2303_vendor_read(0x8383, 0, serial, buf);
715 pl2303_vendor_write(0, 1, serial);
716 pl2303_vendor_write(1, 0, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717
718 if (priv->type == HX) {
719 /* HX chip */
Sarah Sharpeb44da02007-12-14 14:08:00 -0800720 pl2303_vendor_write(2, 0x44, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 /* reset upstream data pipes */
Sarah Sharpeb44da02007-12-14 14:08:00 -0800722 pl2303_vendor_write(8, 0, serial);
723 pl2303_vendor_write(9, 0, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 } else {
Sarah Sharpeb44da02007-12-14 14:08:00 -0800725 pl2303_vendor_write(2, 0x24, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 }
727
728 kfree(buf);
729
730 /* Setup termios */
731 if (port->tty) {
Thiago Galesi372db8a2006-07-31 15:39:27 -0300732 pl2303_set_termios(port, &tmp_termios);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 }
734
735 //FIXME: need to assert RTS and DTR if CRTSCTS off
736
737 dbg("%s - submitting read urb", __FUNCTION__);
738 port->read_urb->dev = serial->dev;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300739 result = usb_submit_urb(port->read_urb, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 if (result) {
Thiago Galesi372db8a2006-07-31 15:39:27 -0300741 dev_err(&port->dev, "%s - failed submitting read urb,"
742 " error %d\n", __FUNCTION__, result);
743 pl2303_close(port, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 return -EPROTO;
745 }
746
747 dbg("%s - submitting interrupt urb", __FUNCTION__);
748 port->interrupt_in_urb->dev = serial->dev;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300749 result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 if (result) {
Thiago Galesi372db8a2006-07-31 15:39:27 -0300751 dev_err(&port->dev, "%s - failed submitting interrupt urb,"
752 " error %d\n", __FUNCTION__, result);
753 pl2303_close(port, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 return -EPROTO;
755 }
756 return 0;
757}
758
Thiago Galesi372db8a2006-07-31 15:39:27 -0300759static int pl2303_tiocmset(struct usb_serial_port *port, struct file *file,
760 unsigned int set, unsigned int clear)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761{
762 struct pl2303_private *priv = usb_get_serial_port_data(port);
763 unsigned long flags;
764 u8 control;
765
Flavio Leitner6fdd8e82005-04-18 17:39:31 -0700766 if (!usb_get_intfdata(port->serial->interface))
767 return -ENODEV;
768
Thiago Galesi372db8a2006-07-31 15:39:27 -0300769 spin_lock_irqsave(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 if (set & TIOCM_RTS)
771 priv->line_control |= CONTROL_RTS;
772 if (set & TIOCM_DTR)
773 priv->line_control |= CONTROL_DTR;
774 if (clear & TIOCM_RTS)
775 priv->line_control &= ~CONTROL_RTS;
776 if (clear & TIOCM_DTR)
777 priv->line_control &= ~CONTROL_DTR;
778 control = priv->line_control;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300779 spin_unlock_irqrestore(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780
Thiago Galesi372db8a2006-07-31 15:39:27 -0300781 return set_control_lines(port->serial->dev, control);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782}
783
Thiago Galesi372db8a2006-07-31 15:39:27 -0300784static int pl2303_tiocmget(struct usb_serial_port *port, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785{
786 struct pl2303_private *priv = usb_get_serial_port_data(port);
787 unsigned long flags;
788 unsigned int mcr;
789 unsigned int status;
790 unsigned int result;
791
792 dbg("%s (%d)", __FUNCTION__, port->number);
793
Flavio Leitner6fdd8e82005-04-18 17:39:31 -0700794 if (!usb_get_intfdata(port->serial->interface))
795 return -ENODEV;
796
Thiago Galesi372db8a2006-07-31 15:39:27 -0300797 spin_lock_irqsave(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 mcr = priv->line_control;
799 status = priv->line_status;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300800 spin_unlock_irqrestore(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801
802 result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0)
803 | ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0)
804 | ((status & UART_CTS) ? TIOCM_CTS : 0)
805 | ((status & UART_DSR) ? TIOCM_DSR : 0)
806 | ((status & UART_RING) ? TIOCM_RI : 0)
807 | ((status & UART_DCD) ? TIOCM_CD : 0);
808
809 dbg("%s - result = %x", __FUNCTION__, result);
810
811 return result;
812}
813
814static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
815{
816 struct pl2303_private *priv = usb_get_serial_port_data(port);
817 unsigned long flags;
818 unsigned int prevstatus;
819 unsigned int status;
820 unsigned int changed;
821
Thiago Galesi372db8a2006-07-31 15:39:27 -0300822 spin_lock_irqsave(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 prevstatus = priv->line_status;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300824 spin_unlock_irqrestore(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825
826 while (1) {
827 interruptible_sleep_on(&priv->delta_msr_wait);
828 /* see if a signal did it */
829 if (signal_pending(current))
830 return -ERESTARTSYS;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300831
832 spin_lock_irqsave(&priv->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 status = priv->line_status;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300834 spin_unlock_irqrestore(&priv->lock, flags);
835
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 changed=prevstatus^status;
Thiago Galesi372db8a2006-07-31 15:39:27 -0300837
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 if (((arg & TIOCM_RNG) && (changed & UART_RING)) ||
839 ((arg & TIOCM_DSR) && (changed & UART_DSR)) ||
840 ((arg & TIOCM_CD) && (changed & UART_DCD)) ||
841 ((arg & TIOCM_CTS) && (changed & UART_CTS)) ) {
842 return 0;
843 }
844 prevstatus = status;
845 }
846 /* NOTREACHED */
847 return 0;
848}
849
Thiago Galesi372db8a2006-07-31 15:39:27 -0300850static int pl2303_ioctl(struct usb_serial_port *port, struct file *file,
851 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852{
853 dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd);
854
855 switch (cmd) {
856 case TIOCMIWAIT:
857 dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number);
858 return wait_modem_info(port, arg);
859
860 default:
861 dbg("%s not supported = 0x%04x", __FUNCTION__, cmd);
862 break;
863 }
864
865 return -ENOIOCTLCMD;
866}
867
Thiago Galesi372db8a2006-07-31 15:39:27 -0300868static void pl2303_break_ctl(struct usb_serial_port *port, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869{
870 struct usb_serial *serial = port->serial;
871 u16 state;
872 int result;
873
874 dbg("%s - port %d", __FUNCTION__, port->number);
875
876 if (break_state == 0)
877 state = BREAK_OFF;
878 else
879 state = BREAK_ON;
880 dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on");
881
Thiago Galesi372db8a2006-07-31 15:39:27 -0300882 result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
883 BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
884 0, NULL, 0, 100);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 if (result)
886 dbg("%s - error sending break = %d", __FUNCTION__, result);
887}
888
Thiago Galesi372db8a2006-07-31 15:39:27 -0300889static void pl2303_shutdown(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890{
891 int i;
892 struct pl2303_private *priv;
893
894 dbg("%s", __FUNCTION__);
895
896 for (i = 0; i < serial->num_ports; ++i) {
897 priv = usb_get_serial_port_data(serial->port[i]);
898 if (priv) {
899 pl2303_buf_free(priv->buf);
900 kfree(priv);
901 usb_set_serial_port_data(serial->port[i], NULL);
902 }
Thiago Galesi372db8a2006-07-31 15:39:27 -0300903 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904}
905
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700906static void pl2303_update_line_status(struct usb_serial_port *port,
907 unsigned char *data,
908 unsigned int actual_length)
909{
910
911 struct pl2303_private *priv = usb_get_serial_port_data(port);
912 unsigned long flags;
913 u8 status_idx = UART_STATE;
Horst Schirmeier95f209f2005-07-28 15:32:20 +0200914 u8 length = UART_STATE + 1;
Thiago Galesi9c537612006-07-29 10:47:12 -0300915 u16 idv, idp;
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700916
Thiago Galesi9c537612006-07-29 10:47:12 -0300917 idv = le16_to_cpu(port->serial->dev->descriptor.idVendor);
918 idp = le16_to_cpu(port->serial->dev->descriptor.idProduct);
919
920
921 if (idv == SIEMENS_VENDOR_ID) {
922 if (idp == SIEMENS_PRODUCT_ID_X65 ||
923 idp == SIEMENS_PRODUCT_ID_SX1 ||
924 idp == SIEMENS_PRODUCT_ID_X75) {
925
926 length = 1;
927 status_idx = 0;
928 }
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700929 }
930
931 if (actual_length < length)
Luiz Fernando N. Capitulinoa009b752006-07-25 16:58:30 -0300932 return;
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700933
934 /* Save off the uart status for others to look at */
935 spin_lock_irqsave(&priv->lock, flags);
936 priv->line_status = data[status_idx];
937 spin_unlock_irqrestore(&priv->lock, flags);
Thiago Galesi372db8a2006-07-31 15:39:27 -0300938 wake_up_interruptible(&priv->delta_msr_wait);
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700939}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940
David Howells7d12e782006-10-05 14:55:46 +0100941static void pl2303_read_int_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942{
943 struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 unsigned char *data = urb->transfer_buffer;
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700945 unsigned int actual_length = urb->actual_length;
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700946 int status = urb->status;
947 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948
949 dbg("%s (%d)", __FUNCTION__, port->number);
950
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700951 switch (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 case 0:
953 /* success */
954 break;
955 case -ECONNRESET:
956 case -ENOENT:
957 case -ESHUTDOWN:
958 /* this urb is terminated, clean up */
Thiago Galesi372db8a2006-07-31 15:39:27 -0300959 dbg("%s - urb shutting down with status: %d", __FUNCTION__,
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700960 status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 return;
962 default:
Thiago Galesi372db8a2006-07-31 15:39:27 -0300963 dbg("%s - nonzero urb status received: %d", __FUNCTION__,
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700964 status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 goto exit;
966 }
967
Thiago Galesi372db8a2006-07-31 15:39:27 -0300968 usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
969 urb->actual_length, urb->transfer_buffer);
970
Flavio Leitner97bb13e2005-04-18 17:39:31 -0700971 pl2303_update_line_status(port, data, actual_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973exit:
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700974 retval = usb_submit_urb(urb, GFP_ATOMIC);
975 if (retval)
Thiago Galesi372db8a2006-07-31 15:39:27 -0300976 dev_err(&urb->dev->dev,
977 "%s - usb_submit_urb failed with result %d\n",
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700978 __FUNCTION__, retval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979}
980
David Howells7d12e782006-10-05 14:55:46 +0100981static void pl2303_read_bulk_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982{
983 struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
984 struct pl2303_private *priv = usb_get_serial_port_data(port);
985 struct tty_struct *tty;
986 unsigned char *data = urb->transfer_buffer;
987 unsigned long flags;
988 int i;
989 int result;
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700990 int status = urb->status;
991 u8 line_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 char tty_flag;
993
994 dbg("%s - port %d", __FUNCTION__, port->number);
995
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -0700996 if (status) {
997 dbg("%s - urb status = %d", __FUNCTION__, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 if (!port->open_count) {
999 dbg("%s - port is closed, exiting.", __FUNCTION__);
1000 return;
1001 }
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001002 if (status == -EPROTO) {
Thiago Galesi372db8a2006-07-31 15:39:27 -03001003 /* PL2303 mysteriously fails with -EPROTO reschedule
1004 * the read */
1005 dbg("%s - caught -EPROTO, resubmitting the urb",
1006 __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 urb->dev = port->serial->dev;
1008 result = usb_submit_urb(urb, GFP_ATOMIC);
1009 if (result)
Thiago Galesi372db8a2006-07-31 15:39:27 -03001010 dev_err(&urb->dev->dev, "%s - failed"
1011 " resubmitting read urb, error %d\n",
1012 __FUNCTION__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 return;
1014 }
1015 dbg("%s - unable to handle the error, exiting.", __FUNCTION__);
1016 return;
1017 }
1018
Thiago Galesi372db8a2006-07-31 15:39:27 -03001019 usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
1020 urb->actual_length, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021
1022 /* get tty_flag from status */
1023 tty_flag = TTY_NORMAL;
1024
1025 spin_lock_irqsave(&priv->lock, flags);
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001026 line_status = priv->line_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
1028 spin_unlock_irqrestore(&priv->lock, flags);
Thiago Galesi372db8a2006-07-31 15:39:27 -03001029 wake_up_interruptible(&priv->delta_msr_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030
1031 /* break takes precedence over parity, */
1032 /* which takes precedence over framing errors */
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001033 if (line_status & UART_BREAK_ERROR )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 tty_flag = TTY_BREAK;
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001035 else if (line_status & UART_PARITY_ERROR)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 tty_flag = TTY_PARITY;
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001037 else if (line_status & UART_FRAME_ERROR)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 tty_flag = TTY_FRAME;
1039 dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag);
1040
1041 tty = port->tty;
1042 if (tty && urb->actual_length) {
Alan Cox33f0f882006-01-09 20:54:13 -08001043 tty_buffer_request_room(tty, urb->actual_length + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 /* overrun is special, not associated with a char */
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001045 if (line_status & UART_OVERRUN_ERROR)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
Alan Cox33f0f882006-01-09 20:54:13 -08001047 for (i = 0; i < urb->actual_length; ++i)
Thiago Galesi372db8a2006-07-31 15:39:27 -03001048 tty_insert_flip_char(tty, data[i], tty_flag);
1049 tty_flip_buffer_push(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 }
1051
1052 /* Schedule the next read _if_ we are still open */
1053 if (port->open_count) {
1054 urb->dev = port->serial->dev;
1055 result = usb_submit_urb(urb, GFP_ATOMIC);
1056 if (result)
Thiago Galesi372db8a2006-07-31 15:39:27 -03001057 dev_err(&urb->dev->dev, "%s - failed resubmitting"
1058 " read urb, error %d\n", __FUNCTION__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 }
1060
1061 return;
1062}
1063
David Howells7d12e782006-10-05 14:55:46 +01001064static void pl2303_write_bulk_callback(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065{
1066 struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
1067 struct pl2303_private *priv = usb_get_serial_port_data(port);
1068 int result;
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001069 int status = urb->status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070
1071 dbg("%s - port %d", __FUNCTION__, port->number);
1072
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001073 switch (status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 case 0:
1075 /* success */
1076 break;
1077 case -ECONNRESET:
1078 case -ENOENT:
1079 case -ESHUTDOWN:
1080 /* this urb is terminated, clean up */
Thiago Galesi372db8a2006-07-31 15:39:27 -03001081 dbg("%s - urb shutting down with status: %d", __FUNCTION__,
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001082 status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 priv->write_urb_in_use = 0;
1084 return;
1085 default:
1086 /* error in the urb, so we have to resubmit it */
1087 dbg("%s - Overflow in write", __FUNCTION__);
Thiago Galesi372db8a2006-07-31 15:39:27 -03001088 dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
Greg Kroah-Hartman461d6962007-06-15 15:44:13 -07001089 status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 port->write_urb->transfer_buffer_length = 1;
1091 port->write_urb->dev = port->serial->dev;
Thiago Galesi372db8a2006-07-31 15:39:27 -03001092 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 if (result)
Thiago Galesi372db8a2006-07-31 15:39:27 -03001094 dev_err(&urb->dev->dev, "%s - failed resubmitting write"
1095 " urb, error %d\n", __FUNCTION__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 else
1097 return;
1098 }
1099
1100 priv->write_urb_in_use = 0;
1101
1102 /* send any buffered data */
1103 pl2303_send(port);
1104}
1105
Thiago Galesi572d3132006-07-29 10:46:37 -03001106/* All of the device info needed for the PL2303 SIO serial converter */
1107static struct usb_serial_driver pl2303_device = {
1108 .driver = {
1109 .owner = THIS_MODULE,
1110 .name = "pl2303",
1111 },
1112 .id_table = id_table,
Johannes Hölzld9b1b782006-12-17 21:50:24 +01001113 .usb_driver = &pl2303_driver,
Thiago Galesi572d3132006-07-29 10:46:37 -03001114 .num_interrupt_in = NUM_DONT_CARE,
1115 .num_bulk_in = 1,
1116 .num_bulk_out = 1,
1117 .num_ports = 1,
1118 .open = pl2303_open,
1119 .close = pl2303_close,
1120 .write = pl2303_write,
1121 .ioctl = pl2303_ioctl,
1122 .break_ctl = pl2303_break_ctl,
1123 .set_termios = pl2303_set_termios,
1124 .tiocmget = pl2303_tiocmget,
1125 .tiocmset = pl2303_tiocmset,
1126 .read_bulk_callback = pl2303_read_bulk_callback,
1127 .read_int_callback = pl2303_read_int_callback,
1128 .write_bulk_callback = pl2303_write_bulk_callback,
1129 .write_room = pl2303_write_room,
1130 .chars_in_buffer = pl2303_chars_in_buffer,
1131 .attach = pl2303_startup,
1132 .shutdown = pl2303_shutdown,
1133};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134
Thiago Galesi372db8a2006-07-31 15:39:27 -03001135static int __init pl2303_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136{
1137 int retval;
Thiago Galesi372db8a2006-07-31 15:39:27 -03001138
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 retval = usb_serial_register(&pl2303_device);
1140 if (retval)
1141 goto failed_usb_serial_register;
1142 retval = usb_register(&pl2303_driver);
1143 if (retval)
1144 goto failed_usb_register;
Greg Kroah-Hartman17a882f2005-06-20 21:15:16 -07001145 info(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 return 0;
1147failed_usb_register:
1148 usb_serial_deregister(&pl2303_device);
1149failed_usb_serial_register:
1150 return retval;
1151}
1152
Thiago Galesi372db8a2006-07-31 15:39:27 -03001153static void __exit pl2303_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154{
Thiago Galesi372db8a2006-07-31 15:39:27 -03001155 usb_deregister(&pl2303_driver);
1156 usb_serial_deregister(&pl2303_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157}
1158
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159module_init(pl2303_init);
1160module_exit(pl2303_exit);
1161
1162MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163MODULE_LICENSE("GPL");
1164
1165module_param(debug, bool, S_IRUGO | S_IWUSR);
1166MODULE_PARM_DESC(debug, "Debug enabled or not");
1167