]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Prolific PL2303 USB to serial adaptor driver | |
3 | * | |
4d0dce3e | 4 | * Copyright (C) 2001-2007 Greg Kroah-Hartman (greg@kroah.com) |
1da177e4 LT |
5 | * Copyright (C) 2003 IBM Corp. |
6 | * | |
7 | * Original driver for 2.2.x by anonymous | |
8 | * | |
4d0dce3e GKH |
9 | * 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. | |
1da177e4 | 12 | * |
3a0f43e9 AC |
13 | * See Documentation/usb/usb-serial.txt for more information on using this |
14 | * driver | |
1da177e4 LT |
15 | */ |
16 | ||
1da177e4 LT |
17 | #include <linux/kernel.h> |
18 | #include <linux/errno.h> | |
1da177e4 LT |
19 | #include <linux/slab.h> |
20 | #include <linux/tty.h> | |
21 | #include <linux/tty_driver.h> | |
22 | #include <linux/tty_flip.h> | |
23 | #include <linux/serial.h> | |
24 | #include <linux/module.h> | |
25 | #include <linux/moduleparam.h> | |
26 | #include <linux/spinlock.h> | |
3a0f43e9 | 27 | #include <linux/uaccess.h> |
1da177e4 | 28 | #include <linux/usb.h> |
a969888c | 29 | #include <linux/usb/serial.h> |
b2d6d98f | 30 | #include <asm/unaligned.h> |
1da177e4 LT |
31 | #include "pl2303.h" |
32 | ||
228e4105 JH |
33 | |
34 | #define PL2303_QUIRK_UART_STATE_IDX0 BIT(0) | |
23c6acb9 | 35 | #define PL2303_QUIRK_LEGACY BIT(1) |
228e4105 | 36 | |
7d40d7e8 | 37 | static const struct usb_device_id id_table[] = { |
1da177e4 LT |
38 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) }, |
39 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) }, | |
3d861494 | 40 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11) }, |
1da177e4 LT |
41 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) }, |
42 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) }, | |
b483b6aa | 43 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ALDIGA) }, |
4be2fa18 | 44 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MMX) }, |
727df356 | 45 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_GPRS) }, |
18344a1c | 46 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) }, |
96a3e79e | 47 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) }, |
1da177e4 | 48 | { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, |
8a28dea3 | 49 | { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, |
1da177e4 LT |
50 | { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, |
51 | { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) }, | |
52 | { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) }, | |
53 | { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) }, | |
54 | { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) }, | |
58381719 | 55 | { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID_2080) }, |
1da177e4 LT |
56 | { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) }, |
57 | { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) }, | |
58 | { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) }, | |
59 | { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) }, | |
60 | { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) }, | |
61 | { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) }, | |
62 | { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) }, | |
63 | { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) }, | |
228e4105 JH |
64 | { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1), |
65 | .driver_info = PL2303_QUIRK_UART_STATE_IDX0 }, | |
66 | { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65), | |
67 | .driver_info = PL2303_QUIRK_UART_STATE_IDX0 }, | |
68 | { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75), | |
69 | .driver_info = PL2303_QUIRK_UART_STATE_IDX0 }, | |
e7beb667 | 70 | { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_EF81) }, |
912299f6 | 71 | { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_ID_S81) }, /* Benq/Siemens S81 */ |
acbb36f1 | 72 | { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) }, |
c6c27721 CL |
73 | { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) }, |
74 | { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID) }, | |
6cceb05f | 75 | { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) }, |
c6c27721 | 76 | { USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) }, |
491b04ce | 77 | { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) }, |
3b928474 | 78 | { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) }, |
b7aa94b6 | 79 | { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, |
8fd80133 | 80 | { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) }, |
2d94b981 | 81 | { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) }, |
9e3285db | 82 | { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) }, |
cc311ee7 | 83 | { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, |
7c992001 | 84 | { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, |
af4b8514 | 85 | { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, |
b16c02fb AS |
86 | { USB_DEVICE(HP_VENDOR_ID, HP_LD960_PRODUCT_ID) }, |
87 | { USB_DEVICE(HP_VENDOR_ID, HP_LCM220_PRODUCT_ID) }, | |
88 | { USB_DEVICE(HP_VENDOR_ID, HP_LCM960_PRODUCT_ID) }, | |
8540d666 | 89 | { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) }, |
f36ecd5d | 90 | { USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) }, |
49276560 | 91 | { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) }, |
35904e6b | 92 | { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) }, |
9a61d726 | 93 | { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) }, |
598f0b70 | 94 | { USB_DEVICE(SMART_VENDOR_ID, SMART_PRODUCT_ID) }, |
1da177e4 LT |
95 | { } /* Terminating entry */ |
96 | }; | |
97 | ||
372db8a7 | 98 | MODULE_DEVICE_TABLE(usb, id_table); |
1da177e4 | 99 | |
1da177e4 LT |
100 | #define SET_LINE_REQUEST_TYPE 0x21 |
101 | #define SET_LINE_REQUEST 0x20 | |
102 | ||
103 | #define SET_CONTROL_REQUEST_TYPE 0x21 | |
104 | #define SET_CONTROL_REQUEST 0x22 | |
105 | #define CONTROL_DTR 0x01 | |
106 | #define CONTROL_RTS 0x02 | |
107 | ||
108 | #define BREAK_REQUEST_TYPE 0x21 | |
3a0f43e9 | 109 | #define BREAK_REQUEST 0x23 |
1da177e4 LT |
110 | #define BREAK_ON 0xffff |
111 | #define BREAK_OFF 0x0000 | |
112 | ||
113 | #define GET_LINE_REQUEST_TYPE 0xa1 | |
114 | #define GET_LINE_REQUEST 0x21 | |
115 | ||
116 | #define VENDOR_WRITE_REQUEST_TYPE 0x40 | |
117 | #define VENDOR_WRITE_REQUEST 0x01 | |
118 | ||
119 | #define VENDOR_READ_REQUEST_TYPE 0xc0 | |
120 | #define VENDOR_READ_REQUEST 0x01 | |
121 | ||
228e4105 | 122 | #define UART_STATE_INDEX 8 |
dbfd2866 | 123 | #define UART_STATE_MSR_MASK 0x8b |
1da177e4 LT |
124 | #define UART_STATE_TRANSIENT_MASK 0x74 |
125 | #define UART_DCD 0x01 | |
126 | #define UART_DSR 0x02 | |
127 | #define UART_BREAK_ERROR 0x04 | |
128 | #define UART_RING 0x08 | |
129 | #define UART_FRAME_ERROR 0x10 | |
130 | #define UART_PARITY_ERROR 0x20 | |
131 | #define UART_OVERRUN_ERROR 0x40 | |
132 | #define UART_CTS 0x80 | |
133 | ||
1da177e4 LT |
134 | |
135 | enum pl2303_type { | |
7f966ac7 JH |
136 | TYPE_01, /* Type 0 and 1 (difference unknown) */ |
137 | TYPE_HX, /* HX version of the pl2303 chip */ | |
359defda JH |
138 | TYPE_COUNT |
139 | }; | |
140 | ||
141 | struct pl2303_type_data { | |
142 | speed_t max_baud_rate; | |
143 | unsigned long quirks; | |
1da177e4 LT |
144 | }; |
145 | ||
8bf769eb | 146 | struct pl2303_serial_private { |
b6934681 | 147 | const struct pl2303_type_data *type; |
228e4105 | 148 | unsigned long quirks; |
8bf769eb JH |
149 | }; |
150 | ||
1da177e4 LT |
151 | struct pl2303_private { |
152 | spinlock_t lock; | |
1da177e4 LT |
153 | u8 line_control; |
154 | u8 line_status; | |
623c8263 JH |
155 | |
156 | u8 line_settings[7]; | |
1da177e4 LT |
157 | }; |
158 | ||
b6934681 | 159 | static const struct pl2303_type_data pl2303_type_data[TYPE_COUNT] = { |
359defda JH |
160 | [TYPE_01] = { |
161 | .max_baud_rate = 1228800, | |
162 | .quirks = PL2303_QUIRK_LEGACY, | |
163 | }, | |
164 | }; | |
165 | ||
362eb026 JH |
166 | static int pl2303_vendor_read(struct usb_serial *serial, u16 value, |
167 | unsigned char buf[1]) | |
eb44da0b | 168 | { |
362eb026 | 169 | struct device *dev = &serial->interface->dev; |
ccfe8188 JH |
170 | int res; |
171 | ||
172 | res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | |
eb44da0b | 173 | VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE, |
362eb026 JH |
174 | value, 0, buf, 1, 100); |
175 | if (res != 1) { | |
176 | dev_err(dev, "%s - failed to read [%04x]: %d\n", __func__, | |
177 | value, res); | |
178 | if (res >= 0) | |
179 | res = -EIO; | |
180 | ||
181 | return res; | |
182 | } | |
ccfe8188 | 183 | |
362eb026 | 184 | dev_dbg(dev, "%s - [%04x] = %02x\n", __func__, value, buf[0]); |
ccfe8188 | 185 | |
362eb026 | 186 | return 0; |
eb44da0b SS |
187 | } |
188 | ||
362eb026 | 189 | static int pl2303_vendor_write(struct usb_serial *serial, u16 value, u16 index) |
eb44da0b | 190 | { |
362eb026 | 191 | struct device *dev = &serial->interface->dev; |
ccfe8188 JH |
192 | int res; |
193 | ||
362eb026 JH |
194 | dev_dbg(dev, "%s - [%04x] = %02x\n", __func__, value, index); |
195 | ||
ccfe8188 | 196 | res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), |
eb44da0b SS |
197 | VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE, |
198 | value, index, NULL, 0, 100); | |
362eb026 JH |
199 | if (res) { |
200 | dev_err(dev, "%s - failed to write [%04x]: %d\n", __func__, | |
201 | value, res); | |
202 | return res; | |
203 | } | |
ccfe8188 | 204 | |
362eb026 | 205 | return 0; |
eb44da0b SS |
206 | } |
207 | ||
228e4105 JH |
208 | static int pl2303_probe(struct usb_serial *serial, |
209 | const struct usb_device_id *id) | |
210 | { | |
211 | usb_set_serial_data(serial, (void *)id->driver_info); | |
212 | ||
213 | return 0; | |
214 | } | |
215 | ||
372db8a7 | 216 | static int pl2303_startup(struct usb_serial *serial) |
1da177e4 | 217 | { |
8bf769eb | 218 | struct pl2303_serial_private *spriv; |
7f966ac7 | 219 | enum pl2303_type type = TYPE_01; |
3e152505 | 220 | unsigned char *buf; |
8bf769eb JH |
221 | |
222 | spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); | |
223 | if (!spriv) | |
224 | return -ENOMEM; | |
1da177e4 | 225 | |
362eb026 | 226 | buf = kmalloc(1, GFP_KERNEL); |
8bf769eb JH |
227 | if (!buf) { |
228 | kfree(spriv); | |
3e152505 | 229 | return -ENOMEM; |
8bf769eb | 230 | } |
3e152505 | 231 | |
b52e1113 | 232 | if (serial->dev->descriptor.bDeviceClass == 0x02) |
7f966ac7 | 233 | type = TYPE_01; /* type 0 */ |
b52e1113 | 234 | else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40) |
7f966ac7 | 235 | type = TYPE_HX; |
281393ad | 236 | else if (serial->dev->descriptor.bDeviceClass == 0x00) |
7f966ac7 | 237 | type = TYPE_01; /* type 1 */ |
281393ad | 238 | else if (serial->dev->descriptor.bDeviceClass == 0xFF) |
7f966ac7 | 239 | type = TYPE_01; /* type 1 */ |
b52e1113 | 240 | dev_dbg(&serial->interface->dev, "device type: %d\n", type); |
1da177e4 | 241 | |
359defda | 242 | spriv->type = &pl2303_type_data[type]; |
228e4105 | 243 | spriv->quirks = (unsigned long)usb_get_serial_data(serial); |
359defda | 244 | spriv->quirks |= spriv->type->quirks; |
228e4105 | 245 | |
8bf769eb | 246 | usb_set_serial_data(serial, spriv); |
3e152505 | 247 | |
362eb026 JH |
248 | pl2303_vendor_read(serial, 0x8484, buf); |
249 | pl2303_vendor_write(serial, 0x0404, 0); | |
250 | pl2303_vendor_read(serial, 0x8484, buf); | |
251 | pl2303_vendor_read(serial, 0x8383, buf); | |
252 | pl2303_vendor_read(serial, 0x8484, buf); | |
253 | pl2303_vendor_write(serial, 0x0404, 1); | |
254 | pl2303_vendor_read(serial, 0x8484, buf); | |
255 | pl2303_vendor_read(serial, 0x8383, buf); | |
256 | pl2303_vendor_write(serial, 0, 1); | |
257 | pl2303_vendor_write(serial, 1, 0); | |
23c6acb9 | 258 | if (spriv->quirks & PL2303_QUIRK_LEGACY) |
362eb026 | 259 | pl2303_vendor_write(serial, 2, 0x24); |
7f966ac7 JH |
260 | else |
261 | pl2303_vendor_write(serial, 2, 0x44); | |
3e152505 SS |
262 | |
263 | kfree(buf); | |
ccfe8188 | 264 | |
1da177e4 | 265 | return 0; |
8bf769eb | 266 | } |
1da177e4 | 267 | |
8bf769eb JH |
268 | static void pl2303_release(struct usb_serial *serial) |
269 | { | |
ccfe8188 | 270 | struct pl2303_serial_private *spriv = usb_get_serial_data(serial); |
8bf769eb | 271 | |
8bf769eb JH |
272 | kfree(spriv); |
273 | } | |
274 | ||
275 | static int pl2303_port_probe(struct usb_serial_port *port) | |
276 | { | |
277 | struct pl2303_private *priv; | |
278 | ||
279 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | |
280 | if (!priv) | |
281 | return -ENOMEM; | |
282 | ||
283 | spin_lock_init(&priv->lock); | |
8bf769eb JH |
284 | |
285 | usb_set_serial_port_data(port, priv); | |
286 | ||
d7be6221 JH |
287 | port->port.drain_delay = 256; |
288 | ||
8bf769eb JH |
289 | return 0; |
290 | } | |
291 | ||
292 | static int pl2303_port_remove(struct usb_serial_port *port) | |
293 | { | |
ccfe8188 | 294 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
8bf769eb | 295 | |
8bf769eb JH |
296 | kfree(priv); |
297 | ||
298 | return 0; | |
1da177e4 LT |
299 | } |
300 | ||
f45d0a5a | 301 | static int pl2303_set_control_lines(struct usb_serial_port *port, u8 value) |
1da177e4 | 302 | { |
f45d0a5a | 303 | struct usb_device *dev = port->serial->dev; |
1da177e4 | 304 | int retval; |
3a0f43e9 | 305 | |
a6ec8245 JH |
306 | dev_dbg(&port->dev, "%s - %02x\n", __func__, value); |
307 | ||
372db8a7 TG |
308 | retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
309 | SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE, | |
310 | value, 0, NULL, 0, 100); | |
a6ec8245 JH |
311 | if (retval) |
312 | dev_err(&port->dev, "%s - failed: %d\n", __func__, retval); | |
ccfe8188 | 313 | |
1da177e4 LT |
314 | return retval; |
315 | } | |
316 | ||
59afe10e | 317 | /* |
5d85045f JH |
318 | * Returns the nearest supported baud rate that can be set directly without |
319 | * using divisors. | |
59afe10e JH |
320 | */ |
321 | static speed_t pl2303_get_supported_baud_rate(speed_t baud) | |
1da177e4 | 322 | { |
59afe10e JH |
323 | static const speed_t baud_sup[] = { |
324 | 75, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600, | |
325 | 14400, 19200, 28800, 38400, 57600, 115200, 230400, 460800, | |
5d85045f | 326 | 614400, 921600, 1228800, 2457600, 3000000, 6000000 |
59afe10e | 327 | }; |
1da177e4 | 328 | |
59afe10e | 329 | unsigned i; |
692ed4dd | 330 | |
7e12a6fc GKH |
331 | for (i = 0; i < ARRAY_SIZE(baud_sup); ++i) { |
332 | if (baud_sup[i] > baud) | |
333 | break; | |
334 | } | |
692ed4dd | 335 | |
7e12a6fc GKH |
336 | if (i == ARRAY_SIZE(baud_sup)) |
337 | baud = baud_sup[i - 1]; | |
338 | else if (i > 0 && (baud_sup[i] - baud) > (baud - baud_sup[i - 1])) | |
339 | baud = baud_sup[i - 1]; | |
340 | else | |
341 | baud = baud_sup[i]; | |
692ed4dd | 342 | |
59afe10e JH |
343 | return baud; |
344 | } | |
345 | ||
20b4c787 JH |
346 | /* |
347 | * NOTE: If unsupported baud rates are set directly, the PL2303 seems to | |
348 | * use 9600 baud. | |
349 | */ | |
350 | static speed_t pl2303_encode_baud_rate_direct(unsigned char buf[4], | |
351 | speed_t baud) | |
352 | { | |
353 | put_unaligned_le32(baud, buf); | |
354 | ||
355 | return baud; | |
356 | } | |
357 | ||
c82c6d45 JH |
358 | static speed_t pl2303_encode_baud_rate_divisor(unsigned char buf[4], |
359 | speed_t baud) | |
360 | { | |
361 | unsigned int tmp; | |
362 | ||
363 | /* | |
364 | * Apparently the formula is: | |
365 | * baudrate = 12M * 32 / (2^buf[1]) / buf[0] | |
366 | */ | |
367 | tmp = 12000000 * 32 / baud; | |
368 | buf[3] = 0x80; | |
369 | buf[2] = 0; | |
370 | buf[1] = (tmp >= 256); | |
371 | while (tmp >= 256) { | |
372 | tmp >>= 2; | |
373 | buf[1] <<= 1; | |
374 | } | |
375 | buf[0] = tmp; | |
376 | ||
377 | return baud; | |
378 | } | |
379 | ||
59afe10e JH |
380 | static void pl2303_encode_baud_rate(struct tty_struct *tty, |
381 | struct usb_serial_port *port, | |
382 | u8 buf[4]) | |
383 | { | |
384 | struct usb_serial *serial = port->serial; | |
385 | struct pl2303_serial_private *spriv = usb_get_serial_data(serial); | |
5d85045f | 386 | speed_t baud_sup; |
59afe10e JH |
387 | speed_t baud; |
388 | ||
389 | baud = tty_get_baud_rate(tty); | |
390 | dev_dbg(&port->dev, "baud requested = %u\n", baud); | |
391 | if (!baud) | |
392 | return; | |
871996ed JH |
393 | |
394 | if (spriv->type->max_baud_rate) | |
395 | baud = min_t(speed_t, baud, spriv->type->max_baud_rate); | |
5d85045f JH |
396 | /* |
397 | * Set baud rate to nearest supported value. | |
398 | * | |
399 | * NOTE: Baud rate 500k can only be set using divisors. | |
400 | */ | |
401 | baud_sup = pl2303_get_supported_baud_rate(baud); | |
20b4c787 | 402 | |
5d85045f | 403 | if (baud == 500000) |
c82c6d45 | 404 | baud = pl2303_encode_baud_rate_divisor(buf, baud); |
5d85045f JH |
405 | else |
406 | baud = pl2303_encode_baud_rate_direct(buf, baud_sup); | |
692ed4dd | 407 | |
15e7cead | 408 | /* Save resulting baud rate */ |
b2d6d98f | 409 | tty_encode_baud_rate(tty, baud, baud); |
f84ee3b2 | 410 | dev_dbg(&port->dev, "baud set = %u\n", baud); |
15e7cead JH |
411 | } |
412 | ||
383d19c5 JH |
413 | static int pl2303_get_line_request(struct usb_serial_port *port, |
414 | unsigned char buf[7]) | |
415 | { | |
416 | struct usb_device *udev = port->serial->dev; | |
417 | int ret; | |
418 | ||
419 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | |
420 | GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, | |
421 | 0, 0, buf, 7, 100); | |
422 | if (ret != 7) { | |
423 | dev_err(&port->dev, "%s - failed: %d\n", __func__, ret); | |
424 | ||
425 | if (ret > 0) | |
426 | ret = -EIO; | |
427 | ||
428 | return ret; | |
429 | } | |
430 | ||
431 | dev_dbg(&port->dev, "%s - %7ph\n", __func__, buf); | |
432 | ||
433 | return 0; | |
434 | } | |
435 | ||
436 | static int pl2303_set_line_request(struct usb_serial_port *port, | |
437 | unsigned char buf[7]) | |
438 | { | |
439 | struct usb_device *udev = port->serial->dev; | |
440 | int ret; | |
441 | ||
442 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | |
443 | SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE, | |
444 | 0, 0, buf, 7, 100); | |
445 | if (ret != 7) { | |
446 | dev_err(&port->dev, "%s - failed: %d\n", __func__, ret); | |
447 | ||
448 | if (ret > 0) | |
449 | ret = -EIO; | |
450 | ||
451 | return ret; | |
452 | } | |
453 | ||
454 | dev_dbg(&port->dev, "%s - %7ph\n", __func__, buf); | |
455 | ||
456 | return 0; | |
457 | } | |
458 | ||
15e7cead JH |
459 | static void pl2303_set_termios(struct tty_struct *tty, |
460 | struct usb_serial_port *port, struct ktermios *old_termios) | |
461 | { | |
462 | struct usb_serial *serial = port->serial; | |
463 | struct pl2303_serial_private *spriv = usb_get_serial_data(serial); | |
464 | struct pl2303_private *priv = usb_get_serial_port_data(port); | |
465 | unsigned long flags; | |
15e7cead | 466 | unsigned char *buf; |
383d19c5 | 467 | int ret; |
15e7cead JH |
468 | u8 control; |
469 | ||
15e7cead JH |
470 | if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios)) |
471 | return; | |
472 | ||
15e7cead JH |
473 | buf = kzalloc(7, GFP_KERNEL); |
474 | if (!buf) { | |
15e7cead JH |
475 | /* Report back no change occurred */ |
476 | if (old_termios) | |
477 | tty->termios = *old_termios; | |
478 | return; | |
479 | } | |
480 | ||
383d19c5 | 481 | pl2303_get_line_request(port, buf); |
15e7cead | 482 | |
a3132499 CL |
483 | switch (C_CSIZE(tty)) { |
484 | case CS5: | |
485 | buf[6] = 5; | |
486 | break; | |
487 | case CS6: | |
488 | buf[6] = 6; | |
489 | break; | |
490 | case CS7: | |
491 | buf[6] = 7; | |
492 | break; | |
493 | default: | |
494 | case CS8: | |
495 | buf[6] = 8; | |
15e7cead | 496 | } |
a3132499 | 497 | dev_dbg(&port->dev, "data bits = %d\n", buf[6]); |
15e7cead | 498 | |
692ed4dd | 499 | /* For reference buf[0]:buf[3] baud rate value */ |
79816824 | 500 | pl2303_encode_baud_rate(tty, port, &buf[0]); |
15e7cead | 501 | |
1da177e4 LT |
502 | /* For reference buf[4]=0 is 1 stop bits */ |
503 | /* For reference buf[4]=1 is 1.5 stop bits */ | |
504 | /* For reference buf[4]=2 is 2 stop bits */ | |
87265b45 JH |
505 | if (C_CSTOPB(tty)) { |
506 | /* | |
507 | * NOTE: Comply with "real" UARTs / RS232: | |
29cf1b72 FS |
508 | * use 1.5 instead of 2 stop bits with 5 data bits |
509 | */ | |
87265b45 | 510 | if (C_CSIZE(tty) == CS5) { |
29cf1b72 | 511 | buf[4] = 1; |
d8789b2b | 512 | dev_dbg(&port->dev, "stop bits = 1.5\n"); |
29cf1b72 FS |
513 | } else { |
514 | buf[4] = 2; | |
d8789b2b | 515 | dev_dbg(&port->dev, "stop bits = 2\n"); |
29cf1b72 | 516 | } |
1da177e4 LT |
517 | } else { |
518 | buf[4] = 0; | |
d8789b2b | 519 | dev_dbg(&port->dev, "stop bits = 1\n"); |
1da177e4 LT |
520 | } |
521 | ||
87265b45 | 522 | if (C_PARENB(tty)) { |
1da177e4 LT |
523 | /* For reference buf[5]=0 is none parity */ |
524 | /* For reference buf[5]=1 is odd parity */ | |
525 | /* For reference buf[5]=2 is even parity */ | |
526 | /* For reference buf[5]=3 is mark parity */ | |
527 | /* For reference buf[5]=4 is space parity */ | |
87265b45 | 528 | if (C_PARODD(tty)) { |
619c4354 | 529 | if (C_CMSPAR(tty)) { |
6dd81b45 | 530 | buf[5] = 3; |
d8789b2b | 531 | dev_dbg(&port->dev, "parity = mark\n"); |
6dd81b45 FS |
532 | } else { |
533 | buf[5] = 1; | |
d8789b2b | 534 | dev_dbg(&port->dev, "parity = odd\n"); |
6dd81b45 | 535 | } |
1da177e4 | 536 | } else { |
619c4354 | 537 | if (C_CMSPAR(tty)) { |
6dd81b45 | 538 | buf[5] = 4; |
d8789b2b | 539 | dev_dbg(&port->dev, "parity = space\n"); |
6dd81b45 FS |
540 | } else { |
541 | buf[5] = 2; | |
d8789b2b | 542 | dev_dbg(&port->dev, "parity = even\n"); |
6dd81b45 | 543 | } |
1da177e4 LT |
544 | } |
545 | } else { | |
546 | buf[5] = 0; | |
d8789b2b | 547 | dev_dbg(&port->dev, "parity = none\n"); |
1da177e4 LT |
548 | } |
549 | ||
623c8263 JH |
550 | /* |
551 | * Some PL2303 are known to lose bytes if you change serial settings | |
552 | * even to the same values as before. Thus we actually need to filter | |
553 | * in this specific case. | |
554 | * | |
555 | * Note that the tty_termios_hw_change check above is not sufficient | |
556 | * as a previously requested baud rate may differ from the one | |
557 | * actually used (and stored in old_termios). | |
558 | * | |
559 | * NOTE: No additional locking needed for line_settings as it is | |
560 | * only used in set_termios, which is serialised against itself. | |
561 | */ | |
562 | if (!old_termios || memcmp(buf, priv->line_settings, 7)) { | |
383d19c5 JH |
563 | ret = pl2303_set_line_request(port, buf); |
564 | if (!ret) | |
623c8263 JH |
565 | memcpy(priv->line_settings, buf, 7); |
566 | } | |
1da177e4 LT |
567 | |
568 | /* change control lines if we are switching to or from B0 */ | |
569 | spin_lock_irqsave(&priv->lock, flags); | |
570 | control = priv->line_control; | |
87265b45 | 571 | if (C_BAUD(tty) == B0) |
1da177e4 | 572 | priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); |
2d8f4447 | 573 | else if (old_termios && (old_termios->c_cflag & CBAUD) == B0) |
1da177e4 LT |
574 | priv->line_control |= (CONTROL_DTR | CONTROL_RTS); |
575 | if (control != priv->line_control) { | |
576 | control = priv->line_control; | |
577 | spin_unlock_irqrestore(&priv->lock, flags); | |
f45d0a5a | 578 | pl2303_set_control_lines(port, control); |
1da177e4 LT |
579 | } else { |
580 | spin_unlock_irqrestore(&priv->lock, flags); | |
581 | } | |
372db8a7 | 582 | |
87265b45 | 583 | if (C_CRTSCTS(tty)) { |
23c6acb9 | 584 | if (spriv->quirks & PL2303_QUIRK_LEGACY) |
362eb026 | 585 | pl2303_vendor_write(serial, 0x0, 0x41); |
7f966ac7 JH |
586 | else |
587 | pl2303_vendor_write(serial, 0x0, 0x61); | |
715f9527 | 588 | } else { |
362eb026 | 589 | pl2303_vendor_write(serial, 0x0, 0x0); |
1da177e4 | 590 | } |
572d3138 TG |
591 | |
592 | kfree(buf); | |
593 | } | |
594 | ||
335f8514 AC |
595 | static void pl2303_dtr_rts(struct usb_serial_port *port, int on) |
596 | { | |
597 | struct pl2303_private *priv = usb_get_serial_port_data(port); | |
598 | unsigned long flags; | |
599 | u8 control; | |
600 | ||
601 | spin_lock_irqsave(&priv->lock, flags); | |
335f8514 AC |
602 | if (on) |
603 | priv->line_control |= (CONTROL_DTR | CONTROL_RTS); | |
604 | else | |
605 | priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); | |
606 | control = priv->line_control; | |
607 | spin_unlock_irqrestore(&priv->lock, flags); | |
ccfe8188 | 608 | |
f45d0a5a | 609 | pl2303_set_control_lines(port, control); |
335f8514 AC |
610 | } |
611 | ||
612 | static void pl2303_close(struct usb_serial_port *port) | |
572d3138 | 613 | { |
8b0127b2 | 614 | usb_serial_generic_close(port); |
572d3138 | 615 | usb_kill_urb(port->interrupt_in_urb); |
1da177e4 LT |
616 | } |
617 | ||
a509a7e4 | 618 | static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port) |
1da177e4 | 619 | { |
1da177e4 | 620 | struct usb_serial *serial = port->serial; |
8bf769eb | 621 | struct pl2303_serial_private *spriv = usb_get_serial_data(serial); |
1da177e4 LT |
622 | int result; |
623 | ||
23c6acb9 | 624 | if (spriv->quirks & PL2303_QUIRK_LEGACY) { |
1694899f D |
625 | usb_clear_halt(serial->dev, port->write_urb->pipe); |
626 | usb_clear_halt(serial->dev, port->read_urb->pipe); | |
3e152505 | 627 | } else { |
1da177e4 | 628 | /* reset upstream data pipes */ |
362eb026 JH |
629 | pl2303_vendor_write(serial, 8, 0); |
630 | pl2303_vendor_write(serial, 9, 0); | |
1da177e4 LT |
631 | } |
632 | ||
1da177e4 | 633 | /* Setup termios */ |
95da310e | 634 | if (tty) |
2d8f4447 | 635 | pl2303_set_termios(tty, port, NULL); |
1da177e4 | 636 | |
372db8a7 | 637 | result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); |
1da177e4 | 638 | if (result) { |
ccfe8188 JH |
639 | dev_err(&port->dev, "failed to submit interrupt urb: %d\n", |
640 | result); | |
db6e9186 | 641 | return result; |
1da177e4 | 642 | } |
d4691c3f | 643 | |
f5230a53 | 644 | result = usb_serial_generic_open(tty, port); |
d4691c3f JH |
645 | if (result) { |
646 | usb_kill_urb(port->interrupt_in_urb); | |
647 | return result; | |
648 | } | |
649 | ||
1da177e4 LT |
650 | return 0; |
651 | } | |
652 | ||
20b9d177 | 653 | static int pl2303_tiocmset(struct tty_struct *tty, |
372db8a7 | 654 | unsigned int set, unsigned int clear) |
1da177e4 | 655 | { |
95da310e | 656 | struct usb_serial_port *port = tty->driver_data; |
1da177e4 LT |
657 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
658 | unsigned long flags; | |
659 | u8 control; | |
6f1efd6c | 660 | int ret; |
6fdd8e8e | 661 | |
372db8a7 | 662 | spin_lock_irqsave(&priv->lock, flags); |
1da177e4 LT |
663 | if (set & TIOCM_RTS) |
664 | priv->line_control |= CONTROL_RTS; | |
665 | if (set & TIOCM_DTR) | |
666 | priv->line_control |= CONTROL_DTR; | |
667 | if (clear & TIOCM_RTS) | |
668 | priv->line_control &= ~CONTROL_RTS; | |
669 | if (clear & TIOCM_DTR) | |
670 | priv->line_control &= ~CONTROL_DTR; | |
671 | control = priv->line_control; | |
372db8a7 | 672 | spin_unlock_irqrestore(&priv->lock, flags); |
1da177e4 | 673 | |
5ddbb26b JH |
674 | ret = pl2303_set_control_lines(port, control); |
675 | if (ret) | |
676 | return usb_translate_errors(ret); | |
6f1efd6c | 677 | |
5ddbb26b | 678 | return 0; |
1da177e4 LT |
679 | } |
680 | ||
60b33c13 | 681 | static int pl2303_tiocmget(struct tty_struct *tty) |
1da177e4 | 682 | { |
95da310e | 683 | struct usb_serial_port *port = tty->driver_data; |
1da177e4 LT |
684 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
685 | unsigned long flags; | |
686 | unsigned int mcr; | |
687 | unsigned int status; | |
688 | unsigned int result; | |
689 | ||
372db8a7 | 690 | spin_lock_irqsave(&priv->lock, flags); |
1da177e4 LT |
691 | mcr = priv->line_control; |
692 | status = priv->line_status; | |
372db8a7 | 693 | spin_unlock_irqrestore(&priv->lock, flags); |
1da177e4 LT |
694 | |
695 | result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0) | |
696 | | ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0) | |
697 | | ((status & UART_CTS) ? TIOCM_CTS : 0) | |
698 | | ((status & UART_DSR) ? TIOCM_DSR : 0) | |
699 | | ((status & UART_RING) ? TIOCM_RI : 0) | |
700 | | ((status & UART_DCD) ? TIOCM_CD : 0); | |
701 | ||
d8789b2b | 702 | dev_dbg(&port->dev, "%s - result = %x\n", __func__, result); |
1da177e4 LT |
703 | |
704 | return result; | |
705 | } | |
706 | ||
335f8514 AC |
707 | static int pl2303_carrier_raised(struct usb_serial_port *port) |
708 | { | |
709 | struct pl2303_private *priv = usb_get_serial_port_data(port); | |
ccfe8188 | 710 | |
335f8514 AC |
711 | if (priv->line_status & UART_DCD) |
712 | return 1; | |
ccfe8188 | 713 | |
335f8514 AC |
714 | return 0; |
715 | } | |
716 | ||
00a0d0d6 | 717 | static int pl2303_ioctl(struct tty_struct *tty, |
372db8a7 | 718 | unsigned int cmd, unsigned long arg) |
1da177e4 | 719 | { |
67b9946d | 720 | struct serial_struct ser; |
95da310e | 721 | struct usb_serial_port *port = tty->driver_data; |
d8789b2b | 722 | |
1da177e4 | 723 | switch (cmd) { |
67b9946d JT |
724 | case TIOCGSERIAL: |
725 | memset(&ser, 0, sizeof ser); | |
726 | ser.type = PORT_16654; | |
e5b1e206 | 727 | ser.line = port->minor; |
1143832e | 728 | ser.port = port->port_number; |
67b9946d JT |
729 | ser.baud_base = 460800; |
730 | ||
731 | if (copy_to_user((void __user *)arg, &ser, sizeof ser)) | |
732 | return -EFAULT; | |
733 | ||
734 | return 0; | |
3a0f43e9 | 735 | default: |
3a0f43e9 | 736 | break; |
1da177e4 | 737 | } |
ccfe8188 | 738 | |
1da177e4 LT |
739 | return -ENOIOCTLCMD; |
740 | } | |
741 | ||
95da310e | 742 | static void pl2303_break_ctl(struct tty_struct *tty, int break_state) |
1da177e4 | 743 | { |
95da310e | 744 | struct usb_serial_port *port = tty->driver_data; |
1da177e4 LT |
745 | struct usb_serial *serial = port->serial; |
746 | u16 state; | |
747 | int result; | |
748 | ||
1da177e4 LT |
749 | if (break_state == 0) |
750 | state = BREAK_OFF; | |
751 | else | |
752 | state = BREAK_ON; | |
ccfe8188 | 753 | |
d8789b2b | 754 | dev_dbg(&port->dev, "%s - turning break %s\n", __func__, |
3a0f43e9 | 755 | state == BREAK_OFF ? "off" : "on"); |
1da177e4 | 756 | |
372db8a7 TG |
757 | result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), |
758 | BREAK_REQUEST, BREAK_REQUEST_TYPE, state, | |
759 | 0, NULL, 0, 100); | |
1da177e4 | 760 | if (result) |
d8789b2b | 761 | dev_err(&port->dev, "error sending break = %d\n", result); |
1da177e4 LT |
762 | } |
763 | ||
97bb13ec FL |
764 | static void pl2303_update_line_status(struct usb_serial_port *port, |
765 | unsigned char *data, | |
766 | unsigned int actual_length) | |
767 | { | |
228e4105 JH |
768 | struct usb_serial *serial = port->serial; |
769 | struct pl2303_serial_private *spriv = usb_get_serial_data(serial); | |
97bb13ec | 770 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
d14fc1a7 | 771 | struct tty_struct *tty; |
97bb13ec | 772 | unsigned long flags; |
228e4105 | 773 | unsigned int status_idx = UART_STATE_INDEX; |
6020c3be JH |
774 | u8 status; |
775 | u8 delta; | |
97bb13ec | 776 | |
228e4105 JH |
777 | if (spriv->quirks & PL2303_QUIRK_UART_STATE_IDX0) |
778 | status_idx = 0; | |
97bb13ec | 779 | |
228e4105 | 780 | if (actual_length < status_idx + 1) |
a009b75a | 781 | return; |
97bb13ec | 782 | |
6020c3be JH |
783 | status = data[status_idx]; |
784 | ||
3a0f43e9 | 785 | /* Save off the uart status for others to look at */ |
97bb13ec | 786 | spin_lock_irqsave(&priv->lock, flags); |
6020c3be JH |
787 | delta = priv->line_status ^ status; |
788 | priv->line_status = status; | |
97bb13ec | 789 | spin_unlock_irqrestore(&priv->lock, flags); |
ccfe8188 | 790 | |
6020c3be | 791 | if (status & UART_BREAK_ERROR) |
430eb0d2 | 792 | usb_serial_handle_break(port); |
ccfe8188 | 793 | |
dbfd2866 | 794 | if (delta & UART_STATE_MSR_MASK) { |
a4bcb294 JH |
795 | if (delta & UART_CTS) |
796 | port->icount.cts++; | |
797 | if (delta & UART_DSR) | |
798 | port->icount.dsr++; | |
799 | if (delta & UART_RING) | |
800 | port->icount.rng++; | |
dbfd2866 | 801 | if (delta & UART_DCD) { |
a4bcb294 | 802 | port->icount.dcd++; |
dbfd2866 JH |
803 | tty = tty_port_tty_get(&port->port); |
804 | if (tty) { | |
805 | usb_serial_handle_dcd_change(port, tty, | |
6020c3be | 806 | status & UART_DCD); |
dbfd2866 JH |
807 | tty_kref_put(tty); |
808 | } | |
6020c3be | 809 | } |
dbfd2866 JH |
810 | |
811 | wake_up_interruptible(&port->port.delta_msr_wait); | |
6020c3be | 812 | } |
97bb13ec | 813 | } |
1da177e4 | 814 | |
7d12e780 | 815 | static void pl2303_read_int_callback(struct urb *urb) |
1da177e4 | 816 | { |
cdc97792 | 817 | struct usb_serial_port *port = urb->context; |
1da177e4 | 818 | unsigned char *data = urb->transfer_buffer; |
97bb13ec | 819 | unsigned int actual_length = urb->actual_length; |
461d696a GKH |
820 | int status = urb->status; |
821 | int retval; | |
1da177e4 | 822 | |
461d696a | 823 | switch (status) { |
1da177e4 LT |
824 | case 0: |
825 | /* success */ | |
826 | break; | |
827 | case -ECONNRESET: | |
828 | case -ENOENT: | |
829 | case -ESHUTDOWN: | |
830 | /* this urb is terminated, clean up */ | |
d8789b2b GKH |
831 | dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n", |
832 | __func__, status); | |
1da177e4 LT |
833 | return; |
834 | default: | |
d8789b2b GKH |
835 | dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n", |
836 | __func__, status); | |
1da177e4 LT |
837 | goto exit; |
838 | } | |
839 | ||
59d33f2f | 840 | usb_serial_debug_data(&port->dev, __func__, |
372db8a7 TG |
841 | urb->actual_length, urb->transfer_buffer); |
842 | ||
97bb13ec | 843 | pl2303_update_line_status(port, data, actual_length); |
1da177e4 | 844 | |
1da177e4 | 845 | exit: |
461d696a | 846 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
ccfe8188 | 847 | if (retval) { |
d8789b2b | 848 | dev_err(&port->dev, |
372db8a7 | 849 | "%s - usb_submit_urb failed with result %d\n", |
441b62c1 | 850 | __func__, retval); |
ccfe8188 | 851 | } |
1da177e4 LT |
852 | } |
853 | ||
f08e07ac | 854 | static void pl2303_process_read_urb(struct urb *urb) |
d4fc4a7b | 855 | { |
f08e07ac JH |
856 | struct usb_serial_port *port = urb->context; |
857 | struct pl2303_private *priv = usb_get_serial_port_data(port); | |
d4fc4a7b | 858 | unsigned char *data = urb->transfer_buffer; |
d4fc4a7b | 859 | char tty_flag = TTY_NORMAL; |
f08e07ac JH |
860 | unsigned long flags; |
861 | u8 line_status; | |
862 | int i; | |
863 | ||
864 | /* update line status */ | |
865 | spin_lock_irqsave(&priv->lock, flags); | |
866 | line_status = priv->line_status; | |
867 | priv->line_status &= ~UART_STATE_TRANSIENT_MASK; | |
868 | spin_unlock_irqrestore(&priv->lock, flags); | |
f08e07ac JH |
869 | |
870 | if (!urb->actual_length) | |
871 | return; | |
872 | ||
ccfe8188 JH |
873 | /* |
874 | * Break takes precedence over parity, which takes precedence over | |
875 | * framing errors. | |
876 | */ | |
d4fc4a7b AC |
877 | if (line_status & UART_BREAK_ERROR) |
878 | tty_flag = TTY_BREAK; | |
879 | else if (line_status & UART_PARITY_ERROR) | |
880 | tty_flag = TTY_PARITY; | |
881 | else if (line_status & UART_FRAME_ERROR) | |
882 | tty_flag = TTY_FRAME; | |
d4fc4a7b | 883 | |
3ba19fe3 JH |
884 | if (tty_flag != TTY_NORMAL) |
885 | dev_dbg(&port->dev, "%s - tty_flag = %d\n", __func__, | |
886 | tty_flag); | |
d4fc4a7b AC |
887 | /* overrun is special, not associated with a char */ |
888 | if (line_status & UART_OVERRUN_ERROR) | |
92a19f9c | 889 | tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); |
9388e2e7 | 890 | |
d45cc8df | 891 | if (port->port.console && port->sysrq) { |
d4fc4a7b | 892 | for (i = 0; i < urb->actual_length; ++i) |
6ee9f4b4 | 893 | if (!usb_serial_handle_sysrq_char(port, data[i])) |
92a19f9c JS |
894 | tty_insert_flip_char(&port->port, data[i], |
895 | tty_flag); | |
d45cc8df | 896 | } else { |
2f693357 | 897 | tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag, |
d45cc8df | 898 | urb->actual_length); |
9388e2e7 | 899 | } |
1da177e4 | 900 | |
2e124b4a | 901 | tty_flip_buffer_push(&port->port); |
1da177e4 LT |
902 | } |
903 | ||
572d3138 TG |
904 | static struct usb_serial_driver pl2303_device = { |
905 | .driver = { | |
906 | .owner = THIS_MODULE, | |
907 | .name = "pl2303", | |
908 | }, | |
909 | .id_table = id_table, | |
572d3138 | 910 | .num_ports = 1, |
7919c2fd | 911 | .bulk_in_size = 256, |
3efeaff6 | 912 | .bulk_out_size = 256, |
572d3138 TG |
913 | .open = pl2303_open, |
914 | .close = pl2303_close, | |
ccfe8188 | 915 | .dtr_rts = pl2303_dtr_rts, |
335f8514 | 916 | .carrier_raised = pl2303_carrier_raised, |
572d3138 TG |
917 | .ioctl = pl2303_ioctl, |
918 | .break_ctl = pl2303_break_ctl, | |
919 | .set_termios = pl2303_set_termios, | |
920 | .tiocmget = pl2303_tiocmget, | |
921 | .tiocmset = pl2303_tiocmset, | |
a4bcb294 | 922 | .tiocmiwait = usb_serial_generic_tiocmiwait, |
f08e07ac | 923 | .process_read_urb = pl2303_process_read_urb, |
572d3138 | 924 | .read_int_callback = pl2303_read_int_callback, |
228e4105 | 925 | .probe = pl2303_probe, |
572d3138 | 926 | .attach = pl2303_startup, |
f9c99bb8 | 927 | .release = pl2303_release, |
8bf769eb JH |
928 | .port_probe = pl2303_port_probe, |
929 | .port_remove = pl2303_port_remove, | |
572d3138 | 930 | }; |
1da177e4 | 931 | |
f667ddad AS |
932 | static struct usb_serial_driver * const serial_drivers[] = { |
933 | &pl2303_device, NULL | |
934 | }; | |
935 | ||
68e24113 | 936 | module_usb_serial_driver(serial_drivers, id_table); |
1da177e4 | 937 | |
ccfe8188 | 938 | MODULE_DESCRIPTION("Prolific PL2303 USB to serial adaptor driver"); |
1da177e4 | 939 | MODULE_LICENSE("GPL"); |