diff options
Diffstat (limited to 'drivers/usb/serial/ark3116.c')
-rw-r--r-- | drivers/usb/serial/ark3116.c | 977 |
1 files changed, 708 insertions, 269 deletions
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 131e61adaaf7..9b66bf19f751 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2009 by Bart Hartgers (bart.hartgers+ark3116@gmail.com) | ||
3 | * Original version: | ||
2 | * Copyright (C) 2006 | 4 | * Copyright (C) 2006 |
3 | * Simon Schulz (ark3116_driver <at> auctionant.de) | 5 | * Simon Schulz (ark3116_driver <at> auctionant.de) |
4 | * | 6 | * |
@@ -6,10 +8,13 @@ | |||
6 | * - implements a driver for the arkmicro ark3116 chipset (vendor=0x6547, | 8 | * - implements a driver for the arkmicro ark3116 chipset (vendor=0x6547, |
7 | * productid=0x0232) (used in a datacable called KQ-U8A) | 9 | * productid=0x0232) (used in a datacable called KQ-U8A) |
8 | * | 10 | * |
9 | * - based on code by krisfx -> thanks !! | 11 | * Supports full modem status lines, break, hardware flow control. Does not |
10 | * (see http://www.linuxquestions.org/questions/showthread.php?p=2184457#post2184457) | 12 | * support software flow control, since I do not know how to enable it in hw. |
11 | * | 13 | * |
12 | * - based on logs created by usbsnoopy | 14 | * This driver is a essentially new implementation. I initially dug |
15 | * into the old ark3116.c driver and suddenly realized the ark3116 is | ||
16 | * a 16450 with a USB interface glued to it. See comments at the | ||
17 | * bottom of this file. | ||
13 | * | 18 | * |
14 | * This program is free software; you can redistribute it and/or modify it | 19 | * This program is free software; you can redistribute it and/or modify it |
15 | * under the terms of the GNU General Public License as published by the | 20 | * under the terms of the GNU General Public License as published by the |
@@ -19,17 +24,34 @@ | |||
19 | 24 | ||
20 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
21 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/ioctl.h> | ||
22 | #include <linux/tty.h> | 28 | #include <linux/tty.h> |
29 | #include <linux/slab.h> | ||
30 | #include <linux/tty_flip.h> | ||
23 | #include <linux/module.h> | 31 | #include <linux/module.h> |
24 | #include <linux/usb.h> | 32 | #include <linux/usb.h> |
25 | #include <linux/usb/serial.h> | 33 | #include <linux/usb/serial.h> |
26 | #include <linux/serial.h> | 34 | #include <linux/serial.h> |
35 | #include <linux/serial_reg.h> | ||
27 | #include <linux/uaccess.h> | 36 | #include <linux/uaccess.h> |
28 | 37 | #include <linux/mutex.h> | |
38 | #include <linux/spinlock.h> | ||
29 | 39 | ||
30 | static int debug; | 40 | static int debug; |
41 | /* | ||
42 | * Version information | ||
43 | */ | ||
31 | 44 | ||
32 | static struct usb_device_id id_table [] = { | 45 | #define DRIVER_VERSION "v0.5" |
46 | #define DRIVER_AUTHOR "Bart Hartgers <bart.hartgers+ark3116@gmail.com>" | ||
47 | #define DRIVER_DESC "USB ARK3116 serial/IrDA driver" | ||
48 | #define DRIVER_DEV_DESC "ARK3116 RS232/IrDA" | ||
49 | #define DRIVER_NAME "ark3116" | ||
50 | |||
51 | /* usb timeout of 1 second */ | ||
52 | #define ARK_TIMEOUT (1*HZ) | ||
53 | |||
54 | static const struct usb_device_id id_table[] = { | ||
33 | { USB_DEVICE(0x6547, 0x0232) }, | 55 | { USB_DEVICE(0x6547, 0x0232) }, |
34 | { USB_DEVICE(0x18ec, 0x3118) }, /* USB to IrDA adapter */ | 56 | { USB_DEVICE(0x18ec, 0x3118) }, /* USB to IrDA adapter */ |
35 | { }, | 57 | { }, |
@@ -45,118 +67,152 @@ static int is_irda(struct usb_serial *serial) | |||
45 | return 0; | 67 | return 0; |
46 | } | 68 | } |
47 | 69 | ||
48 | static inline void ARK3116_SND(struct usb_serial *serial, int seq, | 70 | struct ark3116_private { |
49 | __u8 request, __u8 requesttype, | 71 | wait_queue_head_t delta_msr_wait; |
50 | __u16 value, __u16 index) | 72 | struct async_icount icount; |
73 | int irda; /* 1 for irda device */ | ||
74 | |||
75 | /* protects hw register updates */ | ||
76 | struct mutex hw_lock; | ||
77 | |||
78 | int quot; /* baudrate divisor */ | ||
79 | __u32 lcr; /* line control register value */ | ||
80 | __u32 hcr; /* handshake control register (0x8) | ||
81 | * value */ | ||
82 | __u32 mcr; /* modem contol register value */ | ||
83 | |||
84 | /* protects the status values below */ | ||
85 | spinlock_t status_lock; | ||
86 | __u32 msr; /* modem status register value */ | ||
87 | __u32 lsr; /* line status register value */ | ||
88 | }; | ||
89 | |||
90 | static int ark3116_write_reg(struct usb_serial *serial, | ||
91 | unsigned reg, __u8 val) | ||
51 | { | 92 | { |
52 | int result; | 93 | int result; |
94 | /* 0xfe 0x40 are magic values taken from original driver */ | ||
53 | result = usb_control_msg(serial->dev, | 95 | result = usb_control_msg(serial->dev, |
54 | usb_sndctrlpipe(serial->dev, 0), | 96 | usb_sndctrlpipe(serial->dev, 0), |
55 | request, requesttype, value, index, | 97 | 0xfe, 0x40, val, reg, |
56 | NULL, 0x00, 1000); | 98 | NULL, 0, ARK_TIMEOUT); |
57 | dbg("%03d > ok", seq); | 99 | return result; |
58 | } | 100 | } |
59 | 101 | ||
60 | static inline void ARK3116_RCV(struct usb_serial *serial, int seq, | 102 | static int ark3116_read_reg(struct usb_serial *serial, |
61 | __u8 request, __u8 requesttype, | 103 | unsigned reg, unsigned char *buf) |
62 | __u16 value, __u16 index, __u8 expected, | ||
63 | char *buf) | ||
64 | { | 104 | { |
65 | int result; | 105 | int result; |
106 | /* 0xfe 0xc0 are magic values taken from original driver */ | ||
66 | result = usb_control_msg(serial->dev, | 107 | result = usb_control_msg(serial->dev, |
67 | usb_rcvctrlpipe(serial->dev, 0), | 108 | usb_rcvctrlpipe(serial->dev, 0), |
68 | request, requesttype, value, index, | 109 | 0xfe, 0xc0, 0, reg, |
69 | buf, 0x0000001, 1000); | 110 | buf, 1, ARK_TIMEOUT); |
70 | if (result) | 111 | if (result < 0) |
71 | dbg("%03d < %d bytes [0x%02X]", seq, result, | 112 | return result; |
72 | ((unsigned char *)buf)[0]); | ||
73 | else | 113 | else |
74 | dbg("%03d < 0 bytes", seq); | 114 | return buf[0]; |
75 | } | 115 | } |
76 | 116 | ||
77 | static inline void ARK3116_RCV_QUIET(struct usb_serial *serial, | 117 | static inline int calc_divisor(int bps) |
78 | __u8 request, __u8 requesttype, | ||
79 | __u16 value, __u16 index, char *buf) | ||
80 | { | 118 | { |
81 | usb_control_msg(serial->dev, | 119 | /* Original ark3116 made some exceptions in rounding here |
82 | usb_rcvctrlpipe(serial->dev, 0), | 120 | * because windows did the same. Assume that is not really |
83 | request, requesttype, value, index, | 121 | * necessary. |
84 | buf, 0x0000001, 1000); | 122 | * Crystal is 12MHz, probably because of USB, but we divide by 4? |
123 | */ | ||
124 | return (12000000 + 2*bps) / (4*bps); | ||
85 | } | 125 | } |
86 | 126 | ||
87 | static int ark3116_attach(struct usb_serial *serial) | 127 | static int ark3116_attach(struct usb_serial *serial) |
88 | { | 128 | { |
89 | char *buf; | 129 | struct usb_serial_port *port = serial->port[0]; |
130 | struct ark3116_private *priv; | ||
131 | |||
132 | /* make sure we have our end-points */ | ||
133 | if ((serial->num_bulk_in == 0) || | ||
134 | (serial->num_bulk_out == 0) || | ||
135 | (serial->num_interrupt_in == 0)) { | ||
136 | dev_err(&serial->dev->dev, | ||
137 | "%s - missing endpoint - " | ||
138 | "bulk in: %d, bulk out: %d, int in %d\n", | ||
139 | KBUILD_MODNAME, | ||
140 | serial->num_bulk_in, | ||
141 | serial->num_bulk_out, | ||
142 | serial->num_interrupt_in); | ||
143 | return -EINVAL; | ||
144 | } | ||
90 | 145 | ||
91 | buf = kmalloc(1, GFP_KERNEL); | 146 | priv = kzalloc(sizeof(struct ark3116_private), |
92 | if (!buf) { | 147 | GFP_KERNEL); |
93 | dbg("error kmalloc -> out of mem?"); | 148 | if (!priv) |
94 | return -ENOMEM; | 149 | return -ENOMEM; |
95 | } | ||
96 | 150 | ||
97 | if (is_irda(serial)) | 151 | init_waitqueue_head(&priv->delta_msr_wait); |
98 | dbg("IrDA mode"); | 152 | mutex_init(&priv->hw_lock); |
153 | spin_lock_init(&priv->status_lock); | ||
154 | |||
155 | priv->irda = is_irda(serial); | ||
99 | 156 | ||
100 | /* 3 */ | 157 | usb_set_serial_port_data(port, priv); |
101 | ARK3116_SND(serial, 3, 0xFE, 0x40, 0x0008, 0x0002); | ||
102 | ARK3116_SND(serial, 4, 0xFE, 0x40, 0x0008, 0x0001); | ||
103 | ARK3116_SND(serial, 5, 0xFE, 0x40, 0x0000, 0x0008); | ||
104 | ARK3116_SND(serial, 6, 0xFE, 0x40, is_irda(serial) ? 0x0001 : 0x0000, | ||
105 | 0x000B); | ||
106 | 158 | ||
107 | if (is_irda(serial)) { | 159 | /* setup the hardware */ |
108 | ARK3116_SND(serial, 1001, 0xFE, 0x40, 0x0000, 0x000C); | 160 | ark3116_write_reg(serial, UART_IER, 0); |
109 | ARK3116_SND(serial, 1002, 0xFE, 0x40, 0x0041, 0x000D); | 161 | /* disable DMA */ |
110 | ARK3116_SND(serial, 1003, 0xFE, 0x40, 0x0001, 0x000A); | 162 | ark3116_write_reg(serial, UART_FCR, 0); |
163 | /* handshake control */ | ||
164 | priv->hcr = 0; | ||
165 | ark3116_write_reg(serial, 0x8 , 0); | ||
166 | /* modem control */ | ||
167 | priv->mcr = 0; | ||
168 | ark3116_write_reg(serial, UART_MCR, 0); | ||
169 | |||
170 | if (!(priv->irda)) { | ||
171 | ark3116_write_reg(serial, 0xb , 0); | ||
172 | } else { | ||
173 | ark3116_write_reg(serial, 0xb , 1); | ||
174 | ark3116_write_reg(serial, 0xc , 0); | ||
175 | ark3116_write_reg(serial, 0xd , 0x41); | ||
176 | ark3116_write_reg(serial, 0xa , 1); | ||
111 | } | 177 | } |
112 | 178 | ||
113 | /* <-- seq7 */ | 179 | /* setup baudrate */ |
114 | ARK3116_RCV(serial, 7, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf); | 180 | ark3116_write_reg(serial, UART_LCR, UART_LCR_DLAB); |
115 | ARK3116_SND(serial, 8, 0xFE, 0x40, 0x0080, 0x0003); | ||
116 | ARK3116_SND(serial, 9, 0xFE, 0x40, 0x001A, 0x0000); | ||
117 | ARK3116_SND(serial, 10, 0xFE, 0x40, 0x0000, 0x0001); | ||
118 | ARK3116_SND(serial, 11, 0xFE, 0x40, 0x0000, 0x0003); | ||
119 | |||
120 | /* <-- seq12 */ | ||
121 | ARK3116_RCV(serial, 12, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf); | ||
122 | ARK3116_SND(serial, 13, 0xFE, 0x40, 0x0000, 0x0004); | ||
123 | |||
124 | /* 14 */ | ||
125 | ARK3116_RCV(serial, 14, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf); | ||
126 | ARK3116_SND(serial, 15, 0xFE, 0x40, 0x0000, 0x0004); | ||
127 | |||
128 | /* 16 */ | ||
129 | ARK3116_RCV(serial, 16, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf); | ||
130 | /* --> seq17 */ | ||
131 | ARK3116_SND(serial, 17, 0xFE, 0x40, 0x0001, 0x0004); | ||
132 | |||
133 | /* <-- seq18 */ | ||
134 | ARK3116_RCV(serial, 18, 0xFE, 0xC0, 0x0000, 0x0004, 0x01, buf); | ||
135 | |||
136 | /* --> seq19 */ | ||
137 | ARK3116_SND(serial, 19, 0xFE, 0x40, 0x0003, 0x0004); | ||
138 | |||
139 | /* <-- seq20 */ | ||
140 | /* seems like serial port status info (RTS, CTS, ...) */ | ||
141 | /* returns modem control line status?! */ | ||
142 | ARK3116_RCV(serial, 20, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf); | ||
143 | |||
144 | /* set 9600 baud & do some init?! */ | ||
145 | ARK3116_SND(serial, 147, 0xFE, 0x40, 0x0083, 0x0003); | ||
146 | ARK3116_SND(serial, 148, 0xFE, 0x40, 0x0038, 0x0000); | ||
147 | ARK3116_SND(serial, 149, 0xFE, 0x40, 0x0001, 0x0001); | ||
148 | if (is_irda(serial)) | ||
149 | ARK3116_SND(serial, 1004, 0xFE, 0x40, 0x0000, 0x0009); | ||
150 | ARK3116_SND(serial, 150, 0xFE, 0x40, 0x0003, 0x0003); | ||
151 | ARK3116_RCV(serial, 151, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf); | ||
152 | ARK3116_SND(serial, 152, 0xFE, 0x40, 0x0000, 0x0003); | ||
153 | ARK3116_RCV(serial, 153, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf); | ||
154 | ARK3116_SND(serial, 154, 0xFE, 0x40, 0x0003, 0x0003); | ||
155 | 181 | ||
156 | kfree(buf); | 182 | /* setup for 9600 8N1 */ |
183 | priv->quot = calc_divisor(9600); | ||
184 | ark3116_write_reg(serial, UART_DLL, priv->quot & 0xff); | ||
185 | ark3116_write_reg(serial, UART_DLM, (priv->quot>>8) & 0xff); | ||
186 | |||
187 | priv->lcr = UART_LCR_WLEN8; | ||
188 | ark3116_write_reg(serial, UART_LCR, UART_LCR_WLEN8); | ||
189 | |||
190 | ark3116_write_reg(serial, 0xe, 0); | ||
191 | |||
192 | if (priv->irda) | ||
193 | ark3116_write_reg(serial, 0x9, 0); | ||
194 | |||
195 | dev_info(&serial->dev->dev, | ||
196 | "%s using %s mode\n", | ||
197 | KBUILD_MODNAME, | ||
198 | priv->irda ? "IrDA" : "RS232"); | ||
157 | return 0; | 199 | return 0; |
158 | } | 200 | } |
159 | 201 | ||
202 | static void ark3116_release(struct usb_serial *serial) | ||
203 | { | ||
204 | struct usb_serial_port *port = serial->port[0]; | ||
205 | struct ark3116_private *priv = usb_get_serial_port_data(port); | ||
206 | |||
207 | /* device is closed, so URBs and DMA should be down */ | ||
208 | |||
209 | usb_set_serial_port_data(port, NULL); | ||
210 | |||
211 | mutex_destroy(&priv->hw_lock); | ||
212 | |||
213 | kfree(priv); | ||
214 | } | ||
215 | |||
160 | static void ark3116_init_termios(struct tty_struct *tty) | 216 | static void ark3116_init_termios(struct tty_struct *tty) |
161 | { | 217 | { |
162 | struct ktermios *termios = tty->termios; | 218 | struct ktermios *termios = tty->termios; |
@@ -172,200 +228,189 @@ static void ark3116_set_termios(struct tty_struct *tty, | |||
172 | struct ktermios *old_termios) | 228 | struct ktermios *old_termios) |
173 | { | 229 | { |
174 | struct usb_serial *serial = port->serial; | 230 | struct usb_serial *serial = port->serial; |
231 | struct ark3116_private *priv = usb_get_serial_port_data(port); | ||
175 | struct ktermios *termios = tty->termios; | 232 | struct ktermios *termios = tty->termios; |
176 | unsigned int cflag = termios->c_cflag; | 233 | unsigned int cflag = termios->c_cflag; |
177 | int baud; | 234 | int bps = tty_get_baud_rate(tty); |
178 | int ark3116_baud; | 235 | int quot; |
179 | char *buf; | 236 | __u8 lcr, hcr, eval; |
180 | char config; | 237 | |
181 | 238 | /* set data bit count */ | |
182 | config = 0; | 239 | switch (cflag & CSIZE) { |
183 | 240 | case CS5: | |
184 | dbg("%s - port %d", __func__, port->number); | 241 | lcr = UART_LCR_WLEN5; |
242 | break; | ||
243 | case CS6: | ||
244 | lcr = UART_LCR_WLEN6; | ||
245 | break; | ||
246 | case CS7: | ||
247 | lcr = UART_LCR_WLEN7; | ||
248 | break; | ||
249 | default: | ||
250 | case CS8: | ||
251 | lcr = UART_LCR_WLEN8; | ||
252 | break; | ||
253 | } | ||
254 | if (cflag & CSTOPB) | ||
255 | lcr |= UART_LCR_STOP; | ||
256 | if (cflag & PARENB) | ||
257 | lcr |= UART_LCR_PARITY; | ||
258 | if (!(cflag & PARODD)) | ||
259 | lcr |= UART_LCR_EPAR; | ||
260 | #ifdef CMSPAR | ||
261 | if (cflag & CMSPAR) | ||
262 | lcr |= UART_LCR_SPAR; | ||
263 | #endif | ||
264 | /* handshake control */ | ||
265 | hcr = (cflag & CRTSCTS) ? 0x03 : 0x00; | ||
266 | |||
267 | /* calc baudrate */ | ||
268 | dbg("%s - setting bps to %d", __func__, bps); | ||
269 | eval = 0; | ||
270 | switch (bps) { | ||
271 | case 0: | ||
272 | quot = calc_divisor(9600); | ||
273 | break; | ||
274 | default: | ||
275 | if ((bps < 75) || (bps > 3000000)) | ||
276 | bps = 9600; | ||
277 | quot = calc_divisor(bps); | ||
278 | break; | ||
279 | case 460800: | ||
280 | eval = 1; | ||
281 | quot = calc_divisor(bps); | ||
282 | break; | ||
283 | case 921600: | ||
284 | eval = 2; | ||
285 | quot = calc_divisor(bps); | ||
286 | break; | ||
287 | } | ||
185 | 288 | ||
289 | /* Update state: synchronize */ | ||
290 | mutex_lock(&priv->hw_lock); | ||
186 | 291 | ||
187 | cflag = termios->c_cflag; | 292 | /* keep old LCR_SBC bit */ |
188 | termios->c_cflag &= ~(CMSPAR|CRTSCTS); | 293 | lcr |= (priv->lcr & UART_LCR_SBC); |
189 | 294 | ||
190 | buf = kmalloc(1, GFP_KERNEL); | 295 | dbg("%s - setting hcr:0x%02x,lcr:0x%02x,quot:%d", |
191 | if (!buf) { | 296 | __func__, hcr, lcr, quot); |
192 | dbg("error kmalloc"); | ||
193 | *termios = *old_termios; | ||
194 | return; | ||
195 | } | ||
196 | 297 | ||
197 | /* set data bit count (8/7/6/5) */ | 298 | /* handshake control */ |
198 | if (cflag & CSIZE) { | 299 | if (priv->hcr != hcr) { |
199 | switch (cflag & CSIZE) { | 300 | priv->hcr = hcr; |
200 | case CS5: | 301 | ark3116_write_reg(serial, 0x8, hcr); |
201 | config |= 0x00; | ||
202 | dbg("setting CS5"); | ||
203 | break; | ||
204 | case CS6: | ||
205 | config |= 0x01; | ||
206 | dbg("setting CS6"); | ||
207 | break; | ||
208 | case CS7: | ||
209 | config |= 0x02; | ||
210 | dbg("setting CS7"); | ||
211 | break; | ||
212 | default: | ||
213 | dbg("CSIZE was set but not CS5-CS8, using CS8!"); | ||
214 | /* fall through */ | ||
215 | case CS8: | ||
216 | config |= 0x03; | ||
217 | dbg("setting CS8"); | ||
218 | break; | ||
219 | } | ||
220 | } | 302 | } |
221 | 303 | ||
222 | /* set parity (NONE/EVEN/ODD) */ | 304 | /* baudrate */ |
223 | if (cflag & PARENB) { | 305 | if (priv->quot != quot) { |
224 | if (cflag & PARODD) { | 306 | priv->quot = quot; |
225 | config |= 0x08; | 307 | priv->lcr = lcr; /* need to write lcr anyway */ |
226 | dbg("setting parity to ODD"); | 308 | |
227 | } else { | 309 | /* disable DMA since transmit/receive is |
228 | config |= 0x18; | 310 | * shadowed by UART_DLL |
229 | dbg("setting parity to EVEN"); | 311 | */ |
230 | } | 312 | ark3116_write_reg(serial, UART_FCR, 0); |
231 | } else { | 313 | |
232 | dbg("setting parity to NONE"); | 314 | ark3116_write_reg(serial, UART_LCR, |
315 | lcr|UART_LCR_DLAB); | ||
316 | ark3116_write_reg(serial, UART_DLL, quot & 0xff); | ||
317 | ark3116_write_reg(serial, UART_DLM, (quot>>8) & 0xff); | ||
318 | |||
319 | /* restore lcr */ | ||
320 | ark3116_write_reg(serial, UART_LCR, lcr); | ||
321 | /* magic baudrate thingy: not sure what it does, | ||
322 | * but windows does this as well. | ||
323 | */ | ||
324 | ark3116_write_reg(serial, 0xe, eval); | ||
325 | |||
326 | /* enable DMA */ | ||
327 | ark3116_write_reg(serial, UART_FCR, UART_FCR_DMA_SELECT); | ||
328 | } else if (priv->lcr != lcr) { | ||
329 | priv->lcr = lcr; | ||
330 | ark3116_write_reg(serial, UART_LCR, lcr); | ||
233 | } | 331 | } |
234 | 332 | ||
235 | /* set stop bit (1/2) */ | 333 | mutex_unlock(&priv->hw_lock); |
236 | if (cflag & CSTOPB) { | ||
237 | config |= 0x04; | ||
238 | dbg("setting 2 stop bits"); | ||
239 | } else { | ||
240 | dbg("setting 1 stop bit"); | ||
241 | } | ||
242 | 334 | ||
243 | /* set baudrate */ | 335 | /* check for software flow control */ |
244 | baud = tty_get_baud_rate(tty); | 336 | if (I_IXOFF(tty) || I_IXON(tty)) { |
245 | 337 | dev_warn(&serial->dev->dev, | |
246 | switch (baud) { | 338 | "%s: don't know how to do software flow control\n", |
247 | case 75: | 339 | KBUILD_MODNAME); |
248 | case 150: | ||
249 | case 300: | ||
250 | case 600: | ||
251 | case 1200: | ||
252 | case 1800: | ||
253 | case 2400: | ||
254 | case 4800: | ||
255 | case 9600: | ||
256 | case 19200: | ||
257 | case 38400: | ||
258 | case 57600: | ||
259 | case 115200: | ||
260 | case 230400: | ||
261 | case 460800: | ||
262 | /* Report the resulting rate back to the caller */ | ||
263 | tty_encode_baud_rate(tty, baud, baud); | ||
264 | break; | ||
265 | /* set 9600 as default (if given baudrate is invalid for example) */ | ||
266 | default: | ||
267 | tty_encode_baud_rate(tty, 9600, 9600); | ||
268 | case 0: | ||
269 | baud = 9600; | ||
270 | } | 340 | } |
271 | 341 | ||
272 | /* | 342 | /* Don't rewrite B0 */ |
273 | * found by try'n'error, be careful, maybe there are other options | 343 | if (tty_termios_baud_rate(termios)) |
274 | * for multiplicator etc! (3.5 for example) | 344 | tty_termios_encode_baud_rate(termios, bps, bps); |
275 | */ | 345 | } |
276 | if (baud == 460800) | ||
277 | /* strange, for 460800 the formula is wrong | ||
278 | * if using round() then 9600baud is wrong) */ | ||
279 | ark3116_baud = 7; | ||
280 | else | ||
281 | ark3116_baud = 3000000 / baud; | ||
282 | |||
283 | /* ? */ | ||
284 | ARK3116_RCV(serial, 0, 0xFE, 0xC0, 0x0000, 0x0003, 0x03, buf); | ||
285 | |||
286 | /* offset = buf[0]; */ | ||
287 | /* offset = 0x03; */ | ||
288 | /* dbg("using 0x%04X as target for 0x0003:", 0x0080 + offset); */ | ||
289 | |||
290 | /* set baudrate */ | ||
291 | dbg("setting baudrate to %d (->reg=%d)", baud, ark3116_baud); | ||
292 | ARK3116_SND(serial, 147, 0xFE, 0x40, 0x0083, 0x0003); | ||
293 | ARK3116_SND(serial, 148, 0xFE, 0x40, | ||
294 | (ark3116_baud & 0x00FF), 0x0000); | ||
295 | ARK3116_SND(serial, 149, 0xFE, 0x40, | ||
296 | (ark3116_baud & 0xFF00) >> 8, 0x0001); | ||
297 | ARK3116_SND(serial, 150, 0xFE, 0x40, 0x0003, 0x0003); | ||
298 | |||
299 | /* ? */ | ||
300 | ARK3116_RCV(serial, 151, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf); | ||
301 | ARK3116_SND(serial, 152, 0xFE, 0x40, 0x0000, 0x0003); | ||
302 | |||
303 | /* set data bit count, stop bit count & parity: */ | ||
304 | dbg("updating bit count, stop bit or parity (cfg=0x%02X)", config); | ||
305 | ARK3116_RCV(serial, 153, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf); | ||
306 | ARK3116_SND(serial, 154, 0xFE, 0x40, config, 0x0003); | ||
307 | 346 | ||
308 | if (cflag & CRTSCTS) | 347 | static void ark3116_close(struct usb_serial_port *port) |
309 | dbg("CRTSCTS not supported by chipset?!"); | 348 | { |
349 | struct usb_serial *serial = port->serial; | ||
310 | 350 | ||
311 | /* TEST ARK3116_SND(154, 0xFE, 0x40, 0xFFFF, 0x0006); */ | 351 | if (serial->dev) { |
352 | /* disable DMA */ | ||
353 | ark3116_write_reg(serial, UART_FCR, 0); | ||
312 | 354 | ||
313 | kfree(buf); | 355 | /* deactivate interrupts */ |
356 | ark3116_write_reg(serial, UART_IER, 0); | ||
314 | 357 | ||
315 | return; | 358 | /* shutdown any bulk reads that might be going on */ |
359 | if (serial->num_bulk_out) | ||
360 | usb_kill_urb(port->write_urb); | ||
361 | if (serial->num_bulk_in) | ||
362 | usb_kill_urb(port->read_urb); | ||
363 | if (serial->num_interrupt_in) | ||
364 | usb_kill_urb(port->interrupt_in_urb); | ||
365 | } | ||
316 | } | 366 | } |
317 | 367 | ||
318 | static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port) | 368 | static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port) |
319 | { | 369 | { |
320 | struct ktermios tmp_termios; | 370 | struct ark3116_private *priv = usb_get_serial_port_data(port); |
321 | struct usb_serial *serial = port->serial; | 371 | struct usb_serial *serial = port->serial; |
322 | char *buf; | 372 | unsigned char *buf; |
323 | int result = 0; | 373 | int result; |
324 | |||
325 | dbg("%s - port %d", __func__, port->number); | ||
326 | 374 | ||
327 | buf = kmalloc(1, GFP_KERNEL); | 375 | buf = kmalloc(1, GFP_KERNEL); |
328 | if (!buf) { | 376 | if (buf == NULL) |
329 | dbg("error kmalloc -> out of mem?"); | ||
330 | return -ENOMEM; | 377 | return -ENOMEM; |
331 | } | ||
332 | 378 | ||
333 | result = usb_serial_generic_open(tty, port); | 379 | result = usb_serial_generic_open(tty, port); |
334 | if (result) | 380 | if (result) { |
381 | dbg("%s - usb_serial_generic_open failed: %d", | ||
382 | __func__, result); | ||
335 | goto err_out; | 383 | goto err_out; |
384 | } | ||
336 | 385 | ||
337 | /* open */ | 386 | /* setup termios */ |
338 | ARK3116_RCV(serial, 111, 0xFE, 0xC0, 0x0000, 0x0003, 0x02, buf); | 387 | if (tty) |
339 | 388 | ark3116_set_termios(tty, port, NULL); | |
340 | ARK3116_SND(serial, 112, 0xFE, 0x40, 0x0082, 0x0003); | ||
341 | ARK3116_SND(serial, 113, 0xFE, 0x40, 0x001A, 0x0000); | ||
342 | ARK3116_SND(serial, 114, 0xFE, 0x40, 0x0000, 0x0001); | ||
343 | ARK3116_SND(serial, 115, 0xFE, 0x40, 0x0002, 0x0003); | ||
344 | |||
345 | ARK3116_RCV(serial, 116, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf); | ||
346 | ARK3116_SND(serial, 117, 0xFE, 0x40, 0x0002, 0x0004); | ||
347 | |||
348 | ARK3116_RCV(serial, 118, 0xFE, 0xC0, 0x0000, 0x0004, 0x02, buf); | ||
349 | ARK3116_SND(serial, 119, 0xFE, 0x40, 0x0000, 0x0004); | ||
350 | |||
351 | ARK3116_RCV(serial, 120, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf); | ||
352 | 389 | ||
353 | ARK3116_SND(serial, 121, 0xFE, 0x40, 0x0001, 0x0004); | 390 | /* remove any data still left: also clears error state */ |
391 | ark3116_read_reg(serial, UART_RX, buf); | ||
354 | 392 | ||
355 | ARK3116_RCV(serial, 122, 0xFE, 0xC0, 0x0000, 0x0004, 0x01, buf); | 393 | /* read modem status */ |
394 | priv->msr = ark3116_read_reg(serial, UART_MSR, buf); | ||
395 | /* read line status */ | ||
396 | priv->lsr = ark3116_read_reg(serial, UART_LSR, buf); | ||
356 | 397 | ||
357 | ARK3116_SND(serial, 123, 0xFE, 0x40, 0x0003, 0x0004); | 398 | result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); |
399 | if (result) { | ||
400 | dev_err(&port->dev, "submit irq_in urb failed %d\n", | ||
401 | result); | ||
402 | ark3116_close(port); | ||
403 | goto err_out; | ||
404 | } | ||
358 | 405 | ||
359 | /* returns different values (control lines?!) */ | 406 | /* activate interrupts */ |
360 | ARK3116_RCV(serial, 124, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf); | 407 | ark3116_write_reg(port->serial, UART_IER, UART_IER_MSI|UART_IER_RLSI); |
361 | 408 | ||
362 | /* initialise termios */ | 409 | /* enable DMA */ |
363 | if (tty) | 410 | ark3116_write_reg(port->serial, UART_FCR, UART_FCR_DMA_SELECT); |
364 | ark3116_set_termios(tty, port, &tmp_termios); | ||
365 | 411 | ||
366 | err_out: | 412 | err_out: |
367 | kfree(buf); | 413 | kfree(buf); |
368 | |||
369 | return result; | 414 | return result; |
370 | } | 415 | } |
371 | 416 | ||
@@ -373,6 +418,7 @@ static int ark3116_ioctl(struct tty_struct *tty, struct file *file, | |||
373 | unsigned int cmd, unsigned long arg) | 418 | unsigned int cmd, unsigned long arg) |
374 | { | 419 | { |
375 | struct usb_serial_port *port = tty->driver_data; | 420 | struct usb_serial_port *port = tty->driver_data; |
421 | struct ark3116_private *priv = usb_get_serial_port_data(port); | ||
376 | struct serial_struct serstruct; | 422 | struct serial_struct serstruct; |
377 | void __user *user_arg = (void __user *)arg; | 423 | void __user *user_arg = (void __user *)arg; |
378 | 424 | ||
@@ -394,9 +440,48 @@ static int ark3116_ioctl(struct tty_struct *tty, struct file *file, | |||
394 | if (copy_from_user(&serstruct, user_arg, sizeof(serstruct))) | 440 | if (copy_from_user(&serstruct, user_arg, sizeof(serstruct))) |
395 | return -EFAULT; | 441 | return -EFAULT; |
396 | return 0; | 442 | return 0; |
397 | default: | 443 | case TIOCMIWAIT: |
398 | dbg("%s cmd 0x%04x not supported", __func__, cmd); | 444 | for (;;) { |
445 | struct async_icount prev = priv->icount; | ||
446 | interruptible_sleep_on(&priv->delta_msr_wait); | ||
447 | /* see if a signal did it */ | ||
448 | if (signal_pending(current)) | ||
449 | return -ERESTARTSYS; | ||
450 | if ((prev.rng == priv->icount.rng) && | ||
451 | (prev.dsr == priv->icount.dsr) && | ||
452 | (prev.dcd == priv->icount.dcd) && | ||
453 | (prev.cts == priv->icount.cts)) | ||
454 | return -EIO; | ||
455 | if ((arg & TIOCM_RNG && | ||
456 | (prev.rng != priv->icount.rng)) || | ||
457 | (arg & TIOCM_DSR && | ||
458 | (prev.dsr != priv->icount.dsr)) || | ||
459 | (arg & TIOCM_CD && | ||
460 | (prev.dcd != priv->icount.dcd)) || | ||
461 | (arg & TIOCM_CTS && | ||
462 | (prev.cts != priv->icount.cts))) | ||
463 | return 0; | ||
464 | } | ||
399 | break; | 465 | break; |
466 | case TIOCGICOUNT: { | ||
467 | struct serial_icounter_struct icount; | ||
468 | struct async_icount cnow = priv->icount; | ||
469 | memset(&icount, 0, sizeof(icount)); | ||
470 | icount.cts = cnow.cts; | ||
471 | icount.dsr = cnow.dsr; | ||
472 | icount.rng = cnow.rng; | ||
473 | icount.dcd = cnow.dcd; | ||
474 | icount.rx = cnow.rx; | ||
475 | icount.tx = cnow.tx; | ||
476 | icount.frame = cnow.frame; | ||
477 | icount.overrun = cnow.overrun; | ||
478 | icount.parity = cnow.parity; | ||
479 | icount.brk = cnow.brk; | ||
480 | icount.buf_overrun = cnow.buf_overrun; | ||
481 | if (copy_to_user(user_arg, &icount, sizeof(icount))) | ||
482 | return -EFAULT; | ||
483 | return 0; | ||
484 | } | ||
400 | } | 485 | } |
401 | 486 | ||
402 | return -ENOIOCTLCMD; | 487 | return -ENOIOCTLCMD; |
@@ -405,32 +490,272 @@ static int ark3116_ioctl(struct tty_struct *tty, struct file *file, | |||
405 | static int ark3116_tiocmget(struct tty_struct *tty, struct file *file) | 490 | static int ark3116_tiocmget(struct tty_struct *tty, struct file *file) |
406 | { | 491 | { |
407 | struct usb_serial_port *port = tty->driver_data; | 492 | struct usb_serial_port *port = tty->driver_data; |
408 | struct usb_serial *serial = port->serial; | 493 | struct ark3116_private *priv = usb_get_serial_port_data(port); |
409 | char *buf; | 494 | __u32 status; |
410 | char temp; | 495 | __u32 ctrl; |
496 | unsigned long flags; | ||
497 | |||
498 | mutex_lock(&priv->hw_lock); | ||
499 | ctrl = priv->mcr; | ||
500 | mutex_unlock(&priv->hw_lock); | ||
501 | |||
502 | spin_lock_irqsave(&priv->status_lock, flags); | ||
503 | status = priv->msr; | ||
504 | spin_unlock_irqrestore(&priv->status_lock, flags); | ||
505 | |||
506 | return (status & UART_MSR_DSR ? TIOCM_DSR : 0) | | ||
507 | (status & UART_MSR_CTS ? TIOCM_CTS : 0) | | ||
508 | (status & UART_MSR_RI ? TIOCM_RI : 0) | | ||
509 | (status & UART_MSR_DCD ? TIOCM_CD : 0) | | ||
510 | (ctrl & UART_MCR_DTR ? TIOCM_DTR : 0) | | ||
511 | (ctrl & UART_MCR_RTS ? TIOCM_RTS : 0) | | ||
512 | (ctrl & UART_MCR_OUT1 ? TIOCM_OUT1 : 0) | | ||
513 | (ctrl & UART_MCR_OUT2 ? TIOCM_OUT2 : 0); | ||
514 | } | ||
411 | 515 | ||
412 | /* seems like serial port status info (RTS, CTS, ...) is stored | 516 | static int ark3116_tiocmset(struct tty_struct *tty, struct file *file, |
413 | * in reg(?) 0x0006 | 517 | unsigned set, unsigned clr) |
414 | * pcb connection point 11 = GND -> sets bit4 of response | 518 | { |
415 | * pcb connection point 7 = GND -> sets bit6 of response | 519 | struct usb_serial_port *port = tty->driver_data; |
520 | struct ark3116_private *priv = usb_get_serial_port_data(port); | ||
521 | |||
522 | /* we need to take the mutex here, to make sure that the value | ||
523 | * in priv->mcr is actually the one that is in the hardware | ||
416 | */ | 524 | */ |
417 | 525 | ||
418 | buf = kmalloc(1, GFP_KERNEL); | 526 | mutex_lock(&priv->hw_lock); |
419 | if (!buf) { | 527 | |
420 | dbg("error kmalloc"); | 528 | if (set & TIOCM_RTS) |
421 | return -ENOMEM; | 529 | priv->mcr |= UART_MCR_RTS; |
530 | if (set & TIOCM_DTR) | ||
531 | priv->mcr |= UART_MCR_DTR; | ||
532 | if (set & TIOCM_OUT1) | ||
533 | priv->mcr |= UART_MCR_OUT1; | ||
534 | if (set & TIOCM_OUT2) | ||
535 | priv->mcr |= UART_MCR_OUT2; | ||
536 | if (clr & TIOCM_RTS) | ||
537 | priv->mcr &= ~UART_MCR_RTS; | ||
538 | if (clr & TIOCM_DTR) | ||
539 | priv->mcr &= ~UART_MCR_DTR; | ||
540 | if (clr & TIOCM_OUT1) | ||
541 | priv->mcr &= ~UART_MCR_OUT1; | ||
542 | if (clr & TIOCM_OUT2) | ||
543 | priv->mcr &= ~UART_MCR_OUT2; | ||
544 | |||
545 | ark3116_write_reg(port->serial, UART_MCR, priv->mcr); | ||
546 | |||
547 | mutex_unlock(&priv->hw_lock); | ||
548 | |||
549 | return 0; | ||
550 | } | ||
551 | |||
552 | static void ark3116_break_ctl(struct tty_struct *tty, int break_state) | ||
553 | { | ||
554 | struct usb_serial_port *port = tty->driver_data; | ||
555 | struct ark3116_private *priv = usb_get_serial_port_data(port); | ||
556 | |||
557 | /* LCR is also used for other things: protect access */ | ||
558 | mutex_lock(&priv->hw_lock); | ||
559 | |||
560 | if (break_state) | ||
561 | priv->lcr |= UART_LCR_SBC; | ||
562 | else | ||
563 | priv->lcr &= ~UART_LCR_SBC; | ||
564 | |||
565 | ark3116_write_reg(port->serial, UART_LCR, priv->lcr); | ||
566 | |||
567 | mutex_unlock(&priv->hw_lock); | ||
568 | } | ||
569 | |||
570 | static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr) | ||
571 | { | ||
572 | struct ark3116_private *priv = usb_get_serial_port_data(port); | ||
573 | unsigned long flags; | ||
574 | |||
575 | spin_lock_irqsave(&priv->status_lock, flags); | ||
576 | priv->msr = msr; | ||
577 | spin_unlock_irqrestore(&priv->status_lock, flags); | ||
578 | |||
579 | if (msr & UART_MSR_ANY_DELTA) { | ||
580 | /* update input line counters */ | ||
581 | if (msr & UART_MSR_DCTS) | ||
582 | priv->icount.cts++; | ||
583 | if (msr & UART_MSR_DDSR) | ||
584 | priv->icount.dsr++; | ||
585 | if (msr & UART_MSR_DDCD) | ||
586 | priv->icount.dcd++; | ||
587 | if (msr & UART_MSR_TERI) | ||
588 | priv->icount.rng++; | ||
589 | wake_up_interruptible(&priv->delta_msr_wait); | ||
422 | } | 590 | } |
591 | } | ||
423 | 592 | ||
424 | /* read register */ | 593 | static void ark3116_update_lsr(struct usb_serial_port *port, __u8 lsr) |
425 | ARK3116_RCV_QUIET(serial, 0xFE, 0xC0, 0x0000, 0x0006, buf); | 594 | { |
426 | temp = buf[0]; | 595 | struct ark3116_private *priv = usb_get_serial_port_data(port); |
427 | kfree(buf); | 596 | unsigned long flags; |
597 | |||
598 | spin_lock_irqsave(&priv->status_lock, flags); | ||
599 | /* combine bits */ | ||
600 | priv->lsr |= lsr; | ||
601 | spin_unlock_irqrestore(&priv->status_lock, flags); | ||
602 | |||
603 | if (lsr&UART_LSR_BRK_ERROR_BITS) { | ||
604 | if (lsr & UART_LSR_BI) | ||
605 | priv->icount.brk++; | ||
606 | if (lsr & UART_LSR_FE) | ||
607 | priv->icount.frame++; | ||
608 | if (lsr & UART_LSR_PE) | ||
609 | priv->icount.parity++; | ||
610 | if (lsr & UART_LSR_OE) | ||
611 | priv->icount.overrun++; | ||
612 | } | ||
613 | } | ||
428 | 614 | ||
429 | /* i do not really know if bit4=CTS and bit6=DSR... just a | 615 | static void ark3116_read_int_callback(struct urb *urb) |
430 | * quick guess! | 616 | { |
431 | */ | 617 | struct usb_serial_port *port = urb->context; |
432 | return (temp & (1<<4) ? TIOCM_CTS : 0) | 618 | int status = urb->status; |
433 | | (temp & (1<<6) ? TIOCM_DSR : 0); | 619 | const __u8 *data = urb->transfer_buffer; |
620 | int result; | ||
621 | |||
622 | switch (status) { | ||
623 | case -ECONNRESET: | ||
624 | case -ENOENT: | ||
625 | case -ESHUTDOWN: | ||
626 | /* this urb is terminated, clean up */ | ||
627 | dbg("%s - urb shutting down with status: %d", | ||
628 | __func__, status); | ||
629 | return; | ||
630 | default: | ||
631 | dbg("%s - nonzero urb status received: %d", | ||
632 | __func__, status); | ||
633 | break; | ||
634 | case 0: /* success */ | ||
635 | /* discovered this by trail and error... */ | ||
636 | if ((urb->actual_length == 4) && (data[0] == 0xe8)) { | ||
637 | const __u8 id = data[1]&UART_IIR_ID; | ||
638 | dbg("%s: iir=%02x", __func__, data[1]); | ||
639 | if (id == UART_IIR_MSI) { | ||
640 | dbg("%s: msr=%02x", __func__, data[3]); | ||
641 | ark3116_update_msr(port, data[3]); | ||
642 | break; | ||
643 | } else if (id == UART_IIR_RLSI) { | ||
644 | dbg("%s: lsr=%02x", __func__, data[2]); | ||
645 | ark3116_update_lsr(port, data[2]); | ||
646 | break; | ||
647 | } | ||
648 | } | ||
649 | /* | ||
650 | * Not sure what this data meant... | ||
651 | */ | ||
652 | usb_serial_debug_data(debug, &port->dev, | ||
653 | __func__, | ||
654 | urb->actual_length, | ||
655 | urb->transfer_buffer); | ||
656 | break; | ||
657 | } | ||
658 | |||
659 | result = usb_submit_urb(urb, GFP_ATOMIC); | ||
660 | if (result) | ||
661 | dev_err(&urb->dev->dev, | ||
662 | "%s - Error %d submitting interrupt urb\n", | ||
663 | __func__, result); | ||
664 | } | ||
665 | |||
666 | |||
667 | /* Data comes in via the bulk (data) URB, erors/interrupts via the int URB. | ||
668 | * This means that we cannot be sure which data byte has an associated error | ||
669 | * condition, so we report an error for all data in the next bulk read. | ||
670 | * | ||
671 | * Actually, there might even be a window between the bulk data leaving the | ||
672 | * ark and reading/resetting the lsr in the read_bulk_callback where an | ||
673 | * interrupt for the next data block could come in. | ||
674 | * Without somekind of ordering on the ark, we would have to report the | ||
675 | * error for the next block of data as well... | ||
676 | * For now, let's pretend this can't happen. | ||
677 | */ | ||
678 | |||
679 | static void send_to_tty(struct tty_struct *tty, | ||
680 | const unsigned char *chars, | ||
681 | size_t size, char flag) | ||
682 | { | ||
683 | if (size == 0) | ||
684 | return; | ||
685 | if (flag == TTY_NORMAL) { | ||
686 | tty_insert_flip_string(tty, chars, size); | ||
687 | } else { | ||
688 | int i; | ||
689 | for (i = 0; i < size; ++i) | ||
690 | tty_insert_flip_char(tty, chars[i], flag); | ||
691 | } | ||
692 | } | ||
693 | |||
694 | static void ark3116_read_bulk_callback(struct urb *urb) | ||
695 | { | ||
696 | struct usb_serial_port *port = urb->context; | ||
697 | struct ark3116_private *priv = usb_get_serial_port_data(port); | ||
698 | const __u8 *data = urb->transfer_buffer; | ||
699 | int status = urb->status; | ||
700 | struct tty_struct *tty; | ||
701 | unsigned long flags; | ||
702 | int result; | ||
703 | char flag; | ||
704 | __u32 lsr; | ||
705 | |||
706 | switch (status) { | ||
707 | case -ECONNRESET: | ||
708 | case -ENOENT: | ||
709 | case -ESHUTDOWN: | ||
710 | /* this urb is terminated, clean up */ | ||
711 | dbg("%s - urb shutting down with status: %d", | ||
712 | __func__, status); | ||
713 | return; | ||
714 | default: | ||
715 | dbg("%s - nonzero urb status received: %d", | ||
716 | __func__, status); | ||
717 | break; | ||
718 | case 0: /* success */ | ||
719 | |||
720 | spin_lock_irqsave(&priv->status_lock, flags); | ||
721 | lsr = priv->lsr; | ||
722 | /* clear error bits */ | ||
723 | priv->lsr &= ~UART_LSR_BRK_ERROR_BITS; | ||
724 | spin_unlock_irqrestore(&priv->status_lock, flags); | ||
725 | |||
726 | if (unlikely(lsr & UART_LSR_BI)) | ||
727 | flag = TTY_BREAK; | ||
728 | else if (unlikely(lsr & UART_LSR_PE)) | ||
729 | flag = TTY_PARITY; | ||
730 | else if (unlikely(lsr & UART_LSR_FE)) | ||
731 | flag = TTY_FRAME; | ||
732 | else | ||
733 | flag = TTY_NORMAL; | ||
734 | |||
735 | tty = tty_port_tty_get(&port->port); | ||
736 | if (tty) { | ||
737 | /* overrun is special, not associated with a char */ | ||
738 | if (unlikely(lsr & UART_LSR_OE)) | ||
739 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
740 | send_to_tty(tty, data, urb->actual_length, flag); | ||
741 | tty_flip_buffer_push(tty); | ||
742 | tty_kref_put(tty); | ||
743 | } | ||
744 | |||
745 | /* Throttle the device if requested by tty */ | ||
746 | spin_lock_irqsave(&port->lock, flags); | ||
747 | port->throttled = port->throttle_req; | ||
748 | if (port->throttled) { | ||
749 | spin_unlock_irqrestore(&port->lock, flags); | ||
750 | return; | ||
751 | } else | ||
752 | spin_unlock_irqrestore(&port->lock, flags); | ||
753 | } | ||
754 | /* Continue reading from device */ | ||
755 | result = usb_submit_urb(urb, GFP_ATOMIC); | ||
756 | if (result) | ||
757 | dev_err(&urb->dev->dev, "%s - failed resubmitting" | ||
758 | " read urb, error %d\n", __func__, result); | ||
434 | } | 759 | } |
435 | 760 | ||
436 | static struct usb_driver ark3116_driver = { | 761 | static struct usb_driver ark3116_driver = { |
@@ -450,11 +775,17 @@ static struct usb_serial_driver ark3116_device = { | |||
450 | .usb_driver = &ark3116_driver, | 775 | .usb_driver = &ark3116_driver, |
451 | .num_ports = 1, | 776 | .num_ports = 1, |
452 | .attach = ark3116_attach, | 777 | .attach = ark3116_attach, |
778 | .release = ark3116_release, | ||
453 | .set_termios = ark3116_set_termios, | 779 | .set_termios = ark3116_set_termios, |
454 | .init_termios = ark3116_init_termios, | 780 | .init_termios = ark3116_init_termios, |
455 | .ioctl = ark3116_ioctl, | 781 | .ioctl = ark3116_ioctl, |
456 | .tiocmget = ark3116_tiocmget, | 782 | .tiocmget = ark3116_tiocmget, |
783 | .tiocmset = ark3116_tiocmset, | ||
457 | .open = ark3116_open, | 784 | .open = ark3116_open, |
785 | .close = ark3116_close, | ||
786 | .break_ctl = ark3116_break_ctl, | ||
787 | .read_int_callback = ark3116_read_int_callback, | ||
788 | .read_bulk_callback = ark3116_read_bulk_callback, | ||
458 | }; | 789 | }; |
459 | 790 | ||
460 | static int __init ark3116_init(void) | 791 | static int __init ark3116_init(void) |
@@ -465,7 +796,12 @@ static int __init ark3116_init(void) | |||
465 | if (retval) | 796 | if (retval) |
466 | return retval; | 797 | return retval; |
467 | retval = usb_register(&ark3116_driver); | 798 | retval = usb_register(&ark3116_driver); |
468 | if (retval) | 799 | if (retval == 0) { |
800 | printk(KERN_INFO "%s:" | ||
801 | DRIVER_VERSION ":" | ||
802 | DRIVER_DESC "\n", | ||
803 | KBUILD_MODNAME); | ||
804 | } else | ||
469 | usb_serial_deregister(&ark3116_device); | 805 | usb_serial_deregister(&ark3116_device); |
470 | return retval; | 806 | return retval; |
471 | } | 807 | } |
@@ -480,6 +816,109 @@ module_init(ark3116_init); | |||
480 | module_exit(ark3116_exit); | 816 | module_exit(ark3116_exit); |
481 | MODULE_LICENSE("GPL"); | 817 | MODULE_LICENSE("GPL"); |
482 | 818 | ||
819 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
820 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
821 | |||
483 | module_param(debug, bool, S_IRUGO | S_IWUSR); | 822 | module_param(debug, bool, S_IRUGO | S_IWUSR); |
484 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | 823 | MODULE_PARM_DESC(debug, "Enable debug"); |
485 | 824 | ||
825 | /* | ||
826 | * The following describes what I learned from studying the old | ||
827 | * ark3116.c driver, disassembling the windows driver, and some lucky | ||
828 | * guesses. Since I do not have any datasheet or other | ||
829 | * documentation, inaccuracies are almost guaranteed. | ||
830 | * | ||
831 | * Some specs for the ARK3116 can be found here: | ||
832 | * http://web.archive.org/web/20060318000438/ | ||
833 | * www.arkmicro.com/en/products/view.php?id=10 | ||
834 | * On that page, 2 GPIO pins are mentioned: I assume these are the | ||
835 | * OUT1 and OUT2 pins of the UART, so I added support for those | ||
836 | * through the MCR. Since the pins are not available on my hardware, | ||
837 | * I could not verify this. | ||
838 | * Also, it states there is "on-chip hardware flow control". I have | ||
839 | * discovered how to enable that. Unfortunately, I do not know how to | ||
840 | * enable XON/XOFF (software) flow control, which would need support | ||
841 | * from the chip as well to work. Because of the wording on the web | ||
842 | * page there is a real possibility the chip simply does not support | ||
843 | * software flow control. | ||
844 | * | ||
845 | * I got my ark3116 as part of a mobile phone adapter cable. On the | ||
846 | * PCB, the following numbered contacts are present: | ||
847 | * | ||
848 | * 1:- +5V | ||
849 | * 2:o DTR | ||
850 | * 3:i RX | ||
851 | * 4:i DCD | ||
852 | * 5:o RTS | ||
853 | * 6:o TX | ||
854 | * 7:i RI | ||
855 | * 8:i DSR | ||
856 | * 10:- 0V | ||
857 | * 11:i CTS | ||
858 | * | ||
859 | * On my chip, all signals seem to be 3.3V, but 5V tolerant. But that | ||
860 | * may be different for the one you have ;-). | ||
861 | * | ||
862 | * The windows driver limits the registers to 0-F, so I assume there | ||
863 | * are actually 16 present on the device. | ||
864 | * | ||
865 | * On an UART interrupt, 4 bytes of data come in on the interrupt | ||
866 | * endpoint. The bytes are 0xe8 IIR LSR MSR. | ||
867 | * | ||
868 | * The baudrate seems to be generated from the 12MHz crystal, using | ||
869 | * 4-times subsampling. So quot=12e6/(4*baud). Also see description | ||
870 | * of register E. | ||
871 | * | ||
872 | * Registers 0-7: | ||
873 | * These seem to be the same as for a regular 16450. The FCR is set | ||
874 | * to UART_FCR_DMA_SELECT (0x8), I guess to enable transfers between | ||
875 | * the UART and the USB bridge/DMA engine. | ||
876 | * | ||
877 | * Register 8: | ||
878 | * By trial and error, I found out that bit 0 enables hardware CTS, | ||
879 | * stopping TX when CTS is +5V. Bit 1 does the same for RTS, making | ||
880 | * RTS +5V when the 3116 cannot transfer the data to the USB bus | ||
881 | * (verified by disabling the reading URB). Note that as far as I can | ||
882 | * tell, the windows driver does NOT use this, so there might be some | ||
883 | * hardware bug or something. | ||
884 | * | ||
885 | * According to a patch provided here | ||
886 | * (http://lkml.org/lkml/2009/7/26/56), the ARK3116 can also be used | ||
887 | * as an IrDA dongle. Since I do not have such a thing, I could not | ||
888 | * investigate that aspect. However, I can speculate ;-). | ||
889 | * | ||
890 | * - IrDA encodes data differently than RS232. Most likely, one of | ||
891 | * the bits in registers 9..E enables the IR ENDEC (encoder/decoder). | ||
892 | * - Depending on the IR transceiver, the input and output need to be | ||
893 | * inverted, so there are probably bits for that as well. | ||
894 | * - IrDA is half-duplex, so there should be a bit for selecting that. | ||
895 | * | ||
896 | * This still leaves at least two registers unaccounted for. Perhaps | ||
897 | * The chip can do XON/XOFF or CRC in HW? | ||
898 | * | ||
899 | * Register 9: | ||
900 | * Set to 0x00 for IrDA, when the baudrate is initialised. | ||
901 | * | ||
902 | * Register A: | ||
903 | * Set to 0x01 for IrDA, at init. | ||
904 | * | ||
905 | * Register B: | ||
906 | * Set to 0x01 for IrDA, 0x00 for RS232, at init. | ||
907 | * | ||
908 | * Register C: | ||
909 | * Set to 00 for IrDA, at init. | ||
910 | * | ||
911 | * Register D: | ||
912 | * Set to 0x41 for IrDA, at init. | ||
913 | * | ||
914 | * Register E: | ||
915 | * Somekind of baudrate override. The windows driver seems to set | ||
916 | * this to 0x00 for normal baudrates, 0x01 for 460800, 0x02 for 921600. | ||
917 | * Since 460800 and 921600 cannot be obtained by dividing 3MHz by an integer, | ||
918 | * it could be somekind of subdivisor thingy. | ||
919 | * However,it does not seem to do anything: selecting 921600 (divisor 3, | ||
920 | * reg E=2), still gets 1 MHz. I also checked if registers 9, C or F would | ||
921 | * work, but they don't. | ||
922 | * | ||
923 | * Register F: unknown | ||
924 | */ | ||