1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Digi AccelePort USB-4 and USB-2 Serial Converters
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright 2000 by Digi International
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Shamelessly based on Brian Warner's keyspan_pda.c and Greg Kroah-Hartman's
8*4882a593Smuzhiyun * usb-serial driver.
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * Peter Berger (pberger@brimson.com)
11*4882a593Smuzhiyun * Al Borchers (borchers@steinerpoint.com)
12*4882a593Smuzhiyun */
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include <linux/kernel.h>
15*4882a593Smuzhiyun #include <linux/errno.h>
16*4882a593Smuzhiyun #include <linux/slab.h>
17*4882a593Smuzhiyun #include <linux/tty.h>
18*4882a593Smuzhiyun #include <linux/tty_driver.h>
19*4882a593Smuzhiyun #include <linux/tty_flip.h>
20*4882a593Smuzhiyun #include <linux/module.h>
21*4882a593Smuzhiyun #include <linux/spinlock.h>
22*4882a593Smuzhiyun #include <linux/uaccess.h>
23*4882a593Smuzhiyun #include <linux/usb.h>
24*4882a593Smuzhiyun #include <linux/wait.h>
25*4882a593Smuzhiyun #include <linux/sched/signal.h>
26*4882a593Smuzhiyun #include <linux/usb/serial.h>
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /* Defines */
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #define DRIVER_AUTHOR "Peter Berger <pberger@brimson.com>, Al Borchers <borchers@steinerpoint.com>"
31*4882a593Smuzhiyun #define DRIVER_DESC "Digi AccelePort USB-2/USB-4 Serial Converter driver"
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun /* port output buffer length -- must be <= transfer buffer length - 2 */
34*4882a593Smuzhiyun /* so we can be sure to send the full buffer in one urb */
35*4882a593Smuzhiyun #define DIGI_OUT_BUF_SIZE 8
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun /* port input buffer length -- must be >= transfer buffer length - 3 */
38*4882a593Smuzhiyun /* so we can be sure to hold at least one full buffer from one urb */
39*4882a593Smuzhiyun #define DIGI_IN_BUF_SIZE 64
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun /* retry timeout while sleeping */
42*4882a593Smuzhiyun #define DIGI_RETRY_TIMEOUT (HZ/10)
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun /* timeout while waiting for tty output to drain in close */
45*4882a593Smuzhiyun /* this delay is used twice in close, so the total delay could */
46*4882a593Smuzhiyun /* be twice this value */
47*4882a593Smuzhiyun #define DIGI_CLOSE_TIMEOUT (5*HZ)
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun /* AccelePort USB Defines */
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun /* ids */
53*4882a593Smuzhiyun #define DIGI_VENDOR_ID 0x05c5
54*4882a593Smuzhiyun #define DIGI_2_ID 0x0002 /* USB-2 */
55*4882a593Smuzhiyun #define DIGI_4_ID 0x0004 /* USB-4 */
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun /* commands
58*4882a593Smuzhiyun * "INB": can be used on the in-band endpoint
59*4882a593Smuzhiyun * "OOB": can be used on the out-of-band endpoint
60*4882a593Smuzhiyun */
61*4882a593Smuzhiyun #define DIGI_CMD_SET_BAUD_RATE 0 /* INB, OOB */
62*4882a593Smuzhiyun #define DIGI_CMD_SET_WORD_SIZE 1 /* INB, OOB */
63*4882a593Smuzhiyun #define DIGI_CMD_SET_PARITY 2 /* INB, OOB */
64*4882a593Smuzhiyun #define DIGI_CMD_SET_STOP_BITS 3 /* INB, OOB */
65*4882a593Smuzhiyun #define DIGI_CMD_SET_INPUT_FLOW_CONTROL 4 /* INB, OOB */
66*4882a593Smuzhiyun #define DIGI_CMD_SET_OUTPUT_FLOW_CONTROL 5 /* INB, OOB */
67*4882a593Smuzhiyun #define DIGI_CMD_SET_DTR_SIGNAL 6 /* INB, OOB */
68*4882a593Smuzhiyun #define DIGI_CMD_SET_RTS_SIGNAL 7 /* INB, OOB */
69*4882a593Smuzhiyun #define DIGI_CMD_READ_INPUT_SIGNALS 8 /* OOB */
70*4882a593Smuzhiyun #define DIGI_CMD_IFLUSH_FIFO 9 /* OOB */
71*4882a593Smuzhiyun #define DIGI_CMD_RECEIVE_ENABLE 10 /* INB, OOB */
72*4882a593Smuzhiyun #define DIGI_CMD_BREAK_CONTROL 11 /* INB, OOB */
73*4882a593Smuzhiyun #define DIGI_CMD_LOCAL_LOOPBACK 12 /* INB, OOB */
74*4882a593Smuzhiyun #define DIGI_CMD_TRANSMIT_IDLE 13 /* INB, OOB */
75*4882a593Smuzhiyun #define DIGI_CMD_READ_UART_REGISTER 14 /* OOB */
76*4882a593Smuzhiyun #define DIGI_CMD_WRITE_UART_REGISTER 15 /* INB, OOB */
77*4882a593Smuzhiyun #define DIGI_CMD_AND_UART_REGISTER 16 /* INB, OOB */
78*4882a593Smuzhiyun #define DIGI_CMD_OR_UART_REGISTER 17 /* INB, OOB */
79*4882a593Smuzhiyun #define DIGI_CMD_SEND_DATA 18 /* INB */
80*4882a593Smuzhiyun #define DIGI_CMD_RECEIVE_DATA 19 /* INB */
81*4882a593Smuzhiyun #define DIGI_CMD_RECEIVE_DISABLE 20 /* INB */
82*4882a593Smuzhiyun #define DIGI_CMD_GET_PORT_TYPE 21 /* OOB */
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun /* baud rates */
85*4882a593Smuzhiyun #define DIGI_BAUD_50 0
86*4882a593Smuzhiyun #define DIGI_BAUD_75 1
87*4882a593Smuzhiyun #define DIGI_BAUD_110 2
88*4882a593Smuzhiyun #define DIGI_BAUD_150 3
89*4882a593Smuzhiyun #define DIGI_BAUD_200 4
90*4882a593Smuzhiyun #define DIGI_BAUD_300 5
91*4882a593Smuzhiyun #define DIGI_BAUD_600 6
92*4882a593Smuzhiyun #define DIGI_BAUD_1200 7
93*4882a593Smuzhiyun #define DIGI_BAUD_1800 8
94*4882a593Smuzhiyun #define DIGI_BAUD_2400 9
95*4882a593Smuzhiyun #define DIGI_BAUD_4800 10
96*4882a593Smuzhiyun #define DIGI_BAUD_7200 11
97*4882a593Smuzhiyun #define DIGI_BAUD_9600 12
98*4882a593Smuzhiyun #define DIGI_BAUD_14400 13
99*4882a593Smuzhiyun #define DIGI_BAUD_19200 14
100*4882a593Smuzhiyun #define DIGI_BAUD_28800 15
101*4882a593Smuzhiyun #define DIGI_BAUD_38400 16
102*4882a593Smuzhiyun #define DIGI_BAUD_57600 17
103*4882a593Smuzhiyun #define DIGI_BAUD_76800 18
104*4882a593Smuzhiyun #define DIGI_BAUD_115200 19
105*4882a593Smuzhiyun #define DIGI_BAUD_153600 20
106*4882a593Smuzhiyun #define DIGI_BAUD_230400 21
107*4882a593Smuzhiyun #define DIGI_BAUD_460800 22
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun /* arguments */
110*4882a593Smuzhiyun #define DIGI_WORD_SIZE_5 0
111*4882a593Smuzhiyun #define DIGI_WORD_SIZE_6 1
112*4882a593Smuzhiyun #define DIGI_WORD_SIZE_7 2
113*4882a593Smuzhiyun #define DIGI_WORD_SIZE_8 3
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun #define DIGI_PARITY_NONE 0
116*4882a593Smuzhiyun #define DIGI_PARITY_ODD 1
117*4882a593Smuzhiyun #define DIGI_PARITY_EVEN 2
118*4882a593Smuzhiyun #define DIGI_PARITY_MARK 3
119*4882a593Smuzhiyun #define DIGI_PARITY_SPACE 4
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun #define DIGI_STOP_BITS_1 0
122*4882a593Smuzhiyun #define DIGI_STOP_BITS_2 1
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun #define DIGI_INPUT_FLOW_CONTROL_XON_XOFF 1
125*4882a593Smuzhiyun #define DIGI_INPUT_FLOW_CONTROL_RTS 2
126*4882a593Smuzhiyun #define DIGI_INPUT_FLOW_CONTROL_DTR 4
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun #define DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF 1
129*4882a593Smuzhiyun #define DIGI_OUTPUT_FLOW_CONTROL_CTS 2
130*4882a593Smuzhiyun #define DIGI_OUTPUT_FLOW_CONTROL_DSR 4
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun #define DIGI_DTR_INACTIVE 0
133*4882a593Smuzhiyun #define DIGI_DTR_ACTIVE 1
134*4882a593Smuzhiyun #define DIGI_DTR_INPUT_FLOW_CONTROL 2
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun #define DIGI_RTS_INACTIVE 0
137*4882a593Smuzhiyun #define DIGI_RTS_ACTIVE 1
138*4882a593Smuzhiyun #define DIGI_RTS_INPUT_FLOW_CONTROL 2
139*4882a593Smuzhiyun #define DIGI_RTS_TOGGLE 3
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun #define DIGI_FLUSH_TX 1
142*4882a593Smuzhiyun #define DIGI_FLUSH_RX 2
143*4882a593Smuzhiyun #define DIGI_RESUME_TX 4 /* clears xoff condition */
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun #define DIGI_TRANSMIT_NOT_IDLE 0
146*4882a593Smuzhiyun #define DIGI_TRANSMIT_IDLE 1
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun #define DIGI_DISABLE 0
149*4882a593Smuzhiyun #define DIGI_ENABLE 1
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun #define DIGI_DEASSERT 0
152*4882a593Smuzhiyun #define DIGI_ASSERT 1
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun /* in band status codes */
155*4882a593Smuzhiyun #define DIGI_OVERRUN_ERROR 4
156*4882a593Smuzhiyun #define DIGI_PARITY_ERROR 8
157*4882a593Smuzhiyun #define DIGI_FRAMING_ERROR 16
158*4882a593Smuzhiyun #define DIGI_BREAK_ERROR 32
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun /* out of band status */
161*4882a593Smuzhiyun #define DIGI_NO_ERROR 0
162*4882a593Smuzhiyun #define DIGI_BAD_FIRST_PARAMETER 1
163*4882a593Smuzhiyun #define DIGI_BAD_SECOND_PARAMETER 2
164*4882a593Smuzhiyun #define DIGI_INVALID_LINE 3
165*4882a593Smuzhiyun #define DIGI_INVALID_OPCODE 4
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun /* input signals */
168*4882a593Smuzhiyun #define DIGI_READ_INPUT_SIGNALS_SLOT 1
169*4882a593Smuzhiyun #define DIGI_READ_INPUT_SIGNALS_ERR 2
170*4882a593Smuzhiyun #define DIGI_READ_INPUT_SIGNALS_BUSY 4
171*4882a593Smuzhiyun #define DIGI_READ_INPUT_SIGNALS_PE 8
172*4882a593Smuzhiyun #define DIGI_READ_INPUT_SIGNALS_CTS 16
173*4882a593Smuzhiyun #define DIGI_READ_INPUT_SIGNALS_DSR 32
174*4882a593Smuzhiyun #define DIGI_READ_INPUT_SIGNALS_RI 64
175*4882a593Smuzhiyun #define DIGI_READ_INPUT_SIGNALS_DCD 128
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun /* Structures */
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun struct digi_serial {
181*4882a593Smuzhiyun spinlock_t ds_serial_lock;
182*4882a593Smuzhiyun struct usb_serial_port *ds_oob_port; /* out-of-band port */
183*4882a593Smuzhiyun int ds_oob_port_num; /* index of out-of-band port */
184*4882a593Smuzhiyun int ds_device_started;
185*4882a593Smuzhiyun };
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun struct digi_port {
188*4882a593Smuzhiyun spinlock_t dp_port_lock;
189*4882a593Smuzhiyun int dp_port_num;
190*4882a593Smuzhiyun int dp_out_buf_len;
191*4882a593Smuzhiyun unsigned char dp_out_buf[DIGI_OUT_BUF_SIZE];
192*4882a593Smuzhiyun int dp_write_urb_in_use;
193*4882a593Smuzhiyun unsigned int dp_modem_signals;
194*4882a593Smuzhiyun int dp_transmit_idle;
195*4882a593Smuzhiyun wait_queue_head_t dp_transmit_idle_wait;
196*4882a593Smuzhiyun int dp_throttled;
197*4882a593Smuzhiyun int dp_throttle_restart;
198*4882a593Smuzhiyun wait_queue_head_t dp_flush_wait;
199*4882a593Smuzhiyun wait_queue_head_t dp_close_wait; /* wait queue for close */
200*4882a593Smuzhiyun struct usb_serial_port *dp_port;
201*4882a593Smuzhiyun };
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun /* Local Function Declarations */
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun static int digi_write_oob_command(struct usb_serial_port *port,
207*4882a593Smuzhiyun unsigned char *buf, int count, int interruptible);
208*4882a593Smuzhiyun static int digi_write_inb_command(struct usb_serial_port *port,
209*4882a593Smuzhiyun unsigned char *buf, int count, unsigned long timeout);
210*4882a593Smuzhiyun static int digi_set_modem_signals(struct usb_serial_port *port,
211*4882a593Smuzhiyun unsigned int modem_signals, int interruptible);
212*4882a593Smuzhiyun static int digi_transmit_idle(struct usb_serial_port *port,
213*4882a593Smuzhiyun unsigned long timeout);
214*4882a593Smuzhiyun static void digi_rx_throttle(struct tty_struct *tty);
215*4882a593Smuzhiyun static void digi_rx_unthrottle(struct tty_struct *tty);
216*4882a593Smuzhiyun static void digi_set_termios(struct tty_struct *tty,
217*4882a593Smuzhiyun struct usb_serial_port *port, struct ktermios *old_termios);
218*4882a593Smuzhiyun static void digi_break_ctl(struct tty_struct *tty, int break_state);
219*4882a593Smuzhiyun static int digi_tiocmget(struct tty_struct *tty);
220*4882a593Smuzhiyun static int digi_tiocmset(struct tty_struct *tty, unsigned int set,
221*4882a593Smuzhiyun unsigned int clear);
222*4882a593Smuzhiyun static int digi_write(struct tty_struct *tty, struct usb_serial_port *port,
223*4882a593Smuzhiyun const unsigned char *buf, int count);
224*4882a593Smuzhiyun static void digi_write_bulk_callback(struct urb *urb);
225*4882a593Smuzhiyun static int digi_write_room(struct tty_struct *tty);
226*4882a593Smuzhiyun static int digi_chars_in_buffer(struct tty_struct *tty);
227*4882a593Smuzhiyun static int digi_open(struct tty_struct *tty, struct usb_serial_port *port);
228*4882a593Smuzhiyun static void digi_close(struct usb_serial_port *port);
229*4882a593Smuzhiyun static void digi_dtr_rts(struct usb_serial_port *port, int on);
230*4882a593Smuzhiyun static int digi_startup_device(struct usb_serial *serial);
231*4882a593Smuzhiyun static int digi_startup(struct usb_serial *serial);
232*4882a593Smuzhiyun static void digi_disconnect(struct usb_serial *serial);
233*4882a593Smuzhiyun static void digi_release(struct usb_serial *serial);
234*4882a593Smuzhiyun static int digi_port_probe(struct usb_serial_port *port);
235*4882a593Smuzhiyun static int digi_port_remove(struct usb_serial_port *port);
236*4882a593Smuzhiyun static void digi_read_bulk_callback(struct urb *urb);
237*4882a593Smuzhiyun static int digi_read_inb_callback(struct urb *urb);
238*4882a593Smuzhiyun static int digi_read_oob_callback(struct urb *urb);
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun static const struct usb_device_id id_table_combined[] = {
242*4882a593Smuzhiyun { USB_DEVICE(DIGI_VENDOR_ID, DIGI_2_ID) },
243*4882a593Smuzhiyun { USB_DEVICE(DIGI_VENDOR_ID, DIGI_4_ID) },
244*4882a593Smuzhiyun { } /* Terminating entry */
245*4882a593Smuzhiyun };
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun static const struct usb_device_id id_table_2[] = {
248*4882a593Smuzhiyun { USB_DEVICE(DIGI_VENDOR_ID, DIGI_2_ID) },
249*4882a593Smuzhiyun { } /* Terminating entry */
250*4882a593Smuzhiyun };
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun static const struct usb_device_id id_table_4[] = {
253*4882a593Smuzhiyun { USB_DEVICE(DIGI_VENDOR_ID, DIGI_4_ID) },
254*4882a593Smuzhiyun { } /* Terminating entry */
255*4882a593Smuzhiyun };
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun MODULE_DEVICE_TABLE(usb, id_table_combined);
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun /* device info needed for the Digi serial converter */
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun static struct usb_serial_driver digi_acceleport_2_device = {
262*4882a593Smuzhiyun .driver = {
263*4882a593Smuzhiyun .owner = THIS_MODULE,
264*4882a593Smuzhiyun .name = "digi_2",
265*4882a593Smuzhiyun },
266*4882a593Smuzhiyun .description = "Digi 2 port USB adapter",
267*4882a593Smuzhiyun .id_table = id_table_2,
268*4882a593Smuzhiyun .num_ports = 3,
269*4882a593Smuzhiyun .num_bulk_in = 4,
270*4882a593Smuzhiyun .num_bulk_out = 4,
271*4882a593Smuzhiyun .open = digi_open,
272*4882a593Smuzhiyun .close = digi_close,
273*4882a593Smuzhiyun .dtr_rts = digi_dtr_rts,
274*4882a593Smuzhiyun .write = digi_write,
275*4882a593Smuzhiyun .write_room = digi_write_room,
276*4882a593Smuzhiyun .write_bulk_callback = digi_write_bulk_callback,
277*4882a593Smuzhiyun .read_bulk_callback = digi_read_bulk_callback,
278*4882a593Smuzhiyun .chars_in_buffer = digi_chars_in_buffer,
279*4882a593Smuzhiyun .throttle = digi_rx_throttle,
280*4882a593Smuzhiyun .unthrottle = digi_rx_unthrottle,
281*4882a593Smuzhiyun .set_termios = digi_set_termios,
282*4882a593Smuzhiyun .break_ctl = digi_break_ctl,
283*4882a593Smuzhiyun .tiocmget = digi_tiocmget,
284*4882a593Smuzhiyun .tiocmset = digi_tiocmset,
285*4882a593Smuzhiyun .attach = digi_startup,
286*4882a593Smuzhiyun .disconnect = digi_disconnect,
287*4882a593Smuzhiyun .release = digi_release,
288*4882a593Smuzhiyun .port_probe = digi_port_probe,
289*4882a593Smuzhiyun .port_remove = digi_port_remove,
290*4882a593Smuzhiyun };
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun static struct usb_serial_driver digi_acceleport_4_device = {
293*4882a593Smuzhiyun .driver = {
294*4882a593Smuzhiyun .owner = THIS_MODULE,
295*4882a593Smuzhiyun .name = "digi_4",
296*4882a593Smuzhiyun },
297*4882a593Smuzhiyun .description = "Digi 4 port USB adapter",
298*4882a593Smuzhiyun .id_table = id_table_4,
299*4882a593Smuzhiyun .num_ports = 4,
300*4882a593Smuzhiyun .num_bulk_in = 5,
301*4882a593Smuzhiyun .num_bulk_out = 5,
302*4882a593Smuzhiyun .open = digi_open,
303*4882a593Smuzhiyun .close = digi_close,
304*4882a593Smuzhiyun .write = digi_write,
305*4882a593Smuzhiyun .write_room = digi_write_room,
306*4882a593Smuzhiyun .write_bulk_callback = digi_write_bulk_callback,
307*4882a593Smuzhiyun .read_bulk_callback = digi_read_bulk_callback,
308*4882a593Smuzhiyun .chars_in_buffer = digi_chars_in_buffer,
309*4882a593Smuzhiyun .throttle = digi_rx_throttle,
310*4882a593Smuzhiyun .unthrottle = digi_rx_unthrottle,
311*4882a593Smuzhiyun .set_termios = digi_set_termios,
312*4882a593Smuzhiyun .break_ctl = digi_break_ctl,
313*4882a593Smuzhiyun .tiocmget = digi_tiocmget,
314*4882a593Smuzhiyun .tiocmset = digi_tiocmset,
315*4882a593Smuzhiyun .attach = digi_startup,
316*4882a593Smuzhiyun .disconnect = digi_disconnect,
317*4882a593Smuzhiyun .release = digi_release,
318*4882a593Smuzhiyun .port_probe = digi_port_probe,
319*4882a593Smuzhiyun .port_remove = digi_port_remove,
320*4882a593Smuzhiyun };
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun static struct usb_serial_driver * const serial_drivers[] = {
323*4882a593Smuzhiyun &digi_acceleport_2_device, &digi_acceleport_4_device, NULL
324*4882a593Smuzhiyun };
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun /* Functions */
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun /*
329*4882a593Smuzhiyun * Cond Wait Interruptible Timeout Irqrestore
330*4882a593Smuzhiyun *
331*4882a593Smuzhiyun * Do spin_unlock_irqrestore and interruptible_sleep_on_timeout
332*4882a593Smuzhiyun * so that wake ups are not lost if they occur between the unlock
333*4882a593Smuzhiyun * and the sleep. In other words, spin_unlock_irqrestore and
334*4882a593Smuzhiyun * interruptible_sleep_on_timeout are "atomic" with respect to
335*4882a593Smuzhiyun * wake ups. This is used to implement condition variables.
336*4882a593Smuzhiyun *
337*4882a593Smuzhiyun * interruptible_sleep_on_timeout is deprecated and has been replaced
338*4882a593Smuzhiyun * with the equivalent code.
339*4882a593Smuzhiyun */
340*4882a593Smuzhiyun
cond_wait_interruptible_timeout_irqrestore(wait_queue_head_t * q,long timeout,spinlock_t * lock,unsigned long flags)341*4882a593Smuzhiyun static long cond_wait_interruptible_timeout_irqrestore(
342*4882a593Smuzhiyun wait_queue_head_t *q, long timeout,
343*4882a593Smuzhiyun spinlock_t *lock, unsigned long flags)
344*4882a593Smuzhiyun __releases(lock)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun DEFINE_WAIT(wait);
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun prepare_to_wait(q, &wait, TASK_INTERRUPTIBLE);
349*4882a593Smuzhiyun spin_unlock_irqrestore(lock, flags);
350*4882a593Smuzhiyun timeout = schedule_timeout(timeout);
351*4882a593Smuzhiyun finish_wait(q, &wait);
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun return timeout;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun /*
357*4882a593Smuzhiyun * Digi Write OOB Command
358*4882a593Smuzhiyun *
359*4882a593Smuzhiyun * Write commands on the out of band port. Commands are 4
360*4882a593Smuzhiyun * bytes each, multiple commands can be sent at once, and
361*4882a593Smuzhiyun * no command will be split across USB packets. Returns 0
362*4882a593Smuzhiyun * if successful, -EINTR if interrupted while sleeping and
363*4882a593Smuzhiyun * the interruptible flag is true, or a negative error
364*4882a593Smuzhiyun * returned by usb_submit_urb.
365*4882a593Smuzhiyun */
366*4882a593Smuzhiyun
digi_write_oob_command(struct usb_serial_port * port,unsigned char * buf,int count,int interruptible)367*4882a593Smuzhiyun static int digi_write_oob_command(struct usb_serial_port *port,
368*4882a593Smuzhiyun unsigned char *buf, int count, int interruptible)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun int ret = 0;
371*4882a593Smuzhiyun int len;
372*4882a593Smuzhiyun struct usb_serial_port *oob_port = (struct usb_serial_port *)((struct digi_serial *)(usb_get_serial_data(port->serial)))->ds_oob_port;
373*4882a593Smuzhiyun struct digi_port *oob_priv = usb_get_serial_port_data(oob_port);
374*4882a593Smuzhiyun unsigned long flags = 0;
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun dev_dbg(&port->dev,
377*4882a593Smuzhiyun "digi_write_oob_command: TOP: port=%d, count=%d\n",
378*4882a593Smuzhiyun oob_priv->dp_port_num, count);
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
381*4882a593Smuzhiyun while (count > 0) {
382*4882a593Smuzhiyun while (oob_priv->dp_write_urb_in_use) {
383*4882a593Smuzhiyun cond_wait_interruptible_timeout_irqrestore(
384*4882a593Smuzhiyun &oob_port->write_wait, DIGI_RETRY_TIMEOUT,
385*4882a593Smuzhiyun &oob_priv->dp_port_lock, flags);
386*4882a593Smuzhiyun if (interruptible && signal_pending(current))
387*4882a593Smuzhiyun return -EINTR;
388*4882a593Smuzhiyun spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun /* len must be a multiple of 4, so commands are not split */
392*4882a593Smuzhiyun len = min(count, oob_port->bulk_out_size);
393*4882a593Smuzhiyun if (len > 4)
394*4882a593Smuzhiyun len &= ~3;
395*4882a593Smuzhiyun memcpy(oob_port->write_urb->transfer_buffer, buf, len);
396*4882a593Smuzhiyun oob_port->write_urb->transfer_buffer_length = len;
397*4882a593Smuzhiyun ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC);
398*4882a593Smuzhiyun if (ret == 0) {
399*4882a593Smuzhiyun oob_priv->dp_write_urb_in_use = 1;
400*4882a593Smuzhiyun count -= len;
401*4882a593Smuzhiyun buf += len;
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags);
405*4882a593Smuzhiyun if (ret)
406*4882a593Smuzhiyun dev_err(&port->dev, "%s: usb_submit_urb failed, ret=%d\n",
407*4882a593Smuzhiyun __func__, ret);
408*4882a593Smuzhiyun return ret;
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun /*
414*4882a593Smuzhiyun * Digi Write In Band Command
415*4882a593Smuzhiyun *
416*4882a593Smuzhiyun * Write commands on the given port. Commands are 4
417*4882a593Smuzhiyun * bytes each, multiple commands can be sent at once, and
418*4882a593Smuzhiyun * no command will be split across USB packets. If timeout
419*4882a593Smuzhiyun * is non-zero, write in band command will return after
420*4882a593Smuzhiyun * waiting unsuccessfully for the URB status to clear for
421*4882a593Smuzhiyun * timeout ticks. Returns 0 if successful, or a negative
422*4882a593Smuzhiyun * error returned by digi_write.
423*4882a593Smuzhiyun */
424*4882a593Smuzhiyun
digi_write_inb_command(struct usb_serial_port * port,unsigned char * buf,int count,unsigned long timeout)425*4882a593Smuzhiyun static int digi_write_inb_command(struct usb_serial_port *port,
426*4882a593Smuzhiyun unsigned char *buf, int count, unsigned long timeout)
427*4882a593Smuzhiyun {
428*4882a593Smuzhiyun int ret = 0;
429*4882a593Smuzhiyun int len;
430*4882a593Smuzhiyun struct digi_port *priv = usb_get_serial_port_data(port);
431*4882a593Smuzhiyun unsigned char *data = port->write_urb->transfer_buffer;
432*4882a593Smuzhiyun unsigned long flags = 0;
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun dev_dbg(&port->dev, "digi_write_inb_command: TOP: port=%d, count=%d\n",
435*4882a593Smuzhiyun priv->dp_port_num, count);
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun if (timeout)
438*4882a593Smuzhiyun timeout += jiffies;
439*4882a593Smuzhiyun else
440*4882a593Smuzhiyun timeout = ULONG_MAX;
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun spin_lock_irqsave(&priv->dp_port_lock, flags);
443*4882a593Smuzhiyun while (count > 0 && ret == 0) {
444*4882a593Smuzhiyun while (priv->dp_write_urb_in_use &&
445*4882a593Smuzhiyun time_before(jiffies, timeout)) {
446*4882a593Smuzhiyun cond_wait_interruptible_timeout_irqrestore(
447*4882a593Smuzhiyun &port->write_wait, DIGI_RETRY_TIMEOUT,
448*4882a593Smuzhiyun &priv->dp_port_lock, flags);
449*4882a593Smuzhiyun if (signal_pending(current))
450*4882a593Smuzhiyun return -EINTR;
451*4882a593Smuzhiyun spin_lock_irqsave(&priv->dp_port_lock, flags);
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun /* len must be a multiple of 4 and small enough to */
455*4882a593Smuzhiyun /* guarantee the write will send buffered data first, */
456*4882a593Smuzhiyun /* so commands are in order with data and not split */
457*4882a593Smuzhiyun len = min(count, port->bulk_out_size-2-priv->dp_out_buf_len);
458*4882a593Smuzhiyun if (len > 4)
459*4882a593Smuzhiyun len &= ~3;
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun /* write any buffered data first */
462*4882a593Smuzhiyun if (priv->dp_out_buf_len > 0) {
463*4882a593Smuzhiyun data[0] = DIGI_CMD_SEND_DATA;
464*4882a593Smuzhiyun data[1] = priv->dp_out_buf_len;
465*4882a593Smuzhiyun memcpy(data + 2, priv->dp_out_buf,
466*4882a593Smuzhiyun priv->dp_out_buf_len);
467*4882a593Smuzhiyun memcpy(data + 2 + priv->dp_out_buf_len, buf, len);
468*4882a593Smuzhiyun port->write_urb->transfer_buffer_length
469*4882a593Smuzhiyun = priv->dp_out_buf_len + 2 + len;
470*4882a593Smuzhiyun } else {
471*4882a593Smuzhiyun memcpy(data, buf, len);
472*4882a593Smuzhiyun port->write_urb->transfer_buffer_length = len;
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
476*4882a593Smuzhiyun if (ret == 0) {
477*4882a593Smuzhiyun priv->dp_write_urb_in_use = 1;
478*4882a593Smuzhiyun priv->dp_out_buf_len = 0;
479*4882a593Smuzhiyun count -= len;
480*4882a593Smuzhiyun buf += len;
481*4882a593Smuzhiyun }
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->dp_port_lock, flags);
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun if (ret)
487*4882a593Smuzhiyun dev_err(&port->dev,
488*4882a593Smuzhiyun "%s: usb_submit_urb failed, ret=%d, port=%d\n",
489*4882a593Smuzhiyun __func__, ret, priv->dp_port_num);
490*4882a593Smuzhiyun return ret;
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun /*
495*4882a593Smuzhiyun * Digi Set Modem Signals
496*4882a593Smuzhiyun *
497*4882a593Smuzhiyun * Sets or clears DTR and RTS on the port, according to the
498*4882a593Smuzhiyun * modem_signals argument. Use TIOCM_DTR and TIOCM_RTS flags
499*4882a593Smuzhiyun * for the modem_signals argument. Returns 0 if successful,
500*4882a593Smuzhiyun * -EINTR if interrupted while sleeping, or a non-zero error
501*4882a593Smuzhiyun * returned by usb_submit_urb.
502*4882a593Smuzhiyun */
503*4882a593Smuzhiyun
digi_set_modem_signals(struct usb_serial_port * port,unsigned int modem_signals,int interruptible)504*4882a593Smuzhiyun static int digi_set_modem_signals(struct usb_serial_port *port,
505*4882a593Smuzhiyun unsigned int modem_signals, int interruptible)
506*4882a593Smuzhiyun {
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun int ret;
509*4882a593Smuzhiyun struct digi_port *port_priv = usb_get_serial_port_data(port);
510*4882a593Smuzhiyun struct usb_serial_port *oob_port = (struct usb_serial_port *) ((struct digi_serial *)(usb_get_serial_data(port->serial)))->ds_oob_port;
511*4882a593Smuzhiyun struct digi_port *oob_priv = usb_get_serial_port_data(oob_port);
512*4882a593Smuzhiyun unsigned char *data = oob_port->write_urb->transfer_buffer;
513*4882a593Smuzhiyun unsigned long flags = 0;
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun dev_dbg(&port->dev,
517*4882a593Smuzhiyun "digi_set_modem_signals: TOP: port=%d, modem_signals=0x%x\n",
518*4882a593Smuzhiyun port_priv->dp_port_num, modem_signals);
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
521*4882a593Smuzhiyun spin_lock(&port_priv->dp_port_lock);
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun while (oob_priv->dp_write_urb_in_use) {
524*4882a593Smuzhiyun spin_unlock(&port_priv->dp_port_lock);
525*4882a593Smuzhiyun cond_wait_interruptible_timeout_irqrestore(
526*4882a593Smuzhiyun &oob_port->write_wait, DIGI_RETRY_TIMEOUT,
527*4882a593Smuzhiyun &oob_priv->dp_port_lock, flags);
528*4882a593Smuzhiyun if (interruptible && signal_pending(current))
529*4882a593Smuzhiyun return -EINTR;
530*4882a593Smuzhiyun spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
531*4882a593Smuzhiyun spin_lock(&port_priv->dp_port_lock);
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun data[0] = DIGI_CMD_SET_DTR_SIGNAL;
534*4882a593Smuzhiyun data[1] = port_priv->dp_port_num;
535*4882a593Smuzhiyun data[2] = (modem_signals & TIOCM_DTR) ?
536*4882a593Smuzhiyun DIGI_DTR_ACTIVE : DIGI_DTR_INACTIVE;
537*4882a593Smuzhiyun data[3] = 0;
538*4882a593Smuzhiyun data[4] = DIGI_CMD_SET_RTS_SIGNAL;
539*4882a593Smuzhiyun data[5] = port_priv->dp_port_num;
540*4882a593Smuzhiyun data[6] = (modem_signals & TIOCM_RTS) ?
541*4882a593Smuzhiyun DIGI_RTS_ACTIVE : DIGI_RTS_INACTIVE;
542*4882a593Smuzhiyun data[7] = 0;
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun oob_port->write_urb->transfer_buffer_length = 8;
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC);
547*4882a593Smuzhiyun if (ret == 0) {
548*4882a593Smuzhiyun oob_priv->dp_write_urb_in_use = 1;
549*4882a593Smuzhiyun port_priv->dp_modem_signals &= ~(TIOCM_DTR | TIOCM_RTS);
550*4882a593Smuzhiyun port_priv->dp_modem_signals |=
551*4882a593Smuzhiyun modem_signals & (TIOCM_DTR | TIOCM_RTS);
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun spin_unlock(&port_priv->dp_port_lock);
554*4882a593Smuzhiyun spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags);
555*4882a593Smuzhiyun if (ret)
556*4882a593Smuzhiyun dev_err(&port->dev, "%s: usb_submit_urb failed, ret=%d\n",
557*4882a593Smuzhiyun __func__, ret);
558*4882a593Smuzhiyun return ret;
559*4882a593Smuzhiyun }
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun /*
562*4882a593Smuzhiyun * Digi Transmit Idle
563*4882a593Smuzhiyun *
564*4882a593Smuzhiyun * Digi transmit idle waits, up to timeout ticks, for the transmitter
565*4882a593Smuzhiyun * to go idle. It returns 0 if successful or a negative error.
566*4882a593Smuzhiyun *
567*4882a593Smuzhiyun * There are race conditions here if more than one process is calling
568*4882a593Smuzhiyun * digi_transmit_idle on the same port at the same time. However, this
569*4882a593Smuzhiyun * is only called from close, and only one process can be in close on a
570*4882a593Smuzhiyun * port at a time, so its ok.
571*4882a593Smuzhiyun */
572*4882a593Smuzhiyun
digi_transmit_idle(struct usb_serial_port * port,unsigned long timeout)573*4882a593Smuzhiyun static int digi_transmit_idle(struct usb_serial_port *port,
574*4882a593Smuzhiyun unsigned long timeout)
575*4882a593Smuzhiyun {
576*4882a593Smuzhiyun int ret;
577*4882a593Smuzhiyun unsigned char buf[2];
578*4882a593Smuzhiyun struct digi_port *priv = usb_get_serial_port_data(port);
579*4882a593Smuzhiyun unsigned long flags = 0;
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun spin_lock_irqsave(&priv->dp_port_lock, flags);
582*4882a593Smuzhiyun priv->dp_transmit_idle = 0;
583*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->dp_port_lock, flags);
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun buf[0] = DIGI_CMD_TRANSMIT_IDLE;
586*4882a593Smuzhiyun buf[1] = 0;
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun timeout += jiffies;
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun ret = digi_write_inb_command(port, buf, 2, timeout - jiffies);
591*4882a593Smuzhiyun if (ret != 0)
592*4882a593Smuzhiyun return ret;
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun spin_lock_irqsave(&priv->dp_port_lock, flags);
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun while (time_before(jiffies, timeout) && !priv->dp_transmit_idle) {
597*4882a593Smuzhiyun cond_wait_interruptible_timeout_irqrestore(
598*4882a593Smuzhiyun &priv->dp_transmit_idle_wait, DIGI_RETRY_TIMEOUT,
599*4882a593Smuzhiyun &priv->dp_port_lock, flags);
600*4882a593Smuzhiyun if (signal_pending(current))
601*4882a593Smuzhiyun return -EINTR;
602*4882a593Smuzhiyun spin_lock_irqsave(&priv->dp_port_lock, flags);
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun priv->dp_transmit_idle = 0;
605*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->dp_port_lock, flags);
606*4882a593Smuzhiyun return 0;
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun }
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun
digi_rx_throttle(struct tty_struct * tty)611*4882a593Smuzhiyun static void digi_rx_throttle(struct tty_struct *tty)
612*4882a593Smuzhiyun {
613*4882a593Smuzhiyun unsigned long flags;
614*4882a593Smuzhiyun struct usb_serial_port *port = tty->driver_data;
615*4882a593Smuzhiyun struct digi_port *priv = usb_get_serial_port_data(port);
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun /* stop receiving characters by not resubmitting the read urb */
618*4882a593Smuzhiyun spin_lock_irqsave(&priv->dp_port_lock, flags);
619*4882a593Smuzhiyun priv->dp_throttled = 1;
620*4882a593Smuzhiyun priv->dp_throttle_restart = 0;
621*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->dp_port_lock, flags);
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun
digi_rx_unthrottle(struct tty_struct * tty)625*4882a593Smuzhiyun static void digi_rx_unthrottle(struct tty_struct *tty)
626*4882a593Smuzhiyun {
627*4882a593Smuzhiyun int ret = 0;
628*4882a593Smuzhiyun unsigned long flags;
629*4882a593Smuzhiyun struct usb_serial_port *port = tty->driver_data;
630*4882a593Smuzhiyun struct digi_port *priv = usb_get_serial_port_data(port);
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun spin_lock_irqsave(&priv->dp_port_lock, flags);
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun /* restart read chain */
635*4882a593Smuzhiyun if (priv->dp_throttle_restart)
636*4882a593Smuzhiyun ret = usb_submit_urb(port->read_urb, GFP_ATOMIC);
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun /* turn throttle off */
639*4882a593Smuzhiyun priv->dp_throttled = 0;
640*4882a593Smuzhiyun priv->dp_throttle_restart = 0;
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->dp_port_lock, flags);
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun if (ret)
645*4882a593Smuzhiyun dev_err(&port->dev,
646*4882a593Smuzhiyun "%s: usb_submit_urb failed, ret=%d, port=%d\n",
647*4882a593Smuzhiyun __func__, ret, priv->dp_port_num);
648*4882a593Smuzhiyun }
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun
digi_set_termios(struct tty_struct * tty,struct usb_serial_port * port,struct ktermios * old_termios)651*4882a593Smuzhiyun static void digi_set_termios(struct tty_struct *tty,
652*4882a593Smuzhiyun struct usb_serial_port *port, struct ktermios *old_termios)
653*4882a593Smuzhiyun {
654*4882a593Smuzhiyun struct digi_port *priv = usb_get_serial_port_data(port);
655*4882a593Smuzhiyun struct device *dev = &port->dev;
656*4882a593Smuzhiyun unsigned int iflag = tty->termios.c_iflag;
657*4882a593Smuzhiyun unsigned int cflag = tty->termios.c_cflag;
658*4882a593Smuzhiyun unsigned int old_iflag = old_termios->c_iflag;
659*4882a593Smuzhiyun unsigned int old_cflag = old_termios->c_cflag;
660*4882a593Smuzhiyun unsigned char buf[32];
661*4882a593Smuzhiyun unsigned int modem_signals;
662*4882a593Smuzhiyun int arg, ret;
663*4882a593Smuzhiyun int i = 0;
664*4882a593Smuzhiyun speed_t baud;
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun dev_dbg(dev,
667*4882a593Smuzhiyun "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, old_cflag=0x%x\n",
668*4882a593Smuzhiyun priv->dp_port_num, iflag, old_iflag, cflag, old_cflag);
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun /* set baud rate */
671*4882a593Smuzhiyun baud = tty_get_baud_rate(tty);
672*4882a593Smuzhiyun if (baud != tty_termios_baud_rate(old_termios)) {
673*4882a593Smuzhiyun arg = -1;
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun /* reassert DTR and (maybe) RTS on transition from B0 */
676*4882a593Smuzhiyun if ((old_cflag & CBAUD) == B0) {
677*4882a593Smuzhiyun /* don't set RTS if using hardware flow control */
678*4882a593Smuzhiyun /* and throttling input */
679*4882a593Smuzhiyun modem_signals = TIOCM_DTR;
680*4882a593Smuzhiyun if (!C_CRTSCTS(tty) || !tty_throttled(tty))
681*4882a593Smuzhiyun modem_signals |= TIOCM_RTS;
682*4882a593Smuzhiyun digi_set_modem_signals(port, modem_signals, 1);
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun switch (baud) {
685*4882a593Smuzhiyun /* drop DTR and RTS on transition to B0 */
686*4882a593Smuzhiyun case 0: digi_set_modem_signals(port, 0, 1); break;
687*4882a593Smuzhiyun case 50: arg = DIGI_BAUD_50; break;
688*4882a593Smuzhiyun case 75: arg = DIGI_BAUD_75; break;
689*4882a593Smuzhiyun case 110: arg = DIGI_BAUD_110; break;
690*4882a593Smuzhiyun case 150: arg = DIGI_BAUD_150; break;
691*4882a593Smuzhiyun case 200: arg = DIGI_BAUD_200; break;
692*4882a593Smuzhiyun case 300: arg = DIGI_BAUD_300; break;
693*4882a593Smuzhiyun case 600: arg = DIGI_BAUD_600; break;
694*4882a593Smuzhiyun case 1200: arg = DIGI_BAUD_1200; break;
695*4882a593Smuzhiyun case 1800: arg = DIGI_BAUD_1800; break;
696*4882a593Smuzhiyun case 2400: arg = DIGI_BAUD_2400; break;
697*4882a593Smuzhiyun case 4800: arg = DIGI_BAUD_4800; break;
698*4882a593Smuzhiyun case 9600: arg = DIGI_BAUD_9600; break;
699*4882a593Smuzhiyun case 19200: arg = DIGI_BAUD_19200; break;
700*4882a593Smuzhiyun case 38400: arg = DIGI_BAUD_38400; break;
701*4882a593Smuzhiyun case 57600: arg = DIGI_BAUD_57600; break;
702*4882a593Smuzhiyun case 115200: arg = DIGI_BAUD_115200; break;
703*4882a593Smuzhiyun case 230400: arg = DIGI_BAUD_230400; break;
704*4882a593Smuzhiyun case 460800: arg = DIGI_BAUD_460800; break;
705*4882a593Smuzhiyun default:
706*4882a593Smuzhiyun arg = DIGI_BAUD_9600;
707*4882a593Smuzhiyun baud = 9600;
708*4882a593Smuzhiyun break;
709*4882a593Smuzhiyun }
710*4882a593Smuzhiyun if (arg != -1) {
711*4882a593Smuzhiyun buf[i++] = DIGI_CMD_SET_BAUD_RATE;
712*4882a593Smuzhiyun buf[i++] = priv->dp_port_num;
713*4882a593Smuzhiyun buf[i++] = arg;
714*4882a593Smuzhiyun buf[i++] = 0;
715*4882a593Smuzhiyun }
716*4882a593Smuzhiyun }
717*4882a593Smuzhiyun /* set parity */
718*4882a593Smuzhiyun tty->termios.c_cflag &= ~CMSPAR;
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun if ((cflag & (PARENB | PARODD)) != (old_cflag & (PARENB | PARODD))) {
721*4882a593Smuzhiyun if (cflag & PARENB) {
722*4882a593Smuzhiyun if (cflag & PARODD)
723*4882a593Smuzhiyun arg = DIGI_PARITY_ODD;
724*4882a593Smuzhiyun else
725*4882a593Smuzhiyun arg = DIGI_PARITY_EVEN;
726*4882a593Smuzhiyun } else {
727*4882a593Smuzhiyun arg = DIGI_PARITY_NONE;
728*4882a593Smuzhiyun }
729*4882a593Smuzhiyun buf[i++] = DIGI_CMD_SET_PARITY;
730*4882a593Smuzhiyun buf[i++] = priv->dp_port_num;
731*4882a593Smuzhiyun buf[i++] = arg;
732*4882a593Smuzhiyun buf[i++] = 0;
733*4882a593Smuzhiyun }
734*4882a593Smuzhiyun /* set word size */
735*4882a593Smuzhiyun if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
736*4882a593Smuzhiyun arg = -1;
737*4882a593Smuzhiyun switch (cflag & CSIZE) {
738*4882a593Smuzhiyun case CS5: arg = DIGI_WORD_SIZE_5; break;
739*4882a593Smuzhiyun case CS6: arg = DIGI_WORD_SIZE_6; break;
740*4882a593Smuzhiyun case CS7: arg = DIGI_WORD_SIZE_7; break;
741*4882a593Smuzhiyun case CS8: arg = DIGI_WORD_SIZE_8; break;
742*4882a593Smuzhiyun default:
743*4882a593Smuzhiyun dev_dbg(dev,
744*4882a593Smuzhiyun "digi_set_termios: can't handle word size %d\n",
745*4882a593Smuzhiyun cflag & CSIZE);
746*4882a593Smuzhiyun break;
747*4882a593Smuzhiyun }
748*4882a593Smuzhiyun
749*4882a593Smuzhiyun if (arg != -1) {
750*4882a593Smuzhiyun buf[i++] = DIGI_CMD_SET_WORD_SIZE;
751*4882a593Smuzhiyun buf[i++] = priv->dp_port_num;
752*4882a593Smuzhiyun buf[i++] = arg;
753*4882a593Smuzhiyun buf[i++] = 0;
754*4882a593Smuzhiyun }
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun }
757*4882a593Smuzhiyun
758*4882a593Smuzhiyun /* set stop bits */
759*4882a593Smuzhiyun if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) {
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun if ((cflag & CSTOPB))
762*4882a593Smuzhiyun arg = DIGI_STOP_BITS_2;
763*4882a593Smuzhiyun else
764*4882a593Smuzhiyun arg = DIGI_STOP_BITS_1;
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun buf[i++] = DIGI_CMD_SET_STOP_BITS;
767*4882a593Smuzhiyun buf[i++] = priv->dp_port_num;
768*4882a593Smuzhiyun buf[i++] = arg;
769*4882a593Smuzhiyun buf[i++] = 0;
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun }
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun /* set input flow control */
774*4882a593Smuzhiyun if ((iflag & IXOFF) != (old_iflag & IXOFF) ||
775*4882a593Smuzhiyun (cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
776*4882a593Smuzhiyun arg = 0;
777*4882a593Smuzhiyun if (iflag & IXOFF)
778*4882a593Smuzhiyun arg |= DIGI_INPUT_FLOW_CONTROL_XON_XOFF;
779*4882a593Smuzhiyun else
780*4882a593Smuzhiyun arg &= ~DIGI_INPUT_FLOW_CONTROL_XON_XOFF;
781*4882a593Smuzhiyun
782*4882a593Smuzhiyun if (cflag & CRTSCTS) {
783*4882a593Smuzhiyun arg |= DIGI_INPUT_FLOW_CONTROL_RTS;
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun /* On USB-4 it is necessary to assert RTS prior */
786*4882a593Smuzhiyun /* to selecting RTS input flow control. */
787*4882a593Smuzhiyun buf[i++] = DIGI_CMD_SET_RTS_SIGNAL;
788*4882a593Smuzhiyun buf[i++] = priv->dp_port_num;
789*4882a593Smuzhiyun buf[i++] = DIGI_RTS_ACTIVE;
790*4882a593Smuzhiyun buf[i++] = 0;
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun } else {
793*4882a593Smuzhiyun arg &= ~DIGI_INPUT_FLOW_CONTROL_RTS;
794*4882a593Smuzhiyun }
795*4882a593Smuzhiyun buf[i++] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
796*4882a593Smuzhiyun buf[i++] = priv->dp_port_num;
797*4882a593Smuzhiyun buf[i++] = arg;
798*4882a593Smuzhiyun buf[i++] = 0;
799*4882a593Smuzhiyun }
800*4882a593Smuzhiyun
801*4882a593Smuzhiyun /* set output flow control */
802*4882a593Smuzhiyun if ((iflag & IXON) != (old_iflag & IXON) ||
803*4882a593Smuzhiyun (cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
804*4882a593Smuzhiyun arg = 0;
805*4882a593Smuzhiyun if (iflag & IXON)
806*4882a593Smuzhiyun arg |= DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF;
807*4882a593Smuzhiyun else
808*4882a593Smuzhiyun arg &= ~DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF;
809*4882a593Smuzhiyun
810*4882a593Smuzhiyun if (cflag & CRTSCTS)
811*4882a593Smuzhiyun arg |= DIGI_OUTPUT_FLOW_CONTROL_CTS;
812*4882a593Smuzhiyun else
813*4882a593Smuzhiyun arg &= ~DIGI_OUTPUT_FLOW_CONTROL_CTS;
814*4882a593Smuzhiyun
815*4882a593Smuzhiyun buf[i++] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL;
816*4882a593Smuzhiyun buf[i++] = priv->dp_port_num;
817*4882a593Smuzhiyun buf[i++] = arg;
818*4882a593Smuzhiyun buf[i++] = 0;
819*4882a593Smuzhiyun }
820*4882a593Smuzhiyun
821*4882a593Smuzhiyun /* set receive enable/disable */
822*4882a593Smuzhiyun if ((cflag & CREAD) != (old_cflag & CREAD)) {
823*4882a593Smuzhiyun if (cflag & CREAD)
824*4882a593Smuzhiyun arg = DIGI_ENABLE;
825*4882a593Smuzhiyun else
826*4882a593Smuzhiyun arg = DIGI_DISABLE;
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun buf[i++] = DIGI_CMD_RECEIVE_ENABLE;
829*4882a593Smuzhiyun buf[i++] = priv->dp_port_num;
830*4882a593Smuzhiyun buf[i++] = arg;
831*4882a593Smuzhiyun buf[i++] = 0;
832*4882a593Smuzhiyun }
833*4882a593Smuzhiyun ret = digi_write_oob_command(port, buf, i, 1);
834*4882a593Smuzhiyun if (ret != 0)
835*4882a593Smuzhiyun dev_dbg(dev, "digi_set_termios: write oob failed, ret=%d\n", ret);
836*4882a593Smuzhiyun tty_encode_baud_rate(tty, baud, baud);
837*4882a593Smuzhiyun }
838*4882a593Smuzhiyun
839*4882a593Smuzhiyun
digi_break_ctl(struct tty_struct * tty,int break_state)840*4882a593Smuzhiyun static void digi_break_ctl(struct tty_struct *tty, int break_state)
841*4882a593Smuzhiyun {
842*4882a593Smuzhiyun struct usb_serial_port *port = tty->driver_data;
843*4882a593Smuzhiyun unsigned char buf[4];
844*4882a593Smuzhiyun
845*4882a593Smuzhiyun buf[0] = DIGI_CMD_BREAK_CONTROL;
846*4882a593Smuzhiyun buf[1] = 2; /* length */
847*4882a593Smuzhiyun buf[2] = break_state ? 1 : 0;
848*4882a593Smuzhiyun buf[3] = 0; /* pad */
849*4882a593Smuzhiyun digi_write_inb_command(port, buf, 4, 0);
850*4882a593Smuzhiyun }
851*4882a593Smuzhiyun
852*4882a593Smuzhiyun
digi_tiocmget(struct tty_struct * tty)853*4882a593Smuzhiyun static int digi_tiocmget(struct tty_struct *tty)
854*4882a593Smuzhiyun {
855*4882a593Smuzhiyun struct usb_serial_port *port = tty->driver_data;
856*4882a593Smuzhiyun struct digi_port *priv = usb_get_serial_port_data(port);
857*4882a593Smuzhiyun unsigned int val;
858*4882a593Smuzhiyun unsigned long flags;
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun spin_lock_irqsave(&priv->dp_port_lock, flags);
861*4882a593Smuzhiyun val = priv->dp_modem_signals;
862*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->dp_port_lock, flags);
863*4882a593Smuzhiyun return val;
864*4882a593Smuzhiyun }
865*4882a593Smuzhiyun
866*4882a593Smuzhiyun
digi_tiocmset(struct tty_struct * tty,unsigned int set,unsigned int clear)867*4882a593Smuzhiyun static int digi_tiocmset(struct tty_struct *tty,
868*4882a593Smuzhiyun unsigned int set, unsigned int clear)
869*4882a593Smuzhiyun {
870*4882a593Smuzhiyun struct usb_serial_port *port = tty->driver_data;
871*4882a593Smuzhiyun struct digi_port *priv = usb_get_serial_port_data(port);
872*4882a593Smuzhiyun unsigned int val;
873*4882a593Smuzhiyun unsigned long flags;
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun spin_lock_irqsave(&priv->dp_port_lock, flags);
876*4882a593Smuzhiyun val = (priv->dp_modem_signals & ~clear) | set;
877*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->dp_port_lock, flags);
878*4882a593Smuzhiyun return digi_set_modem_signals(port, val, 1);
879*4882a593Smuzhiyun }
880*4882a593Smuzhiyun
881*4882a593Smuzhiyun
digi_write(struct tty_struct * tty,struct usb_serial_port * port,const unsigned char * buf,int count)882*4882a593Smuzhiyun static int digi_write(struct tty_struct *tty, struct usb_serial_port *port,
883*4882a593Smuzhiyun const unsigned char *buf, int count)
884*4882a593Smuzhiyun {
885*4882a593Smuzhiyun
886*4882a593Smuzhiyun int ret, data_len, new_len;
887*4882a593Smuzhiyun struct digi_port *priv = usb_get_serial_port_data(port);
888*4882a593Smuzhiyun unsigned char *data = port->write_urb->transfer_buffer;
889*4882a593Smuzhiyun unsigned long flags = 0;
890*4882a593Smuzhiyun
891*4882a593Smuzhiyun dev_dbg(&port->dev,
892*4882a593Smuzhiyun "digi_write: TOP: port=%d, count=%d, in_interrupt=%ld\n",
893*4882a593Smuzhiyun priv->dp_port_num, count, in_interrupt());
894*4882a593Smuzhiyun
895*4882a593Smuzhiyun /* copy user data (which can sleep) before getting spin lock */
896*4882a593Smuzhiyun count = min(count, port->bulk_out_size-2);
897*4882a593Smuzhiyun count = min(64, count);
898*4882a593Smuzhiyun
899*4882a593Smuzhiyun /* be sure only one write proceeds at a time */
900*4882a593Smuzhiyun /* there are races on the port private buffer */
901*4882a593Smuzhiyun spin_lock_irqsave(&priv->dp_port_lock, flags);
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun /* wait for urb status clear to submit another urb */
904*4882a593Smuzhiyun if (priv->dp_write_urb_in_use) {
905*4882a593Smuzhiyun /* buffer data if count is 1 (probably put_char) if possible */
906*4882a593Smuzhiyun if (count == 1 && priv->dp_out_buf_len < DIGI_OUT_BUF_SIZE) {
907*4882a593Smuzhiyun priv->dp_out_buf[priv->dp_out_buf_len++] = *buf;
908*4882a593Smuzhiyun new_len = 1;
909*4882a593Smuzhiyun } else {
910*4882a593Smuzhiyun new_len = 0;
911*4882a593Smuzhiyun }
912*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->dp_port_lock, flags);
913*4882a593Smuzhiyun return new_len;
914*4882a593Smuzhiyun }
915*4882a593Smuzhiyun
916*4882a593Smuzhiyun /* allow space for any buffered data and for new data, up to */
917*4882a593Smuzhiyun /* transfer buffer size - 2 (for command and length bytes) */
918*4882a593Smuzhiyun new_len = min(count, port->bulk_out_size-2-priv->dp_out_buf_len);
919*4882a593Smuzhiyun data_len = new_len + priv->dp_out_buf_len;
920*4882a593Smuzhiyun
921*4882a593Smuzhiyun if (data_len == 0) {
922*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->dp_port_lock, flags);
923*4882a593Smuzhiyun return 0;
924*4882a593Smuzhiyun }
925*4882a593Smuzhiyun
926*4882a593Smuzhiyun port->write_urb->transfer_buffer_length = data_len+2;
927*4882a593Smuzhiyun
928*4882a593Smuzhiyun *data++ = DIGI_CMD_SEND_DATA;
929*4882a593Smuzhiyun *data++ = data_len;
930*4882a593Smuzhiyun
931*4882a593Smuzhiyun /* copy in buffered data first */
932*4882a593Smuzhiyun memcpy(data, priv->dp_out_buf, priv->dp_out_buf_len);
933*4882a593Smuzhiyun data += priv->dp_out_buf_len;
934*4882a593Smuzhiyun
935*4882a593Smuzhiyun /* copy in new data */
936*4882a593Smuzhiyun memcpy(data, buf, new_len);
937*4882a593Smuzhiyun
938*4882a593Smuzhiyun ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
939*4882a593Smuzhiyun if (ret == 0) {
940*4882a593Smuzhiyun priv->dp_write_urb_in_use = 1;
941*4882a593Smuzhiyun ret = new_len;
942*4882a593Smuzhiyun priv->dp_out_buf_len = 0;
943*4882a593Smuzhiyun }
944*4882a593Smuzhiyun
945*4882a593Smuzhiyun /* return length of new data written, or error */
946*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->dp_port_lock, flags);
947*4882a593Smuzhiyun if (ret < 0)
948*4882a593Smuzhiyun dev_err_console(port,
949*4882a593Smuzhiyun "%s: usb_submit_urb failed, ret=%d, port=%d\n",
950*4882a593Smuzhiyun __func__, ret, priv->dp_port_num);
951*4882a593Smuzhiyun dev_dbg(&port->dev, "digi_write: returning %d\n", ret);
952*4882a593Smuzhiyun return ret;
953*4882a593Smuzhiyun
954*4882a593Smuzhiyun }
955*4882a593Smuzhiyun
digi_write_bulk_callback(struct urb * urb)956*4882a593Smuzhiyun static void digi_write_bulk_callback(struct urb *urb)
957*4882a593Smuzhiyun {
958*4882a593Smuzhiyun
959*4882a593Smuzhiyun struct usb_serial_port *port = urb->context;
960*4882a593Smuzhiyun struct usb_serial *serial;
961*4882a593Smuzhiyun struct digi_port *priv;
962*4882a593Smuzhiyun struct digi_serial *serial_priv;
963*4882a593Smuzhiyun unsigned long flags;
964*4882a593Smuzhiyun int ret = 0;
965*4882a593Smuzhiyun int status = urb->status;
966*4882a593Smuzhiyun bool wakeup;
967*4882a593Smuzhiyun
968*4882a593Smuzhiyun /* port and serial sanity check */
969*4882a593Smuzhiyun if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) {
970*4882a593Smuzhiyun pr_err("%s: port or port->private is NULL, status=%d\n",
971*4882a593Smuzhiyun __func__, status);
972*4882a593Smuzhiyun return;
973*4882a593Smuzhiyun }
974*4882a593Smuzhiyun serial = port->serial;
975*4882a593Smuzhiyun if (serial == NULL || (serial_priv = usb_get_serial_data(serial)) == NULL) {
976*4882a593Smuzhiyun dev_err(&port->dev,
977*4882a593Smuzhiyun "%s: serial or serial->private is NULL, status=%d\n",
978*4882a593Smuzhiyun __func__, status);
979*4882a593Smuzhiyun return;
980*4882a593Smuzhiyun }
981*4882a593Smuzhiyun
982*4882a593Smuzhiyun /* handle oob callback */
983*4882a593Smuzhiyun if (priv->dp_port_num == serial_priv->ds_oob_port_num) {
984*4882a593Smuzhiyun dev_dbg(&port->dev, "digi_write_bulk_callback: oob callback\n");
985*4882a593Smuzhiyun spin_lock_irqsave(&priv->dp_port_lock, flags);
986*4882a593Smuzhiyun priv->dp_write_urb_in_use = 0;
987*4882a593Smuzhiyun wake_up_interruptible(&port->write_wait);
988*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->dp_port_lock, flags);
989*4882a593Smuzhiyun return;
990*4882a593Smuzhiyun }
991*4882a593Smuzhiyun
992*4882a593Smuzhiyun /* try to send any buffered data on this port */
993*4882a593Smuzhiyun wakeup = true;
994*4882a593Smuzhiyun spin_lock_irqsave(&priv->dp_port_lock, flags);
995*4882a593Smuzhiyun priv->dp_write_urb_in_use = 0;
996*4882a593Smuzhiyun if (priv->dp_out_buf_len > 0) {
997*4882a593Smuzhiyun *((unsigned char *)(port->write_urb->transfer_buffer))
998*4882a593Smuzhiyun = (unsigned char)DIGI_CMD_SEND_DATA;
999*4882a593Smuzhiyun *((unsigned char *)(port->write_urb->transfer_buffer) + 1)
1000*4882a593Smuzhiyun = (unsigned char)priv->dp_out_buf_len;
1001*4882a593Smuzhiyun port->write_urb->transfer_buffer_length =
1002*4882a593Smuzhiyun priv->dp_out_buf_len + 2;
1003*4882a593Smuzhiyun memcpy(port->write_urb->transfer_buffer + 2, priv->dp_out_buf,
1004*4882a593Smuzhiyun priv->dp_out_buf_len);
1005*4882a593Smuzhiyun ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
1006*4882a593Smuzhiyun if (ret == 0) {
1007*4882a593Smuzhiyun priv->dp_write_urb_in_use = 1;
1008*4882a593Smuzhiyun priv->dp_out_buf_len = 0;
1009*4882a593Smuzhiyun wakeup = false;
1010*4882a593Smuzhiyun }
1011*4882a593Smuzhiyun }
1012*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->dp_port_lock, flags);
1013*4882a593Smuzhiyun
1014*4882a593Smuzhiyun if (ret && ret != -EPERM)
1015*4882a593Smuzhiyun dev_err_console(port,
1016*4882a593Smuzhiyun "%s: usb_submit_urb failed, ret=%d, port=%d\n",
1017*4882a593Smuzhiyun __func__, ret, priv->dp_port_num);
1018*4882a593Smuzhiyun
1019*4882a593Smuzhiyun if (wakeup)
1020*4882a593Smuzhiyun tty_port_tty_wakeup(&port->port);
1021*4882a593Smuzhiyun }
1022*4882a593Smuzhiyun
digi_write_room(struct tty_struct * tty)1023*4882a593Smuzhiyun static int digi_write_room(struct tty_struct *tty)
1024*4882a593Smuzhiyun {
1025*4882a593Smuzhiyun struct usb_serial_port *port = tty->driver_data;
1026*4882a593Smuzhiyun struct digi_port *priv = usb_get_serial_port_data(port);
1027*4882a593Smuzhiyun int room;
1028*4882a593Smuzhiyun unsigned long flags = 0;
1029*4882a593Smuzhiyun
1030*4882a593Smuzhiyun spin_lock_irqsave(&priv->dp_port_lock, flags);
1031*4882a593Smuzhiyun
1032*4882a593Smuzhiyun if (priv->dp_write_urb_in_use)
1033*4882a593Smuzhiyun room = 0;
1034*4882a593Smuzhiyun else
1035*4882a593Smuzhiyun room = port->bulk_out_size - 2 - priv->dp_out_buf_len;
1036*4882a593Smuzhiyun
1037*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->dp_port_lock, flags);
1038*4882a593Smuzhiyun dev_dbg(&port->dev, "digi_write_room: port=%d, room=%d\n", priv->dp_port_num, room);
1039*4882a593Smuzhiyun return room;
1040*4882a593Smuzhiyun
1041*4882a593Smuzhiyun }
1042*4882a593Smuzhiyun
digi_chars_in_buffer(struct tty_struct * tty)1043*4882a593Smuzhiyun static int digi_chars_in_buffer(struct tty_struct *tty)
1044*4882a593Smuzhiyun {
1045*4882a593Smuzhiyun struct usb_serial_port *port = tty->driver_data;
1046*4882a593Smuzhiyun struct digi_port *priv = usb_get_serial_port_data(port);
1047*4882a593Smuzhiyun
1048*4882a593Smuzhiyun if (priv->dp_write_urb_in_use) {
1049*4882a593Smuzhiyun dev_dbg(&port->dev, "digi_chars_in_buffer: port=%d, chars=%d\n",
1050*4882a593Smuzhiyun priv->dp_port_num, port->bulk_out_size - 2);
1051*4882a593Smuzhiyun /* return(port->bulk_out_size - 2); */
1052*4882a593Smuzhiyun return 256;
1053*4882a593Smuzhiyun } else {
1054*4882a593Smuzhiyun dev_dbg(&port->dev, "digi_chars_in_buffer: port=%d, chars=%d\n",
1055*4882a593Smuzhiyun priv->dp_port_num, priv->dp_out_buf_len);
1056*4882a593Smuzhiyun return priv->dp_out_buf_len;
1057*4882a593Smuzhiyun }
1058*4882a593Smuzhiyun
1059*4882a593Smuzhiyun }
1060*4882a593Smuzhiyun
digi_dtr_rts(struct usb_serial_port * port,int on)1061*4882a593Smuzhiyun static void digi_dtr_rts(struct usb_serial_port *port, int on)
1062*4882a593Smuzhiyun {
1063*4882a593Smuzhiyun /* Adjust DTR and RTS */
1064*4882a593Smuzhiyun digi_set_modem_signals(port, on * (TIOCM_DTR | TIOCM_RTS), 1);
1065*4882a593Smuzhiyun }
1066*4882a593Smuzhiyun
digi_open(struct tty_struct * tty,struct usb_serial_port * port)1067*4882a593Smuzhiyun static int digi_open(struct tty_struct *tty, struct usb_serial_port *port)
1068*4882a593Smuzhiyun {
1069*4882a593Smuzhiyun int ret;
1070*4882a593Smuzhiyun unsigned char buf[32];
1071*4882a593Smuzhiyun struct digi_port *priv = usb_get_serial_port_data(port);
1072*4882a593Smuzhiyun struct ktermios not_termios;
1073*4882a593Smuzhiyun
1074*4882a593Smuzhiyun /* be sure the device is started up */
1075*4882a593Smuzhiyun if (digi_startup_device(port->serial) != 0)
1076*4882a593Smuzhiyun return -ENXIO;
1077*4882a593Smuzhiyun
1078*4882a593Smuzhiyun /* read modem signals automatically whenever they change */
1079*4882a593Smuzhiyun buf[0] = DIGI_CMD_READ_INPUT_SIGNALS;
1080*4882a593Smuzhiyun buf[1] = priv->dp_port_num;
1081*4882a593Smuzhiyun buf[2] = DIGI_ENABLE;
1082*4882a593Smuzhiyun buf[3] = 0;
1083*4882a593Smuzhiyun
1084*4882a593Smuzhiyun /* flush fifos */
1085*4882a593Smuzhiyun buf[4] = DIGI_CMD_IFLUSH_FIFO;
1086*4882a593Smuzhiyun buf[5] = priv->dp_port_num;
1087*4882a593Smuzhiyun buf[6] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
1088*4882a593Smuzhiyun buf[7] = 0;
1089*4882a593Smuzhiyun
1090*4882a593Smuzhiyun ret = digi_write_oob_command(port, buf, 8, 1);
1091*4882a593Smuzhiyun if (ret != 0)
1092*4882a593Smuzhiyun dev_dbg(&port->dev, "digi_open: write oob failed, ret=%d\n", ret);
1093*4882a593Smuzhiyun
1094*4882a593Smuzhiyun /* set termios settings */
1095*4882a593Smuzhiyun if (tty) {
1096*4882a593Smuzhiyun not_termios.c_cflag = ~tty->termios.c_cflag;
1097*4882a593Smuzhiyun not_termios.c_iflag = ~tty->termios.c_iflag;
1098*4882a593Smuzhiyun digi_set_termios(tty, port, ¬_termios);
1099*4882a593Smuzhiyun }
1100*4882a593Smuzhiyun return 0;
1101*4882a593Smuzhiyun }
1102*4882a593Smuzhiyun
1103*4882a593Smuzhiyun
digi_close(struct usb_serial_port * port)1104*4882a593Smuzhiyun static void digi_close(struct usb_serial_port *port)
1105*4882a593Smuzhiyun {
1106*4882a593Smuzhiyun DEFINE_WAIT(wait);
1107*4882a593Smuzhiyun int ret;
1108*4882a593Smuzhiyun unsigned char buf[32];
1109*4882a593Smuzhiyun struct digi_port *priv = usb_get_serial_port_data(port);
1110*4882a593Smuzhiyun
1111*4882a593Smuzhiyun mutex_lock(&port->serial->disc_mutex);
1112*4882a593Smuzhiyun /* if disconnected, just clear flags */
1113*4882a593Smuzhiyun if (port->serial->disconnected)
1114*4882a593Smuzhiyun goto exit;
1115*4882a593Smuzhiyun
1116*4882a593Smuzhiyun /* FIXME: Transmit idle belongs in the wait_unti_sent path */
1117*4882a593Smuzhiyun digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
1118*4882a593Smuzhiyun
1119*4882a593Smuzhiyun /* disable input flow control */
1120*4882a593Smuzhiyun buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
1121*4882a593Smuzhiyun buf[1] = priv->dp_port_num;
1122*4882a593Smuzhiyun buf[2] = DIGI_DISABLE;
1123*4882a593Smuzhiyun buf[3] = 0;
1124*4882a593Smuzhiyun
1125*4882a593Smuzhiyun /* disable output flow control */
1126*4882a593Smuzhiyun buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL;
1127*4882a593Smuzhiyun buf[5] = priv->dp_port_num;
1128*4882a593Smuzhiyun buf[6] = DIGI_DISABLE;
1129*4882a593Smuzhiyun buf[7] = 0;
1130*4882a593Smuzhiyun
1131*4882a593Smuzhiyun /* disable reading modem signals automatically */
1132*4882a593Smuzhiyun buf[8] = DIGI_CMD_READ_INPUT_SIGNALS;
1133*4882a593Smuzhiyun buf[9] = priv->dp_port_num;
1134*4882a593Smuzhiyun buf[10] = DIGI_DISABLE;
1135*4882a593Smuzhiyun buf[11] = 0;
1136*4882a593Smuzhiyun
1137*4882a593Smuzhiyun /* disable receive */
1138*4882a593Smuzhiyun buf[12] = DIGI_CMD_RECEIVE_ENABLE;
1139*4882a593Smuzhiyun buf[13] = priv->dp_port_num;
1140*4882a593Smuzhiyun buf[14] = DIGI_DISABLE;
1141*4882a593Smuzhiyun buf[15] = 0;
1142*4882a593Smuzhiyun
1143*4882a593Smuzhiyun /* flush fifos */
1144*4882a593Smuzhiyun buf[16] = DIGI_CMD_IFLUSH_FIFO;
1145*4882a593Smuzhiyun buf[17] = priv->dp_port_num;
1146*4882a593Smuzhiyun buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
1147*4882a593Smuzhiyun buf[19] = 0;
1148*4882a593Smuzhiyun
1149*4882a593Smuzhiyun ret = digi_write_oob_command(port, buf, 20, 0);
1150*4882a593Smuzhiyun if (ret != 0)
1151*4882a593Smuzhiyun dev_dbg(&port->dev, "digi_close: write oob failed, ret=%d\n",
1152*4882a593Smuzhiyun ret);
1153*4882a593Smuzhiyun /* wait for final commands on oob port to complete */
1154*4882a593Smuzhiyun prepare_to_wait(&priv->dp_flush_wait, &wait,
1155*4882a593Smuzhiyun TASK_INTERRUPTIBLE);
1156*4882a593Smuzhiyun schedule_timeout(DIGI_CLOSE_TIMEOUT);
1157*4882a593Smuzhiyun finish_wait(&priv->dp_flush_wait, &wait);
1158*4882a593Smuzhiyun
1159*4882a593Smuzhiyun /* shutdown any outstanding bulk writes */
1160*4882a593Smuzhiyun usb_kill_urb(port->write_urb);
1161*4882a593Smuzhiyun exit:
1162*4882a593Smuzhiyun spin_lock_irq(&priv->dp_port_lock);
1163*4882a593Smuzhiyun priv->dp_write_urb_in_use = 0;
1164*4882a593Smuzhiyun wake_up_interruptible(&priv->dp_close_wait);
1165*4882a593Smuzhiyun spin_unlock_irq(&priv->dp_port_lock);
1166*4882a593Smuzhiyun mutex_unlock(&port->serial->disc_mutex);
1167*4882a593Smuzhiyun }
1168*4882a593Smuzhiyun
1169*4882a593Smuzhiyun
1170*4882a593Smuzhiyun /*
1171*4882a593Smuzhiyun * Digi Startup Device
1172*4882a593Smuzhiyun *
1173*4882a593Smuzhiyun * Starts reads on all ports. Must be called AFTER startup, with
1174*4882a593Smuzhiyun * urbs initialized. Returns 0 if successful, non-zero error otherwise.
1175*4882a593Smuzhiyun */
1176*4882a593Smuzhiyun
digi_startup_device(struct usb_serial * serial)1177*4882a593Smuzhiyun static int digi_startup_device(struct usb_serial *serial)
1178*4882a593Smuzhiyun {
1179*4882a593Smuzhiyun int i, ret = 0;
1180*4882a593Smuzhiyun struct digi_serial *serial_priv = usb_get_serial_data(serial);
1181*4882a593Smuzhiyun struct usb_serial_port *port;
1182*4882a593Smuzhiyun
1183*4882a593Smuzhiyun /* be sure this happens exactly once */
1184*4882a593Smuzhiyun spin_lock(&serial_priv->ds_serial_lock);
1185*4882a593Smuzhiyun if (serial_priv->ds_device_started) {
1186*4882a593Smuzhiyun spin_unlock(&serial_priv->ds_serial_lock);
1187*4882a593Smuzhiyun return 0;
1188*4882a593Smuzhiyun }
1189*4882a593Smuzhiyun serial_priv->ds_device_started = 1;
1190*4882a593Smuzhiyun spin_unlock(&serial_priv->ds_serial_lock);
1191*4882a593Smuzhiyun
1192*4882a593Smuzhiyun /* start reading from each bulk in endpoint for the device */
1193*4882a593Smuzhiyun /* set USB_DISABLE_SPD flag for write bulk urbs */
1194*4882a593Smuzhiyun for (i = 0; i < serial->type->num_ports + 1; i++) {
1195*4882a593Smuzhiyun port = serial->port[i];
1196*4882a593Smuzhiyun ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
1197*4882a593Smuzhiyun if (ret != 0) {
1198*4882a593Smuzhiyun dev_err(&port->dev,
1199*4882a593Smuzhiyun "%s: usb_submit_urb failed, ret=%d, port=%d\n",
1200*4882a593Smuzhiyun __func__, ret, i);
1201*4882a593Smuzhiyun break;
1202*4882a593Smuzhiyun }
1203*4882a593Smuzhiyun }
1204*4882a593Smuzhiyun return ret;
1205*4882a593Smuzhiyun }
1206*4882a593Smuzhiyun
digi_port_init(struct usb_serial_port * port,unsigned port_num)1207*4882a593Smuzhiyun static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
1208*4882a593Smuzhiyun {
1209*4882a593Smuzhiyun struct digi_port *priv;
1210*4882a593Smuzhiyun
1211*4882a593Smuzhiyun priv = kzalloc(sizeof(*priv), GFP_KERNEL);
1212*4882a593Smuzhiyun if (!priv)
1213*4882a593Smuzhiyun return -ENOMEM;
1214*4882a593Smuzhiyun
1215*4882a593Smuzhiyun spin_lock_init(&priv->dp_port_lock);
1216*4882a593Smuzhiyun priv->dp_port_num = port_num;
1217*4882a593Smuzhiyun init_waitqueue_head(&priv->dp_transmit_idle_wait);
1218*4882a593Smuzhiyun init_waitqueue_head(&priv->dp_flush_wait);
1219*4882a593Smuzhiyun init_waitqueue_head(&priv->dp_close_wait);
1220*4882a593Smuzhiyun priv->dp_port = port;
1221*4882a593Smuzhiyun
1222*4882a593Smuzhiyun init_waitqueue_head(&port->write_wait);
1223*4882a593Smuzhiyun
1224*4882a593Smuzhiyun usb_set_serial_port_data(port, priv);
1225*4882a593Smuzhiyun
1226*4882a593Smuzhiyun return 0;
1227*4882a593Smuzhiyun }
1228*4882a593Smuzhiyun
digi_startup(struct usb_serial * serial)1229*4882a593Smuzhiyun static int digi_startup(struct usb_serial *serial)
1230*4882a593Smuzhiyun {
1231*4882a593Smuzhiyun struct digi_serial *serial_priv;
1232*4882a593Smuzhiyun int ret;
1233*4882a593Smuzhiyun
1234*4882a593Smuzhiyun serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
1235*4882a593Smuzhiyun if (!serial_priv)
1236*4882a593Smuzhiyun return -ENOMEM;
1237*4882a593Smuzhiyun
1238*4882a593Smuzhiyun spin_lock_init(&serial_priv->ds_serial_lock);
1239*4882a593Smuzhiyun serial_priv->ds_oob_port_num = serial->type->num_ports;
1240*4882a593Smuzhiyun serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num];
1241*4882a593Smuzhiyun
1242*4882a593Smuzhiyun ret = digi_port_init(serial_priv->ds_oob_port,
1243*4882a593Smuzhiyun serial_priv->ds_oob_port_num);
1244*4882a593Smuzhiyun if (ret) {
1245*4882a593Smuzhiyun kfree(serial_priv);
1246*4882a593Smuzhiyun return ret;
1247*4882a593Smuzhiyun }
1248*4882a593Smuzhiyun
1249*4882a593Smuzhiyun usb_set_serial_data(serial, serial_priv);
1250*4882a593Smuzhiyun
1251*4882a593Smuzhiyun return 0;
1252*4882a593Smuzhiyun }
1253*4882a593Smuzhiyun
1254*4882a593Smuzhiyun
digi_disconnect(struct usb_serial * serial)1255*4882a593Smuzhiyun static void digi_disconnect(struct usb_serial *serial)
1256*4882a593Smuzhiyun {
1257*4882a593Smuzhiyun int i;
1258*4882a593Smuzhiyun
1259*4882a593Smuzhiyun /* stop reads and writes on all ports */
1260*4882a593Smuzhiyun for (i = 0; i < serial->type->num_ports + 1; i++) {
1261*4882a593Smuzhiyun usb_kill_urb(serial->port[i]->read_urb);
1262*4882a593Smuzhiyun usb_kill_urb(serial->port[i]->write_urb);
1263*4882a593Smuzhiyun }
1264*4882a593Smuzhiyun }
1265*4882a593Smuzhiyun
1266*4882a593Smuzhiyun
digi_release(struct usb_serial * serial)1267*4882a593Smuzhiyun static void digi_release(struct usb_serial *serial)
1268*4882a593Smuzhiyun {
1269*4882a593Smuzhiyun struct digi_serial *serial_priv;
1270*4882a593Smuzhiyun struct digi_port *priv;
1271*4882a593Smuzhiyun
1272*4882a593Smuzhiyun serial_priv = usb_get_serial_data(serial);
1273*4882a593Smuzhiyun
1274*4882a593Smuzhiyun priv = usb_get_serial_port_data(serial_priv->ds_oob_port);
1275*4882a593Smuzhiyun kfree(priv);
1276*4882a593Smuzhiyun
1277*4882a593Smuzhiyun kfree(serial_priv);
1278*4882a593Smuzhiyun }
1279*4882a593Smuzhiyun
digi_port_probe(struct usb_serial_port * port)1280*4882a593Smuzhiyun static int digi_port_probe(struct usb_serial_port *port)
1281*4882a593Smuzhiyun {
1282*4882a593Smuzhiyun return digi_port_init(port, port->port_number);
1283*4882a593Smuzhiyun }
1284*4882a593Smuzhiyun
digi_port_remove(struct usb_serial_port * port)1285*4882a593Smuzhiyun static int digi_port_remove(struct usb_serial_port *port)
1286*4882a593Smuzhiyun {
1287*4882a593Smuzhiyun struct digi_port *priv;
1288*4882a593Smuzhiyun
1289*4882a593Smuzhiyun priv = usb_get_serial_port_data(port);
1290*4882a593Smuzhiyun kfree(priv);
1291*4882a593Smuzhiyun
1292*4882a593Smuzhiyun return 0;
1293*4882a593Smuzhiyun }
1294*4882a593Smuzhiyun
digi_read_bulk_callback(struct urb * urb)1295*4882a593Smuzhiyun static void digi_read_bulk_callback(struct urb *urb)
1296*4882a593Smuzhiyun {
1297*4882a593Smuzhiyun struct usb_serial_port *port = urb->context;
1298*4882a593Smuzhiyun struct digi_port *priv;
1299*4882a593Smuzhiyun struct digi_serial *serial_priv;
1300*4882a593Smuzhiyun int ret;
1301*4882a593Smuzhiyun int status = urb->status;
1302*4882a593Smuzhiyun
1303*4882a593Smuzhiyun /* port sanity check, do not resubmit if port is not valid */
1304*4882a593Smuzhiyun if (port == NULL)
1305*4882a593Smuzhiyun return;
1306*4882a593Smuzhiyun priv = usb_get_serial_port_data(port);
1307*4882a593Smuzhiyun if (priv == NULL) {
1308*4882a593Smuzhiyun dev_err(&port->dev, "%s: port->private is NULL, status=%d\n",
1309*4882a593Smuzhiyun __func__, status);
1310*4882a593Smuzhiyun return;
1311*4882a593Smuzhiyun }
1312*4882a593Smuzhiyun if (port->serial == NULL ||
1313*4882a593Smuzhiyun (serial_priv = usb_get_serial_data(port->serial)) == NULL) {
1314*4882a593Smuzhiyun dev_err(&port->dev, "%s: serial is bad or serial->private "
1315*4882a593Smuzhiyun "is NULL, status=%d\n", __func__, status);
1316*4882a593Smuzhiyun return;
1317*4882a593Smuzhiyun }
1318*4882a593Smuzhiyun
1319*4882a593Smuzhiyun /* do not resubmit urb if it has any status error */
1320*4882a593Smuzhiyun if (status) {
1321*4882a593Smuzhiyun dev_err(&port->dev,
1322*4882a593Smuzhiyun "%s: nonzero read bulk status: status=%d, port=%d\n",
1323*4882a593Smuzhiyun __func__, status, priv->dp_port_num);
1324*4882a593Smuzhiyun return;
1325*4882a593Smuzhiyun }
1326*4882a593Smuzhiyun
1327*4882a593Smuzhiyun /* handle oob or inb callback, do not resubmit if error */
1328*4882a593Smuzhiyun if (priv->dp_port_num == serial_priv->ds_oob_port_num) {
1329*4882a593Smuzhiyun if (digi_read_oob_callback(urb) != 0)
1330*4882a593Smuzhiyun return;
1331*4882a593Smuzhiyun } else {
1332*4882a593Smuzhiyun if (digi_read_inb_callback(urb) != 0)
1333*4882a593Smuzhiyun return;
1334*4882a593Smuzhiyun }
1335*4882a593Smuzhiyun
1336*4882a593Smuzhiyun /* continue read */
1337*4882a593Smuzhiyun ret = usb_submit_urb(urb, GFP_ATOMIC);
1338*4882a593Smuzhiyun if (ret != 0 && ret != -EPERM) {
1339*4882a593Smuzhiyun dev_err(&port->dev,
1340*4882a593Smuzhiyun "%s: failed resubmitting urb, ret=%d, port=%d\n",
1341*4882a593Smuzhiyun __func__, ret, priv->dp_port_num);
1342*4882a593Smuzhiyun }
1343*4882a593Smuzhiyun
1344*4882a593Smuzhiyun }
1345*4882a593Smuzhiyun
1346*4882a593Smuzhiyun /*
1347*4882a593Smuzhiyun * Digi Read INB Callback
1348*4882a593Smuzhiyun *
1349*4882a593Smuzhiyun * Digi Read INB Callback handles reads on the in band ports, sending
1350*4882a593Smuzhiyun * the data on to the tty subsystem. When called we know port and
1351*4882a593Smuzhiyun * port->private are not NULL and port->serial has been validated.
1352*4882a593Smuzhiyun * It returns 0 if successful, 1 if successful but the port is
1353*4882a593Smuzhiyun * throttled, and -1 if the sanity checks failed.
1354*4882a593Smuzhiyun */
1355*4882a593Smuzhiyun
digi_read_inb_callback(struct urb * urb)1356*4882a593Smuzhiyun static int digi_read_inb_callback(struct urb *urb)
1357*4882a593Smuzhiyun {
1358*4882a593Smuzhiyun struct usb_serial_port *port = urb->context;
1359*4882a593Smuzhiyun struct digi_port *priv = usb_get_serial_port_data(port);
1360*4882a593Smuzhiyun unsigned char *buf = urb->transfer_buffer;
1361*4882a593Smuzhiyun unsigned long flags;
1362*4882a593Smuzhiyun int opcode;
1363*4882a593Smuzhiyun int len;
1364*4882a593Smuzhiyun int port_status;
1365*4882a593Smuzhiyun unsigned char *data;
1366*4882a593Smuzhiyun int tty_flag, throttled;
1367*4882a593Smuzhiyun
1368*4882a593Smuzhiyun /* short/multiple packet check */
1369*4882a593Smuzhiyun if (urb->actual_length < 2) {
1370*4882a593Smuzhiyun dev_warn(&port->dev, "short packet received\n");
1371*4882a593Smuzhiyun return -1;
1372*4882a593Smuzhiyun }
1373*4882a593Smuzhiyun
1374*4882a593Smuzhiyun opcode = buf[0];
1375*4882a593Smuzhiyun len = buf[1];
1376*4882a593Smuzhiyun
1377*4882a593Smuzhiyun if (urb->actual_length != len + 2) {
1378*4882a593Smuzhiyun dev_err(&port->dev, "malformed packet received: port=%d, opcode=%d, len=%d, actual_length=%u\n",
1379*4882a593Smuzhiyun priv->dp_port_num, opcode, len, urb->actual_length);
1380*4882a593Smuzhiyun return -1;
1381*4882a593Smuzhiyun }
1382*4882a593Smuzhiyun
1383*4882a593Smuzhiyun if (opcode == DIGI_CMD_RECEIVE_DATA && len < 1) {
1384*4882a593Smuzhiyun dev_err(&port->dev, "malformed data packet received\n");
1385*4882a593Smuzhiyun return -1;
1386*4882a593Smuzhiyun }
1387*4882a593Smuzhiyun
1388*4882a593Smuzhiyun spin_lock_irqsave(&priv->dp_port_lock, flags);
1389*4882a593Smuzhiyun
1390*4882a593Smuzhiyun /* check for throttle; if set, do not resubmit read urb */
1391*4882a593Smuzhiyun /* indicate the read chain needs to be restarted on unthrottle */
1392*4882a593Smuzhiyun throttled = priv->dp_throttled;
1393*4882a593Smuzhiyun if (throttled)
1394*4882a593Smuzhiyun priv->dp_throttle_restart = 1;
1395*4882a593Smuzhiyun
1396*4882a593Smuzhiyun /* receive data */
1397*4882a593Smuzhiyun if (opcode == DIGI_CMD_RECEIVE_DATA) {
1398*4882a593Smuzhiyun port_status = buf[2];
1399*4882a593Smuzhiyun data = &buf[3];
1400*4882a593Smuzhiyun
1401*4882a593Smuzhiyun /* get flag from port_status */
1402*4882a593Smuzhiyun tty_flag = 0;
1403*4882a593Smuzhiyun
1404*4882a593Smuzhiyun /* overrun is special, not associated with a char */
1405*4882a593Smuzhiyun if (port_status & DIGI_OVERRUN_ERROR)
1406*4882a593Smuzhiyun tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
1407*4882a593Smuzhiyun
1408*4882a593Smuzhiyun /* break takes precedence over parity, */
1409*4882a593Smuzhiyun /* which takes precedence over framing errors */
1410*4882a593Smuzhiyun if (port_status & DIGI_BREAK_ERROR)
1411*4882a593Smuzhiyun tty_flag = TTY_BREAK;
1412*4882a593Smuzhiyun else if (port_status & DIGI_PARITY_ERROR)
1413*4882a593Smuzhiyun tty_flag = TTY_PARITY;
1414*4882a593Smuzhiyun else if (port_status & DIGI_FRAMING_ERROR)
1415*4882a593Smuzhiyun tty_flag = TTY_FRAME;
1416*4882a593Smuzhiyun
1417*4882a593Smuzhiyun /* data length is len-1 (one byte of len is port_status) */
1418*4882a593Smuzhiyun --len;
1419*4882a593Smuzhiyun if (len > 0) {
1420*4882a593Smuzhiyun tty_insert_flip_string_fixed_flag(&port->port, data,
1421*4882a593Smuzhiyun tty_flag, len);
1422*4882a593Smuzhiyun tty_flip_buffer_push(&port->port);
1423*4882a593Smuzhiyun }
1424*4882a593Smuzhiyun }
1425*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->dp_port_lock, flags);
1426*4882a593Smuzhiyun
1427*4882a593Smuzhiyun if (opcode == DIGI_CMD_RECEIVE_DISABLE)
1428*4882a593Smuzhiyun dev_dbg(&port->dev, "%s: got RECEIVE_DISABLE\n", __func__);
1429*4882a593Smuzhiyun else if (opcode != DIGI_CMD_RECEIVE_DATA)
1430*4882a593Smuzhiyun dev_dbg(&port->dev, "%s: unknown opcode: %d\n", __func__, opcode);
1431*4882a593Smuzhiyun
1432*4882a593Smuzhiyun return throttled ? 1 : 0;
1433*4882a593Smuzhiyun
1434*4882a593Smuzhiyun }
1435*4882a593Smuzhiyun
1436*4882a593Smuzhiyun
1437*4882a593Smuzhiyun /*
1438*4882a593Smuzhiyun * Digi Read OOB Callback
1439*4882a593Smuzhiyun *
1440*4882a593Smuzhiyun * Digi Read OOB Callback handles reads on the out of band port.
1441*4882a593Smuzhiyun * When called we know port and port->private are not NULL and
1442*4882a593Smuzhiyun * the port->serial is valid. It returns 0 if successful, and
1443*4882a593Smuzhiyun * -1 if the sanity checks failed.
1444*4882a593Smuzhiyun */
1445*4882a593Smuzhiyun
digi_read_oob_callback(struct urb * urb)1446*4882a593Smuzhiyun static int digi_read_oob_callback(struct urb *urb)
1447*4882a593Smuzhiyun {
1448*4882a593Smuzhiyun
1449*4882a593Smuzhiyun struct usb_serial_port *port = urb->context;
1450*4882a593Smuzhiyun struct usb_serial *serial = port->serial;
1451*4882a593Smuzhiyun struct tty_struct *tty;
1452*4882a593Smuzhiyun struct digi_port *priv;
1453*4882a593Smuzhiyun unsigned char *buf = urb->transfer_buffer;
1454*4882a593Smuzhiyun int opcode, line, status, val;
1455*4882a593Smuzhiyun unsigned long flags;
1456*4882a593Smuzhiyun int i;
1457*4882a593Smuzhiyun unsigned int rts;
1458*4882a593Smuzhiyun
1459*4882a593Smuzhiyun if (urb->actual_length < 4)
1460*4882a593Smuzhiyun return -1;
1461*4882a593Smuzhiyun
1462*4882a593Smuzhiyun /* handle each oob command */
1463*4882a593Smuzhiyun for (i = 0; i < urb->actual_length - 3; i += 4) {
1464*4882a593Smuzhiyun opcode = buf[i];
1465*4882a593Smuzhiyun line = buf[i + 1];
1466*4882a593Smuzhiyun status = buf[i + 2];
1467*4882a593Smuzhiyun val = buf[i + 3];
1468*4882a593Smuzhiyun
1469*4882a593Smuzhiyun dev_dbg(&port->dev, "digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d\n",
1470*4882a593Smuzhiyun opcode, line, status, val);
1471*4882a593Smuzhiyun
1472*4882a593Smuzhiyun if (status != 0 || line >= serial->type->num_ports)
1473*4882a593Smuzhiyun continue;
1474*4882a593Smuzhiyun
1475*4882a593Smuzhiyun port = serial->port[line];
1476*4882a593Smuzhiyun
1477*4882a593Smuzhiyun priv = usb_get_serial_port_data(port);
1478*4882a593Smuzhiyun if (priv == NULL)
1479*4882a593Smuzhiyun return -1;
1480*4882a593Smuzhiyun
1481*4882a593Smuzhiyun tty = tty_port_tty_get(&port->port);
1482*4882a593Smuzhiyun
1483*4882a593Smuzhiyun rts = 0;
1484*4882a593Smuzhiyun if (tty)
1485*4882a593Smuzhiyun rts = C_CRTSCTS(tty);
1486*4882a593Smuzhiyun
1487*4882a593Smuzhiyun if (tty && opcode == DIGI_CMD_READ_INPUT_SIGNALS) {
1488*4882a593Smuzhiyun bool wakeup = false;
1489*4882a593Smuzhiyun
1490*4882a593Smuzhiyun spin_lock_irqsave(&priv->dp_port_lock, flags);
1491*4882a593Smuzhiyun /* convert from digi flags to termiox flags */
1492*4882a593Smuzhiyun if (val & DIGI_READ_INPUT_SIGNALS_CTS) {
1493*4882a593Smuzhiyun priv->dp_modem_signals |= TIOCM_CTS;
1494*4882a593Smuzhiyun if (rts)
1495*4882a593Smuzhiyun wakeup = true;
1496*4882a593Smuzhiyun } else {
1497*4882a593Smuzhiyun priv->dp_modem_signals &= ~TIOCM_CTS;
1498*4882a593Smuzhiyun /* port must be open to use tty struct */
1499*4882a593Smuzhiyun }
1500*4882a593Smuzhiyun if (val & DIGI_READ_INPUT_SIGNALS_DSR)
1501*4882a593Smuzhiyun priv->dp_modem_signals |= TIOCM_DSR;
1502*4882a593Smuzhiyun else
1503*4882a593Smuzhiyun priv->dp_modem_signals &= ~TIOCM_DSR;
1504*4882a593Smuzhiyun if (val & DIGI_READ_INPUT_SIGNALS_RI)
1505*4882a593Smuzhiyun priv->dp_modem_signals |= TIOCM_RI;
1506*4882a593Smuzhiyun else
1507*4882a593Smuzhiyun priv->dp_modem_signals &= ~TIOCM_RI;
1508*4882a593Smuzhiyun if (val & DIGI_READ_INPUT_SIGNALS_DCD)
1509*4882a593Smuzhiyun priv->dp_modem_signals |= TIOCM_CD;
1510*4882a593Smuzhiyun else
1511*4882a593Smuzhiyun priv->dp_modem_signals &= ~TIOCM_CD;
1512*4882a593Smuzhiyun
1513*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->dp_port_lock, flags);
1514*4882a593Smuzhiyun
1515*4882a593Smuzhiyun if (wakeup)
1516*4882a593Smuzhiyun tty_port_tty_wakeup(&port->port);
1517*4882a593Smuzhiyun } else if (opcode == DIGI_CMD_TRANSMIT_IDLE) {
1518*4882a593Smuzhiyun spin_lock_irqsave(&priv->dp_port_lock, flags);
1519*4882a593Smuzhiyun priv->dp_transmit_idle = 1;
1520*4882a593Smuzhiyun wake_up_interruptible(&priv->dp_transmit_idle_wait);
1521*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->dp_port_lock, flags);
1522*4882a593Smuzhiyun } else if (opcode == DIGI_CMD_IFLUSH_FIFO) {
1523*4882a593Smuzhiyun wake_up_interruptible(&priv->dp_flush_wait);
1524*4882a593Smuzhiyun }
1525*4882a593Smuzhiyun tty_kref_put(tty);
1526*4882a593Smuzhiyun }
1527*4882a593Smuzhiyun return 0;
1528*4882a593Smuzhiyun
1529*4882a593Smuzhiyun }
1530*4882a593Smuzhiyun
1531*4882a593Smuzhiyun module_usb_serial_driver(serial_drivers, id_table_combined);
1532*4882a593Smuzhiyun
1533*4882a593Smuzhiyun MODULE_AUTHOR(DRIVER_AUTHOR);
1534*4882a593Smuzhiyun MODULE_DESCRIPTION(DRIVER_DESC);
1535*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1536