1d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/*
2d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * This code was developed for the Quatech USB line for linux, it used
3d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * much of the code developed by Greg Kroah-Hartman for USB serial devices
4d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton *
5d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton */
6d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
7d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/errno.h>
8d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/init.h>
9d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/slab.h>
10d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/tty.h>
11d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/tty_driver.h>
12d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/tty_flip.h>
13d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/module.h>
14d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/serial.h>
15d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/usb.h>
16d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/usb/serial.h>
17d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/uaccess.h>
18d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1990ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool debug;
20d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
21d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/* Version Information */
22d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DRIVER_VERSION "v2.14"
23d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DRIVER_AUTHOR "Tim Gobeli, Quatech, Inc"
24d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DRIVER_DESC "Quatech USB to Serial Driver"
25d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
26d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define	USB_VENDOR_ID_QUATECH			0x061d	/* Quatech VID */
27d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_SSU200	0xC030	/* SSU200 */
28d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_DSU100	0xC040	/* DSU100 */
29d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_DSU200	0xC050	/* DSU200 */
30d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_QSU100	0xC060	/* QSU100 */
31d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_QSU200	0xC070	/* QSU200 */
32d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_ESU100A	0xC080	/* ESU100A */
33d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_ESU100B	0xC081	/* ESU100B */
34d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_ESU200A	0xC0A0	/* ESU200A */
35d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_ESU200B	0xC0A1	/* ESU200B */
36d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU100A	0xC090	/* HSU100A */
37d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU100B	0xC091	/* HSU100B */
38d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU100C	0xC092	/* HSU100C */
39d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU100D	0xC093	/* HSU100D */
40d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU200A	0xC0B0	/* HSU200A */
41d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU200B	0xC0B1	/* HSU200B */
42d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU200C	0xC0B2	/* HSU200C */
43d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU200D	0xC0B3	/* HSU200D */
44d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_SSU100_2  0xC120	/* SSU100_2 */
45d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_DSU100_2  0xC140	/* DSU100_2 */
46d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_DSU400_2  0xC150	/* DSU400_2 */
47d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_QSU100_2  0xC160	/* QSU100_2 */
48d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_QSU400_2  0xC170	/* QSU400_2 */
49d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_ESU400_2  0xC180	/* ESU400_2 */
50d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_ESU100_2  0xC1A0	/* ESU100_2 */
51d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
52d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_SET_GET_DEVICE           0xc2
53d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_OPEN_CLOSE_CHANNEL       0xca
54d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_GET_SET_PREBUF_TRIG_LVL  0xcc
55d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_SET_ATF                  0xcd
56d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_GET_SET_REGISTER         0xc0
57d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_GET_SET_UART             0xc1
58d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_HW_FLOW_CONTROL_MASK     0xc5
59d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_SW_FLOW_CONTROL_MASK     0xc6
60d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_SW_FLOW_CONTROL_DISABLE  0xc7
61d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_BREAK_CONTROL            0xc8
62d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
63d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define USBD_TRANSFER_DIRECTION_IN    0xc0
64d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define USBD_TRANSFER_DIRECTION_OUT   0x40
65d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
66d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  MAX_BAUD_RATE              460800
67d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  MAX_BAUD_REMAINDER         4608
68d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
69d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  DIV_LATCH_LS               0x00
70d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  XMT_HOLD_REGISTER          0x00
71d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  XVR_BUFFER_REGISTER        0x00
72d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  DIV_LATCH_MS               0x01
73d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  FIFO_CONTROL_REGISTER      0x02
74d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  LINE_CONTROL_REGISTER      0x03
75d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  MODEM_CONTROL_REGISTER     0x04
76d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  LINE_STATUS_REGISTER       0x05
77d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  MODEM_STATUS_REGISTER      0x06
78d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
79d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MCR_DTR             0x01
80d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MCR_RTS             0x02
81d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MCR_LOOP            0x10
82d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
83d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_CTS             0x10
84d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_CD              0x80
85d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_RI              0x40
86d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_DSR             0x20
87d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_MASK            0xf0
88d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
89d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_8_DATA              0x03
90d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_7_DATA              0x02
91d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_6_DATA              0x01
92d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_5_DATA              0x00
93d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
94d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_ODD_PARITY          0X08
95d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_EVEN_PARITY         0X18
96d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_TWO_STOPB           0x04
97d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_ONE_STOPB           0x00
98d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
99d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DEFAULT_DIVISOR  0x30	/* gives 9600 baud rate */
100d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DEFAULT_LCR SERIAL_8_DATA	/* 8, none , 1 */
101d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
102d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define FULLPWRBIT          0x00000080
103d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define NEXT_BOARD_POWER_BIT        0x00000004
104d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
105d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_LSR_OE       0x02
106d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_LSR_PE       0x04
107d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_LSR_FE       0x08
108d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_LSR_BI       0x10
109d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
110d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_CTS             0x10
111d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_CD              0x80
112d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_RI              0x40
113d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_DSR             0x20
114d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define  SERIAL_MSR_MASK            0xf0
115d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
116d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define PREFUFF_LEVEL_CONSERVATIVE  128
117d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define ATC_DISABLED                0x0
118d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
119d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define RR_BITS             0x03	/* for clearing clock bits */
120d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DUPMODE_BITS        0xc0
121d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define CLKS_X4             0x02
122d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
123d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define LOOPMODE_BITS       0x41	/* LOOP1 = b6, LOOP0 = b0 (PORT B) */
124d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define ALL_LOOPBACK        0x01
125d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define MODEM_CTRL          0x40
126d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define RS232_MODE          0x00
127d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
128a457732b836b970c82c7ba35b4cfc938c9c543f9Németh Mártonstatic const struct usb_device_id serqt_id_table[] = {
129d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU200)},
130d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU100)},
131d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU200)},
132d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU100)},
133d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU200)},
134d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU100A)},
135d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU100B)},
136d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU200A)},
137d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU200B)},
138d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100A)},
139d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100B)},
140d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100C)},
141d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100D)},
142d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200A)},
143d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200B)},
144d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200C)},
145d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200D)},
146d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU100_2)},
147d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU100_2)},
148d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU400_2)},
149d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU100_2)},
150d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU400_2)},
151d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU400_2)},
152d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU100_2)},
153d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	{}			/* Terminating entry */
154d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton};
155d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
156d75662e164d5175c5e5f9339ff4d6f6980613d96Bill PembertonMODULE_DEVICE_TABLE(usb, serqt_id_table);
157d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
158d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstruct qt_get_device_data {
159d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 porta;
160d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 portb;
161d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 portc;
162d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton};
163d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
164d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstruct qt_open_channel_data {
165d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 line_status;
166d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 modem_status;
167d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton};
168d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
169d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstruct quatech_port {
170d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int port_num;		/* number of the port */
171d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct urb *write_urb;	/* write URB for this port */
172d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct urb *read_urb;	/* read URB for this port */
173d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct urb *int_urb;
174d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
175d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 shadowLCR;		/* last LCR value received */
176d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 shadowMCR;		/* last MCR value received */
177d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 shadowMSR;		/* last MSR value received */
178d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 shadowLSR;		/* last LSR value received */
179d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	char open_ports;
180d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
181d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Used for TIOCMIWAIT */
182d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	wait_queue_head_t msr_wait;
183d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	char prev_status, diff_status;
184d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
185d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	wait_queue_head_t wait;
186d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
187d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct async_icount icount;
188d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
189d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port;	/* owner of this object */
190d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct qt_get_device_data DeviceData;
191fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov	struct mutex lock;
192d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	bool read_urb_busy;
193d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int RxHolding;
194d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int ReadBulkStopped;
195d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	char closePending;
196d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton};
197d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
198d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic struct usb_driver serqt_usb_driver = {
199d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.name = "quatech-usb-serial",
200d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.probe = usb_serial_probe,
201d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.disconnect = usb_serial_disconnect,
202d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.id_table = serqt_id_table,
203d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton};
204d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
205d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int port_paranoia_check(struct usb_serial_port *port,
206d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			       const char *function)
207d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
208d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!port) {
209d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - port == NULL", function);
210d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -1;
211d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
212d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!port->serial) {
213d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - port->serial == NULL\n", function);
214d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -1;
215d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
216d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
217d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return 0;
218d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
219d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
220d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int serial_paranoia_check(struct usb_serial *serial,
221d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 const char *function)
222d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
223d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!serial) {
224d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - serial == NULL\n", function);
225d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -1;
226d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
227d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
228d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!serial->type) {
229d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - serial->type == NULL!", function);
230d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -1;
231d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
232d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
233d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return 0;
234d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
235d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
236d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic inline struct quatech_port *qt_get_port_private(struct usb_serial_port
237d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton						       *port)
238d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
239d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return (struct quatech_port *)usb_get_serial_port_data(port);
240d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
241d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
242d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic inline void qt_set_port_private(struct usb_serial_port *port,
243d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				       struct quatech_port *data)
244d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
245d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	usb_set_serial_port_data(port, (void *)data);
246d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
247d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
248d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic struct usb_serial *get_usb_serial(struct usb_serial_port *port,
249d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					 const char *function)
250d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
251d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* if no port was specified, or it fails a paranoia check */
252d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!port ||
253d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    port_paranoia_check(port, function) ||
254d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    serial_paranoia_check(port->serial, function)) {
255d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/*
256d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		 * then say that we dont have a valid usb_serial thing,
257d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		 * which will end up genrating -ENODEV return values
258d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		 */
259d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return NULL;
260d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
261d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
262d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return port->serial;
263d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
264d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
265d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void ProcessLineStatus(struct quatech_port *qt_port,
266d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			      unsigned char line_status)
267d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
268d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
269d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	qt_port->shadowLSR =
270d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    line_status & (SERIAL_LSR_OE | SERIAL_LSR_PE | SERIAL_LSR_FE |
271d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			   SERIAL_LSR_BI);
272d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return;
273d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
274d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
275d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void ProcessModemStatus(struct quatech_port *qt_port,
276d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			       unsigned char modem_status)
277d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
278d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
279d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	qt_port->shadowMSR = modem_status;
280d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	wake_up_interruptible(&qt_port->wait);
281d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return;
282d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
283d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
28494362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Coxstatic void ProcessRxChar(struct tty_struct *tty, struct usb_serial_port *port,
28594362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox						unsigned char data)
286d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
287d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct urb *urb = port->read_urb;
28894362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox	if (urb->actual_length)
28994362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox		tty_insert_flip_char(tty, data, TTY_NORMAL);
290d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
291d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
292d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_write_bulk_callback(struct urb *urb)
293d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
294d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct tty_struct *tty;
295d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int status;
296d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *quatech_port;
297d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
298d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status = urb->status;
299d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
300d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status) {
301d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("nonzero write bulk status received:%d\n", status);
302d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return;
303d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
304d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
305d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	quatech_port = urb->context;
306d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
307d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, quatech_port->port_num);
308d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
309d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	tty = tty_port_tty_get(&quatech_port->port->port);
310d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
311d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (tty)
312d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		tty_wakeup(tty);
313d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	tty_kref_put(tty);
314d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
315d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
316d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_interrupt_callback(struct urb *urb)
317d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
318d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* FIXME */
319d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
320d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
321d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_read_bulk_callback(struct urb *urb)
322d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
323d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
324d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port = urb->context;
325d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial = get_usb_serial(port, __func__);
326d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port = qt_get_port_private(port);
327d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned char *data;
328d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct tty_struct *tty;
329d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int index;
330d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int RxCount;
331d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int i, result;
332d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int flag, flag_data;
333d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
334d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (urb->status) {
335d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_port->ReadBulkStopped = 1;
336d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - nonzero write bulk status received: %d\n",
337d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    __func__, urb->status);
338d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return;
339d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
340d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
341d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	tty = tty_port_tty_get(&port->port);
342d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!tty) {
343d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - bad tty pointer - exiting", __func__);
344d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return;
345d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
346d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
347d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	data = urb->transfer_buffer;
348d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
349d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	RxCount = urb->actual_length;
350d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
351d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* index = MINOR(port->tty->device) - serial->minor; */
352d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	index = tty->index - serial->minor;
353d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
354d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
355d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding);
356d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
357d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (port_paranoia_check(port, __func__) != 0) {
358d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - port_paranoia_check, exiting\n", __func__);
359d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_port->ReadBulkStopped = 1;
360f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton		goto exit;
361d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
362d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
363d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!serial) {
364d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - bad serial pointer, exiting\n", __func__);
365f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton		goto exit;
366d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
367d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (qt_port->closePending == 1) {
368d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* Were closing , stop reading */
369d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - (qt_port->closepending == 1\n", __func__);
370d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_port->ReadBulkStopped = 1;
371f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton		goto exit;
372d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
373d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
374d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/*
375d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 * RxHolding is asserted by throttle, if we assert it, we're not
376d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 * receiving any more characters and let the box handle the flow
377d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 * control
378d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 */
379d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (qt_port->RxHolding == 1) {
380d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_port->ReadBulkStopped = 1;
381f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton		goto exit;
382d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
383d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
384d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (urb->status) {
385d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_port->ReadBulkStopped = 1;
386d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
387d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - nonzero read bulk status received: %d\n",
388d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    __func__, urb->status);
389f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton		goto exit;
390d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
391d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
392d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (tty && RxCount) {
393d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		flag_data = 0;
394d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		for (i = 0; i < RxCount; ++i) {
395d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			/* Look ahead code here */
396d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			if ((i <= (RxCount - 3)) && (data[i] == 0x1b)
397d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    && (data[i + 1] == 0x1b)) {
398d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				flag = 0;
399d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				switch (data[i + 2]) {
400d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				case 0x00:
401d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					/* line status change 4th byte must follow */
402d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					if (i > (RxCount - 4)) {
403d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton						dbg("Illegal escape seuences in received data\n");
404d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton						break;
405d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					}
406d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					ProcessLineStatus(qt_port, data[i + 3]);
407d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					i += 3;
408d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					flag = 1;
409d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					break;
410d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
411d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				case 0x01:
412d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					/* Modem status status change 4th byte must follow */
4131695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev					dbg("Modem status status.\n");
414d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					if (i > (RxCount - 4)) {
415d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton						dbg("Illegal escape sequences in received data\n");
416d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton						break;
417d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					}
418d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					ProcessModemStatus(qt_port,
419d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton							   data[i + 3]);
420d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					i += 3;
421d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					flag = 1;
422d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					break;
423d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				case 0xff:
4241695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev					dbg("No status sequence.\n");
425d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
42694362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox					if (tty) {
42794362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox						ProcessRxChar(tty, port, data[i]);
42894362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox						ProcessRxChar(tty, port, data[i + 1]);
42994362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox					}
430d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					i += 2;
431d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					break;
432d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				}
433d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				if (flag == 1)
434d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					continue;
435d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			}
436d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
43794362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox			if (tty && urb->actual_length)
43894362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox				tty_insert_flip_char(tty, data[i], TTY_NORMAL);
439d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
440d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
441d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		tty_flip_buffer_push(tty);
442d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
443d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
444d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Continue trying to always read  */
445d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	usb_fill_bulk_urb(port->read_urb, serial->dev,
446d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  usb_rcvbulkpipe(serial->dev,
447d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					  port->bulk_in_endpointAddress),
448d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  port->read_urb->transfer_buffer,
449d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  port->read_urb->transfer_buffer_length,
450d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  qt_read_bulk_callback, port);
451d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
452d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (result)
453d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - failed resubmitting read urb, error %d",
454d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    __func__, result);
455d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	else {
456d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (tty && RxCount) {
457d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			tty_flip_buffer_push(tty);
458d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			tty_schedule_flip(tty);
459d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
460d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
461d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
462d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	schedule_work(&port->work);
463f3a756883ac028c536479e2eb283477fec80c828Bill Pembertonexit:
464f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton	tty_kref_put(tty);
465d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
466d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
467d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/*
468d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * qt_get_device
469d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton *   Issue a GET_DEVICE vendor-specific request on the default control pipe If
470d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton *   successful, fills in the qt_get_device_data structure pointed to by
471d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton *   device_data, otherwise return a negative error number of the problem.
472d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton */
473d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
474d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_get_device(struct usb_serial *serial,
475d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			 struct qt_get_device_data *device_data)
476d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
477d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
478d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned char *transfer_buffer;
479d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
480d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	transfer_buffer =
481d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    kmalloc(sizeof(struct qt_get_device_data), GFP_KERNEL);
482d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!transfer_buffer)
483d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ENOMEM;
484d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
485d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
486d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 QT_SET_GET_DEVICE, 0xc0, 0, 0,
487d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 transfer_buffer,
488d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 sizeof(struct qt_get_device_data), 300);
489d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (result > 0)
490d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		memcpy(device_data, transfer_buffer,
491d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		       sizeof(struct qt_get_device_data));
492d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	kfree(transfer_buffer);
493d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
494d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
495d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
496d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
497d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/****************************************************************************
498d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton *  BoxSetPrebufferLevel
499d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton   TELLS BOX WHEN TO ASSERT FLOW CONTROL
500d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton ****************************************************************************/
501d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxSetPrebufferLevel(struct usb_serial *serial)
502d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
503d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
504d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u16 buffer_length;
505d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
506d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	buffer_length = PREFUFF_LEVEL_CONSERVATIVE;
507d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
508d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 QT_GET_SET_PREBUF_TRIG_LVL, 0x40,
509d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 buffer_length, 0, NULL, 0, 300);
510d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
511d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
512d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
513d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/****************************************************************************
514d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton *  BoxSetATC
515d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton   TELLS BOX WHEN TO ASSERT automatic transmitter control
516d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton   ****************************************************************************/
517d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxSetATC(struct usb_serial *serial, __u16 n_Mode)
518d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
519d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
520d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u16 buffer_length;
521d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
522d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	buffer_length = PREFUFF_LEVEL_CONSERVATIVE;
523d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
524d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result =
525d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
526d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    QT_SET_ATF, 0x40, n_Mode, 0, NULL, 0, 300);
527d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
528d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
529d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
530d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
531d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/**
532d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * qt_set_device
533d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton *   Issue a SET_DEVICE vendor-specific request on the default control pipe If
534d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton *   successful returns the number of bytes written, otherwise it returns a
535d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton *   negative error number of the problem.
536d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton */
537d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_set_device(struct usb_serial *serial,
538d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			 struct qt_get_device_data *device_data)
539d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
540d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
541d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u16 length;
542d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u16 PortSettings;
543d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
544d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	PortSettings = ((__u16) (device_data->portb));
545d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	PortSettings = (PortSettings << 8);
546d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	PortSettings += ((__u16) (device_data->porta));
547d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
548d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	length = sizeof(struct qt_get_device_data);
549d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - PortSettings = 0x%x\n", __func__, PortSettings);
550d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
551d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
552d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 QT_SET_GET_DEVICE, 0x40, PortSettings,
553d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 0, NULL, 0, 300);
554d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
555d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
556d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
557d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_open_channel(struct usb_serial *serial, __u16 Uart_Number,
558d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			   struct qt_open_channel_data *pDeviceData)
559d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
560d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
561d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
562d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
563d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 QT_OPEN_CLOSE_CHANNEL,
564d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 USBD_TRANSFER_DIRECTION_IN, 1, Uart_Number,
565d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 pDeviceData,
566d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 sizeof(struct qt_open_channel_data), 300);
567d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
568d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
569d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
570d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
571d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
572d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_close_channel(struct usb_serial *serial, __u16 Uart_Number)
573d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
574d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
575d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
576d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
577d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 QT_OPEN_CLOSE_CHANNEL,
578d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 USBD_TRANSFER_DIRECTION_OUT, 0, Uart_Number,
579d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 NULL, 0, 300);
580d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
581d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
582d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
583d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
584d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
585d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/****************************************************************************
586d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton* BoxGetRegister
587d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton*	issuse a GET_REGISTER vendor-spcific request on the default control pipe
588d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton*	If successful, fills in the  pValue with the register value asked for
589d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton****************************************************************************/
590d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxGetRegister(struct usb_serial *serial, unsigned short Uart_Number,
591d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  unsigned short Register_Num, __u8 *pValue)
592d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
593d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
594d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u16 current_length;
595d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
596d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	current_length = sizeof(struct qt_get_device_data);
597d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
598d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result =
599d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
600d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    QT_GET_SET_REGISTER, 0xC0, Register_Num,
601d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    Uart_Number, (void *)pValue, sizeof(*pValue), 300);
602d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
603d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
604d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
605d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
606d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/****************************************************************************
607d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton* BoxSetRegister
608d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton*	issuse a GET_REGISTER vendor-spcific request on the default control pipe
609d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton*	If successful, fills in the  pValue with the register value asked for
610d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton****************************************************************************/
611d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxSetRegister(struct usb_serial *serial, unsigned short Uart_Number,
612d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  unsigned short Register_Num, unsigned short Value)
613d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
614d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
615d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned short RegAndByte;
616d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
617d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	RegAndByte = Value;
618d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	RegAndByte = RegAndByte << 8;
619d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	RegAndByte = RegAndByte + Register_Num;
620d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
621d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/*
622d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
623d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 QT_GET_SET_REGISTER, 0xC0, Register_Num,
624d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 Uart_Number, NULL, 0, 300);
625d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton*/
626d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
627d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result =
628d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
629d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    QT_GET_SET_REGISTER, 0x40, RegAndByte, Uart_Number,
630d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    NULL, 0, 300);
631d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
632d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
633d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
634d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
635d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/*
636d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * qt_setuart
637d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * issuse a SET_UART vendor-spcific request on the default control pipe
638d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * If successful sets baud rate divisor and LCR value
639d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton */
640d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_setuart(struct usb_serial *serial, unsigned short Uart_Number,
641d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		      unsigned short default_divisor, unsigned char default_LCR)
642d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
643d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
644d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned short UartNumandLCR;
645d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
646d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	UartNumandLCR = (default_LCR << 8) + Uart_Number;
647d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
648d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result =
649d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
650d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    QT_GET_SET_UART, 0x40, default_divisor,
651d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    UartNumandLCR, NULL, 0, 300);
652d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
653d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
654d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
655d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
656d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxSetHW_FlowCtrl(struct usb_serial *serial, unsigned int index,
657d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			     int bSet)
658d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
659d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 mcr = 0;
660d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u8 msr = 0, MOUT_Value = 0;
661d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int status;
662d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
663d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (bSet == 1) {
664d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* flow control, box will clear RTS line to prevent remote */
665d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		mcr = SERIAL_MCR_RTS;
666d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	} /* device from xmitting more chars */
667d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	else {
668d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* no flow control to remote device */
669d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		mcr = 0;
670d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
671d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
672d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	MOUT_Value = mcr << 8;
673d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
674d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (bSet == 1) {
675d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* flow control, box will inhibit xmit data if CTS line is
676d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		 * asserted */
677d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		msr = SERIAL_MSR_CTS;
678d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	} else {
679d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* Box will not inhimbe xmit data due to CTS line */
680d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		msr = 0;
681d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
682d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	MOUT_Value |= msr;
683d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
684d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status =
685d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
686d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    QT_HW_FLOW_CONTROL_MASK, 0x40, MOUT_Value,
687d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    index, NULL, 0, 300);
688d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return status;
689d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
690d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
691d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
692d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxSetSW_FlowCtrl(struct usb_serial *serial, __u16 index,
693d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			     unsigned char stop_char, unsigned char start_char)
694d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
695d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	__u16 nSWflowout;
696d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
697d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
698d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	nSWflowout = start_char << 8;
699d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	nSWflowout = (unsigned short)stop_char;
700d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
701d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result =
702d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
703d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    QT_SW_FLOW_CONTROL_MASK, 0x40, nSWflowout,
704d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    index, NULL, 0, 300);
705d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
706d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
707d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
708d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
709d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxDisable_SW_FlowCtrl(struct usb_serial *serial, __u16 index)
710d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
711d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
712d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
713d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result =
714d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
715d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    QT_SW_FLOW_CONTROL_DISABLE, 0x40, 0, index,
716d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    NULL, 0, 300);
717d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return result;
718d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
719d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
720d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
721d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_startup(struct usb_serial *serial)
722d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
723d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port;
724d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port;
725d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct qt_get_device_data DeviceData;
726d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int i;
727d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int status;
728d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
729d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("enterting %s", __func__);
730d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
731d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Now setup per port private data */
732d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	for (i = 0; i < serial->num_ports; i++) {
733d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		port = serial->port[i];
734d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_port = kzalloc(sizeof(*qt_port), GFP_KERNEL);
735d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (!qt_port) {
736d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			dbg("%s: kmalloc for quatech_port (%d) failed!.",
737d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    __func__, i);
7381695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev			for (--i; i >= 0; i--) {
739de8f8bd63334fe2014be7d9ab3a81ce9b96e5d19Oliver Neukum				port = serial->port[i];
740de8f8bd63334fe2014be7d9ab3a81ce9b96e5d19Oliver Neukum				kfree(usb_get_serial_port_data(port));
741de8f8bd63334fe2014be7d9ab3a81ce9b96e5d19Oliver Neukum				usb_set_serial_port_data(port, NULL);
742de8f8bd63334fe2014be7d9ab3a81ce9b96e5d19Oliver Neukum			}
743d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			return -ENOMEM;
744d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
745fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov		mutex_init(&qt_port->lock);
746d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
747d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		usb_set_serial_port_data(port, qt_port);
748d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
749d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
750d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
751d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status = qt_get_device(serial, &DeviceData);
752d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0) {
753d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg(__FILE__ "box_get_device failed");
754d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		goto startup_error;
755d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
756d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
757d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg(__FILE__ "DeviceData.portb = 0x%x", DeviceData.portb);
758d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
759d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	DeviceData.portb &= ~FULLPWRBIT;
760d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg(__FILE__ "Changing DeviceData.portb to 0x%x", DeviceData.portb);
761d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
762d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status = qt_set_device(serial, &DeviceData);
763d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0) {
764d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg(__FILE__ "qt_set_device failed\n");
765d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		goto startup_error;
766d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
767d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
768d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status = qt_get_device(serial, &DeviceData);
769d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0) {
770d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg(__FILE__ "qt_get_device failed");
771d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		goto startup_error;
772d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
773d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
774d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	switch (serial->dev->descriptor.idProduct) {
775d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_DSU100:
776d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_QSU100:
777d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_ESU100A:
778d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_ESU100B:
779d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_HSU100A:
780d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_HSU100B:
781d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_HSU100C:
782d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_HSU100D:
783d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS);
784d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.porta |= CLKS_X4;
785d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.portb &= ~(LOOPMODE_BITS);
786d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.portb |= RS232_MODE;
787d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		break;
788d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
789d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_SSU200:
790d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_DSU200:
791d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_QSU200:
792d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_ESU200A:
793d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_ESU200B:
794d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_HSU200A:
795d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_HSU200B:
796d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_HSU200C:
797d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case QUATECH_HSU200D:
798d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS);
799d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.porta |= CLKS_X4;
800d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.portb &= ~(LOOPMODE_BITS);
801d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.portb |= ALL_LOOPBACK;
802d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		break;
803d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	default:
804d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS);
805d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.porta |= CLKS_X4;
806d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.portb &= ~(LOOPMODE_BITS);
807d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		DeviceData.portb |= RS232_MODE;
808d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		break;
809d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
810d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
811d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
812d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status = BoxSetPrebufferLevel(serial);	/* sets to default value */
813d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0) {
814d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg(__FILE__ "BoxSetPrebufferLevel failed\n");
815d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		goto startup_error;
816d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
817d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
818d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status = BoxSetATC(serial, ATC_DISABLED);
819d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0) {
820d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg(__FILE__ "BoxSetATC failed\n");
821d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		goto startup_error;
822d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
823d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
824d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg(__FILE__ "DeviceData.portb = 0x%x", DeviceData.portb);
825d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
826d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	DeviceData.portb |= NEXT_BOARD_POWER_BIT;
827d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg(__FILE__ "Changing DeviceData.portb to 0x%x", DeviceData.portb);
828d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
829d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status = qt_set_device(serial, &DeviceData);
830d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0) {
831d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg(__FILE__ "qt_set_device failed\n");
832d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		goto startup_error;
833d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
834d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
835d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("Exit Success %s\n", __func__);
836d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
837d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return 0;
838d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
839d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstartup_error:
840d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	for (i = 0; i < serial->num_ports; i++) {
841d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		port = serial->port[i];
842d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_port = qt_get_port_private(port);
843d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		kfree(qt_port);
844d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		usb_set_serial_port_data(port, NULL);
845d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
846d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
847d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("Exit fail %s\n", __func__);
848d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
849d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return -EIO;
850d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
851d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
852d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_release(struct usb_serial *serial)
853d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
854d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port;
855d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port;
856d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int i;
857d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
858d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("enterting %s", __func__);
859d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
860d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	for (i = 0; i < serial->num_ports; i++) {
861d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		port = serial->port[i];
862d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (!port)
863d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			continue;
864d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
865d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_port = usb_get_serial_port_data(port);
866d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		kfree(qt_port);
867d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		usb_set_serial_port_data(port, NULL);
868d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
869d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
870d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
871d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
87235e2bed559ab80641f1764aae570d92711ddc2faBill Pembertonstatic int qt_open(struct tty_struct *tty,
8732386b331802b1b2664c35f9f4c7aef778aac725fBill Pemberton		   struct usb_serial_port *port)
874d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
875d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial;
876d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *quatech_port;
877d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *port0;
878d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct qt_open_channel_data ChannelData;
879d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
880d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
881d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
882d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (port_paranoia_check(port, __func__))
883d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ENODEV;
884d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
885d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
886d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
887d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	serial = port->serial;
888d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
889d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (serial_paranoia_check(serial, __func__))
890d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ENODEV;
891d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
892d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	quatech_port = qt_get_port_private(port);
893d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	port0 = qt_get_port_private(serial->port[0]);
894d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
895d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (quatech_port == NULL || port0 == NULL)
896d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ENODEV;
897d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
898d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	usb_clear_halt(serial->dev, port->write_urb->pipe);
899d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	usb_clear_halt(serial->dev, port->read_urb->pipe);
900d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	port0->open_ports++;
901d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
902d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = qt_get_device(serial, &port0->DeviceData);
903d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
904d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Port specific setups */
905d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = qt_open_channel(serial, port->number, &ChannelData);
906d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (result < 0) {
907d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg(__FILE__ "qt_open_channel failed\n");
908d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return result;
909d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
910d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg(__FILE__ "qt_open_channel completed.\n");
911d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
912d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/* FIXME: are these needed?  Does it even do anything useful? */
913d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	quatech_port->shadowLSR = ChannelData.line_status &
914d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    (SERIAL_LSR_OE | SERIAL_LSR_PE | SERIAL_LSR_FE | SERIAL_LSR_BI);
915d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
916d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	quatech_port->shadowMSR = ChannelData.modem_status &
917d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    (SERIAL_MSR_CTS | SERIAL_MSR_DSR | SERIAL_MSR_RI | SERIAL_MSR_CD);
918d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
919d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Set Baud rate to default and turn off (default)flow control here */
920d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = qt_setuart(serial, port->number, DEFAULT_DIVISOR, DEFAULT_LCR);
921d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (result < 0) {
922d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg(__FILE__ "qt_setuart failed\n");
923d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return result;
924d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
925d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg(__FILE__ "qt_setuart completed.\n");
926d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
927d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/*
928bbc9a9916bc1cd997f3bf303e7930d5f3c804d37André Goddard Rosa	 * Put this here to make it responsive to stty and defaults set by
929d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 * the tty layer
930d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 */
931d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* FIXME: is this needed? */
932d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* qt_set_termios(tty, port, NULL); */
933d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
934d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/*  Check to see if we've set up our endpoint info yet */
935d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (port0->open_ports == 1) {
936d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (serial->port[0]->interrupt_in_buffer == NULL) {
937d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			/* set up interrupt urb */
938d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			usb_fill_int_urb(serial->port[0]->interrupt_in_urb,
939d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					 serial->dev,
940d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					 usb_rcvintpipe(serial->dev,
941d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton							serial->port[0]->interrupt_in_endpointAddress),
942d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					 serial->port[0]->interrupt_in_buffer,
943d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					 serial->port[0]->
944d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					 interrupt_in_urb->transfer_buffer_length,
945d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					 qt_interrupt_callback, serial,
946d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					 serial->port[0]->
947d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					 interrupt_in_urb->interval);
948d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
949d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			result =
950d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    usb_submit_urb(serial->port[0]->interrupt_in_urb,
951d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					   GFP_KERNEL);
952d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			if (result) {
953d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				dev_err(&port->dev,
954d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					"%s - Error %d submitting "
955d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					"interrupt urb\n", __func__, result);
956d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			}
957d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
958d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
959d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
960d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
961d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
9621695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("port number is %d\n", port->number);
9631695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("serial number is %d\n", port->serial->minor);
9641695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("Bulkin endpoint is %d\n", port->bulk_in_endpointAddress);
9651695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("BulkOut endpoint is %d\n", port->bulk_out_endpointAddress);
9661695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("Interrupt endpoint is %d\n", port->interrupt_in_endpointAddress);
967d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("port's number in the device is %d\n", quatech_port->port_num);
968d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	quatech_port->read_urb = port->read_urb;
969d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
970d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* set up our bulk in urb */
971d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
972d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	usb_fill_bulk_urb(quatech_port->read_urb,
973d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  serial->dev,
974d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  usb_rcvbulkpipe(serial->dev,
975d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					  port->bulk_in_endpointAddress),
976d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  port->bulk_in_buffer,
977d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  quatech_port->read_urb->transfer_buffer_length,
978d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			  qt_read_bulk_callback, quatech_port);
979d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
980d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("qt_open: bulkin endpoint is %d\n", port->bulk_in_endpointAddress);
981d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	quatech_port->read_urb_busy = true;
982d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result = usb_submit_urb(quatech_port->read_urb, GFP_KERNEL);
983d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (result) {
984d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dev_err(&port->dev,
985d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			"%s - Error %d submitting control urb\n",
986d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			__func__, result);
987d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		quatech_port->read_urb_busy = false;
988d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
989d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
990d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* initialize our wait queues */
991d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	init_waitqueue_head(&quatech_port->wait);
992d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	init_waitqueue_head(&quatech_port->msr_wait);
993d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
994d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* initialize our icount structure */
995d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	memset(&(quatech_port->icount), 0x00, sizeof(quatech_port->icount));
996d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
997d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return 0;
998d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
999d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1000d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1001d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_chars_in_buffer(struct tty_struct *tty)
1002d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1003d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port = tty->driver_data;
1004d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial;
1005d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int chars = 0;
1006d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1007d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	serial = get_usb_serial(port, __func__);
1008d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1009d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
1010d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1011d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (serial->num_bulk_out) {
1012d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (port->write_urb->status == -EINPROGRESS)
1013d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			chars = port->write_urb->transfer_buffer_length;
1014d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1015d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1016d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - returns %d\n", __func__, chars);
1017d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1018d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return chars;
1019d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1020d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1021d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_block_until_empty(struct tty_struct *tty,
1022d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				 struct quatech_port *qt_port)
1023d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1024d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int timeout = HZ / 10;
1025d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int wait = 30;
1026d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int count;
1027d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1028d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	while (1) {
1029d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1030d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		count = qt_chars_in_buffer(tty);
1031d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1032d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (count <= 0)
1033d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			return;
1034d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1035d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		interruptible_sleep_on_timeout(&qt_port->wait, timeout);
1036d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1037d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		wait--;
1038d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (wait == 0) {
1039d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			dbg("%s - TIMEOUT", __func__);
1040d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			return;
1041d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		} else {
1042d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			wait = 30;
1043d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
1044d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1045d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1046d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1047f3a756883ac028c536479e2eb283477fec80c828Bill Pembertonstatic void qt_close(struct usb_serial_port *port)
1048d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1049d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial = port->serial;
1050d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port;
1051d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *port0;
1052d9dea3c1c0814a87cc579b425e9776b8ed46b31fBill Pemberton	struct tty_struct *tty;
1053d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int status;
1054d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int index;
1055d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status = 0;
1056d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1057d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
1058d9dea3c1c0814a87cc579b425e9776b8ed46b31fBill Pemberton
1059d9dea3c1c0814a87cc579b425e9776b8ed46b31fBill Pemberton	tty = tty_port_tty_get(&port->port);
1060d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	index = tty->index - serial->minor;
1061d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1062d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	qt_port = qt_get_port_private(port);
1063d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	port0 = qt_get_port_private(serial->port[0]);
1064d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1065d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* shutdown any bulk reads that might be going on */
1066d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (serial->num_bulk_out)
1067d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		usb_unlink_urb(port->write_urb);
1068d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (serial->num_bulk_in)
1069d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		usb_unlink_urb(port->read_urb);
1070d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1071d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* wait up to for transmitter to empty */
1072d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (serial->dev)
1073d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_block_until_empty(tty, qt_port);
1074f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton	tty_kref_put(tty);
1075d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1076d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Close uart channel */
1077d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status = qt_close_channel(serial, index);
1078d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0)
1079d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - port %d qt_close_channel failed.\n",
1080d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    __func__, port->number);
1081d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1082d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	port0->open_ports--;
1083d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1084d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("qt_num_open_ports in close%d:in port%d\n",
1085d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    port0->open_ports, port->number);
1086d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1087d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (port0->open_ports == 0) {
1088d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (serial->port[0]->interrupt_in_urb) {
1089d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			dbg("%s", "Shutdown interrupt_in_urb\n");
1090d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			usb_kill_urb(serial->port[0]->interrupt_in_urb);
1091d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
1092d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1093d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1094d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1095d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (qt_port->write_urb) {
1096d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* if this urb had a transfer buffer already (old tx) free it */
1097ef055f10000c5013d269cac9fc92c200bf314e40Ilia Mirkin		kfree(qt_port->write_urb->transfer_buffer);
1098d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		usb_free_urb(qt_port->write_urb);
1099d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1100d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1101d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1102d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1103d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_write(struct tty_struct *tty, struct usb_serial_port *port,
1104d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    const unsigned char *buf, int count)
1105d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1106d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int result;
1107d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial = get_usb_serial(port, __func__);
1108d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1109d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (serial == NULL)
1110d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ENODEV;
1111d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1112d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
1113d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1114d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (count == 0) {
1115d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - write request of 0 bytes\n", __func__);
1116d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return 0;
1117d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1118d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1119d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* only do something if we have a bulk out endpoint */
1120d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (serial->num_bulk_out) {
1121d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (port->write_urb->status == -EINPROGRESS) {
1122d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			dbg("%s - already writing\n", __func__);
1123d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			return 0;
1124d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
1125d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1126d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		count =
1127d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    (count > port->bulk_out_size) ? port->bulk_out_size : count;
1128d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		memcpy(port->write_urb->transfer_buffer, buf, count);
1129d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1130d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* set up our urb */
1131d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1132d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		usb_fill_bulk_urb(port->write_urb, serial->dev,
1133d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				  usb_sndbulkpipe(serial->dev,
1134d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton						  port->
1135d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton						  bulk_out_endpointAddress),
1136d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				  port->write_urb->transfer_buffer, count,
1137d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				  qt_write_bulk_callback, port);
1138d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1139d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* send the data out the bulk port */
1140d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
1141d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (result)
1142d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			dbg("%s - failed submitting write urb, error %d\n",
1143d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    __func__, result);
1144d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		else
1145d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			result = count;
1146d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1147d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return result;
1148d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1149d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1150d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* no bulk out, so return 0 bytes written */
1151d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return 0;
1152d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1153d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1154d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_write_room(struct tty_struct *tty)
1155d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1156d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port = tty->driver_data;
1157d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial;
1158d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port;
1159d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1160d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int retval = -EINVAL;
1161d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1162d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (port_paranoia_check(port, __func__)) {
1163d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s", "Invalid port\n");
1164d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -1;
1165d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1166d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1167d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	serial = get_usb_serial(port, __func__);
1168d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1169d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!serial)
1170d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ENODEV;
1171d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1172d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	qt_port = qt_get_port_private(port);
1173d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1174fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov	mutex_lock(&qt_port->lock);
1175d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1176d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
1177d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1178d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (serial->num_bulk_out) {
1179d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (port->write_urb->status != -EINPROGRESS)
1180d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			retval = port->bulk_out_size;
1181d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1182d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1183fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov	mutex_unlock(&qt_port->lock);
1184d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return retval;
1185d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1186d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1187d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
118800a0d0d65b61241a718d0aee96f46b9a2d93bf26Alan Coxstatic int qt_ioctl(struct tty_struct *tty,
1189d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    unsigned int cmd, unsigned long arg)
1190d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1191d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port = tty->driver_data;
1192d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port = qt_get_port_private(port);
1193d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial = get_usb_serial(port, __func__);
1194d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int index;
1195d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1196d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s cmd 0x%04x", __func__, cmd);
1197d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1198d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	index = tty->index - serial->minor;
1199d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1200d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (cmd == TIOCMIWAIT) {
1201d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		while (qt_port != NULL) {
1202d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			interruptible_sleep_on(&qt_port->msr_wait);
1203d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			if (signal_pending(current))
1204d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				return -ERESTARTSYS;
1205d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			else {
1206d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				char diff = qt_port->diff_status;
1207d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1208d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				if (diff == 0)
1209d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					return -EIO;	/* no change => error */
1210d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1211d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				/* Consume all events */
1212d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				qt_port->diff_status = 0;
1213d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1214d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				if (((arg & TIOCM_RNG)
1215d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				     && (diff & SERIAL_MSR_RI))
1216d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				    || ((arg & TIOCM_DSR)
1217d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					&& (diff & SERIAL_MSR_DSR))
1218d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				    || ((arg & TIOCM_CD)
1219d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					&& (diff & SERIAL_MSR_CD))
1220d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				    || ((arg & TIOCM_CTS)
1221d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					&& (diff & SERIAL_MSR_CTS))) {
1222d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					return 0;
1223d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				}
1224d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			}
1225d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
1226d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return 0;
1227d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1228d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1229d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s -No ioctl for that one.  port = %d\n", __func__, port->number);
1230d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return -ENOIOCTLCMD;
1231d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1232d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1233d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_set_termios(struct tty_struct *tty,
1234d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			   struct usb_serial_port *port,
1235d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			   struct ktermios *old_termios)
1236d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1237d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct ktermios *termios = tty->termios;
1238d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned char new_LCR = 0;
1239d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int cflag = termios->c_cflag;
1240d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int index;
1241d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int baud, divisor, remainder;
1242d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int status;
1243d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1244d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s", __func__);
1245d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1246d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	index = tty->index - port->serial->minor;
1247d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1248d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	switch (cflag) {
1249d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case CS5:
1250d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		new_LCR |= SERIAL_5_DATA;
1251d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		break;
1252d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case CS6:
1253d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		new_LCR |= SERIAL_6_DATA;
1254d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		break;
1255d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case CS7:
1256d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		new_LCR |= SERIAL_7_DATA;
1257d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		break;
1258d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	default:
1259d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	case CS8:
1260d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		new_LCR |= SERIAL_8_DATA;
1261d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		break;
1262d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1263d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1264d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Parity stuff */
1265d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (cflag & PARENB) {
1266d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (cflag & PARODD)
1267d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			new_LCR |= SERIAL_ODD_PARITY;
1268d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		else
1269d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			new_LCR |= SERIAL_EVEN_PARITY;
1270d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1271d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (cflag & CSTOPB)
1272d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		new_LCR |= SERIAL_TWO_STOPB;
1273d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	else
127435f077dca73132dcac2cac1706417229a68f38c3Roel Kluin		new_LCR |= SERIAL_ONE_STOPB;
1275d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1276d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - 4\n", __func__);
1277d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1278d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Thats the LCR stuff, go ahead and set it */
1279d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	baud = tty_get_baud_rate(tty);
1280d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!baud)
1281d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* pick a default, any default... */
1282d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		baud = 9600;
1283d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1284d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - got baud = %d\n", __func__, baud);
1285d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1286d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	divisor = MAX_BAUD_RATE / baud;
1287d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	remainder = MAX_BAUD_RATE % baud;
1288d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Round to nearest divisor */
1289d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (((remainder * 2) >= baud) && (baud != 110))
1290d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		divisor++;
1291d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1292d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/*
1293d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 * Set Baud rate to default and turn off (default)flow control here
1294d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 */
1295d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status =
1296d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    qt_setuart(port->serial, index, (unsigned short)divisor, new_LCR);
1297d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0) {
1298d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg(__FILE__ "qt_setuart failed\n");
1299d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return;
1300d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1301d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1302d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* Now determine flow control */
1303d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (cflag & CRTSCTS) {
1304d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - Enabling HW flow control port %d\n", __func__,
1305d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    port->number);
1306d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1307d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* Enable RTS/CTS flow control */
1308d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		status = BoxSetHW_FlowCtrl(port->serial, index, 1);
1309d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1310d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (status < 0) {
1311d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			dbg(__FILE__ "BoxSetHW_FlowCtrl failed\n");
1312d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			return;
1313d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
1314d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	} else {
1315d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* Disable RTS/CTS flow control */
1316d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - disabling HW flow control port %d\n", __func__,
1317d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    port->number);
1318d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1319d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		status = BoxSetHW_FlowCtrl(port->serial, index, 0);
1320d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (status < 0) {
1321d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			dbg(__FILE__ "BoxSetHW_FlowCtrl failed\n");
1322d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			return;
1323d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
1324d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1325d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1326d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1327d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* if we are implementing XON/XOFF, set the start and stop character in
1328d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 * the device */
1329d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (I_IXOFF(tty) || I_IXON(tty)) {
1330d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		unsigned char stop_char = STOP_CHAR(tty);
1331d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		unsigned char start_char = START_CHAR(tty);
1332d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		status =
1333d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    BoxSetSW_FlowCtrl(port->serial, index, stop_char,
1334d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				      start_char);
1335d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (status < 0)
1336d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			dbg(__FILE__ "BoxSetSW_FlowCtrl (enabled) failed\n");
1337d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1338d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	} else {
1339d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* disable SW flow control */
1340d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		status = BoxDisable_SW_FlowCtrl(port->serial, index);
1341d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if (status < 0)
1342d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			dbg(__FILE__ "BoxSetSW_FlowCtrl (diabling) failed\n");
1343d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1344d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1345d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	tty->termios->c_cflag &= ~CMSPAR;
1346d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* FIXME: Error cases should be returning the actual bits changed only */
1347d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1348d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1349d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_break(struct tty_struct *tty, int break_state)
1350d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1351d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port = tty->driver_data;
1352d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial = get_usb_serial(port, __func__);
1353d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port;
1354d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	u16 index, onoff;
1355d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int result;
1356d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1357d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	index = tty->index - serial->minor;
1358d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1359d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	qt_port = qt_get_port_private(port);
1360d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1361d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (break_state == -1)
1362d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		onoff = 1;
1363d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	else
1364d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		onoff = 0;
1365d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1366fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov	mutex_lock(&qt_port->lock);
1367d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1368d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
1369d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1370d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	result =
1371d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
1372d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			    QT_BREAK_CONTROL, 0x40, onoff, index, NULL, 0, 300);
1373d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1374fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov	mutex_unlock(&qt_port->lock);
1375d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1376d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1377d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic inline int qt_real_tiocmget(struct tty_struct *tty,
1378d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				   struct usb_serial_port *port,
137960b33c133ca0b7c0b6072c87234b63fee6e80558Alan Cox				   struct usb_serial *serial)
1380d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1381d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1382d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	u8 mcr;
1383d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	u8 msr;
1384d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int result = 0;
1385d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int status;
1386d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int index;
1387d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1388d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d, tty =0x%p\n", __func__, port->number, tty);
1389d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1390d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	index = tty->index - serial->minor;
1391d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status =
1392d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    BoxGetRegister(port->serial, index, MODEM_CONTROL_REGISTER, &mcr);
1393d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status >= 0) {
1394d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		status =
1395d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    BoxGetRegister(port->serial, index,
1396d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				   MODEM_STATUS_REGISTER, &msr);
1397d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1398d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1399d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1400d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status >= 0) {
1401d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		result = ((mcr & SERIAL_MCR_DTR) ? TIOCM_DTR : 0)
1402d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    /* DTR IS SET */
1403d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    | ((mcr & SERIAL_MCR_RTS) ? TIOCM_RTS : 0)
1404d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    /* RTS IS SET */
1405d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    | ((msr & SERIAL_MSR_CTS) ? TIOCM_CTS : 0)
1406d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    /* CTS is set */
1407d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    | ((msr & SERIAL_MSR_CD) ? TIOCM_CAR : 0)
1408d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    /* Carrier detect is set */
1409d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    | ((msr & SERIAL_MSR_RI) ? TIOCM_RI : 0)
1410d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    /* Ring indicator set */
1411d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		    | ((msr & SERIAL_MSR_DSR) ? TIOCM_DSR : 0);
1412d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* DSR is set */
1413d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return result;
1414d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1415d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	} else
1416d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ESPIPE;
1417d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1418d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1419d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic inline int qt_real_tiocmset(struct tty_struct *tty,
1420d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				   struct usb_serial_port *port,
1421d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				   struct usb_serial *serial,
1422d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				   unsigned int value)
1423d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1424d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1425d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	u8 mcr;
1426d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int status;
1427d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int index;
1428d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1429d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
1430d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1431d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	index = tty->index - serial->minor;
1432d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status =
1433d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    BoxGetRegister(port->serial, index, MODEM_CONTROL_REGISTER, &mcr);
1434d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0)
1435d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ESPIPE;
1436d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1437d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/*
1438d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 * Turn off the RTS and DTR and loopbcck and then only turn on what was
1439d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 * asked for
1440d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	 */
1441d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	mcr &= ~(SERIAL_MCR_RTS | SERIAL_MCR_DTR | SERIAL_MCR_LOOP);
1442d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (value & TIOCM_RTS)
1443d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		mcr |= SERIAL_MCR_RTS;
1444d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (value & TIOCM_DTR)
1445d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		mcr |= SERIAL_MCR_DTR;
1446d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (value & TIOCM_LOOP)
1447d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		mcr |= SERIAL_MCR_LOOP;
1448d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1449d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	status =
1450d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    BoxSetRegister(port->serial, index, MODEM_CONTROL_REGISTER, mcr);
1451d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (status < 0)
1452d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ESPIPE;
1453d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	else
1454d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return 0;
1455d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1456d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
145760b33c133ca0b7c0b6072c87234b63fee6e80558Alan Coxstatic int qt_tiocmget(struct tty_struct *tty)
1458d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1459d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port = tty->driver_data;
1460d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial = get_usb_serial(port, __func__);
1461d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port = qt_get_port_private(port);
1462d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int retval = -ENODEV;
1463d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
14641695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("In %s\n", __func__);
1465d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1466d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!serial)
1467d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ENODEV;
1468d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1469fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov	mutex_lock(&qt_port->lock);
1470d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1471d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
1472d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding);
1473d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
147460b33c133ca0b7c0b6072c87234b63fee6e80558Alan Cox	retval = qt_real_tiocmget(tty, port, serial);
1475d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1476fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov	mutex_unlock(&qt_port->lock);
1477d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return retval;
1478d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1479d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
148020b9d17715017ae4dd4ec87fabc36d33b9de708eAlan Coxstatic int qt_tiocmset(struct tty_struct *tty,
1481d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		       unsigned int set, unsigned int clear)
1482d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1483d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1484d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port = tty->driver_data;
1485d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial = get_usb_serial(port, __func__);
1486d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port = qt_get_port_private(port);
1487d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int retval = -ENODEV;
1488d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
14891695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("In %s\n", __func__);
1490d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1491d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!serial)
1492d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return -ENODEV;
1493d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1494fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov	mutex_lock(&qt_port->lock);
1495d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
14961695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("%s - port %d\n", __func__, port->number);
1497d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - qt_port->RxHolding = %d\n", __func__, qt_port->RxHolding);
1498d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
149920b9d17715017ae4dd4ec87fabc36d33b9de708eAlan Cox	retval = qt_real_tiocmset(tty, port, serial, set);
1500d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1501fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov	mutex_unlock(&qt_port->lock);
1502d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return retval;
1503d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1504d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1505d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_throttle(struct tty_struct *tty)
1506d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1507d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port = tty->driver_data;
1508d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial = get_usb_serial(port, __func__);
1509d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port;
1510d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1511d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
1512d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1513d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!serial)
1514d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return;
1515d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1516d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	qt_port = qt_get_port_private(port);
1517d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1518fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov	mutex_lock(&qt_port->lock);
1519d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1520d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	/* pass on to the driver specific version of this function */
1521d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	qt_port->RxHolding = 1;
1522d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port->RxHolding = 1\n", __func__);
1523d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1524fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov	mutex_unlock(&qt_port->lock);
1525d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return;
1526d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1527d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1528d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_unthrottle(struct tty_struct *tty)
1529d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1530d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial_port *port = tty->driver_data;
1531d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct usb_serial *serial = get_usb_serial(port, __func__);
1532d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	struct quatech_port *qt_port;
1533d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	unsigned int result;
1534d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1535d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (!serial)
1536d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		return;
1537d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1538d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	qt_port = qt_get_port_private(port);
1539d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1540fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov	mutex_lock(&qt_port->lock);
1541d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1542d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	dbg("%s - port %d\n", __func__, port->number);
1543d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1544d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	if (qt_port->RxHolding == 1) {
1545d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s -qt_port->RxHolding == 1\n", __func__);
1546d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1547d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		qt_port->RxHolding = 0;
1548d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		dbg("%s - qt_port->RxHolding = 0\n", __func__);
1549d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1550d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		/* if we have a bulk endpoint, start it up */
1551d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		if ((serial->num_bulk_in) && (qt_port->ReadBulkStopped == 1)) {
1552d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			/* Start reading from the device */
1553d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			usb_fill_bulk_urb(port->read_urb, serial->dev,
1554d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					  usb_rcvbulkpipe(serial->dev,
1555d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton							  port->bulk_in_endpointAddress),
1556d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					  port->read_urb->transfer_buffer,
1557d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					  port->read_urb->
1558d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					  transfer_buffer_length,
1559d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton					  qt_read_bulk_callback, port);
1560d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
1561d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton			if (result)
1562d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				err("%s - failed restarting read urb, error %d",
1563d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton				    __func__, result);
1564d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		}
1565d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	}
1566fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov	mutex_unlock(&qt_port->lock);
1567d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return;
1568d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1569d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1570d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1571d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_calc_num_ports(struct usb_serial *serial)
1572d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{
1573d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	int num_ports;
1574d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
15751695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("numberofendpoints: %d\n",
1576d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    (int)serial->interface->cur_altsetting->desc.bNumEndpoints);
15771695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev	dbg("numberofendpoints: %d\n",
1578d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    (int)serial->interface->altsetting->desc.bNumEndpoints);
1579d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1580d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	num_ports =
1581d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	    (serial->interface->cur_altsetting->desc.bNumEndpoints - 1) / 2;
1582d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1583d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	return num_ports;
1584d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}
1585d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1586d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic struct usb_serial_driver quatech_device = {
1587d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.driver = {
1588d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		   .owner = THIS_MODULE,
1589d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		   .name = "serqt",
1590d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton		   },
1591d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.description = DRIVER_DESC,
1592d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.id_table = serqt_id_table,
1593d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.num_ports = 8,
1594d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.open = qt_open,
1595d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.close = qt_close,
1596d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.write = qt_write,
1597d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.write_room = qt_write_room,
1598d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.chars_in_buffer = qt_chars_in_buffer,
1599d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.throttle = qt_throttle,
1600d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.unthrottle = qt_unthrottle,
1601d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.calc_num_ports = qt_calc_num_ports,
1602d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.ioctl = qt_ioctl,
1603d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.set_termios = qt_set_termios,
1604d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.break_ctl = qt_break,
1605d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.tiocmget = qt_tiocmget,
1606d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.tiocmset = qt_tiocmset,
1607d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.attach = qt_startup,
1608d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton	.release = qt_release,
1609d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton};
1610d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
161169276a33bd1d272dc9c3bd577038954811bd1831Alan Sternstatic struct usb_serial_driver * const serial_drivers[] = {
161269276a33bd1d272dc9c3bd577038954811bd1831Alan Stern	&quatech_device, NULL
161369276a33bd1d272dc9c3bd577038954811bd1831Alan Stern};
161469276a33bd1d272dc9c3bd577038954811bd1831Alan Stern
1615e42f85f3d410a5457a2db61d883437ac9e32ceccGreg Kroah-Hartmanmodule_usb_serial_driver(serqt_usb_driver, serial_drivers);
1616d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1617d75662e164d5175c5e5f9339ff4d6f6980613d96Bill PembertonMODULE_AUTHOR(DRIVER_AUTHOR);
1618d75662e164d5175c5e5f9339ff4d6f6980613d96Bill PembertonMODULE_DESCRIPTION(DRIVER_DESC);
1619d75662e164d5175c5e5f9339ff4d6f6980613d96Bill PembertonMODULE_LICENSE("GPL");
1620d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton
1621d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonmodule_param(debug, bool, S_IRUGO | S_IWUSR);
1622d75662e164d5175c5e5f9339ff4d6f6980613d96Bill PembertonMODULE_PARM_DESC(debug, "Debug enabled or not");
1623