1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * usb-serial driver for Quatech SSU-100
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * based on ftdi_sio.c and the original serqt_usb.c from Quatech
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/errno.h>
10*4882a593Smuzhiyun #include <linux/slab.h>
11*4882a593Smuzhiyun #include <linux/tty.h>
12*4882a593Smuzhiyun #include <linux/tty_driver.h>
13*4882a593Smuzhiyun #include <linux/tty_flip.h>
14*4882a593Smuzhiyun #include <linux/module.h>
15*4882a593Smuzhiyun #include <linux/serial.h>
16*4882a593Smuzhiyun #include <linux/usb.h>
17*4882a593Smuzhiyun #include <linux/usb/serial.h>
18*4882a593Smuzhiyun #include <linux/serial_reg.h>
19*4882a593Smuzhiyun #include <linux/uaccess.h>
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun #define QT_OPEN_CLOSE_CHANNEL 0xca
22*4882a593Smuzhiyun #define QT_SET_GET_DEVICE 0xc2
23*4882a593Smuzhiyun #define QT_SET_GET_REGISTER 0xc0
24*4882a593Smuzhiyun #define QT_GET_SET_PREBUF_TRIG_LVL 0xcc
25*4882a593Smuzhiyun #define QT_SET_ATF 0xcd
26*4882a593Smuzhiyun #define QT_GET_SET_UART 0xc1
27*4882a593Smuzhiyun #define QT_TRANSFER_IN 0xc0
28*4882a593Smuzhiyun #define QT_HW_FLOW_CONTROL_MASK 0xc5
29*4882a593Smuzhiyun #define QT_SW_FLOW_CONTROL_MASK 0xc6
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun #define SERIAL_MSR_MASK 0xf0
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #define SERIAL_CRTSCTS ((UART_MCR_RTS << 8) | UART_MSR_CTS)
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #define SERIAL_EVEN_PARITY (UART_LCR_PARITY | UART_LCR_EPAR)
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun #define MAX_BAUD_RATE 460800
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #define ATC_DISABLED 0x00
40*4882a593Smuzhiyun #define DUPMODE_BITS 0xc0
41*4882a593Smuzhiyun #define RR_BITS 0x03
42*4882a593Smuzhiyun #define LOOPMODE_BITS 0x41
43*4882a593Smuzhiyun #define RS232_MODE 0x00
44*4882a593Smuzhiyun #define RTSCTS_TO_CONNECTOR 0x40
45*4882a593Smuzhiyun #define CLKS_X4 0x02
46*4882a593Smuzhiyun #define FULLPWRBIT 0x00000080
47*4882a593Smuzhiyun #define NEXT_BOARD_POWER_BIT 0x00000004
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun #define DRIVER_DESC "Quatech SSU-100 USB to Serial Driver"
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun #define USB_VENDOR_ID_QUATECH 0x061d /* Quatech VID */
52*4882a593Smuzhiyun #define QUATECH_SSU100 0xC020 /* SSU100 */
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun static const struct usb_device_id id_table[] = {
55*4882a593Smuzhiyun {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU100)},
56*4882a593Smuzhiyun {} /* Terminating entry */
57*4882a593Smuzhiyun };
58*4882a593Smuzhiyun MODULE_DEVICE_TABLE(usb, id_table);
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun struct ssu100_port_private {
61*4882a593Smuzhiyun spinlock_t status_lock;
62*4882a593Smuzhiyun u8 shadowLSR;
63*4882a593Smuzhiyun u8 shadowMSR;
64*4882a593Smuzhiyun };
65*4882a593Smuzhiyun
ssu100_control_msg(struct usb_device * dev,u8 request,u16 data,u16 index)66*4882a593Smuzhiyun static inline int ssu100_control_msg(struct usb_device *dev,
67*4882a593Smuzhiyun u8 request, u16 data, u16 index)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
70*4882a593Smuzhiyun request, 0x40, data, index,
71*4882a593Smuzhiyun NULL, 0, 300);
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun
ssu100_setdevice(struct usb_device * dev,u8 * data)74*4882a593Smuzhiyun static inline int ssu100_setdevice(struct usb_device *dev, u8 *data)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun u16 x = ((u16)(data[1] << 8) | (u16)(data[0]));
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun return ssu100_control_msg(dev, QT_SET_GET_DEVICE, x, 0);
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun
ssu100_getdevice(struct usb_device * dev,u8 * data)82*4882a593Smuzhiyun static inline int ssu100_getdevice(struct usb_device *dev, u8 *data)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun int ret;
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
87*4882a593Smuzhiyun QT_SET_GET_DEVICE, 0xc0, 0, 0,
88*4882a593Smuzhiyun data, 3, 300);
89*4882a593Smuzhiyun if (ret < 3) {
90*4882a593Smuzhiyun if (ret >= 0)
91*4882a593Smuzhiyun ret = -EIO;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun return ret;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
ssu100_getregister(struct usb_device * dev,unsigned short uart,unsigned short reg,u8 * data)97*4882a593Smuzhiyun static inline int ssu100_getregister(struct usb_device *dev,
98*4882a593Smuzhiyun unsigned short uart,
99*4882a593Smuzhiyun unsigned short reg,
100*4882a593Smuzhiyun u8 *data)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun int ret;
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
105*4882a593Smuzhiyun QT_SET_GET_REGISTER, 0xc0, reg,
106*4882a593Smuzhiyun uart, data, sizeof(*data), 300);
107*4882a593Smuzhiyun if (ret < (int)sizeof(*data)) {
108*4882a593Smuzhiyun if (ret >= 0)
109*4882a593Smuzhiyun ret = -EIO;
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun return ret;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun
ssu100_setregister(struct usb_device * dev,unsigned short uart,unsigned short reg,u16 data)116*4882a593Smuzhiyun static inline int ssu100_setregister(struct usb_device *dev,
117*4882a593Smuzhiyun unsigned short uart,
118*4882a593Smuzhiyun unsigned short reg,
119*4882a593Smuzhiyun u16 data)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun u16 value = (data << 8) | reg;
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
124*4882a593Smuzhiyun QT_SET_GET_REGISTER, 0x40, value, uart,
125*4882a593Smuzhiyun NULL, 0, 300);
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun #define set_mctrl(dev, set) update_mctrl((dev), (set), 0)
130*4882a593Smuzhiyun #define clear_mctrl(dev, clear) update_mctrl((dev), 0, (clear))
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun /* these do not deal with device that have more than 1 port */
update_mctrl(struct usb_device * dev,unsigned int set,unsigned int clear)133*4882a593Smuzhiyun static inline int update_mctrl(struct usb_device *dev, unsigned int set,
134*4882a593Smuzhiyun unsigned int clear)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun unsigned urb_value;
137*4882a593Smuzhiyun int result;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) {
140*4882a593Smuzhiyun dev_dbg(&dev->dev, "%s - DTR|RTS not being set|cleared\n", __func__);
141*4882a593Smuzhiyun return 0; /* no change */
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun clear &= ~set; /* 'set' takes precedence over 'clear' */
145*4882a593Smuzhiyun urb_value = 0;
146*4882a593Smuzhiyun if (set & TIOCM_DTR)
147*4882a593Smuzhiyun urb_value |= UART_MCR_DTR;
148*4882a593Smuzhiyun if (set & TIOCM_RTS)
149*4882a593Smuzhiyun urb_value |= UART_MCR_RTS;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun result = ssu100_setregister(dev, 0, UART_MCR, urb_value);
152*4882a593Smuzhiyun if (result < 0)
153*4882a593Smuzhiyun dev_dbg(&dev->dev, "%s Error from MODEM_CTRL urb\n", __func__);
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun return result;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
ssu100_initdevice(struct usb_device * dev)158*4882a593Smuzhiyun static int ssu100_initdevice(struct usb_device *dev)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun u8 *data;
161*4882a593Smuzhiyun int result = 0;
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun data = kzalloc(3, GFP_KERNEL);
164*4882a593Smuzhiyun if (!data)
165*4882a593Smuzhiyun return -ENOMEM;
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun result = ssu100_getdevice(dev, data);
168*4882a593Smuzhiyun if (result < 0) {
169*4882a593Smuzhiyun dev_dbg(&dev->dev, "%s - get_device failed %i\n", __func__, result);
170*4882a593Smuzhiyun goto out;
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun data[1] &= ~FULLPWRBIT;
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun result = ssu100_setdevice(dev, data);
176*4882a593Smuzhiyun if (result < 0) {
177*4882a593Smuzhiyun dev_dbg(&dev->dev, "%s - setdevice failed %i\n", __func__, result);
178*4882a593Smuzhiyun goto out;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun result = ssu100_control_msg(dev, QT_GET_SET_PREBUF_TRIG_LVL, 128, 0);
182*4882a593Smuzhiyun if (result < 0) {
183*4882a593Smuzhiyun dev_dbg(&dev->dev, "%s - set prebuffer level failed %i\n", __func__, result);
184*4882a593Smuzhiyun goto out;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun result = ssu100_control_msg(dev, QT_SET_ATF, ATC_DISABLED, 0);
188*4882a593Smuzhiyun if (result < 0) {
189*4882a593Smuzhiyun dev_dbg(&dev->dev, "%s - set ATFprebuffer level failed %i\n", __func__, result);
190*4882a593Smuzhiyun goto out;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun result = ssu100_getdevice(dev, data);
194*4882a593Smuzhiyun if (result < 0) {
195*4882a593Smuzhiyun dev_dbg(&dev->dev, "%s - get_device failed %i\n", __func__, result);
196*4882a593Smuzhiyun goto out;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun data[0] &= ~(RR_BITS | DUPMODE_BITS);
200*4882a593Smuzhiyun data[0] |= CLKS_X4;
201*4882a593Smuzhiyun data[1] &= ~(LOOPMODE_BITS);
202*4882a593Smuzhiyun data[1] |= RS232_MODE;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun result = ssu100_setdevice(dev, data);
205*4882a593Smuzhiyun if (result < 0) {
206*4882a593Smuzhiyun dev_dbg(&dev->dev, "%s - setdevice failed %i\n", __func__, result);
207*4882a593Smuzhiyun goto out;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun out: kfree(data);
211*4882a593Smuzhiyun return result;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun
ssu100_set_termios(struct tty_struct * tty,struct usb_serial_port * port,struct ktermios * old_termios)216*4882a593Smuzhiyun static void ssu100_set_termios(struct tty_struct *tty,
217*4882a593Smuzhiyun struct usb_serial_port *port,
218*4882a593Smuzhiyun struct ktermios *old_termios)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun struct usb_device *dev = port->serial->dev;
221*4882a593Smuzhiyun struct ktermios *termios = &tty->termios;
222*4882a593Smuzhiyun u16 baud, divisor, remainder;
223*4882a593Smuzhiyun unsigned int cflag = termios->c_cflag;
224*4882a593Smuzhiyun u16 urb_value = 0; /* will hold the new flags */
225*4882a593Smuzhiyun int result;
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun if (cflag & PARENB) {
228*4882a593Smuzhiyun if (cflag & PARODD)
229*4882a593Smuzhiyun urb_value |= UART_LCR_PARITY;
230*4882a593Smuzhiyun else
231*4882a593Smuzhiyun urb_value |= SERIAL_EVEN_PARITY;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun switch (cflag & CSIZE) {
235*4882a593Smuzhiyun case CS5:
236*4882a593Smuzhiyun urb_value |= UART_LCR_WLEN5;
237*4882a593Smuzhiyun break;
238*4882a593Smuzhiyun case CS6:
239*4882a593Smuzhiyun urb_value |= UART_LCR_WLEN6;
240*4882a593Smuzhiyun break;
241*4882a593Smuzhiyun case CS7:
242*4882a593Smuzhiyun urb_value |= UART_LCR_WLEN7;
243*4882a593Smuzhiyun break;
244*4882a593Smuzhiyun default:
245*4882a593Smuzhiyun case CS8:
246*4882a593Smuzhiyun urb_value |= UART_LCR_WLEN8;
247*4882a593Smuzhiyun break;
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun baud = tty_get_baud_rate(tty);
251*4882a593Smuzhiyun if (!baud)
252*4882a593Smuzhiyun baud = 9600;
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun dev_dbg(&port->dev, "%s - got baud = %d\n", __func__, baud);
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun divisor = MAX_BAUD_RATE / baud;
258*4882a593Smuzhiyun remainder = MAX_BAUD_RATE % baud;
259*4882a593Smuzhiyun if (((remainder * 2) >= baud) && (baud != 110))
260*4882a593Smuzhiyun divisor++;
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun urb_value = urb_value << 8;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun result = ssu100_control_msg(dev, QT_GET_SET_UART, divisor, urb_value);
265*4882a593Smuzhiyun if (result < 0)
266*4882a593Smuzhiyun dev_dbg(&port->dev, "%s - set uart failed\n", __func__);
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun if (cflag & CRTSCTS)
269*4882a593Smuzhiyun result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
270*4882a593Smuzhiyun SERIAL_CRTSCTS, 0);
271*4882a593Smuzhiyun else
272*4882a593Smuzhiyun result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK,
273*4882a593Smuzhiyun 0, 0);
274*4882a593Smuzhiyun if (result < 0)
275*4882a593Smuzhiyun dev_dbg(&port->dev, "%s - set HW flow control failed\n", __func__);
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun if (I_IXOFF(tty) || I_IXON(tty)) {
278*4882a593Smuzhiyun u16 x = ((u16)(START_CHAR(tty) << 8) | (u16)(STOP_CHAR(tty)));
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
281*4882a593Smuzhiyun x, 0);
282*4882a593Smuzhiyun } else
283*4882a593Smuzhiyun result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK,
284*4882a593Smuzhiyun 0, 0);
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun if (result < 0)
287*4882a593Smuzhiyun dev_dbg(&port->dev, "%s - set SW flow control failed\n", __func__);
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun
ssu100_open(struct tty_struct * tty,struct usb_serial_port * port)292*4882a593Smuzhiyun static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun struct usb_device *dev = port->serial->dev;
295*4882a593Smuzhiyun struct ssu100_port_private *priv = usb_get_serial_port_data(port);
296*4882a593Smuzhiyun u8 *data;
297*4882a593Smuzhiyun int result;
298*4882a593Smuzhiyun unsigned long flags;
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun data = kzalloc(2, GFP_KERNEL);
301*4882a593Smuzhiyun if (!data)
302*4882a593Smuzhiyun return -ENOMEM;
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
305*4882a593Smuzhiyun QT_OPEN_CLOSE_CHANNEL,
306*4882a593Smuzhiyun QT_TRANSFER_IN, 0x01,
307*4882a593Smuzhiyun 0, data, 2, 300);
308*4882a593Smuzhiyun if (result < 2) {
309*4882a593Smuzhiyun dev_dbg(&port->dev, "%s - open failed %i\n", __func__, result);
310*4882a593Smuzhiyun if (result >= 0)
311*4882a593Smuzhiyun result = -EIO;
312*4882a593Smuzhiyun kfree(data);
313*4882a593Smuzhiyun return result;
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun spin_lock_irqsave(&priv->status_lock, flags);
317*4882a593Smuzhiyun priv->shadowLSR = data[0];
318*4882a593Smuzhiyun priv->shadowMSR = data[1];
319*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->status_lock, flags);
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun kfree(data);
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun /* set to 9600 */
324*4882a593Smuzhiyun result = ssu100_control_msg(dev, QT_GET_SET_UART, 0x30, 0x0300);
325*4882a593Smuzhiyun if (result < 0)
326*4882a593Smuzhiyun dev_dbg(&port->dev, "%s - set uart failed\n", __func__);
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun if (tty)
329*4882a593Smuzhiyun ssu100_set_termios(tty, port, &tty->termios);
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun return usb_serial_generic_open(tty, port);
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun
get_serial_info(struct tty_struct * tty,struct serial_struct * ss)334*4882a593Smuzhiyun static int get_serial_info(struct tty_struct *tty,
335*4882a593Smuzhiyun struct serial_struct *ss)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun struct usb_serial_port *port = tty->driver_data;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun ss->line = port->minor;
340*4882a593Smuzhiyun ss->port = 0;
341*4882a593Smuzhiyun ss->irq = 0;
342*4882a593Smuzhiyun ss->xmit_fifo_size = port->bulk_out_size;
343*4882a593Smuzhiyun ss->baud_base = 9600;
344*4882a593Smuzhiyun ss->close_delay = 5*HZ;
345*4882a593Smuzhiyun ss->closing_wait = 30*HZ;
346*4882a593Smuzhiyun return 0;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun
ssu100_attach(struct usb_serial * serial)349*4882a593Smuzhiyun static int ssu100_attach(struct usb_serial *serial)
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun return ssu100_initdevice(serial->dev);
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun
ssu100_port_probe(struct usb_serial_port * port)354*4882a593Smuzhiyun static int ssu100_port_probe(struct usb_serial_port *port)
355*4882a593Smuzhiyun {
356*4882a593Smuzhiyun struct ssu100_port_private *priv;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun priv = kzalloc(sizeof(*priv), GFP_KERNEL);
359*4882a593Smuzhiyun if (!priv)
360*4882a593Smuzhiyun return -ENOMEM;
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun spin_lock_init(&priv->status_lock);
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun usb_set_serial_port_data(port, priv);
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun return 0;
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun
ssu100_port_remove(struct usb_serial_port * port)369*4882a593Smuzhiyun static int ssu100_port_remove(struct usb_serial_port *port)
370*4882a593Smuzhiyun {
371*4882a593Smuzhiyun struct ssu100_port_private *priv;
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun priv = usb_get_serial_port_data(port);
374*4882a593Smuzhiyun kfree(priv);
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun return 0;
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun
ssu100_tiocmget(struct tty_struct * tty)379*4882a593Smuzhiyun static int ssu100_tiocmget(struct tty_struct *tty)
380*4882a593Smuzhiyun {
381*4882a593Smuzhiyun struct usb_serial_port *port = tty->driver_data;
382*4882a593Smuzhiyun struct usb_device *dev = port->serial->dev;
383*4882a593Smuzhiyun u8 *d;
384*4882a593Smuzhiyun int r;
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun d = kzalloc(2, GFP_KERNEL);
387*4882a593Smuzhiyun if (!d)
388*4882a593Smuzhiyun return -ENOMEM;
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun r = ssu100_getregister(dev, 0, UART_MCR, d);
391*4882a593Smuzhiyun if (r < 0)
392*4882a593Smuzhiyun goto mget_out;
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun r = ssu100_getregister(dev, 0, UART_MSR, d+1);
395*4882a593Smuzhiyun if (r < 0)
396*4882a593Smuzhiyun goto mget_out;
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun r = (d[0] & UART_MCR_DTR ? TIOCM_DTR : 0) |
399*4882a593Smuzhiyun (d[0] & UART_MCR_RTS ? TIOCM_RTS : 0) |
400*4882a593Smuzhiyun (d[1] & UART_MSR_CTS ? TIOCM_CTS : 0) |
401*4882a593Smuzhiyun (d[1] & UART_MSR_DCD ? TIOCM_CAR : 0) |
402*4882a593Smuzhiyun (d[1] & UART_MSR_RI ? TIOCM_RI : 0) |
403*4882a593Smuzhiyun (d[1] & UART_MSR_DSR ? TIOCM_DSR : 0);
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun mget_out:
406*4882a593Smuzhiyun kfree(d);
407*4882a593Smuzhiyun return r;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun
ssu100_tiocmset(struct tty_struct * tty,unsigned int set,unsigned int clear)410*4882a593Smuzhiyun static int ssu100_tiocmset(struct tty_struct *tty,
411*4882a593Smuzhiyun unsigned int set, unsigned int clear)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun struct usb_serial_port *port = tty->driver_data;
414*4882a593Smuzhiyun struct usb_device *dev = port->serial->dev;
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun return update_mctrl(dev, set, clear);
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun
ssu100_dtr_rts(struct usb_serial_port * port,int on)419*4882a593Smuzhiyun static void ssu100_dtr_rts(struct usb_serial_port *port, int on)
420*4882a593Smuzhiyun {
421*4882a593Smuzhiyun struct usb_device *dev = port->serial->dev;
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun /* Disable flow control */
424*4882a593Smuzhiyun if (!on) {
425*4882a593Smuzhiyun if (ssu100_setregister(dev, 0, UART_MCR, 0) < 0)
426*4882a593Smuzhiyun dev_err(&port->dev, "error from flowcontrol urb\n");
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun /* drop RTS and DTR */
429*4882a593Smuzhiyun if (on)
430*4882a593Smuzhiyun set_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
431*4882a593Smuzhiyun else
432*4882a593Smuzhiyun clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun
ssu100_update_msr(struct usb_serial_port * port,u8 msr)435*4882a593Smuzhiyun static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)
436*4882a593Smuzhiyun {
437*4882a593Smuzhiyun struct ssu100_port_private *priv = usb_get_serial_port_data(port);
438*4882a593Smuzhiyun unsigned long flags;
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun spin_lock_irqsave(&priv->status_lock, flags);
441*4882a593Smuzhiyun priv->shadowMSR = msr;
442*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->status_lock, flags);
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun if (msr & UART_MSR_ANY_DELTA) {
445*4882a593Smuzhiyun /* update input line counters */
446*4882a593Smuzhiyun if (msr & UART_MSR_DCTS)
447*4882a593Smuzhiyun port->icount.cts++;
448*4882a593Smuzhiyun if (msr & UART_MSR_DDSR)
449*4882a593Smuzhiyun port->icount.dsr++;
450*4882a593Smuzhiyun if (msr & UART_MSR_DDCD)
451*4882a593Smuzhiyun port->icount.dcd++;
452*4882a593Smuzhiyun if (msr & UART_MSR_TERI)
453*4882a593Smuzhiyun port->icount.rng++;
454*4882a593Smuzhiyun wake_up_interruptible(&port->port.delta_msr_wait);
455*4882a593Smuzhiyun }
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun
ssu100_update_lsr(struct usb_serial_port * port,u8 lsr,char * tty_flag)458*4882a593Smuzhiyun static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr,
459*4882a593Smuzhiyun char *tty_flag)
460*4882a593Smuzhiyun {
461*4882a593Smuzhiyun struct ssu100_port_private *priv = usb_get_serial_port_data(port);
462*4882a593Smuzhiyun unsigned long flags;
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun spin_lock_irqsave(&priv->status_lock, flags);
465*4882a593Smuzhiyun priv->shadowLSR = lsr;
466*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->status_lock, flags);
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun *tty_flag = TTY_NORMAL;
469*4882a593Smuzhiyun if (lsr & UART_LSR_BRK_ERROR_BITS) {
470*4882a593Smuzhiyun /* we always want to update icount, but we only want to
471*4882a593Smuzhiyun * update tty_flag for one case */
472*4882a593Smuzhiyun if (lsr & UART_LSR_BI) {
473*4882a593Smuzhiyun port->icount.brk++;
474*4882a593Smuzhiyun *tty_flag = TTY_BREAK;
475*4882a593Smuzhiyun usb_serial_handle_break(port);
476*4882a593Smuzhiyun }
477*4882a593Smuzhiyun if (lsr & UART_LSR_PE) {
478*4882a593Smuzhiyun port->icount.parity++;
479*4882a593Smuzhiyun if (*tty_flag == TTY_NORMAL)
480*4882a593Smuzhiyun *tty_flag = TTY_PARITY;
481*4882a593Smuzhiyun }
482*4882a593Smuzhiyun if (lsr & UART_LSR_FE) {
483*4882a593Smuzhiyun port->icount.frame++;
484*4882a593Smuzhiyun if (*tty_flag == TTY_NORMAL)
485*4882a593Smuzhiyun *tty_flag = TTY_FRAME;
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun if (lsr & UART_LSR_OE) {
488*4882a593Smuzhiyun port->icount.overrun++;
489*4882a593Smuzhiyun tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
ssu100_process_read_urb(struct urb * urb)495*4882a593Smuzhiyun static void ssu100_process_read_urb(struct urb *urb)
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun struct usb_serial_port *port = urb->context;
498*4882a593Smuzhiyun char *packet = urb->transfer_buffer;
499*4882a593Smuzhiyun char flag = TTY_NORMAL;
500*4882a593Smuzhiyun u32 len = urb->actual_length;
501*4882a593Smuzhiyun int i;
502*4882a593Smuzhiyun char *ch;
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun if ((len >= 4) &&
505*4882a593Smuzhiyun (packet[0] == 0x1b) && (packet[1] == 0x1b) &&
506*4882a593Smuzhiyun ((packet[2] == 0x00) || (packet[2] == 0x01))) {
507*4882a593Smuzhiyun if (packet[2] == 0x00)
508*4882a593Smuzhiyun ssu100_update_lsr(port, packet[3], &flag);
509*4882a593Smuzhiyun if (packet[2] == 0x01)
510*4882a593Smuzhiyun ssu100_update_msr(port, packet[3]);
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun len -= 4;
513*4882a593Smuzhiyun ch = packet + 4;
514*4882a593Smuzhiyun } else
515*4882a593Smuzhiyun ch = packet;
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun if (!len)
518*4882a593Smuzhiyun return; /* status only */
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun if (port->sysrq) {
521*4882a593Smuzhiyun for (i = 0; i < len; i++, ch++) {
522*4882a593Smuzhiyun if (!usb_serial_handle_sysrq_char(port, *ch))
523*4882a593Smuzhiyun tty_insert_flip_char(&port->port, *ch, flag);
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun } else {
526*4882a593Smuzhiyun tty_insert_flip_string_fixed_flag(&port->port, ch, flag, len);
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun tty_flip_buffer_push(&port->port);
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun static struct usb_serial_driver ssu100_device = {
533*4882a593Smuzhiyun .driver = {
534*4882a593Smuzhiyun .owner = THIS_MODULE,
535*4882a593Smuzhiyun .name = "ssu100",
536*4882a593Smuzhiyun },
537*4882a593Smuzhiyun .description = DRIVER_DESC,
538*4882a593Smuzhiyun .id_table = id_table,
539*4882a593Smuzhiyun .num_ports = 1,
540*4882a593Smuzhiyun .open = ssu100_open,
541*4882a593Smuzhiyun .attach = ssu100_attach,
542*4882a593Smuzhiyun .port_probe = ssu100_port_probe,
543*4882a593Smuzhiyun .port_remove = ssu100_port_remove,
544*4882a593Smuzhiyun .dtr_rts = ssu100_dtr_rts,
545*4882a593Smuzhiyun .process_read_urb = ssu100_process_read_urb,
546*4882a593Smuzhiyun .tiocmget = ssu100_tiocmget,
547*4882a593Smuzhiyun .tiocmset = ssu100_tiocmset,
548*4882a593Smuzhiyun .tiocmiwait = usb_serial_generic_tiocmiwait,
549*4882a593Smuzhiyun .get_icount = usb_serial_generic_get_icount,
550*4882a593Smuzhiyun .get_serial = get_serial_info,
551*4882a593Smuzhiyun .set_termios = ssu100_set_termios,
552*4882a593Smuzhiyun };
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun static struct usb_serial_driver * const serial_drivers[] = {
555*4882a593Smuzhiyun &ssu100_device, NULL
556*4882a593Smuzhiyun };
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun module_usb_serial_driver(serial_drivers, id_table);
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun MODULE_DESCRIPTION(DRIVER_DESC);
561*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
562