diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/Kconfig | 10 | ||||
-rw-r--r-- | drivers/usb/serial/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/serial/oti6858.c | 1341 | ||||
-rw-r--r-- | drivers/usb/serial/oti6858.h | 15 |
4 files changed, 1367 insertions, 0 deletions
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 3efe67092f15..43d6db696f90 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig | |||
@@ -464,6 +464,16 @@ config USB_SERIAL_PL2303 | |||
464 | To compile this driver as a module, choose M here: the | 464 | To compile this driver as a module, choose M here: the |
465 | module will be called pl2303. | 465 | module will be called pl2303. |
466 | 466 | ||
467 | config USB_SERIAL_OTI6858 | ||
468 | tristate "USB Ours Technology Inc. OTi-6858 USB To RS232 Bridge Controller (EXPERIMENTAL)" | ||
469 | depends on USB_SERIAL | ||
470 | help | ||
471 | Say Y here if you want to use the OTi-6858 single port USB to serial | ||
472 | converter device. | ||
473 | |||
474 | To compile this driver as a module, choose M here: the | ||
475 | module will be called oti6858. | ||
476 | |||
467 | config USB_SERIAL_HP4X | 477 | config USB_SERIAL_HP4X |
468 | tristate "USB HP4x Calculators support" | 478 | tristate "USB HP4x Calculators support" |
469 | depends on USB_SERIAL | 479 | depends on USB_SERIAL |
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 61166ad450e6..07a976eca6b7 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile | |||
@@ -40,6 +40,7 @@ obj-$(CONFIG_USB_SERIAL_MOS7840) += mos7840.o | |||
40 | obj-$(CONFIG_USB_SERIAL_NAVMAN) += navman.o | 40 | obj-$(CONFIG_USB_SERIAL_NAVMAN) += navman.o |
41 | obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o | 41 | obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o |
42 | obj-$(CONFIG_USB_SERIAL_OPTION) += option.o | 42 | obj-$(CONFIG_USB_SERIAL_OPTION) += option.o |
43 | obj-$(CONFIG_USB_SERIAL_OTI6858) += oti6858.o | ||
43 | obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o | 44 | obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o |
44 | obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o | 45 | obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o |
45 | obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o | 46 | obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o |
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c new file mode 100644 index 000000000000..2a609922ab91 --- /dev/null +++ b/drivers/usb/serial/oti6858.c | |||
@@ -0,0 +1,1341 @@ | |||
1 | /* | ||
2 | * Ours Technology Inc. OTi-6858 USB to serial adapter driver. | ||
3 | * | ||
4 | * Copyleft (C) 2007 Kees Lemmens (adapted for kernel 2.6.20) | ||
5 | * Copyright (C) 2006 Tomasz Michal Lukaszewski (FIXME: add e-mail) | ||
6 | * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) | ||
7 | * Copyright (C) 2003 IBM Corp. | ||
8 | * | ||
9 | * Many thanks to the authors of pl2303 driver: all functions in this file | ||
10 | * are heavily based on pl2303 code, buffering code is a 1-to-1 copy. | ||
11 | * | ||
12 | * Warning! You use this driver on your own risk! The only official | ||
13 | * description of this device I have is datasheet from manufacturer, | ||
14 | * and it doesn't contain almost any information needed to write a driver. | ||
15 | * Almost all knowlegde used while writing this driver was gathered by: | ||
16 | * - analyzing traffic between device and the M$ Windows 2000 driver, | ||
17 | * - trying different bit combinations and checking pin states | ||
18 | * with a voltmeter, | ||
19 | * - receiving malformed frames and producing buffer overflows | ||
20 | * to learn how errors are reported, | ||
21 | * So, THIS CODE CAN DESTROY OTi-6858 AND ANY OTHER DEVICES, THAT ARE | ||
22 | * CONNECTED TO IT! | ||
23 | * | ||
24 | * This program is free software; you can redistribute it and/or modify | ||
25 | * it under the terms of the GNU General Public License as published by | ||
26 | * the Free Software Foundation; either version 2 of the License. | ||
27 | * | ||
28 | * See Documentation/usb/usb-serial.txt for more information on using this driver | ||
29 | * | ||
30 | * TODO: | ||
31 | * - implement correct flushing for ioctls and oti6858_close() | ||
32 | * - check how errors (rx overflow, parity error, framing error) are reported | ||
33 | * - implement oti6858_break_ctl() | ||
34 | * - implement more ioctls | ||
35 | * - test/implement flow control | ||
36 | * - allow setting custom baud rates | ||
37 | */ | ||
38 | |||
39 | #include <linux/kernel.h> | ||
40 | #include <linux/errno.h> | ||
41 | #include <linux/init.h> | ||
42 | #include <linux/slab.h> | ||
43 | #include <linux/tty.h> | ||
44 | #include <linux/tty_driver.h> | ||
45 | #include <linux/tty_flip.h> | ||
46 | #include <linux/serial.h> | ||
47 | #include <linux/module.h> | ||
48 | #include <linux/moduleparam.h> | ||
49 | #include <linux/spinlock.h> | ||
50 | #include <linux/usb.h> | ||
51 | #include <linux/usb/serial.h> | ||
52 | #include <asm/uaccess.h> | ||
53 | #include "oti6858.h" | ||
54 | |||
55 | #define OTI6858_DESCRIPTION \ | ||
56 | "Ours Technology Inc. OTi-6858 USB to serial adapter driver" | ||
57 | #define OTI6858_AUTHOR "Tomasz Michal Lukaszewski <FIXME@FIXME>" | ||
58 | #define OTI6858_VERSION "0.1" | ||
59 | |||
60 | static struct usb_device_id id_table [] = { | ||
61 | { USB_DEVICE(OTI6858_VENDOR_ID, OTI6858_PRODUCT_ID) }, | ||
62 | { } | ||
63 | }; | ||
64 | |||
65 | MODULE_DEVICE_TABLE(usb, id_table); | ||
66 | |||
67 | static struct usb_driver oti6858_driver = { | ||
68 | .name = "oti6858", | ||
69 | .probe = usb_serial_probe, | ||
70 | .disconnect = usb_serial_disconnect, | ||
71 | .id_table = id_table, | ||
72 | .no_dynamic_id = 1, | ||
73 | }; | ||
74 | |||
75 | static int debug; | ||
76 | |||
77 | |||
78 | /* buffering code, copied from pl2303 driver */ | ||
79 | #define PL2303_BUF_SIZE 1024 | ||
80 | #define PL2303_TMP_BUF_SIZE 1024 | ||
81 | |||
82 | struct pl2303_buf { | ||
83 | unsigned int buf_size; | ||
84 | char *buf_buf; | ||
85 | char *buf_get; | ||
86 | char *buf_put; | ||
87 | }; | ||
88 | |||
89 | /* requests */ | ||
90 | #define OTI6858_REQ_GET_STATUS (USB_DIR_IN | USB_TYPE_VENDOR | 0x00) | ||
91 | #define OTI6858_REQ_T_GET_STATUS 0x01 | ||
92 | |||
93 | #define OTI6858_REQ_SET_LINE (USB_DIR_OUT | USB_TYPE_VENDOR | 0x00) | ||
94 | #define OTI6858_REQ_T_SET_LINE 0x00 | ||
95 | |||
96 | #define OTI6858_REQ_CHECK_TXBUFF (USB_DIR_IN | USB_TYPE_VENDOR | 0x01) | ||
97 | #define OTI6858_REQ_T_CHECK_TXBUFF 0x00 | ||
98 | |||
99 | /* format of the control packet */ | ||
100 | struct oti6858_control_pkt { | ||
101 | u16 divisor; /* baud rate = 96000000 / (16 * divisor), LE */ | ||
102 | #define OTI6858_MAX_BAUD_RATE 3000000 | ||
103 | u8 frame_fmt; | ||
104 | #define FMT_STOP_BITS_MASK 0xc0 | ||
105 | #define FMT_STOP_BITS_1 0x00 | ||
106 | #define FMT_STOP_BITS_2 0x40 /* 1.5 stop bits if FMT_DATA_BITS_5 */ | ||
107 | #define FMT_PARITY_MASK 0x38 | ||
108 | #define FMT_PARITY_NONE 0x00 | ||
109 | #define FMT_PARITY_ODD 0x08 | ||
110 | #define FMT_PARITY_EVEN 0x18 | ||
111 | #define FMT_PARITY_MARK 0x28 | ||
112 | #define FMT_PARITY_SPACE 0x38 | ||
113 | #define FMT_DATA_BITS_MASK 0x03 | ||
114 | #define FMT_DATA_BITS_5 0x00 | ||
115 | #define FMT_DATA_BITS_6 0x01 | ||
116 | #define FMT_DATA_BITS_7 0x02 | ||
117 | #define FMT_DATA_BITS_8 0x03 | ||
118 | u8 something; /* always equals 0x43 */ | ||
119 | u8 control; /* settings of flow control lines */ | ||
120 | #define CONTROL_MASK 0x0c | ||
121 | #define CONTROL_DTR_HIGH 0x08 | ||
122 | #define CONTROL_RTS_HIGH 0x04 | ||
123 | u8 tx_status; | ||
124 | #define TX_BUFFER_EMPTIED 0x09 | ||
125 | u8 pin_state; | ||
126 | #define PIN_MASK 0x3f | ||
127 | #define PIN_RTS 0x20 /* output pin */ | ||
128 | #define PIN_CTS 0x10 /* input pin, active low */ | ||
129 | #define PIN_DSR 0x08 /* input pin, active low */ | ||
130 | #define PIN_DTR 0x04 /* output pin */ | ||
131 | #define PIN_RI 0x02 /* input pin, active low */ | ||
132 | #define PIN_DCD 0x01 /* input pin, active low */ | ||
133 | u8 rx_bytes_avail; /* number of bytes in rx buffer */; | ||
134 | }; | ||
135 | |||
136 | #define OTI6858_CTRL_PKT_SIZE sizeof(struct oti6858_control_pkt) | ||
137 | #define OTI6858_CTRL_EQUALS_PENDING(a, priv) \ | ||
138 | ( ((a)->divisor == (priv)->pending_setup.divisor) \ | ||
139 | && ((a)->control == (priv)->pending_setup.control) \ | ||
140 | && ((a)->frame_fmt == (priv)->pending_setup.frame_fmt) ) | ||
141 | |||
142 | /* function prototypes */ | ||
143 | static int oti6858_open(struct usb_serial_port *port, struct file *filp); | ||
144 | static void oti6858_close(struct usb_serial_port *port, struct file *filp); | ||
145 | static void oti6858_set_termios(struct usb_serial_port *port, | ||
146 | struct ktermios *old); | ||
147 | static int oti6858_ioctl(struct usb_serial_port *port, struct file *file, | ||
148 | unsigned int cmd, unsigned long arg); | ||
149 | static void oti6858_read_int_callback(struct urb *urb); | ||
150 | static void oti6858_read_bulk_callback(struct urb *urb); | ||
151 | static void oti6858_write_bulk_callback(struct urb *urb); | ||
152 | static int oti6858_write(struct usb_serial_port *port, | ||
153 | const unsigned char *buf, int count); | ||
154 | static int oti6858_write_room(struct usb_serial_port *port); | ||
155 | static void oti6858_break_ctl(struct usb_serial_port *port, int break_state); | ||
156 | static int oti6858_chars_in_buffer(struct usb_serial_port *port); | ||
157 | static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file); | ||
158 | static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file, | ||
159 | unsigned int set, unsigned int clear); | ||
160 | static int oti6858_startup(struct usb_serial *serial); | ||
161 | static void oti6858_shutdown(struct usb_serial *serial); | ||
162 | |||
163 | /* functions operating on buffers */ | ||
164 | static struct pl2303_buf *pl2303_buf_alloc(unsigned int size); | ||
165 | static void pl2303_buf_free(struct pl2303_buf *pb); | ||
166 | static void pl2303_buf_clear(struct pl2303_buf *pb); | ||
167 | static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb); | ||
168 | static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb); | ||
169 | static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf, | ||
170 | unsigned int count); | ||
171 | static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, | ||
172 | unsigned int count); | ||
173 | |||
174 | |||
175 | /* device info */ | ||
176 | static struct usb_serial_driver oti6858_device = { | ||
177 | .driver = { | ||
178 | .owner = THIS_MODULE, | ||
179 | .name = "oti6858", | ||
180 | }, | ||
181 | .id_table = id_table, | ||
182 | .num_interrupt_in = 1, | ||
183 | .num_bulk_in = 1, | ||
184 | .num_bulk_out = 1, | ||
185 | .num_ports = 1, | ||
186 | .open = oti6858_open, | ||
187 | .close = oti6858_close, | ||
188 | .write = oti6858_write, | ||
189 | .ioctl = oti6858_ioctl, | ||
190 | .break_ctl = oti6858_break_ctl, | ||
191 | .set_termios = oti6858_set_termios, | ||
192 | .tiocmget = oti6858_tiocmget, | ||
193 | .tiocmset = oti6858_tiocmset, | ||
194 | .read_bulk_callback = oti6858_read_bulk_callback, | ||
195 | .read_int_callback = oti6858_read_int_callback, | ||
196 | .write_bulk_callback = oti6858_write_bulk_callback, | ||
197 | .write_room = oti6858_write_room, | ||
198 | .chars_in_buffer = oti6858_chars_in_buffer, | ||
199 | .attach = oti6858_startup, | ||
200 | .shutdown = oti6858_shutdown, | ||
201 | }; | ||
202 | |||
203 | struct oti6858_private { | ||
204 | spinlock_t lock; | ||
205 | |||
206 | struct pl2303_buf *buf; | ||
207 | struct oti6858_control_pkt status; | ||
208 | |||
209 | struct { | ||
210 | u8 read_urb_in_use; | ||
211 | u8 write_urb_in_use; | ||
212 | u8 termios_initialized; | ||
213 | } flags; | ||
214 | struct delayed_work delayed_write_work; | ||
215 | |||
216 | struct { | ||
217 | u16 divisor; | ||
218 | u8 frame_fmt; | ||
219 | u8 control; | ||
220 | } pending_setup; | ||
221 | u8 transient; | ||
222 | u8 setup_done; | ||
223 | struct delayed_work delayed_setup_work; | ||
224 | |||
225 | wait_queue_head_t intr_wait; | ||
226 | struct usb_serial_port *port; /* USB port with which associated */ | ||
227 | }; | ||
228 | |||
229 | #undef dbg | ||
230 | /* #define dbg(format, arg...) printk(KERN_INFO "%s: " format "\n", __FILE__, ## arg) */ | ||
231 | #define dbg(format, arg...) printk(KERN_INFO "" format "\n", ## arg) | ||
232 | |||
233 | static void setup_line(struct work_struct *work) | ||
234 | { | ||
235 | struct oti6858_private *priv = container_of(work, struct oti6858_private, delayed_setup_work.work); | ||
236 | struct usb_serial_port *port = priv->port; | ||
237 | struct oti6858_control_pkt *new_setup; | ||
238 | unsigned long flags; | ||
239 | int result; | ||
240 | |||
241 | dbg("%s(port = %d)", __FUNCTION__, port->number); | ||
242 | |||
243 | if ((new_setup = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) { | ||
244 | dev_err(&port->dev, "%s(): out of memory!\n", __FUNCTION__); | ||
245 | /* we will try again */ | ||
246 | schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2)); | ||
247 | return; | ||
248 | } | ||
249 | |||
250 | result = usb_control_msg(port->serial->dev, | ||
251 | usb_rcvctrlpipe(port->serial->dev, 0), | ||
252 | OTI6858_REQ_T_GET_STATUS, | ||
253 | OTI6858_REQ_GET_STATUS, | ||
254 | 0, 0, | ||
255 | new_setup, OTI6858_CTRL_PKT_SIZE, | ||
256 | 100); | ||
257 | |||
258 | if (result != OTI6858_CTRL_PKT_SIZE) { | ||
259 | dev_err(&port->dev, "%s(): error reading status", __FUNCTION__); | ||
260 | kfree(new_setup); | ||
261 | /* we will try again */ | ||
262 | schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2)); | ||
263 | return; | ||
264 | } | ||
265 | |||
266 | spin_lock_irqsave(&priv->lock, flags); | ||
267 | if (!OTI6858_CTRL_EQUALS_PENDING(new_setup, priv)) { | ||
268 | new_setup->divisor = priv->pending_setup.divisor; | ||
269 | new_setup->control = priv->pending_setup.control; | ||
270 | new_setup->frame_fmt = priv->pending_setup.frame_fmt; | ||
271 | |||
272 | spin_unlock_irqrestore(&priv->lock, flags); | ||
273 | result = usb_control_msg(port->serial->dev, | ||
274 | usb_sndctrlpipe(port->serial->dev, 0), | ||
275 | OTI6858_REQ_T_SET_LINE, | ||
276 | OTI6858_REQ_SET_LINE, | ||
277 | 0, 0, | ||
278 | new_setup, OTI6858_CTRL_PKT_SIZE, | ||
279 | 100); | ||
280 | } else { | ||
281 | spin_unlock_irqrestore(&priv->lock, flags); | ||
282 | result = 0; | ||
283 | } | ||
284 | kfree(new_setup); | ||
285 | |||
286 | spin_lock_irqsave(&priv->lock, flags); | ||
287 | if (result != OTI6858_CTRL_PKT_SIZE) | ||
288 | priv->transient = 0; | ||
289 | priv->setup_done = 1; | ||
290 | spin_unlock_irqrestore(&priv->lock, flags); | ||
291 | |||
292 | dbg("%s(): submitting interrupt urb", __FUNCTION__); | ||
293 | port->interrupt_in_urb->dev = port->serial->dev; | ||
294 | result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); | ||
295 | if (result != 0) { | ||
296 | dev_err(&port->dev, "%s(): usb_submit_urb() failed" | ||
297 | " with error %d\n", __FUNCTION__, result); | ||
298 | } | ||
299 | } | ||
300 | |||
301 | void send_data(struct work_struct *work) | ||
302 | { | ||
303 | struct oti6858_private *priv = container_of(work, struct oti6858_private, delayed_write_work.work); | ||
304 | struct usb_serial_port *port = priv->port; | ||
305 | int count = 0, result; | ||
306 | unsigned long flags; | ||
307 | unsigned char allow; | ||
308 | |||
309 | dbg("%s(port = %d)", __FUNCTION__, port->number); | ||
310 | |||
311 | spin_lock_irqsave(&priv->lock, flags); | ||
312 | if (priv->flags.write_urb_in_use) { | ||
313 | spin_unlock_irqrestore(&priv->lock, flags); | ||
314 | schedule_delayed_work(&priv->delayed_write_work, msecs_to_jiffies(2)); | ||
315 | return; | ||
316 | } | ||
317 | priv->flags.write_urb_in_use = 1; | ||
318 | |||
319 | count = pl2303_buf_data_avail(priv->buf); | ||
320 | spin_unlock_irqrestore(&priv->lock, flags); | ||
321 | if (count > port->bulk_out_size) | ||
322 | count = port->bulk_out_size; | ||
323 | |||
324 | if (count != 0) { | ||
325 | result = usb_control_msg(port->serial->dev, | ||
326 | usb_rcvctrlpipe(port->serial->dev, 0), | ||
327 | OTI6858_REQ_T_CHECK_TXBUFF, | ||
328 | OTI6858_REQ_CHECK_TXBUFF, | ||
329 | count, 0, &allow, 1, 100); | ||
330 | if (result != 1 || allow != 0) | ||
331 | count = 0; | ||
332 | } | ||
333 | |||
334 | if (count == 0) { | ||
335 | priv->flags.write_urb_in_use = 0; | ||
336 | |||
337 | dbg("%s(): submitting interrupt urb", __FUNCTION__); | ||
338 | port->interrupt_in_urb->dev = port->serial->dev; | ||
339 | result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); | ||
340 | if (result != 0) { | ||
341 | dev_err(&port->dev, "%s(): usb_submit_urb() failed" | ||
342 | " with error %d\n", __FUNCTION__, result); | ||
343 | } | ||
344 | return; | ||
345 | } | ||
346 | |||
347 | spin_lock_irqsave(&priv->lock, flags); | ||
348 | pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer, count); | ||
349 | spin_unlock_irqrestore(&priv->lock, flags); | ||
350 | |||
351 | port->write_urb->transfer_buffer_length = count; | ||
352 | port->write_urb->dev = port->serial->dev; | ||
353 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | ||
354 | if (result != 0) { | ||
355 | dev_err(&port->dev, "%s(): usb_submit_urb() failed" | ||
356 | " with error %d\n", __FUNCTION__, result); | ||
357 | priv->flags.write_urb_in_use = 0; | ||
358 | } | ||
359 | |||
360 | usb_serial_port_softint(port); | ||
361 | } | ||
362 | |||
363 | static int oti6858_startup(struct usb_serial *serial) | ||
364 | { | ||
365 | struct usb_serial_port *port = serial->port[0]; | ||
366 | struct oti6858_private *priv; | ||
367 | int i; | ||
368 | |||
369 | for (i = 0; i < serial->num_ports; ++i) { | ||
370 | priv = kzalloc(sizeof(struct oti6858_private), GFP_KERNEL); | ||
371 | if (!priv) | ||
372 | break; | ||
373 | priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE); | ||
374 | if (priv->buf == NULL) { | ||
375 | kfree(priv); | ||
376 | break; | ||
377 | } | ||
378 | |||
379 | spin_lock_init(&priv->lock); | ||
380 | init_waitqueue_head(&priv->intr_wait); | ||
381 | // INIT_WORK(&priv->setup_work, setup_line, serial->port[i]); | ||
382 | // INIT_WORK(&priv->write_work, send_data, serial->port[i]); | ||
383 | priv->port = port; | ||
384 | INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line); | ||
385 | INIT_DELAYED_WORK(&priv->delayed_write_work, send_data); | ||
386 | |||
387 | usb_set_serial_port_data(serial->port[i], priv); | ||
388 | } | ||
389 | if (i == serial->num_ports) | ||
390 | return 0; | ||
391 | |||
392 | for (--i; i >= 0; --i) { | ||
393 | priv = usb_get_serial_port_data(serial->port[i]); | ||
394 | pl2303_buf_free(priv->buf); | ||
395 | kfree(priv); | ||
396 | usb_set_serial_port_data(serial->port[i], NULL); | ||
397 | } | ||
398 | return -ENOMEM; | ||
399 | } | ||
400 | |||
401 | static int oti6858_write(struct usb_serial_port *port, | ||
402 | const unsigned char *buf, int count) | ||
403 | { | ||
404 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
405 | unsigned long flags; | ||
406 | |||
407 | dbg("%s(port = %d, count = %d)", __FUNCTION__, port->number, count); | ||
408 | |||
409 | if (!count) | ||
410 | return count; | ||
411 | |||
412 | spin_lock_irqsave(&priv->lock, flags); | ||
413 | count = pl2303_buf_put(priv->buf, buf, count); | ||
414 | spin_unlock_irqrestore(&priv->lock, flags); | ||
415 | |||
416 | return count; | ||
417 | } | ||
418 | |||
419 | static int oti6858_write_room(struct usb_serial_port *port) | ||
420 | { | ||
421 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
422 | int room = 0; | ||
423 | unsigned long flags; | ||
424 | |||
425 | dbg("%s(port = %d)", __FUNCTION__, port->number); | ||
426 | |||
427 | spin_lock_irqsave(&priv->lock, flags); | ||
428 | room = pl2303_buf_space_avail(priv->buf); | ||
429 | spin_unlock_irqrestore(&priv->lock, flags); | ||
430 | |||
431 | return room; | ||
432 | } | ||
433 | |||
434 | static int oti6858_chars_in_buffer(struct usb_serial_port *port) | ||
435 | { | ||
436 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
437 | int chars = 0; | ||
438 | unsigned long flags; | ||
439 | |||
440 | dbg("%s(port = %d)", __FUNCTION__, port->number); | ||
441 | |||
442 | spin_lock_irqsave(&priv->lock, flags); | ||
443 | chars = pl2303_buf_data_avail(priv->buf); | ||
444 | spin_unlock_irqrestore(&priv->lock, flags); | ||
445 | |||
446 | return chars; | ||
447 | } | ||
448 | |||
449 | static void oti6858_set_termios(struct usb_serial_port *port, | ||
450 | struct ktermios *old_termios) | ||
451 | { | ||
452 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
453 | unsigned long flags; | ||
454 | unsigned int cflag; | ||
455 | u8 frame_fmt, control; | ||
456 | u16 divisor; | ||
457 | int br; | ||
458 | |||
459 | dbg("%s(port = %d)", __FUNCTION__, port->number); | ||
460 | |||
461 | if ((!port->tty) || (!port->tty->termios)) { | ||
462 | dbg("%s(): no tty structures", __FUNCTION__); | ||
463 | return; | ||
464 | } | ||
465 | |||
466 | spin_lock_irqsave(&priv->lock, flags); | ||
467 | if (!priv->flags.termios_initialized) { | ||
468 | *(port->tty->termios) = tty_std_termios; | ||
469 | port->tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL; | ||
470 | priv->flags.termios_initialized = 1; | ||
471 | } | ||
472 | spin_unlock_irqrestore(&priv->lock, flags); | ||
473 | |||
474 | cflag = port->tty->termios->c_cflag; | ||
475 | |||
476 | spin_lock_irqsave(&priv->lock, flags); | ||
477 | divisor = priv->pending_setup.divisor; | ||
478 | frame_fmt = priv->pending_setup.frame_fmt; | ||
479 | control = priv->pending_setup.control; | ||
480 | spin_unlock_irqrestore(&priv->lock, flags); | ||
481 | |||
482 | frame_fmt &= ~FMT_DATA_BITS_MASK; | ||
483 | switch (cflag & CSIZE) { | ||
484 | case CS5: | ||
485 | frame_fmt |= FMT_DATA_BITS_5; | ||
486 | break; | ||
487 | case CS6: | ||
488 | frame_fmt |= FMT_DATA_BITS_6; | ||
489 | break; | ||
490 | case CS7: | ||
491 | frame_fmt |= FMT_DATA_BITS_7; | ||
492 | break; | ||
493 | default: | ||
494 | case CS8: | ||
495 | frame_fmt |= FMT_DATA_BITS_8; | ||
496 | break; | ||
497 | } | ||
498 | |||
499 | /* manufacturer claims that this device can work with baud rates | ||
500 | * up to 3 Mbps; I've tested it only on 115200 bps, so I can't | ||
501 | * guarantee that any other baud rate will work (especially | ||
502 | * the higher ones) | ||
503 | */ | ||
504 | br = tty_get_baud_rate(port->tty); | ||
505 | if (br == 0) { | ||
506 | divisor = 0; | ||
507 | } else if (br <= OTI6858_MAX_BAUD_RATE) { | ||
508 | int real_br; | ||
509 | |||
510 | divisor = (96000000 + 8 * br) / (16 * br); | ||
511 | real_br = 96000000 / (16 * divisor); | ||
512 | if ((((real_br - br) * 100 + br - 1) / br) > 2) { | ||
513 | dbg("%s(): baud rate %d is invalid", __FUNCTION__, br); | ||
514 | return; | ||
515 | } | ||
516 | divisor = cpu_to_le16(divisor); | ||
517 | } else { | ||
518 | dbg("%s(): baud rate %d is too high", __FUNCTION__, br); | ||
519 | return; | ||
520 | } | ||
521 | |||
522 | frame_fmt &= ~FMT_STOP_BITS_MASK; | ||
523 | if ((cflag & CSTOPB) != 0) { | ||
524 | frame_fmt |= FMT_STOP_BITS_2; | ||
525 | } else { | ||
526 | frame_fmt |= FMT_STOP_BITS_1; | ||
527 | } | ||
528 | |||
529 | frame_fmt &= ~FMT_PARITY_MASK; | ||
530 | if ((cflag & PARENB) != 0) { | ||
531 | if ((cflag & PARODD) != 0) { | ||
532 | frame_fmt |= FMT_PARITY_ODD; | ||
533 | } else { | ||
534 | frame_fmt |= FMT_PARITY_EVEN; | ||
535 | } | ||
536 | } else { | ||
537 | frame_fmt |= FMT_PARITY_NONE; | ||
538 | } | ||
539 | |||
540 | control &= ~CONTROL_MASK; | ||
541 | if ((cflag & CRTSCTS) != 0) | ||
542 | control |= (CONTROL_DTR_HIGH | CONTROL_RTS_HIGH); | ||
543 | |||
544 | /* change control lines if we are switching to or from B0 */ | ||
545 | /* FIXME: | ||
546 | spin_lock_irqsave(&priv->lock, flags); | ||
547 | control = priv->line_control; | ||
548 | if ((cflag & CBAUD) == B0) | ||
549 | priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); | ||
550 | else | ||
551 | priv->line_control |= (CONTROL_DTR | CONTROL_RTS); | ||
552 | if (control != priv->line_control) { | ||
553 | control = priv->line_control; | ||
554 | spin_unlock_irqrestore(&priv->lock, flags); | ||
555 | set_control_lines(serial->dev, control); | ||
556 | } else { | ||
557 | spin_unlock_irqrestore(&priv->lock, flags); | ||
558 | } | ||
559 | */ | ||
560 | |||
561 | spin_lock_irqsave(&priv->lock, flags); | ||
562 | if (divisor != priv->pending_setup.divisor | ||
563 | || control != priv->pending_setup.control | ||
564 | || frame_fmt != priv->pending_setup.frame_fmt) { | ||
565 | priv->pending_setup.divisor = divisor; | ||
566 | priv->pending_setup.control = control; | ||
567 | priv->pending_setup.frame_fmt = frame_fmt; | ||
568 | } | ||
569 | spin_unlock_irqrestore(&priv->lock, flags); | ||
570 | } | ||
571 | |||
572 | static int oti6858_open(struct usb_serial_port *port, struct file *filp) | ||
573 | { | ||
574 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
575 | struct ktermios tmp_termios; | ||
576 | struct usb_serial *serial = port->serial; | ||
577 | struct oti6858_control_pkt *buf; | ||
578 | unsigned long flags; | ||
579 | int result; | ||
580 | |||
581 | dbg("%s(port = %d)", __FUNCTION__, port->number); | ||
582 | |||
583 | usb_clear_halt(serial->dev, port->write_urb->pipe); | ||
584 | usb_clear_halt(serial->dev, port->read_urb->pipe); | ||
585 | |||
586 | if (port->open_count != 1) | ||
587 | return 0; | ||
588 | |||
589 | if ((buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) { | ||
590 | dev_err(&port->dev, "%s(): out of memory!\n", __FUNCTION__); | ||
591 | return -ENOMEM; | ||
592 | } | ||
593 | |||
594 | result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | ||
595 | OTI6858_REQ_T_GET_STATUS, | ||
596 | OTI6858_REQ_GET_STATUS, | ||
597 | 0, 0, | ||
598 | buf, OTI6858_CTRL_PKT_SIZE, | ||
599 | 100); | ||
600 | if (result != OTI6858_CTRL_PKT_SIZE) { | ||
601 | /* assume default (after power-on reset) values */ | ||
602 | buf->divisor = cpu_to_le16(0x009c); /* 38400 bps */ | ||
603 | buf->frame_fmt = 0x03; /* 8N1 */ | ||
604 | buf->something = 0x43; | ||
605 | buf->control = 0x4c; /* DTR, RTS */ | ||
606 | buf->tx_status = 0x00; | ||
607 | buf->pin_state = 0x5b; /* RTS, CTS, DSR, DTR, RI, DCD */ | ||
608 | buf->rx_bytes_avail = 0x00; | ||
609 | } | ||
610 | |||
611 | spin_lock_irqsave(&priv->lock, flags); | ||
612 | memcpy(&priv->status, buf, OTI6858_CTRL_PKT_SIZE); | ||
613 | priv->pending_setup.divisor = buf->divisor; | ||
614 | priv->pending_setup.frame_fmt = buf->frame_fmt; | ||
615 | priv->pending_setup.control = buf->control; | ||
616 | spin_unlock_irqrestore(&priv->lock, flags); | ||
617 | kfree(buf); | ||
618 | |||
619 | dbg("%s(): submitting interrupt urb", __FUNCTION__); | ||
620 | port->interrupt_in_urb->dev = serial->dev; | ||
621 | result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); | ||
622 | if (result != 0) { | ||
623 | dev_err(&port->dev, "%s(): usb_submit_urb() failed" | ||
624 | " with error %d\n", __FUNCTION__, result); | ||
625 | oti6858_close(port, NULL); | ||
626 | return -EPROTO; | ||
627 | } | ||
628 | |||
629 | /* setup termios */ | ||
630 | if (port->tty) | ||
631 | oti6858_set_termios(port, &tmp_termios); | ||
632 | |||
633 | return 0; | ||
634 | } | ||
635 | |||
636 | static void oti6858_close(struct usb_serial_port *port, struct file *filp) | ||
637 | { | ||
638 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
639 | unsigned long flags; | ||
640 | long timeout; | ||
641 | wait_queue_t wait; | ||
642 | |||
643 | dbg("%s(port = %d)", __FUNCTION__, port->number); | ||
644 | |||
645 | /* wait for data to drain from the buffer */ | ||
646 | spin_lock_irqsave(&priv->lock, flags); | ||
647 | timeout = 30 * HZ; /* PL2303_CLOSING_WAIT */ | ||
648 | init_waitqueue_entry(&wait, current); | ||
649 | add_wait_queue(&port->tty->write_wait, &wait); | ||
650 | dbg("%s(): entering wait loop", __FUNCTION__); | ||
651 | for (;;) { | ||
652 | set_current_state(TASK_INTERRUPTIBLE); | ||
653 | if (pl2303_buf_data_avail(priv->buf) == 0 | ||
654 | || timeout == 0 || signal_pending(current) | ||
655 | || !usb_get_intfdata(port->serial->interface)) /* disconnect */ | ||
656 | break; | ||
657 | spin_unlock_irqrestore(&priv->lock, flags); | ||
658 | timeout = schedule_timeout(timeout); | ||
659 | spin_lock_irqsave(&priv->lock, flags); | ||
660 | } | ||
661 | set_current_state(TASK_RUNNING); | ||
662 | remove_wait_queue(&port->tty->write_wait, &wait); | ||
663 | dbg("%s(): after wait loop", __FUNCTION__); | ||
664 | |||
665 | /* clear out any remaining data in the buffer */ | ||
666 | pl2303_buf_clear(priv->buf); | ||
667 | spin_unlock_irqrestore(&priv->lock, flags); | ||
668 | |||
669 | /* wait for characters to drain from the device */ | ||
670 | /* (this is long enough for the entire 256 byte */ | ||
671 | /* pl2303 hardware buffer to drain with no flow */ | ||
672 | /* control for data rates of 1200 bps or more, */ | ||
673 | /* for lower rates we should really know how much */ | ||
674 | /* data is in the buffer to compute a delay */ | ||
675 | /* that is not unnecessarily long) */ | ||
676 | /* FIXME | ||
677 | bps = tty_get_baud_rate(port->tty); | ||
678 | if (bps > 1200) | ||
679 | timeout = max((HZ*2560)/bps,HZ/10); | ||
680 | else | ||
681 | */ | ||
682 | timeout = 2*HZ; | ||
683 | schedule_timeout_interruptible(timeout); | ||
684 | dbg("%s(): after schedule_timeout_interruptible()", __FUNCTION__); | ||
685 | |||
686 | /* cancel scheduled setup */ | ||
687 | cancel_delayed_work(&priv->delayed_setup_work); | ||
688 | cancel_delayed_work(&priv->delayed_write_work); | ||
689 | flush_scheduled_work(); | ||
690 | |||
691 | /* shutdown our urbs */ | ||
692 | dbg("%s(): shutting down urbs", __FUNCTION__); | ||
693 | usb_kill_urb(port->write_urb); | ||
694 | usb_kill_urb(port->read_urb); | ||
695 | usb_kill_urb(port->interrupt_in_urb); | ||
696 | |||
697 | /* | ||
698 | if (port->tty && (port->tty->termios->c_cflag) & HUPCL) { | ||
699 | // drop DTR and RTS | ||
700 | spin_lock_irqsave(&priv->lock, flags); | ||
701 | priv->pending_setup.control &= ~CONTROL_MASK; | ||
702 | spin_unlock_irqrestore(&priv->lock, flags); | ||
703 | } | ||
704 | */ | ||
705 | } | ||
706 | |||
707 | static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file, | ||
708 | unsigned int set, unsigned int clear) | ||
709 | { | ||
710 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
711 | unsigned long flags; | ||
712 | u8 control; | ||
713 | |||
714 | dbg("%s(port = %d, set = 0x%08x, clear = 0x%08x)", | ||
715 | __FUNCTION__, port->number, set, clear); | ||
716 | |||
717 | if (!usb_get_intfdata(port->serial->interface)) | ||
718 | return -ENODEV; | ||
719 | |||
720 | /* FIXME: check if this is correct (active high/low) */ | ||
721 | spin_lock_irqsave(&priv->lock, flags); | ||
722 | control = priv->pending_setup.control; | ||
723 | if ((set & TIOCM_RTS) != 0) | ||
724 | control |= CONTROL_RTS_HIGH; | ||
725 | if ((set & TIOCM_DTR) != 0) | ||
726 | control |= CONTROL_DTR_HIGH; | ||
727 | if ((clear & TIOCM_RTS) != 0) | ||
728 | control &= ~CONTROL_RTS_HIGH; | ||
729 | if ((clear & TIOCM_DTR) != 0) | ||
730 | control &= ~CONTROL_DTR_HIGH; | ||
731 | |||
732 | if (control != priv->pending_setup.control) { | ||
733 | priv->pending_setup.control = control; | ||
734 | } | ||
735 | spin_unlock_irqrestore(&priv->lock, flags); | ||
736 | |||
737 | return 0; | ||
738 | } | ||
739 | |||
740 | static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file) | ||
741 | { | ||
742 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
743 | unsigned long flags; | ||
744 | unsigned pin_state; | ||
745 | unsigned result = 0; | ||
746 | |||
747 | dbg("%s(port = %d)", __FUNCTION__, port->number); | ||
748 | |||
749 | if (!usb_get_intfdata(port->serial->interface)) | ||
750 | return -ENODEV; | ||
751 | |||
752 | spin_lock_irqsave(&priv->lock, flags); | ||
753 | pin_state = priv->status.pin_state & PIN_MASK; | ||
754 | spin_unlock_irqrestore(&priv->lock, flags); | ||
755 | |||
756 | /* FIXME: check if this is correct (active high/low) */ | ||
757 | if ((pin_state & PIN_RTS) != 0) | ||
758 | result |= TIOCM_RTS; | ||
759 | if ((pin_state & PIN_CTS) != 0) | ||
760 | result |= TIOCM_CTS; | ||
761 | if ((pin_state & PIN_DSR) != 0) | ||
762 | result |= TIOCM_DSR; | ||
763 | if ((pin_state & PIN_DTR) != 0) | ||
764 | result |= TIOCM_DTR; | ||
765 | if ((pin_state & PIN_RI) != 0) | ||
766 | result |= TIOCM_RI; | ||
767 | if ((pin_state & PIN_DCD) != 0) | ||
768 | result |= TIOCM_CD; | ||
769 | |||
770 | dbg("%s() = 0x%08x", __FUNCTION__, result); | ||
771 | |||
772 | return result; | ||
773 | } | ||
774 | |||
775 | static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) | ||
776 | { | ||
777 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
778 | unsigned long flags; | ||
779 | unsigned int prev, status; | ||
780 | unsigned int changed; | ||
781 | |||
782 | spin_lock_irqsave(&priv->lock, flags); | ||
783 | prev = priv->status.pin_state; | ||
784 | spin_unlock_irqrestore(&priv->lock, flags); | ||
785 | |||
786 | while (1) { | ||
787 | wait_event_interruptible(priv->intr_wait, priv->status.pin_state != prev); | ||
788 | if (signal_pending(current)) | ||
789 | return -ERESTARTSYS; | ||
790 | |||
791 | spin_lock_irqsave(&priv->lock, flags); | ||
792 | status = priv->status.pin_state & PIN_MASK; | ||
793 | spin_unlock_irqrestore(&priv->lock, flags); | ||
794 | |||
795 | changed = prev ^ status; | ||
796 | /* FIXME: check if this is correct (active high/low) */ | ||
797 | if ( ((arg & TIOCM_RNG) && (changed & PIN_RI)) || | ||
798 | ((arg & TIOCM_DSR) && (changed & PIN_DSR)) || | ||
799 | ((arg & TIOCM_CD) && (changed & PIN_DCD)) || | ||
800 | ((arg & TIOCM_CTS) && (changed & PIN_CTS))) { | ||
801 | return 0; | ||
802 | } | ||
803 | prev = status; | ||
804 | } | ||
805 | |||
806 | /* NOTREACHED */ | ||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | static int oti6858_ioctl(struct usb_serial_port *port, struct file *file, | ||
811 | unsigned int cmd, unsigned long arg) | ||
812 | { | ||
813 | void __user *user_arg = (void __user *) arg; | ||
814 | unsigned int x; | ||
815 | |||
816 | dbg("%s(port = %d, cmd = 0x%04x, arg = 0x%08lx)", | ||
817 | __FUNCTION__, port->number, cmd, arg); | ||
818 | |||
819 | switch (cmd) { | ||
820 | case TCGETS: | ||
821 | if (copy_to_user(user_arg, port->tty->termios, | ||
822 | sizeof(struct ktermios))) { | ||
823 | return -EFAULT; | ||
824 | } | ||
825 | return 0; | ||
826 | |||
827 | case TCSETS: | ||
828 | case TCSETSW: /* FIXME: this is not the same! */ | ||
829 | case TCSETSF: /* FIXME: this is not the same! */ | ||
830 | if (copy_from_user(port->tty->termios, user_arg, | ||
831 | sizeof(struct ktermios))) { | ||
832 | return -EFAULT; | ||
833 | } | ||
834 | oti6858_set_termios(port, NULL); | ||
835 | return 0; | ||
836 | |||
837 | case TCFLSH: | ||
838 | /* FIXME */ | ||
839 | return 0; | ||
840 | |||
841 | case TIOCMBIS: | ||
842 | if (copy_from_user(&x, user_arg, sizeof(x))) | ||
843 | return -EFAULT; | ||
844 | return oti6858_tiocmset(port, NULL, x, 0); | ||
845 | |||
846 | case TIOCMBIC: | ||
847 | if (copy_from_user(&x, user_arg, sizeof(x))) | ||
848 | return -EFAULT; | ||
849 | return oti6858_tiocmset(port, NULL, 0, x); | ||
850 | |||
851 | case TIOCGSERIAL: | ||
852 | if (copy_to_user(user_arg, port->tty->termios, | ||
853 | sizeof(struct ktermios))) { | ||
854 | return -EFAULT; | ||
855 | } | ||
856 | return 0; | ||
857 | |||
858 | case TIOCSSERIAL: | ||
859 | if (copy_from_user(port->tty->termios, user_arg, | ||
860 | sizeof(struct ktermios))) { | ||
861 | return -EFAULT; | ||
862 | } | ||
863 | oti6858_set_termios(port, NULL); | ||
864 | return 0; | ||
865 | |||
866 | case TIOCMIWAIT: | ||
867 | dbg("%s(): TIOCMIWAIT", __FUNCTION__); | ||
868 | return wait_modem_info(port, arg); | ||
869 | |||
870 | default: | ||
871 | dbg("%s(): 0x%04x not supported", __FUNCTION__, cmd); | ||
872 | break; | ||
873 | } | ||
874 | |||
875 | return -ENOIOCTLCMD; | ||
876 | } | ||
877 | |||
878 | static void oti6858_break_ctl(struct usb_serial_port *port, int break_state) | ||
879 | { | ||
880 | int state; | ||
881 | |||
882 | dbg("%s(port = %d)", __FUNCTION__, port->number); | ||
883 | |||
884 | state = (break_state == 0) ? 0 : 1; | ||
885 | dbg("%s(): turning break %s", __FUNCTION__, state ? "on" : "off"); | ||
886 | |||
887 | /* FIXME */ | ||
888 | /* | ||
889 | result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0), | ||
890 | BREAK_REQUEST, BREAK_REQUEST_TYPE, state, | ||
891 | 0, NULL, 0, 100); | ||
892 | if (result != 0) | ||
893 | dbg("%s(): error sending break", __FUNCTION__); | ||
894 | */ | ||
895 | } | ||
896 | |||
897 | static void oti6858_shutdown(struct usb_serial *serial) | ||
898 | { | ||
899 | struct oti6858_private *priv; | ||
900 | int i; | ||
901 | |||
902 | dbg("%s()", __FUNCTION__); | ||
903 | |||
904 | for (i = 0; i < serial->num_ports; ++i) { | ||
905 | priv = usb_get_serial_port_data(serial->port[i]); | ||
906 | if (priv) { | ||
907 | pl2303_buf_free(priv->buf); | ||
908 | kfree(priv); | ||
909 | usb_set_serial_port_data(serial->port[i], NULL); | ||
910 | } | ||
911 | } | ||
912 | } | ||
913 | |||
914 | static void oti6858_read_int_callback(struct urb *urb) | ||
915 | { | ||
916 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; | ||
917 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
918 | int transient = 0, can_recv = 0, resubmit = 1; | ||
919 | |||
920 | dbg("%s(port = %d, urb->status = %d)", | ||
921 | __FUNCTION__, port->number, urb->status); | ||
922 | |||
923 | switch (urb->status) { | ||
924 | case 0: | ||
925 | /* success */ | ||
926 | break; | ||
927 | case -ECONNRESET: | ||
928 | case -ENOENT: | ||
929 | case -ESHUTDOWN: | ||
930 | /* this urb is terminated, clean up */ | ||
931 | dbg("%s(): urb shutting down with status: %d", | ||
932 | __FUNCTION__, urb->status); | ||
933 | return; | ||
934 | default: | ||
935 | dbg("%s(): nonzero urb status received: %d", | ||
936 | __FUNCTION__, urb->status); | ||
937 | break; | ||
938 | } | ||
939 | |||
940 | if (urb->status == 0 && urb->actual_length == OTI6858_CTRL_PKT_SIZE) { | ||
941 | struct oti6858_control_pkt *xs = urb->transfer_buffer; | ||
942 | unsigned long flags; | ||
943 | |||
944 | spin_lock_irqsave(&priv->lock, flags); | ||
945 | |||
946 | if (!priv->transient) { | ||
947 | if (!OTI6858_CTRL_EQUALS_PENDING(xs, priv)) { | ||
948 | if (xs->rx_bytes_avail == 0) { | ||
949 | priv->transient = 4; | ||
950 | priv->setup_done = 0; | ||
951 | resubmit = 0; | ||
952 | dbg("%s(): scheduling setup_line()", | ||
953 | __FUNCTION__); | ||
954 | schedule_delayed_work(&priv->delayed_setup_work, 0); | ||
955 | } | ||
956 | } | ||
957 | } else { | ||
958 | if (OTI6858_CTRL_EQUALS_PENDING(xs, priv)) { | ||
959 | priv->transient = 0; | ||
960 | } else if (!priv->setup_done) { | ||
961 | resubmit = 0; | ||
962 | } else if (--priv->transient == 0) { | ||
963 | if (xs->rx_bytes_avail == 0) { | ||
964 | priv->transient = 4; | ||
965 | priv->setup_done = 0; | ||
966 | resubmit = 0; | ||
967 | dbg("%s(): scheduling setup_line()", | ||
968 | __FUNCTION__); | ||
969 | schedule_delayed_work(&priv->delayed_setup_work, 0); | ||
970 | } | ||
971 | } | ||
972 | } | ||
973 | |||
974 | if (!priv->transient) { | ||
975 | if (xs->pin_state != priv->status.pin_state) | ||
976 | wake_up_interruptible(&priv->intr_wait); | ||
977 | memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE); | ||
978 | } | ||
979 | |||
980 | if (!priv->transient && xs->rx_bytes_avail != 0) { | ||
981 | can_recv = xs->rx_bytes_avail; | ||
982 | priv->flags.read_urb_in_use = 1; | ||
983 | } | ||
984 | |||
985 | transient = priv->transient; | ||
986 | spin_unlock_irqrestore(&priv->lock, flags); | ||
987 | } | ||
988 | |||
989 | if (can_recv) { | ||
990 | int result; | ||
991 | |||
992 | port->read_urb->dev = port->serial->dev; | ||
993 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | ||
994 | if (result != 0) { | ||
995 | priv->flags.read_urb_in_use = 0; | ||
996 | dev_err(&port->dev, "%s(): usb_submit_urb() failed," | ||
997 | " error %d\n", __FUNCTION__, result); | ||
998 | } else { | ||
999 | resubmit = 0; | ||
1000 | } | ||
1001 | } else if (!transient) { | ||
1002 | unsigned long flags; | ||
1003 | |||
1004 | spin_lock_irqsave(&priv->lock, flags); | ||
1005 | if (priv->flags.write_urb_in_use == 0 | ||
1006 | && pl2303_buf_data_avail(priv->buf) != 0) { | ||
1007 | schedule_delayed_work(&priv->delayed_write_work,0); | ||
1008 | resubmit = 0; | ||
1009 | } | ||
1010 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1011 | } | ||
1012 | |||
1013 | if (resubmit) { | ||
1014 | int result; | ||
1015 | |||
1016 | // dbg("%s(): submitting interrupt urb", __FUNCTION__); | ||
1017 | urb->dev = port->serial->dev; | ||
1018 | result = usb_submit_urb(urb, GFP_ATOMIC); | ||
1019 | if (result != 0) { | ||
1020 | dev_err(&urb->dev->dev, | ||
1021 | "%s(): usb_submit_urb() failed with" | ||
1022 | " error %d\n", __FUNCTION__, result); | ||
1023 | } | ||
1024 | } | ||
1025 | } | ||
1026 | |||
1027 | static void oti6858_read_bulk_callback(struct urb *urb) | ||
1028 | { | ||
1029 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; | ||
1030 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
1031 | struct tty_struct *tty; | ||
1032 | unsigned char *data = urb->transfer_buffer; | ||
1033 | unsigned long flags; | ||
1034 | int i, result; | ||
1035 | char tty_flag; | ||
1036 | |||
1037 | dbg("%s(port = %d, urb->status = %d)", | ||
1038 | __FUNCTION__, port->number, urb->status); | ||
1039 | |||
1040 | spin_lock_irqsave(&priv->lock, flags); | ||
1041 | priv->flags.read_urb_in_use = 0; | ||
1042 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1043 | |||
1044 | if (urb->status != 0) { | ||
1045 | if (!port->open_count) { | ||
1046 | dbg("%s(): port is closed, exiting", __FUNCTION__); | ||
1047 | return; | ||
1048 | } | ||
1049 | /* | ||
1050 | if (urb->status == -EPROTO) { | ||
1051 | // PL2303 mysteriously fails with -EPROTO reschedule the read | ||
1052 | dbg("%s - caught -EPROTO, resubmitting the urb", __FUNCTION__); | ||
1053 | urb->status = 0; | ||
1054 | urb->dev = port->serial->dev; | ||
1055 | result = usb_submit_urb(urb, GFP_ATOMIC); | ||
1056 | if (result) | ||
1057 | dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); | ||
1058 | return; | ||
1059 | } | ||
1060 | */ | ||
1061 | dbg("%s(): unable to handle the error, exiting", __FUNCTION__); | ||
1062 | return; | ||
1063 | } | ||
1064 | |||
1065 | // get tty_flag from status | ||
1066 | tty_flag = TTY_NORMAL; | ||
1067 | |||
1068 | /* FIXME: probably, errors will be signalled using interrupt pipe! */ | ||
1069 | /* | ||
1070 | // break takes precedence over parity, | ||
1071 | // which takes precedence over framing errors | ||
1072 | if (status & UART_BREAK_ERROR ) | ||
1073 | tty_flag = TTY_BREAK; | ||
1074 | else if (status & UART_PARITY_ERROR) | ||
1075 | tty_flag = TTY_PARITY; | ||
1076 | else if (status & UART_FRAME_ERROR) | ||
1077 | tty_flag = TTY_FRAME; | ||
1078 | dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag); | ||
1079 | */ | ||
1080 | |||
1081 | tty = port->tty; | ||
1082 | if (tty != NULL && urb->actual_length > 0) { | ||
1083 | tty_buffer_request_room(tty, urb->actual_length); | ||
1084 | for (i = 0; i < urb->actual_length; ++i) | ||
1085 | tty_insert_flip_char(tty, data[i], tty_flag); | ||
1086 | tty_flip_buffer_push(tty); | ||
1087 | } | ||
1088 | |||
1089 | // schedule the interrupt urb if we are still open */ | ||
1090 | if (port->open_count != 0) { | ||
1091 | port->interrupt_in_urb->dev = port->serial->dev; | ||
1092 | result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); | ||
1093 | if (result != 0) { | ||
1094 | dev_err(&port->dev, "%s(): usb_submit_urb() failed," | ||
1095 | " error %d\n", __FUNCTION__, result); | ||
1096 | } | ||
1097 | } | ||
1098 | } | ||
1099 | |||
1100 | static void oti6858_write_bulk_callback(struct urb *urb) | ||
1101 | { | ||
1102 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; | ||
1103 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
1104 | int result; | ||
1105 | |||
1106 | dbg("%s(port = %d, urb->status = %d)", | ||
1107 | __FUNCTION__, port->number, urb->status); | ||
1108 | |||
1109 | switch (urb->status) { | ||
1110 | case 0: | ||
1111 | /* success */ | ||
1112 | break; | ||
1113 | case -ECONNRESET: | ||
1114 | case -ENOENT: | ||
1115 | case -ESHUTDOWN: | ||
1116 | /* this urb is terminated, clean up */ | ||
1117 | dbg("%s(): urb shutting down with status: %d", | ||
1118 | __FUNCTION__, urb->status); | ||
1119 | priv->flags.write_urb_in_use = 0; | ||
1120 | return; | ||
1121 | default: | ||
1122 | /* error in the urb, so we have to resubmit it */ | ||
1123 | dbg("%s(): nonzero write bulk status received: %d", | ||
1124 | __FUNCTION__, urb->status); | ||
1125 | dbg("%s(): overflow in write", __FUNCTION__); | ||
1126 | |||
1127 | port->write_urb->transfer_buffer_length = 1; | ||
1128 | port->write_urb->dev = port->serial->dev; | ||
1129 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | ||
1130 | if (result) { | ||
1131 | dev_err(&port->dev, "%s(): usb_submit_urb() failed," | ||
1132 | " error %d\n", __FUNCTION__, result); | ||
1133 | } else { | ||
1134 | return; | ||
1135 | } | ||
1136 | } | ||
1137 | |||
1138 | priv->flags.write_urb_in_use = 0; | ||
1139 | |||
1140 | // schedule the interrupt urb if we are still open */ | ||
1141 | port->interrupt_in_urb->dev = port->serial->dev; | ||
1142 | dbg("%s(): submitting interrupt urb", __FUNCTION__); | ||
1143 | result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); | ||
1144 | if (result != 0) { | ||
1145 | dev_err(&port->dev, "%s(): failed submitting int urb," | ||
1146 | " error %d\n", __FUNCTION__, result); | ||
1147 | } | ||
1148 | } | ||
1149 | |||
1150 | |||
1151 | /* | ||
1152 | * pl2303_buf_alloc | ||
1153 | * | ||
1154 | * Allocate a circular buffer and all associated memory. | ||
1155 | */ | ||
1156 | static struct pl2303_buf *pl2303_buf_alloc(unsigned int size) | ||
1157 | { | ||
1158 | struct pl2303_buf *pb; | ||
1159 | |||
1160 | if (size == 0) | ||
1161 | return NULL; | ||
1162 | |||
1163 | pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL); | ||
1164 | if (pb == NULL) | ||
1165 | return NULL; | ||
1166 | |||
1167 | pb->buf_buf = kmalloc(size, GFP_KERNEL); | ||
1168 | if (pb->buf_buf == NULL) { | ||
1169 | kfree(pb); | ||
1170 | return NULL; | ||
1171 | } | ||
1172 | |||
1173 | pb->buf_size = size; | ||
1174 | pb->buf_get = pb->buf_put = pb->buf_buf; | ||
1175 | |||
1176 | return pb; | ||
1177 | } | ||
1178 | |||
1179 | /* | ||
1180 | * pl2303_buf_free | ||
1181 | * | ||
1182 | * Free the buffer and all associated memory. | ||
1183 | */ | ||
1184 | static void pl2303_buf_free(struct pl2303_buf *pb) | ||
1185 | { | ||
1186 | if (pb) { | ||
1187 | kfree(pb->buf_buf); | ||
1188 | kfree(pb); | ||
1189 | } | ||
1190 | } | ||
1191 | |||
1192 | /* | ||
1193 | * pl2303_buf_clear | ||
1194 | * | ||
1195 | * Clear out all data in the circular buffer. | ||
1196 | */ | ||
1197 | static void pl2303_buf_clear(struct pl2303_buf *pb) | ||
1198 | { | ||
1199 | if (pb != NULL) { | ||
1200 | /* equivalent to a get of all data available */ | ||
1201 | pb->buf_get = pb->buf_put; | ||
1202 | } | ||
1203 | } | ||
1204 | |||
1205 | /* | ||
1206 | * pl2303_buf_data_avail | ||
1207 | * | ||
1208 | * Return the number of bytes of data available in the circular | ||
1209 | * buffer. | ||
1210 | */ | ||
1211 | static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb) | ||
1212 | { | ||
1213 | if (pb == NULL) | ||
1214 | return 0; | ||
1215 | return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size); | ||
1216 | } | ||
1217 | |||
1218 | /* | ||
1219 | * pl2303_buf_space_avail | ||
1220 | * | ||
1221 | * Return the number of bytes of space available in the circular | ||
1222 | * buffer. | ||
1223 | */ | ||
1224 | static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb) | ||
1225 | { | ||
1226 | if (pb == NULL) | ||
1227 | return 0; | ||
1228 | return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size); | ||
1229 | } | ||
1230 | |||
1231 | /* | ||
1232 | * pl2303_buf_put | ||
1233 | * | ||
1234 | * Copy data data from a user buffer and put it into the circular buffer. | ||
1235 | * Restrict to the amount of space available. | ||
1236 | * | ||
1237 | * Return the number of bytes copied. | ||
1238 | */ | ||
1239 | static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf, | ||
1240 | unsigned int count) | ||
1241 | { | ||
1242 | unsigned int len; | ||
1243 | |||
1244 | if (pb == NULL) | ||
1245 | return 0; | ||
1246 | |||
1247 | len = pl2303_buf_space_avail(pb); | ||
1248 | if (count > len) | ||
1249 | count = len; | ||
1250 | |||
1251 | if (count == 0) | ||
1252 | return 0; | ||
1253 | |||
1254 | len = pb->buf_buf + pb->buf_size - pb->buf_put; | ||
1255 | if (count > len) { | ||
1256 | memcpy(pb->buf_put, buf, len); | ||
1257 | memcpy(pb->buf_buf, buf+len, count - len); | ||
1258 | pb->buf_put = pb->buf_buf + count - len; | ||
1259 | } else { | ||
1260 | memcpy(pb->buf_put, buf, count); | ||
1261 | if (count < len) | ||
1262 | pb->buf_put += count; | ||
1263 | else /* count == len */ | ||
1264 | pb->buf_put = pb->buf_buf; | ||
1265 | } | ||
1266 | |||
1267 | return count; | ||
1268 | } | ||
1269 | |||
1270 | /* | ||
1271 | * pl2303_buf_get | ||
1272 | * | ||
1273 | * Get data from the circular buffer and copy to the given buffer. | ||
1274 | * Restrict to the amount of data available. | ||
1275 | * | ||
1276 | * Return the number of bytes copied. | ||
1277 | */ | ||
1278 | static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, | ||
1279 | unsigned int count) | ||
1280 | { | ||
1281 | unsigned int len; | ||
1282 | |||
1283 | if (pb == NULL) | ||
1284 | return 0; | ||
1285 | |||
1286 | len = pl2303_buf_data_avail(pb); | ||
1287 | if (count > len) | ||
1288 | count = len; | ||
1289 | |||
1290 | if (count == 0) | ||
1291 | return 0; | ||
1292 | |||
1293 | len = pb->buf_buf + pb->buf_size - pb->buf_get; | ||
1294 | if (count > len) { | ||
1295 | memcpy(buf, pb->buf_get, len); | ||
1296 | memcpy(buf+len, pb->buf_buf, count - len); | ||
1297 | pb->buf_get = pb->buf_buf + count - len; | ||
1298 | } else { | ||
1299 | memcpy(buf, pb->buf_get, count); | ||
1300 | if (count < len) | ||
1301 | pb->buf_get += count; | ||
1302 | else /* count == len */ | ||
1303 | pb->buf_get = pb->buf_buf; | ||
1304 | } | ||
1305 | |||
1306 | return count; | ||
1307 | } | ||
1308 | |||
1309 | /* module description and (de)initialization */ | ||
1310 | |||
1311 | static int __init oti6858_init(void) | ||
1312 | { | ||
1313 | int retval; | ||
1314 | |||
1315 | if ((retval = usb_serial_register(&oti6858_device)) == 0) { | ||
1316 | if ((retval = usb_register(&oti6858_driver)) != 0) | ||
1317 | usb_serial_deregister(&oti6858_device); | ||
1318 | else | ||
1319 | return 0; | ||
1320 | } | ||
1321 | |||
1322 | return retval; | ||
1323 | } | ||
1324 | |||
1325 | static void __exit oti6858_exit(void) | ||
1326 | { | ||
1327 | usb_deregister(&oti6858_driver); | ||
1328 | usb_serial_deregister(&oti6858_device); | ||
1329 | } | ||
1330 | |||
1331 | module_init(oti6858_init); | ||
1332 | module_exit(oti6858_exit); | ||
1333 | |||
1334 | MODULE_DESCRIPTION(OTI6858_DESCRIPTION); | ||
1335 | MODULE_AUTHOR(OTI6858_AUTHOR); | ||
1336 | MODULE_VERSION(OTI6858_VERSION); | ||
1337 | MODULE_LICENSE("GPL"); | ||
1338 | |||
1339 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
1340 | MODULE_PARM_DESC(debug, "enable debug output"); | ||
1341 | |||
diff --git a/drivers/usb/serial/oti6858.h b/drivers/usb/serial/oti6858.h new file mode 100644 index 000000000000..704ac3a532b3 --- /dev/null +++ b/drivers/usb/serial/oti6858.h | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * Ours Technology Inc. OTi-6858 USB to serial adapter driver. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | */ | ||
9 | #ifndef __LINUX_USB_SERIAL_OTI6858_H | ||
10 | #define __LINUX_USB_SERIAL_OTI6858_H | ||
11 | |||
12 | #define OTI6858_VENDOR_ID 0x0ea0 | ||
13 | #define OTI6858_PRODUCT_ID 0x6858 | ||
14 | |||
15 | #endif | ||