aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/cp2101.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/usb/serial/cp2101.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/usb/serial/cp2101.c')
-rw-r--r--drivers/usb/serial/cp2101.c591
1 files changed, 591 insertions, 0 deletions
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
new file mode 100644
index 000000000000..7e9bb63eb466
--- /dev/null
+++ b/drivers/usb/serial/cp2101.c
@@ -0,0 +1,591 @@
1/*
2 * Silicon Laboratories CP2101/CP2102 USB to RS232 serial adaptor driver
3 *
4 * Copyright (C) 2005 Craig Shelley (craig@microtron.org.uk)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version
8 * 2 as published by the Free Software Foundation.
9 *
10 */
11
12#include <linux/config.h>
13#include <linux/kernel.h>
14#include <linux/errno.h>
15#include <linux/slab.h>
16#include <linux/tty.h>
17#include <linux/tty_flip.h>
18#include <linux/module.h>
19#include <linux/moduleparam.h>
20#include <linux/usb.h>
21#include <asm/uaccess.h>
22#include "usb-serial.h"
23
24/*
25 * Version Information
26 */
27#define DRIVER_VERSION "v0.03"
28#define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver"
29
30/*
31 * Function Prototypes
32 */
33static int cp2101_open(struct usb_serial_port*, struct file*);
34static void cp2101_cleanup(struct usb_serial_port*);
35static void cp2101_close(struct usb_serial_port*, struct file*);
36static void cp2101_get_termios(struct usb_serial_port*);
37static void cp2101_set_termios(struct usb_serial_port*, struct termios*);
38static void cp2101_break_ctl(struct usb_serial_port*, int);
39static int cp2101_startup (struct usb_serial *);
40static void cp2101_shutdown(struct usb_serial*);
41
42
43static int debug;
44
45static struct usb_device_id id_table [] = {
46 {USB_DEVICE(0x10c4, 0xea60) }, /*Silicon labs factory default*/
47 {USB_DEVICE(0x10ab, 0x10c5) }, /*Siemens MC60 Cable*/
48 { } /* Terminating Entry*/
49};
50
51MODULE_DEVICE_TABLE (usb, id_table);
52
53static struct usb_driver cp2101_driver = {
54 .owner = THIS_MODULE,
55 .name = "CP2101",
56 .probe = usb_serial_probe,
57 .disconnect = usb_serial_disconnect,
58 .id_table = id_table,
59};
60
61static struct usb_serial_device_type cp2101_device = {
62 .owner = THIS_MODULE,
63 .name = "CP2101",
64 .id_table = id_table,
65 .num_interrupt_in = 0,
66 .num_bulk_in = 0,
67 .num_bulk_out = 0,
68 .num_ports = 1,
69 .open = cp2101_open,
70 .close = cp2101_close,
71 .break_ctl = cp2101_break_ctl,
72 .set_termios = cp2101_set_termios,
73 .attach = cp2101_startup,
74 .shutdown = cp2101_shutdown,
75};
76
77/*Config request types*/
78#define REQTYPE_HOST_TO_DEVICE 0x41
79#define REQTYPE_DEVICE_TO_HOST 0xc1
80
81/*Config SET requests. To GET, add 1 to the request number*/
82#define CP2101_UART 0x00 /*Enable / Disable*/
83#define CP2101_BAUDRATE 0x01 /*(BAUD_RATE_GEN_FREQ / baudrate)*/
84#define CP2101_BITS 0x03 /*0x(0)(data bits)(parity)(stop bits)*/
85#define CP2101_BREAK 0x05 /*On / Off*/
86#define CP2101_DTRRTS 0x07 /*101 / 202 ???*/
87#define CP2101_CONFIG_16 0x13 /*16 bytes of config data ???*/
88#define CP2101_CONFIG_6 0x19 /*6 bytes of config data ???*/
89
90/*CP2101_UART*/
91#define UART_ENABLE 0x0001
92#define UART_DISABLE 0x0000
93
94/*CP2101_BAUDRATE*/
95#define BAUD_RATE_GEN_FREQ 0x384000
96
97/*CP2101_BITS*/
98#define BITS_DATA_MASK 0X0f00
99#define BITS_DATA_6 0X0600
100#define BITS_DATA_7 0X0700
101#define BITS_DATA_8 0X0800
102#define BITS_DATA_9 0X0900
103
104#define BITS_PARITY_MASK 0x00f0
105#define BITS_PARITY_NONE 0x0000
106#define BITS_PARITY_ODD 0x0010
107#define BITS_PARITY_EVEN 0x0020
108#define BITS_PARITY_MARK 0x0030
109#define BITS_PARITY_SPACE 0x0040
110
111#define BITS_STOP_MASK 0x000f
112#define BITS_STOP_1 0x0000
113#define BITS_STOP_1_5 0x0001
114#define BITS_STOP_2 0x0002
115#define BREAK_ON 0x0000
116#define BREAK_OFF 0x0001
117
118
119static int cp2101_get_config(struct usb_serial_port* port, u8 request)
120{
121 struct usb_serial *serial = port->serial;
122 unsigned char buf[4];
123 unsigned int value;
124 int result, i;
125
126 /*For get requests, the request number must be incremented*/
127 request++;
128
129 /*Issue the request, attempting to read 4 bytes*/
130 result = usb_control_msg (serial->dev,usb_rcvctrlpipe (serial->dev, 0),
131 request, REQTYPE_DEVICE_TO_HOST, 0x0000,
132 0, buf, 4, 300);
133
134 if (result < 0) {
135 dev_err(&port->dev, "%s - Unable to send config request, "
136 "request=0x%x result=%d\n",
137 __FUNCTION__, request, result);
138 return result;
139 }
140
141 /*Assemble each byte read into an integer value*/
142 value = 0;
143 for (i=0; i<4 && i<result; i++)
144 value |= (buf[i] << (i * 8));
145
146 dbg( " %s - request=0x%x result=%d value=0x%x",
147 __FUNCTION__, request, result, value);
148
149 return value;
150}
151
152static int cp2101_set_config(struct usb_serial_port* port, u8 request, u16 value)
153{
154 struct usb_serial *serial = port->serial;
155 int result;
156 result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0),
157 request, REQTYPE_HOST_TO_DEVICE, value,
158 0, NULL, 0, 300);
159
160 if (result <0) {
161 dev_err(&port->dev, "%s - Unable to send config request, "
162 "request=0x%x value=0x%x result=%d\n",
163 __FUNCTION__, request, value, result);
164 return result;
165 }
166
167 dbg(" %s - request=0x%x value=0x%x result=%d",
168 __FUNCTION__, request, value, result);
169
170 return 0;
171}
172
173static int cp2101_open (struct usb_serial_port *port, struct file *filp)
174{
175 struct usb_serial *serial = port->serial;
176 int result;
177
178 dbg("%s - port %d", __FUNCTION__, port->number);
179
180 if (cp2101_set_config(port, CP2101_UART, UART_ENABLE)) {
181 dev_err(&port->dev, "%s - Unable to enable UART\n",
182 __FUNCTION__);
183 return -EPROTO;
184 }
185
186 /* Start reading from the device */
187 usb_fill_bulk_urb (port->read_urb, serial->dev,
188 usb_rcvbulkpipe(serial->dev,
189 port->bulk_in_endpointAddress),
190 port->read_urb->transfer_buffer,
191 port->read_urb->transfer_buffer_length,
192 serial->type->read_bulk_callback,
193 port);
194 result = usb_submit_urb(port->read_urb, GFP_KERNEL);
195 if (result) {
196 dev_err(&port->dev, "%s - failed resubmitting read urb, "
197 "error %d\n", __FUNCTION__, result);
198 return result;
199 }
200
201 /*Configure the termios structure*/
202 cp2101_get_termios(port);
203
204 return 0;
205}
206
207static void cp2101_cleanup (struct usb_serial_port *port)
208{
209 struct usb_serial *serial = port->serial;
210
211 dbg("%s - port %d", __FUNCTION__, port->number);
212
213 if (serial->dev) {
214 /* shutdown any bulk reads that might be going on */
215 if (serial->num_bulk_out)
216 usb_kill_urb(port->write_urb);
217 if (serial->num_bulk_in)
218 usb_kill_urb(port->read_urb);
219 }
220}
221
222static void cp2101_close (struct usb_serial_port *port, struct file * filp)
223{
224 dbg("%s - port %d", __FUNCTION__, port->number);
225
226 /* shutdown our urbs */
227 dbg("%s - shutting down urbs", __FUNCTION__);
228 usb_kill_urb(port->write_urb);
229 usb_kill_urb(port->read_urb);
230
231 cp2101_set_config(port, CP2101_UART, UART_DISABLE);
232}
233
234/* cp2101_get_termios*/
235/* Reads the baud rate, data bits, parity and stop bits from the device*/
236/* Corrects any unsupported values*/
237/* Configures the termios structure to reflect the state of the device*/
238static void cp2101_get_termios (struct usb_serial_port *port)
239{
240 unsigned int cflag;
241 int baud;
242 int bits;
243
244 dbg("%s - port %d", __FUNCTION__, port->number);
245
246 if ((!port->tty) || (!port->tty->termios)) {
247 dbg("%s - no tty structures", __FUNCTION__);
248 return;
249 }
250 cflag = port->tty->termios->c_cflag;
251
252 baud = cp2101_get_config(port, CP2101_BAUDRATE);
253 /*Convert to baudrate*/
254 if (baud)
255 baud = BAUD_RATE_GEN_FREQ / baud;
256
257 dbg("%s - baud rate = %d", __FUNCTION__, baud);
258 cflag &= ~CBAUD;
259 switch (baud) {
260 /* The baud rates which are commented out below
261 * appear to be supported by the device
262 * but are non-standard
263 */
264 case 600: cflag |= B600; break;
265 case 1200: cflag |= B1200; break;
266 case 1800: cflag |= B1800; break;
267 case 2400: cflag |= B2400; break;
268 case 4800: cflag |= B4800; break;
269 /*case 7200: cflag |= B7200; break;*/
270 case 9600: cflag |= B9600; break;
271 /*case 14400: cflag |= B14400; break;*/
272 case 19200: cflag |= B19200; break;
273 /*case 28800: cflag |= B28800; break;*/
274 case 38400: cflag |= B38400; break;
275 /*case 55854: cflag |= B55054; break;*/
276 case 57600: cflag |= B57600; break;
277 case 115200: cflag |= B115200; break;
278 /*case 127117: cflag |= B127117; break;*/
279 case 230400: cflag |= B230400; break;
280 case 460800: cflag |= B460800; break;
281 case 921600: cflag |= B921600; break;
282 /*case 3686400: cflag |= B3686400; break;*/
283 default:
284 dbg("%s - Baud rate is not supported, "
285 "using 9600 baud", __FUNCTION__);
286 cflag |= B9600;
287 cp2101_set_config(port, CP2101_BAUDRATE,
288 (BAUD_RATE_GEN_FREQ/9600));
289 break;
290 }
291
292 bits = cp2101_get_config(port, CP2101_BITS);
293 cflag &= ~CSIZE;
294 switch(bits & BITS_DATA_MASK) {
295 case BITS_DATA_6:
296 dbg("%s - data bits = 6", __FUNCTION__);
297 cflag |= CS6;
298 break;
299 case BITS_DATA_7:
300 dbg("%s - data bits = 7", __FUNCTION__);
301 cflag |= CS7;
302 break;
303 case BITS_DATA_8:
304 dbg("%s - data bits = 8", __FUNCTION__);
305 cflag |= CS8;
306 break;
307 case BITS_DATA_9:
308 dbg("%s - data bits = 9 (not supported, "
309 "using 8 data bits)", __FUNCTION__);
310 cflag |= CS8;
311 bits &= ~BITS_DATA_MASK;
312 bits |= BITS_DATA_8;
313 cp2101_set_config(port, CP2101_BITS, bits);
314 break;
315 default:
316 dbg("%s - Unknown number of data bits, "
317 "using 8", __FUNCTION__);
318 cflag |= CS8;
319 bits &= ~BITS_DATA_MASK;
320 bits |= BITS_DATA_8;
321 cp2101_set_config(port, CP2101_BITS, bits);
322 break;
323 }
324
325 switch(bits & BITS_PARITY_MASK) {
326 case BITS_PARITY_NONE:
327 dbg("%s - parity = NONE", __FUNCTION__);
328 cflag &= ~PARENB;
329 break;
330 case BITS_PARITY_ODD:
331 dbg("%s - parity = ODD", __FUNCTION__);
332 cflag |= (PARENB|PARODD);
333 break;
334 case BITS_PARITY_EVEN:
335 dbg("%s - parity = EVEN", __FUNCTION__);
336 cflag &= ~PARODD;
337 cflag |= PARENB;
338 break;
339 case BITS_PARITY_MARK:
340 dbg("%s - parity = MARK (not supported, "
341 "disabling parity)", __FUNCTION__);
342 cflag &= ~PARENB;
343 bits &= ~BITS_PARITY_MASK;
344 cp2101_set_config(port, CP2101_BITS, bits);
345 break;
346 case BITS_PARITY_SPACE:
347 dbg("%s - parity = SPACE (not supported, "
348 "disabling parity)", __FUNCTION__);
349 cflag &= ~PARENB;
350 bits &= ~BITS_PARITY_MASK;
351 cp2101_set_config(port, CP2101_BITS, bits);
352 break;
353 default:
354 dbg("%s - Unknown parity mode, "
355 "disabling parity", __FUNCTION__);
356 cflag &= ~PARENB;
357 bits &= ~BITS_PARITY_MASK;
358 cp2101_set_config(port, CP2101_BITS, bits);
359 break;
360 }
361
362 cflag &= ~CSTOPB;
363 switch(bits & BITS_STOP_MASK) {
364 case BITS_STOP_1:
365 dbg("%s - stop bits = 1", __FUNCTION__);
366 break;
367 case BITS_STOP_1_5:
368 dbg("%s - stop bits = 1.5 (not supported, "
369 "using 1 stop bit", __FUNCTION__);
370 bits &= ~BITS_STOP_MASK;
371 cp2101_set_config(port, CP2101_BITS, bits);
372 break;
373 case BITS_STOP_2:
374 dbg("%s - stop bits = 2", __FUNCTION__);
375 cflag |= CSTOPB;
376 break;
377 default:
378 dbg("%s - Unknown number of stop bits, "
379 "using 1 stop bit", __FUNCTION__);
380 bits &= ~BITS_STOP_MASK;
381 cp2101_set_config(port, CP2101_BITS, bits);
382 break;
383 }
384
385 port->tty->termios->c_cflag = cflag;
386}
387
388static void cp2101_set_termios (struct usb_serial_port *port,
389 struct termios *old_termios)
390{
391 unsigned int cflag, old_cflag=0;
392 int baud=0;
393 int bits;
394
395 dbg("%s - port %d", __FUNCTION__, port->number);
396
397 if ((!port->tty) || (!port->tty->termios)) {
398 dbg("%s - no tty structures", __FUNCTION__);
399 return;
400 }
401 cflag = port->tty->termios->c_cflag;
402
403 /* check that they really want us to change something */
404 if (old_termios) {
405 if ((cflag == old_termios->c_cflag) &&
406 (RELEVANT_IFLAG(port->tty->termios->c_iflag)
407 == RELEVANT_IFLAG(old_termios->c_iflag))) {
408 dbg("%s - nothing to change...", __FUNCTION__);
409 return;
410 }
411
412 old_cflag = old_termios->c_cflag;
413 }
414
415 /* If the baud rate is to be updated*/
416 if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
417 switch (cflag & CBAUD) {
418 /* The baud rates which are commented out below
419 * appear to be supported by the device
420 * but are non-standard
421 */
422 case B0: baud = 0; break;
423 case B600: baud = 600; break;
424 case B1200: baud = 1200; break;
425 case B1800: baud = 1800; break;
426 case B2400: baud = 2400; break;
427 case B4800: baud = 4800; break;
428 /*case B7200: baud = 7200; break;*/
429 case B9600: baud = 9600; break;
430 /*ase B14400: baud = 14400; break;*/
431 case B19200: baud = 19200; break;
432 /*case B28800: baud = 28800; break;*/
433 case B38400: baud = 38400; break;
434 /*case B55854: baud = 55054; break;*/
435 case B57600: baud = 57600; break;
436 case B115200: baud = 115200; break;
437 /*case B127117: baud = 127117; break;*/
438 case B230400: baud = 230400; break;
439 case B460800: baud = 460800; break;
440 case B921600: baud = 921600; break;
441 /*case B3686400: baud = 3686400; break;*/
442 default:
443 dev_err(&port->dev, "cp2101 driver does not "
444 "support the baudrate requested\n");
445 break;
446 }
447
448 if (baud) {
449 dbg("%s - Setting baud rate to %d baud", __FUNCTION__,
450 baud);
451 if (cp2101_set_config(port, CP2101_BAUDRATE,
452 (BAUD_RATE_GEN_FREQ / baud)))
453 dev_err(&port->dev, "Baud rate requested not "
454 "supported by device\n");
455 }
456 }
457
458 /*If the number of data bits is to be updated*/
459 if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
460 bits = cp2101_get_config(port, CP2101_BITS);
461 bits &= ~BITS_DATA_MASK;
462 switch (cflag & CSIZE) {
463 case CS6:
464 bits |= BITS_DATA_6;
465 dbg("%s - data bits = 6", __FUNCTION__);
466 break;
467 case CS7:
468 bits |= BITS_DATA_7;
469 dbg("%s - data bits = 7", __FUNCTION__);
470 break;
471 case CS8:
472 bits |= BITS_DATA_8;
473 dbg("%s - data bits = 8", __FUNCTION__);
474 break;
475 /*case CS9:
476 bits |= BITS_DATA_9;
477 dbg("%s - data bits = 9", __FUNCTION__);
478 break;*/
479 default:
480 dev_err(&port->dev, "cp2101 driver does not "
481 "support the number of bits requested,"
482 " using 8 bit mode\n");
483 bits |= BITS_DATA_8;
484 break;
485 }
486 if (cp2101_set_config(port, CP2101_BITS, bits))
487 dev_err(&port->dev, "Number of data bits requested "
488 "not supported by device\n");
489 }
490
491 if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))) {
492 bits = cp2101_get_config(port, CP2101_BITS);
493 bits &= ~BITS_PARITY_MASK;
494 if (cflag & PARENB) {
495 if (cflag & PARODD) {
496 bits |= BITS_PARITY_ODD;
497 dbg("%s - parity = ODD", __FUNCTION__);
498 } else {
499 bits |= BITS_PARITY_EVEN;
500 dbg("%s - parity = EVEN", __FUNCTION__);
501 }
502 }
503 if (cp2101_set_config(port, CP2101_BITS, bits))
504 dev_err(&port->dev, "Parity mode not supported "
505 "by device\n");
506 }
507
508 if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) {
509 bits = cp2101_get_config(port, CP2101_BITS);
510 bits &= ~BITS_STOP_MASK;
511 if (cflag & CSTOPB) {
512 bits |= BITS_STOP_2;
513 dbg("%s - stop bits = 2", __FUNCTION__);
514 } else {
515 bits |= BITS_STOP_1;
516 dbg("%s - stop bits = 1", __FUNCTION__);
517 }
518 if (cp2101_set_config(port, CP2101_BITS, bits))
519 dev_err(&port->dev, "Number of stop bits requested "
520 "not supported by device\n");
521 }
522}
523
524static void cp2101_break_ctl (struct usb_serial_port *port, int break_state)
525{
526 u16 state;
527
528 dbg("%s - port %d", __FUNCTION__, port->number);
529 if (break_state == 0)
530 state = BREAK_OFF;
531 else
532 state = BREAK_ON;
533 dbg("%s - turning break %s", __FUNCTION__,
534 state==BREAK_OFF ? "off" : "on");
535 cp2101_set_config(port, CP2101_BREAK, state);
536}
537
538static int cp2101_startup (struct usb_serial *serial)
539{
540 /*CP2101 buffers behave strangely unless device is reset*/
541 usb_reset_device(serial->dev);
542 return 0;
543}
544
545static void cp2101_shutdown (struct usb_serial *serial)
546{
547 int i;
548
549 dbg("%s", __FUNCTION__);
550
551 /* stop reads and writes on all ports */
552 for (i=0; i < serial->num_ports; ++i) {
553 cp2101_cleanup(serial->port[i]);
554 }
555}
556
557static int __init cp2101_init (void)
558{
559 int retval;
560
561 retval = usb_serial_register(&cp2101_device);
562 if (retval)
563 return retval; /*Failed to register*/
564
565 retval = usb_register(&cp2101_driver);
566 if (retval) {
567 /*Failed to register*/
568 usb_serial_deregister(&cp2101_device);
569 return retval;
570 }
571
572 /*Success*/
573 info(DRIVER_DESC " " DRIVER_VERSION);
574 return 0;
575}
576
577static void __exit cp2101_exit (void)
578{
579 usb_deregister (&cp2101_driver);
580 usb_serial_deregister (&cp2101_device);
581}
582
583module_init(cp2101_init);
584module_exit(cp2101_exit);
585
586MODULE_DESCRIPTION(DRIVER_DESC);
587MODULE_VERSION(DRIVER_VERSION);
588MODULE_LICENSE("GPL");
589
590module_param(debug, bool, S_IRUGO | S_IWUSR);
591MODULE_PARM_DESC(debug, "Enable verbose debugging messages");