diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-09-24 15:42:19 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-09-24 15:42:19 -0400 |
commit | 64f0d8cd089ee7e501116181a343c3739df5fe53 (patch) | |
tree | 96d6c7741048ad32034bbd139a6f2b9b3c2433b2 /drivers/usb/serial | |
parent | f3f4bf5cf0896e58e9831ea53bcb8c7d88127d20 (diff) |
USB: serial: remove vizzini driver
It's out-dated for the tty-layer stuff, and would require a bunch of
work. That's not really a big deal, the big issue is that there is no
company contact for the hardware, so questions we have about it (like
why isn't this just handled by the cdc-acm driver instead?) go
unanswered.
So drop the driver. If someone comes along to help answer the
questions, we can easily revert this and fix up the code.
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Rob Duncan <rob.duncan@exar.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/Kconfig | 8 | ||||
-rw-r--r-- | drivers/usb/serial/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/serial/vizzini.c | 1354 |
3 files changed, 0 insertions, 1363 deletions
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index a5c144694005..f604f707a058 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig | |||
@@ -182,14 +182,6 @@ config USB_SERIAL_VISOR | |||
182 | To compile this driver as a module, choose M here: the | 182 | To compile this driver as a module, choose M here: the |
183 | module will be called visor. | 183 | module will be called visor. |
184 | 184 | ||
185 | config USB_SERIAL_VIZZINI | ||
186 | tristate "USB Vizzini Serial Converter Driver" | ||
187 | help | ||
188 | Say Y here if you have a Vizzini USB to serial device. | ||
189 | |||
190 | To compile this driver as a module, choose M here: the | ||
191 | module will be called vizzini. | ||
192 | |||
193 | config USB_SERIAL_IPAQ | 185 | config USB_SERIAL_IPAQ |
194 | tristate "USB PocketPC PDA Driver" | 186 | tristate "USB PocketPC PDA Driver" |
195 | help | 187 | help |
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 5fd21a01b009..45871f9ad1e1 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile | |||
@@ -59,7 +59,6 @@ obj-$(CONFIG_USB_SERIAL_SYMBOL) += symbolserial.o | |||
59 | obj-$(CONFIG_USB_SERIAL_WWAN) += usb_wwan.o | 59 | obj-$(CONFIG_USB_SERIAL_WWAN) += usb_wwan.o |
60 | obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o | 60 | obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o |
61 | obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o | 61 | obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o |
62 | obj-$(CONFIG_USB_SERIAL_VIZZINI) += vizzini.o | ||
63 | obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o | 62 | obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o |
64 | obj-$(CONFIG_USB_SERIAL_XIRCOM) += keyspan_pda.o | 63 | obj-$(CONFIG_USB_SERIAL_XIRCOM) += keyspan_pda.o |
65 | obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL) += vivopay-serial.o | 64 | obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL) += vivopay-serial.o |
diff --git a/drivers/usb/serial/vizzini.c b/drivers/usb/serial/vizzini.c deleted file mode 100644 index 7f436949dd99..000000000000 --- a/drivers/usb/serial/vizzini.c +++ /dev/null | |||
@@ -1,1354 +0,0 @@ | |||
1 | /* | ||
2 | * vizzini.c | ||
3 | * | ||
4 | * Copyright (c) 2011 Exar Corporation, Inc. | ||
5 | * | ||
6 | * ChangeLog: | ||
7 | * v0.76- Support for 3.0.0 (Ubuntu 11.10) (Removed all Kernel source | ||
8 | * compiler conditions and now the base is Kernel 3.0. Ravi Reddy) | ||
9 | * v0.75- Support for 2.6.38.8 (Ubuntu 11.04) - Added | ||
10 | * .usb_driver = &vizzini_driver. | ||
11 | * v0.74- Support for 2.6.35.22 (Ubuntu 10.10) - Added | ||
12 | * #include <linux/slab.h> to fix kmalloc/kfree error. | ||
13 | * v0.73- Fixed VZIOC_SET_REG (by Ravi Reddy). | ||
14 | * v0.72- Support for 2.6.32.21 (by Ravi Reddy, for Ubuntu 10.04). | ||
15 | * v0.71- Support for 2.6.31. | ||
16 | * v0.5 - Tentative support for compiling with the CentOS 5.1 | ||
17 | * kernel (2.6.18-53). | ||
18 | * v0.4 - First version. Lots of stuff lifted from | ||
19 | * cdc-acm.c (credits due to Armin Fuerst, Pavel Machek, | ||
20 | * Johannes Erdfelt, Vojtech Pavlik, David Kubicek) and | ||
21 | * and sierra.c (credit due to Kevin Lloyd). | ||
22 | */ | ||
23 | |||
24 | /* | ||
25 | * This program is free software; you can redistribute it and/or modify | ||
26 | * it under the terms of the GNU General Public License as published by | ||
27 | * the Free Software Foundation; either version 2 of the License, or | ||
28 | * (at your option) any later version. | ||
29 | * | ||
30 | * This program is distributed in the hope that it will be useful, | ||
31 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
32 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
33 | * GNU General Public License for more details. | ||
34 | * | ||
35 | * You should have received a copy of the GNU General Public License | ||
36 | * along with this program; if not, write to the Free Software | ||
37 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
38 | */ | ||
39 | |||
40 | #define DRIVER_VERSION "v.0.76" | ||
41 | #define DRIVER_AUTHOR "Rob Duncan <rob.duncan@exar.com>" | ||
42 | #define DRIVER_DESC "USB Driver for Vizzini USB serial port" | ||
43 | |||
44 | #undef VIZZINI_IWA | ||
45 | |||
46 | |||
47 | #include <linux/kernel.h> | ||
48 | #include <linux/jiffies.h> | ||
49 | #include <linux/errno.h> | ||
50 | #include <linux/tty.h> | ||
51 | #include <linux/tty_flip.h> | ||
52 | #include <linux/module.h> | ||
53 | #include <linux/usb.h> | ||
54 | #include <linux/usb/serial.h> | ||
55 | #include <linux/serial.h> | ||
56 | #include <linux/slab.h> | ||
57 | #include <linux/uaccess.h> | ||
58 | #include <asm/unaligned.h> | ||
59 | |||
60 | #include <linux/usb/cdc.h> | ||
61 | #ifndef CDC_DATA_INTERFACE_TYPE | ||
62 | #define CDC_DATA_INTERFACE_TYPE 0x0a | ||
63 | #endif | ||
64 | #ifndef USB_RT_ACM | ||
65 | #define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE) | ||
66 | #define ACM_CTRL_DTR 0x01 | ||
67 | #define ACM_CTRL_RTS 0x02 | ||
68 | #define ACM_CTRL_DCD 0x01 | ||
69 | #define ACM_CTRL_DSR 0x02 | ||
70 | #define ACM_CTRL_BRK 0x04 | ||
71 | #define ACM_CTRL_RI 0x08 | ||
72 | #define ACM_CTRL_FRAMING 0x10 | ||
73 | #define ACM_CTRL_PARITY 0x20 | ||
74 | #define ACM_CTRL_OVERRUN 0x40 | ||
75 | #endif | ||
76 | |||
77 | #define XR_SET_REG 0 | ||
78 | #define XR_GETN_REG 1 | ||
79 | |||
80 | #define UART_0_REG_BLOCK 0 | ||
81 | #define UART_1_REG_BLOCK 1 | ||
82 | #define UART_2_REG_BLOCK 2 | ||
83 | #define UART_3_REG_BLOCK 3 | ||
84 | #define URM_REG_BLOCK 4 | ||
85 | #define PRM_REG_BLOCK 5 | ||
86 | #define EPMERR_REG_BLOCK 6 | ||
87 | #define RAMCTL_REG_BLOCK 0x64 | ||
88 | #define TWI_ROM_REG_BLOCK 0x65 | ||
89 | #define EPLOCALS_REG_BLOCK 0x66 | ||
90 | |||
91 | #define MEM_SHADOW_REG_SIZE_S 5 | ||
92 | #define MEM_SHADOW_REG_SIZE (1 << MEM_SHADOW_REG_SIZE_S) | ||
93 | |||
94 | #define MEM_EP_LOCALS_SIZE_S 3 | ||
95 | #define MEM_EP_LOCALS_SIZE (1 << MEM_EP_LOCALS_SIZE_S) | ||
96 | |||
97 | #define EP_WIDE_MODE 0x03 | ||
98 | |||
99 | |||
100 | #define UART_GPIO_MODE 0x01a | ||
101 | |||
102 | #define UART_GPIO_MODE_SEL_M 0x7 | ||
103 | #define UART_GPIO_MODE_SEL_S 0 | ||
104 | #define UART_GPIO_MODE_SEL 0x007 | ||
105 | |||
106 | #define UART_GPIO_MODE_SEL_GPIO (0x0 << UART_GPIO_MODE_SEL_S) | ||
107 | #define UART_GPIO_MODE_SEL_RTS_CTS (0x1 << UART_GPIO_MODE_SEL_S) | ||
108 | #define UART_GPIO_MODE_SEL_DTR_DSR (0x2 << UART_GPIO_MODE_SEL_S) | ||
109 | #define UART_GPIO_MODE_SEL_XCVR_EN_ACT (0x3 << UART_GPIO_MODE_SEL_S) | ||
110 | #define UART_GPIO_MODE_SEL_XCVR_EN_FLOW (0x4 << UART_GPIO_MODE_SEL_S) | ||
111 | |||
112 | #define UART_GPIO_MODE_XCVR_EN_POL_M 0x1 | ||
113 | #define UART_GPIO_MODE_XCVR_EN_POL_S 3 | ||
114 | #define UART_GPIO_MODE_XCVR_EN_POL 0x008 | ||
115 | |||
116 | #define UART_ENABLE 0x003 | ||
117 | #define UART_ENABLE_TX_M 0x1 | ||
118 | #define UART_ENABLE_TX_S 0 | ||
119 | #define UART_ENABLE_TX 0x001 | ||
120 | #define UART_ENABLE_RX_M 0x1 | ||
121 | #define UART_ENABLE_RX_S 1 | ||
122 | #define UART_ENABLE_RX 0x002 | ||
123 | |||
124 | #define UART_CLOCK_DIVISOR_0 0x004 | ||
125 | #define UART_CLOCK_DIVISOR_1 0x005 | ||
126 | #define UART_CLOCK_DIVISOR_2 0x006 | ||
127 | |||
128 | #define UART_CLOCK_DIVISOR_2_MSB_M 0x7 | ||
129 | #define UART_CLOCK_DIVISOR_2_MSB_S 0 | ||
130 | #define UART_CLOCK_DIVISOR_2_MSB 0x007 | ||
131 | #define UART_CLOCK_DIVISOR_2_DIAGMODE_M 0x1 | ||
132 | #define UART_CLOCK_DIVISOR_2_DIAGMODE_S 3 | ||
133 | #define UART_CLOCK_DIVISOR_2_DIAGMODE 0x008 | ||
134 | |||
135 | #define UART_TX_CLOCK_MASK_0 0x007 | ||
136 | #define UART_TX_CLOCK_MASK_1 0x008 | ||
137 | |||
138 | #define UART_RX_CLOCK_MASK_0 0x009 | ||
139 | #define UART_RX_CLOCK_MASK_1 0x00a | ||
140 | |||
141 | #define UART_FORMAT 0x00b | ||
142 | |||
143 | #define UART_FORMAT_SIZE_M 0xf | ||
144 | #define UART_FORMAT_SIZE_S 0 | ||
145 | #define UART_FORMAT_SIZE 0x00f | ||
146 | |||
147 | #define UART_FORMAT_SIZE_7 (0x7 << UART_FORMAT_SIZE_S) | ||
148 | #define UART_FORMAT_SIZE_8 (0x8 << UART_FORMAT_SIZE_S) | ||
149 | #define UART_FORMAT_SIZE_9 (0x9 << UART_FORMAT_SIZE_S) | ||
150 | |||
151 | #define UART_FORMAT_PARITY_M 0x7 | ||
152 | #define UART_FORMAT_PARITY_S 4 | ||
153 | #define UART_FORMAT_PARITY 0x070 | ||
154 | |||
155 | #define UART_FORMAT_PARITY_NONE (0x0 << UART_FORMAT_PARITY_S) | ||
156 | #define UART_FORMAT_PARITY_ODD (0x1 << UART_FORMAT_PARITY_S) | ||
157 | #define UART_FORMAT_PARITY_EVEN (0x2 << UART_FORMAT_PARITY_S) | ||
158 | #define UART_FORMAT_PARITY_1 (0x3 << UART_FORMAT_PARITY_S) | ||
159 | #define UART_FORMAT_PARITY_0 (0x4 << UART_FORMAT_PARITY_S) | ||
160 | |||
161 | #define UART_FORMAT_STOP_M 0x1 | ||
162 | #define UART_FORMAT_STOP_S 7 | ||
163 | #define UART_FORMAT_STOP 0x080 | ||
164 | |||
165 | #define UART_FORMAT_STOP_1 (0x0 << UART_FORMAT_STOP_S) | ||
166 | #define UART_FORMAT_STOP_2 (0x1 << UART_FORMAT_STOP_S) | ||
167 | |||
168 | #define UART_FORMAT_MODE_7N1 0 | ||
169 | #define UART_FORMAT_MODE_RES1 1 | ||
170 | #define UART_FORMAT_MODE_RES2 2 | ||
171 | #define UART_FORMAT_MODE_RES3 3 | ||
172 | #define UART_FORMAT_MODE_7N2 4 | ||
173 | #define UART_FORMAT_MODE_7P1 5 | ||
174 | #define UART_FORMAT_MODE_8N1 6 | ||
175 | #define UART_FORMAT_MODE_RES7 7 | ||
176 | #define UART_FORMAT_MODE_7P2 8 | ||
177 | #define UART_FORMAT_MODE_8N2 9 | ||
178 | #define UART_FORMAT_MODE_8P1 10 | ||
179 | #define UART_FORMAT_MODE_9N1 11 | ||
180 | #define UART_FORMAT_MODE_8P2 12 | ||
181 | #define UART_FORMAT_MODE_RESD 13 | ||
182 | #define UART_FORMAT_MODE_RESE 14 | ||
183 | #define UART_FORMAT_MODE_9N2 15 | ||
184 | |||
185 | #define UART_FLOW 0x00c | ||
186 | |||
187 | #define UART_FLOW_MODE_M 0x7 | ||
188 | #define UART_FLOW_MODE_S 0 | ||
189 | #define UART_FLOW_MODE 0x007 | ||
190 | |||
191 | #define UART_FLOW_MODE_NONE (0x0 << UART_FLOW_MODE_S) | ||
192 | #define UART_FLOW_MODE_HW (0x1 << UART_FLOW_MODE_S) | ||
193 | #define UART_FLOW_MODE_SW (0x2 << UART_FLOW_MODE_S) | ||
194 | #define UART_FLOW_MODE_ADDR_MATCH (0x3 << UART_FLOW_MODE_S) | ||
195 | #define UART_FLOW_MODE_ADDR_MATCH_TX (0x4 << UART_FLOW_MODE_S) | ||
196 | |||
197 | #define UART_FLOW_HALF_DUPLEX_M 0x1 | ||
198 | #define UART_FLOW_HALF_DUPLEX_S 3 | ||
199 | #define UART_FLOW_HALF_DUPLEX 0x008 | ||
200 | |||
201 | #define UART_LOOPBACK_CTL 0x012 | ||
202 | #define UART_LOOPBACK_CTL_ENABLE_M 0x1 | ||
203 | #define UART_LOOPBACK_CTL_ENABLE_S 2 | ||
204 | #define UART_LOOPBACK_CTL_ENABLE 0x004 | ||
205 | #define UART_LOOPBACK_CTL_RX_SOURCE_M 0x3 | ||
206 | #define UART_LOOPBACK_CTL_RX_SOURCE_S 0 | ||
207 | #define UART_LOOPBACK_CTL_RX_SOURCE 0x003 | ||
208 | #define UART_LOOPBACK_CTL_RX_UART0 (0x0 << UART_LOOPBACK_CTL_RX_SOURCE_S) | ||
209 | #define UART_LOOPBACK_CTL_RX_UART1 (0x1 << UART_LOOPBACK_CTL_RX_SOURCE_S) | ||
210 | #define UART_LOOPBACK_CTL_RX_UART2 (0x2 << UART_LOOPBACK_CTL_RX_SOURCE_S) | ||
211 | #define UART_LOOPBACK_CTL_RX_UART3 (0x3 << UART_LOOPBACK_CTL_RX_SOURCE_S) | ||
212 | |||
213 | #define UART_CHANNEL_NUM 0x00d | ||
214 | |||
215 | #define UART_XON_CHAR 0x010 | ||
216 | #define UART_XOFF_CHAR 0x011 | ||
217 | |||
218 | #define UART_GPIO_SET 0x01d | ||
219 | #define UART_GPIO_CLR 0x01e | ||
220 | #define UART_GPIO_STATUS 0x01f | ||
221 | |||
222 | #define URM_ENABLE_BASE 0x010 | ||
223 | #define URM_ENABLE_0 0x010 | ||
224 | #define URM_ENABLE_0_TX_M 0x1 | ||
225 | #define URM_ENABLE_0_TX_S 0 | ||
226 | #define URM_ENABLE_0_TX 0x001 | ||
227 | #define URM_ENABLE_0_RX_M 0x1 | ||
228 | #define URM_ENABLE_0_RX_S 1 | ||
229 | #define URM_ENABLE_0_RX 0x002 | ||
230 | |||
231 | #define URM_RX_FIFO_RESET_0 0x018 | ||
232 | #define URM_RX_FIFO_RESET_1 0x019 | ||
233 | #define URM_RX_FIFO_RESET_2 0x01a | ||
234 | #define URM_RX_FIFO_RESET_3 0x01b | ||
235 | #define URM_TX_FIFO_RESET_0 0x01c | ||
236 | #define URM_TX_FIFO_RESET_1 0x01d | ||
237 | #define URM_TX_FIFO_RESET_2 0x01e | ||
238 | #define URM_TX_FIFO_RESET_3 0x01f | ||
239 | |||
240 | |||
241 | #define RAMCTL_REGS_TXFIFO_0_LEVEL 0x000 | ||
242 | #define RAMCTL_REGS_TXFIFO_1_LEVEL 0x001 | ||
243 | #define RAMCTL_REGS_TXFIFO_2_LEVEL 0x002 | ||
244 | #define RAMCTL_REGS_TXFIFO_3_LEVEL 0x003 | ||
245 | #define RAMCTL_REGS_RXFIFO_0_LEVEL 0x004 | ||
246 | |||
247 | #define RAMCTL_REGS_RXFIFO_0_LEVEL_LEVEL_M 0x7ff | ||
248 | #define RAMCTL_REGS_RXFIFO_0_LEVEL_LEVEL_S 0 | ||
249 | #define RAMCTL_REGS_RXFIFO_0_LEVEL_LEVEL 0x7ff | ||
250 | #define RAMCTL_REGS_RXFIFO_0_LEVEL_STALE_M 0x1 | ||
251 | #define RAMCTL_REGS_RXFIFO_0_LEVEL_STALE_S 11 | ||
252 | #define RAMCTL_REGS_RXFIFO_0_LEVEL_STALE 0x800 | ||
253 | |||
254 | #define RAMCTL_REGS_RXFIFO_1_LEVEL 0x005 | ||
255 | #define RAMCTL_REGS_RXFIFO_2_LEVEL 0x006 | ||
256 | #define RAMCTL_REGS_RXFIFO_3_LEVEL 0x007 | ||
257 | |||
258 | #define RAMCTL_BUFFER_PARITY 0x1 | ||
259 | #define RAMCTL_BUFFER_BREAK 0x2 | ||
260 | #define RAMCTL_BUFFER_FRAME 0x4 | ||
261 | #define RAMCTL_BUFFER_OVERRUN 0x8 | ||
262 | |||
263 | #define N_IN_URB 4 | ||
264 | #define N_OUT_URB 4 | ||
265 | #define IN_BUFLEN 4096 | ||
266 | |||
267 | static struct usb_device_id id_table[] = { | ||
268 | { USB_DEVICE(0x04e2, 0x1410) }, | ||
269 | { USB_DEVICE(0x04e2, 0x1412) }, | ||
270 | { USB_DEVICE(0x04e2, 0x1414) }, | ||
271 | { } | ||
272 | }; | ||
273 | MODULE_DEVICE_TABLE(usb, id_table); | ||
274 | |||
275 | struct vizzini_serial_private { | ||
276 | struct usb_interface *data_interface; | ||
277 | }; | ||
278 | |||
279 | struct vizzini_port_private { | ||
280 | spinlock_t lock; | ||
281 | int outstanding_urbs; | ||
282 | |||
283 | struct urb *in_urbs[N_IN_URB]; | ||
284 | char *in_buffer[N_IN_URB]; | ||
285 | |||
286 | int ctrlin; | ||
287 | int ctrlout; | ||
288 | int clocal; | ||
289 | |||
290 | int block; | ||
291 | int preciseflags; /* USB: wide mode, TTY: flags per character */ | ||
292 | int trans9; /* USB: wide mode, serial 9N1 */ | ||
293 | unsigned int baud_base; /* setserial: used to hack in non-standard baud rates */ | ||
294 | int have_extra_byte; | ||
295 | int extra_byte; | ||
296 | |||
297 | int bcd_device; | ||
298 | |||
299 | #ifdef VIZZINI_IWA | ||
300 | int iwa; | ||
301 | #endif | ||
302 | }; | ||
303 | |||
304 | |||
305 | static int vizzini_rev_a(struct usb_serial_port *port) | ||
306 | { | ||
307 | struct vizzini_port_private *portdata = usb_get_serial_port_data(port); | ||
308 | return portdata->bcd_device == 0; | ||
309 | } | ||
310 | |||
311 | static int acm_ctrl_msg(struct usb_serial_port *port, int request, | ||
312 | int value, void *buf, int len) | ||
313 | { | ||
314 | struct usb_serial *serial = port->serial; | ||
315 | int retval = usb_control_msg(serial->dev, | ||
316 | usb_sndctrlpipe(serial->dev, 0), | ||
317 | request, | ||
318 | USB_RT_ACM, | ||
319 | value, | ||
320 | serial->interface->cur_altsetting->desc.bInterfaceNumber, | ||
321 | buf, | ||
322 | len, | ||
323 | 5000); | ||
324 | dev_dbg(&port->dev, "acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d\n", request, value, len, retval); | ||
325 | return retval < 0 ? retval : 0; | ||
326 | } | ||
327 | |||
328 | #define acm_set_control(port, control) \ | ||
329 | acm_ctrl_msg(port, USB_CDC_REQ_SET_CONTROL_LINE_STATE, control, NULL, 0) | ||
330 | #define acm_set_line(port, line) \ | ||
331 | acm_ctrl_msg(port, USB_CDC_REQ_SET_LINE_CODING, 0, line, sizeof *(line)) | ||
332 | #define acm_send_break(port, ms) \ | ||
333 | acm_ctrl_msg(port, USB_CDC_REQ_SEND_BREAK, ms, NULL, 0) | ||
334 | |||
335 | static int vizzini_set_reg(struct usb_serial_port *port, int block, int regnum, int value) | ||
336 | { | ||
337 | struct usb_serial *serial = port->serial; | ||
338 | int result; | ||
339 | |||
340 | result = usb_control_msg(serial->dev, /* usb device */ | ||
341 | usb_sndctrlpipe(serial->dev, 0), /* endpoint pipe */ | ||
342 | XR_SET_REG, /* request */ | ||
343 | USB_DIR_OUT | USB_TYPE_VENDOR, /* request_type */ | ||
344 | value, /* request value */ | ||
345 | regnum | (block << 8), /* index */ | ||
346 | NULL, /* data */ | ||
347 | 0, /* size */ | ||
348 | 5000); /* timeout */ | ||
349 | |||
350 | return result; | ||
351 | } | ||
352 | |||
353 | static void vizzini_disable(struct usb_serial_port *port) | ||
354 | { | ||
355 | struct vizzini_port_private *portdata = usb_get_serial_port_data(port); | ||
356 | int block = portdata->block; | ||
357 | |||
358 | vizzini_set_reg(port, block, UART_ENABLE, 0); | ||
359 | vizzini_set_reg(port, URM_REG_BLOCK, URM_ENABLE_BASE + block, 0); | ||
360 | } | ||
361 | |||
362 | static void vizzini_enable(struct usb_serial_port *port) | ||
363 | { | ||
364 | struct vizzini_port_private *portdata = usb_get_serial_port_data(port); | ||
365 | int block = portdata->block; | ||
366 | |||
367 | vizzini_set_reg(port, URM_REG_BLOCK, URM_ENABLE_BASE + block, URM_ENABLE_0_TX); | ||
368 | vizzini_set_reg(port, block, UART_ENABLE, UART_ENABLE_TX | UART_ENABLE_RX); | ||
369 | vizzini_set_reg(port, URM_REG_BLOCK, URM_ENABLE_BASE + block, URM_ENABLE_0_TX | URM_ENABLE_0_RX); | ||
370 | } | ||
371 | |||
372 | struct vizzini_baud_rate { | ||
373 | unsigned int tx; | ||
374 | unsigned int rx0; | ||
375 | unsigned int rx1; | ||
376 | }; | ||
377 | |||
378 | static struct vizzini_baud_rate vizzini_baud_rates[] = { | ||
379 | { 0x000, 0x000, 0x000 }, | ||
380 | { 0x000, 0x000, 0x000 }, | ||
381 | { 0x100, 0x000, 0x100 }, | ||
382 | { 0x020, 0x400, 0x020 }, | ||
383 | { 0x010, 0x100, 0x010 }, | ||
384 | { 0x208, 0x040, 0x208 }, | ||
385 | { 0x104, 0x820, 0x108 }, | ||
386 | { 0x844, 0x210, 0x884 }, | ||
387 | { 0x444, 0x110, 0x444 }, | ||
388 | { 0x122, 0x888, 0x224 }, | ||
389 | { 0x912, 0x448, 0x924 }, | ||
390 | { 0x492, 0x248, 0x492 }, | ||
391 | { 0x252, 0x928, 0x292 }, | ||
392 | { 0X94A, 0X4A4, 0XA52 }, | ||
393 | { 0X52A, 0XAA4, 0X54A }, | ||
394 | { 0XAAA, 0x954, 0X4AA }, | ||
395 | { 0XAAA, 0x554, 0XAAA }, | ||
396 | { 0x555, 0XAD4, 0X5AA }, | ||
397 | { 0XB55, 0XAB4, 0X55A }, | ||
398 | { 0X6B5, 0X5AC, 0XB56 }, | ||
399 | { 0X5B5, 0XD6C, 0X6D6 }, | ||
400 | { 0XB6D, 0XB6A, 0XDB6 }, | ||
401 | { 0X76D, 0X6DA, 0XBB6 }, | ||
402 | { 0XEDD, 0XDDA, 0X76E }, | ||
403 | { 0XDDD, 0XBBA, 0XEEE }, | ||
404 | { 0X7BB, 0XF7A, 0XDDE }, | ||
405 | { 0XF7B, 0XEF6, 0X7DE }, | ||
406 | { 0XDF7, 0XBF6, 0XF7E }, | ||
407 | { 0X7F7, 0XFEE, 0XEFE }, | ||
408 | { 0XFDF, 0XFBE, 0X7FE }, | ||
409 | { 0XF7F, 0XEFE, 0XFFE }, | ||
410 | { 0XFFF, 0XFFE, 0XFFD }, | ||
411 | }; | ||
412 | |||
413 | static int vizzini_set_baud_rate(struct usb_serial_port *port, unsigned int rate) | ||
414 | { | ||
415 | struct vizzini_port_private *portdata = usb_get_serial_port_data(port); | ||
416 | int block = portdata->block; | ||
417 | unsigned int divisor = 48000000 / rate; | ||
418 | unsigned int i = ((32 * 48000000) / rate) & 0x1f; | ||
419 | unsigned int tx_mask = vizzini_baud_rates[i].tx; | ||
420 | unsigned int rx_mask = (divisor & 1) ? vizzini_baud_rates[i].rx1 : vizzini_baud_rates[i].rx0; | ||
421 | |||
422 | dev_dbg(&port->dev, "Setting baud rate to %d: i=%u div=%u tx=%03x rx=%03x\n", rate, i, divisor, tx_mask, rx_mask); | ||
423 | |||
424 | vizzini_set_reg(port, block, UART_CLOCK_DIVISOR_0, (divisor >> 0) & 0xff); | ||
425 | vizzini_set_reg(port, block, UART_CLOCK_DIVISOR_1, (divisor >> 8) & 0xff); | ||
426 | vizzini_set_reg(port, block, UART_CLOCK_DIVISOR_2, (divisor >> 16) & 0xff); | ||
427 | vizzini_set_reg(port, block, UART_TX_CLOCK_MASK_0, (tx_mask >> 0) & 0xff); | ||
428 | vizzini_set_reg(port, block, UART_TX_CLOCK_MASK_1, (tx_mask >> 8) & 0xff); | ||
429 | vizzini_set_reg(port, block, UART_RX_CLOCK_MASK_0, (rx_mask >> 0) & 0xff); | ||
430 | vizzini_set_reg(port, block, UART_RX_CLOCK_MASK_1, (rx_mask >> 8) & 0xff); | ||
431 | |||
432 | return -EINVAL; | ||
433 | } | ||
434 | |||
435 | static void vizzini_set_termios(struct tty_struct *tty_param, | ||
436 | struct usb_serial_port *port, | ||
437 | struct ktermios *old_termios) | ||
438 | { | ||
439 | struct vizzini_port_private *portdata = usb_get_serial_port_data(port); | ||
440 | unsigned int cflag, block; | ||
441 | speed_t rate; | ||
442 | unsigned int format_size, format_parity, format_stop, flow, gpio_mode; | ||
443 | struct tty_struct *tty = port->port.tty; | ||
444 | |||
445 | cflag = tty->termios->c_cflag; | ||
446 | |||
447 | portdata->clocal = ((cflag & CLOCAL) != 0); | ||
448 | |||
449 | block = portdata->block; | ||
450 | |||
451 | vizzini_disable(port); | ||
452 | |||
453 | if ((cflag & CSIZE) == CS7) { | ||
454 | format_size = UART_FORMAT_SIZE_7; | ||
455 | } else if ((cflag & CSIZE) == CS5) { | ||
456 | /* Enabling 5-bit mode is really 9-bit mode! */ | ||
457 | format_size = UART_FORMAT_SIZE_9; | ||
458 | } else { | ||
459 | format_size = UART_FORMAT_SIZE_8; | ||
460 | } | ||
461 | portdata->trans9 = (format_size == UART_FORMAT_SIZE_9); | ||
462 | |||
463 | if (cflag & PARENB) { | ||
464 | if (cflag & PARODD) { | ||
465 | if (cflag & CMSPAR) | ||
466 | format_parity = UART_FORMAT_PARITY_1; | ||
467 | else | ||
468 | format_parity = UART_FORMAT_PARITY_ODD; | ||
469 | } else { | ||
470 | if (cflag & CMSPAR) | ||
471 | format_parity = UART_FORMAT_PARITY_0; | ||
472 | else | ||
473 | format_parity = UART_FORMAT_PARITY_EVEN; | ||
474 | } | ||
475 | } else { | ||
476 | format_parity = UART_FORMAT_PARITY_NONE; | ||
477 | } | ||
478 | |||
479 | if (cflag & CSTOPB) | ||
480 | format_stop = UART_FORMAT_STOP_2; | ||
481 | else | ||
482 | format_stop = UART_FORMAT_STOP_1; | ||
483 | |||
484 | #ifdef VIZZINI_IWA | ||
485 | if (format_size == UART_FORMAT_SIZE_8) { | ||
486 | portdata->iwa = format_parity; | ||
487 | if (portdata->iwa != UART_FORMAT_PARITY_NONE) { | ||
488 | format_size = UART_FORMAT_SIZE_9; | ||
489 | format_parity = UART_FORMAT_PARITY_NONE; | ||
490 | } | ||
491 | } else { | ||
492 | portdata->iwa = UART_FORMAT_PARITY_NONE; | ||
493 | } | ||
494 | #endif | ||
495 | vizzini_set_reg(port, block, UART_FORMAT, format_size | format_parity | format_stop); | ||
496 | |||
497 | if (cflag & CRTSCTS) { | ||
498 | flow = UART_FLOW_MODE_HW; | ||
499 | gpio_mode = UART_GPIO_MODE_SEL_RTS_CTS; | ||
500 | } else if (I_IXOFF(tty) || I_IXON(tty)) { | ||
501 | unsigned char start_char = START_CHAR(tty); | ||
502 | unsigned char stop_char = STOP_CHAR(tty); | ||
503 | |||
504 | flow = UART_FLOW_MODE_SW; | ||
505 | gpio_mode = UART_GPIO_MODE_SEL_GPIO; | ||
506 | |||
507 | vizzini_set_reg(port, block, UART_XON_CHAR, start_char); | ||
508 | vizzini_set_reg(port, block, UART_XOFF_CHAR, stop_char); | ||
509 | } else { | ||
510 | flow = UART_FLOW_MODE_NONE; | ||
511 | gpio_mode = UART_GPIO_MODE_SEL_GPIO; | ||
512 | } | ||
513 | |||
514 | vizzini_set_reg(port, block, UART_FLOW, flow); | ||
515 | vizzini_set_reg(port, block, UART_GPIO_MODE, gpio_mode); | ||
516 | |||
517 | if (portdata->trans9) { | ||
518 | /* Turn on wide mode if we're 9-bit transparent. */ | ||
519 | vizzini_set_reg(port, EPLOCALS_REG_BLOCK, (block * MEM_EP_LOCALS_SIZE) + EP_WIDE_MODE, 1); | ||
520 | #ifdef VIZZINI_IWA | ||
521 | } else if (portdata->iwa != UART_FORMAT_PARITY_NONE) { | ||
522 | vizzini_set_reg(port, EPLOCALS_REG_BLOCK, (block * MEM_EP_LOCALS_SIZE) + EP_WIDE_MODE, 1); | ||
523 | #endif | ||
524 | } else if (!portdata->preciseflags) { | ||
525 | /* Turn off wide mode unless we have precise flags. */ | ||
526 | vizzini_set_reg(port, EPLOCALS_REG_BLOCK, (block * MEM_EP_LOCALS_SIZE) + EP_WIDE_MODE, 0); | ||
527 | } | ||
528 | |||
529 | rate = tty_get_baud_rate(tty); | ||
530 | if (rate) | ||
531 | vizzini_set_baud_rate(port, rate); | ||
532 | |||
533 | vizzini_enable(port); | ||
534 | } | ||
535 | |||
536 | static void vizzini_break_ctl(struct tty_struct *tty, int break_state) | ||
537 | { | ||
538 | struct usb_serial_port *port = tty->driver_data; | ||
539 | |||
540 | dev_dbg(&port->dev, "BREAK %d\n", break_state); | ||
541 | if (break_state) | ||
542 | acm_send_break(port, 0x10); | ||
543 | else | ||
544 | acm_send_break(port, 0x000); | ||
545 | } | ||
546 | |||
547 | static int vizzini_tiocmget(struct tty_struct *tty) | ||
548 | { | ||
549 | struct usb_serial_port *port = tty->driver_data; | ||
550 | struct vizzini_port_private *portdata = usb_get_serial_port_data(port); | ||
551 | |||
552 | return (portdata->ctrlout & ACM_CTRL_DTR ? TIOCM_DTR : 0) | | ||
553 | (portdata->ctrlout & ACM_CTRL_RTS ? TIOCM_RTS : 0) | | ||
554 | (portdata->ctrlin & ACM_CTRL_DSR ? TIOCM_DSR : 0) | | ||
555 | (portdata->ctrlin & ACM_CTRL_RI ? TIOCM_RI : 0) | | ||
556 | (portdata->ctrlin & ACM_CTRL_DCD ? TIOCM_CD : 0) | | ||
557 | TIOCM_CTS; | ||
558 | } | ||
559 | |||
560 | static int vizzini_tiocmset(struct tty_struct *tty, | ||
561 | unsigned int set, unsigned int clear) | ||
562 | { | ||
563 | struct usb_serial_port *port = tty->driver_data; | ||
564 | struct vizzini_port_private *portdata = usb_get_serial_port_data(port); | ||
565 | unsigned int newctrl; | ||
566 | |||
567 | newctrl = portdata->ctrlout; | ||
568 | set = (set & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (set & TIOCM_RTS ? ACM_CTRL_RTS : 0); | ||
569 | clear = (clear & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (clear & TIOCM_RTS ? ACM_CTRL_RTS : 0); | ||
570 | |||
571 | newctrl = (newctrl & ~clear) | set; | ||
572 | |||
573 | if (portdata->ctrlout == newctrl) | ||
574 | return 0; | ||
575 | return acm_set_control(port, portdata->ctrlout = newctrl); | ||
576 | } | ||
577 | |||
578 | static int vizzini_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) | ||
579 | { | ||
580 | struct usb_serial_port *port = tty->driver_data; | ||
581 | struct vizzini_port_private *portdata = usb_get_serial_port_data(port); | ||
582 | struct serial_struct ss; | ||
583 | |||
584 | dev_dbg(&port->dev, "%s %08x\n", __func__, cmd); | ||
585 | |||
586 | switch (cmd) { | ||
587 | case TIOCGSERIAL: | ||
588 | if (!arg) | ||
589 | return -EFAULT; | ||
590 | memset(&ss, 0, sizeof(ss)); | ||
591 | ss.baud_base = portdata->baud_base; | ||
592 | if (copy_to_user((void __user *)arg, &ss, sizeof(ss))) | ||
593 | return -EFAULT; | ||
594 | break; | ||
595 | |||
596 | case TIOCSSERIAL: | ||
597 | if (!arg) | ||
598 | return -EFAULT; | ||
599 | if (copy_from_user(&ss, (void __user *)arg, sizeof(ss))) | ||
600 | return -EFAULT; | ||
601 | portdata->baud_base = ss.baud_base; | ||
602 | dev_dbg(&port->dev, "baud_base=%d\n", portdata->baud_base); | ||
603 | |||
604 | vizzini_disable(port); | ||
605 | if (portdata->baud_base) | ||
606 | vizzini_set_baud_rate(port, portdata->baud_base); | ||
607 | vizzini_enable(port); | ||
608 | break; | ||
609 | |||
610 | default: | ||
611 | return -ENOIOCTLCMD; | ||
612 | } | ||
613 | |||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | #ifdef VIZZINI_IWA | ||
618 | static const int vizzini_parity[] = { | ||
619 | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, | ||
620 | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, | ||
621 | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, | ||
622 | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, | ||
623 | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, | ||
624 | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, | ||
625 | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, | ||
626 | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, | ||
627 | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, | ||
628 | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, | ||
629 | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, | ||
630 | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, | ||
631 | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, | ||
632 | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, | ||
633 | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, | ||
634 | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 | ||
635 | }; | ||
636 | #endif | ||
637 | |||
638 | static void vizzini_out_callback(struct urb *urb) | ||
639 | { | ||
640 | struct usb_serial_port *port = urb->context; | ||
641 | struct vizzini_port_private *portdata = usb_get_serial_port_data(port); | ||
642 | int status = urb->status; | ||
643 | unsigned long flags; | ||
644 | |||
645 | dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number); | ||
646 | |||
647 | /* free up the transfer buffer, as usb_free_urb() does not do this */ | ||
648 | kfree(urb->transfer_buffer); | ||
649 | |||
650 | if (status) | ||
651 | dev_dbg(&port->dev, "%s - nonzero write bulk status received: %d\n", __func__, status); | ||
652 | |||
653 | spin_lock_irqsave(&portdata->lock, flags); | ||
654 | --portdata->outstanding_urbs; | ||
655 | spin_unlock_irqrestore(&portdata->lock, flags); | ||
656 | |||
657 | usb_serial_port_softint(port); | ||
658 | } | ||
659 | |||
660 | static int vizzini_write_room(struct tty_struct *tty) | ||
661 | { | ||
662 | struct usb_serial_port *port = tty->driver_data; | ||
663 | struct vizzini_port_private *portdata = usb_get_serial_port_data(port); | ||
664 | unsigned long flags; | ||
665 | |||
666 | dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number); | ||
667 | |||
668 | /* try to give a good number back based on if we have any free urbs at | ||
669 | * this point in time */ | ||
670 | spin_lock_irqsave(&portdata->lock, flags); | ||
671 | if (portdata->outstanding_urbs > N_OUT_URB * 2 / 3) { | ||
672 | spin_unlock_irqrestore(&portdata->lock, flags); | ||
673 | dev_dbg(&port->dev, "%s - write limit hit\n", __func__); | ||
674 | return 0; | ||
675 | } | ||
676 | spin_unlock_irqrestore(&portdata->lock, flags); | ||
677 | |||
678 | return 2048; | ||
679 | } | ||
680 | |||
681 | static int vizzini_write(struct tty_struct *tty, struct usb_serial_port *port, | ||
682 | const unsigned char *buf, int count) | ||
683 | { | ||
684 | struct vizzini_port_private *portdata = usb_get_serial_port_data(port); | ||
685 | struct usb_serial *serial = port->serial; | ||
686 | int bufsize = count; | ||
687 | unsigned long flags; | ||
688 | unsigned char *buffer; | ||
689 | struct urb *urb; | ||
690 | int status; | ||
691 | |||
692 | portdata = usb_get_serial_port_data(port); | ||
693 | |||
694 | dev_dbg(&port->dev, "%s: write (%d chars)\n", __func__, count); | ||
695 | |||
696 | spin_lock_irqsave(&portdata->lock, flags); | ||
697 | if (portdata->outstanding_urbs > N_OUT_URB) { | ||
698 | spin_unlock_irqrestore(&portdata->lock, flags); | ||
699 | dev_dbg(&port->dev, "%s - write limit hit\n", __func__); | ||
700 | return 0; | ||
701 | } | ||
702 | portdata->outstanding_urbs++; | ||
703 | spin_unlock_irqrestore(&portdata->lock, flags); | ||
704 | |||
705 | #ifdef VIZZINI_IWA | ||
706 | if (portdata->iwa != UART_FORMAT_PARITY_NONE) | ||
707 | bufsize = count * 2; | ||
708 | #endif | ||
709 | buffer = kmalloc(bufsize, GFP_ATOMIC); | ||
710 | |||
711 | if (!buffer) { | ||
712 | dev_err(&port->dev, "out of memory\n"); | ||
713 | count = -ENOMEM; | ||
714 | goto error_no_buffer; | ||
715 | } | ||
716 | |||
717 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
718 | if (!urb) { | ||
719 | dev_err(&port->dev, "no more free urbs\n"); | ||
720 | count = -ENOMEM; | ||
721 | goto error_no_urb; | ||
722 | } | ||
723 | |||
724 | #ifdef VIZZINI_IWA | ||
725 | if (portdata->iwa != UART_FORMAT_PARITY_NONE) { | ||
726 | int i; | ||
727 | char *b = buffer; | ||
728 | for (i = 0; i < count; ++i) { | ||
729 | int c, p = 0; | ||
730 | c = buf[i]; | ||
731 | switch (portdata->iwa) { | ||
732 | case UART_FORMAT_PARITY_ODD: | ||
733 | p = !vizzini_parity[c]; | ||
734 | break; | ||
735 | case UART_FORMAT_PARITY_EVEN: | ||
736 | p = vizzini_parity[c]; | ||
737 | break; | ||
738 | case UART_FORMAT_PARITY_1: | ||
739 | p = 1; | ||
740 | break; | ||
741 | case UART_FORMAT_PARITY_0: | ||
742 | p = 0; | ||
743 | break; | ||
744 | } | ||
745 | *b++ = c; | ||
746 | *b++ = p; | ||
747 | } | ||
748 | } else | ||
749 | #endif | ||
750 | memcpy(buffer, buf, count); | ||
751 | |||
752 | usb_fill_bulk_urb(urb, serial->dev, | ||
753 | usb_sndbulkpipe(serial->dev, | ||
754 | port->bulk_out_endpointAddress), | ||
755 | buffer, bufsize, vizzini_out_callback, port); | ||
756 | |||
757 | /* send it down the pipe */ | ||
758 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
759 | if (status) { | ||
760 | dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", __func__, status); | ||
761 | count = status; | ||
762 | goto error; | ||
763 | } | ||
764 | |||
765 | /* we are done with this urb, so let the host driver | ||
766 | * really free it when it is finished with it */ | ||
767 | usb_free_urb(urb); | ||
768 | |||
769 | return count; | ||
770 | error: | ||
771 | usb_free_urb(urb); | ||
772 | error_no_urb: | ||
773 | kfree(buffer); | ||
774 | error_no_buffer: | ||
775 | spin_lock_irqsave(&portdata->lock, flags); | ||
776 | --portdata->outstanding_urbs; | ||
777 | spin_unlock_irqrestore(&portdata->lock, flags); | ||
778 | return count; | ||
779 | } | ||
780 | |||
781 | static void vizzini_in_callback(struct urb *urb) | ||
782 | { | ||
783 | int endpoint = usb_pipeendpoint(urb->pipe); | ||
784 | struct usb_serial_port *port = urb->context; | ||
785 | struct vizzini_port_private *portdata = usb_get_serial_port_data(port); | ||
786 | struct tty_struct *tty = port->port.tty; | ||
787 | int preciseflags = portdata->preciseflags; | ||
788 | char *transfer_buffer = urb->transfer_buffer; | ||
789 | int length, room, have_extra_byte; | ||
790 | int err; | ||
791 | |||
792 | if (urb->status) { | ||
793 | dev_dbg(&port->dev, "%s: nonzero status: %d on endpoint %02x.\n", __func__, urb->status, endpoint); | ||
794 | return; | ||
795 | } | ||
796 | |||
797 | #ifdef VIZZINI_IWA | ||
798 | if (portdata->iwa != UART_FORMAT_PARITY_NONE) | ||
799 | preciseflags = true; | ||
800 | #endif | ||
801 | |||
802 | length = urb->actual_length; | ||
803 | if (length == 0) { | ||
804 | dev_dbg(&port->dev, "%s: empty read urb received\n", __func__); | ||
805 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
806 | if (err) | ||
807 | dev_err(&port->dev, "resubmit read urb failed. (%d)\n", err); | ||
808 | return; | ||
809 | } | ||
810 | |||
811 | length = length + (portdata->have_extra_byte ? 1 : 0); | ||
812 | have_extra_byte = (preciseflags && (length & 1)); | ||
813 | length = (preciseflags) ? (length / 2) : length; | ||
814 | |||
815 | room = tty_buffer_request_room(tty, length); | ||
816 | if (room != length) | ||
817 | dev_dbg(&port->dev, "Not enough room in TTY buf, dropped %d chars.\n", length - room); | ||
818 | |||
819 | if (room) { | ||
820 | if (preciseflags) { | ||
821 | char *dp = transfer_buffer; | ||
822 | int i, ch, ch_flags; | ||
823 | |||
824 | for (i = 0; i < room; ++i) { | ||
825 | char tty_flag; | ||
826 | |||
827 | if (i == 0) { | ||
828 | if (portdata->have_extra_byte) | ||
829 | ch = portdata->extra_byte; | ||
830 | else | ||
831 | ch = *dp++; | ||
832 | } else { | ||
833 | ch = *dp++; | ||
834 | } | ||
835 | ch_flags = *dp++; | ||
836 | |||
837 | #ifdef VIZZINI_IWA | ||
838 | { | ||
839 | int p; | ||
840 | switch (portdata->iwa) { | ||
841 | case UART_FORMAT_PARITY_ODD: | ||
842 | p = !vizzini_parity[ch]; | ||
843 | break; | ||
844 | case UART_FORMAT_PARITY_EVEN: | ||
845 | p = vizzini_parity[ch]; | ||
846 | break; | ||
847 | case UART_FORMAT_PARITY_1: | ||
848 | p = 1; | ||
849 | break; | ||
850 | case UART_FORMAT_PARITY_0: | ||
851 | p = 0; | ||
852 | break; | ||
853 | default: | ||
854 | p = 0; | ||
855 | break; | ||
856 | } | ||
857 | ch_flags ^= p; | ||
858 | } | ||
859 | #endif | ||
860 | if (ch_flags & RAMCTL_BUFFER_PARITY) | ||
861 | tty_flag = TTY_PARITY; | ||
862 | else if (ch_flags & RAMCTL_BUFFER_BREAK) | ||
863 | tty_flag = TTY_BREAK; | ||
864 | else if (ch_flags & RAMCTL_BUFFER_FRAME) | ||
865 | tty_flag = TTY_FRAME; | ||
866 | else if (ch_flags & RAMCTL_BUFFER_OVERRUN) | ||
867 | tty_flag = TTY_OVERRUN; | ||
868 | else | ||
869 | tty_flag = TTY_NORMAL; | ||
870 | |||
871 | tty_insert_flip_char(tty, ch, tty_flag); | ||
872 | } | ||
873 | } else { | ||
874 | tty_insert_flip_string(tty, transfer_buffer, room); | ||
875 | } | ||
876 | |||
877 | tty_flip_buffer_push(tty); | ||
878 | } | ||
879 | |||
880 | portdata->have_extra_byte = have_extra_byte; | ||
881 | if (have_extra_byte) | ||
882 | portdata->extra_byte = transfer_buffer[urb->actual_length - 1]; | ||
883 | |||
884 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
885 | if (err) | ||
886 | dev_err(&port->dev, "resubmit read urb failed. (%d)\n", err); | ||
887 | } | ||
888 | |||
889 | static void vizzini_int_callback(struct urb *urb) | ||
890 | { | ||
891 | struct usb_serial_port *port = urb->context; | ||
892 | struct vizzini_port_private *portdata = usb_get_serial_port_data(port); | ||
893 | struct tty_struct *tty = port->port.tty; | ||
894 | |||
895 | struct usb_cdc_notification *dr = urb->transfer_buffer; | ||
896 | unsigned char *data; | ||
897 | int newctrl; | ||
898 | int status; | ||
899 | |||
900 | switch (urb->status) { | ||
901 | case 0: | ||
902 | /* success */ | ||
903 | break; | ||
904 | case -ECONNRESET: | ||
905 | case -ENOENT: | ||
906 | case -ESHUTDOWN: | ||
907 | /* this urb is terminated, clean up */ | ||
908 | dev_dbg(&port->dev, "urb shutting down with status: %d\n", urb->status); | ||
909 | return; | ||
910 | default: | ||
911 | dev_dbg(&port->dev, "nonzero urb status received: %d\n", urb->status); | ||
912 | goto exit; | ||
913 | } | ||
914 | |||
915 | data = (unsigned char *)(dr + 1); | ||
916 | switch (dr->bNotificationType) { | ||
917 | |||
918 | case USB_CDC_NOTIFY_NETWORK_CONNECTION: | ||
919 | dev_dbg(&port->dev, "%s network\n", dr->wValue ? "connected to" : "disconnected from"); | ||
920 | break; | ||
921 | |||
922 | case USB_CDC_NOTIFY_SERIAL_STATE: | ||
923 | newctrl = le16_to_cpu(get_unaligned((__le16 *)data)); | ||
924 | |||
925 | if (!portdata->clocal && (portdata->ctrlin & ~newctrl & ACM_CTRL_DCD)) { | ||
926 | dev_dbg(&port->dev, "calling hangup\n"); | ||
927 | tty_hangup(tty); | ||
928 | } | ||
929 | |||
930 | portdata->ctrlin = newctrl; | ||
931 | |||
932 | dev_dbg(&port->dev, "input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c\n", | ||
933 | portdata->ctrlin & ACM_CTRL_DCD ? '+' : '-', | ||
934 | portdata->ctrlin & ACM_CTRL_DSR ? '+' : '-', | ||
935 | portdata->ctrlin & ACM_CTRL_BRK ? '+' : '-', | ||
936 | portdata->ctrlin & ACM_CTRL_RI ? '+' : '-', | ||
937 | portdata->ctrlin & ACM_CTRL_FRAMING ? '+' : '-', | ||
938 | portdata->ctrlin & ACM_CTRL_PARITY ? '+' : '-', | ||
939 | portdata->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-'); | ||
940 | break; | ||
941 | |||
942 | default: | ||
943 | dev_dbg(&port->dev, "unknown notification %d received: index %d len %d data0 %d data1 %d\n", | ||
944 | dr->bNotificationType, dr->wIndex, | ||
945 | dr->wLength, data[0], data[1]); | ||
946 | break; | ||
947 | } | ||
948 | exit: | ||
949 | dev_dbg(&port->dev, "Resubmitting interrupt IN urb %p\n", urb); | ||
950 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
951 | if (status) | ||
952 | dev_err(&port->dev, "usb_submit_urb failed with result %d", status); | ||
953 | } | ||
954 | |||
955 | static int vizzini_open(struct tty_struct *tty_param, struct usb_serial_port *port) | ||
956 | { | ||
957 | struct vizzini_port_private *portdata; | ||
958 | struct usb_serial *serial = port->serial; | ||
959 | struct tty_struct *tty = port->port.tty; | ||
960 | int i; | ||
961 | struct urb *urb; | ||
962 | int result; | ||
963 | |||
964 | portdata = usb_get_serial_port_data(port); | ||
965 | |||
966 | acm_set_control(port, portdata->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS); | ||
967 | |||
968 | /* Reset low level data toggle and start reading from endpoints */ | ||
969 | for (i = 0; i < N_IN_URB; i++) { | ||
970 | dev_dbg(&port->dev, "%s urb %d\n", __func__, i); | ||
971 | |||
972 | urb = portdata->in_urbs[i]; | ||
973 | if (!urb) | ||
974 | continue; | ||
975 | if (urb->dev != serial->dev) { | ||
976 | dev_dbg(&port->dev, "%s: dev %p != %p\n", __func__, | ||
977 | urb->dev, serial->dev); | ||
978 | continue; | ||
979 | } | ||
980 | |||
981 | /* | ||
982 | * make sure endpoint data toggle is synchronized with the | ||
983 | * device | ||
984 | */ | ||
985 | /* dev_dbg(&port->dev, "%s clearing halt on %x\n", __func__, urb->pipe); */ | ||
986 | /* usb_clear_halt(urb->dev, urb->pipe); */ | ||
987 | |||
988 | dev_dbg(&port->dev, "%s submitting urb %p\n", __func__, urb); | ||
989 | result = usb_submit_urb(urb, GFP_KERNEL); | ||
990 | if (result) { | ||
991 | dev_err(&port->dev, "submit urb %d failed (%d) %d\n", | ||
992 | i, result, urb->transfer_buffer_length); | ||
993 | } | ||
994 | } | ||
995 | |||
996 | tty->low_latency = 1; | ||
997 | |||
998 | /* start up the interrupt endpoint if we have one */ | ||
999 | if (port->interrupt_in_urb) { | ||
1000 | result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); | ||
1001 | if (result) | ||
1002 | dev_err(&port->dev, "submit irq_in urb failed %d\n", | ||
1003 | result); | ||
1004 | } | ||
1005 | return 0; | ||
1006 | } | ||
1007 | |||
1008 | static void vizzini_close(struct usb_serial_port *port) | ||
1009 | { | ||
1010 | int i; | ||
1011 | struct usb_serial *serial = port->serial; | ||
1012 | struct vizzini_port_private *portdata; | ||
1013 | struct tty_struct *tty = port->port.tty; | ||
1014 | |||
1015 | portdata = usb_get_serial_port_data(port); | ||
1016 | |||
1017 | acm_set_control(port, portdata->ctrlout = 0); | ||
1018 | |||
1019 | if (serial->dev) { | ||
1020 | /* Stop reading/writing urbs */ | ||
1021 | for (i = 0; i < N_IN_URB; i++) | ||
1022 | usb_kill_urb(portdata->in_urbs[i]); | ||
1023 | } | ||
1024 | |||
1025 | usb_kill_urb(port->interrupt_in_urb); | ||
1026 | |||
1027 | tty = NULL; /* FIXME */ | ||
1028 | } | ||
1029 | |||
1030 | static int vizzini_attach(struct usb_serial *serial) | ||
1031 | { | ||
1032 | struct vizzini_serial_private *serial_priv = usb_get_serial_data(serial); | ||
1033 | struct usb_interface *interface = serial_priv->data_interface; | ||
1034 | struct usb_host_interface *iface_desc; | ||
1035 | struct usb_endpoint_descriptor *endpoint; | ||
1036 | struct usb_endpoint_descriptor *bulk_in_endpoint = NULL; | ||
1037 | struct usb_endpoint_descriptor *bulk_out_endpoint = NULL; | ||
1038 | |||
1039 | struct usb_serial_port *port; | ||
1040 | struct vizzini_port_private *portdata; | ||
1041 | struct urb *urb; | ||
1042 | int i, j; | ||
1043 | |||
1044 | /* Assume that there's exactly one serial port. */ | ||
1045 | port = serial->port[0]; | ||
1046 | |||
1047 | /* The usb_serial is now fully set up, but we want to make a | ||
1048 | * couple of modifications. Namely, it was configured based | ||
1049 | * upon the control interface and not the data interface, so | ||
1050 | * it has no notion of the bulk in and out endpoints. So we | ||
1051 | * essentially do some of the same allocations and | ||
1052 | * configurations that the usb-serial core would have done if | ||
1053 | * it had not made any faulty assumptions about the | ||
1054 | * endpoints. */ | ||
1055 | |||
1056 | iface_desc = interface->cur_altsetting; | ||
1057 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | ||
1058 | endpoint = &iface_desc->endpoint[i].desc; | ||
1059 | |||
1060 | if (usb_endpoint_is_bulk_in(endpoint)) | ||
1061 | bulk_in_endpoint = endpoint; | ||
1062 | |||
1063 | if (usb_endpoint_is_bulk_out(endpoint)) | ||
1064 | bulk_out_endpoint = endpoint; | ||
1065 | } | ||
1066 | |||
1067 | if (!bulk_out_endpoint || !bulk_in_endpoint) { | ||
1068 | dev_dbg(&port->dev, "Missing endpoint!\n"); | ||
1069 | return -EINVAL; | ||
1070 | } | ||
1071 | |||
1072 | port->bulk_out_endpointAddress = bulk_out_endpoint->bEndpointAddress; | ||
1073 | port->bulk_in_endpointAddress = bulk_in_endpoint->bEndpointAddress; | ||
1074 | |||
1075 | portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); | ||
1076 | if (!portdata) { | ||
1077 | dev_dbg(&port->dev, "%s: kmalloc for vizzini_port_private (%d) failed!.\n", | ||
1078 | __func__, i); | ||
1079 | return -ENOMEM; | ||
1080 | } | ||
1081 | spin_lock_init(&portdata->lock); | ||
1082 | for (j = 0; j < N_IN_URB; j++) { | ||
1083 | portdata->in_buffer[j] = kmalloc(IN_BUFLEN, GFP_KERNEL); | ||
1084 | if (!portdata->in_buffer[j]) { | ||
1085 | for (--j; j >= 0; j--) | ||
1086 | kfree(portdata->in_buffer[j]); | ||
1087 | kfree(portdata); | ||
1088 | return -ENOMEM; | ||
1089 | } | ||
1090 | } | ||
1091 | |||
1092 | /* Bulk OUT endpoints 0x1..0x4 map to register blocks 0..3 */ | ||
1093 | portdata->block = port->bulk_out_endpointAddress - 1; | ||
1094 | |||
1095 | usb_set_serial_port_data(port, portdata); | ||
1096 | |||
1097 | portdata->bcd_device = le16_to_cpu(serial->dev->descriptor.bcdDevice); | ||
1098 | if (vizzini_rev_a(port)) | ||
1099 | dev_info(&port->dev, "Adapting to revA silicon\n"); | ||
1100 | |||
1101 | /* initialize the in urbs */ | ||
1102 | for (j = 0; j < N_IN_URB; ++j) { | ||
1103 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1104 | if (urb == NULL) { | ||
1105 | dev_dbg(&port->dev, "%s: alloc for in port failed.\n", __func__); | ||
1106 | continue; | ||
1107 | } | ||
1108 | /* Fill URB using supplied data. */ | ||
1109 | dev_dbg(&port->dev, "Filling URB %p, EP=%d buf=%p len=%d\n", urb, port->bulk_in_endpointAddress, portdata->in_buffer[j], IN_BUFLEN); | ||
1110 | usb_fill_bulk_urb(urb, serial->dev, | ||
1111 | usb_rcvbulkpipe(serial->dev, | ||
1112 | port->bulk_in_endpointAddress), | ||
1113 | portdata->in_buffer[j], IN_BUFLEN, | ||
1114 | vizzini_in_callback, port); | ||
1115 | portdata->in_urbs[j] = urb; | ||
1116 | } | ||
1117 | |||
1118 | return 0; | ||
1119 | } | ||
1120 | |||
1121 | static void vizzini_serial_disconnect(struct usb_serial *serial) | ||
1122 | { | ||
1123 | struct usb_serial_port *port; | ||
1124 | struct vizzini_port_private *portdata; | ||
1125 | int i, j; | ||
1126 | |||
1127 | dev_dbg(&serial->dev->dev, "%s %p\n", __func__, serial); | ||
1128 | |||
1129 | for (i = 0; i < serial->num_ports; ++i) { | ||
1130 | port = serial->port[i]; | ||
1131 | if (!port) | ||
1132 | continue; | ||
1133 | portdata = usb_get_serial_port_data(port); | ||
1134 | if (!portdata) | ||
1135 | continue; | ||
1136 | |||
1137 | for (j = 0; j < N_IN_URB; j++) { | ||
1138 | usb_kill_urb(portdata->in_urbs[j]); | ||
1139 | usb_free_urb(portdata->in_urbs[j]); | ||
1140 | } | ||
1141 | } | ||
1142 | } | ||
1143 | |||
1144 | static void vizzini_serial_release(struct usb_serial *serial) | ||
1145 | { | ||
1146 | struct usb_serial_port *port; | ||
1147 | struct vizzini_port_private *portdata; | ||
1148 | int i, j; | ||
1149 | |||
1150 | dev_dbg(&serial->dev->dev, "%s %p\n", __func__, serial); | ||
1151 | |||
1152 | for (i = 0; i < serial->num_ports; ++i) { | ||
1153 | port = serial->port[i]; | ||
1154 | if (!port) | ||
1155 | continue; | ||
1156 | portdata = usb_get_serial_port_data(port); | ||
1157 | if (!portdata) | ||
1158 | continue; | ||
1159 | |||
1160 | for (j = 0; j < N_IN_URB; j++) | ||
1161 | kfree(portdata->in_buffer[j]); | ||
1162 | |||
1163 | kfree(portdata); | ||
1164 | usb_set_serial_port_data(port, NULL); | ||
1165 | } | ||
1166 | } | ||
1167 | |||
1168 | static int vizzini_calc_num_ports(struct usb_serial *serial) | ||
1169 | { | ||
1170 | return 1; | ||
1171 | } | ||
1172 | |||
1173 | static int vizzini_probe(struct usb_serial *serial, | ||
1174 | const struct usb_device_id *id) | ||
1175 | { | ||
1176 | struct usb_interface *intf = serial->interface; | ||
1177 | unsigned char *buffer = intf->altsetting->extra; | ||
1178 | int buflen = intf->altsetting->extralen; | ||
1179 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
1180 | struct usb_cdc_union_desc *union_header = NULL; | ||
1181 | struct usb_cdc_country_functional_desc *cfd = NULL; | ||
1182 | int call_interface_num = -1; | ||
1183 | int data_interface_num; | ||
1184 | struct usb_interface *control_interface; | ||
1185 | struct usb_interface *data_interface; | ||
1186 | struct usb_endpoint_descriptor *epctrl; | ||
1187 | struct usb_endpoint_descriptor *epread; | ||
1188 | struct usb_endpoint_descriptor *epwrite; | ||
1189 | struct vizzini_serial_private *serial_priv; | ||
1190 | |||
1191 | if (!buffer) { | ||
1192 | dev_err(&intf->dev, "Weird descriptor references\n"); | ||
1193 | return -EINVAL; | ||
1194 | } | ||
1195 | |||
1196 | if (!buflen) { | ||
1197 | if (intf->cur_altsetting->endpoint->extralen && intf->cur_altsetting->endpoint->extra) { | ||
1198 | dev_dbg(&intf->dev, "Seeking extra descriptors on endpoint\n"); | ||
1199 | buflen = intf->cur_altsetting->endpoint->extralen; | ||
1200 | buffer = intf->cur_altsetting->endpoint->extra; | ||
1201 | } else { | ||
1202 | dev_err(&intf->dev, "Zero length descriptor references\n"); | ||
1203 | return -EINVAL; | ||
1204 | } | ||
1205 | } | ||
1206 | |||
1207 | while (buflen > 0) { | ||
1208 | if (buffer[1] != USB_DT_CS_INTERFACE) { | ||
1209 | dev_err(&intf->dev, "skipping garbage\n"); | ||
1210 | goto next_desc; | ||
1211 | } | ||
1212 | |||
1213 | switch (buffer[2]) { | ||
1214 | case USB_CDC_UNION_TYPE: /* we've found it */ | ||
1215 | if (union_header) { | ||
1216 | dev_err(&intf->dev, "More than one union descriptor, skipping ...\n"); | ||
1217 | goto next_desc; | ||
1218 | } | ||
1219 | union_header = (struct usb_cdc_union_desc *)buffer; | ||
1220 | break; | ||
1221 | case USB_CDC_COUNTRY_TYPE: /* export through sysfs */ | ||
1222 | cfd = (struct usb_cdc_country_functional_desc *)buffer; | ||
1223 | break; | ||
1224 | case USB_CDC_HEADER_TYPE: /* maybe check version */ | ||
1225 | break; /* for now we ignore it */ | ||
1226 | case USB_CDC_CALL_MANAGEMENT_TYPE: | ||
1227 | call_interface_num = buffer[4]; | ||
1228 | break; | ||
1229 | default: | ||
1230 | /* there are LOTS more CDC descriptors that | ||
1231 | * could legitimately be found here. | ||
1232 | */ | ||
1233 | dev_dbg(&intf->dev, "Ignoring descriptor: type %02x, length %d\n", buffer[2], buffer[0]); | ||
1234 | break; | ||
1235 | } | ||
1236 | next_desc: | ||
1237 | buflen -= buffer[0]; | ||
1238 | buffer += buffer[0]; | ||
1239 | } | ||
1240 | |||
1241 | if (!union_header) { | ||
1242 | if (call_interface_num > 0) { | ||
1243 | dev_dbg(&intf->dev, "No union descriptor, using call management descriptor\n"); | ||
1244 | data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num)); | ||
1245 | control_interface = intf; | ||
1246 | } else { | ||
1247 | dev_dbg(&intf->dev, "No union descriptor, giving up\n"); | ||
1248 | return -ENODEV; | ||
1249 | } | ||
1250 | } else { | ||
1251 | control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0); | ||
1252 | data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0)); | ||
1253 | if (!control_interface || !data_interface) { | ||
1254 | dev_dbg(&intf->dev, "no interfaces\n"); | ||
1255 | return -ENODEV; | ||
1256 | } | ||
1257 | } | ||
1258 | |||
1259 | if (data_interface_num != call_interface_num) | ||
1260 | dev_dbg(&intf->dev, "Separate call control interface. That is not fully supported.\n"); | ||
1261 | |||
1262 | /* workaround for switched interfaces */ | ||
1263 | if (data_interface->cur_altsetting->desc.bInterfaceClass != CDC_DATA_INTERFACE_TYPE) { | ||
1264 | if (control_interface->cur_altsetting->desc.bInterfaceClass == CDC_DATA_INTERFACE_TYPE) { | ||
1265 | struct usb_interface *t; | ||
1266 | |||
1267 | t = control_interface; | ||
1268 | control_interface = data_interface; | ||
1269 | data_interface = t; | ||
1270 | } else { | ||
1271 | return -EINVAL; | ||
1272 | } | ||
1273 | } | ||
1274 | |||
1275 | /* Accept probe requests only for the control interface */ | ||
1276 | if (intf != control_interface) | ||
1277 | return -ENODEV; | ||
1278 | |||
1279 | if (usb_interface_claimed(data_interface)) { /* valid in this context */ | ||
1280 | dev_dbg(&intf->dev, "The data interface isn't available\n"); | ||
1281 | return -EBUSY; | ||
1282 | } | ||
1283 | |||
1284 | if (data_interface->cur_altsetting->desc.bNumEndpoints < 2) | ||
1285 | return -EINVAL; | ||
1286 | |||
1287 | epctrl = &control_interface->cur_altsetting->endpoint[0].desc; | ||
1288 | epread = &data_interface->cur_altsetting->endpoint[0].desc; | ||
1289 | epwrite = &data_interface->cur_altsetting->endpoint[1].desc; | ||
1290 | if (!usb_endpoint_dir_in(epread)) { | ||
1291 | struct usb_endpoint_descriptor *t; | ||
1292 | t = epread; | ||
1293 | epread = epwrite; | ||
1294 | epwrite = t; | ||
1295 | } | ||
1296 | |||
1297 | /* The documentation suggests that we allocate private storage | ||
1298 | * with the attach() entry point, but we can't allow the data | ||
1299 | * interface to remain unclaimed until then; so we need | ||
1300 | * somewhere to save the claimed interface now. */ | ||
1301 | serial_priv = kzalloc(sizeof(struct vizzini_serial_private), | ||
1302 | GFP_KERNEL); | ||
1303 | if (!serial_priv) | ||
1304 | goto alloc_fail; | ||
1305 | usb_set_serial_data(serial, serial_priv); | ||
1306 | |||
1307 | //usb_driver_claim_interface(&vizzini_driver, data_interface, NULL); | ||
1308 | |||
1309 | /* Don't set the data interface private data. When we | ||
1310 | * disconnect we test this field against NULL to discover | ||
1311 | * whether we're dealing with the control or data | ||
1312 | * interface. */ | ||
1313 | serial_priv->data_interface = data_interface; | ||
1314 | |||
1315 | return 0; | ||
1316 | |||
1317 | alloc_fail: | ||
1318 | return -ENOMEM; | ||
1319 | } | ||
1320 | |||
1321 | static struct usb_serial_driver vizzini_device = { | ||
1322 | .driver = { | ||
1323 | .owner = THIS_MODULE, | ||
1324 | .name = "vizzini", | ||
1325 | }, | ||
1326 | .description = "Vizzini USB serial port", | ||
1327 | .id_table = id_table, | ||
1328 | .calc_num_ports = vizzini_calc_num_ports, | ||
1329 | .probe = vizzini_probe, | ||
1330 | .open = vizzini_open, | ||
1331 | .close = vizzini_close, | ||
1332 | .write = vizzini_write, | ||
1333 | .write_room = vizzini_write_room, | ||
1334 | .ioctl = vizzini_ioctl, | ||
1335 | .set_termios = vizzini_set_termios, | ||
1336 | .break_ctl = vizzini_break_ctl, | ||
1337 | .tiocmget = vizzini_tiocmget, | ||
1338 | .tiocmset = vizzini_tiocmset, | ||
1339 | .attach = vizzini_attach, | ||
1340 | .disconnect = vizzini_serial_disconnect, | ||
1341 | .release = vizzini_serial_release, | ||
1342 | .read_int_callback = vizzini_int_callback, | ||
1343 | }; | ||
1344 | |||
1345 | static struct usb_serial_driver * const serial_drivers[] = { | ||
1346 | &vizzini_device, NULL | ||
1347 | }; | ||
1348 | |||
1349 | module_usb_serial_driver(serial_drivers, id_table); | ||
1350 | |||
1351 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
1352 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
1353 | MODULE_VERSION(DRIVER_VERSION); | ||
1354 | MODULE_LICENSE("GPL"); | ||