hcm's fixes
[kernel-power] / usbhost / drivers / usb2 / serial / ch341.c
1 /*
2  * Copyright 2007, Frank A Kingswood <frank@kingswood-consulting.co.uk>
3  *
4  * ch341.c implements a serial port driver for the Winchiphead CH341.
5  *
6  * The CH341 device can be used to implement an RS232 asynchronous
7  * serial port, an IEEE-1284 parallel printer port or a memory-like
8  * interface. In all cases the CH341 supports an I2C interface as well.
9  * This driver only supports the asynchronous serial interface.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License version
13  * 2 as published by the Free Software Foundation.
14  */
15
16 #include <linux/kernel.h>
17 #include <linux/init.h>
18 #include <linux/tty.h>
19 #include <linux/module.h>
20 #include <linux/usb.h>
21 #include <linux/usb/serial.h>
22 #include <linux/serial.h>
23
24 #define DEFAULT_BAUD_RATE 2400
25 #define DEFAULT_TIMEOUT   1000
26
27 static int debug;
28
29 static struct usb_device_id id_table [] = {
30         { USB_DEVICE(0x4348, 0x5523) },
31         { USB_DEVICE(0x1a86, 0x7523) },
32         { },
33 };
34 MODULE_DEVICE_TABLE(usb, id_table);
35
36 struct ch341_private {
37         unsigned baud_rate;
38         u8 dtr;
39         u8 rts;
40 };
41
42 static int ch341_control_out(struct usb_device *dev, u8 request,
43                              u16 value, u16 index)
44 {
45         int r;
46         dbg("ch341_control_out(%02x,%02x,%04x,%04x)", USB_DIR_OUT|0x40,
47                 (int)request, (int)value, (int)index);
48
49         r = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request,
50                             USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
51                             value, index, NULL, 0, DEFAULT_TIMEOUT);
52
53         return r;
54 }
55
56 static int ch341_control_in(struct usb_device *dev,
57                             u8 request, u16 value, u16 index,
58                             char *buf, unsigned bufsize)
59 {
60         int r;
61         dbg("ch341_control_in(%02x,%02x,%04x,%04x,%p,%u)", USB_DIR_IN|0x40,
62                 (int)request, (int)value, (int)index, buf, (int)bufsize);
63
64         r = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request,
65                             USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
66                             value, index, buf, bufsize, DEFAULT_TIMEOUT);
67         return r;
68 }
69
70 static int ch341_set_baudrate(struct usb_device *dev,
71                               struct ch341_private *priv)
72 {
73         short a, b;
74         int r;
75
76         dbg("ch341_set_baudrate(%d)", priv->baud_rate);
77         switch (priv->baud_rate) {
78         case 2400:
79                 a = 0xd901;
80                 b = 0x0038;
81                 break;
82         case 4800:
83                 a = 0x6402;
84                 b = 0x001f;
85                 break;
86         case 9600:
87                 a = 0xb202;
88                 b = 0x0013;
89                 break;
90         case 19200:
91                 a = 0xd902;
92                 b = 0x000d;
93                 break;
94         case 38400:
95                 a = 0x6403;
96                 b = 0x000a;
97                 break;
98         case 115200:
99                 a = 0xcc03;
100                 b = 0x0008;
101                 break;
102         default:
103                 return -EINVAL;
104         }
105
106         r = ch341_control_out(dev, 0x9a, 0x1312, a);
107         if (!r)
108                 r = ch341_control_out(dev, 0x9a, 0x0f2c, b);
109
110         return r;
111 }
112
113 static int ch341_set_handshake(struct usb_device *dev,
114                                struct ch341_private *priv)
115 {
116         dbg("ch341_set_handshake(%d,%d)", priv->dtr, priv->rts);
117         return ch341_control_out(dev, 0xa4,
118                 ~((priv->dtr?1<<5:0)|(priv->rts?1<<6:0)), 0);
119 }
120
121 static int ch341_get_status(struct usb_device *dev)
122 {
123         char *buffer;
124         int r;
125         const unsigned size = 8;
126
127         dbg("ch341_get_status()");
128
129         buffer = kmalloc(size, GFP_KERNEL);
130         if (!buffer)
131                 return -ENOMEM;
132
133         r = ch341_control_in(dev, 0x95, 0x0706, 0, buffer, size);
134         if (r < 0)
135                 goto out;
136
137         /* Not having the datasheet for the CH341, we ignore the bytes returned
138          * from the device. Return error if the device did not respond in time.
139          */
140         r = 0;
141
142 out:    kfree(buffer);
143         return r;
144 }
145
146 /* -------------------------------------------------------------------------- */
147
148 static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
149 {
150         char *buffer;
151         int r;
152         const unsigned size = 8;
153
154         dbg("ch341_configure()");
155
156         buffer = kmalloc(size, GFP_KERNEL);
157         if (!buffer)
158                 return -ENOMEM;
159
160         /* expect two bytes 0x27 0x00 */
161         r = ch341_control_in(dev, 0x5f, 0, 0, buffer, size);
162         if (r < 0)
163                 goto out;
164
165         r = ch341_control_out(dev, 0xa1, 0, 0);
166         if (r < 0)
167                 goto out;
168
169         r = ch341_set_baudrate(dev, priv);
170         if (r < 0)
171                 goto out;
172
173         /* expect two bytes 0x56 0x00 */
174         r = ch341_control_in(dev, 0x95, 0x2518, 0, buffer, size);
175         if (r < 0)
176                 goto out;
177
178         r = ch341_control_out(dev, 0x9a, 0x2518, 0x0050);
179         if (r < 0)
180                 goto out;
181
182         /* expect 0xff 0xee */
183         r = ch341_get_status(dev);
184         if (r < 0)
185                 goto out;
186
187         r = ch341_control_out(dev, 0xa1, 0x501f, 0xd90a);
188         if (r < 0)
189                 goto out;
190
191         r = ch341_set_baudrate(dev, priv);
192         if (r < 0)
193                 goto out;
194
195         r = ch341_set_handshake(dev, priv);
196         if (r < 0)
197                 goto out;
198
199         /* expect 0x9f 0xee */
200         r = ch341_get_status(dev);
201
202 out:    kfree(buffer);
203         return r;
204 }
205
206 /* allocate private data */
207 static int ch341_attach(struct usb_serial *serial)
208 {
209         struct ch341_private *priv;
210         int r;
211
212         dbg("ch341_attach()");
213
214         /* private data */
215         priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL);
216         if (!priv)
217                 return -ENOMEM;
218
219         priv->baud_rate = DEFAULT_BAUD_RATE;
220         priv->dtr = 1;
221         priv->rts = 1;
222
223         r = ch341_configure(serial->dev, priv);
224         if (r < 0)
225                 goto error;
226
227         usb_set_serial_port_data(serial->port[0], priv);
228         return 0;
229
230 error:  kfree(priv);
231         return r;
232 }
233
234 /* open this device, set default parameters */
235 static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port,
236                                 struct file *filp)
237 {
238         struct usb_serial *serial = port->serial;
239         struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]);
240         int r;
241
242         dbg("ch341_open()");
243
244         priv->baud_rate = DEFAULT_BAUD_RATE;
245         priv->dtr = 1;
246         priv->rts = 1;
247
248         r = ch341_configure(serial->dev, priv);
249         if (r)
250                 goto out;
251
252         r = ch341_set_handshake(serial->dev, priv);
253         if (r)
254                 goto out;
255
256         r = ch341_set_baudrate(serial->dev, priv);
257         if (r)
258                 goto out;
259
260         r = usb_serial_generic_open(tty, port, filp);
261
262 out:    return r;
263 }
264
265 /* Old_termios contains the original termios settings and
266  * tty->termios contains the new setting to be used.
267  */
268 static void ch341_set_termios(struct tty_struct *tty,
269                 struct usb_serial_port *port, struct ktermios *old_termios)
270 {
271         struct ch341_private *priv = usb_get_serial_port_data(port);
272         unsigned baud_rate;
273
274         dbg("ch341_set_termios()");
275
276         baud_rate = tty_get_baud_rate(tty);
277
278         switch (baud_rate) {
279         case 2400:
280         case 4800:
281         case 9600:
282         case 19200:
283         case 38400:
284         case 115200:
285                 priv->baud_rate = baud_rate;
286                 break;
287         default:
288                 dbg("Rate %d not supported, using %d",
289                         baud_rate, DEFAULT_BAUD_RATE);
290                 priv->baud_rate = DEFAULT_BAUD_RATE;
291         }
292
293         ch341_set_baudrate(port->serial->dev, priv);
294
295         /* Unimplemented:
296          * (cflag & CSIZE) : data bits [5, 8]
297          * (cflag & PARENB) : parity {NONE, EVEN, ODD}
298          * (cflag & CSTOPB) : stop bits [1, 2]
299          */
300
301          /* Copy back the old hardware settings */
302          tty_termios_copy_hw(tty->termios, old_termios);
303          /* And re-encode with the new baud */
304          tty_encode_baud_rate(tty, baud_rate, baud_rate);
305 }
306
307 static struct usb_driver ch341_driver = {
308         .name           = "ch341",
309         .probe          = usb_serial_probe,
310         .disconnect     = usb_serial_disconnect,
311         .id_table       = id_table,
312         .no_dynamic_id  = 1,
313 };
314
315 static struct usb_serial_driver ch341_device = {
316         .driver = {
317                 .owner  = THIS_MODULE,
318                 .name   = "ch341-uart",
319         },
320         .id_table         = id_table,
321         .usb_driver       = &ch341_driver,
322         .num_ports        = 1,
323         .open             = ch341_open,
324         .set_termios      = ch341_set_termios,
325         .attach           = ch341_attach,
326 };
327
328 static int __init ch341_init(void)
329 {
330         int retval;
331
332         retval = usb_serial_register(&ch341_device);
333         if (retval)
334                 return retval;
335         retval = usb_register(&ch341_driver);
336         if (retval)
337                 usb_serial_deregister(&ch341_device);
338         return retval;
339 }
340
341 static void __exit ch341_exit(void)
342 {
343         usb_deregister(&ch341_driver);
344         usb_serial_deregister(&ch341_device);
345 }
346
347 module_init(ch341_init);
348 module_exit(ch341_exit);
349 MODULE_LICENSE("GPL");
350
351 module_param(debug, bool, S_IRUGO | S_IWUSR);
352 MODULE_PARM_DESC(debug, "Debug enabled or not");
353
354 /* EOF ch341.c */