xref: /OK3568_Linux_fs/kernel/drivers/usb/serial/ssu100.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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