Commit 6b447f04a9aecdf2a30c1a97e4b034ac7931bb70
Committed by
Linus Torvalds
1 parent
eeb4613436
Exists in
master
and in
4 other branches
tty: Drop the lock_kernel in the private ioctl hook
We don't need the BKL here any more so it can go. In a couple of spots the driver requirements are not clear so push the lock down into the driver. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 5 changed files with 14 additions and 8 deletions Inline Diff
drivers/usb/serial/ftdi_sio.c
1 | /* | 1 | /* |
2 | * USB FTDI SIO driver | 2 | * USB FTDI SIO driver |
3 | * | 3 | * |
4 | * Copyright (C) 1999 - 2001 | 4 | * Copyright (C) 1999 - 2001 |
5 | * Greg Kroah-Hartman (greg@kroah.com) | 5 | * Greg Kroah-Hartman (greg@kroah.com) |
6 | * Bill Ryder (bryder@sgi.com) | 6 | * Bill Ryder (bryder@sgi.com) |
7 | * Copyright (C) 2002 | 7 | * Copyright (C) 2002 |
8 | * Kuba Ober (kuba@mareimbrium.org) | 8 | * Kuba Ober (kuba@mareimbrium.org) |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
12 | * the Free Software Foundation; either version 2 of the License, or | 12 | * the Free Software Foundation; either version 2 of the License, or |
13 | * (at your option) any later version. | 13 | * (at your option) any later version. |
14 | * | 14 | * |
15 | * See Documentation/usb/usb-serial.txt for more information on using this | 15 | * See Documentation/usb/usb-serial.txt for more information on using this |
16 | * driver | 16 | * driver |
17 | * | 17 | * |
18 | * See http://ftdi-usb-sio.sourceforge.net for upto date testing info | 18 | * See http://ftdi-usb-sio.sourceforge.net for upto date testing info |
19 | * and extra documentation | 19 | * and extra documentation |
20 | * | 20 | * |
21 | * Change entries from 2004 and earlier can be found in versions of this | 21 | * Change entries from 2004 and earlier can be found in versions of this |
22 | * file in kernel versions prior to the 2.6.24 release. | 22 | * file in kernel versions prior to the 2.6.24 release. |
23 | * | 23 | * |
24 | */ | 24 | */ |
25 | 25 | ||
26 | /* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */ | 26 | /* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */ |
27 | /* Thanx to FTDI for so kindly providing details of the protocol required */ | 27 | /* Thanx to FTDI for so kindly providing details of the protocol required */ |
28 | /* to talk to the device */ | 28 | /* to talk to the device */ |
29 | /* Thanx to gkh and the rest of the usb dev group for all code I have | 29 | /* Thanx to gkh and the rest of the usb dev group for all code I have |
30 | assimilated :-) */ | 30 | assimilated :-) */ |
31 | 31 | ||
32 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
33 | #include <linux/errno.h> | 33 | #include <linux/errno.h> |
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/tty.h> | 36 | #include <linux/tty.h> |
37 | #include <linux/tty_driver.h> | 37 | #include <linux/tty_driver.h> |
38 | #include <linux/tty_flip.h> | 38 | #include <linux/tty_flip.h> |
39 | #include <linux/module.h> | 39 | #include <linux/module.h> |
40 | #include <linux/spinlock.h> | 40 | #include <linux/spinlock.h> |
41 | #include <linux/uaccess.h> | 41 | #include <linux/uaccess.h> |
42 | #include <linux/usb.h> | 42 | #include <linux/usb.h> |
43 | #include <linux/serial.h> | 43 | #include <linux/serial.h> |
44 | #include <linux/usb/serial.h> | 44 | #include <linux/usb/serial.h> |
45 | #include "ftdi_sio.h" | 45 | #include "ftdi_sio.h" |
46 | 46 | ||
47 | /* | 47 | /* |
48 | * Version Information | 48 | * Version Information |
49 | */ | 49 | */ |
50 | #define DRIVER_VERSION "v1.4.3" | 50 | #define DRIVER_VERSION "v1.4.3" |
51 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>" | 51 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>" |
52 | #define DRIVER_DESC "USB FTDI Serial Converters Driver" | 52 | #define DRIVER_DESC "USB FTDI Serial Converters Driver" |
53 | 53 | ||
54 | static int debug; | 54 | static int debug; |
55 | static __u16 vendor = FTDI_VID; | 55 | static __u16 vendor = FTDI_VID; |
56 | static __u16 product; | 56 | static __u16 product; |
57 | 57 | ||
58 | struct ftdi_private { | 58 | struct ftdi_private { |
59 | ftdi_chip_type_t chip_type; | 59 | ftdi_chip_type_t chip_type; |
60 | /* type of device, either SIO or FT8U232AM */ | 60 | /* type of device, either SIO or FT8U232AM */ |
61 | int baud_base; /* baud base clock for divisor setting */ | 61 | int baud_base; /* baud base clock for divisor setting */ |
62 | int custom_divisor; /* custom_divisor kludge, this is for | 62 | int custom_divisor; /* custom_divisor kludge, this is for |
63 | baud_base (different from what goes to the | 63 | baud_base (different from what goes to the |
64 | chip!) */ | 64 | chip!) */ |
65 | __u16 last_set_data_urb_value ; | 65 | __u16 last_set_data_urb_value ; |
66 | /* the last data state set - needed for doing | 66 | /* the last data state set - needed for doing |
67 | * a break | 67 | * a break |
68 | */ | 68 | */ |
69 | int write_offset; /* This is the offset in the usb data block to | 69 | int write_offset; /* This is the offset in the usb data block to |
70 | * write the serial data - it varies between | 70 | * write the serial data - it varies between |
71 | * devices | 71 | * devices |
72 | */ | 72 | */ |
73 | int flags; /* some ASYNC_xxxx flags are supported */ | 73 | int flags; /* some ASYNC_xxxx flags are supported */ |
74 | unsigned long last_dtr_rts; /* saved modem control outputs */ | 74 | unsigned long last_dtr_rts; /* saved modem control outputs */ |
75 | wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ | 75 | wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ |
76 | char prev_status, diff_status; /* Used for TIOCMIWAIT */ | 76 | char prev_status, diff_status; /* Used for TIOCMIWAIT */ |
77 | __u8 rx_flags; /* receive state flags (throttling) */ | 77 | __u8 rx_flags; /* receive state flags (throttling) */ |
78 | spinlock_t rx_lock; /* spinlock for receive state */ | 78 | spinlock_t rx_lock; /* spinlock for receive state */ |
79 | struct delayed_work rx_work; | 79 | struct delayed_work rx_work; |
80 | struct usb_serial_port *port; | 80 | struct usb_serial_port *port; |
81 | int rx_processed; | 81 | int rx_processed; |
82 | unsigned long rx_bytes; | 82 | unsigned long rx_bytes; |
83 | 83 | ||
84 | __u16 interface; /* FT2232C port interface (0 for FT232/245) */ | 84 | __u16 interface; /* FT2232C port interface (0 for FT232/245) */ |
85 | 85 | ||
86 | speed_t force_baud; /* if non-zero, force the baud rate to | 86 | speed_t force_baud; /* if non-zero, force the baud rate to |
87 | this value */ | 87 | this value */ |
88 | int force_rtscts; /* if non-zero, force RTS-CTS to always | 88 | int force_rtscts; /* if non-zero, force RTS-CTS to always |
89 | be enabled */ | 89 | be enabled */ |
90 | 90 | ||
91 | spinlock_t tx_lock; /* spinlock for transmit state */ | 91 | spinlock_t tx_lock; /* spinlock for transmit state */ |
92 | unsigned long tx_bytes; | 92 | unsigned long tx_bytes; |
93 | unsigned long tx_outstanding_bytes; | 93 | unsigned long tx_outstanding_bytes; |
94 | unsigned long tx_outstanding_urbs; | 94 | unsigned long tx_outstanding_urbs; |
95 | }; | 95 | }; |
96 | 96 | ||
97 | /* struct ftdi_sio_quirk is used by devices requiring special attention. */ | 97 | /* struct ftdi_sio_quirk is used by devices requiring special attention. */ |
98 | struct ftdi_sio_quirk { | 98 | struct ftdi_sio_quirk { |
99 | int (*probe)(struct usb_serial *); | 99 | int (*probe)(struct usb_serial *); |
100 | /* Special settings for probed ports. */ | 100 | /* Special settings for probed ports. */ |
101 | void (*port_probe)(struct ftdi_private *); | 101 | void (*port_probe)(struct ftdi_private *); |
102 | }; | 102 | }; |
103 | 103 | ||
104 | static int ftdi_jtag_probe(struct usb_serial *serial); | 104 | static int ftdi_jtag_probe(struct usb_serial *serial); |
105 | static int ftdi_mtxorb_hack_setup(struct usb_serial *serial); | 105 | static int ftdi_mtxorb_hack_setup(struct usb_serial *serial); |
106 | static void ftdi_USB_UIRT_setup(struct ftdi_private *priv); | 106 | static void ftdi_USB_UIRT_setup(struct ftdi_private *priv); |
107 | static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv); | 107 | static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv); |
108 | 108 | ||
109 | static struct ftdi_sio_quirk ftdi_jtag_quirk = { | 109 | static struct ftdi_sio_quirk ftdi_jtag_quirk = { |
110 | .probe = ftdi_jtag_probe, | 110 | .probe = ftdi_jtag_probe, |
111 | }; | 111 | }; |
112 | 112 | ||
113 | static struct ftdi_sio_quirk ftdi_mtxorb_hack_quirk = { | 113 | static struct ftdi_sio_quirk ftdi_mtxorb_hack_quirk = { |
114 | .probe = ftdi_mtxorb_hack_setup, | 114 | .probe = ftdi_mtxorb_hack_setup, |
115 | }; | 115 | }; |
116 | 116 | ||
117 | static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = { | 117 | static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = { |
118 | .port_probe = ftdi_USB_UIRT_setup, | 118 | .port_probe = ftdi_USB_UIRT_setup, |
119 | }; | 119 | }; |
120 | 120 | ||
121 | static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { | 121 | static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { |
122 | .port_probe = ftdi_HE_TIRA1_setup, | 122 | .port_probe = ftdi_HE_TIRA1_setup, |
123 | }; | 123 | }; |
124 | 124 | ||
125 | /* | 125 | /* |
126 | * The 8U232AM has the same API as the sio except for: | 126 | * The 8U232AM has the same API as the sio except for: |
127 | * - it can support MUCH higher baudrates; up to: | 127 | * - it can support MUCH higher baudrates; up to: |
128 | * o 921600 for RS232 and 2000000 for RS422/485 at 48MHz | 128 | * o 921600 for RS232 and 2000000 for RS422/485 at 48MHz |
129 | * o 230400 at 12MHz | 129 | * o 230400 at 12MHz |
130 | * so .. 8U232AM's baudrate setting codes are different | 130 | * so .. 8U232AM's baudrate setting codes are different |
131 | * - it has a two byte status code. | 131 | * - it has a two byte status code. |
132 | * - it returns characters every 16ms (the FTDI does it every 40ms) | 132 | * - it returns characters every 16ms (the FTDI does it every 40ms) |
133 | * | 133 | * |
134 | * the bcdDevice value is used to differentiate FT232BM and FT245BM from | 134 | * the bcdDevice value is used to differentiate FT232BM and FT245BM from |
135 | * the earlier FT8U232AM and FT8U232BM. For now, include all known VID/PID | 135 | * the earlier FT8U232AM and FT8U232BM. For now, include all known VID/PID |
136 | * combinations in both tables. | 136 | * combinations in both tables. |
137 | * FIXME: perhaps bcdDevice can also identify 12MHz FT8U232AM devices, | 137 | * FIXME: perhaps bcdDevice can also identify 12MHz FT8U232AM devices, |
138 | * but I don't know if those ever went into mass production. [Ian Abbott] | 138 | * but I don't know if those ever went into mass production. [Ian Abbott] |
139 | */ | 139 | */ |
140 | 140 | ||
141 | 141 | ||
142 | 142 | ||
143 | static struct usb_device_id id_table_combined [] = { | 143 | static struct usb_device_id id_table_combined [] = { |
144 | { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) }, | 144 | { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) }, |
145 | { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) }, | 145 | { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) }, |
146 | { USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) }, | 146 | { USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) }, |
147 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) }, | 147 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) }, |
148 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_1_PID) }, | 148 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_1_PID) }, |
149 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_2_PID) }, | 149 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_2_PID) }, |
150 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_3_PID) }, | 150 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_3_PID) }, |
151 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_4_PID) }, | 151 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_4_PID) }, |
152 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_5_PID) }, | 152 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_5_PID) }, |
153 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_6_PID) }, | 153 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_6_PID) }, |
154 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_7_PID) }, | 154 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_7_PID) }, |
155 | { USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) }, | 155 | { USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) }, |
156 | { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, | 156 | { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, |
157 | { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) }, | 157 | { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) }, |
158 | { USB_DEVICE(FTDI_VID, FTDI_IPLUS2_PID) }, | 158 | { USB_DEVICE(FTDI_VID, FTDI_IPLUS2_PID) }, |
159 | { USB_DEVICE(FTDI_VID, FTDI_DMX4ALL) }, | 159 | { USB_DEVICE(FTDI_VID, FTDI_DMX4ALL) }, |
160 | { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) }, | 160 | { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) }, |
161 | { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, | 161 | { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, |
162 | { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, | 162 | { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, |
163 | { USB_DEVICE(FTDI_VID, FTDI_232RL_PID) }, | 163 | { USB_DEVICE(FTDI_VID, FTDI_232RL_PID) }, |
164 | { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, | 164 | { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, |
165 | { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) }, | 165 | { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) }, |
166 | { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, | 166 | { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, |
167 | { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) }, | 167 | { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) }, |
168 | { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, | 168 | { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, |
169 | { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, | 169 | { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, |
170 | { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) }, | 170 | { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) }, |
171 | { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) }, | 171 | { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) }, |
172 | { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) }, | 172 | { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) }, |
173 | { USB_DEVICE(FTDI_VID, FTDI_XF_547_PID) }, | 173 | { USB_DEVICE(FTDI_VID, FTDI_XF_547_PID) }, |
174 | { USB_DEVICE(FTDI_VID, FTDI_XF_633_PID) }, | 174 | { USB_DEVICE(FTDI_VID, FTDI_XF_633_PID) }, |
175 | { USB_DEVICE(FTDI_VID, FTDI_XF_631_PID) }, | 175 | { USB_DEVICE(FTDI_VID, FTDI_XF_631_PID) }, |
176 | { USB_DEVICE(FTDI_VID, FTDI_XF_635_PID) }, | 176 | { USB_DEVICE(FTDI_VID, FTDI_XF_635_PID) }, |
177 | { USB_DEVICE(FTDI_VID, FTDI_XF_640_PID) }, | 177 | { USB_DEVICE(FTDI_VID, FTDI_XF_640_PID) }, |
178 | { USB_DEVICE(FTDI_VID, FTDI_XF_642_PID) }, | 178 | { USB_DEVICE(FTDI_VID, FTDI_XF_642_PID) }, |
179 | { USB_DEVICE(FTDI_VID, FTDI_DSS20_PID) }, | 179 | { USB_DEVICE(FTDI_VID, FTDI_DSS20_PID) }, |
180 | { USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) }, | 180 | { USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) }, |
181 | { USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) }, | 181 | { USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) }, |
182 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_0_PID) }, | 182 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_0_PID) }, |
183 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_1_PID) }, | 183 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_1_PID) }, |
184 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_2_PID) }, | 184 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_2_PID) }, |
185 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_3_PID) }, | 185 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_3_PID) }, |
186 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) }, | 186 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) }, |
187 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) }, | 187 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) }, |
188 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) }, | 188 | { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) }, |
189 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) }, | 189 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) }, |
190 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) }, | 190 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) }, |
191 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) }, | 191 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) }, |
192 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0103_PID) }, | 192 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0103_PID) }, |
193 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0104_PID) }, | 193 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0104_PID) }, |
194 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0105_PID) }, | 194 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0105_PID) }, |
195 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0106_PID) }, | 195 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0106_PID) }, |
196 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0107_PID) }, | 196 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0107_PID) }, |
197 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0108_PID) }, | 197 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0108_PID) }, |
198 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0109_PID) }, | 198 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0109_PID) }, |
199 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010A_PID) }, | 199 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010A_PID) }, |
200 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010B_PID) }, | 200 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010B_PID) }, |
201 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010C_PID) }, | 201 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010C_PID) }, |
202 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010D_PID) }, | 202 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010D_PID) }, |
203 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010E_PID) }, | 203 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010E_PID) }, |
204 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010F_PID) }, | 204 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010F_PID) }, |
205 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0110_PID) }, | 205 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0110_PID) }, |
206 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0111_PID) }, | 206 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0111_PID) }, |
207 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0112_PID) }, | 207 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0112_PID) }, |
208 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0113_PID) }, | 208 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0113_PID) }, |
209 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0114_PID) }, | 209 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0114_PID) }, |
210 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0115_PID) }, | 210 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0115_PID) }, |
211 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0116_PID) }, | 211 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0116_PID) }, |
212 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0117_PID) }, | 212 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0117_PID) }, |
213 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0118_PID) }, | 213 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0118_PID) }, |
214 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0119_PID) }, | 214 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0119_PID) }, |
215 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011A_PID) }, | 215 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011A_PID) }, |
216 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011B_PID) }, | 216 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011B_PID) }, |
217 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011C_PID) }, | 217 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011C_PID) }, |
218 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011D_PID) }, | 218 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011D_PID) }, |
219 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011E_PID) }, | 219 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011E_PID) }, |
220 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011F_PID) }, | 220 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011F_PID) }, |
221 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0120_PID) }, | 221 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0120_PID) }, |
222 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0121_PID) }, | 222 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0121_PID) }, |
223 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0122_PID) }, | 223 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0122_PID) }, |
224 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0123_PID) }, | 224 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0123_PID) }, |
225 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0124_PID) }, | 225 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0124_PID) }, |
226 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0125_PID) }, | 226 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0125_PID) }, |
227 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0126_PID) }, | 227 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0126_PID) }, |
228 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0127_PID), | 228 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0127_PID), |
229 | .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, | 229 | .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, |
230 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0128_PID) }, | 230 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0128_PID) }, |
231 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0129_PID) }, | 231 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0129_PID) }, |
232 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012A_PID) }, | 232 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012A_PID) }, |
233 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012B_PID) }, | 233 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012B_PID) }, |
234 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012C_PID), | 234 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012C_PID), |
235 | .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, | 235 | .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, |
236 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012D_PID) }, | 236 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012D_PID) }, |
237 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012E_PID) }, | 237 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012E_PID) }, |
238 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012F_PID) }, | 238 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012F_PID) }, |
239 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0130_PID) }, | 239 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0130_PID) }, |
240 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0131_PID) }, | 240 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0131_PID) }, |
241 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0132_PID) }, | 241 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0132_PID) }, |
242 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0133_PID) }, | 242 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0133_PID) }, |
243 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0134_PID) }, | 243 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0134_PID) }, |
244 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0135_PID) }, | 244 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0135_PID) }, |
245 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0136_PID) }, | 245 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0136_PID) }, |
246 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0137_PID) }, | 246 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0137_PID) }, |
247 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0138_PID) }, | 247 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0138_PID) }, |
248 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0139_PID) }, | 248 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0139_PID) }, |
249 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013A_PID) }, | 249 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013A_PID) }, |
250 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013B_PID) }, | 250 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013B_PID) }, |
251 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013C_PID) }, | 251 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013C_PID) }, |
252 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013D_PID) }, | 252 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013D_PID) }, |
253 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013E_PID) }, | 253 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013E_PID) }, |
254 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013F_PID) }, | 254 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013F_PID) }, |
255 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0140_PID) }, | 255 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0140_PID) }, |
256 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0141_PID) }, | 256 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0141_PID) }, |
257 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0142_PID) }, | 257 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0142_PID) }, |
258 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0143_PID) }, | 258 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0143_PID) }, |
259 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0144_PID) }, | 259 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0144_PID) }, |
260 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0145_PID) }, | 260 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0145_PID) }, |
261 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0146_PID) }, | 261 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0146_PID) }, |
262 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0147_PID) }, | 262 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0147_PID) }, |
263 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0148_PID) }, | 263 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0148_PID) }, |
264 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0149_PID) }, | 264 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0149_PID) }, |
265 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014A_PID) }, | 265 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014A_PID) }, |
266 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014B_PID) }, | 266 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014B_PID) }, |
267 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014C_PID) }, | 267 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014C_PID) }, |
268 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014D_PID) }, | 268 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014D_PID) }, |
269 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014E_PID) }, | 269 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014E_PID) }, |
270 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014F_PID) }, | 270 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014F_PID) }, |
271 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0150_PID) }, | 271 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0150_PID) }, |
272 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0151_PID) }, | 272 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0151_PID) }, |
273 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0152_PID) }, | 273 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0152_PID) }, |
274 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0153_PID), | 274 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0153_PID), |
275 | .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, | 275 | .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, |
276 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0154_PID), | 276 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0154_PID), |
277 | .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, | 277 | .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, |
278 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0155_PID), | 278 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0155_PID), |
279 | .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, | 279 | .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, |
280 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0156_PID), | 280 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0156_PID), |
281 | .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, | 281 | .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, |
282 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0157_PID), | 282 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0157_PID), |
283 | .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, | 283 | .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, |
284 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0158_PID), | 284 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0158_PID), |
285 | .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, | 285 | .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk }, |
286 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0159_PID) }, | 286 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0159_PID) }, |
287 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015A_PID) }, | 287 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015A_PID) }, |
288 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015B_PID) }, | 288 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015B_PID) }, |
289 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015C_PID) }, | 289 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015C_PID) }, |
290 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015D_PID) }, | 290 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015D_PID) }, |
291 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015E_PID) }, | 291 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015E_PID) }, |
292 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015F_PID) }, | 292 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015F_PID) }, |
293 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0160_PID) }, | 293 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0160_PID) }, |
294 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0161_PID) }, | 294 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0161_PID) }, |
295 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0162_PID) }, | 295 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0162_PID) }, |
296 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0163_PID) }, | 296 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0163_PID) }, |
297 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0164_PID) }, | 297 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0164_PID) }, |
298 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0165_PID) }, | 298 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0165_PID) }, |
299 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0166_PID) }, | 299 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0166_PID) }, |
300 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0167_PID) }, | 300 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0167_PID) }, |
301 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0168_PID) }, | 301 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0168_PID) }, |
302 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0169_PID) }, | 302 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0169_PID) }, |
303 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016A_PID) }, | 303 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016A_PID) }, |
304 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016B_PID) }, | 304 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016B_PID) }, |
305 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016C_PID) }, | 305 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016C_PID) }, |
306 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016D_PID) }, | 306 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016D_PID) }, |
307 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016E_PID) }, | 307 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016E_PID) }, |
308 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016F_PID) }, | 308 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016F_PID) }, |
309 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0170_PID) }, | 309 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0170_PID) }, |
310 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0171_PID) }, | 310 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0171_PID) }, |
311 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0172_PID) }, | 311 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0172_PID) }, |
312 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0173_PID) }, | 312 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0173_PID) }, |
313 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0174_PID) }, | 313 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0174_PID) }, |
314 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0175_PID) }, | 314 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0175_PID) }, |
315 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0176_PID) }, | 315 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0176_PID) }, |
316 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0177_PID) }, | 316 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0177_PID) }, |
317 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0178_PID) }, | 317 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0178_PID) }, |
318 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0179_PID) }, | 318 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0179_PID) }, |
319 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017A_PID) }, | 319 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017A_PID) }, |
320 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017B_PID) }, | 320 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017B_PID) }, |
321 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017C_PID) }, | 321 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017C_PID) }, |
322 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017D_PID) }, | 322 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017D_PID) }, |
323 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017E_PID) }, | 323 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017E_PID) }, |
324 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017F_PID) }, | 324 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017F_PID) }, |
325 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0180_PID) }, | 325 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0180_PID) }, |
326 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0181_PID) }, | 326 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0181_PID) }, |
327 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0182_PID) }, | 327 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0182_PID) }, |
328 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0183_PID) }, | 328 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0183_PID) }, |
329 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0184_PID) }, | 329 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0184_PID) }, |
330 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0185_PID) }, | 330 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0185_PID) }, |
331 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0186_PID) }, | 331 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0186_PID) }, |
332 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0187_PID) }, | 332 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0187_PID) }, |
333 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0188_PID) }, | 333 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0188_PID) }, |
334 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0189_PID) }, | 334 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0189_PID) }, |
335 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018A_PID) }, | 335 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018A_PID) }, |
336 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018B_PID) }, | 336 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018B_PID) }, |
337 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018C_PID) }, | 337 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018C_PID) }, |
338 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018D_PID) }, | 338 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018D_PID) }, |
339 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018E_PID) }, | 339 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018E_PID) }, |
340 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018F_PID) }, | 340 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018F_PID) }, |
341 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0190_PID) }, | 341 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0190_PID) }, |
342 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0191_PID) }, | 342 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0191_PID) }, |
343 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0192_PID) }, | 343 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0192_PID) }, |
344 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0193_PID) }, | 344 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0193_PID) }, |
345 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0194_PID) }, | 345 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0194_PID) }, |
346 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0195_PID) }, | 346 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0195_PID) }, |
347 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0196_PID) }, | 347 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0196_PID) }, |
348 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0197_PID) }, | 348 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0197_PID) }, |
349 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0198_PID) }, | 349 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0198_PID) }, |
350 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0199_PID) }, | 350 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0199_PID) }, |
351 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019A_PID) }, | 351 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019A_PID) }, |
352 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019B_PID) }, | 352 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019B_PID) }, |
353 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019C_PID) }, | 353 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019C_PID) }, |
354 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019D_PID) }, | 354 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019D_PID) }, |
355 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019E_PID) }, | 355 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019E_PID) }, |
356 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019F_PID) }, | 356 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019F_PID) }, |
357 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A0_PID) }, | 357 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A0_PID) }, |
358 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A1_PID) }, | 358 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A1_PID) }, |
359 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A2_PID) }, | 359 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A2_PID) }, |
360 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A3_PID) }, | 360 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A3_PID) }, |
361 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A4_PID) }, | 361 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A4_PID) }, |
362 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A5_PID) }, | 362 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A5_PID) }, |
363 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A6_PID) }, | 363 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A6_PID) }, |
364 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A7_PID) }, | 364 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A7_PID) }, |
365 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A8_PID) }, | 365 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A8_PID) }, |
366 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A9_PID) }, | 366 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A9_PID) }, |
367 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AA_PID) }, | 367 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AA_PID) }, |
368 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AB_PID) }, | 368 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AB_PID) }, |
369 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AC_PID) }, | 369 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AC_PID) }, |
370 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AD_PID) }, | 370 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AD_PID) }, |
371 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AE_PID) }, | 371 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AE_PID) }, |
372 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AF_PID) }, | 372 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AF_PID) }, |
373 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B0_PID) }, | 373 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B0_PID) }, |
374 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B1_PID) }, | 374 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B1_PID) }, |
375 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B2_PID) }, | 375 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B2_PID) }, |
376 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B3_PID) }, | 376 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B3_PID) }, |
377 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B4_PID) }, | 377 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B4_PID) }, |
378 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B5_PID) }, | 378 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B5_PID) }, |
379 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B6_PID) }, | 379 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B6_PID) }, |
380 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B7_PID) }, | 380 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B7_PID) }, |
381 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B8_PID) }, | 381 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B8_PID) }, |
382 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B9_PID) }, | 382 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B9_PID) }, |
383 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BA_PID) }, | 383 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BA_PID) }, |
384 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BB_PID) }, | 384 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BB_PID) }, |
385 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BC_PID) }, | 385 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BC_PID) }, |
386 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BD_PID) }, | 386 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BD_PID) }, |
387 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BE_PID) }, | 387 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BE_PID) }, |
388 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BF_PID) }, | 388 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BF_PID) }, |
389 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C0_PID) }, | 389 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C0_PID) }, |
390 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C1_PID) }, | 390 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C1_PID) }, |
391 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C2_PID) }, | 391 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C2_PID) }, |
392 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C3_PID) }, | 392 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C3_PID) }, |
393 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C4_PID) }, | 393 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C4_PID) }, |
394 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C5_PID) }, | 394 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C5_PID) }, |
395 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C6_PID) }, | 395 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C6_PID) }, |
396 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C7_PID) }, | 396 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C7_PID) }, |
397 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C8_PID) }, | 397 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C8_PID) }, |
398 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C9_PID) }, | 398 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C9_PID) }, |
399 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CA_PID) }, | 399 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CA_PID) }, |
400 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CB_PID) }, | 400 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CB_PID) }, |
401 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CC_PID) }, | 401 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CC_PID) }, |
402 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CD_PID) }, | 402 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CD_PID) }, |
403 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CE_PID) }, | 403 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CE_PID) }, |
404 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CF_PID) }, | 404 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CF_PID) }, |
405 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D0_PID) }, | 405 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D0_PID) }, |
406 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D1_PID) }, | 406 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D1_PID) }, |
407 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D2_PID) }, | 407 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D2_PID) }, |
408 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D3_PID) }, | 408 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D3_PID) }, |
409 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D4_PID) }, | 409 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D4_PID) }, |
410 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D5_PID) }, | 410 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D5_PID) }, |
411 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D6_PID) }, | 411 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D6_PID) }, |
412 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D7_PID) }, | 412 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D7_PID) }, |
413 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D8_PID) }, | 413 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D8_PID) }, |
414 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D9_PID) }, | 414 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D9_PID) }, |
415 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DA_PID) }, | 415 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DA_PID) }, |
416 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DB_PID) }, | 416 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DB_PID) }, |
417 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DC_PID) }, | 417 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DC_PID) }, |
418 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DD_PID) }, | 418 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DD_PID) }, |
419 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DE_PID) }, | 419 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DE_PID) }, |
420 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DF_PID) }, | 420 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DF_PID) }, |
421 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E0_PID) }, | 421 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E0_PID) }, |
422 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E1_PID) }, | 422 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E1_PID) }, |
423 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E2_PID) }, | 423 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E2_PID) }, |
424 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E3_PID) }, | 424 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E3_PID) }, |
425 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E4_PID) }, | 425 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E4_PID) }, |
426 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E5_PID) }, | 426 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E5_PID) }, |
427 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E6_PID) }, | 427 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E6_PID) }, |
428 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E7_PID) }, | 428 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E7_PID) }, |
429 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E8_PID) }, | 429 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E8_PID) }, |
430 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E9_PID) }, | 430 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E9_PID) }, |
431 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EA_PID) }, | 431 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EA_PID) }, |
432 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EB_PID) }, | 432 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EB_PID) }, |
433 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EC_PID) }, | 433 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EC_PID) }, |
434 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01ED_PID) }, | 434 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01ED_PID) }, |
435 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EE_PID) }, | 435 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EE_PID) }, |
436 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EF_PID) }, | 436 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EF_PID) }, |
437 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F0_PID) }, | 437 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F0_PID) }, |
438 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F1_PID) }, | 438 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F1_PID) }, |
439 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F2_PID) }, | 439 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F2_PID) }, |
440 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F3_PID) }, | 440 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F3_PID) }, |
441 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F4_PID) }, | 441 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F4_PID) }, |
442 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F5_PID) }, | 442 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F5_PID) }, |
443 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F6_PID) }, | 443 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F6_PID) }, |
444 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F7_PID) }, | 444 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F7_PID) }, |
445 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F8_PID) }, | 445 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F8_PID) }, |
446 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F9_PID) }, | 446 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F9_PID) }, |
447 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FA_PID) }, | 447 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FA_PID) }, |
448 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FB_PID) }, | 448 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FB_PID) }, |
449 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FC_PID) }, | 449 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FC_PID) }, |
450 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FD_PID) }, | 450 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FD_PID) }, |
451 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FE_PID) }, | 451 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FE_PID) }, |
452 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FF_PID) }, | 452 | { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FF_PID) }, |
453 | { USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) }, | 453 | { USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) }, |
454 | { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) }, | 454 | { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) }, |
455 | { USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) }, | 455 | { USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) }, |
456 | { USB_DEVICE(FTDI_VID, FTDI_USBX_707_PID) }, | 456 | { USB_DEVICE(FTDI_VID, FTDI_USBX_707_PID) }, |
457 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) }, | 457 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) }, |
458 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) }, | 458 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) }, |
459 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) }, | 459 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) }, |
460 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2104_PID) }, | 460 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2104_PID) }, |
461 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2106_PID) }, | 461 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2106_PID) }, |
462 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_1_PID) }, | 462 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_1_PID) }, |
463 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_2_PID) }, | 463 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_2_PID) }, |
464 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_1_PID) }, | 464 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_1_PID) }, |
465 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_2_PID) }, | 465 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_2_PID) }, |
466 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_1_PID) }, | 466 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_1_PID) }, |
467 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_2_PID) }, | 467 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_2_PID) }, |
468 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_1_PID) }, | 468 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_1_PID) }, |
469 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_2_PID) }, | 469 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_2_PID) }, |
470 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_3_PID) }, | 470 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_3_PID) }, |
471 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_4_PID) }, | 471 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_4_PID) }, |
472 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_1_PID) }, | 472 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_1_PID) }, |
473 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_2_PID) }, | 473 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_2_PID) }, |
474 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_3_PID) }, | 474 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_3_PID) }, |
475 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_4_PID) }, | 475 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_4_PID) }, |
476 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_1_PID) }, | 476 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_1_PID) }, |
477 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_2_PID) }, | 477 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_2_PID) }, |
478 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_3_PID) }, | 478 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_3_PID) }, |
479 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_4_PID) }, | 479 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_4_PID) }, |
480 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_1_PID) }, | 480 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_1_PID) }, |
481 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_2_PID) }, | 481 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_2_PID) }, |
482 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_3_PID) }, | 482 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_3_PID) }, |
483 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_4_PID) }, | 483 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_4_PID) }, |
484 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_5_PID) }, | 484 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_5_PID) }, |
485 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_6_PID) }, | 485 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_6_PID) }, |
486 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_7_PID) }, | 486 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_7_PID) }, |
487 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_8_PID) }, | 487 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_8_PID) }, |
488 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_1_PID) }, | 488 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_1_PID) }, |
489 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_2_PID) }, | 489 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_2_PID) }, |
490 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_3_PID) }, | 490 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_3_PID) }, |
491 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_4_PID) }, | 491 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_4_PID) }, |
492 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_5_PID) }, | 492 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_5_PID) }, |
493 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_6_PID) }, | 493 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_6_PID) }, |
494 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_7_PID) }, | 494 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_7_PID) }, |
495 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_8_PID) }, | 495 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_8_PID) }, |
496 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_1_PID) }, | 496 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_1_PID) }, |
497 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_2_PID) }, | 497 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_2_PID) }, |
498 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_3_PID) }, | 498 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_3_PID) }, |
499 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_4_PID) }, | 499 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_4_PID) }, |
500 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_5_PID) }, | 500 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_5_PID) }, |
501 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) }, | 501 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) }, |
502 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) }, | 502 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) }, |
503 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) }, | 503 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) }, |
504 | { USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) }, | 504 | { USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) }, |
505 | { USB_DEVICE(OCT_VID, OCT_US101_PID) }, | 505 | { USB_DEVICE(OCT_VID, OCT_US101_PID) }, |
506 | { USB_DEVICE(FTDI_VID, FTDI_HE_TIRA1_PID), | 506 | { USB_DEVICE(FTDI_VID, FTDI_HE_TIRA1_PID), |
507 | .driver_info = (kernel_ulong_t)&ftdi_HE_TIRA1_quirk }, | 507 | .driver_info = (kernel_ulong_t)&ftdi_HE_TIRA1_quirk }, |
508 | { USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID), | 508 | { USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID), |
509 | .driver_info = (kernel_ulong_t)&ftdi_USB_UIRT_quirk }, | 509 | .driver_info = (kernel_ulong_t)&ftdi_USB_UIRT_quirk }, |
510 | { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_1) }, | 510 | { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_1) }, |
511 | { USB_DEVICE(FTDI_VID, PROTEGO_R2X0) }, | 511 | { USB_DEVICE(FTDI_VID, PROTEGO_R2X0) }, |
512 | { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_3) }, | 512 | { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_3) }, |
513 | { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_4) }, | 513 | { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_4) }, |
514 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E808_PID) }, | 514 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E808_PID) }, |
515 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E809_PID) }, | 515 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E809_PID) }, |
516 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80A_PID) }, | 516 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80A_PID) }, |
517 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80B_PID) }, | 517 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80B_PID) }, |
518 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80C_PID) }, | 518 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80C_PID) }, |
519 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80D_PID) }, | 519 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80D_PID) }, |
520 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80E_PID) }, | 520 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80E_PID) }, |
521 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80F_PID) }, | 521 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80F_PID) }, |
522 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E888_PID) }, | 522 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E888_PID) }, |
523 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E889_PID) }, | 523 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E889_PID) }, |
524 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88A_PID) }, | 524 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88A_PID) }, |
525 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88B_PID) }, | 525 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88B_PID) }, |
526 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88C_PID) }, | 526 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88C_PID) }, |
527 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88D_PID) }, | 527 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88D_PID) }, |
528 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88E_PID) }, | 528 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88E_PID) }, |
529 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88F_PID) }, | 529 | { USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88F_PID) }, |
530 | { USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) }, | 530 | { USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) }, |
531 | { USB_DEVICE(FTDI_VID, FTDI_ELV_UM100_PID) }, | 531 | { USB_DEVICE(FTDI_VID, FTDI_ELV_UM100_PID) }, |
532 | { USB_DEVICE(FTDI_VID, FTDI_ELV_UR100_PID) }, | 532 | { USB_DEVICE(FTDI_VID, FTDI_ELV_UR100_PID) }, |
533 | { USB_DEVICE(FTDI_VID, FTDI_ELV_ALC8500_PID) }, | 533 | { USB_DEVICE(FTDI_VID, FTDI_ELV_ALC8500_PID) }, |
534 | { USB_DEVICE(FTDI_VID, FTDI_PYRAMID_PID) }, | 534 | { USB_DEVICE(FTDI_VID, FTDI_PYRAMID_PID) }, |
535 | { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) }, | 535 | { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) }, |
536 | { USB_DEVICE(FTDI_VID, FTDI_IBS_US485_PID) }, | 536 | { USB_DEVICE(FTDI_VID, FTDI_IBS_US485_PID) }, |
537 | { USB_DEVICE(FTDI_VID, FTDI_IBS_PICPRO_PID) }, | 537 | { USB_DEVICE(FTDI_VID, FTDI_IBS_PICPRO_PID) }, |
538 | { USB_DEVICE(FTDI_VID, FTDI_IBS_PCMCIA_PID) }, | 538 | { USB_DEVICE(FTDI_VID, FTDI_IBS_PCMCIA_PID) }, |
539 | { USB_DEVICE(FTDI_VID, FTDI_IBS_PK1_PID) }, | 539 | { USB_DEVICE(FTDI_VID, FTDI_IBS_PK1_PID) }, |
540 | { USB_DEVICE(FTDI_VID, FTDI_IBS_RS232MON_PID) }, | 540 | { USB_DEVICE(FTDI_VID, FTDI_IBS_RS232MON_PID) }, |
541 | { USB_DEVICE(FTDI_VID, FTDI_IBS_APP70_PID) }, | 541 | { USB_DEVICE(FTDI_VID, FTDI_IBS_APP70_PID) }, |
542 | { USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) }, | 542 | { USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) }, |
543 | { USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) }, | 543 | { USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) }, |
544 | /* | 544 | /* |
545 | * Due to many user requests for multiple ELV devices we enable | 545 | * Due to many user requests for multiple ELV devices we enable |
546 | * them by default. | 546 | * them by default. |
547 | */ | 547 | */ |
548 | { USB_DEVICE(FTDI_VID, FTDI_ELV_CLI7000_PID) }, | 548 | { USB_DEVICE(FTDI_VID, FTDI_ELV_CLI7000_PID) }, |
549 | { USB_DEVICE(FTDI_VID, FTDI_ELV_PPS7330_PID) }, | 549 | { USB_DEVICE(FTDI_VID, FTDI_ELV_PPS7330_PID) }, |
550 | { USB_DEVICE(FTDI_VID, FTDI_ELV_TFM100_PID) }, | 550 | { USB_DEVICE(FTDI_VID, FTDI_ELV_TFM100_PID) }, |
551 | { USB_DEVICE(FTDI_VID, FTDI_ELV_UDF77_PID) }, | 551 | { USB_DEVICE(FTDI_VID, FTDI_ELV_UDF77_PID) }, |
552 | { USB_DEVICE(FTDI_VID, FTDI_ELV_UIO88_PID) }, | 552 | { USB_DEVICE(FTDI_VID, FTDI_ELV_UIO88_PID) }, |
553 | { USB_DEVICE(FTDI_VID, FTDI_ELV_UAD8_PID) }, | 553 | { USB_DEVICE(FTDI_VID, FTDI_ELV_UAD8_PID) }, |
554 | { USB_DEVICE(FTDI_VID, FTDI_ELV_UDA7_PID) }, | 554 | { USB_DEVICE(FTDI_VID, FTDI_ELV_UDA7_PID) }, |
555 | { USB_DEVICE(FTDI_VID, FTDI_ELV_USI2_PID) }, | 555 | { USB_DEVICE(FTDI_VID, FTDI_ELV_USI2_PID) }, |
556 | { USB_DEVICE(FTDI_VID, FTDI_ELV_T1100_PID) }, | 556 | { USB_DEVICE(FTDI_VID, FTDI_ELV_T1100_PID) }, |
557 | { USB_DEVICE(FTDI_VID, FTDI_ELV_PCD200_PID) }, | 557 | { USB_DEVICE(FTDI_VID, FTDI_ELV_PCD200_PID) }, |
558 | { USB_DEVICE(FTDI_VID, FTDI_ELV_ULA200_PID) }, | 558 | { USB_DEVICE(FTDI_VID, FTDI_ELV_ULA200_PID) }, |
559 | { USB_DEVICE(FTDI_VID, FTDI_ELV_CSI8_PID) }, | 559 | { USB_DEVICE(FTDI_VID, FTDI_ELV_CSI8_PID) }, |
560 | { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1000DL_PID) }, | 560 | { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1000DL_PID) }, |
561 | { USB_DEVICE(FTDI_VID, FTDI_ELV_PCK100_PID) }, | 561 | { USB_DEVICE(FTDI_VID, FTDI_ELV_PCK100_PID) }, |
562 | { USB_DEVICE(FTDI_VID, FTDI_ELV_RFP500_PID) }, | 562 | { USB_DEVICE(FTDI_VID, FTDI_ELV_RFP500_PID) }, |
563 | { USB_DEVICE(FTDI_VID, FTDI_ELV_FS20SIG_PID) }, | 563 | { USB_DEVICE(FTDI_VID, FTDI_ELV_FS20SIG_PID) }, |
564 | { USB_DEVICE(FTDI_VID, FTDI_ELV_WS300PC_PID) }, | 564 | { USB_DEVICE(FTDI_VID, FTDI_ELV_WS300PC_PID) }, |
565 | { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1300PC_PID) }, | 565 | { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1300PC_PID) }, |
566 | { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1010PC_PID) }, | 566 | { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1010PC_PID) }, |
567 | { USB_DEVICE(FTDI_VID, FTDI_ELV_WS500_PID) }, | 567 | { USB_DEVICE(FTDI_VID, FTDI_ELV_WS500_PID) }, |
568 | { USB_DEVICE(FTDI_VID, FTDI_ELV_HS485_PID) }, | 568 | { USB_DEVICE(FTDI_VID, FTDI_ELV_HS485_PID) }, |
569 | { USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) }, | 569 | { USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) }, |
570 | { USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) }, | 570 | { USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) }, |
571 | { USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) }, | 571 | { USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) }, |
572 | { USB_DEVICE(FTDI_VID, LINX_FUTURE_1_PID) }, | 572 | { USB_DEVICE(FTDI_VID, LINX_FUTURE_1_PID) }, |
573 | { USB_DEVICE(FTDI_VID, LINX_FUTURE_2_PID) }, | 573 | { USB_DEVICE(FTDI_VID, LINX_FUTURE_2_PID) }, |
574 | { USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) }, | 574 | { USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) }, |
575 | { USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) }, | 575 | { USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) }, |
576 | { USB_DEVICE(FTDI_VID, FTDI_CCSMACHX_2_PID) }, | 576 | { USB_DEVICE(FTDI_VID, FTDI_CCSMACHX_2_PID) }, |
577 | { USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) }, | 577 | { USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) }, |
578 | { USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) }, | 578 | { USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) }, |
579 | { USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) }, | 579 | { USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) }, |
580 | { USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) }, | 580 | { USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) }, |
581 | { USB_DEVICE(FALCOM_VID, FALCOM_SAMBA_PID) }, | 581 | { USB_DEVICE(FALCOM_VID, FALCOM_SAMBA_PID) }, |
582 | { USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) }, | 582 | { USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) }, |
583 | { USB_DEVICE(FTDI_VID, FTDI_OCEANIC_PID) }, | 583 | { USB_DEVICE(FTDI_VID, FTDI_OCEANIC_PID) }, |
584 | { USB_DEVICE(TTI_VID, TTI_QL355P_PID) }, | 584 | { USB_DEVICE(TTI_VID, TTI_QL355P_PID) }, |
585 | { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) }, | 585 | { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) }, |
586 | { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, | 586 | { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, |
587 | { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, | 587 | { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, |
588 | { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) }, | 588 | { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) }, |
589 | { USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) }, | 589 | { USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) }, |
590 | { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) }, | 590 | { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) }, |
591 | { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) }, | 591 | { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) }, |
592 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_0_PID) }, | 592 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_0_PID) }, |
593 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_1_PID) }, | 593 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_1_PID) }, |
594 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_2_PID) }, | 594 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_2_PID) }, |
595 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_3_PID) }, | 595 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_3_PID) }, |
596 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_4_PID) }, | 596 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_4_PID) }, |
597 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) }, | 597 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) }, |
598 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) }, | 598 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) }, |
599 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) }, | 599 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) }, |
600 | { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) }, | 600 | { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) }, |
601 | { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) }, | 601 | { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) }, |
602 | { USB_DEVICE(FTDI_VID, FTDI_MHAM_KW_PID) }, | 602 | { USB_DEVICE(FTDI_VID, FTDI_MHAM_KW_PID) }, |
603 | { USB_DEVICE(FTDI_VID, FTDI_MHAM_YS_PID) }, | 603 | { USB_DEVICE(FTDI_VID, FTDI_MHAM_YS_PID) }, |
604 | { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y6_PID) }, | 604 | { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y6_PID) }, |
605 | { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y8_PID) }, | 605 | { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y8_PID) }, |
606 | { USB_DEVICE(FTDI_VID, FTDI_MHAM_IC_PID) }, | 606 | { USB_DEVICE(FTDI_VID, FTDI_MHAM_IC_PID) }, |
607 | { USB_DEVICE(FTDI_VID, FTDI_MHAM_DB9_PID) }, | 607 | { USB_DEVICE(FTDI_VID, FTDI_MHAM_DB9_PID) }, |
608 | { USB_DEVICE(FTDI_VID, FTDI_MHAM_RS232_PID) }, | 608 | { USB_DEVICE(FTDI_VID, FTDI_MHAM_RS232_PID) }, |
609 | { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y9_PID) }, | 609 | { USB_DEVICE(FTDI_VID, FTDI_MHAM_Y9_PID) }, |
610 | { USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_VCP_PID) }, | 610 | { USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_VCP_PID) }, |
611 | { USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_D2XX_PID) }, | 611 | { USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_D2XX_PID) }, |
612 | { USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) }, | 612 | { USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) }, |
613 | { USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) }, | 613 | { USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) }, |
614 | { USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) }, | 614 | { USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) }, |
615 | { USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) }, | 615 | { USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) }, |
616 | { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) }, | 616 | { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) }, |
617 | { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) }, | 617 | { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) }, |
618 | { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) }, | 618 | { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) }, |
619 | { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HRC_PID) }, | 619 | { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HRC_PID) }, |
620 | { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16IC_PID) }, | 620 | { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16IC_PID) }, |
621 | { USB_DEVICE(KOBIL_VID, KOBIL_CONV_B1_PID) }, | 621 | { USB_DEVICE(KOBIL_VID, KOBIL_CONV_B1_PID) }, |
622 | { USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) }, | 622 | { USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) }, |
623 | { USB_DEVICE(POSIFLEX_VID, POSIFLEX_PP7000_PID) }, | 623 | { USB_DEVICE(POSIFLEX_VID, POSIFLEX_PP7000_PID) }, |
624 | { USB_DEVICE(FTDI_VID, FTDI_TTUSB_PID) }, | 624 | { USB_DEVICE(FTDI_VID, FTDI_TTUSB_PID) }, |
625 | { USB_DEVICE(FTDI_VID, FTDI_ECLO_COM_1WIRE_PID) }, | 625 | { USB_DEVICE(FTDI_VID, FTDI_ECLO_COM_1WIRE_PID) }, |
626 | { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_777_PID) }, | 626 | { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_777_PID) }, |
627 | { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_8900F_PID) }, | 627 | { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_8900F_PID) }, |
628 | { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) }, | 628 | { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) }, |
629 | { USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) }, | 629 | { USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) }, |
630 | { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) }, | 630 | { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) }, |
631 | { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) }, | 631 | { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) }, |
632 | { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) }, | 632 | { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) }, |
633 | { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) }, | 633 | { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) }, |
634 | { USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) }, | 634 | { USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) }, |
635 | { USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) }, | 635 | { USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) }, |
636 | { USB_DEVICE(TESTO_VID, TESTO_USB_INTERFACE_PID) }, | 636 | { USB_DEVICE(TESTO_VID, TESTO_USB_INTERFACE_PID) }, |
637 | { USB_DEVICE(FTDI_VID, FTDI_GAMMA_SCOUT_PID) }, | 637 | { USB_DEVICE(FTDI_VID, FTDI_GAMMA_SCOUT_PID) }, |
638 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13M_PID) }, | 638 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13M_PID) }, |
639 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) }, | 639 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) }, |
640 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) }, | 640 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) }, |
641 | { USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) }, | 641 | { USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) }, |
642 | { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, | 642 | { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, |
643 | { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) }, | 643 | { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) }, |
644 | { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) }, | 644 | { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) }, |
645 | { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) }, | 645 | { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) }, |
646 | { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) }, | 646 | { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) }, |
647 | { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) }, | 647 | { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) }, |
648 | { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID), | 648 | { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID), |
649 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | 649 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, |
650 | { USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID), | 650 | { USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID), |
651 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | 651 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, |
652 | { USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID), | 652 | { USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID), |
653 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | 653 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, |
654 | { USB_DEVICE(FTDI_VID, LMI_LM3S_DEVEL_BOARD_PID), | 654 | { USB_DEVICE(FTDI_VID, LMI_LM3S_DEVEL_BOARD_PID), |
655 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | 655 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, |
656 | { USB_DEVICE(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID), | 656 | { USB_DEVICE(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID), |
657 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | 657 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, |
658 | { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, | 658 | { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, |
659 | { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) }, | 659 | { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) }, |
660 | { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) }, | 660 | { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) }, |
661 | { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DGQG_PID) }, | 661 | { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DGQG_PID) }, |
662 | { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) }, | 662 | { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) }, |
663 | { }, /* Optional parameter entry */ | 663 | { }, /* Optional parameter entry */ |
664 | { } /* Terminating entry */ | 664 | { } /* Terminating entry */ |
665 | }; | 665 | }; |
666 | 666 | ||
667 | MODULE_DEVICE_TABLE(usb, id_table_combined); | 667 | MODULE_DEVICE_TABLE(usb, id_table_combined); |
668 | 668 | ||
669 | static struct usb_driver ftdi_driver = { | 669 | static struct usb_driver ftdi_driver = { |
670 | .name = "ftdi_sio", | 670 | .name = "ftdi_sio", |
671 | .probe = usb_serial_probe, | 671 | .probe = usb_serial_probe, |
672 | .disconnect = usb_serial_disconnect, | 672 | .disconnect = usb_serial_disconnect, |
673 | .id_table = id_table_combined, | 673 | .id_table = id_table_combined, |
674 | .no_dynamic_id = 1, | 674 | .no_dynamic_id = 1, |
675 | }; | 675 | }; |
676 | 676 | ||
677 | static const char *ftdi_chip_name[] = { | 677 | static const char *ftdi_chip_name[] = { |
678 | [SIO] = "SIO", /* the serial part of FT8U100AX */ | 678 | [SIO] = "SIO", /* the serial part of FT8U100AX */ |
679 | [FT8U232AM] = "FT8U232AM", | 679 | [FT8U232AM] = "FT8U232AM", |
680 | [FT232BM] = "FT232BM", | 680 | [FT232BM] = "FT232BM", |
681 | [FT2232C] = "FT2232C", | 681 | [FT2232C] = "FT2232C", |
682 | [FT232RL] = "FT232RL", | 682 | [FT232RL] = "FT232RL", |
683 | }; | 683 | }; |
684 | 684 | ||
685 | 685 | ||
686 | /* Constants for read urb and write urb */ | 686 | /* Constants for read urb and write urb */ |
687 | #define BUFSZ 512 | 687 | #define BUFSZ 512 |
688 | #define PKTSZ 64 | 688 | #define PKTSZ 64 |
689 | 689 | ||
690 | /* rx_flags */ | 690 | /* rx_flags */ |
691 | #define THROTTLED 0x01 | 691 | #define THROTTLED 0x01 |
692 | #define ACTUALLY_THROTTLED 0x02 | 692 | #define ACTUALLY_THROTTLED 0x02 |
693 | 693 | ||
694 | /* Used for TIOCMIWAIT */ | 694 | /* Used for TIOCMIWAIT */ |
695 | #define FTDI_STATUS_B0_MASK (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD) | 695 | #define FTDI_STATUS_B0_MASK (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD) |
696 | #define FTDI_STATUS_B1_MASK (FTDI_RS_BI) | 696 | #define FTDI_STATUS_B1_MASK (FTDI_RS_BI) |
697 | /* End TIOCMIWAIT */ | 697 | /* End TIOCMIWAIT */ |
698 | 698 | ||
699 | #define FTDI_IMPL_ASYNC_FLAGS = (ASYNC_SPD_HI | ASYNC_SPD_VHI \ | 699 | #define FTDI_IMPL_ASYNC_FLAGS = (ASYNC_SPD_HI | ASYNC_SPD_VHI \ |
700 | | ASYNC_SPD_CUST | ASYNC_SPD_SHI | ASYNC_SPD_WARP) | 700 | | ASYNC_SPD_CUST | ASYNC_SPD_SHI | ASYNC_SPD_WARP) |
701 | 701 | ||
702 | /* function prototypes for a FTDI serial converter */ | 702 | /* function prototypes for a FTDI serial converter */ |
703 | static int ftdi_sio_probe(struct usb_serial *serial, | 703 | static int ftdi_sio_probe(struct usb_serial *serial, |
704 | const struct usb_device_id *id); | 704 | const struct usb_device_id *id); |
705 | static void ftdi_shutdown(struct usb_serial *serial); | 705 | static void ftdi_shutdown(struct usb_serial *serial); |
706 | static int ftdi_sio_port_probe(struct usb_serial_port *port); | 706 | static int ftdi_sio_port_probe(struct usb_serial_port *port); |
707 | static int ftdi_sio_port_remove(struct usb_serial_port *port); | 707 | static int ftdi_sio_port_remove(struct usb_serial_port *port); |
708 | static int ftdi_open(struct tty_struct *tty, | 708 | static int ftdi_open(struct tty_struct *tty, |
709 | struct usb_serial_port *port, struct file *filp); | 709 | struct usb_serial_port *port, struct file *filp); |
710 | static void ftdi_close(struct tty_struct *tty, | 710 | static void ftdi_close(struct tty_struct *tty, |
711 | struct usb_serial_port *port, struct file *filp); | 711 | struct usb_serial_port *port, struct file *filp); |
712 | static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, | 712 | static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, |
713 | const unsigned char *buf, int count); | 713 | const unsigned char *buf, int count); |
714 | static int ftdi_write_room(struct tty_struct *tty); | 714 | static int ftdi_write_room(struct tty_struct *tty); |
715 | static int ftdi_chars_in_buffer(struct tty_struct *tty); | 715 | static int ftdi_chars_in_buffer(struct tty_struct *tty); |
716 | static void ftdi_write_bulk_callback(struct urb *urb); | 716 | static void ftdi_write_bulk_callback(struct urb *urb); |
717 | static void ftdi_read_bulk_callback(struct urb *urb); | 717 | static void ftdi_read_bulk_callback(struct urb *urb); |
718 | static void ftdi_process_read(struct work_struct *work); | 718 | static void ftdi_process_read(struct work_struct *work); |
719 | static void ftdi_set_termios(struct tty_struct *tty, | 719 | static void ftdi_set_termios(struct tty_struct *tty, |
720 | struct usb_serial_port *port, struct ktermios *old); | 720 | struct usb_serial_port *port, struct ktermios *old); |
721 | static int ftdi_tiocmget(struct tty_struct *tty, struct file *file); | 721 | static int ftdi_tiocmget(struct tty_struct *tty, struct file *file); |
722 | static int ftdi_tiocmset(struct tty_struct *tty, struct file *file, | 722 | static int ftdi_tiocmset(struct tty_struct *tty, struct file *file, |
723 | unsigned int set, unsigned int clear); | 723 | unsigned int set, unsigned int clear); |
724 | static int ftdi_ioctl(struct tty_struct *tty, struct file *file, | 724 | static int ftdi_ioctl(struct tty_struct *tty, struct file *file, |
725 | unsigned int cmd, unsigned long arg); | 725 | unsigned int cmd, unsigned long arg); |
726 | static void ftdi_break_ctl(struct tty_struct *tty, int break_state); | 726 | static void ftdi_break_ctl(struct tty_struct *tty, int break_state); |
727 | static void ftdi_throttle(struct tty_struct *tty); | 727 | static void ftdi_throttle(struct tty_struct *tty); |
728 | static void ftdi_unthrottle(struct tty_struct *tty); | 728 | static void ftdi_unthrottle(struct tty_struct *tty); |
729 | 729 | ||
730 | static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base); | 730 | static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base); |
731 | static unsigned short int ftdi_232am_baud_to_divisor(int baud); | 731 | static unsigned short int ftdi_232am_baud_to_divisor(int baud); |
732 | static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base); | 732 | static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base); |
733 | static __u32 ftdi_232bm_baud_to_divisor(int baud); | 733 | static __u32 ftdi_232bm_baud_to_divisor(int baud); |
734 | 734 | ||
735 | static struct usb_serial_driver ftdi_sio_device = { | 735 | static struct usb_serial_driver ftdi_sio_device = { |
736 | .driver = { | 736 | .driver = { |
737 | .owner = THIS_MODULE, | 737 | .owner = THIS_MODULE, |
738 | .name = "ftdi_sio", | 738 | .name = "ftdi_sio", |
739 | }, | 739 | }, |
740 | .description = "FTDI USB Serial Device", | 740 | .description = "FTDI USB Serial Device", |
741 | .usb_driver = &ftdi_driver , | 741 | .usb_driver = &ftdi_driver , |
742 | .id_table = id_table_combined, | 742 | .id_table = id_table_combined, |
743 | .num_ports = 1, | 743 | .num_ports = 1, |
744 | .probe = ftdi_sio_probe, | 744 | .probe = ftdi_sio_probe, |
745 | .port_probe = ftdi_sio_port_probe, | 745 | .port_probe = ftdi_sio_port_probe, |
746 | .port_remove = ftdi_sio_port_remove, | 746 | .port_remove = ftdi_sio_port_remove, |
747 | .open = ftdi_open, | 747 | .open = ftdi_open, |
748 | .close = ftdi_close, | 748 | .close = ftdi_close, |
749 | .throttle = ftdi_throttle, | 749 | .throttle = ftdi_throttle, |
750 | .unthrottle = ftdi_unthrottle, | 750 | .unthrottle = ftdi_unthrottle, |
751 | .write = ftdi_write, | 751 | .write = ftdi_write, |
752 | .write_room = ftdi_write_room, | 752 | .write_room = ftdi_write_room, |
753 | .chars_in_buffer = ftdi_chars_in_buffer, | 753 | .chars_in_buffer = ftdi_chars_in_buffer, |
754 | .read_bulk_callback = ftdi_read_bulk_callback, | 754 | .read_bulk_callback = ftdi_read_bulk_callback, |
755 | .write_bulk_callback = ftdi_write_bulk_callback, | 755 | .write_bulk_callback = ftdi_write_bulk_callback, |
756 | .tiocmget = ftdi_tiocmget, | 756 | .tiocmget = ftdi_tiocmget, |
757 | .tiocmset = ftdi_tiocmset, | 757 | .tiocmset = ftdi_tiocmset, |
758 | .ioctl = ftdi_ioctl, | 758 | .ioctl = ftdi_ioctl, |
759 | .set_termios = ftdi_set_termios, | 759 | .set_termios = ftdi_set_termios, |
760 | .break_ctl = ftdi_break_ctl, | 760 | .break_ctl = ftdi_break_ctl, |
761 | .shutdown = ftdi_shutdown, | 761 | .shutdown = ftdi_shutdown, |
762 | }; | 762 | }; |
763 | 763 | ||
764 | 764 | ||
765 | #define WDR_TIMEOUT 5000 /* default urb timeout */ | 765 | #define WDR_TIMEOUT 5000 /* default urb timeout */ |
766 | #define WDR_SHORT_TIMEOUT 1000 /* shorter urb timeout */ | 766 | #define WDR_SHORT_TIMEOUT 1000 /* shorter urb timeout */ |
767 | 767 | ||
768 | /* High and low are for DTR, RTS etc etc */ | 768 | /* High and low are for DTR, RTS etc etc */ |
769 | #define HIGH 1 | 769 | #define HIGH 1 |
770 | #define LOW 0 | 770 | #define LOW 0 |
771 | 771 | ||
772 | /* number of outstanding urbs to prevent userspace DoS from happening */ | 772 | /* number of outstanding urbs to prevent userspace DoS from happening */ |
773 | #define URB_UPPER_LIMIT 42 | 773 | #define URB_UPPER_LIMIT 42 |
774 | 774 | ||
775 | /* | 775 | /* |
776 | * *************************************************************************** | 776 | * *************************************************************************** |
777 | * Utility functions | 777 | * Utility functions |
778 | * *************************************************************************** | 778 | * *************************************************************************** |
779 | */ | 779 | */ |
780 | 780 | ||
781 | static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base) | 781 | static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base) |
782 | { | 782 | { |
783 | unsigned short int divisor; | 783 | unsigned short int divisor; |
784 | /* divisor shifted 3 bits to the left */ | 784 | /* divisor shifted 3 bits to the left */ |
785 | int divisor3 = base / 2 / baud; | 785 | int divisor3 = base / 2 / baud; |
786 | if ((divisor3 & 0x7) == 7) | 786 | if ((divisor3 & 0x7) == 7) |
787 | divisor3++; /* round x.7/8 up to x+1 */ | 787 | divisor3++; /* round x.7/8 up to x+1 */ |
788 | divisor = divisor3 >> 3; | 788 | divisor = divisor3 >> 3; |
789 | divisor3 &= 0x7; | 789 | divisor3 &= 0x7; |
790 | if (divisor3 == 1) | 790 | if (divisor3 == 1) |
791 | divisor |= 0xc000; | 791 | divisor |= 0xc000; |
792 | else if (divisor3 >= 4) | 792 | else if (divisor3 >= 4) |
793 | divisor |= 0x4000; | 793 | divisor |= 0x4000; |
794 | else if (divisor3 != 0) | 794 | else if (divisor3 != 0) |
795 | divisor |= 0x8000; | 795 | divisor |= 0x8000; |
796 | else if (divisor == 1) | 796 | else if (divisor == 1) |
797 | divisor = 0; /* special case for maximum baud rate */ | 797 | divisor = 0; /* special case for maximum baud rate */ |
798 | return divisor; | 798 | return divisor; |
799 | } | 799 | } |
800 | 800 | ||
801 | static unsigned short int ftdi_232am_baud_to_divisor(int baud) | 801 | static unsigned short int ftdi_232am_baud_to_divisor(int baud) |
802 | { | 802 | { |
803 | return ftdi_232am_baud_base_to_divisor(baud, 48000000); | 803 | return ftdi_232am_baud_base_to_divisor(baud, 48000000); |
804 | } | 804 | } |
805 | 805 | ||
806 | static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base) | 806 | static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base) |
807 | { | 807 | { |
808 | static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; | 808 | static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; |
809 | __u32 divisor; | 809 | __u32 divisor; |
810 | /* divisor shifted 3 bits to the left */ | 810 | /* divisor shifted 3 bits to the left */ |
811 | int divisor3 = base / 2 / baud; | 811 | int divisor3 = base / 2 / baud; |
812 | divisor = divisor3 >> 3; | 812 | divisor = divisor3 >> 3; |
813 | divisor |= (__u32)divfrac[divisor3 & 0x7] << 14; | 813 | divisor |= (__u32)divfrac[divisor3 & 0x7] << 14; |
814 | /* Deal with special cases for highest baud rates. */ | 814 | /* Deal with special cases for highest baud rates. */ |
815 | if (divisor == 1) | 815 | if (divisor == 1) |
816 | divisor = 0; | 816 | divisor = 0; |
817 | else if (divisor == 0x4001) | 817 | else if (divisor == 0x4001) |
818 | divisor = 1; | 818 | divisor = 1; |
819 | return divisor; | 819 | return divisor; |
820 | } | 820 | } |
821 | 821 | ||
822 | static __u32 ftdi_232bm_baud_to_divisor(int baud) | 822 | static __u32 ftdi_232bm_baud_to_divisor(int baud) |
823 | { | 823 | { |
824 | return ftdi_232bm_baud_base_to_divisor(baud, 48000000); | 824 | return ftdi_232bm_baud_base_to_divisor(baud, 48000000); |
825 | } | 825 | } |
826 | 826 | ||
827 | #define set_mctrl(port, set) update_mctrl((port), (set), 0) | 827 | #define set_mctrl(port, set) update_mctrl((port), (set), 0) |
828 | #define clear_mctrl(port, clear) update_mctrl((port), 0, (clear)) | 828 | #define clear_mctrl(port, clear) update_mctrl((port), 0, (clear)) |
829 | 829 | ||
830 | static int update_mctrl(struct usb_serial_port *port, unsigned int set, | 830 | static int update_mctrl(struct usb_serial_port *port, unsigned int set, |
831 | unsigned int clear) | 831 | unsigned int clear) |
832 | { | 832 | { |
833 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 833 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
834 | char *buf; | 834 | char *buf; |
835 | unsigned urb_value; | 835 | unsigned urb_value; |
836 | int rv; | 836 | int rv; |
837 | 837 | ||
838 | if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) { | 838 | if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) { |
839 | dbg("%s - DTR|RTS not being set|cleared", __func__); | 839 | dbg("%s - DTR|RTS not being set|cleared", __func__); |
840 | return 0; /* no change */ | 840 | return 0; /* no change */ |
841 | } | 841 | } |
842 | 842 | ||
843 | buf = kmalloc(1, GFP_NOIO); | 843 | buf = kmalloc(1, GFP_NOIO); |
844 | if (!buf) | 844 | if (!buf) |
845 | return -ENOMEM; | 845 | return -ENOMEM; |
846 | 846 | ||
847 | clear &= ~set; /* 'set' takes precedence over 'clear' */ | 847 | clear &= ~set; /* 'set' takes precedence over 'clear' */ |
848 | urb_value = 0; | 848 | urb_value = 0; |
849 | if (clear & TIOCM_DTR) | 849 | if (clear & TIOCM_DTR) |
850 | urb_value |= FTDI_SIO_SET_DTR_LOW; | 850 | urb_value |= FTDI_SIO_SET_DTR_LOW; |
851 | if (clear & TIOCM_RTS) | 851 | if (clear & TIOCM_RTS) |
852 | urb_value |= FTDI_SIO_SET_RTS_LOW; | 852 | urb_value |= FTDI_SIO_SET_RTS_LOW; |
853 | if (set & TIOCM_DTR) | 853 | if (set & TIOCM_DTR) |
854 | urb_value |= FTDI_SIO_SET_DTR_HIGH; | 854 | urb_value |= FTDI_SIO_SET_DTR_HIGH; |
855 | if (set & TIOCM_RTS) | 855 | if (set & TIOCM_RTS) |
856 | urb_value |= FTDI_SIO_SET_RTS_HIGH; | 856 | urb_value |= FTDI_SIO_SET_RTS_HIGH; |
857 | rv = usb_control_msg(port->serial->dev, | 857 | rv = usb_control_msg(port->serial->dev, |
858 | usb_sndctrlpipe(port->serial->dev, 0), | 858 | usb_sndctrlpipe(port->serial->dev, 0), |
859 | FTDI_SIO_SET_MODEM_CTRL_REQUEST, | 859 | FTDI_SIO_SET_MODEM_CTRL_REQUEST, |
860 | FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, | 860 | FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, |
861 | urb_value, priv->interface, | 861 | urb_value, priv->interface, |
862 | buf, 0, WDR_TIMEOUT); | 862 | buf, 0, WDR_TIMEOUT); |
863 | 863 | ||
864 | kfree(buf); | 864 | kfree(buf); |
865 | if (rv < 0) { | 865 | if (rv < 0) { |
866 | dbg("%s Error from MODEM_CTRL urb: DTR %s, RTS %s", | 866 | dbg("%s Error from MODEM_CTRL urb: DTR %s, RTS %s", |
867 | __func__, | 867 | __func__, |
868 | (set & TIOCM_DTR) ? "HIGH" : | 868 | (set & TIOCM_DTR) ? "HIGH" : |
869 | (clear & TIOCM_DTR) ? "LOW" : "unchanged", | 869 | (clear & TIOCM_DTR) ? "LOW" : "unchanged", |
870 | (set & TIOCM_RTS) ? "HIGH" : | 870 | (set & TIOCM_RTS) ? "HIGH" : |
871 | (clear & TIOCM_RTS) ? "LOW" : "unchanged"); | 871 | (clear & TIOCM_RTS) ? "LOW" : "unchanged"); |
872 | } else { | 872 | } else { |
873 | dbg("%s - DTR %s, RTS %s", __func__, | 873 | dbg("%s - DTR %s, RTS %s", __func__, |
874 | (set & TIOCM_DTR) ? "HIGH" : | 874 | (set & TIOCM_DTR) ? "HIGH" : |
875 | (clear & TIOCM_DTR) ? "LOW" : "unchanged", | 875 | (clear & TIOCM_DTR) ? "LOW" : "unchanged", |
876 | (set & TIOCM_RTS) ? "HIGH" : | 876 | (set & TIOCM_RTS) ? "HIGH" : |
877 | (clear & TIOCM_RTS) ? "LOW" : "unchanged"); | 877 | (clear & TIOCM_RTS) ? "LOW" : "unchanged"); |
878 | /* FIXME: locking on last_dtr_rts */ | 878 | /* FIXME: locking on last_dtr_rts */ |
879 | priv->last_dtr_rts = (priv->last_dtr_rts & ~clear) | set; | 879 | priv->last_dtr_rts = (priv->last_dtr_rts & ~clear) | set; |
880 | } | 880 | } |
881 | return rv; | 881 | return rv; |
882 | } | 882 | } |
883 | 883 | ||
884 | 884 | ||
885 | static __u32 get_ftdi_divisor(struct tty_struct *tty, | 885 | static __u32 get_ftdi_divisor(struct tty_struct *tty, |
886 | struct usb_serial_port *port) | 886 | struct usb_serial_port *port) |
887 | { /* get_ftdi_divisor */ | 887 | { /* get_ftdi_divisor */ |
888 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 888 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
889 | __u32 div_value = 0; | 889 | __u32 div_value = 0; |
890 | int div_okay = 1; | 890 | int div_okay = 1; |
891 | int baud; | 891 | int baud; |
892 | 892 | ||
893 | /* | 893 | /* |
894 | * The logic involved in setting the baudrate can be cleanly split into | 894 | * The logic involved in setting the baudrate can be cleanly split into |
895 | * 3 steps. | 895 | * 3 steps. |
896 | * 1. Standard baud rates are set in tty->termios->c_cflag | 896 | * 1. Standard baud rates are set in tty->termios->c_cflag |
897 | * 2. If these are not enough, you can set any speed using alt_speed as | 897 | * 2. If these are not enough, you can set any speed using alt_speed as |
898 | * follows: | 898 | * follows: |
899 | * - set tty->termios->c_cflag speed to B38400 | 899 | * - set tty->termios->c_cflag speed to B38400 |
900 | * - set your real speed in tty->alt_speed; it gets ignored when | 900 | * - set your real speed in tty->alt_speed; it gets ignored when |
901 | * alt_speed==0, (or) | 901 | * alt_speed==0, (or) |
902 | * - call TIOCSSERIAL ioctl with (struct serial_struct) set as | 902 | * - call TIOCSSERIAL ioctl with (struct serial_struct) set as |
903 | * follows: | 903 | * follows: |
904 | * flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP], | 904 | * flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP], |
905 | * this just sets alt_speed to (HI: 57600, VHI: 115200, | 905 | * this just sets alt_speed to (HI: 57600, VHI: 115200, |
906 | * SHI: 230400, WARP: 460800) | 906 | * SHI: 230400, WARP: 460800) |
907 | * ** Steps 1, 2 are done courtesy of tty_get_baud_rate | 907 | * ** Steps 1, 2 are done courtesy of tty_get_baud_rate |
908 | * 3. You can also set baud rate by setting custom divisor as follows | 908 | * 3. You can also set baud rate by setting custom divisor as follows |
909 | * - set tty->termios->c_cflag speed to B38400 | 909 | * - set tty->termios->c_cflag speed to B38400 |
910 | * - call TIOCSSERIAL ioctl with (struct serial_struct) set as | 910 | * - call TIOCSSERIAL ioctl with (struct serial_struct) set as |
911 | * follows: | 911 | * follows: |
912 | * o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST | 912 | * o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST |
913 | * o custom_divisor set to baud_base / your_new_baudrate | 913 | * o custom_divisor set to baud_base / your_new_baudrate |
914 | * ** Step 3 is done courtesy of code borrowed from serial.c | 914 | * ** Step 3 is done courtesy of code borrowed from serial.c |
915 | * I should really spend some time and separate + move this common | 915 | * I should really spend some time and separate + move this common |
916 | * code to serial.c, it is replicated in nearly every serial driver | 916 | * code to serial.c, it is replicated in nearly every serial driver |
917 | * you see. | 917 | * you see. |
918 | */ | 918 | */ |
919 | 919 | ||
920 | /* 1. Get the baud rate from the tty settings, this observes | 920 | /* 1. Get the baud rate from the tty settings, this observes |
921 | alt_speed hack */ | 921 | alt_speed hack */ |
922 | 922 | ||
923 | baud = tty_get_baud_rate(tty); | 923 | baud = tty_get_baud_rate(tty); |
924 | dbg("%s - tty_get_baud_rate reports speed %d", __func__, baud); | 924 | dbg("%s - tty_get_baud_rate reports speed %d", __func__, baud); |
925 | 925 | ||
926 | /* 2. Observe async-compatible custom_divisor hack, update baudrate | 926 | /* 2. Observe async-compatible custom_divisor hack, update baudrate |
927 | if needed */ | 927 | if needed */ |
928 | 928 | ||
929 | if (baud == 38400 && | 929 | if (baud == 38400 && |
930 | ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && | 930 | ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && |
931 | (priv->custom_divisor)) { | 931 | (priv->custom_divisor)) { |
932 | baud = priv->baud_base / priv->custom_divisor; | 932 | baud = priv->baud_base / priv->custom_divisor; |
933 | dbg("%s - custom divisor %d sets baud rate to %d", | 933 | dbg("%s - custom divisor %d sets baud rate to %d", |
934 | __func__, priv->custom_divisor, baud); | 934 | __func__, priv->custom_divisor, baud); |
935 | } | 935 | } |
936 | 936 | ||
937 | /* 3. Convert baudrate to device-specific divisor */ | 937 | /* 3. Convert baudrate to device-specific divisor */ |
938 | 938 | ||
939 | if (!baud) | 939 | if (!baud) |
940 | baud = 9600; | 940 | baud = 9600; |
941 | switch (priv->chip_type) { | 941 | switch (priv->chip_type) { |
942 | case SIO: /* SIO chip */ | 942 | case SIO: /* SIO chip */ |
943 | switch (baud) { | 943 | switch (baud) { |
944 | case 300: div_value = ftdi_sio_b300; break; | 944 | case 300: div_value = ftdi_sio_b300; break; |
945 | case 600: div_value = ftdi_sio_b600; break; | 945 | case 600: div_value = ftdi_sio_b600; break; |
946 | case 1200: div_value = ftdi_sio_b1200; break; | 946 | case 1200: div_value = ftdi_sio_b1200; break; |
947 | case 2400: div_value = ftdi_sio_b2400; break; | 947 | case 2400: div_value = ftdi_sio_b2400; break; |
948 | case 4800: div_value = ftdi_sio_b4800; break; | 948 | case 4800: div_value = ftdi_sio_b4800; break; |
949 | case 9600: div_value = ftdi_sio_b9600; break; | 949 | case 9600: div_value = ftdi_sio_b9600; break; |
950 | case 19200: div_value = ftdi_sio_b19200; break; | 950 | case 19200: div_value = ftdi_sio_b19200; break; |
951 | case 38400: div_value = ftdi_sio_b38400; break; | 951 | case 38400: div_value = ftdi_sio_b38400; break; |
952 | case 57600: div_value = ftdi_sio_b57600; break; | 952 | case 57600: div_value = ftdi_sio_b57600; break; |
953 | case 115200: div_value = ftdi_sio_b115200; break; | 953 | case 115200: div_value = ftdi_sio_b115200; break; |
954 | } /* baud */ | 954 | } /* baud */ |
955 | if (div_value == 0) { | 955 | if (div_value == 0) { |
956 | dbg("%s - Baudrate (%d) requested is not supported", | 956 | dbg("%s - Baudrate (%d) requested is not supported", |
957 | __func__, baud); | 957 | __func__, baud); |
958 | div_value = ftdi_sio_b9600; | 958 | div_value = ftdi_sio_b9600; |
959 | baud = 9600; | 959 | baud = 9600; |
960 | div_okay = 0; | 960 | div_okay = 0; |
961 | } | 961 | } |
962 | break; | 962 | break; |
963 | case FT8U232AM: /* 8U232AM chip */ | 963 | case FT8U232AM: /* 8U232AM chip */ |
964 | if (baud <= 3000000) { | 964 | if (baud <= 3000000) { |
965 | div_value = ftdi_232am_baud_to_divisor(baud); | 965 | div_value = ftdi_232am_baud_to_divisor(baud); |
966 | } else { | 966 | } else { |
967 | dbg("%s - Baud rate too high!", __func__); | 967 | dbg("%s - Baud rate too high!", __func__); |
968 | baud = 9600; | 968 | baud = 9600; |
969 | div_value = ftdi_232am_baud_to_divisor(9600); | 969 | div_value = ftdi_232am_baud_to_divisor(9600); |
970 | div_okay = 0; | 970 | div_okay = 0; |
971 | } | 971 | } |
972 | break; | 972 | break; |
973 | case FT232BM: /* FT232BM chip */ | 973 | case FT232BM: /* FT232BM chip */ |
974 | case FT2232C: /* FT2232C chip */ | 974 | case FT2232C: /* FT2232C chip */ |
975 | case FT232RL: | 975 | case FT232RL: |
976 | if (baud <= 3000000) { | 976 | if (baud <= 3000000) { |
977 | div_value = ftdi_232bm_baud_to_divisor(baud); | 977 | div_value = ftdi_232bm_baud_to_divisor(baud); |
978 | } else { | 978 | } else { |
979 | dbg("%s - Baud rate too high!", __func__); | 979 | dbg("%s - Baud rate too high!", __func__); |
980 | div_value = ftdi_232bm_baud_to_divisor(9600); | 980 | div_value = ftdi_232bm_baud_to_divisor(9600); |
981 | div_okay = 0; | 981 | div_okay = 0; |
982 | baud = 9600; | 982 | baud = 9600; |
983 | } | 983 | } |
984 | break; | 984 | break; |
985 | } /* priv->chip_type */ | 985 | } /* priv->chip_type */ |
986 | 986 | ||
987 | if (div_okay) { | 987 | if (div_okay) { |
988 | dbg("%s - Baud rate set to %d (divisor 0x%lX) on chip %s", | 988 | dbg("%s - Baud rate set to %d (divisor 0x%lX) on chip %s", |
989 | __func__, baud, (unsigned long)div_value, | 989 | __func__, baud, (unsigned long)div_value, |
990 | ftdi_chip_name[priv->chip_type]); | 990 | ftdi_chip_name[priv->chip_type]); |
991 | } | 991 | } |
992 | 992 | ||
993 | tty_encode_baud_rate(tty, baud, baud); | 993 | tty_encode_baud_rate(tty, baud, baud); |
994 | return div_value; | 994 | return div_value; |
995 | } | 995 | } |
996 | 996 | ||
997 | static int change_speed(struct tty_struct *tty, struct usb_serial_port *port) | 997 | static int change_speed(struct tty_struct *tty, struct usb_serial_port *port) |
998 | { | 998 | { |
999 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 999 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1000 | char *buf; | 1000 | char *buf; |
1001 | __u16 urb_value; | 1001 | __u16 urb_value; |
1002 | __u16 urb_index; | 1002 | __u16 urb_index; |
1003 | __u32 urb_index_value; | 1003 | __u32 urb_index_value; |
1004 | int rv; | 1004 | int rv; |
1005 | 1005 | ||
1006 | buf = kmalloc(1, GFP_NOIO); | 1006 | buf = kmalloc(1, GFP_NOIO); |
1007 | if (!buf) | 1007 | if (!buf) |
1008 | return -ENOMEM; | 1008 | return -ENOMEM; |
1009 | 1009 | ||
1010 | urb_index_value = get_ftdi_divisor(tty, port); | 1010 | urb_index_value = get_ftdi_divisor(tty, port); |
1011 | urb_value = (__u16)urb_index_value; | 1011 | urb_value = (__u16)urb_index_value; |
1012 | urb_index = (__u16)(urb_index_value >> 16); | 1012 | urb_index = (__u16)(urb_index_value >> 16); |
1013 | if (priv->interface) { /* FT2232C */ | 1013 | if (priv->interface) { /* FT2232C */ |
1014 | urb_index = (__u16)((urb_index << 8) | priv->interface); | 1014 | urb_index = (__u16)((urb_index << 8) | priv->interface); |
1015 | } | 1015 | } |
1016 | 1016 | ||
1017 | rv = usb_control_msg(port->serial->dev, | 1017 | rv = usb_control_msg(port->serial->dev, |
1018 | usb_sndctrlpipe(port->serial->dev, 0), | 1018 | usb_sndctrlpipe(port->serial->dev, 0), |
1019 | FTDI_SIO_SET_BAUDRATE_REQUEST, | 1019 | FTDI_SIO_SET_BAUDRATE_REQUEST, |
1020 | FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, | 1020 | FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, |
1021 | urb_value, urb_index, | 1021 | urb_value, urb_index, |
1022 | buf, 0, WDR_SHORT_TIMEOUT); | 1022 | buf, 0, WDR_SHORT_TIMEOUT); |
1023 | 1023 | ||
1024 | kfree(buf); | 1024 | kfree(buf); |
1025 | return rv; | 1025 | return rv; |
1026 | } | 1026 | } |
1027 | 1027 | ||
1028 | 1028 | ||
1029 | 1029 | ||
1030 | static int get_serial_info(struct usb_serial_port *port, | 1030 | static int get_serial_info(struct usb_serial_port *port, |
1031 | struct serial_struct __user *retinfo) | 1031 | struct serial_struct __user *retinfo) |
1032 | { | 1032 | { |
1033 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1033 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1034 | struct serial_struct tmp; | 1034 | struct serial_struct tmp; |
1035 | 1035 | ||
1036 | if (!retinfo) | 1036 | if (!retinfo) |
1037 | return -EFAULT; | 1037 | return -EFAULT; |
1038 | memset(&tmp, 0, sizeof(tmp)); | 1038 | memset(&tmp, 0, sizeof(tmp)); |
1039 | tmp.flags = priv->flags; | 1039 | tmp.flags = priv->flags; |
1040 | tmp.baud_base = priv->baud_base; | 1040 | tmp.baud_base = priv->baud_base; |
1041 | tmp.custom_divisor = priv->custom_divisor; | 1041 | tmp.custom_divisor = priv->custom_divisor; |
1042 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) | 1042 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) |
1043 | return -EFAULT; | 1043 | return -EFAULT; |
1044 | return 0; | 1044 | return 0; |
1045 | } /* get_serial_info */ | 1045 | } /* get_serial_info */ |
1046 | 1046 | ||
1047 | 1047 | ||
1048 | static int set_serial_info(struct tty_struct *tty, | 1048 | static int set_serial_info(struct tty_struct *tty, |
1049 | struct usb_serial_port *port, struct serial_struct __user *newinfo) | 1049 | struct usb_serial_port *port, struct serial_struct __user *newinfo) |
1050 | { /* set_serial_info */ | 1050 | { /* set_serial_info */ |
1051 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1051 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1052 | struct serial_struct new_serial; | 1052 | struct serial_struct new_serial; |
1053 | struct ftdi_private old_priv; | 1053 | struct ftdi_private old_priv; |
1054 | 1054 | ||
1055 | if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) | 1055 | if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) |
1056 | return -EFAULT; | 1056 | return -EFAULT; |
1057 | |||
1058 | lock_kernel(); | ||
1057 | old_priv = *priv; | 1059 | old_priv = *priv; |
1058 | 1060 | ||
1059 | /* Do error checking and permission checking */ | 1061 | /* Do error checking and permission checking */ |
1060 | 1062 | ||
1061 | if (!capable(CAP_SYS_ADMIN)) { | 1063 | if (!capable(CAP_SYS_ADMIN)) { |
1062 | if (((new_serial.flags & ~ASYNC_USR_MASK) != | 1064 | if (((new_serial.flags & ~ASYNC_USR_MASK) != |
1063 | (priv->flags & ~ASYNC_USR_MASK))) | 1065 | (priv->flags & ~ASYNC_USR_MASK))) |
1064 | return -EPERM; | 1066 | return -EPERM; |
1065 | priv->flags = ((priv->flags & ~ASYNC_USR_MASK) | | 1067 | priv->flags = ((priv->flags & ~ASYNC_USR_MASK) | |
1066 | (new_serial.flags & ASYNC_USR_MASK)); | 1068 | (new_serial.flags & ASYNC_USR_MASK)); |
1067 | priv->custom_divisor = new_serial.custom_divisor; | 1069 | priv->custom_divisor = new_serial.custom_divisor; |
1068 | goto check_and_exit; | 1070 | goto check_and_exit; |
1069 | } | 1071 | } |
1070 | 1072 | ||
1071 | if ((new_serial.baud_base != priv->baud_base) && | 1073 | if ((new_serial.baud_base != priv->baud_base) && |
1072 | (new_serial.baud_base < 9600)) | 1074 | (new_serial.baud_base < 9600)) { |
1075 | unlock_kernel(); | ||
1073 | return -EINVAL; | 1076 | return -EINVAL; |
1077 | } | ||
1074 | 1078 | ||
1075 | /* Make the changes - these are privileged changes! */ | 1079 | /* Make the changes - these are privileged changes! */ |
1076 | 1080 | ||
1077 | priv->flags = ((priv->flags & ~ASYNC_FLAGS) | | 1081 | priv->flags = ((priv->flags & ~ASYNC_FLAGS) | |
1078 | (new_serial.flags & ASYNC_FLAGS)); | 1082 | (new_serial.flags & ASYNC_FLAGS)); |
1079 | priv->custom_divisor = new_serial.custom_divisor; | 1083 | priv->custom_divisor = new_serial.custom_divisor; |
1080 | 1084 | ||
1081 | tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 1085 | tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
1082 | 1086 | ||
1083 | check_and_exit: | 1087 | check_and_exit: |
1084 | if ((old_priv.flags & ASYNC_SPD_MASK) != | 1088 | if ((old_priv.flags & ASYNC_SPD_MASK) != |
1085 | (priv->flags & ASYNC_SPD_MASK)) { | 1089 | (priv->flags & ASYNC_SPD_MASK)) { |
1086 | if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) | 1090 | if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) |
1087 | tty->alt_speed = 57600; | 1091 | tty->alt_speed = 57600; |
1088 | else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) | 1092 | else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) |
1089 | tty->alt_speed = 115200; | 1093 | tty->alt_speed = 115200; |
1090 | else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) | 1094 | else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) |
1091 | tty->alt_speed = 230400; | 1095 | tty->alt_speed = 230400; |
1092 | else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) | 1096 | else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) |
1093 | tty->alt_speed = 460800; | 1097 | tty->alt_speed = 460800; |
1094 | else | 1098 | else |
1095 | tty->alt_speed = 0; | 1099 | tty->alt_speed = 0; |
1096 | } | 1100 | } |
1097 | if (((old_priv.flags & ASYNC_SPD_MASK) != | 1101 | if (((old_priv.flags & ASYNC_SPD_MASK) != |
1098 | (priv->flags & ASYNC_SPD_MASK)) || | 1102 | (priv->flags & ASYNC_SPD_MASK)) || |
1099 | (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && | 1103 | (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && |
1100 | (old_priv.custom_divisor != priv->custom_divisor))) { | 1104 | (old_priv.custom_divisor != priv->custom_divisor))) { |
1105 | unlock_kernel(); | ||
1101 | change_speed(tty, port); | 1106 | change_speed(tty, port); |
1102 | } | 1107 | } |
1108 | else | ||
1109 | unlock_kernel(); | ||
1103 | return 0; | 1110 | return 0; |
1104 | 1111 | ||
1105 | } /* set_serial_info */ | 1112 | } /* set_serial_info */ |
1106 | 1113 | ||
1107 | 1114 | ||
1108 | /* Determine type of FTDI chip based on USB config and descriptor. */ | 1115 | /* Determine type of FTDI chip based on USB config and descriptor. */ |
1109 | static void ftdi_determine_type(struct usb_serial_port *port) | 1116 | static void ftdi_determine_type(struct usb_serial_port *port) |
1110 | { | 1117 | { |
1111 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1118 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1112 | struct usb_serial *serial = port->serial; | 1119 | struct usb_serial *serial = port->serial; |
1113 | struct usb_device *udev = serial->dev; | 1120 | struct usb_device *udev = serial->dev; |
1114 | unsigned version; | 1121 | unsigned version; |
1115 | unsigned interfaces; | 1122 | unsigned interfaces; |
1116 | 1123 | ||
1117 | /* Assume it is not the original SIO device for now. */ | 1124 | /* Assume it is not the original SIO device for now. */ |
1118 | priv->baud_base = 48000000 / 2; | 1125 | priv->baud_base = 48000000 / 2; |
1119 | priv->write_offset = 0; | 1126 | priv->write_offset = 0; |
1120 | 1127 | ||
1121 | version = le16_to_cpu(udev->descriptor.bcdDevice); | 1128 | version = le16_to_cpu(udev->descriptor.bcdDevice); |
1122 | interfaces = udev->actconfig->desc.bNumInterfaces; | 1129 | interfaces = udev->actconfig->desc.bNumInterfaces; |
1123 | dbg("%s: bcdDevice = 0x%x, bNumInterfaces = %u", __func__, | 1130 | dbg("%s: bcdDevice = 0x%x, bNumInterfaces = %u", __func__, |
1124 | version, interfaces); | 1131 | version, interfaces); |
1125 | if (interfaces > 1) { | 1132 | if (interfaces > 1) { |
1126 | int inter; | 1133 | int inter; |
1127 | 1134 | ||
1128 | /* Multiple interfaces. Assume FT2232C. */ | 1135 | /* Multiple interfaces. Assume FT2232C. */ |
1129 | priv->chip_type = FT2232C; | 1136 | priv->chip_type = FT2232C; |
1130 | /* Determine interface code. */ | 1137 | /* Determine interface code. */ |
1131 | inter = serial->interface->altsetting->desc.bInterfaceNumber; | 1138 | inter = serial->interface->altsetting->desc.bInterfaceNumber; |
1132 | if (inter == 0) | 1139 | if (inter == 0) |
1133 | priv->interface = PIT_SIOA; | 1140 | priv->interface = PIT_SIOA; |
1134 | else | 1141 | else |
1135 | priv->interface = PIT_SIOB; | 1142 | priv->interface = PIT_SIOB; |
1136 | /* BM-type devices have a bug where bcdDevice gets set | 1143 | /* BM-type devices have a bug where bcdDevice gets set |
1137 | * to 0x200 when iSerialNumber is 0. */ | 1144 | * to 0x200 when iSerialNumber is 0. */ |
1138 | if (version < 0x500) { | 1145 | if (version < 0x500) { |
1139 | dbg("%s: something fishy - bcdDevice too low for multi-interface device", | 1146 | dbg("%s: something fishy - bcdDevice too low for multi-interface device", |
1140 | __func__); | 1147 | __func__); |
1141 | } | 1148 | } |
1142 | } else if (version < 0x200) { | 1149 | } else if (version < 0x200) { |
1143 | /* Old device. Assume its the original SIO. */ | 1150 | /* Old device. Assume its the original SIO. */ |
1144 | priv->chip_type = SIO; | 1151 | priv->chip_type = SIO; |
1145 | priv->baud_base = 12000000 / 16; | 1152 | priv->baud_base = 12000000 / 16; |
1146 | priv->write_offset = 1; | 1153 | priv->write_offset = 1; |
1147 | } else if (version < 0x400) { | 1154 | } else if (version < 0x400) { |
1148 | /* Assume its an FT8U232AM (or FT8U245AM) */ | 1155 | /* Assume its an FT8U232AM (or FT8U245AM) */ |
1149 | /* (It might be a BM because of the iSerialNumber bug, | 1156 | /* (It might be a BM because of the iSerialNumber bug, |
1150 | * but it will still work as an AM device.) */ | 1157 | * but it will still work as an AM device.) */ |
1151 | priv->chip_type = FT8U232AM; | 1158 | priv->chip_type = FT8U232AM; |
1152 | } else if (version < 0x600) { | 1159 | } else if (version < 0x600) { |
1153 | /* Assume its an FT232BM (or FT245BM) */ | 1160 | /* Assume its an FT232BM (or FT245BM) */ |
1154 | priv->chip_type = FT232BM; | 1161 | priv->chip_type = FT232BM; |
1155 | } else { | 1162 | } else { |
1156 | /* Assume its an FT232R */ | 1163 | /* Assume its an FT232R */ |
1157 | priv->chip_type = FT232RL; | 1164 | priv->chip_type = FT232RL; |
1158 | } | 1165 | } |
1159 | dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]); | 1166 | dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]); |
1160 | } | 1167 | } |
1161 | 1168 | ||
1162 | 1169 | ||
1163 | /* | 1170 | /* |
1164 | * *************************************************************************** | 1171 | * *************************************************************************** |
1165 | * Sysfs Attribute | 1172 | * Sysfs Attribute |
1166 | * *************************************************************************** | 1173 | * *************************************************************************** |
1167 | */ | 1174 | */ |
1168 | 1175 | ||
1169 | static ssize_t show_latency_timer(struct device *dev, | 1176 | static ssize_t show_latency_timer(struct device *dev, |
1170 | struct device_attribute *attr, char *buf) | 1177 | struct device_attribute *attr, char *buf) |
1171 | { | 1178 | { |
1172 | struct usb_serial_port *port = to_usb_serial_port(dev); | 1179 | struct usb_serial_port *port = to_usb_serial_port(dev); |
1173 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1180 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1174 | struct usb_device *udev = port->serial->dev; | 1181 | struct usb_device *udev = port->serial->dev; |
1175 | unsigned short latency = 0; | 1182 | unsigned short latency = 0; |
1176 | int rv = 0; | 1183 | int rv = 0; |
1177 | 1184 | ||
1178 | 1185 | ||
1179 | dbg("%s", __func__); | 1186 | dbg("%s", __func__); |
1180 | 1187 | ||
1181 | rv = usb_control_msg(udev, | 1188 | rv = usb_control_msg(udev, |
1182 | usb_rcvctrlpipe(udev, 0), | 1189 | usb_rcvctrlpipe(udev, 0), |
1183 | FTDI_SIO_GET_LATENCY_TIMER_REQUEST, | 1190 | FTDI_SIO_GET_LATENCY_TIMER_REQUEST, |
1184 | FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE, | 1191 | FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE, |
1185 | 0, priv->interface, | 1192 | 0, priv->interface, |
1186 | (char *) &latency, 1, WDR_TIMEOUT); | 1193 | (char *) &latency, 1, WDR_TIMEOUT); |
1187 | 1194 | ||
1188 | if (rv < 0) { | 1195 | if (rv < 0) { |
1189 | dev_err(dev, "Unable to read latency timer: %i\n", rv); | 1196 | dev_err(dev, "Unable to read latency timer: %i\n", rv); |
1190 | return -EIO; | 1197 | return -EIO; |
1191 | } | 1198 | } |
1192 | return sprintf(buf, "%i\n", latency); | 1199 | return sprintf(buf, "%i\n", latency); |
1193 | } | 1200 | } |
1194 | 1201 | ||
1195 | /* Write a new value of the latency timer, in units of milliseconds. */ | 1202 | /* Write a new value of the latency timer, in units of milliseconds. */ |
1196 | static ssize_t store_latency_timer(struct device *dev, | 1203 | static ssize_t store_latency_timer(struct device *dev, |
1197 | struct device_attribute *attr, const char *valbuf, | 1204 | struct device_attribute *attr, const char *valbuf, |
1198 | size_t count) | 1205 | size_t count) |
1199 | { | 1206 | { |
1200 | struct usb_serial_port *port = to_usb_serial_port(dev); | 1207 | struct usb_serial_port *port = to_usb_serial_port(dev); |
1201 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1208 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1202 | struct usb_device *udev = port->serial->dev; | 1209 | struct usb_device *udev = port->serial->dev; |
1203 | char buf[1]; | 1210 | char buf[1]; |
1204 | int v = simple_strtoul(valbuf, NULL, 10); | 1211 | int v = simple_strtoul(valbuf, NULL, 10); |
1205 | int rv = 0; | 1212 | int rv = 0; |
1206 | 1213 | ||
1207 | dbg("%s: setting latency timer = %i", __func__, v); | 1214 | dbg("%s: setting latency timer = %i", __func__, v); |
1208 | 1215 | ||
1209 | rv = usb_control_msg(udev, | 1216 | rv = usb_control_msg(udev, |
1210 | usb_sndctrlpipe(udev, 0), | 1217 | usb_sndctrlpipe(udev, 0), |
1211 | FTDI_SIO_SET_LATENCY_TIMER_REQUEST, | 1218 | FTDI_SIO_SET_LATENCY_TIMER_REQUEST, |
1212 | FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, | 1219 | FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, |
1213 | v, priv->interface, | 1220 | v, priv->interface, |
1214 | buf, 0, WDR_TIMEOUT); | 1221 | buf, 0, WDR_TIMEOUT); |
1215 | 1222 | ||
1216 | if (rv < 0) { | 1223 | if (rv < 0) { |
1217 | dev_err(dev, "Unable to write latency timer: %i\n", rv); | 1224 | dev_err(dev, "Unable to write latency timer: %i\n", rv); |
1218 | return -EIO; | 1225 | return -EIO; |
1219 | } | 1226 | } |
1220 | 1227 | ||
1221 | return count; | 1228 | return count; |
1222 | } | 1229 | } |
1223 | 1230 | ||
1224 | /* Write an event character directly to the FTDI register. The ASCII | 1231 | /* Write an event character directly to the FTDI register. The ASCII |
1225 | value is in the low 8 bits, with the enable bit in the 9th bit. */ | 1232 | value is in the low 8 bits, with the enable bit in the 9th bit. */ |
1226 | static ssize_t store_event_char(struct device *dev, | 1233 | static ssize_t store_event_char(struct device *dev, |
1227 | struct device_attribute *attr, const char *valbuf, size_t count) | 1234 | struct device_attribute *attr, const char *valbuf, size_t count) |
1228 | { | 1235 | { |
1229 | struct usb_serial_port *port = to_usb_serial_port(dev); | 1236 | struct usb_serial_port *port = to_usb_serial_port(dev); |
1230 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1237 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1231 | struct usb_device *udev = port->serial->dev; | 1238 | struct usb_device *udev = port->serial->dev; |
1232 | char buf[1]; | 1239 | char buf[1]; |
1233 | int v = simple_strtoul(valbuf, NULL, 10); | 1240 | int v = simple_strtoul(valbuf, NULL, 10); |
1234 | int rv = 0; | 1241 | int rv = 0; |
1235 | 1242 | ||
1236 | dbg("%s: setting event char = %i", __func__, v); | 1243 | dbg("%s: setting event char = %i", __func__, v); |
1237 | 1244 | ||
1238 | rv = usb_control_msg(udev, | 1245 | rv = usb_control_msg(udev, |
1239 | usb_sndctrlpipe(udev, 0), | 1246 | usb_sndctrlpipe(udev, 0), |
1240 | FTDI_SIO_SET_EVENT_CHAR_REQUEST, | 1247 | FTDI_SIO_SET_EVENT_CHAR_REQUEST, |
1241 | FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE, | 1248 | FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE, |
1242 | v, priv->interface, | 1249 | v, priv->interface, |
1243 | buf, 0, WDR_TIMEOUT); | 1250 | buf, 0, WDR_TIMEOUT); |
1244 | 1251 | ||
1245 | if (rv < 0) { | 1252 | if (rv < 0) { |
1246 | dbg("Unable to write event character: %i", rv); | 1253 | dbg("Unable to write event character: %i", rv); |
1247 | return -EIO; | 1254 | return -EIO; |
1248 | } | 1255 | } |
1249 | 1256 | ||
1250 | return count; | 1257 | return count; |
1251 | } | 1258 | } |
1252 | 1259 | ||
1253 | static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, | 1260 | static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, |
1254 | store_latency_timer); | 1261 | store_latency_timer); |
1255 | static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char); | 1262 | static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char); |
1256 | 1263 | ||
1257 | static int create_sysfs_attrs(struct usb_serial_port *port) | 1264 | static int create_sysfs_attrs(struct usb_serial_port *port) |
1258 | { | 1265 | { |
1259 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1266 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1260 | int retval = 0; | 1267 | int retval = 0; |
1261 | 1268 | ||
1262 | dbg("%s", __func__); | 1269 | dbg("%s", __func__); |
1263 | 1270 | ||
1264 | /* XXX I've no idea if the original SIO supports the event_char | 1271 | /* XXX I've no idea if the original SIO supports the event_char |
1265 | * sysfs parameter, so I'm playing it safe. */ | 1272 | * sysfs parameter, so I'm playing it safe. */ |
1266 | if (priv->chip_type != SIO) { | 1273 | if (priv->chip_type != SIO) { |
1267 | dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]); | 1274 | dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]); |
1268 | retval = device_create_file(&port->dev, &dev_attr_event_char); | 1275 | retval = device_create_file(&port->dev, &dev_attr_event_char); |
1269 | if ((!retval) && | 1276 | if ((!retval) && |
1270 | (priv->chip_type == FT232BM || | 1277 | (priv->chip_type == FT232BM || |
1271 | priv->chip_type == FT2232C || | 1278 | priv->chip_type == FT2232C || |
1272 | priv->chip_type == FT232RL)) { | 1279 | priv->chip_type == FT232RL)) { |
1273 | retval = device_create_file(&port->dev, | 1280 | retval = device_create_file(&port->dev, |
1274 | &dev_attr_latency_timer); | 1281 | &dev_attr_latency_timer); |
1275 | } | 1282 | } |
1276 | } | 1283 | } |
1277 | return retval; | 1284 | return retval; |
1278 | } | 1285 | } |
1279 | 1286 | ||
1280 | static void remove_sysfs_attrs(struct usb_serial_port *port) | 1287 | static void remove_sysfs_attrs(struct usb_serial_port *port) |
1281 | { | 1288 | { |
1282 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1289 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1283 | 1290 | ||
1284 | dbg("%s", __func__); | 1291 | dbg("%s", __func__); |
1285 | 1292 | ||
1286 | /* XXX see create_sysfs_attrs */ | 1293 | /* XXX see create_sysfs_attrs */ |
1287 | if (priv->chip_type != SIO) { | 1294 | if (priv->chip_type != SIO) { |
1288 | device_remove_file(&port->dev, &dev_attr_event_char); | 1295 | device_remove_file(&port->dev, &dev_attr_event_char); |
1289 | if (priv->chip_type == FT232BM || | 1296 | if (priv->chip_type == FT232BM || |
1290 | priv->chip_type == FT2232C || | 1297 | priv->chip_type == FT2232C || |
1291 | priv->chip_type == FT232RL) { | 1298 | priv->chip_type == FT232RL) { |
1292 | device_remove_file(&port->dev, &dev_attr_latency_timer); | 1299 | device_remove_file(&port->dev, &dev_attr_latency_timer); |
1293 | } | 1300 | } |
1294 | } | 1301 | } |
1295 | 1302 | ||
1296 | } | 1303 | } |
1297 | 1304 | ||
1298 | /* | 1305 | /* |
1299 | * *************************************************************************** | 1306 | * *************************************************************************** |
1300 | * FTDI driver specific functions | 1307 | * FTDI driver specific functions |
1301 | * *************************************************************************** | 1308 | * *************************************************************************** |
1302 | */ | 1309 | */ |
1303 | 1310 | ||
1304 | /* Probe function to check for special devices */ | 1311 | /* Probe function to check for special devices */ |
1305 | static int ftdi_sio_probe(struct usb_serial *serial, | 1312 | static int ftdi_sio_probe(struct usb_serial *serial, |
1306 | const struct usb_device_id *id) | 1313 | const struct usb_device_id *id) |
1307 | { | 1314 | { |
1308 | struct ftdi_sio_quirk *quirk = | 1315 | struct ftdi_sio_quirk *quirk = |
1309 | (struct ftdi_sio_quirk *)id->driver_info; | 1316 | (struct ftdi_sio_quirk *)id->driver_info; |
1310 | 1317 | ||
1311 | if (quirk && quirk->probe) { | 1318 | if (quirk && quirk->probe) { |
1312 | int ret = quirk->probe(serial); | 1319 | int ret = quirk->probe(serial); |
1313 | if (ret != 0) | 1320 | if (ret != 0) |
1314 | return ret; | 1321 | return ret; |
1315 | } | 1322 | } |
1316 | 1323 | ||
1317 | usb_set_serial_data(serial, (void *)id->driver_info); | 1324 | usb_set_serial_data(serial, (void *)id->driver_info); |
1318 | 1325 | ||
1319 | return 0; | 1326 | return 0; |
1320 | } | 1327 | } |
1321 | 1328 | ||
1322 | static int ftdi_sio_port_probe(struct usb_serial_port *port) | 1329 | static int ftdi_sio_port_probe(struct usb_serial_port *port) |
1323 | { | 1330 | { |
1324 | struct ftdi_private *priv; | 1331 | struct ftdi_private *priv; |
1325 | struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial); | 1332 | struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial); |
1326 | 1333 | ||
1327 | 1334 | ||
1328 | dbg("%s", __func__); | 1335 | dbg("%s", __func__); |
1329 | 1336 | ||
1330 | priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL); | 1337 | priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL); |
1331 | if (!priv) { | 1338 | if (!priv) { |
1332 | dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__, | 1339 | dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__, |
1333 | sizeof(struct ftdi_private)); | 1340 | sizeof(struct ftdi_private)); |
1334 | return -ENOMEM; | 1341 | return -ENOMEM; |
1335 | } | 1342 | } |
1336 | 1343 | ||
1337 | spin_lock_init(&priv->rx_lock); | 1344 | spin_lock_init(&priv->rx_lock); |
1338 | spin_lock_init(&priv->tx_lock); | 1345 | spin_lock_init(&priv->tx_lock); |
1339 | init_waitqueue_head(&priv->delta_msr_wait); | 1346 | init_waitqueue_head(&priv->delta_msr_wait); |
1340 | /* This will push the characters through immediately rather | 1347 | /* This will push the characters through immediately rather |
1341 | than queue a task to deliver them */ | 1348 | than queue a task to deliver them */ |
1342 | priv->flags = ASYNC_LOW_LATENCY; | 1349 | priv->flags = ASYNC_LOW_LATENCY; |
1343 | 1350 | ||
1344 | if (quirk && quirk->port_probe) | 1351 | if (quirk && quirk->port_probe) |
1345 | quirk->port_probe(priv); | 1352 | quirk->port_probe(priv); |
1346 | 1353 | ||
1347 | /* Increase the size of read buffers */ | 1354 | /* Increase the size of read buffers */ |
1348 | kfree(port->bulk_in_buffer); | 1355 | kfree(port->bulk_in_buffer); |
1349 | port->bulk_in_buffer = kmalloc(BUFSZ, GFP_KERNEL); | 1356 | port->bulk_in_buffer = kmalloc(BUFSZ, GFP_KERNEL); |
1350 | if (!port->bulk_in_buffer) { | 1357 | if (!port->bulk_in_buffer) { |
1351 | kfree(priv); | 1358 | kfree(priv); |
1352 | return -ENOMEM; | 1359 | return -ENOMEM; |
1353 | } | 1360 | } |
1354 | if (port->read_urb) { | 1361 | if (port->read_urb) { |
1355 | port->read_urb->transfer_buffer = port->bulk_in_buffer; | 1362 | port->read_urb->transfer_buffer = port->bulk_in_buffer; |
1356 | port->read_urb->transfer_buffer_length = BUFSZ; | 1363 | port->read_urb->transfer_buffer_length = BUFSZ; |
1357 | } | 1364 | } |
1358 | 1365 | ||
1359 | INIT_DELAYED_WORK(&priv->rx_work, ftdi_process_read); | 1366 | INIT_DELAYED_WORK(&priv->rx_work, ftdi_process_read); |
1360 | priv->port = port; | 1367 | priv->port = port; |
1361 | 1368 | ||
1362 | /* Free port's existing write urb and transfer buffer. */ | 1369 | /* Free port's existing write urb and transfer buffer. */ |
1363 | if (port->write_urb) { | 1370 | if (port->write_urb) { |
1364 | usb_free_urb(port->write_urb); | 1371 | usb_free_urb(port->write_urb); |
1365 | port->write_urb = NULL; | 1372 | port->write_urb = NULL; |
1366 | } | 1373 | } |
1367 | kfree(port->bulk_out_buffer); | 1374 | kfree(port->bulk_out_buffer); |
1368 | port->bulk_out_buffer = NULL; | 1375 | port->bulk_out_buffer = NULL; |
1369 | 1376 | ||
1370 | usb_set_serial_port_data(port, priv); | 1377 | usb_set_serial_port_data(port, priv); |
1371 | 1378 | ||
1372 | ftdi_determine_type(port); | 1379 | ftdi_determine_type(port); |
1373 | create_sysfs_attrs(port); | 1380 | create_sysfs_attrs(port); |
1374 | return 0; | 1381 | return 0; |
1375 | } | 1382 | } |
1376 | 1383 | ||
1377 | /* Setup for the USB-UIRT device, which requires hardwired | 1384 | /* Setup for the USB-UIRT device, which requires hardwired |
1378 | * baudrate (38400 gets mapped to 312500) */ | 1385 | * baudrate (38400 gets mapped to 312500) */ |
1379 | /* Called from usbserial:serial_probe */ | 1386 | /* Called from usbserial:serial_probe */ |
1380 | static void ftdi_USB_UIRT_setup(struct ftdi_private *priv) | 1387 | static void ftdi_USB_UIRT_setup(struct ftdi_private *priv) |
1381 | { | 1388 | { |
1382 | dbg("%s", __func__); | 1389 | dbg("%s", __func__); |
1383 | 1390 | ||
1384 | priv->flags |= ASYNC_SPD_CUST; | 1391 | priv->flags |= ASYNC_SPD_CUST; |
1385 | priv->custom_divisor = 77; | 1392 | priv->custom_divisor = 77; |
1386 | priv->force_baud = 38400; | 1393 | priv->force_baud = 38400; |
1387 | } /* ftdi_USB_UIRT_setup */ | 1394 | } /* ftdi_USB_UIRT_setup */ |
1388 | 1395 | ||
1389 | /* Setup for the HE-TIRA1 device, which requires hardwired | 1396 | /* Setup for the HE-TIRA1 device, which requires hardwired |
1390 | * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled. */ | 1397 | * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled. */ |
1391 | 1398 | ||
1392 | static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv) | 1399 | static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv) |
1393 | { | 1400 | { |
1394 | dbg("%s", __func__); | 1401 | dbg("%s", __func__); |
1395 | 1402 | ||
1396 | priv->flags |= ASYNC_SPD_CUST; | 1403 | priv->flags |= ASYNC_SPD_CUST; |
1397 | priv->custom_divisor = 240; | 1404 | priv->custom_divisor = 240; |
1398 | priv->force_baud = 38400; | 1405 | priv->force_baud = 38400; |
1399 | priv->force_rtscts = 1; | 1406 | priv->force_rtscts = 1; |
1400 | } /* ftdi_HE_TIRA1_setup */ | 1407 | } /* ftdi_HE_TIRA1_setup */ |
1401 | 1408 | ||
1402 | /* | 1409 | /* |
1403 | * First port on JTAG adaptors such as Olimex arm-usb-ocd or the FIC/OpenMoko | 1410 | * First port on JTAG adaptors such as Olimex arm-usb-ocd or the FIC/OpenMoko |
1404 | * Neo1973 Debug Board is reserved for JTAG interface and can be accessed from | 1411 | * Neo1973 Debug Board is reserved for JTAG interface and can be accessed from |
1405 | * userspace using openocd. | 1412 | * userspace using openocd. |
1406 | */ | 1413 | */ |
1407 | static int ftdi_jtag_probe(struct usb_serial *serial) | 1414 | static int ftdi_jtag_probe(struct usb_serial *serial) |
1408 | { | 1415 | { |
1409 | struct usb_device *udev = serial->dev; | 1416 | struct usb_device *udev = serial->dev; |
1410 | struct usb_interface *interface = serial->interface; | 1417 | struct usb_interface *interface = serial->interface; |
1411 | 1418 | ||
1412 | dbg("%s", __func__); | 1419 | dbg("%s", __func__); |
1413 | 1420 | ||
1414 | if (interface == udev->actconfig->interface[0]) { | 1421 | if (interface == udev->actconfig->interface[0]) { |
1415 | dev_info(&udev->dev, | 1422 | dev_info(&udev->dev, |
1416 | "Ignoring serial port reserved for JTAG\n"); | 1423 | "Ignoring serial port reserved for JTAG\n"); |
1417 | return -ENODEV; | 1424 | return -ENODEV; |
1418 | } | 1425 | } |
1419 | 1426 | ||
1420 | return 0; | 1427 | return 0; |
1421 | } | 1428 | } |
1422 | 1429 | ||
1423 | /* | 1430 | /* |
1424 | * The Matrix Orbital VK204-25-USB has an invalid IN endpoint. | 1431 | * The Matrix Orbital VK204-25-USB has an invalid IN endpoint. |
1425 | * We have to correct it if we want to read from it. | 1432 | * We have to correct it if we want to read from it. |
1426 | */ | 1433 | */ |
1427 | static int ftdi_mtxorb_hack_setup(struct usb_serial *serial) | 1434 | static int ftdi_mtxorb_hack_setup(struct usb_serial *serial) |
1428 | { | 1435 | { |
1429 | struct usb_host_endpoint *ep = serial->dev->ep_in[1]; | 1436 | struct usb_host_endpoint *ep = serial->dev->ep_in[1]; |
1430 | struct usb_endpoint_descriptor *ep_desc = &ep->desc; | 1437 | struct usb_endpoint_descriptor *ep_desc = &ep->desc; |
1431 | 1438 | ||
1432 | if (ep->enabled && ep_desc->wMaxPacketSize == 0) { | 1439 | if (ep->enabled && ep_desc->wMaxPacketSize == 0) { |
1433 | ep_desc->wMaxPacketSize = cpu_to_le16(0x40); | 1440 | ep_desc->wMaxPacketSize = cpu_to_le16(0x40); |
1434 | dev_info(&serial->dev->dev, | 1441 | dev_info(&serial->dev->dev, |
1435 | "Fixing invalid wMaxPacketSize on read pipe\n"); | 1442 | "Fixing invalid wMaxPacketSize on read pipe\n"); |
1436 | } | 1443 | } |
1437 | 1444 | ||
1438 | return 0; | 1445 | return 0; |
1439 | } | 1446 | } |
1440 | 1447 | ||
1441 | /* ftdi_shutdown is called from usbserial:usb_serial_disconnect | 1448 | /* ftdi_shutdown is called from usbserial:usb_serial_disconnect |
1442 | * it is called when the usb device is disconnected | 1449 | * it is called when the usb device is disconnected |
1443 | * | 1450 | * |
1444 | * usbserial:usb_serial_disconnect | 1451 | * usbserial:usb_serial_disconnect |
1445 | * calls __serial_close for each open of the port | 1452 | * calls __serial_close for each open of the port |
1446 | * shutdown is called then (ie ftdi_shutdown) | 1453 | * shutdown is called then (ie ftdi_shutdown) |
1447 | */ | 1454 | */ |
1448 | static void ftdi_shutdown(struct usb_serial *serial) | 1455 | static void ftdi_shutdown(struct usb_serial *serial) |
1449 | { | 1456 | { |
1450 | dbg("%s", __func__); | 1457 | dbg("%s", __func__); |
1451 | } | 1458 | } |
1452 | 1459 | ||
1453 | static int ftdi_sio_port_remove(struct usb_serial_port *port) | 1460 | static int ftdi_sio_port_remove(struct usb_serial_port *port) |
1454 | { | 1461 | { |
1455 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1462 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1456 | 1463 | ||
1457 | dbg("%s", __func__); | 1464 | dbg("%s", __func__); |
1458 | 1465 | ||
1459 | remove_sysfs_attrs(port); | 1466 | remove_sysfs_attrs(port); |
1460 | 1467 | ||
1461 | /* all open ports are closed at this point | 1468 | /* all open ports are closed at this point |
1462 | * (by usbserial.c:__serial_close, which calls ftdi_close) | 1469 | * (by usbserial.c:__serial_close, which calls ftdi_close) |
1463 | */ | 1470 | */ |
1464 | 1471 | ||
1465 | if (priv) { | 1472 | if (priv) { |
1466 | usb_set_serial_port_data(port, NULL); | 1473 | usb_set_serial_port_data(port, NULL); |
1467 | kfree(priv); | 1474 | kfree(priv); |
1468 | } | 1475 | } |
1469 | 1476 | ||
1470 | return 0; | 1477 | return 0; |
1471 | } | 1478 | } |
1472 | 1479 | ||
1473 | static int ftdi_open(struct tty_struct *tty, | 1480 | static int ftdi_open(struct tty_struct *tty, |
1474 | struct usb_serial_port *port, struct file *filp) | 1481 | struct usb_serial_port *port, struct file *filp) |
1475 | { /* ftdi_open */ | 1482 | { /* ftdi_open */ |
1476 | struct usb_device *dev = port->serial->dev; | 1483 | struct usb_device *dev = port->serial->dev; |
1477 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1484 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1478 | unsigned long flags; | 1485 | unsigned long flags; |
1479 | 1486 | ||
1480 | int result = 0; | 1487 | int result = 0; |
1481 | char buf[1]; /* Needed for the usb_control_msg I think */ | 1488 | char buf[1]; /* Needed for the usb_control_msg I think */ |
1482 | 1489 | ||
1483 | dbg("%s", __func__); | 1490 | dbg("%s", __func__); |
1484 | 1491 | ||
1485 | spin_lock_irqsave(&priv->tx_lock, flags); | 1492 | spin_lock_irqsave(&priv->tx_lock, flags); |
1486 | priv->tx_bytes = 0; | 1493 | priv->tx_bytes = 0; |
1487 | spin_unlock_irqrestore(&priv->tx_lock, flags); | 1494 | spin_unlock_irqrestore(&priv->tx_lock, flags); |
1488 | spin_lock_irqsave(&priv->rx_lock, flags); | 1495 | spin_lock_irqsave(&priv->rx_lock, flags); |
1489 | priv->rx_bytes = 0; | 1496 | priv->rx_bytes = 0; |
1490 | spin_unlock_irqrestore(&priv->rx_lock, flags); | 1497 | spin_unlock_irqrestore(&priv->rx_lock, flags); |
1491 | 1498 | ||
1492 | if (tty) | 1499 | if (tty) |
1493 | tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 1500 | tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
1494 | 1501 | ||
1495 | /* No error checking for this (will get errors later anyway) */ | 1502 | /* No error checking for this (will get errors later anyway) */ |
1496 | /* See ftdi_sio.h for description of what is reset */ | 1503 | /* See ftdi_sio.h for description of what is reset */ |
1497 | usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 1504 | usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
1498 | FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, | 1505 | FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, |
1499 | FTDI_SIO_RESET_SIO, | 1506 | FTDI_SIO_RESET_SIO, |
1500 | priv->interface, buf, 0, WDR_TIMEOUT); | 1507 | priv->interface, buf, 0, WDR_TIMEOUT); |
1501 | 1508 | ||
1502 | /* Termios defaults are set by usb_serial_init. We don't change | 1509 | /* Termios defaults are set by usb_serial_init. We don't change |
1503 | port->tty->termios - this would lose speed settings, etc. | 1510 | port->tty->termios - this would lose speed settings, etc. |
1504 | This is same behaviour as serial.c/rs_open() - Kuba */ | 1511 | This is same behaviour as serial.c/rs_open() - Kuba */ |
1505 | 1512 | ||
1506 | /* ftdi_set_termios will send usb control messages */ | 1513 | /* ftdi_set_termios will send usb control messages */ |
1507 | if (tty) | 1514 | if (tty) |
1508 | ftdi_set_termios(tty, port, tty->termios); | 1515 | ftdi_set_termios(tty, port, tty->termios); |
1509 | 1516 | ||
1510 | /* FIXME: Flow control might be enabled, so it should be checked - | 1517 | /* FIXME: Flow control might be enabled, so it should be checked - |
1511 | we have no control of defaults! */ | 1518 | we have no control of defaults! */ |
1512 | /* Turn on RTS and DTR since we are not flow controlling by default */ | 1519 | /* Turn on RTS and DTR since we are not flow controlling by default */ |
1513 | set_mctrl(port, TIOCM_DTR | TIOCM_RTS); | 1520 | set_mctrl(port, TIOCM_DTR | TIOCM_RTS); |
1514 | 1521 | ||
1515 | /* Not throttled */ | 1522 | /* Not throttled */ |
1516 | spin_lock_irqsave(&priv->rx_lock, flags); | 1523 | spin_lock_irqsave(&priv->rx_lock, flags); |
1517 | priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); | 1524 | priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); |
1518 | spin_unlock_irqrestore(&priv->rx_lock, flags); | 1525 | spin_unlock_irqrestore(&priv->rx_lock, flags); |
1519 | 1526 | ||
1520 | /* Start reading from the device */ | 1527 | /* Start reading from the device */ |
1521 | priv->rx_processed = 0; | 1528 | priv->rx_processed = 0; |
1522 | usb_fill_bulk_urb(port->read_urb, dev, | 1529 | usb_fill_bulk_urb(port->read_urb, dev, |
1523 | usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress), | 1530 | usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress), |
1524 | port->read_urb->transfer_buffer, | 1531 | port->read_urb->transfer_buffer, |
1525 | port->read_urb->transfer_buffer_length, | 1532 | port->read_urb->transfer_buffer_length, |
1526 | ftdi_read_bulk_callback, port); | 1533 | ftdi_read_bulk_callback, port); |
1527 | result = usb_submit_urb(port->read_urb, GFP_KERNEL); | 1534 | result = usb_submit_urb(port->read_urb, GFP_KERNEL); |
1528 | if (result) | 1535 | if (result) |
1529 | dev_err(&port->dev, | 1536 | dev_err(&port->dev, |
1530 | "%s - failed submitting read urb, error %d\n", | 1537 | "%s - failed submitting read urb, error %d\n", |
1531 | __func__, result); | 1538 | __func__, result); |
1532 | 1539 | ||
1533 | 1540 | ||
1534 | return result; | 1541 | return result; |
1535 | } /* ftdi_open */ | 1542 | } /* ftdi_open */ |
1536 | 1543 | ||
1537 | 1544 | ||
1538 | 1545 | ||
1539 | /* | 1546 | /* |
1540 | * usbserial:__serial_close only calls ftdi_close if the point is open | 1547 | * usbserial:__serial_close only calls ftdi_close if the point is open |
1541 | * | 1548 | * |
1542 | * This only gets called when it is the last close | 1549 | * This only gets called when it is the last close |
1543 | * | 1550 | * |
1544 | * | 1551 | * |
1545 | */ | 1552 | */ |
1546 | 1553 | ||
1547 | static void ftdi_close(struct tty_struct *tty, | 1554 | static void ftdi_close(struct tty_struct *tty, |
1548 | struct usb_serial_port *port, struct file *filp) | 1555 | struct usb_serial_port *port, struct file *filp) |
1549 | { /* ftdi_close */ | 1556 | { /* ftdi_close */ |
1550 | unsigned int c_cflag = tty->termios->c_cflag; | 1557 | unsigned int c_cflag = tty->termios->c_cflag; |
1551 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1558 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1552 | char buf[1]; | 1559 | char buf[1]; |
1553 | 1560 | ||
1554 | dbg("%s", __func__); | 1561 | dbg("%s", __func__); |
1555 | 1562 | ||
1556 | mutex_lock(&port->serial->disc_mutex); | 1563 | mutex_lock(&port->serial->disc_mutex); |
1557 | if (c_cflag & HUPCL && !port->serial->disconnected) { | 1564 | if (c_cflag & HUPCL && !port->serial->disconnected) { |
1558 | /* Disable flow control */ | 1565 | /* Disable flow control */ |
1559 | if (usb_control_msg(port->serial->dev, | 1566 | if (usb_control_msg(port->serial->dev, |
1560 | usb_sndctrlpipe(port->serial->dev, 0), | 1567 | usb_sndctrlpipe(port->serial->dev, 0), |
1561 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, | 1568 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, |
1562 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, | 1569 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, |
1563 | 0, priv->interface, buf, 0, | 1570 | 0, priv->interface, buf, 0, |
1564 | WDR_TIMEOUT) < 0) { | 1571 | WDR_TIMEOUT) < 0) { |
1565 | dev_err(&port->dev, "error from flowcontrol urb\n"); | 1572 | dev_err(&port->dev, "error from flowcontrol urb\n"); |
1566 | } | 1573 | } |
1567 | 1574 | ||
1568 | /* drop RTS and DTR */ | 1575 | /* drop RTS and DTR */ |
1569 | clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | 1576 | clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); |
1570 | } /* Note change no line if hupcl is off */ | 1577 | } /* Note change no line if hupcl is off */ |
1571 | mutex_unlock(&port->serial->disc_mutex); | 1578 | mutex_unlock(&port->serial->disc_mutex); |
1572 | 1579 | ||
1573 | /* cancel any scheduled reading */ | 1580 | /* cancel any scheduled reading */ |
1574 | cancel_delayed_work(&priv->rx_work); | 1581 | cancel_delayed_work(&priv->rx_work); |
1575 | flush_scheduled_work(); | 1582 | flush_scheduled_work(); |
1576 | 1583 | ||
1577 | /* shutdown our bulk read */ | 1584 | /* shutdown our bulk read */ |
1578 | usb_kill_urb(port->read_urb); | 1585 | usb_kill_urb(port->read_urb); |
1579 | } /* ftdi_close */ | 1586 | } /* ftdi_close */ |
1580 | 1587 | ||
1581 | 1588 | ||
1582 | 1589 | ||
1583 | /* The SIO requires the first byte to have: | 1590 | /* The SIO requires the first byte to have: |
1584 | * B0 1 | 1591 | * B0 1 |
1585 | * B1 0 | 1592 | * B1 0 |
1586 | * B2..7 length of message excluding byte 0 | 1593 | * B2..7 length of message excluding byte 0 |
1587 | * | 1594 | * |
1588 | * The new devices do not require this byte | 1595 | * The new devices do not require this byte |
1589 | */ | 1596 | */ |
1590 | static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, | 1597 | static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, |
1591 | const unsigned char *buf, int count) | 1598 | const unsigned char *buf, int count) |
1592 | { /* ftdi_write */ | 1599 | { /* ftdi_write */ |
1593 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1600 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1594 | struct urb *urb; | 1601 | struct urb *urb; |
1595 | unsigned char *buffer; | 1602 | unsigned char *buffer; |
1596 | int data_offset ; /* will be 1 for the SIO and 0 otherwise */ | 1603 | int data_offset ; /* will be 1 for the SIO and 0 otherwise */ |
1597 | int status; | 1604 | int status; |
1598 | int transfer_size; | 1605 | int transfer_size; |
1599 | unsigned long flags; | 1606 | unsigned long flags; |
1600 | 1607 | ||
1601 | dbg("%s port %d, %d bytes", __func__, port->number, count); | 1608 | dbg("%s port %d, %d bytes", __func__, port->number, count); |
1602 | 1609 | ||
1603 | if (count == 0) { | 1610 | if (count == 0) { |
1604 | dbg("write request of 0 bytes"); | 1611 | dbg("write request of 0 bytes"); |
1605 | return 0; | 1612 | return 0; |
1606 | } | 1613 | } |
1607 | spin_lock_irqsave(&priv->tx_lock, flags); | 1614 | spin_lock_irqsave(&priv->tx_lock, flags); |
1608 | if (priv->tx_outstanding_urbs > URB_UPPER_LIMIT) { | 1615 | if (priv->tx_outstanding_urbs > URB_UPPER_LIMIT) { |
1609 | spin_unlock_irqrestore(&priv->tx_lock, flags); | 1616 | spin_unlock_irqrestore(&priv->tx_lock, flags); |
1610 | dbg("%s - write limit hit\n", __func__); | 1617 | dbg("%s - write limit hit\n", __func__); |
1611 | return 0; | 1618 | return 0; |
1612 | } | 1619 | } |
1613 | priv->tx_outstanding_urbs++; | 1620 | priv->tx_outstanding_urbs++; |
1614 | spin_unlock_irqrestore(&priv->tx_lock, flags); | 1621 | spin_unlock_irqrestore(&priv->tx_lock, flags); |
1615 | 1622 | ||
1616 | data_offset = priv->write_offset; | 1623 | data_offset = priv->write_offset; |
1617 | dbg("data_offset set to %d", data_offset); | 1624 | dbg("data_offset set to %d", data_offset); |
1618 | 1625 | ||
1619 | /* Determine total transfer size */ | 1626 | /* Determine total transfer size */ |
1620 | transfer_size = count; | 1627 | transfer_size = count; |
1621 | if (data_offset > 0) { | 1628 | if (data_offset > 0) { |
1622 | /* Original sio needs control bytes too... */ | 1629 | /* Original sio needs control bytes too... */ |
1623 | transfer_size += (data_offset * | 1630 | transfer_size += (data_offset * |
1624 | ((count + (PKTSZ - 1 - data_offset)) / | 1631 | ((count + (PKTSZ - 1 - data_offset)) / |
1625 | (PKTSZ - data_offset))); | 1632 | (PKTSZ - data_offset))); |
1626 | } | 1633 | } |
1627 | 1634 | ||
1628 | buffer = kmalloc(transfer_size, GFP_ATOMIC); | 1635 | buffer = kmalloc(transfer_size, GFP_ATOMIC); |
1629 | if (!buffer) { | 1636 | if (!buffer) { |
1630 | dev_err(&port->dev, | 1637 | dev_err(&port->dev, |
1631 | "%s ran out of kernel memory for urb ...\n", __func__); | 1638 | "%s ran out of kernel memory for urb ...\n", __func__); |
1632 | count = -ENOMEM; | 1639 | count = -ENOMEM; |
1633 | goto error_no_buffer; | 1640 | goto error_no_buffer; |
1634 | } | 1641 | } |
1635 | 1642 | ||
1636 | urb = usb_alloc_urb(0, GFP_ATOMIC); | 1643 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
1637 | if (!urb) { | 1644 | if (!urb) { |
1638 | dev_err(&port->dev, "%s - no more free urbs\n", __func__); | 1645 | dev_err(&port->dev, "%s - no more free urbs\n", __func__); |
1639 | count = -ENOMEM; | 1646 | count = -ENOMEM; |
1640 | goto error_no_urb; | 1647 | goto error_no_urb; |
1641 | } | 1648 | } |
1642 | 1649 | ||
1643 | /* Copy data */ | 1650 | /* Copy data */ |
1644 | if (data_offset > 0) { | 1651 | if (data_offset > 0) { |
1645 | /* Original sio requires control byte at start of | 1652 | /* Original sio requires control byte at start of |
1646 | each packet. */ | 1653 | each packet. */ |
1647 | int user_pktsz = PKTSZ - data_offset; | 1654 | int user_pktsz = PKTSZ - data_offset; |
1648 | int todo = count; | 1655 | int todo = count; |
1649 | unsigned char *first_byte = buffer; | 1656 | unsigned char *first_byte = buffer; |
1650 | const unsigned char *current_position = buf; | 1657 | const unsigned char *current_position = buf; |
1651 | 1658 | ||
1652 | while (todo > 0) { | 1659 | while (todo > 0) { |
1653 | if (user_pktsz > todo) | 1660 | if (user_pktsz > todo) |
1654 | user_pktsz = todo; | 1661 | user_pktsz = todo; |
1655 | /* Write the control byte at the front of the packet*/ | 1662 | /* Write the control byte at the front of the packet*/ |
1656 | *first_byte = 1 | ((user_pktsz) << 2); | 1663 | *first_byte = 1 | ((user_pktsz) << 2); |
1657 | /* Copy data for packet */ | 1664 | /* Copy data for packet */ |
1658 | memcpy(first_byte + data_offset, | 1665 | memcpy(first_byte + data_offset, |
1659 | current_position, user_pktsz); | 1666 | current_position, user_pktsz); |
1660 | first_byte += user_pktsz + data_offset; | 1667 | first_byte += user_pktsz + data_offset; |
1661 | current_position += user_pktsz; | 1668 | current_position += user_pktsz; |
1662 | todo -= user_pktsz; | 1669 | todo -= user_pktsz; |
1663 | } | 1670 | } |
1664 | } else { | 1671 | } else { |
1665 | /* No control byte required. */ | 1672 | /* No control byte required. */ |
1666 | /* Copy in the data to send */ | 1673 | /* Copy in the data to send */ |
1667 | memcpy(buffer, buf, count); | 1674 | memcpy(buffer, buf, count); |
1668 | } | 1675 | } |
1669 | 1676 | ||
1670 | usb_serial_debug_data(debug, &port->dev, __func__, | 1677 | usb_serial_debug_data(debug, &port->dev, __func__, |
1671 | transfer_size, buffer); | 1678 | transfer_size, buffer); |
1672 | 1679 | ||
1673 | /* fill the buffer and send it */ | 1680 | /* fill the buffer and send it */ |
1674 | usb_fill_bulk_urb(urb, port->serial->dev, | 1681 | usb_fill_bulk_urb(urb, port->serial->dev, |
1675 | usb_sndbulkpipe(port->serial->dev, | 1682 | usb_sndbulkpipe(port->serial->dev, |
1676 | port->bulk_out_endpointAddress), | 1683 | port->bulk_out_endpointAddress), |
1677 | buffer, transfer_size, | 1684 | buffer, transfer_size, |
1678 | ftdi_write_bulk_callback, port); | 1685 | ftdi_write_bulk_callback, port); |
1679 | 1686 | ||
1680 | status = usb_submit_urb(urb, GFP_ATOMIC); | 1687 | status = usb_submit_urb(urb, GFP_ATOMIC); |
1681 | if (status) { | 1688 | if (status) { |
1682 | dev_err(&port->dev, | 1689 | dev_err(&port->dev, |
1683 | "%s - failed submitting write urb, error %d\n", | 1690 | "%s - failed submitting write urb, error %d\n", |
1684 | __func__, status); | 1691 | __func__, status); |
1685 | count = status; | 1692 | count = status; |
1686 | goto error; | 1693 | goto error; |
1687 | } else { | 1694 | } else { |
1688 | spin_lock_irqsave(&priv->tx_lock, flags); | 1695 | spin_lock_irqsave(&priv->tx_lock, flags); |
1689 | priv->tx_outstanding_bytes += count; | 1696 | priv->tx_outstanding_bytes += count; |
1690 | priv->tx_bytes += count; | 1697 | priv->tx_bytes += count; |
1691 | spin_unlock_irqrestore(&priv->tx_lock, flags); | 1698 | spin_unlock_irqrestore(&priv->tx_lock, flags); |
1692 | } | 1699 | } |
1693 | 1700 | ||
1694 | /* we are done with this urb, so let the host driver | 1701 | /* we are done with this urb, so let the host driver |
1695 | * really free it when it is finished with it */ | 1702 | * really free it when it is finished with it */ |
1696 | usb_free_urb(urb); | 1703 | usb_free_urb(urb); |
1697 | 1704 | ||
1698 | dbg("%s write returning: %d", __func__, count); | 1705 | dbg("%s write returning: %d", __func__, count); |
1699 | return count; | 1706 | return count; |
1700 | error: | 1707 | error: |
1701 | usb_free_urb(urb); | 1708 | usb_free_urb(urb); |
1702 | error_no_urb: | 1709 | error_no_urb: |
1703 | kfree(buffer); | 1710 | kfree(buffer); |
1704 | error_no_buffer: | 1711 | error_no_buffer: |
1705 | spin_lock_irqsave(&priv->tx_lock, flags); | 1712 | spin_lock_irqsave(&priv->tx_lock, flags); |
1706 | priv->tx_outstanding_urbs--; | 1713 | priv->tx_outstanding_urbs--; |
1707 | spin_unlock_irqrestore(&priv->tx_lock, flags); | 1714 | spin_unlock_irqrestore(&priv->tx_lock, flags); |
1708 | return count; | 1715 | return count; |
1709 | } /* ftdi_write */ | 1716 | } /* ftdi_write */ |
1710 | 1717 | ||
1711 | 1718 | ||
1712 | /* This function may get called when the device is closed */ | 1719 | /* This function may get called when the device is closed */ |
1713 | 1720 | ||
1714 | static void ftdi_write_bulk_callback(struct urb *urb) | 1721 | static void ftdi_write_bulk_callback(struct urb *urb) |
1715 | { | 1722 | { |
1716 | unsigned long flags; | 1723 | unsigned long flags; |
1717 | struct usb_serial_port *port = urb->context; | 1724 | struct usb_serial_port *port = urb->context; |
1718 | struct ftdi_private *priv; | 1725 | struct ftdi_private *priv; |
1719 | int data_offset; /* will be 1 for the SIO and 0 otherwise */ | 1726 | int data_offset; /* will be 1 for the SIO and 0 otherwise */ |
1720 | unsigned long countback; | 1727 | unsigned long countback; |
1721 | int status = urb->status; | 1728 | int status = urb->status; |
1722 | 1729 | ||
1723 | /* free up the transfer buffer, as usb_free_urb() does not do this */ | 1730 | /* free up the transfer buffer, as usb_free_urb() does not do this */ |
1724 | kfree(urb->transfer_buffer); | 1731 | kfree(urb->transfer_buffer); |
1725 | 1732 | ||
1726 | dbg("%s - port %d", __func__, port->number); | 1733 | dbg("%s - port %d", __func__, port->number); |
1727 | 1734 | ||
1728 | if (status) { | 1735 | if (status) { |
1729 | dbg("nonzero write bulk status received: %d", status); | 1736 | dbg("nonzero write bulk status received: %d", status); |
1730 | return; | 1737 | return; |
1731 | } | 1738 | } |
1732 | 1739 | ||
1733 | priv = usb_get_serial_port_data(port); | 1740 | priv = usb_get_serial_port_data(port); |
1734 | if (!priv) { | 1741 | if (!priv) { |
1735 | dbg("%s - bad port private data pointer - exiting", __func__); | 1742 | dbg("%s - bad port private data pointer - exiting", __func__); |
1736 | return; | 1743 | return; |
1737 | } | 1744 | } |
1738 | /* account for transferred data */ | 1745 | /* account for transferred data */ |
1739 | countback = urb->actual_length; | 1746 | countback = urb->actual_length; |
1740 | data_offset = priv->write_offset; | 1747 | data_offset = priv->write_offset; |
1741 | if (data_offset > 0) { | 1748 | if (data_offset > 0) { |
1742 | /* Subtract the control bytes */ | 1749 | /* Subtract the control bytes */ |
1743 | countback -= (data_offset * DIV_ROUND_UP(countback, PKTSZ)); | 1750 | countback -= (data_offset * DIV_ROUND_UP(countback, PKTSZ)); |
1744 | } | 1751 | } |
1745 | spin_lock_irqsave(&priv->tx_lock, flags); | 1752 | spin_lock_irqsave(&priv->tx_lock, flags); |
1746 | --priv->tx_outstanding_urbs; | 1753 | --priv->tx_outstanding_urbs; |
1747 | priv->tx_outstanding_bytes -= countback; | 1754 | priv->tx_outstanding_bytes -= countback; |
1748 | spin_unlock_irqrestore(&priv->tx_lock, flags); | 1755 | spin_unlock_irqrestore(&priv->tx_lock, flags); |
1749 | 1756 | ||
1750 | usb_serial_port_softint(port); | 1757 | usb_serial_port_softint(port); |
1751 | } /* ftdi_write_bulk_callback */ | 1758 | } /* ftdi_write_bulk_callback */ |
1752 | 1759 | ||
1753 | 1760 | ||
1754 | static int ftdi_write_room(struct tty_struct *tty) | 1761 | static int ftdi_write_room(struct tty_struct *tty) |
1755 | { | 1762 | { |
1756 | struct usb_serial_port *port = tty->driver_data; | 1763 | struct usb_serial_port *port = tty->driver_data; |
1757 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1764 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1758 | int room; | 1765 | int room; |
1759 | unsigned long flags; | 1766 | unsigned long flags; |
1760 | 1767 | ||
1761 | dbg("%s - port %d", __func__, port->number); | 1768 | dbg("%s - port %d", __func__, port->number); |
1762 | 1769 | ||
1763 | spin_lock_irqsave(&priv->tx_lock, flags); | 1770 | spin_lock_irqsave(&priv->tx_lock, flags); |
1764 | if (priv->tx_outstanding_urbs < URB_UPPER_LIMIT) { | 1771 | if (priv->tx_outstanding_urbs < URB_UPPER_LIMIT) { |
1765 | /* | 1772 | /* |
1766 | * We really can take anything the user throws at us | 1773 | * We really can take anything the user throws at us |
1767 | * but let's pick a nice big number to tell the tty | 1774 | * but let's pick a nice big number to tell the tty |
1768 | * layer that we have lots of free space | 1775 | * layer that we have lots of free space |
1769 | */ | 1776 | */ |
1770 | room = 2048; | 1777 | room = 2048; |
1771 | } else { | 1778 | } else { |
1772 | room = 0; | 1779 | room = 0; |
1773 | } | 1780 | } |
1774 | spin_unlock_irqrestore(&priv->tx_lock, flags); | 1781 | spin_unlock_irqrestore(&priv->tx_lock, flags); |
1775 | return room; | 1782 | return room; |
1776 | } | 1783 | } |
1777 | 1784 | ||
1778 | static int ftdi_chars_in_buffer(struct tty_struct *tty) | 1785 | static int ftdi_chars_in_buffer(struct tty_struct *tty) |
1779 | { | 1786 | { |
1780 | struct usb_serial_port *port = tty->driver_data; | 1787 | struct usb_serial_port *port = tty->driver_data; |
1781 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1788 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1782 | int buffered; | 1789 | int buffered; |
1783 | unsigned long flags; | 1790 | unsigned long flags; |
1784 | 1791 | ||
1785 | dbg("%s - port %d", __func__, port->number); | 1792 | dbg("%s - port %d", __func__, port->number); |
1786 | 1793 | ||
1787 | spin_lock_irqsave(&priv->tx_lock, flags); | 1794 | spin_lock_irqsave(&priv->tx_lock, flags); |
1788 | buffered = (int)priv->tx_outstanding_bytes; | 1795 | buffered = (int)priv->tx_outstanding_bytes; |
1789 | spin_unlock_irqrestore(&priv->tx_lock, flags); | 1796 | spin_unlock_irqrestore(&priv->tx_lock, flags); |
1790 | if (buffered < 0) { | 1797 | if (buffered < 0) { |
1791 | dev_err(&port->dev, "%s outstanding tx bytes is negative!\n", | 1798 | dev_err(&port->dev, "%s outstanding tx bytes is negative!\n", |
1792 | __func__); | 1799 | __func__); |
1793 | buffered = 0; | 1800 | buffered = 0; |
1794 | } | 1801 | } |
1795 | return buffered; | 1802 | return buffered; |
1796 | } | 1803 | } |
1797 | 1804 | ||
1798 | static void ftdi_read_bulk_callback(struct urb *urb) | 1805 | static void ftdi_read_bulk_callback(struct urb *urb) |
1799 | { | 1806 | { |
1800 | struct usb_serial_port *port = urb->context; | 1807 | struct usb_serial_port *port = urb->context; |
1801 | struct tty_struct *tty; | 1808 | struct tty_struct *tty; |
1802 | struct ftdi_private *priv; | 1809 | struct ftdi_private *priv; |
1803 | unsigned long countread; | 1810 | unsigned long countread; |
1804 | unsigned long flags; | 1811 | unsigned long flags; |
1805 | int status = urb->status; | 1812 | int status = urb->status; |
1806 | 1813 | ||
1807 | if (urb->number_of_packets > 0) { | 1814 | if (urb->number_of_packets > 0) { |
1808 | dev_err(&port->dev, "%s transfer_buffer_length %d " | 1815 | dev_err(&port->dev, "%s transfer_buffer_length %d " |
1809 | "actual_length %d number of packets %d\n", __func__, | 1816 | "actual_length %d number of packets %d\n", __func__, |
1810 | urb->transfer_buffer_length, | 1817 | urb->transfer_buffer_length, |
1811 | urb->actual_length, urb->number_of_packets); | 1818 | urb->actual_length, urb->number_of_packets); |
1812 | dev_err(&port->dev, "%s transfer_flags %x\n", __func__, | 1819 | dev_err(&port->dev, "%s transfer_flags %x\n", __func__, |
1813 | urb->transfer_flags); | 1820 | urb->transfer_flags); |
1814 | } | 1821 | } |
1815 | 1822 | ||
1816 | dbg("%s - port %d", __func__, port->number); | 1823 | dbg("%s - port %d", __func__, port->number); |
1817 | 1824 | ||
1818 | if (port->port.count <= 0) | 1825 | if (port->port.count <= 0) |
1819 | return; | 1826 | return; |
1820 | 1827 | ||
1821 | tty = tty_port_tty_get(&port->port); | 1828 | tty = tty_port_tty_get(&port->port); |
1822 | if (!tty) { | 1829 | if (!tty) { |
1823 | dbg("%s - bad tty pointer - exiting", __func__); | 1830 | dbg("%s - bad tty pointer - exiting", __func__); |
1824 | return; | 1831 | return; |
1825 | } | 1832 | } |
1826 | 1833 | ||
1827 | priv = usb_get_serial_port_data(port); | 1834 | priv = usb_get_serial_port_data(port); |
1828 | if (!priv) { | 1835 | if (!priv) { |
1829 | dbg("%s - bad port private data pointer - exiting", __func__); | 1836 | dbg("%s - bad port private data pointer - exiting", __func__); |
1830 | goto out; | 1837 | goto out; |
1831 | } | 1838 | } |
1832 | 1839 | ||
1833 | if (urb != port->read_urb) | 1840 | if (urb != port->read_urb) |
1834 | dev_err(&port->dev, "%s - Not my urb!\n", __func__); | 1841 | dev_err(&port->dev, "%s - Not my urb!\n", __func__); |
1835 | 1842 | ||
1836 | if (status) { | 1843 | if (status) { |
1837 | /* This will happen at close every time so it is a dbg not an | 1844 | /* This will happen at close every time so it is a dbg not an |
1838 | err */ | 1845 | err */ |
1839 | dbg("(this is ok on close) nonzero read bulk status received: %d", status); | 1846 | dbg("(this is ok on close) nonzero read bulk status received: %d", status); |
1840 | goto out; | 1847 | goto out; |
1841 | } | 1848 | } |
1842 | 1849 | ||
1843 | /* count data bytes, but not status bytes */ | 1850 | /* count data bytes, but not status bytes */ |
1844 | countread = urb->actual_length; | 1851 | countread = urb->actual_length; |
1845 | countread -= 2 * DIV_ROUND_UP(countread, PKTSZ); | 1852 | countread -= 2 * DIV_ROUND_UP(countread, PKTSZ); |
1846 | spin_lock_irqsave(&priv->rx_lock, flags); | 1853 | spin_lock_irqsave(&priv->rx_lock, flags); |
1847 | priv->rx_bytes += countread; | 1854 | priv->rx_bytes += countread; |
1848 | spin_unlock_irqrestore(&priv->rx_lock, flags); | 1855 | spin_unlock_irqrestore(&priv->rx_lock, flags); |
1849 | 1856 | ||
1850 | ftdi_process_read(&priv->rx_work.work); | 1857 | ftdi_process_read(&priv->rx_work.work); |
1851 | out: | 1858 | out: |
1852 | tty_kref_put(tty); | 1859 | tty_kref_put(tty); |
1853 | } /* ftdi_read_bulk_callback */ | 1860 | } /* ftdi_read_bulk_callback */ |
1854 | 1861 | ||
1855 | 1862 | ||
1856 | static void ftdi_process_read(struct work_struct *work) | 1863 | static void ftdi_process_read(struct work_struct *work) |
1857 | { /* ftdi_process_read */ | 1864 | { /* ftdi_process_read */ |
1858 | struct ftdi_private *priv = | 1865 | struct ftdi_private *priv = |
1859 | container_of(work, struct ftdi_private, rx_work.work); | 1866 | container_of(work, struct ftdi_private, rx_work.work); |
1860 | struct usb_serial_port *port = priv->port; | 1867 | struct usb_serial_port *port = priv->port; |
1861 | struct urb *urb; | 1868 | struct urb *urb; |
1862 | struct tty_struct *tty; | 1869 | struct tty_struct *tty; |
1863 | char error_flag; | 1870 | char error_flag; |
1864 | unsigned char *data; | 1871 | unsigned char *data; |
1865 | 1872 | ||
1866 | int i; | 1873 | int i; |
1867 | int result; | 1874 | int result; |
1868 | int need_flip; | 1875 | int need_flip; |
1869 | int packet_offset; | 1876 | int packet_offset; |
1870 | unsigned long flags; | 1877 | unsigned long flags; |
1871 | 1878 | ||
1872 | dbg("%s - port %d", __func__, port->number); | 1879 | dbg("%s - port %d", __func__, port->number); |
1873 | 1880 | ||
1874 | if (port->port.count <= 0) | 1881 | if (port->port.count <= 0) |
1875 | return; | 1882 | return; |
1876 | 1883 | ||
1877 | tty = tty_port_tty_get(&port->port); | 1884 | tty = tty_port_tty_get(&port->port); |
1878 | if (!tty) { | 1885 | if (!tty) { |
1879 | dbg("%s - bad tty pointer - exiting", __func__); | 1886 | dbg("%s - bad tty pointer - exiting", __func__); |
1880 | return; | 1887 | return; |
1881 | } | 1888 | } |
1882 | 1889 | ||
1883 | priv = usb_get_serial_port_data(port); | 1890 | priv = usb_get_serial_port_data(port); |
1884 | if (!priv) { | 1891 | if (!priv) { |
1885 | dbg("%s - bad port private data pointer - exiting", __func__); | 1892 | dbg("%s - bad port private data pointer - exiting", __func__); |
1886 | goto out; | 1893 | goto out; |
1887 | } | 1894 | } |
1888 | 1895 | ||
1889 | urb = port->read_urb; | 1896 | urb = port->read_urb; |
1890 | if (!urb) { | 1897 | if (!urb) { |
1891 | dbg("%s - bad read_urb pointer - exiting", __func__); | 1898 | dbg("%s - bad read_urb pointer - exiting", __func__); |
1892 | goto out; | 1899 | goto out; |
1893 | } | 1900 | } |
1894 | 1901 | ||
1895 | data = urb->transfer_buffer; | 1902 | data = urb->transfer_buffer; |
1896 | 1903 | ||
1897 | if (priv->rx_processed) { | 1904 | if (priv->rx_processed) { |
1898 | dbg("%s - already processed: %d bytes, %d remain", __func__, | 1905 | dbg("%s - already processed: %d bytes, %d remain", __func__, |
1899 | priv->rx_processed, | 1906 | priv->rx_processed, |
1900 | urb->actual_length - priv->rx_processed); | 1907 | urb->actual_length - priv->rx_processed); |
1901 | } else { | 1908 | } else { |
1902 | /* The first two bytes of every read packet are status */ | 1909 | /* The first two bytes of every read packet are status */ |
1903 | if (urb->actual_length > 2) | 1910 | if (urb->actual_length > 2) |
1904 | usb_serial_debug_data(debug, &port->dev, __func__, | 1911 | usb_serial_debug_data(debug, &port->dev, __func__, |
1905 | urb->actual_length, data); | 1912 | urb->actual_length, data); |
1906 | else | 1913 | else |
1907 | dbg("Status only: %03oo %03oo", data[0], data[1]); | 1914 | dbg("Status only: %03oo %03oo", data[0], data[1]); |
1908 | } | 1915 | } |
1909 | 1916 | ||
1910 | 1917 | ||
1911 | /* TO DO -- check for hung up line and handle appropriately: */ | 1918 | /* TO DO -- check for hung up line and handle appropriately: */ |
1912 | /* send hangup */ | 1919 | /* send hangup */ |
1913 | /* See acm.c - you do a tty_hangup - eg tty_hangup(tty) */ | 1920 | /* See acm.c - you do a tty_hangup - eg tty_hangup(tty) */ |
1914 | /* if CD is dropped and the line is not CLOCAL then we should hangup */ | 1921 | /* if CD is dropped and the line is not CLOCAL then we should hangup */ |
1915 | 1922 | ||
1916 | need_flip = 0; | 1923 | need_flip = 0; |
1917 | for (packet_offset = priv->rx_processed; | 1924 | for (packet_offset = priv->rx_processed; |
1918 | packet_offset < urb->actual_length; packet_offset += PKTSZ) { | 1925 | packet_offset < urb->actual_length; packet_offset += PKTSZ) { |
1919 | int length; | 1926 | int length; |
1920 | 1927 | ||
1921 | /* Compare new line status to the old one, signal if different/ | 1928 | /* Compare new line status to the old one, signal if different/ |
1922 | N.B. packet may be processed more than once, but differences | 1929 | N.B. packet may be processed more than once, but differences |
1923 | are only processed once. */ | 1930 | are only processed once. */ |
1924 | if (priv != NULL) { | 1931 | if (priv != NULL) { |
1925 | char new_status = data[packet_offset + 0] & | 1932 | char new_status = data[packet_offset + 0] & |
1926 | FTDI_STATUS_B0_MASK; | 1933 | FTDI_STATUS_B0_MASK; |
1927 | if (new_status != priv->prev_status) { | 1934 | if (new_status != priv->prev_status) { |
1928 | priv->diff_status |= | 1935 | priv->diff_status |= |
1929 | new_status ^ priv->prev_status; | 1936 | new_status ^ priv->prev_status; |
1930 | wake_up_interruptible(&priv->delta_msr_wait); | 1937 | wake_up_interruptible(&priv->delta_msr_wait); |
1931 | priv->prev_status = new_status; | 1938 | priv->prev_status = new_status; |
1932 | } | 1939 | } |
1933 | } | 1940 | } |
1934 | 1941 | ||
1935 | length = min(PKTSZ, urb->actual_length-packet_offset)-2; | 1942 | length = min(PKTSZ, urb->actual_length-packet_offset)-2; |
1936 | if (length < 0) { | 1943 | if (length < 0) { |
1937 | dev_err(&port->dev, "%s - bad packet length: %d\n", | 1944 | dev_err(&port->dev, "%s - bad packet length: %d\n", |
1938 | __func__, length+2); | 1945 | __func__, length+2); |
1939 | length = 0; | 1946 | length = 0; |
1940 | } | 1947 | } |
1941 | 1948 | ||
1942 | if (priv->rx_flags & THROTTLED) { | 1949 | if (priv->rx_flags & THROTTLED) { |
1943 | dbg("%s - throttled", __func__); | 1950 | dbg("%s - throttled", __func__); |
1944 | break; | 1951 | break; |
1945 | } | 1952 | } |
1946 | if (tty_buffer_request_room(tty, length) < length) { | 1953 | if (tty_buffer_request_room(tty, length) < length) { |
1947 | /* break out & wait for throttling/unthrottling to | 1954 | /* break out & wait for throttling/unthrottling to |
1948 | happen */ | 1955 | happen */ |
1949 | dbg("%s - receive room low", __func__); | 1956 | dbg("%s - receive room low", __func__); |
1950 | break; | 1957 | break; |
1951 | } | 1958 | } |
1952 | 1959 | ||
1953 | /* Handle errors and break */ | 1960 | /* Handle errors and break */ |
1954 | error_flag = TTY_NORMAL; | 1961 | error_flag = TTY_NORMAL; |
1955 | /* Although the device uses a bitmask and hence can have | 1962 | /* Although the device uses a bitmask and hence can have |
1956 | multiple errors on a packet - the order here sets the | 1963 | multiple errors on a packet - the order here sets the |
1957 | priority the error is returned to the tty layer */ | 1964 | priority the error is returned to the tty layer */ |
1958 | 1965 | ||
1959 | if (data[packet_offset+1] & FTDI_RS_OE) { | 1966 | if (data[packet_offset+1] & FTDI_RS_OE) { |
1960 | error_flag = TTY_OVERRUN; | 1967 | error_flag = TTY_OVERRUN; |
1961 | dbg("OVERRRUN error"); | 1968 | dbg("OVERRRUN error"); |
1962 | } | 1969 | } |
1963 | if (data[packet_offset+1] & FTDI_RS_BI) { | 1970 | if (data[packet_offset+1] & FTDI_RS_BI) { |
1964 | error_flag = TTY_BREAK; | 1971 | error_flag = TTY_BREAK; |
1965 | dbg("BREAK received"); | 1972 | dbg("BREAK received"); |
1966 | } | 1973 | } |
1967 | if (data[packet_offset+1] & FTDI_RS_PE) { | 1974 | if (data[packet_offset+1] & FTDI_RS_PE) { |
1968 | error_flag = TTY_PARITY; | 1975 | error_flag = TTY_PARITY; |
1969 | dbg("PARITY error"); | 1976 | dbg("PARITY error"); |
1970 | } | 1977 | } |
1971 | if (data[packet_offset+1] & FTDI_RS_FE) { | 1978 | if (data[packet_offset+1] & FTDI_RS_FE) { |
1972 | error_flag = TTY_FRAME; | 1979 | error_flag = TTY_FRAME; |
1973 | dbg("FRAMING error"); | 1980 | dbg("FRAMING error"); |
1974 | } | 1981 | } |
1975 | if (length > 0) { | 1982 | if (length > 0) { |
1976 | for (i = 2; i < length+2; i++) { | 1983 | for (i = 2; i < length+2; i++) { |
1977 | /* Note that the error flag is duplicated for | 1984 | /* Note that the error flag is duplicated for |
1978 | every character received since we don't know | 1985 | every character received since we don't know |
1979 | which character it applied to */ | 1986 | which character it applied to */ |
1980 | tty_insert_flip_char(tty, | 1987 | tty_insert_flip_char(tty, |
1981 | data[packet_offset + i], error_flag); | 1988 | data[packet_offset + i], error_flag); |
1982 | } | 1989 | } |
1983 | need_flip = 1; | 1990 | need_flip = 1; |
1984 | } | 1991 | } |
1985 | 1992 | ||
1986 | #ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW | 1993 | #ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW |
1987 | /* if a parity error is detected you get status packets forever | 1994 | /* if a parity error is detected you get status packets forever |
1988 | until a character is sent without a parity error. | 1995 | until a character is sent without a parity error. |
1989 | This doesn't work well since the application receives a | 1996 | This doesn't work well since the application receives a |
1990 | never ending stream of bad data - even though new data | 1997 | never ending stream of bad data - even though new data |
1991 | hasn't been sent. Therefore I (bill) have taken this out. | 1998 | hasn't been sent. Therefore I (bill) have taken this out. |
1992 | However - this might make sense for framing errors and so on | 1999 | However - this might make sense for framing errors and so on |
1993 | so I am leaving the code in for now. | 2000 | so I am leaving the code in for now. |
1994 | */ | 2001 | */ |
1995 | else { | 2002 | else { |
1996 | if (error_flag != TTY_NORMAL) { | 2003 | if (error_flag != TTY_NORMAL) { |
1997 | dbg("error_flag is not normal"); | 2004 | dbg("error_flag is not normal"); |
1998 | /* In this case it is just status - if that is | 2005 | /* In this case it is just status - if that is |
1999 | an error send a bad character */ | 2006 | an error send a bad character */ |
2000 | if (tty->flip.count >= TTY_FLIPBUF_SIZE) | 2007 | if (tty->flip.count >= TTY_FLIPBUF_SIZE) |
2001 | tty_flip_buffer_push(tty); | 2008 | tty_flip_buffer_push(tty); |
2002 | tty_insert_flip_char(tty, 0xff, error_flag); | 2009 | tty_insert_flip_char(tty, 0xff, error_flag); |
2003 | need_flip = 1; | 2010 | need_flip = 1; |
2004 | } | 2011 | } |
2005 | } | 2012 | } |
2006 | #endif | 2013 | #endif |
2007 | } /* "for(packet_offset=0..." */ | 2014 | } /* "for(packet_offset=0..." */ |
2008 | 2015 | ||
2009 | /* Low latency */ | 2016 | /* Low latency */ |
2010 | if (need_flip) | 2017 | if (need_flip) |
2011 | tty_flip_buffer_push(tty); | 2018 | tty_flip_buffer_push(tty); |
2012 | 2019 | ||
2013 | if (packet_offset < urb->actual_length) { | 2020 | if (packet_offset < urb->actual_length) { |
2014 | /* not completely processed - record progress */ | 2021 | /* not completely processed - record progress */ |
2015 | priv->rx_processed = packet_offset; | 2022 | priv->rx_processed = packet_offset; |
2016 | dbg("%s - incomplete, %d bytes processed, %d remain", | 2023 | dbg("%s - incomplete, %d bytes processed, %d remain", |
2017 | __func__, packet_offset, | 2024 | __func__, packet_offset, |
2018 | urb->actual_length - packet_offset); | 2025 | urb->actual_length - packet_offset); |
2019 | /* check if we were throttled while processing */ | 2026 | /* check if we were throttled while processing */ |
2020 | spin_lock_irqsave(&priv->rx_lock, flags); | 2027 | spin_lock_irqsave(&priv->rx_lock, flags); |
2021 | if (priv->rx_flags & THROTTLED) { | 2028 | if (priv->rx_flags & THROTTLED) { |
2022 | priv->rx_flags |= ACTUALLY_THROTTLED; | 2029 | priv->rx_flags |= ACTUALLY_THROTTLED; |
2023 | spin_unlock_irqrestore(&priv->rx_lock, flags); | 2030 | spin_unlock_irqrestore(&priv->rx_lock, flags); |
2024 | dbg("%s - deferring remainder until unthrottled", | 2031 | dbg("%s - deferring remainder until unthrottled", |
2025 | __func__); | 2032 | __func__); |
2026 | return; | 2033 | return; |
2027 | } | 2034 | } |
2028 | spin_unlock_irqrestore(&priv->rx_lock, flags); | 2035 | spin_unlock_irqrestore(&priv->rx_lock, flags); |
2029 | /* if the port is closed stop trying to read */ | 2036 | /* if the port is closed stop trying to read */ |
2030 | if (port->port.count > 0) | 2037 | if (port->port.count > 0) |
2031 | /* delay processing of remainder */ | 2038 | /* delay processing of remainder */ |
2032 | schedule_delayed_work(&priv->rx_work, 1); | 2039 | schedule_delayed_work(&priv->rx_work, 1); |
2033 | else | 2040 | else |
2034 | dbg("%s - port is closed", __func__); | 2041 | dbg("%s - port is closed", __func__); |
2035 | goto out; | 2042 | goto out; |
2036 | } | 2043 | } |
2037 | 2044 | ||
2038 | /* urb is completely processed */ | 2045 | /* urb is completely processed */ |
2039 | priv->rx_processed = 0; | 2046 | priv->rx_processed = 0; |
2040 | 2047 | ||
2041 | /* if the port is closed stop trying to read */ | 2048 | /* if the port is closed stop trying to read */ |
2042 | if (port->port.count > 0) { | 2049 | if (port->port.count > 0) { |
2043 | /* Continue trying to always read */ | 2050 | /* Continue trying to always read */ |
2044 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, | 2051 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, |
2045 | usb_rcvbulkpipe(port->serial->dev, | 2052 | usb_rcvbulkpipe(port->serial->dev, |
2046 | port->bulk_in_endpointAddress), | 2053 | port->bulk_in_endpointAddress), |
2047 | port->read_urb->transfer_buffer, | 2054 | port->read_urb->transfer_buffer, |
2048 | port->read_urb->transfer_buffer_length, | 2055 | port->read_urb->transfer_buffer_length, |
2049 | ftdi_read_bulk_callback, port); | 2056 | ftdi_read_bulk_callback, port); |
2050 | 2057 | ||
2051 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | 2058 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); |
2052 | if (result) | 2059 | if (result) |
2053 | dev_err(&port->dev, | 2060 | dev_err(&port->dev, |
2054 | "%s - failed resubmitting read urb, error %d\n", | 2061 | "%s - failed resubmitting read urb, error %d\n", |
2055 | __func__, result); | 2062 | __func__, result); |
2056 | } | 2063 | } |
2057 | out: | 2064 | out: |
2058 | tty_kref_put(tty); | 2065 | tty_kref_put(tty); |
2059 | } /* ftdi_process_read */ | 2066 | } /* ftdi_process_read */ |
2060 | 2067 | ||
2061 | 2068 | ||
2062 | static void ftdi_break_ctl(struct tty_struct *tty, int break_state) | 2069 | static void ftdi_break_ctl(struct tty_struct *tty, int break_state) |
2063 | { | 2070 | { |
2064 | struct usb_serial_port *port = tty->driver_data; | 2071 | struct usb_serial_port *port = tty->driver_data; |
2065 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 2072 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
2066 | __u16 urb_value = 0; | 2073 | __u16 urb_value = 0; |
2067 | char buf[1]; | 2074 | char buf[1]; |
2068 | 2075 | ||
2069 | /* break_state = -1 to turn on break, and 0 to turn off break */ | 2076 | /* break_state = -1 to turn on break, and 0 to turn off break */ |
2070 | /* see drivers/char/tty_io.c to see it used */ | 2077 | /* see drivers/char/tty_io.c to see it used */ |
2071 | /* last_set_data_urb_value NEVER has the break bit set in it */ | 2078 | /* last_set_data_urb_value NEVER has the break bit set in it */ |
2072 | 2079 | ||
2073 | if (break_state) | 2080 | if (break_state) |
2074 | urb_value = priv->last_set_data_urb_value | FTDI_SIO_SET_BREAK; | 2081 | urb_value = priv->last_set_data_urb_value | FTDI_SIO_SET_BREAK; |
2075 | else | 2082 | else |
2076 | urb_value = priv->last_set_data_urb_value; | 2083 | urb_value = priv->last_set_data_urb_value; |
2077 | 2084 | ||
2078 | if (usb_control_msg(port->serial->dev, | 2085 | if (usb_control_msg(port->serial->dev, |
2079 | usb_sndctrlpipe(port->serial->dev, 0), | 2086 | usb_sndctrlpipe(port->serial->dev, 0), |
2080 | FTDI_SIO_SET_DATA_REQUEST, | 2087 | FTDI_SIO_SET_DATA_REQUEST, |
2081 | FTDI_SIO_SET_DATA_REQUEST_TYPE, | 2088 | FTDI_SIO_SET_DATA_REQUEST_TYPE, |
2082 | urb_value , priv->interface, | 2089 | urb_value , priv->interface, |
2083 | buf, 0, WDR_TIMEOUT) < 0) { | 2090 | buf, 0, WDR_TIMEOUT) < 0) { |
2084 | dev_err(&port->dev, "%s FAILED to enable/disable break state " | 2091 | dev_err(&port->dev, "%s FAILED to enable/disable break state " |
2085 | "(state was %d)\n", __func__, break_state); | 2092 | "(state was %d)\n", __func__, break_state); |
2086 | } | 2093 | } |
2087 | 2094 | ||
2088 | dbg("%s break state is %d - urb is %d", __func__, | 2095 | dbg("%s break state is %d - urb is %d", __func__, |
2089 | break_state, urb_value); | 2096 | break_state, urb_value); |
2090 | 2097 | ||
2091 | } | 2098 | } |
2092 | 2099 | ||
2093 | 2100 | ||
2094 | /* old_termios contains the original termios settings and tty->termios contains | 2101 | /* old_termios contains the original termios settings and tty->termios contains |
2095 | * the new setting to be used | 2102 | * the new setting to be used |
2096 | * WARNING: set_termios calls this with old_termios in kernel space | 2103 | * WARNING: set_termios calls this with old_termios in kernel space |
2097 | */ | 2104 | */ |
2098 | 2105 | ||
2099 | static void ftdi_set_termios(struct tty_struct *tty, | 2106 | static void ftdi_set_termios(struct tty_struct *tty, |
2100 | struct usb_serial_port *port, struct ktermios *old_termios) | 2107 | struct usb_serial_port *port, struct ktermios *old_termios) |
2101 | { /* ftdi_termios */ | 2108 | { /* ftdi_termios */ |
2102 | struct usb_device *dev = port->serial->dev; | 2109 | struct usb_device *dev = port->serial->dev; |
2103 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 2110 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
2104 | struct ktermios *termios = tty->termios; | 2111 | struct ktermios *termios = tty->termios; |
2105 | unsigned int cflag = termios->c_cflag; | 2112 | unsigned int cflag = termios->c_cflag; |
2106 | __u16 urb_value; /* will hold the new flags */ | 2113 | __u16 urb_value; /* will hold the new flags */ |
2107 | char buf[1]; /* Perhaps I should dynamically alloc this? */ | 2114 | char buf[1]; /* Perhaps I should dynamically alloc this? */ |
2108 | 2115 | ||
2109 | /* Added for xon/xoff support */ | 2116 | /* Added for xon/xoff support */ |
2110 | unsigned int iflag = termios->c_iflag; | 2117 | unsigned int iflag = termios->c_iflag; |
2111 | unsigned char vstop; | 2118 | unsigned char vstop; |
2112 | unsigned char vstart; | 2119 | unsigned char vstart; |
2113 | 2120 | ||
2114 | dbg("%s", __func__); | 2121 | dbg("%s", __func__); |
2115 | 2122 | ||
2116 | /* Force baud rate if this device requires it, unless it is set to | 2123 | /* Force baud rate if this device requires it, unless it is set to |
2117 | B0. */ | 2124 | B0. */ |
2118 | if (priv->force_baud && ((termios->c_cflag & CBAUD) != B0)) { | 2125 | if (priv->force_baud && ((termios->c_cflag & CBAUD) != B0)) { |
2119 | dbg("%s: forcing baud rate for this device", __func__); | 2126 | dbg("%s: forcing baud rate for this device", __func__); |
2120 | tty_encode_baud_rate(tty, priv->force_baud, | 2127 | tty_encode_baud_rate(tty, priv->force_baud, |
2121 | priv->force_baud); | 2128 | priv->force_baud); |
2122 | } | 2129 | } |
2123 | 2130 | ||
2124 | /* Force RTS-CTS if this device requires it. */ | 2131 | /* Force RTS-CTS if this device requires it. */ |
2125 | if (priv->force_rtscts) { | 2132 | if (priv->force_rtscts) { |
2126 | dbg("%s: forcing rtscts for this device", __func__); | 2133 | dbg("%s: forcing rtscts for this device", __func__); |
2127 | termios->c_cflag |= CRTSCTS; | 2134 | termios->c_cflag |= CRTSCTS; |
2128 | } | 2135 | } |
2129 | 2136 | ||
2130 | cflag = termios->c_cflag; | 2137 | cflag = termios->c_cflag; |
2131 | 2138 | ||
2132 | /* FIXME -For this cut I don't care if the line is really changing or | 2139 | /* FIXME -For this cut I don't care if the line is really changing or |
2133 | not - so just do the change regardless - should be able to | 2140 | not - so just do the change regardless - should be able to |
2134 | compare old_termios and tty->termios */ | 2141 | compare old_termios and tty->termios */ |
2135 | /* NOTE These routines can get interrupted by | 2142 | /* NOTE These routines can get interrupted by |
2136 | ftdi_sio_read_bulk_callback - need to examine what this means - | 2143 | ftdi_sio_read_bulk_callback - need to examine what this means - |
2137 | don't see any problems yet */ | 2144 | don't see any problems yet */ |
2138 | 2145 | ||
2139 | /* Set number of data bits, parity, stop bits */ | 2146 | /* Set number of data bits, parity, stop bits */ |
2140 | 2147 | ||
2141 | termios->c_cflag &= ~CMSPAR; | 2148 | termios->c_cflag &= ~CMSPAR; |
2142 | 2149 | ||
2143 | urb_value = 0; | 2150 | urb_value = 0; |
2144 | urb_value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 : | 2151 | urb_value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 : |
2145 | FTDI_SIO_SET_DATA_STOP_BITS_1); | 2152 | FTDI_SIO_SET_DATA_STOP_BITS_1); |
2146 | urb_value |= (cflag & PARENB ? | 2153 | urb_value |= (cflag & PARENB ? |
2147 | (cflag & PARODD ? FTDI_SIO_SET_DATA_PARITY_ODD : | 2154 | (cflag & PARODD ? FTDI_SIO_SET_DATA_PARITY_ODD : |
2148 | FTDI_SIO_SET_DATA_PARITY_EVEN) : | 2155 | FTDI_SIO_SET_DATA_PARITY_EVEN) : |
2149 | FTDI_SIO_SET_DATA_PARITY_NONE); | 2156 | FTDI_SIO_SET_DATA_PARITY_NONE); |
2150 | if (cflag & CSIZE) { | 2157 | if (cflag & CSIZE) { |
2151 | switch (cflag & CSIZE) { | 2158 | switch (cflag & CSIZE) { |
2152 | case CS5: urb_value |= 5; dbg("Setting CS5"); break; | 2159 | case CS5: urb_value |= 5; dbg("Setting CS5"); break; |
2153 | case CS6: urb_value |= 6; dbg("Setting CS6"); break; | 2160 | case CS6: urb_value |= 6; dbg("Setting CS6"); break; |
2154 | case CS7: urb_value |= 7; dbg("Setting CS7"); break; | 2161 | case CS7: urb_value |= 7; dbg("Setting CS7"); break; |
2155 | case CS8: urb_value |= 8; dbg("Setting CS8"); break; | 2162 | case CS8: urb_value |= 8; dbg("Setting CS8"); break; |
2156 | default: | 2163 | default: |
2157 | dev_err(&port->dev, "CSIZE was set but not CS5-CS8\n"); | 2164 | dev_err(&port->dev, "CSIZE was set but not CS5-CS8\n"); |
2158 | } | 2165 | } |
2159 | } | 2166 | } |
2160 | 2167 | ||
2161 | /* This is needed by the break command since it uses the same command | 2168 | /* This is needed by the break command since it uses the same command |
2162 | - but is or'ed with this value */ | 2169 | - but is or'ed with this value */ |
2163 | priv->last_set_data_urb_value = urb_value; | 2170 | priv->last_set_data_urb_value = urb_value; |
2164 | 2171 | ||
2165 | if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 2172 | if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
2166 | FTDI_SIO_SET_DATA_REQUEST, | 2173 | FTDI_SIO_SET_DATA_REQUEST, |
2167 | FTDI_SIO_SET_DATA_REQUEST_TYPE, | 2174 | FTDI_SIO_SET_DATA_REQUEST_TYPE, |
2168 | urb_value , priv->interface, | 2175 | urb_value , priv->interface, |
2169 | buf, 0, WDR_SHORT_TIMEOUT) < 0) { | 2176 | buf, 0, WDR_SHORT_TIMEOUT) < 0) { |
2170 | dev_err(&port->dev, "%s FAILED to set " | 2177 | dev_err(&port->dev, "%s FAILED to set " |
2171 | "databits/stopbits/parity\n", __func__); | 2178 | "databits/stopbits/parity\n", __func__); |
2172 | } | 2179 | } |
2173 | 2180 | ||
2174 | /* Now do the baudrate */ | 2181 | /* Now do the baudrate */ |
2175 | if ((cflag & CBAUD) == B0) { | 2182 | if ((cflag & CBAUD) == B0) { |
2176 | /* Disable flow control */ | 2183 | /* Disable flow control */ |
2177 | if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 2184 | if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
2178 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, | 2185 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, |
2179 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, | 2186 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, |
2180 | 0, priv->interface, | 2187 | 0, priv->interface, |
2181 | buf, 0, WDR_TIMEOUT) < 0) { | 2188 | buf, 0, WDR_TIMEOUT) < 0) { |
2182 | dev_err(&port->dev, | 2189 | dev_err(&port->dev, |
2183 | "%s error from disable flowcontrol urb\n", | 2190 | "%s error from disable flowcontrol urb\n", |
2184 | __func__); | 2191 | __func__); |
2185 | } | 2192 | } |
2186 | /* Drop RTS and DTR */ | 2193 | /* Drop RTS and DTR */ |
2187 | clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | 2194 | clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); |
2188 | } else { | 2195 | } else { |
2189 | /* set the baudrate determined before */ | 2196 | /* set the baudrate determined before */ |
2190 | if (change_speed(tty, port)) | 2197 | if (change_speed(tty, port)) |
2191 | dev_err(&port->dev, "%s urb failed to set baudrate\n", | 2198 | dev_err(&port->dev, "%s urb failed to set baudrate\n", |
2192 | __func__); | 2199 | __func__); |
2193 | /* Ensure RTS and DTR are raised when baudrate changed from 0 */ | 2200 | /* Ensure RTS and DTR are raised when baudrate changed from 0 */ |
2194 | if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) | 2201 | if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) |
2195 | set_mctrl(port, TIOCM_DTR | TIOCM_RTS); | 2202 | set_mctrl(port, TIOCM_DTR | TIOCM_RTS); |
2196 | } | 2203 | } |
2197 | 2204 | ||
2198 | /* Set flow control */ | 2205 | /* Set flow control */ |
2199 | /* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */ | 2206 | /* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */ |
2200 | if (cflag & CRTSCTS) { | 2207 | if (cflag & CRTSCTS) { |
2201 | dbg("%s Setting to CRTSCTS flow control", __func__); | 2208 | dbg("%s Setting to CRTSCTS flow control", __func__); |
2202 | if (usb_control_msg(dev, | 2209 | if (usb_control_msg(dev, |
2203 | usb_sndctrlpipe(dev, 0), | 2210 | usb_sndctrlpipe(dev, 0), |
2204 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, | 2211 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, |
2205 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, | 2212 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, |
2206 | 0 , (FTDI_SIO_RTS_CTS_HS | priv->interface), | 2213 | 0 , (FTDI_SIO_RTS_CTS_HS | priv->interface), |
2207 | buf, 0, WDR_TIMEOUT) < 0) { | 2214 | buf, 0, WDR_TIMEOUT) < 0) { |
2208 | dev_err(&port->dev, | 2215 | dev_err(&port->dev, |
2209 | "urb failed to set to rts/cts flow control\n"); | 2216 | "urb failed to set to rts/cts flow control\n"); |
2210 | } | 2217 | } |
2211 | 2218 | ||
2212 | } else { | 2219 | } else { |
2213 | /* | 2220 | /* |
2214 | * Xon/Xoff code | 2221 | * Xon/Xoff code |
2215 | * | 2222 | * |
2216 | * Check the IXOFF status in the iflag component of the | 2223 | * Check the IXOFF status in the iflag component of the |
2217 | * termios structure. If IXOFF is not set, the pre-xon/xoff | 2224 | * termios structure. If IXOFF is not set, the pre-xon/xoff |
2218 | * code is executed. | 2225 | * code is executed. |
2219 | */ | 2226 | */ |
2220 | if (iflag & IXOFF) { | 2227 | if (iflag & IXOFF) { |
2221 | dbg("%s request to enable xonxoff iflag=%04x", | 2228 | dbg("%s request to enable xonxoff iflag=%04x", |
2222 | __func__, iflag); | 2229 | __func__, iflag); |
2223 | /* Try to enable the XON/XOFF on the ftdi_sio | 2230 | /* Try to enable the XON/XOFF on the ftdi_sio |
2224 | * Set the vstart and vstop -- could have been done up | 2231 | * Set the vstart and vstop -- could have been done up |
2225 | * above where a lot of other dereferencing is done but | 2232 | * above where a lot of other dereferencing is done but |
2226 | * that would be very inefficient as vstart and vstop | 2233 | * that would be very inefficient as vstart and vstop |
2227 | * are not always needed. | 2234 | * are not always needed. |
2228 | */ | 2235 | */ |
2229 | vstart = termios->c_cc[VSTART]; | 2236 | vstart = termios->c_cc[VSTART]; |
2230 | vstop = termios->c_cc[VSTOP]; | 2237 | vstop = termios->c_cc[VSTOP]; |
2231 | urb_value = (vstop << 8) | (vstart); | 2238 | urb_value = (vstop << 8) | (vstart); |
2232 | 2239 | ||
2233 | if (usb_control_msg(dev, | 2240 | if (usb_control_msg(dev, |
2234 | usb_sndctrlpipe(dev, 0), | 2241 | usb_sndctrlpipe(dev, 0), |
2235 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, | 2242 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, |
2236 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, | 2243 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, |
2237 | urb_value , (FTDI_SIO_XON_XOFF_HS | 2244 | urb_value , (FTDI_SIO_XON_XOFF_HS |
2238 | | priv->interface), | 2245 | | priv->interface), |
2239 | buf, 0, WDR_TIMEOUT) < 0) { | 2246 | buf, 0, WDR_TIMEOUT) < 0) { |
2240 | dev_err(&port->dev, "urb failed to set to " | 2247 | dev_err(&port->dev, "urb failed to set to " |
2241 | "xon/xoff flow control\n"); | 2248 | "xon/xoff flow control\n"); |
2242 | } | 2249 | } |
2243 | } else { | 2250 | } else { |
2244 | /* else clause to only run if cflag ! CRTSCTS and iflag | 2251 | /* else clause to only run if cflag ! CRTSCTS and iflag |
2245 | * ! XOFF. CHECKME Assuming XON/XOFF handled by tty | 2252 | * ! XOFF. CHECKME Assuming XON/XOFF handled by tty |
2246 | * stack - not by device */ | 2253 | * stack - not by device */ |
2247 | dbg("%s Turning off hardware flow control", __func__); | 2254 | dbg("%s Turning off hardware flow control", __func__); |
2248 | if (usb_control_msg(dev, | 2255 | if (usb_control_msg(dev, |
2249 | usb_sndctrlpipe(dev, 0), | 2256 | usb_sndctrlpipe(dev, 0), |
2250 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, | 2257 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, |
2251 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, | 2258 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, |
2252 | 0, priv->interface, | 2259 | 0, priv->interface, |
2253 | buf, 0, WDR_TIMEOUT) < 0) { | 2260 | buf, 0, WDR_TIMEOUT) < 0) { |
2254 | dev_err(&port->dev, | 2261 | dev_err(&port->dev, |
2255 | "urb failed to clear flow control\n"); | 2262 | "urb failed to clear flow control\n"); |
2256 | } | 2263 | } |
2257 | } | 2264 | } |
2258 | 2265 | ||
2259 | } | 2266 | } |
2260 | return; | 2267 | return; |
2261 | } | 2268 | } |
2262 | 2269 | ||
2263 | static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) | 2270 | static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) |
2264 | { | 2271 | { |
2265 | struct usb_serial_port *port = tty->driver_data; | 2272 | struct usb_serial_port *port = tty->driver_data; |
2266 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 2273 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
2267 | unsigned char buf[2]; | 2274 | unsigned char buf[2]; |
2268 | int ret; | 2275 | int ret; |
2269 | 2276 | ||
2270 | dbg("%s TIOCMGET", __func__); | 2277 | dbg("%s TIOCMGET", __func__); |
2271 | switch (priv->chip_type) { | 2278 | switch (priv->chip_type) { |
2272 | case SIO: | 2279 | case SIO: |
2273 | /* Request the status from the device */ | 2280 | /* Request the status from the device */ |
2274 | ret = usb_control_msg(port->serial->dev, | 2281 | ret = usb_control_msg(port->serial->dev, |
2275 | usb_rcvctrlpipe(port->serial->dev, 0), | 2282 | usb_rcvctrlpipe(port->serial->dev, 0), |
2276 | FTDI_SIO_GET_MODEM_STATUS_REQUEST, | 2283 | FTDI_SIO_GET_MODEM_STATUS_REQUEST, |
2277 | FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, | 2284 | FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, |
2278 | 0, 0, | 2285 | 0, 0, |
2279 | buf, 1, WDR_TIMEOUT); | 2286 | buf, 1, WDR_TIMEOUT); |
2280 | if (ret < 0) { | 2287 | if (ret < 0) { |
2281 | dbg("%s Could not get modem status of device - err: %d", __func__, | 2288 | dbg("%s Could not get modem status of device - err: %d", __func__, |
2282 | ret); | 2289 | ret); |
2283 | return ret; | 2290 | return ret; |
2284 | } | 2291 | } |
2285 | break; | 2292 | break; |
2286 | case FT8U232AM: | 2293 | case FT8U232AM: |
2287 | case FT232BM: | 2294 | case FT232BM: |
2288 | case FT2232C: | 2295 | case FT2232C: |
2289 | case FT232RL: | 2296 | case FT232RL: |
2290 | /* the 8U232AM returns a two byte value (the sio is a 1 byte | 2297 | /* the 8U232AM returns a two byte value (the sio is a 1 byte |
2291 | value) - in the same format as the data returned from the in | 2298 | value) - in the same format as the data returned from the in |
2292 | point */ | 2299 | point */ |
2293 | ret = usb_control_msg(port->serial->dev, | 2300 | ret = usb_control_msg(port->serial->dev, |
2294 | usb_rcvctrlpipe(port->serial->dev, 0), | 2301 | usb_rcvctrlpipe(port->serial->dev, 0), |
2295 | FTDI_SIO_GET_MODEM_STATUS_REQUEST, | 2302 | FTDI_SIO_GET_MODEM_STATUS_REQUEST, |
2296 | FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, | 2303 | FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, |
2297 | 0, priv->interface, | 2304 | 0, priv->interface, |
2298 | buf, 2, WDR_TIMEOUT); | 2305 | buf, 2, WDR_TIMEOUT); |
2299 | if (ret < 0) { | 2306 | if (ret < 0) { |
2300 | dbg("%s Could not get modem status of device - err: %d", __func__, | 2307 | dbg("%s Could not get modem status of device - err: %d", __func__, |
2301 | ret); | 2308 | ret); |
2302 | return ret; | 2309 | return ret; |
2303 | } | 2310 | } |
2304 | break; | 2311 | break; |
2305 | default: | 2312 | default: |
2306 | return -EFAULT; | 2313 | return -EFAULT; |
2307 | break; | 2314 | break; |
2308 | } | 2315 | } |
2309 | 2316 | ||
2310 | return (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | | 2317 | return (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | |
2311 | (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) | | 2318 | (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) | |
2312 | (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) | | 2319 | (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) | |
2313 | (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) | | 2320 | (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) | |
2314 | priv->last_dtr_rts; | 2321 | priv->last_dtr_rts; |
2315 | } | 2322 | } |
2316 | 2323 | ||
2317 | static int ftdi_tiocmset(struct tty_struct *tty, struct file *file, | 2324 | static int ftdi_tiocmset(struct tty_struct *tty, struct file *file, |
2318 | unsigned int set, unsigned int clear) | 2325 | unsigned int set, unsigned int clear) |
2319 | { | 2326 | { |
2320 | struct usb_serial_port *port = tty->driver_data; | 2327 | struct usb_serial_port *port = tty->driver_data; |
2321 | dbg("%s TIOCMSET", __func__); | 2328 | dbg("%s TIOCMSET", __func__); |
2322 | return update_mctrl(port, set, clear); | 2329 | return update_mctrl(port, set, clear); |
2323 | } | 2330 | } |
2324 | 2331 | ||
2325 | 2332 | ||
2326 | static int ftdi_ioctl(struct tty_struct *tty, struct file *file, | 2333 | static int ftdi_ioctl(struct tty_struct *tty, struct file *file, |
2327 | unsigned int cmd, unsigned long arg) | 2334 | unsigned int cmd, unsigned long arg) |
2328 | { | 2335 | { |
2329 | struct usb_serial_port *port = tty->driver_data; | 2336 | struct usb_serial_port *port = tty->driver_data; |
2330 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 2337 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
2331 | 2338 | ||
2332 | dbg("%s cmd 0x%04x", __func__, cmd); | 2339 | dbg("%s cmd 0x%04x", __func__, cmd); |
2333 | 2340 | ||
2334 | /* Based on code from acm.c and others */ | 2341 | /* Based on code from acm.c and others */ |
2335 | switch (cmd) { | 2342 | switch (cmd) { |
2336 | 2343 | ||
2337 | case TIOCGSERIAL: /* gets serial port data */ | 2344 | case TIOCGSERIAL: /* gets serial port data */ |
2338 | return get_serial_info(port, | 2345 | return get_serial_info(port, |
2339 | (struct serial_struct __user *) arg); | 2346 | (struct serial_struct __user *) arg); |
2340 | 2347 | ||
2341 | case TIOCSSERIAL: /* sets serial port data */ | 2348 | case TIOCSSERIAL: /* sets serial port data */ |
2342 | return set_serial_info(tty, port, | 2349 | return set_serial_info(tty, port, |
2343 | (struct serial_struct __user *) arg); | 2350 | (struct serial_struct __user *) arg); |
2344 | 2351 | ||
2345 | /* | 2352 | /* |
2346 | * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change | 2353 | * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change |
2347 | * - mask passed in arg for lines of interest | 2354 | * - mask passed in arg for lines of interest |
2348 | * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) | 2355 | * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) |
2349 | * Caller should use TIOCGICOUNT to see which one it was. | 2356 | * Caller should use TIOCGICOUNT to see which one it was. |
2350 | * | 2357 | * |
2351 | * This code is borrowed from linux/drivers/char/serial.c | 2358 | * This code is borrowed from linux/drivers/char/serial.c |
2352 | */ | 2359 | */ |
2353 | case TIOCMIWAIT: | 2360 | case TIOCMIWAIT: |
2354 | while (priv != NULL) { | 2361 | while (priv != NULL) { |
2355 | interruptible_sleep_on(&priv->delta_msr_wait); | 2362 | interruptible_sleep_on(&priv->delta_msr_wait); |
2356 | /* see if a signal did it */ | 2363 | /* see if a signal did it */ |
2357 | if (signal_pending(current)) | 2364 | if (signal_pending(current)) |
2358 | return -ERESTARTSYS; | 2365 | return -ERESTARTSYS; |
2359 | else { | 2366 | else { |
2360 | char diff = priv->diff_status; | 2367 | char diff = priv->diff_status; |
2361 | 2368 | ||
2362 | if (diff == 0) | 2369 | if (diff == 0) |
2363 | return -EIO; /* no change => error */ | 2370 | return -EIO; /* no change => error */ |
2364 | 2371 | ||
2365 | /* Consume all events */ | 2372 | /* Consume all events */ |
2366 | priv->diff_status = 0; | 2373 | priv->diff_status = 0; |
2367 | 2374 | ||
2368 | /* Return 0 if caller wanted to know about | 2375 | /* Return 0 if caller wanted to know about |
2369 | these bits */ | 2376 | these bits */ |
2370 | if (((arg & TIOCM_RNG) && (diff & FTDI_RS0_RI)) || | 2377 | if (((arg & TIOCM_RNG) && (diff & FTDI_RS0_RI)) || |
2371 | ((arg & TIOCM_DSR) && (diff & FTDI_RS0_DSR)) || | 2378 | ((arg & TIOCM_DSR) && (diff & FTDI_RS0_DSR)) || |
2372 | ((arg & TIOCM_CD) && (diff & FTDI_RS0_RLSD)) || | 2379 | ((arg & TIOCM_CD) && (diff & FTDI_RS0_RLSD)) || |
2373 | ((arg & TIOCM_CTS) && (diff & FTDI_RS0_CTS))) { | 2380 | ((arg & TIOCM_CTS) && (diff & FTDI_RS0_CTS))) { |
2374 | return 0; | 2381 | return 0; |
2375 | } | 2382 | } |
2376 | /* | 2383 | /* |
2377 | * Otherwise caller can't care less about what | 2384 | * Otherwise caller can't care less about what |
2378 | * happened,and so we continue to wait for more | 2385 | * happened,and so we continue to wait for more |
2379 | * events. | 2386 | * events. |
2380 | */ | 2387 | */ |
2381 | } | 2388 | } |
2382 | } | 2389 | } |
2383 | return 0; | 2390 | return 0; |
2384 | default: | 2391 | default: |
2385 | break; | 2392 | break; |
2386 | } | 2393 | } |
2387 | /* This is not necessarily an error - turns out the higher layers | 2394 | /* This is not necessarily an error - turns out the higher layers |
2388 | * will do some ioctls themselves (see comment above) | 2395 | * will do some ioctls themselves (see comment above) |
2389 | */ | 2396 | */ |
2390 | dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __func__, cmd); | 2397 | dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __func__, cmd); |
2391 | return -ENOIOCTLCMD; | 2398 | return -ENOIOCTLCMD; |
2392 | } | 2399 | } |
2393 | 2400 | ||
2394 | static void ftdi_throttle(struct tty_struct *tty) | 2401 | static void ftdi_throttle(struct tty_struct *tty) |
2395 | { | 2402 | { |
2396 | struct usb_serial_port *port = tty->driver_data; | 2403 | struct usb_serial_port *port = tty->driver_data; |
2397 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 2404 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
2398 | unsigned long flags; | 2405 | unsigned long flags; |
2399 | 2406 | ||
2400 | dbg("%s - port %d", __func__, port->number); | 2407 | dbg("%s - port %d", __func__, port->number); |
2401 | 2408 | ||
2402 | spin_lock_irqsave(&priv->rx_lock, flags); | 2409 | spin_lock_irqsave(&priv->rx_lock, flags); |
2403 | priv->rx_flags |= THROTTLED; | 2410 | priv->rx_flags |= THROTTLED; |
2404 | spin_unlock_irqrestore(&priv->rx_lock, flags); | 2411 | spin_unlock_irqrestore(&priv->rx_lock, flags); |
2405 | } | 2412 | } |
2406 | 2413 | ||
2407 | 2414 | ||
2408 | static void ftdi_unthrottle(struct tty_struct *tty) | 2415 | static void ftdi_unthrottle(struct tty_struct *tty) |
2409 | { | 2416 | { |
2410 | struct usb_serial_port *port = tty->driver_data; | 2417 | struct usb_serial_port *port = tty->driver_data; |
2411 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 2418 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
2412 | int actually_throttled; | 2419 | int actually_throttled; |
2413 | unsigned long flags; | 2420 | unsigned long flags; |
2414 | 2421 | ||
2415 | dbg("%s - port %d", __func__, port->number); | 2422 | dbg("%s - port %d", __func__, port->number); |
2416 | 2423 | ||
2417 | spin_lock_irqsave(&priv->rx_lock, flags); | 2424 | spin_lock_irqsave(&priv->rx_lock, flags); |
2418 | actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED; | 2425 | actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED; |
2419 | priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); | 2426 | priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); |
2420 | spin_unlock_irqrestore(&priv->rx_lock, flags); | 2427 | spin_unlock_irqrestore(&priv->rx_lock, flags); |
2421 | 2428 | ||
2422 | if (actually_throttled) | 2429 | if (actually_throttled) |
2423 | schedule_delayed_work(&priv->rx_work, 0); | 2430 | schedule_delayed_work(&priv->rx_work, 0); |
2424 | } | 2431 | } |
2425 | 2432 | ||
2426 | static int __init ftdi_init(void) | 2433 | static int __init ftdi_init(void) |
2427 | { | 2434 | { |
2428 | int retval; | 2435 | int retval; |
2429 | 2436 | ||
2430 | dbg("%s", __func__); | 2437 | dbg("%s", __func__); |
2431 | if (vendor > 0 && product > 0) { | 2438 | if (vendor > 0 && product > 0) { |
2432 | /* Add user specified VID/PID to reserved element of table. */ | 2439 | /* Add user specified VID/PID to reserved element of table. */ |
2433 | int i; | 2440 | int i; |
2434 | for (i = 0; id_table_combined[i].idVendor; i++) | 2441 | for (i = 0; id_table_combined[i].idVendor; i++) |
2435 | ; | 2442 | ; |
2436 | id_table_combined[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE; | 2443 | id_table_combined[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE; |
2437 | id_table_combined[i].idVendor = vendor; | 2444 | id_table_combined[i].idVendor = vendor; |
2438 | id_table_combined[i].idProduct = product; | 2445 | id_table_combined[i].idProduct = product; |
2439 | } | 2446 | } |
2440 | retval = usb_serial_register(&ftdi_sio_device); | 2447 | retval = usb_serial_register(&ftdi_sio_device); |
2441 | if (retval) | 2448 | if (retval) |
2442 | goto failed_sio_register; | 2449 | goto failed_sio_register; |
2443 | retval = usb_register(&ftdi_driver); | 2450 | retval = usb_register(&ftdi_driver); |
2444 | if (retval) | 2451 | if (retval) |
2445 | goto failed_usb_register; | 2452 | goto failed_usb_register; |
2446 | 2453 | ||
2447 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | 2454 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" |
2448 | DRIVER_DESC "\n"); | 2455 | DRIVER_DESC "\n"); |
2449 | return 0; | 2456 | return 0; |
2450 | failed_usb_register: | 2457 | failed_usb_register: |
2451 | usb_serial_deregister(&ftdi_sio_device); | 2458 | usb_serial_deregister(&ftdi_sio_device); |
2452 | failed_sio_register: | 2459 | failed_sio_register: |
2453 | return retval; | 2460 | return retval; |
2454 | } | 2461 | } |
2455 | 2462 | ||
2456 | 2463 | ||
2457 | static void __exit ftdi_exit(void) | 2464 | static void __exit ftdi_exit(void) |
2458 | { | 2465 | { |
2459 | 2466 | ||
2460 | dbg("%s", __func__); | 2467 | dbg("%s", __func__); |
2461 | 2468 | ||
2462 | usb_deregister(&ftdi_driver); | 2469 | usb_deregister(&ftdi_driver); |
2463 | usb_serial_deregister(&ftdi_sio_device); | 2470 | usb_serial_deregister(&ftdi_sio_device); |
2464 | 2471 | ||
2465 | } | 2472 | } |
2466 | 2473 | ||
2467 | 2474 | ||
2468 | module_init(ftdi_init); | 2475 | module_init(ftdi_init); |
2469 | module_exit(ftdi_exit); | 2476 | module_exit(ftdi_exit); |
2470 | 2477 | ||
2471 | MODULE_AUTHOR(DRIVER_AUTHOR); | 2478 | MODULE_AUTHOR(DRIVER_AUTHOR); |
2472 | MODULE_DESCRIPTION(DRIVER_DESC); | 2479 | MODULE_DESCRIPTION(DRIVER_DESC); |
2473 | MODULE_LICENSE("GPL"); | 2480 | MODULE_LICENSE("GPL"); |
2474 | 2481 | ||
2475 | module_param(debug, bool, S_IRUGO | S_IWUSR); | 2482 | module_param(debug, bool, S_IRUGO | S_IWUSR); |
2476 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | 2483 | MODULE_PARM_DESC(debug, "Debug enabled or not"); |
2477 | module_param(vendor, ushort, 0); | 2484 | module_param(vendor, ushort, 0); |
2478 | MODULE_PARM_DESC(vendor, "User specified vendor ID (default=" | 2485 | MODULE_PARM_DESC(vendor, "User specified vendor ID (default=" |
2479 | __MODULE_STRING(FTDI_VID)")"); | 2486 | __MODULE_STRING(FTDI_VID)")"); |
2480 | module_param(product, ushort, 0); | 2487 | module_param(product, ushort, 0); |
2481 | MODULE_PARM_DESC(product, "User specified product ID"); | 2488 | MODULE_PARM_DESC(product, "User specified product ID"); |
2482 | 2489 | ||
2483 | 2490 |
drivers/usb/serial/kl5kusb105.c
1 | /* | 1 | /* |
2 | * KLSI KL5KUSB105 chip RS232 converter driver | 2 | * KLSI KL5KUSB105 chip RS232 converter driver |
3 | * | 3 | * |
4 | * Copyright (C) 2001 Utz-Uwe Haus <haus@uuhaus.de> | 4 | * Copyright (C) 2001 Utz-Uwe Haus <haus@uuhaus.de> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation; either version 2 of the License, or | 8 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. | 9 | * (at your option) any later version. |
10 | * | 10 | * |
11 | * All information about the device was acquired using SniffUSB ans snoopUSB | 11 | * All information about the device was acquired using SniffUSB ans snoopUSB |
12 | * on Windows98. | 12 | * on Windows98. |
13 | * It was written out of frustration with the PalmConnect USB Serial adapter | 13 | * It was written out of frustration with the PalmConnect USB Serial adapter |
14 | * sold by Palm Inc. | 14 | * sold by Palm Inc. |
15 | * Neither Palm, nor their contractor (MCCI) or their supplier (KLSI) provided | 15 | * Neither Palm, nor their contractor (MCCI) or their supplier (KLSI) provided |
16 | * information that was not already available. | 16 | * information that was not already available. |
17 | * | 17 | * |
18 | * It seems that KLSI bought some silicon-design information from ScanLogic, | 18 | * It seems that KLSI bought some silicon-design information from ScanLogic, |
19 | * whose SL11R processor is at the core of the KL5KUSB chipset from KLSI. | 19 | * whose SL11R processor is at the core of the KL5KUSB chipset from KLSI. |
20 | * KLSI has firmware available for their devices; it is probable that the | 20 | * KLSI has firmware available for their devices; it is probable that the |
21 | * firmware differs from that used by KLSI in their products. If you have an | 21 | * firmware differs from that used by KLSI in their products. If you have an |
22 | * original KLSI device and can provide some information on it, I would be | 22 | * original KLSI device and can provide some information on it, I would be |
23 | * most interested in adding support for it here. If you have any information | 23 | * most interested in adding support for it here. If you have any information |
24 | * on the protocol used (or find errors in my reverse-engineered stuff), please | 24 | * on the protocol used (or find errors in my reverse-engineered stuff), please |
25 | * let me know. | 25 | * let me know. |
26 | * | 26 | * |
27 | * The code was only tested with a PalmConnect USB adapter; if you | 27 | * The code was only tested with a PalmConnect USB adapter; if you |
28 | * are adventurous, try it with any KLSI-based device and let me know how it | 28 | * are adventurous, try it with any KLSI-based device and let me know how it |
29 | * breaks so that I can fix it! | 29 | * breaks so that I can fix it! |
30 | */ | 30 | */ |
31 | 31 | ||
32 | /* TODO: | 32 | /* TODO: |
33 | * check modem line signals | 33 | * check modem line signals |
34 | * implement handshaking or decide that we do not support it | 34 | * implement handshaking or decide that we do not support it |
35 | */ | 35 | */ |
36 | 36 | ||
37 | /* History: | 37 | /* History: |
38 | * 0.3a - implemented pools of write URBs | 38 | * 0.3a - implemented pools of write URBs |
39 | * 0.3 - alpha version for public testing | 39 | * 0.3 - alpha version for public testing |
40 | * 0.2 - TIOCMGET works, so autopilot(1) can be used! | 40 | * 0.2 - TIOCMGET works, so autopilot(1) can be used! |
41 | * 0.1 - can be used to to pilot-xfer -p /dev/ttyUSB0 -l | 41 | * 0.1 - can be used to to pilot-xfer -p /dev/ttyUSB0 -l |
42 | * | 42 | * |
43 | * The driver skeleton is mainly based on mct_u232.c and various other | 43 | * The driver skeleton is mainly based on mct_u232.c and various other |
44 | * pieces of code shamelessly copied from the drivers/usb/serial/ directory. | 44 | * pieces of code shamelessly copied from the drivers/usb/serial/ directory. |
45 | */ | 45 | */ |
46 | 46 | ||
47 | 47 | ||
48 | #include <linux/kernel.h> | 48 | #include <linux/kernel.h> |
49 | #include <linux/errno.h> | 49 | #include <linux/errno.h> |
50 | #include <linux/init.h> | 50 | #include <linux/init.h> |
51 | #include <linux/slab.h> | 51 | #include <linux/slab.h> |
52 | #include <linux/tty.h> | 52 | #include <linux/tty.h> |
53 | #include <linux/tty_driver.h> | 53 | #include <linux/tty_driver.h> |
54 | #include <linux/tty_flip.h> | 54 | #include <linux/tty_flip.h> |
55 | #include <linux/module.h> | 55 | #include <linux/module.h> |
56 | #include <linux/uaccess.h> | 56 | #include <linux/uaccess.h> |
57 | #include <asm/unaligned.h> | 57 | #include <asm/unaligned.h> |
58 | #include <linux/usb.h> | 58 | #include <linux/usb.h> |
59 | #include <linux/usb/serial.h> | 59 | #include <linux/usb/serial.h> |
60 | #include "kl5kusb105.h" | 60 | #include "kl5kusb105.h" |
61 | 61 | ||
62 | static int debug; | 62 | static int debug; |
63 | 63 | ||
64 | /* | 64 | /* |
65 | * Version Information | 65 | * Version Information |
66 | */ | 66 | */ |
67 | #define DRIVER_VERSION "v0.3a" | 67 | #define DRIVER_VERSION "v0.3a" |
68 | #define DRIVER_AUTHOR "Utz-Uwe Haus <haus@uuhaus.de>" | 68 | #define DRIVER_AUTHOR "Utz-Uwe Haus <haus@uuhaus.de>" |
69 | #define DRIVER_DESC "KLSI KL5KUSB105 chipset USB->Serial Converter driver" | 69 | #define DRIVER_DESC "KLSI KL5KUSB105 chipset USB->Serial Converter driver" |
70 | 70 | ||
71 | 71 | ||
72 | /* | 72 | /* |
73 | * Function prototypes | 73 | * Function prototypes |
74 | */ | 74 | */ |
75 | static int klsi_105_startup(struct usb_serial *serial); | 75 | static int klsi_105_startup(struct usb_serial *serial); |
76 | static void klsi_105_shutdown(struct usb_serial *serial); | 76 | static void klsi_105_shutdown(struct usb_serial *serial); |
77 | static int klsi_105_open(struct tty_struct *tty, | 77 | static int klsi_105_open(struct tty_struct *tty, |
78 | struct usb_serial_port *port, struct file *filp); | 78 | struct usb_serial_port *port, struct file *filp); |
79 | static void klsi_105_close(struct tty_struct *tty, | 79 | static void klsi_105_close(struct tty_struct *tty, |
80 | struct usb_serial_port *port, struct file *filp); | 80 | struct usb_serial_port *port, struct file *filp); |
81 | static int klsi_105_write(struct tty_struct *tty, | 81 | static int klsi_105_write(struct tty_struct *tty, |
82 | struct usb_serial_port *port, const unsigned char *buf, int count); | 82 | struct usb_serial_port *port, const unsigned char *buf, int count); |
83 | static void klsi_105_write_bulk_callback(struct urb *urb); | 83 | static void klsi_105_write_bulk_callback(struct urb *urb); |
84 | static int klsi_105_chars_in_buffer(struct tty_struct *tty); | 84 | static int klsi_105_chars_in_buffer(struct tty_struct *tty); |
85 | static int klsi_105_write_room(struct tty_struct *tty); | 85 | static int klsi_105_write_room(struct tty_struct *tty); |
86 | static void klsi_105_read_bulk_callback(struct urb *urb); | 86 | static void klsi_105_read_bulk_callback(struct urb *urb); |
87 | static void klsi_105_set_termios(struct tty_struct *tty, | 87 | static void klsi_105_set_termios(struct tty_struct *tty, |
88 | struct usb_serial_port *port, struct ktermios *old); | 88 | struct usb_serial_port *port, struct ktermios *old); |
89 | static void klsi_105_throttle(struct tty_struct *tty); | 89 | static void klsi_105_throttle(struct tty_struct *tty); |
90 | static void klsi_105_unthrottle(struct tty_struct *tty); | 90 | static void klsi_105_unthrottle(struct tty_struct *tty); |
91 | static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file); | 91 | static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file); |
92 | static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file, | 92 | static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file, |
93 | unsigned int set, unsigned int clear); | 93 | unsigned int set, unsigned int clear); |
94 | 94 | ||
95 | /* | 95 | /* |
96 | * All of the device info needed for the KLSI converters. | 96 | * All of the device info needed for the KLSI converters. |
97 | */ | 97 | */ |
98 | static struct usb_device_id id_table [] = { | 98 | static struct usb_device_id id_table [] = { |
99 | { USB_DEVICE(PALMCONNECT_VID, PALMCONNECT_PID) }, | 99 | { USB_DEVICE(PALMCONNECT_VID, PALMCONNECT_PID) }, |
100 | { USB_DEVICE(KLSI_VID, KLSI_KL5KUSB105D_PID) }, | 100 | { USB_DEVICE(KLSI_VID, KLSI_KL5KUSB105D_PID) }, |
101 | { } /* Terminating entry */ | 101 | { } /* Terminating entry */ |
102 | }; | 102 | }; |
103 | 103 | ||
104 | MODULE_DEVICE_TABLE(usb, id_table); | 104 | MODULE_DEVICE_TABLE(usb, id_table); |
105 | 105 | ||
106 | static struct usb_driver kl5kusb105d_driver = { | 106 | static struct usb_driver kl5kusb105d_driver = { |
107 | .name = "kl5kusb105d", | 107 | .name = "kl5kusb105d", |
108 | .probe = usb_serial_probe, | 108 | .probe = usb_serial_probe, |
109 | .disconnect = usb_serial_disconnect, | 109 | .disconnect = usb_serial_disconnect, |
110 | .id_table = id_table, | 110 | .id_table = id_table, |
111 | .no_dynamic_id = 1, | 111 | .no_dynamic_id = 1, |
112 | }; | 112 | }; |
113 | 113 | ||
114 | static struct usb_serial_driver kl5kusb105d_device = { | 114 | static struct usb_serial_driver kl5kusb105d_device = { |
115 | .driver = { | 115 | .driver = { |
116 | .owner = THIS_MODULE, | 116 | .owner = THIS_MODULE, |
117 | .name = "kl5kusb105d", | 117 | .name = "kl5kusb105d", |
118 | }, | 118 | }, |
119 | .description = "KL5KUSB105D / PalmConnect", | 119 | .description = "KL5KUSB105D / PalmConnect", |
120 | .usb_driver = &kl5kusb105d_driver, | 120 | .usb_driver = &kl5kusb105d_driver, |
121 | .id_table = id_table, | 121 | .id_table = id_table, |
122 | .num_ports = 1, | 122 | .num_ports = 1, |
123 | .open = klsi_105_open, | 123 | .open = klsi_105_open, |
124 | .close = klsi_105_close, | 124 | .close = klsi_105_close, |
125 | .write = klsi_105_write, | 125 | .write = klsi_105_write, |
126 | .write_bulk_callback = klsi_105_write_bulk_callback, | 126 | .write_bulk_callback = klsi_105_write_bulk_callback, |
127 | .chars_in_buffer = klsi_105_chars_in_buffer, | 127 | .chars_in_buffer = klsi_105_chars_in_buffer, |
128 | .write_room = klsi_105_write_room, | 128 | .write_room = klsi_105_write_room, |
129 | .read_bulk_callback = klsi_105_read_bulk_callback, | 129 | .read_bulk_callback = klsi_105_read_bulk_callback, |
130 | .set_termios = klsi_105_set_termios, | 130 | .set_termios = klsi_105_set_termios, |
131 | /*.break_ctl = klsi_105_break_ctl,*/ | 131 | /*.break_ctl = klsi_105_break_ctl,*/ |
132 | .tiocmget = klsi_105_tiocmget, | 132 | .tiocmget = klsi_105_tiocmget, |
133 | .tiocmset = klsi_105_tiocmset, | 133 | .tiocmset = klsi_105_tiocmset, |
134 | .attach = klsi_105_startup, | 134 | .attach = klsi_105_startup, |
135 | .shutdown = klsi_105_shutdown, | 135 | .shutdown = klsi_105_shutdown, |
136 | .throttle = klsi_105_throttle, | 136 | .throttle = klsi_105_throttle, |
137 | .unthrottle = klsi_105_unthrottle, | 137 | .unthrottle = klsi_105_unthrottle, |
138 | }; | 138 | }; |
139 | 139 | ||
140 | struct klsi_105_port_settings { | 140 | struct klsi_105_port_settings { |
141 | __u8 pktlen; /* always 5, it seems */ | 141 | __u8 pktlen; /* always 5, it seems */ |
142 | __u8 baudrate; | 142 | __u8 baudrate; |
143 | __u8 databits; | 143 | __u8 databits; |
144 | __u8 unknown1; | 144 | __u8 unknown1; |
145 | __u8 unknown2; | 145 | __u8 unknown2; |
146 | } __attribute__ ((packed)); | 146 | } __attribute__ ((packed)); |
147 | 147 | ||
148 | /* we implement a pool of NUM_URBS urbs per usb_serial */ | 148 | /* we implement a pool of NUM_URBS urbs per usb_serial */ |
149 | #define NUM_URBS 1 | 149 | #define NUM_URBS 1 |
150 | #define URB_TRANSFER_BUFFER_SIZE 64 | 150 | #define URB_TRANSFER_BUFFER_SIZE 64 |
151 | struct klsi_105_private { | 151 | struct klsi_105_private { |
152 | struct klsi_105_port_settings cfg; | 152 | struct klsi_105_port_settings cfg; |
153 | struct ktermios termios; | 153 | struct ktermios termios; |
154 | unsigned long line_state; /* modem line settings */ | 154 | unsigned long line_state; /* modem line settings */ |
155 | /* write pool */ | 155 | /* write pool */ |
156 | struct urb *write_urb_pool[NUM_URBS]; | 156 | struct urb *write_urb_pool[NUM_URBS]; |
157 | spinlock_t lock; | 157 | spinlock_t lock; |
158 | unsigned long bytes_in; | 158 | unsigned long bytes_in; |
159 | unsigned long bytes_out; | 159 | unsigned long bytes_out; |
160 | }; | 160 | }; |
161 | 161 | ||
162 | 162 | ||
163 | /* | 163 | /* |
164 | * Handle vendor specific USB requests | 164 | * Handle vendor specific USB requests |
165 | */ | 165 | */ |
166 | 166 | ||
167 | 167 | ||
168 | #define KLSI_TIMEOUT 5000 /* default urb timeout */ | 168 | #define KLSI_TIMEOUT 5000 /* default urb timeout */ |
169 | 169 | ||
170 | static int klsi_105_chg_port_settings(struct usb_serial_port *port, | 170 | static int klsi_105_chg_port_settings(struct usb_serial_port *port, |
171 | struct klsi_105_port_settings *settings) | 171 | struct klsi_105_port_settings *settings) |
172 | { | 172 | { |
173 | int rc; | 173 | int rc; |
174 | 174 | ||
175 | rc = usb_control_msg(port->serial->dev, | 175 | rc = usb_control_msg(port->serial->dev, |
176 | usb_sndctrlpipe(port->serial->dev, 0), | 176 | usb_sndctrlpipe(port->serial->dev, 0), |
177 | KL5KUSB105A_SIO_SET_DATA, | 177 | KL5KUSB105A_SIO_SET_DATA, |
178 | USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_INTERFACE, | 178 | USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_INTERFACE, |
179 | 0, /* value */ | 179 | 0, /* value */ |
180 | 0, /* index */ | 180 | 0, /* index */ |
181 | settings, | 181 | settings, |
182 | sizeof(struct klsi_105_port_settings), | 182 | sizeof(struct klsi_105_port_settings), |
183 | KLSI_TIMEOUT); | 183 | KLSI_TIMEOUT); |
184 | if (rc < 0) | 184 | if (rc < 0) |
185 | dev_err(&port->dev, | 185 | dev_err(&port->dev, |
186 | "Change port settings failed (error = %d)\n", rc); | 186 | "Change port settings failed (error = %d)\n", rc); |
187 | dev_info(&port->serial->dev->dev, | 187 | dev_info(&port->serial->dev->dev, |
188 | "%d byte block, baudrate %x, databits %d, u1 %d, u2 %d\n", | 188 | "%d byte block, baudrate %x, databits %d, u1 %d, u2 %d\n", |
189 | settings->pktlen, settings->baudrate, settings->databits, | 189 | settings->pktlen, settings->baudrate, settings->databits, |
190 | settings->unknown1, settings->unknown2); | 190 | settings->unknown1, settings->unknown2); |
191 | return rc; | 191 | return rc; |
192 | } /* klsi_105_chg_port_settings */ | 192 | } /* klsi_105_chg_port_settings */ |
193 | 193 | ||
194 | /* translate a 16-bit status value from the device to linux's TIO bits */ | 194 | /* translate a 16-bit status value from the device to linux's TIO bits */ |
195 | static unsigned long klsi_105_status2linestate(const __u16 status) | 195 | static unsigned long klsi_105_status2linestate(const __u16 status) |
196 | { | 196 | { |
197 | unsigned long res = 0; | 197 | unsigned long res = 0; |
198 | 198 | ||
199 | res = ((status & KL5KUSB105A_DSR) ? TIOCM_DSR : 0) | 199 | res = ((status & KL5KUSB105A_DSR) ? TIOCM_DSR : 0) |
200 | | ((status & KL5KUSB105A_CTS) ? TIOCM_CTS : 0) | 200 | | ((status & KL5KUSB105A_CTS) ? TIOCM_CTS : 0) |
201 | ; | 201 | ; |
202 | 202 | ||
203 | return res; | 203 | return res; |
204 | } | 204 | } |
205 | /* | 205 | /* |
206 | * Read line control via vendor command and return result through | 206 | * Read line control via vendor command and return result through |
207 | * *line_state_p | 207 | * *line_state_p |
208 | */ | 208 | */ |
209 | /* It seems that the status buffer has always only 2 bytes length */ | 209 | /* It seems that the status buffer has always only 2 bytes length */ |
210 | #define KLSI_STATUSBUF_LEN 2 | 210 | #define KLSI_STATUSBUF_LEN 2 |
211 | static int klsi_105_get_line_state(struct usb_serial_port *port, | 211 | static int klsi_105_get_line_state(struct usb_serial_port *port, |
212 | unsigned long *line_state_p) | 212 | unsigned long *line_state_p) |
213 | { | 213 | { |
214 | int rc; | 214 | int rc; |
215 | __u8 status_buf[KLSI_STATUSBUF_LEN] = { -1, -1}; | 215 | __u8 status_buf[KLSI_STATUSBUF_LEN] = { -1, -1}; |
216 | __u16 status; | 216 | __u16 status; |
217 | 217 | ||
218 | dev_info(&port->serial->dev->dev, "sending SIO Poll request\n"); | 218 | dev_info(&port->serial->dev->dev, "sending SIO Poll request\n"); |
219 | rc = usb_control_msg(port->serial->dev, | 219 | rc = usb_control_msg(port->serial->dev, |
220 | usb_rcvctrlpipe(port->serial->dev, 0), | 220 | usb_rcvctrlpipe(port->serial->dev, 0), |
221 | KL5KUSB105A_SIO_POLL, | 221 | KL5KUSB105A_SIO_POLL, |
222 | USB_TYPE_VENDOR | USB_DIR_IN, | 222 | USB_TYPE_VENDOR | USB_DIR_IN, |
223 | 0, /* value */ | 223 | 0, /* value */ |
224 | 0, /* index */ | 224 | 0, /* index */ |
225 | status_buf, KLSI_STATUSBUF_LEN, | 225 | status_buf, KLSI_STATUSBUF_LEN, |
226 | 10000 | 226 | 10000 |
227 | ); | 227 | ); |
228 | if (rc < 0) | 228 | if (rc < 0) |
229 | dev_err(&port->dev, "Reading line status failed (error = %d)\n", | 229 | dev_err(&port->dev, "Reading line status failed (error = %d)\n", |
230 | rc); | 230 | rc); |
231 | else { | 231 | else { |
232 | status = get_unaligned_le16(status_buf); | 232 | status = get_unaligned_le16(status_buf); |
233 | 233 | ||
234 | dev_info(&port->serial->dev->dev, "read status %x %x", | 234 | dev_info(&port->serial->dev->dev, "read status %x %x", |
235 | status_buf[0], status_buf[1]); | 235 | status_buf[0], status_buf[1]); |
236 | 236 | ||
237 | *line_state_p = klsi_105_status2linestate(status); | 237 | *line_state_p = klsi_105_status2linestate(status); |
238 | } | 238 | } |
239 | return rc; | 239 | return rc; |
240 | } | 240 | } |
241 | 241 | ||
242 | 242 | ||
243 | /* | 243 | /* |
244 | * Driver's tty interface functions | 244 | * Driver's tty interface functions |
245 | */ | 245 | */ |
246 | 246 | ||
247 | static int klsi_105_startup(struct usb_serial *serial) | 247 | static int klsi_105_startup(struct usb_serial *serial) |
248 | { | 248 | { |
249 | struct klsi_105_private *priv; | 249 | struct klsi_105_private *priv; |
250 | int i, j; | 250 | int i, j; |
251 | 251 | ||
252 | /* check if we support the product id (see keyspan.c) | 252 | /* check if we support the product id (see keyspan.c) |
253 | * FIXME | 253 | * FIXME |
254 | */ | 254 | */ |
255 | 255 | ||
256 | /* allocate the private data structure */ | 256 | /* allocate the private data structure */ |
257 | for (i = 0; i < serial->num_ports; i++) { | 257 | for (i = 0; i < serial->num_ports; i++) { |
258 | priv = kmalloc(sizeof(struct klsi_105_private), | 258 | priv = kmalloc(sizeof(struct klsi_105_private), |
259 | GFP_KERNEL); | 259 | GFP_KERNEL); |
260 | if (!priv) { | 260 | if (!priv) { |
261 | dbg("%skmalloc for klsi_105_private failed.", __func__); | 261 | dbg("%skmalloc for klsi_105_private failed.", __func__); |
262 | i--; | 262 | i--; |
263 | goto err_cleanup; | 263 | goto err_cleanup; |
264 | } | 264 | } |
265 | /* set initial values for control structures */ | 265 | /* set initial values for control structures */ |
266 | priv->cfg.pktlen = 5; | 266 | priv->cfg.pktlen = 5; |
267 | priv->cfg.baudrate = kl5kusb105a_sio_b9600; | 267 | priv->cfg.baudrate = kl5kusb105a_sio_b9600; |
268 | priv->cfg.databits = kl5kusb105a_dtb_8; | 268 | priv->cfg.databits = kl5kusb105a_dtb_8; |
269 | priv->cfg.unknown1 = 0; | 269 | priv->cfg.unknown1 = 0; |
270 | priv->cfg.unknown2 = 1; | 270 | priv->cfg.unknown2 = 1; |
271 | 271 | ||
272 | priv->line_state = 0; | 272 | priv->line_state = 0; |
273 | 273 | ||
274 | priv->bytes_in = 0; | 274 | priv->bytes_in = 0; |
275 | priv->bytes_out = 0; | 275 | priv->bytes_out = 0; |
276 | usb_set_serial_port_data(serial->port[i], priv); | 276 | usb_set_serial_port_data(serial->port[i], priv); |
277 | 277 | ||
278 | spin_lock_init(&priv->lock); | 278 | spin_lock_init(&priv->lock); |
279 | for (j = 0; j < NUM_URBS; j++) { | 279 | for (j = 0; j < NUM_URBS; j++) { |
280 | struct urb *urb = usb_alloc_urb(0, GFP_KERNEL); | 280 | struct urb *urb = usb_alloc_urb(0, GFP_KERNEL); |
281 | 281 | ||
282 | priv->write_urb_pool[j] = urb; | 282 | priv->write_urb_pool[j] = urb; |
283 | if (urb == NULL) { | 283 | if (urb == NULL) { |
284 | dev_err(&serial->dev->dev, "No more urbs???\n"); | 284 | dev_err(&serial->dev->dev, "No more urbs???\n"); |
285 | goto err_cleanup; | 285 | goto err_cleanup; |
286 | } | 286 | } |
287 | 287 | ||
288 | urb->transfer_buffer = | 288 | urb->transfer_buffer = |
289 | kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); | 289 | kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); |
290 | if (!urb->transfer_buffer) { | 290 | if (!urb->transfer_buffer) { |
291 | dev_err(&serial->dev->dev, | 291 | dev_err(&serial->dev->dev, |
292 | "%s - out of memory for urb buffers.\n", | 292 | "%s - out of memory for urb buffers.\n", |
293 | __func__); | 293 | __func__); |
294 | goto err_cleanup; | 294 | goto err_cleanup; |
295 | } | 295 | } |
296 | } | 296 | } |
297 | 297 | ||
298 | /* priv->termios is left uninitalized until port opening */ | 298 | /* priv->termios is left uninitalized until port opening */ |
299 | init_waitqueue_head(&serial->port[i]->write_wait); | 299 | init_waitqueue_head(&serial->port[i]->write_wait); |
300 | } | 300 | } |
301 | 301 | ||
302 | return 0; | 302 | return 0; |
303 | 303 | ||
304 | err_cleanup: | 304 | err_cleanup: |
305 | for (; i >= 0; i--) { | 305 | for (; i >= 0; i--) { |
306 | priv = usb_get_serial_port_data(serial->port[i]); | 306 | priv = usb_get_serial_port_data(serial->port[i]); |
307 | for (j = 0; j < NUM_URBS; j++) { | 307 | for (j = 0; j < NUM_URBS; j++) { |
308 | if (priv->write_urb_pool[j]) { | 308 | if (priv->write_urb_pool[j]) { |
309 | kfree(priv->write_urb_pool[j]->transfer_buffer); | 309 | kfree(priv->write_urb_pool[j]->transfer_buffer); |
310 | usb_free_urb(priv->write_urb_pool[j]); | 310 | usb_free_urb(priv->write_urb_pool[j]); |
311 | } | 311 | } |
312 | } | 312 | } |
313 | usb_set_serial_port_data(serial->port[i], NULL); | 313 | usb_set_serial_port_data(serial->port[i], NULL); |
314 | } | 314 | } |
315 | return -ENOMEM; | 315 | return -ENOMEM; |
316 | } /* klsi_105_startup */ | 316 | } /* klsi_105_startup */ |
317 | 317 | ||
318 | 318 | ||
319 | static void klsi_105_shutdown(struct usb_serial *serial) | 319 | static void klsi_105_shutdown(struct usb_serial *serial) |
320 | { | 320 | { |
321 | int i; | 321 | int i; |
322 | 322 | ||
323 | dbg("%s", __func__); | 323 | dbg("%s", __func__); |
324 | 324 | ||
325 | /* stop reads and writes on all ports */ | 325 | /* stop reads and writes on all ports */ |
326 | for (i = 0; i < serial->num_ports; ++i) { | 326 | for (i = 0; i < serial->num_ports; ++i) { |
327 | struct klsi_105_private *priv = | 327 | struct klsi_105_private *priv = |
328 | usb_get_serial_port_data(serial->port[i]); | 328 | usb_get_serial_port_data(serial->port[i]); |
329 | unsigned long flags; | 329 | unsigned long flags; |
330 | 330 | ||
331 | if (priv) { | 331 | if (priv) { |
332 | /* kill our write urb pool */ | 332 | /* kill our write urb pool */ |
333 | int j; | 333 | int j; |
334 | struct urb **write_urbs = priv->write_urb_pool; | 334 | struct urb **write_urbs = priv->write_urb_pool; |
335 | spin_lock_irqsave(&priv->lock, flags); | 335 | spin_lock_irqsave(&priv->lock, flags); |
336 | 336 | ||
337 | for (j = 0; j < NUM_URBS; j++) { | 337 | for (j = 0; j < NUM_URBS; j++) { |
338 | if (write_urbs[j]) { | 338 | if (write_urbs[j]) { |
339 | /* FIXME - uncomment the following | 339 | /* FIXME - uncomment the following |
340 | * usb_kill_urb call when the host | 340 | * usb_kill_urb call when the host |
341 | * controllers get fixed to set | 341 | * controllers get fixed to set |
342 | * urb->dev = NULL after the urb is | 342 | * urb->dev = NULL after the urb is |
343 | * finished. Otherwise this call | 343 | * finished. Otherwise this call |
344 | * oopses. */ | 344 | * oopses. */ |
345 | /* usb_kill_urb(write_urbs[j]); */ | 345 | /* usb_kill_urb(write_urbs[j]); */ |
346 | kfree(write_urbs[j]->transfer_buffer); | 346 | kfree(write_urbs[j]->transfer_buffer); |
347 | usb_free_urb(write_urbs[j]); | 347 | usb_free_urb(write_urbs[j]); |
348 | } | 348 | } |
349 | } | 349 | } |
350 | spin_unlock_irqrestore(&priv->lock, flags); | 350 | spin_unlock_irqrestore(&priv->lock, flags); |
351 | kfree(priv); | 351 | kfree(priv); |
352 | usb_set_serial_port_data(serial->port[i], NULL); | 352 | usb_set_serial_port_data(serial->port[i], NULL); |
353 | } | 353 | } |
354 | } | 354 | } |
355 | } /* klsi_105_shutdown */ | 355 | } /* klsi_105_shutdown */ |
356 | 356 | ||
357 | static int klsi_105_open(struct tty_struct *tty, | 357 | static int klsi_105_open(struct tty_struct *tty, |
358 | struct usb_serial_port *port, struct file *filp) | 358 | struct usb_serial_port *port, struct file *filp) |
359 | { | 359 | { |
360 | struct klsi_105_private *priv = usb_get_serial_port_data(port); | 360 | struct klsi_105_private *priv = usb_get_serial_port_data(port); |
361 | int retval = 0; | 361 | int retval = 0; |
362 | int rc; | 362 | int rc; |
363 | int i; | 363 | int i; |
364 | unsigned long line_state; | 364 | unsigned long line_state; |
365 | struct klsi_105_port_settings cfg; | 365 | struct klsi_105_port_settings cfg; |
366 | unsigned long flags; | 366 | unsigned long flags; |
367 | 367 | ||
368 | dbg("%s port %d", __func__, port->number); | 368 | dbg("%s port %d", __func__, port->number); |
369 | 369 | ||
370 | /* force low_latency on so that our tty_push actually forces | 370 | /* force low_latency on so that our tty_push actually forces |
371 | * the data through | 371 | * the data through |
372 | * tty->low_latency = 1; */ | 372 | * tty->low_latency = 1; */ |
373 | 373 | ||
374 | /* Do a defined restart: | 374 | /* Do a defined restart: |
375 | * Set up sane default baud rate and send the 'READ_ON' | 375 | * Set up sane default baud rate and send the 'READ_ON' |
376 | * vendor command. | 376 | * vendor command. |
377 | * FIXME: set modem line control (how?) | 377 | * FIXME: set modem line control (how?) |
378 | * Then read the modem line control and store values in | 378 | * Then read the modem line control and store values in |
379 | * priv->line_state. | 379 | * priv->line_state. |
380 | */ | 380 | */ |
381 | cfg.pktlen = 5; | 381 | cfg.pktlen = 5; |
382 | cfg.baudrate = kl5kusb105a_sio_b9600; | 382 | cfg.baudrate = kl5kusb105a_sio_b9600; |
383 | cfg.databits = kl5kusb105a_dtb_8; | 383 | cfg.databits = kl5kusb105a_dtb_8; |
384 | cfg.unknown1 = 0; | 384 | cfg.unknown1 = 0; |
385 | cfg.unknown2 = 1; | 385 | cfg.unknown2 = 1; |
386 | klsi_105_chg_port_settings(port, &cfg); | 386 | klsi_105_chg_port_settings(port, &cfg); |
387 | 387 | ||
388 | /* set up termios structure */ | 388 | /* set up termios structure */ |
389 | spin_lock_irqsave(&priv->lock, flags); | 389 | spin_lock_irqsave(&priv->lock, flags); |
390 | priv->termios.c_iflag = tty->termios->c_iflag; | 390 | priv->termios.c_iflag = tty->termios->c_iflag; |
391 | priv->termios.c_oflag = tty->termios->c_oflag; | 391 | priv->termios.c_oflag = tty->termios->c_oflag; |
392 | priv->termios.c_cflag = tty->termios->c_cflag; | 392 | priv->termios.c_cflag = tty->termios->c_cflag; |
393 | priv->termios.c_lflag = tty->termios->c_lflag; | 393 | priv->termios.c_lflag = tty->termios->c_lflag; |
394 | for (i = 0; i < NCCS; i++) | 394 | for (i = 0; i < NCCS; i++) |
395 | priv->termios.c_cc[i] = tty->termios->c_cc[i]; | 395 | priv->termios.c_cc[i] = tty->termios->c_cc[i]; |
396 | priv->cfg.pktlen = cfg.pktlen; | 396 | priv->cfg.pktlen = cfg.pktlen; |
397 | priv->cfg.baudrate = cfg.baudrate; | 397 | priv->cfg.baudrate = cfg.baudrate; |
398 | priv->cfg.databits = cfg.databits; | 398 | priv->cfg.databits = cfg.databits; |
399 | priv->cfg.unknown1 = cfg.unknown1; | 399 | priv->cfg.unknown1 = cfg.unknown1; |
400 | priv->cfg.unknown2 = cfg.unknown2; | 400 | priv->cfg.unknown2 = cfg.unknown2; |
401 | spin_unlock_irqrestore(&priv->lock, flags); | 401 | spin_unlock_irqrestore(&priv->lock, flags); |
402 | 402 | ||
403 | /* READ_ON and urb submission */ | 403 | /* READ_ON and urb submission */ |
404 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, | 404 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, |
405 | usb_rcvbulkpipe(port->serial->dev, | 405 | usb_rcvbulkpipe(port->serial->dev, |
406 | port->bulk_in_endpointAddress), | 406 | port->bulk_in_endpointAddress), |
407 | port->read_urb->transfer_buffer, | 407 | port->read_urb->transfer_buffer, |
408 | port->read_urb->transfer_buffer_length, | 408 | port->read_urb->transfer_buffer_length, |
409 | klsi_105_read_bulk_callback, | 409 | klsi_105_read_bulk_callback, |
410 | port); | 410 | port); |
411 | 411 | ||
412 | rc = usb_submit_urb(port->read_urb, GFP_KERNEL); | 412 | rc = usb_submit_urb(port->read_urb, GFP_KERNEL); |
413 | if (rc) { | 413 | if (rc) { |
414 | dev_err(&port->dev, "%s - failed submitting read urb, " | 414 | dev_err(&port->dev, "%s - failed submitting read urb, " |
415 | "error %d\n", __func__, rc); | 415 | "error %d\n", __func__, rc); |
416 | retval = rc; | 416 | retval = rc; |
417 | goto exit; | 417 | goto exit; |
418 | } | 418 | } |
419 | 419 | ||
420 | rc = usb_control_msg(port->serial->dev, | 420 | rc = usb_control_msg(port->serial->dev, |
421 | usb_sndctrlpipe(port->serial->dev, 0), | 421 | usb_sndctrlpipe(port->serial->dev, 0), |
422 | KL5KUSB105A_SIO_CONFIGURE, | 422 | KL5KUSB105A_SIO_CONFIGURE, |
423 | USB_TYPE_VENDOR|USB_DIR_OUT|USB_RECIP_INTERFACE, | 423 | USB_TYPE_VENDOR|USB_DIR_OUT|USB_RECIP_INTERFACE, |
424 | KL5KUSB105A_SIO_CONFIGURE_READ_ON, | 424 | KL5KUSB105A_SIO_CONFIGURE_READ_ON, |
425 | 0, /* index */ | 425 | 0, /* index */ |
426 | NULL, | 426 | NULL, |
427 | 0, | 427 | 0, |
428 | KLSI_TIMEOUT); | 428 | KLSI_TIMEOUT); |
429 | if (rc < 0) { | 429 | if (rc < 0) { |
430 | dev_err(&port->dev, "Enabling read failed (error = %d)\n", rc); | 430 | dev_err(&port->dev, "Enabling read failed (error = %d)\n", rc); |
431 | retval = rc; | 431 | retval = rc; |
432 | } else | 432 | } else |
433 | dbg("%s - enabled reading", __func__); | 433 | dbg("%s - enabled reading", __func__); |
434 | 434 | ||
435 | rc = klsi_105_get_line_state(port, &line_state); | 435 | rc = klsi_105_get_line_state(port, &line_state); |
436 | if (rc >= 0) { | 436 | if (rc >= 0) { |
437 | spin_lock_irqsave(&priv->lock, flags); | 437 | spin_lock_irqsave(&priv->lock, flags); |
438 | priv->line_state = line_state; | 438 | priv->line_state = line_state; |
439 | spin_unlock_irqrestore(&priv->lock, flags); | 439 | spin_unlock_irqrestore(&priv->lock, flags); |
440 | dbg("%s - read line state 0x%lx", __func__, line_state); | 440 | dbg("%s - read line state 0x%lx", __func__, line_state); |
441 | retval = 0; | 441 | retval = 0; |
442 | } else | 442 | } else |
443 | retval = rc; | 443 | retval = rc; |
444 | 444 | ||
445 | exit: | 445 | exit: |
446 | return retval; | 446 | return retval; |
447 | } /* klsi_105_open */ | 447 | } /* klsi_105_open */ |
448 | 448 | ||
449 | 449 | ||
450 | static void klsi_105_close(struct tty_struct *tty, | 450 | static void klsi_105_close(struct tty_struct *tty, |
451 | struct usb_serial_port *port, struct file *filp) | 451 | struct usb_serial_port *port, struct file *filp) |
452 | { | 452 | { |
453 | struct klsi_105_private *priv = usb_get_serial_port_data(port); | 453 | struct klsi_105_private *priv = usb_get_serial_port_data(port); |
454 | int rc; | 454 | int rc; |
455 | 455 | ||
456 | dbg("%s port %d", __func__, port->number); | 456 | dbg("%s port %d", __func__, port->number); |
457 | 457 | ||
458 | mutex_lock(&port->serial->disc_mutex); | 458 | mutex_lock(&port->serial->disc_mutex); |
459 | if (!port->serial->disconnected) { | 459 | if (!port->serial->disconnected) { |
460 | /* send READ_OFF */ | 460 | /* send READ_OFF */ |
461 | rc = usb_control_msg(port->serial->dev, | 461 | rc = usb_control_msg(port->serial->dev, |
462 | usb_sndctrlpipe(port->serial->dev, 0), | 462 | usb_sndctrlpipe(port->serial->dev, 0), |
463 | KL5KUSB105A_SIO_CONFIGURE, | 463 | KL5KUSB105A_SIO_CONFIGURE, |
464 | USB_TYPE_VENDOR | USB_DIR_OUT, | 464 | USB_TYPE_VENDOR | USB_DIR_OUT, |
465 | KL5KUSB105A_SIO_CONFIGURE_READ_OFF, | 465 | KL5KUSB105A_SIO_CONFIGURE_READ_OFF, |
466 | 0, /* index */ | 466 | 0, /* index */ |
467 | NULL, 0, | 467 | NULL, 0, |
468 | KLSI_TIMEOUT); | 468 | KLSI_TIMEOUT); |
469 | if (rc < 0) | 469 | if (rc < 0) |
470 | dev_err(&port->dev, | 470 | dev_err(&port->dev, |
471 | "Disabling read failed (error = %d)\n", rc); | 471 | "Disabling read failed (error = %d)\n", rc); |
472 | } | 472 | } |
473 | mutex_unlock(&port->serial->disc_mutex); | 473 | mutex_unlock(&port->serial->disc_mutex); |
474 | 474 | ||
475 | /* shutdown our bulk reads and writes */ | 475 | /* shutdown our bulk reads and writes */ |
476 | usb_kill_urb(port->write_urb); | 476 | usb_kill_urb(port->write_urb); |
477 | usb_kill_urb(port->read_urb); | 477 | usb_kill_urb(port->read_urb); |
478 | /* unlink our write pool */ | 478 | /* unlink our write pool */ |
479 | /* FIXME */ | 479 | /* FIXME */ |
480 | /* wgg - do I need this? I think so. */ | 480 | /* wgg - do I need this? I think so. */ |
481 | usb_kill_urb(port->interrupt_in_urb); | 481 | usb_kill_urb(port->interrupt_in_urb); |
482 | dev_info(&port->serial->dev->dev, | 482 | dev_info(&port->serial->dev->dev, |
483 | "port stats: %ld bytes in, %ld bytes out\n", | 483 | "port stats: %ld bytes in, %ld bytes out\n", |
484 | priv->bytes_in, priv->bytes_out); | 484 | priv->bytes_in, priv->bytes_out); |
485 | } /* klsi_105_close */ | 485 | } /* klsi_105_close */ |
486 | 486 | ||
487 | 487 | ||
488 | /* We need to write a complete 64-byte data block and encode the | 488 | /* We need to write a complete 64-byte data block and encode the |
489 | * number actually sent in the first double-byte, LSB-order. That | 489 | * number actually sent in the first double-byte, LSB-order. That |
490 | * leaves at most 62 bytes of payload. | 490 | * leaves at most 62 bytes of payload. |
491 | */ | 491 | */ |
492 | #define KLSI_105_DATA_OFFSET 2 /* in the bulk urb data block */ | 492 | #define KLSI_105_DATA_OFFSET 2 /* in the bulk urb data block */ |
493 | 493 | ||
494 | 494 | ||
495 | static int klsi_105_write(struct tty_struct *tty, | 495 | static int klsi_105_write(struct tty_struct *tty, |
496 | struct usb_serial_port *port, const unsigned char *buf, int count) | 496 | struct usb_serial_port *port, const unsigned char *buf, int count) |
497 | { | 497 | { |
498 | struct klsi_105_private *priv = usb_get_serial_port_data(port); | 498 | struct klsi_105_private *priv = usb_get_serial_port_data(port); |
499 | int result, size; | 499 | int result, size; |
500 | int bytes_sent = 0; | 500 | int bytes_sent = 0; |
501 | 501 | ||
502 | dbg("%s - port %d", __func__, port->number); | 502 | dbg("%s - port %d", __func__, port->number); |
503 | 503 | ||
504 | while (count > 0) { | 504 | while (count > 0) { |
505 | /* try to find a free urb (write 0 bytes if none) */ | 505 | /* try to find a free urb (write 0 bytes if none) */ |
506 | struct urb *urb = NULL; | 506 | struct urb *urb = NULL; |
507 | unsigned long flags; | 507 | unsigned long flags; |
508 | int i; | 508 | int i; |
509 | /* since the pool is per-port we might not need | 509 | /* since the pool is per-port we might not need |
510 | the spin lock !? */ | 510 | the spin lock !? */ |
511 | spin_lock_irqsave(&priv->lock, flags); | 511 | spin_lock_irqsave(&priv->lock, flags); |
512 | for (i = 0; i < NUM_URBS; i++) { | 512 | for (i = 0; i < NUM_URBS; i++) { |
513 | if (priv->write_urb_pool[i]->status != -EINPROGRESS) { | 513 | if (priv->write_urb_pool[i]->status != -EINPROGRESS) { |
514 | urb = priv->write_urb_pool[i]; | 514 | urb = priv->write_urb_pool[i]; |
515 | dbg("%s - using pool URB %d", __func__, i); | 515 | dbg("%s - using pool URB %d", __func__, i); |
516 | break; | 516 | break; |
517 | } | 517 | } |
518 | } | 518 | } |
519 | spin_unlock_irqrestore(&priv->lock, flags); | 519 | spin_unlock_irqrestore(&priv->lock, flags); |
520 | 520 | ||
521 | if (urb == NULL) { | 521 | if (urb == NULL) { |
522 | dbg("%s - no more free urbs", __func__); | 522 | dbg("%s - no more free urbs", __func__); |
523 | goto exit; | 523 | goto exit; |
524 | } | 524 | } |
525 | 525 | ||
526 | if (urb->transfer_buffer == NULL) { | 526 | if (urb->transfer_buffer == NULL) { |
527 | urb->transfer_buffer = | 527 | urb->transfer_buffer = |
528 | kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC); | 528 | kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC); |
529 | if (urb->transfer_buffer == NULL) { | 529 | if (urb->transfer_buffer == NULL) { |
530 | dev_err(&port->dev, | 530 | dev_err(&port->dev, |
531 | "%s - no more kernel memory...\n", | 531 | "%s - no more kernel memory...\n", |
532 | __func__); | 532 | __func__); |
533 | goto exit; | 533 | goto exit; |
534 | } | 534 | } |
535 | } | 535 | } |
536 | 536 | ||
537 | size = min(count, port->bulk_out_size - KLSI_105_DATA_OFFSET); | 537 | size = min(count, port->bulk_out_size - KLSI_105_DATA_OFFSET); |
538 | size = min(size, URB_TRANSFER_BUFFER_SIZE - | 538 | size = min(size, URB_TRANSFER_BUFFER_SIZE - |
539 | KLSI_105_DATA_OFFSET); | 539 | KLSI_105_DATA_OFFSET); |
540 | 540 | ||
541 | memcpy(urb->transfer_buffer + KLSI_105_DATA_OFFSET, buf, size); | 541 | memcpy(urb->transfer_buffer + KLSI_105_DATA_OFFSET, buf, size); |
542 | 542 | ||
543 | /* write payload size into transfer buffer */ | 543 | /* write payload size into transfer buffer */ |
544 | ((__u8 *)urb->transfer_buffer)[0] = (__u8) (size & 0xFF); | 544 | ((__u8 *)urb->transfer_buffer)[0] = (__u8) (size & 0xFF); |
545 | ((__u8 *)urb->transfer_buffer)[1] = (__u8) ((size & 0xFF00)>>8); | 545 | ((__u8 *)urb->transfer_buffer)[1] = (__u8) ((size & 0xFF00)>>8); |
546 | 546 | ||
547 | /* set up our urb */ | 547 | /* set up our urb */ |
548 | usb_fill_bulk_urb(urb, port->serial->dev, | 548 | usb_fill_bulk_urb(urb, port->serial->dev, |
549 | usb_sndbulkpipe(port->serial->dev, | 549 | usb_sndbulkpipe(port->serial->dev, |
550 | port->bulk_out_endpointAddress), | 550 | port->bulk_out_endpointAddress), |
551 | urb->transfer_buffer, | 551 | urb->transfer_buffer, |
552 | URB_TRANSFER_BUFFER_SIZE, | 552 | URB_TRANSFER_BUFFER_SIZE, |
553 | klsi_105_write_bulk_callback, | 553 | klsi_105_write_bulk_callback, |
554 | port); | 554 | port); |
555 | 555 | ||
556 | /* send the data out the bulk port */ | 556 | /* send the data out the bulk port */ |
557 | result = usb_submit_urb(urb, GFP_ATOMIC); | 557 | result = usb_submit_urb(urb, GFP_ATOMIC); |
558 | if (result) { | 558 | if (result) { |
559 | dev_err(&port->dev, | 559 | dev_err(&port->dev, |
560 | "%s - failed submitting write urb, error %d\n", | 560 | "%s - failed submitting write urb, error %d\n", |
561 | __func__, result); | 561 | __func__, result); |
562 | goto exit; | 562 | goto exit; |
563 | } | 563 | } |
564 | buf += size; | 564 | buf += size; |
565 | bytes_sent += size; | 565 | bytes_sent += size; |
566 | count -= size; | 566 | count -= size; |
567 | } | 567 | } |
568 | exit: | 568 | exit: |
569 | /* lockless, but it's for debug info only... */ | 569 | /* lockless, but it's for debug info only... */ |
570 | priv->bytes_out += bytes_sent; | 570 | priv->bytes_out += bytes_sent; |
571 | 571 | ||
572 | return bytes_sent; /* that's how much we wrote */ | 572 | return bytes_sent; /* that's how much we wrote */ |
573 | } /* klsi_105_write */ | 573 | } /* klsi_105_write */ |
574 | 574 | ||
575 | static void klsi_105_write_bulk_callback(struct urb *urb) | 575 | static void klsi_105_write_bulk_callback(struct urb *urb) |
576 | { | 576 | { |
577 | struct usb_serial_port *port = urb->context; | 577 | struct usb_serial_port *port = urb->context; |
578 | int status = urb->status; | 578 | int status = urb->status; |
579 | 579 | ||
580 | dbg("%s - port %d", __func__, port->number); | 580 | dbg("%s - port %d", __func__, port->number); |
581 | 581 | ||
582 | if (status) { | 582 | if (status) { |
583 | dbg("%s - nonzero write bulk status received: %d", __func__, | 583 | dbg("%s - nonzero write bulk status received: %d", __func__, |
584 | status); | 584 | status); |
585 | return; | 585 | return; |
586 | } | 586 | } |
587 | 587 | ||
588 | usb_serial_port_softint(port); | 588 | usb_serial_port_softint(port); |
589 | } /* klsi_105_write_bulk_completion_callback */ | 589 | } /* klsi_105_write_bulk_completion_callback */ |
590 | 590 | ||
591 | 591 | ||
592 | /* return number of characters currently in the writing process */ | 592 | /* return number of characters currently in the writing process */ |
593 | static int klsi_105_chars_in_buffer(struct tty_struct *tty) | 593 | static int klsi_105_chars_in_buffer(struct tty_struct *tty) |
594 | { | 594 | { |
595 | struct usb_serial_port *port = tty->driver_data; | 595 | struct usb_serial_port *port = tty->driver_data; |
596 | int chars = 0; | 596 | int chars = 0; |
597 | int i; | 597 | int i; |
598 | unsigned long flags; | 598 | unsigned long flags; |
599 | struct klsi_105_private *priv = usb_get_serial_port_data(port); | 599 | struct klsi_105_private *priv = usb_get_serial_port_data(port); |
600 | 600 | ||
601 | spin_lock_irqsave(&priv->lock, flags); | 601 | spin_lock_irqsave(&priv->lock, flags); |
602 | 602 | ||
603 | for (i = 0; i < NUM_URBS; ++i) { | 603 | for (i = 0; i < NUM_URBS; ++i) { |
604 | if (priv->write_urb_pool[i]->status == -EINPROGRESS) | 604 | if (priv->write_urb_pool[i]->status == -EINPROGRESS) |
605 | chars += URB_TRANSFER_BUFFER_SIZE; | 605 | chars += URB_TRANSFER_BUFFER_SIZE; |
606 | } | 606 | } |
607 | 607 | ||
608 | spin_unlock_irqrestore(&priv->lock, flags); | 608 | spin_unlock_irqrestore(&priv->lock, flags); |
609 | 609 | ||
610 | dbg("%s - returns %d", __func__, chars); | 610 | dbg("%s - returns %d", __func__, chars); |
611 | return chars; | 611 | return chars; |
612 | } | 612 | } |
613 | 613 | ||
614 | static int klsi_105_write_room(struct tty_struct *tty) | 614 | static int klsi_105_write_room(struct tty_struct *tty) |
615 | { | 615 | { |
616 | struct usb_serial_port *port = tty->driver_data; | 616 | struct usb_serial_port *port = tty->driver_data; |
617 | unsigned long flags; | 617 | unsigned long flags; |
618 | int i; | 618 | int i; |
619 | int room = 0; | 619 | int room = 0; |
620 | struct klsi_105_private *priv = usb_get_serial_port_data(port); | 620 | struct klsi_105_private *priv = usb_get_serial_port_data(port); |
621 | 621 | ||
622 | spin_lock_irqsave(&priv->lock, flags); | 622 | spin_lock_irqsave(&priv->lock, flags); |
623 | for (i = 0; i < NUM_URBS; ++i) { | 623 | for (i = 0; i < NUM_URBS; ++i) { |
624 | if (priv->write_urb_pool[i]->status != -EINPROGRESS) | 624 | if (priv->write_urb_pool[i]->status != -EINPROGRESS) |
625 | room += URB_TRANSFER_BUFFER_SIZE; | 625 | room += URB_TRANSFER_BUFFER_SIZE; |
626 | } | 626 | } |
627 | 627 | ||
628 | spin_unlock_irqrestore(&priv->lock, flags); | 628 | spin_unlock_irqrestore(&priv->lock, flags); |
629 | 629 | ||
630 | dbg("%s - returns %d", __func__, room); | 630 | dbg("%s - returns %d", __func__, room); |
631 | return room; | 631 | return room; |
632 | } | 632 | } |
633 | 633 | ||
634 | 634 | ||
635 | 635 | ||
636 | static void klsi_105_read_bulk_callback(struct urb *urb) | 636 | static void klsi_105_read_bulk_callback(struct urb *urb) |
637 | { | 637 | { |
638 | struct usb_serial_port *port = urb->context; | 638 | struct usb_serial_port *port = urb->context; |
639 | struct klsi_105_private *priv = usb_get_serial_port_data(port); | 639 | struct klsi_105_private *priv = usb_get_serial_port_data(port); |
640 | struct tty_struct *tty; | 640 | struct tty_struct *tty; |
641 | unsigned char *data = urb->transfer_buffer; | 641 | unsigned char *data = urb->transfer_buffer; |
642 | int rc; | 642 | int rc; |
643 | int status = urb->status; | 643 | int status = urb->status; |
644 | 644 | ||
645 | dbg("%s - port %d", __func__, port->number); | 645 | dbg("%s - port %d", __func__, port->number); |
646 | 646 | ||
647 | /* The urb might have been killed. */ | 647 | /* The urb might have been killed. */ |
648 | if (status) { | 648 | if (status) { |
649 | dbg("%s - nonzero read bulk status received: %d", __func__, | 649 | dbg("%s - nonzero read bulk status received: %d", __func__, |
650 | status); | 650 | status); |
651 | return; | 651 | return; |
652 | } | 652 | } |
653 | 653 | ||
654 | /* The data received is again preceded by a length double-byte in LSB- | 654 | /* The data received is again preceded by a length double-byte in LSB- |
655 | * first order (see klsi_105_write() ) | 655 | * first order (see klsi_105_write() ) |
656 | */ | 656 | */ |
657 | if (urb->actual_length == 0) { | 657 | if (urb->actual_length == 0) { |
658 | /* empty urbs seem to happen, we ignore them */ | 658 | /* empty urbs seem to happen, we ignore them */ |
659 | /* dbg("%s - emtpy URB", __func__); */ | 659 | /* dbg("%s - emtpy URB", __func__); */ |
660 | ; | 660 | ; |
661 | } else if (urb->actual_length <= 2) { | 661 | } else if (urb->actual_length <= 2) { |
662 | dbg("%s - size %d URB not understood", __func__, | 662 | dbg("%s - size %d URB not understood", __func__, |
663 | urb->actual_length); | 663 | urb->actual_length); |
664 | usb_serial_debug_data(debug, &port->dev, __func__, | 664 | usb_serial_debug_data(debug, &port->dev, __func__, |
665 | urb->actual_length, data); | 665 | urb->actual_length, data); |
666 | } else { | 666 | } else { |
667 | int bytes_sent = ((__u8 *) data)[0] + | 667 | int bytes_sent = ((__u8 *) data)[0] + |
668 | ((unsigned int) ((__u8 *) data)[1] << 8); | 668 | ((unsigned int) ((__u8 *) data)[1] << 8); |
669 | tty = tty_port_tty_get(&port->port); | 669 | tty = tty_port_tty_get(&port->port); |
670 | /* we should immediately resubmit the URB, before attempting | 670 | /* we should immediately resubmit the URB, before attempting |
671 | * to pass the data on to the tty layer. But that needs locking | 671 | * to pass the data on to the tty layer. But that needs locking |
672 | * against re-entry an then mixed-up data because of | 672 | * against re-entry an then mixed-up data because of |
673 | * intermixed tty_flip_buffer_push()s | 673 | * intermixed tty_flip_buffer_push()s |
674 | * FIXME | 674 | * FIXME |
675 | */ | 675 | */ |
676 | usb_serial_debug_data(debug, &port->dev, __func__, | 676 | usb_serial_debug_data(debug, &port->dev, __func__, |
677 | urb->actual_length, data); | 677 | urb->actual_length, data); |
678 | 678 | ||
679 | if (bytes_sent + 2 > urb->actual_length) { | 679 | if (bytes_sent + 2 > urb->actual_length) { |
680 | dbg("%s - trying to read more data than available" | 680 | dbg("%s - trying to read more data than available" |
681 | " (%d vs. %d)", __func__, | 681 | " (%d vs. %d)", __func__, |
682 | bytes_sent+2, urb->actual_length); | 682 | bytes_sent+2, urb->actual_length); |
683 | /* cap at implied limit */ | 683 | /* cap at implied limit */ |
684 | bytes_sent = urb->actual_length - 2; | 684 | bytes_sent = urb->actual_length - 2; |
685 | } | 685 | } |
686 | 686 | ||
687 | tty_buffer_request_room(tty, bytes_sent); | 687 | tty_buffer_request_room(tty, bytes_sent); |
688 | tty_insert_flip_string(tty, data + 2, bytes_sent); | 688 | tty_insert_flip_string(tty, data + 2, bytes_sent); |
689 | tty_flip_buffer_push(tty); | 689 | tty_flip_buffer_push(tty); |
690 | tty_kref_put(tty); | 690 | tty_kref_put(tty); |
691 | 691 | ||
692 | /* again lockless, but debug info only */ | 692 | /* again lockless, but debug info only */ |
693 | priv->bytes_in += bytes_sent; | 693 | priv->bytes_in += bytes_sent; |
694 | } | 694 | } |
695 | /* Continue trying to always read */ | 695 | /* Continue trying to always read */ |
696 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, | 696 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, |
697 | usb_rcvbulkpipe(port->serial->dev, | 697 | usb_rcvbulkpipe(port->serial->dev, |
698 | port->bulk_in_endpointAddress), | 698 | port->bulk_in_endpointAddress), |
699 | port->read_urb->transfer_buffer, | 699 | port->read_urb->transfer_buffer, |
700 | port->read_urb->transfer_buffer_length, | 700 | port->read_urb->transfer_buffer_length, |
701 | klsi_105_read_bulk_callback, | 701 | klsi_105_read_bulk_callback, |
702 | port); | 702 | port); |
703 | rc = usb_submit_urb(port->read_urb, GFP_ATOMIC); | 703 | rc = usb_submit_urb(port->read_urb, GFP_ATOMIC); |
704 | if (rc) | 704 | if (rc) |
705 | dev_err(&port->dev, | 705 | dev_err(&port->dev, |
706 | "%s - failed resubmitting read urb, error %d\n", | 706 | "%s - failed resubmitting read urb, error %d\n", |
707 | __func__, rc); | 707 | __func__, rc); |
708 | } /* klsi_105_read_bulk_callback */ | 708 | } /* klsi_105_read_bulk_callback */ |
709 | 709 | ||
710 | 710 | ||
711 | static void klsi_105_set_termios(struct tty_struct *tty, | 711 | static void klsi_105_set_termios(struct tty_struct *tty, |
712 | struct usb_serial_port *port, | 712 | struct usb_serial_port *port, |
713 | struct ktermios *old_termios) | 713 | struct ktermios *old_termios) |
714 | { | 714 | { |
715 | struct klsi_105_private *priv = usb_get_serial_port_data(port); | 715 | struct klsi_105_private *priv = usb_get_serial_port_data(port); |
716 | unsigned int iflag = tty->termios->c_iflag; | 716 | unsigned int iflag = tty->termios->c_iflag; |
717 | unsigned int old_iflag = old_termios->c_iflag; | 717 | unsigned int old_iflag = old_termios->c_iflag; |
718 | unsigned int cflag = tty->termios->c_cflag; | 718 | unsigned int cflag = tty->termios->c_cflag; |
719 | unsigned int old_cflag = old_termios->c_cflag; | 719 | unsigned int old_cflag = old_termios->c_cflag; |
720 | struct klsi_105_port_settings cfg; | 720 | struct klsi_105_port_settings cfg; |
721 | unsigned long flags; | 721 | unsigned long flags; |
722 | speed_t baud; | 722 | speed_t baud; |
723 | 723 | ||
724 | /* lock while we are modifying the settings */ | 724 | /* lock while we are modifying the settings */ |
725 | spin_lock_irqsave(&priv->lock, flags); | 725 | spin_lock_irqsave(&priv->lock, flags); |
726 | 726 | ||
727 | /* | 727 | /* |
728 | * Update baud rate | 728 | * Update baud rate |
729 | */ | 729 | */ |
730 | baud = tty_get_baud_rate(tty); | 730 | baud = tty_get_baud_rate(tty); |
731 | 731 | ||
732 | if ((cflag & CBAUD) != (old_cflag & CBAUD)) { | 732 | if ((cflag & CBAUD) != (old_cflag & CBAUD)) { |
733 | /* reassert DTR and (maybe) RTS on transition from B0 */ | 733 | /* reassert DTR and (maybe) RTS on transition from B0 */ |
734 | if ((old_cflag & CBAUD) == B0) { | 734 | if ((old_cflag & CBAUD) == B0) { |
735 | dbg("%s: baud was B0", __func__); | 735 | dbg("%s: baud was B0", __func__); |
736 | #if 0 | 736 | #if 0 |
737 | priv->control_state |= TIOCM_DTR; | 737 | priv->control_state |= TIOCM_DTR; |
738 | /* don't set RTS if using hardware flow control */ | 738 | /* don't set RTS if using hardware flow control */ |
739 | if (!(old_cflag & CRTSCTS)) | 739 | if (!(old_cflag & CRTSCTS)) |
740 | priv->control_state |= TIOCM_RTS; | 740 | priv->control_state |= TIOCM_RTS; |
741 | mct_u232_set_modem_ctrl(serial, priv->control_state); | 741 | mct_u232_set_modem_ctrl(serial, priv->control_state); |
742 | #endif | 742 | #endif |
743 | } | 743 | } |
744 | } | 744 | } |
745 | switch (baud) { | 745 | switch (baud) { |
746 | case 0: /* handled below */ | 746 | case 0: /* handled below */ |
747 | break; | 747 | break; |
748 | case 1200: | 748 | case 1200: |
749 | priv->cfg.baudrate = kl5kusb105a_sio_b1200; | 749 | priv->cfg.baudrate = kl5kusb105a_sio_b1200; |
750 | break; | 750 | break; |
751 | case 2400: | 751 | case 2400: |
752 | priv->cfg.baudrate = kl5kusb105a_sio_b2400; | 752 | priv->cfg.baudrate = kl5kusb105a_sio_b2400; |
753 | break; | 753 | break; |
754 | case 4800: | 754 | case 4800: |
755 | priv->cfg.baudrate = kl5kusb105a_sio_b4800; | 755 | priv->cfg.baudrate = kl5kusb105a_sio_b4800; |
756 | break; | 756 | break; |
757 | case 9600: | 757 | case 9600: |
758 | priv->cfg.baudrate = kl5kusb105a_sio_b9600; | 758 | priv->cfg.baudrate = kl5kusb105a_sio_b9600; |
759 | break; | 759 | break; |
760 | case 19200: | 760 | case 19200: |
761 | priv->cfg.baudrate = kl5kusb105a_sio_b19200; | 761 | priv->cfg.baudrate = kl5kusb105a_sio_b19200; |
762 | break; | 762 | break; |
763 | case 38400: | 763 | case 38400: |
764 | priv->cfg.baudrate = kl5kusb105a_sio_b38400; | 764 | priv->cfg.baudrate = kl5kusb105a_sio_b38400; |
765 | break; | 765 | break; |
766 | case 57600: | 766 | case 57600: |
767 | priv->cfg.baudrate = kl5kusb105a_sio_b57600; | 767 | priv->cfg.baudrate = kl5kusb105a_sio_b57600; |
768 | break; | 768 | break; |
769 | case 115200: | 769 | case 115200: |
770 | priv->cfg.baudrate = kl5kusb105a_sio_b115200; | 770 | priv->cfg.baudrate = kl5kusb105a_sio_b115200; |
771 | break; | 771 | break; |
772 | default: | 772 | default: |
773 | dbg("KLSI USB->Serial converter:" | 773 | dbg("KLSI USB->Serial converter:" |
774 | " unsupported baudrate request, using default of 9600"); | 774 | " unsupported baudrate request, using default of 9600"); |
775 | priv->cfg.baudrate = kl5kusb105a_sio_b9600; | 775 | priv->cfg.baudrate = kl5kusb105a_sio_b9600; |
776 | baud = 9600; | 776 | baud = 9600; |
777 | break; | 777 | break; |
778 | } | 778 | } |
779 | if ((cflag & CBAUD) == B0) { | 779 | if ((cflag & CBAUD) == B0) { |
780 | dbg("%s: baud is B0", __func__); | 780 | dbg("%s: baud is B0", __func__); |
781 | /* Drop RTS and DTR */ | 781 | /* Drop RTS and DTR */ |
782 | /* maybe this should be simulated by sending read | 782 | /* maybe this should be simulated by sending read |
783 | * disable and read enable messages? | 783 | * disable and read enable messages? |
784 | */ | 784 | */ |
785 | ; | 785 | ; |
786 | #if 0 | 786 | #if 0 |
787 | priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); | 787 | priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); |
788 | mct_u232_set_modem_ctrl(serial, priv->control_state); | 788 | mct_u232_set_modem_ctrl(serial, priv->control_state); |
789 | #endif | 789 | #endif |
790 | } | 790 | } |
791 | tty_encode_baud_rate(tty, baud, baud); | 791 | tty_encode_baud_rate(tty, baud, baud); |
792 | 792 | ||
793 | if ((cflag & CSIZE) != (old_cflag & CSIZE)) { | 793 | if ((cflag & CSIZE) != (old_cflag & CSIZE)) { |
794 | /* set the number of data bits */ | 794 | /* set the number of data bits */ |
795 | switch (cflag & CSIZE) { | 795 | switch (cflag & CSIZE) { |
796 | case CS5: | 796 | case CS5: |
797 | dbg("%s - 5 bits/byte not supported", __func__); | 797 | dbg("%s - 5 bits/byte not supported", __func__); |
798 | spin_unlock_irqrestore(&priv->lock, flags); | 798 | spin_unlock_irqrestore(&priv->lock, flags); |
799 | return ; | 799 | return ; |
800 | case CS6: | 800 | case CS6: |
801 | dbg("%s - 6 bits/byte not supported", __func__); | 801 | dbg("%s - 6 bits/byte not supported", __func__); |
802 | spin_unlock_irqrestore(&priv->lock, flags); | 802 | spin_unlock_irqrestore(&priv->lock, flags); |
803 | return ; | 803 | return ; |
804 | case CS7: | 804 | case CS7: |
805 | priv->cfg.databits = kl5kusb105a_dtb_7; | 805 | priv->cfg.databits = kl5kusb105a_dtb_7; |
806 | break; | 806 | break; |
807 | case CS8: | 807 | case CS8: |
808 | priv->cfg.databits = kl5kusb105a_dtb_8; | 808 | priv->cfg.databits = kl5kusb105a_dtb_8; |
809 | break; | 809 | break; |
810 | default: | 810 | default: |
811 | dev_err(&port->dev, | 811 | dev_err(&port->dev, |
812 | "CSIZE was not CS5-CS8, using default of 8\n"); | 812 | "CSIZE was not CS5-CS8, using default of 8\n"); |
813 | priv->cfg.databits = kl5kusb105a_dtb_8; | 813 | priv->cfg.databits = kl5kusb105a_dtb_8; |
814 | break; | 814 | break; |
815 | } | 815 | } |
816 | } | 816 | } |
817 | 817 | ||
818 | /* | 818 | /* |
819 | * Update line control register (LCR) | 819 | * Update line control register (LCR) |
820 | */ | 820 | */ |
821 | if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD)) | 821 | if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD)) |
822 | || (cflag & CSTOPB) != (old_cflag & CSTOPB)) { | 822 | || (cflag & CSTOPB) != (old_cflag & CSTOPB)) { |
823 | /* Not currently supported */ | 823 | /* Not currently supported */ |
824 | tty->termios->c_cflag &= ~(PARENB|PARODD|CSTOPB); | 824 | tty->termios->c_cflag &= ~(PARENB|PARODD|CSTOPB); |
825 | #if 0 | 825 | #if 0 |
826 | priv->last_lcr = 0; | 826 | priv->last_lcr = 0; |
827 | 827 | ||
828 | /* set the parity */ | 828 | /* set the parity */ |
829 | if (cflag & PARENB) | 829 | if (cflag & PARENB) |
830 | priv->last_lcr |= (cflag & PARODD) ? | 830 | priv->last_lcr |= (cflag & PARODD) ? |
831 | MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN; | 831 | MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN; |
832 | else | 832 | else |
833 | priv->last_lcr |= MCT_U232_PARITY_NONE; | 833 | priv->last_lcr |= MCT_U232_PARITY_NONE; |
834 | 834 | ||
835 | /* set the number of stop bits */ | 835 | /* set the number of stop bits */ |
836 | priv->last_lcr |= (cflag & CSTOPB) ? | 836 | priv->last_lcr |= (cflag & CSTOPB) ? |
837 | MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1; | 837 | MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1; |
838 | 838 | ||
839 | mct_u232_set_line_ctrl(serial, priv->last_lcr); | 839 | mct_u232_set_line_ctrl(serial, priv->last_lcr); |
840 | #endif | 840 | #endif |
841 | ; | 841 | ; |
842 | } | 842 | } |
843 | /* | 843 | /* |
844 | * Set flow control: well, I do not really now how to handle DTR/RTS. | 844 | * Set flow control: well, I do not really now how to handle DTR/RTS. |
845 | * Just do what we have seen with SniffUSB on Win98. | 845 | * Just do what we have seen with SniffUSB on Win98. |
846 | */ | 846 | */ |
847 | if ((iflag & IXOFF) != (old_iflag & IXOFF) | 847 | if ((iflag & IXOFF) != (old_iflag & IXOFF) |
848 | || (iflag & IXON) != (old_iflag & IXON) | 848 | || (iflag & IXON) != (old_iflag & IXON) |
849 | || (cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { | 849 | || (cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { |
850 | /* Not currently supported */ | 850 | /* Not currently supported */ |
851 | tty->termios->c_cflag &= ~CRTSCTS; | 851 | tty->termios->c_cflag &= ~CRTSCTS; |
852 | /* Drop DTR/RTS if no flow control otherwise assert */ | 852 | /* Drop DTR/RTS if no flow control otherwise assert */ |
853 | #if 0 | 853 | #if 0 |
854 | if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS)) | 854 | if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS)) |
855 | priv->control_state |= TIOCM_DTR | TIOCM_RTS; | 855 | priv->control_state |= TIOCM_DTR | TIOCM_RTS; |
856 | else | 856 | else |
857 | priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); | 857 | priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); |
858 | mct_u232_set_modem_ctrl(serial, priv->control_state); | 858 | mct_u232_set_modem_ctrl(serial, priv->control_state); |
859 | #endif | 859 | #endif |
860 | ; | 860 | ; |
861 | } | 861 | } |
862 | memcpy(&cfg, &priv->cfg, sizeof(cfg)); | 862 | memcpy(&cfg, &priv->cfg, sizeof(cfg)); |
863 | spin_unlock_irqrestore(&priv->lock, flags); | 863 | spin_unlock_irqrestore(&priv->lock, flags); |
864 | 864 | ||
865 | /* now commit changes to device */ | 865 | /* now commit changes to device */ |
866 | klsi_105_chg_port_settings(port, &cfg); | 866 | klsi_105_chg_port_settings(port, &cfg); |
867 | } /* klsi_105_set_termios */ | 867 | } /* klsi_105_set_termios */ |
868 | 868 | ||
869 | 869 | ||
870 | #if 0 | 870 | #if 0 |
871 | static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) | 871 | static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) |
872 | { | 872 | { |
873 | struct usb_serial_port *port = tty->driver_data; | 873 | struct usb_serial_port *port = tty->driver_data; |
874 | struct usb_serial *serial = port->serial; | 874 | struct usb_serial *serial = port->serial; |
875 | struct mct_u232_private *priv = | 875 | struct mct_u232_private *priv = |
876 | (struct mct_u232_private *)port->private; | 876 | (struct mct_u232_private *)port->private; |
877 | unsigned char lcr = priv->last_lcr; | 877 | unsigned char lcr = priv->last_lcr; |
878 | 878 | ||
879 | dbg("%sstate=%d", __func__, break_state); | 879 | dbg("%sstate=%d", __func__, break_state); |
880 | 880 | ||
881 | /* LOCKING */ | ||
881 | if (break_state) | 882 | if (break_state) |
882 | lcr |= MCT_U232_SET_BREAK; | 883 | lcr |= MCT_U232_SET_BREAK; |
883 | 884 | ||
884 | mct_u232_set_line_ctrl(serial, lcr); | 885 | mct_u232_set_line_ctrl(serial, lcr); |
885 | } /* mct_u232_break_ctl */ | 886 | } /* mct_u232_break_ctl */ |
886 | #endif | 887 | #endif |
887 | 888 | ||
888 | static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file) | 889 | static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file) |
889 | { | 890 | { |
890 | struct usb_serial_port *port = tty->driver_data; | 891 | struct usb_serial_port *port = tty->driver_data; |
891 | struct klsi_105_private *priv = usb_get_serial_port_data(port); | 892 | struct klsi_105_private *priv = usb_get_serial_port_data(port); |
892 | unsigned long flags; | 893 | unsigned long flags; |
893 | int rc; | 894 | int rc; |
894 | unsigned long line_state; | 895 | unsigned long line_state; |
895 | dbg("%s - request, just guessing", __func__); | 896 | dbg("%s - request, just guessing", __func__); |
896 | 897 | ||
897 | rc = klsi_105_get_line_state(port, &line_state); | 898 | rc = klsi_105_get_line_state(port, &line_state); |
898 | if (rc < 0) { | 899 | if (rc < 0) { |
899 | dev_err(&port->dev, | 900 | dev_err(&port->dev, |
900 | "Reading line control failed (error = %d)\n", rc); | 901 | "Reading line control failed (error = %d)\n", rc); |
901 | /* better return value? EAGAIN? */ | 902 | /* better return value? EAGAIN? */ |
902 | return rc; | 903 | return rc; |
903 | } | 904 | } |
904 | 905 | ||
905 | spin_lock_irqsave(&priv->lock, flags); | 906 | spin_lock_irqsave(&priv->lock, flags); |
906 | priv->line_state = line_state; | 907 | priv->line_state = line_state; |
907 | spin_unlock_irqrestore(&priv->lock, flags); | 908 | spin_unlock_irqrestore(&priv->lock, flags); |
908 | dbg("%s - read line state 0x%lx", __func__, line_state); | 909 | dbg("%s - read line state 0x%lx", __func__, line_state); |
909 | return (int)line_state; | 910 | return (int)line_state; |
910 | } | 911 | } |
911 | 912 | ||
912 | static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file, | 913 | static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file, |
913 | unsigned int set, unsigned int clear) | 914 | unsigned int set, unsigned int clear) |
914 | { | 915 | { |
915 | int retval = -EINVAL; | 916 | int retval = -EINVAL; |
916 | 917 | ||
917 | dbg("%s", __func__); | 918 | dbg("%s", __func__); |
918 | 919 | ||
919 | /* if this ever gets implemented, it should be done something like this: | 920 | /* if this ever gets implemented, it should be done something like this: |
920 | struct usb_serial *serial = port->serial; | 921 | struct usb_serial *serial = port->serial; |
921 | struct klsi_105_private *priv = usb_get_serial_port_data(port); | 922 | struct klsi_105_private *priv = usb_get_serial_port_data(port); |
922 | unsigned long flags; | 923 | unsigned long flags; |
923 | int control; | 924 | int control; |
924 | 925 | ||
925 | spin_lock_irqsave (&priv->lock, flags); | 926 | spin_lock_irqsave (&priv->lock, flags); |
926 | if (set & TIOCM_RTS) | 927 | if (set & TIOCM_RTS) |
927 | priv->control_state |= TIOCM_RTS; | 928 | priv->control_state |= TIOCM_RTS; |
928 | if (set & TIOCM_DTR) | 929 | if (set & TIOCM_DTR) |
929 | priv->control_state |= TIOCM_DTR; | 930 | priv->control_state |= TIOCM_DTR; |
930 | if (clear & TIOCM_RTS) | 931 | if (clear & TIOCM_RTS) |
931 | priv->control_state &= ~TIOCM_RTS; | 932 | priv->control_state &= ~TIOCM_RTS; |
932 | if (clear & TIOCM_DTR) | 933 | if (clear & TIOCM_DTR) |
933 | priv->control_state &= ~TIOCM_DTR; | 934 | priv->control_state &= ~TIOCM_DTR; |
934 | control = priv->control_state; | 935 | control = priv->control_state; |
935 | spin_unlock_irqrestore (&priv->lock, flags); | 936 | spin_unlock_irqrestore (&priv->lock, flags); |
936 | retval = mct_u232_set_modem_ctrl(serial, control); | 937 | retval = mct_u232_set_modem_ctrl(serial, control); |
937 | */ | 938 | */ |
938 | return retval; | 939 | return retval; |
939 | } | 940 | } |
940 | 941 | ||
941 | static void klsi_105_throttle(struct tty_struct *tty) | 942 | static void klsi_105_throttle(struct tty_struct *tty) |
942 | { | 943 | { |
943 | struct usb_serial_port *port = tty->driver_data; | 944 | struct usb_serial_port *port = tty->driver_data; |
944 | dbg("%s - port %d", __func__, port->number); | 945 | dbg("%s - port %d", __func__, port->number); |
945 | usb_kill_urb(port->read_urb); | 946 | usb_kill_urb(port->read_urb); |
946 | } | 947 | } |
947 | 948 | ||
948 | static void klsi_105_unthrottle(struct tty_struct *tty) | 949 | static void klsi_105_unthrottle(struct tty_struct *tty) |
949 | { | 950 | { |
950 | struct usb_serial_port *port = tty->driver_data; | 951 | struct usb_serial_port *port = tty->driver_data; |
951 | int result; | 952 | int result; |
952 | 953 | ||
953 | dbg("%s - port %d", __func__, port->number); | 954 | dbg("%s - port %d", __func__, port->number); |
954 | 955 | ||
955 | port->read_urb->dev = port->serial->dev; | 956 | port->read_urb->dev = port->serial->dev; |
956 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | 957 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); |
957 | if (result) | 958 | if (result) |
958 | dev_err(&port->dev, | 959 | dev_err(&port->dev, |
959 | "%s - failed submitting read urb, error %d\n", | 960 | "%s - failed submitting read urb, error %d\n", |
960 | __func__, result); | 961 | __func__, result); |
961 | } | 962 | } |
962 | 963 | ||
963 | 964 | ||
964 | 965 | ||
965 | static int __init klsi_105_init(void) | 966 | static int __init klsi_105_init(void) |
966 | { | 967 | { |
967 | int retval; | 968 | int retval; |
968 | retval = usb_serial_register(&kl5kusb105d_device); | 969 | retval = usb_serial_register(&kl5kusb105d_device); |
969 | if (retval) | 970 | if (retval) |
970 | goto failed_usb_serial_register; | 971 | goto failed_usb_serial_register; |
971 | retval = usb_register(&kl5kusb105d_driver); | 972 | retval = usb_register(&kl5kusb105d_driver); |
972 | if (retval) | 973 | if (retval) |
973 | goto failed_usb_register; | 974 | goto failed_usb_register; |
974 | 975 | ||
975 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | 976 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" |
976 | DRIVER_DESC "\n"); | 977 | DRIVER_DESC "\n"); |
977 | return 0; | 978 | return 0; |
978 | failed_usb_register: | 979 | failed_usb_register: |
979 | usb_serial_deregister(&kl5kusb105d_device); | 980 | usb_serial_deregister(&kl5kusb105d_device); |
980 | failed_usb_serial_register: | 981 | failed_usb_serial_register: |
981 | return retval; | 982 | return retval; |
982 | } | 983 | } |
983 | 984 | ||
984 | 985 | ||
985 | static void __exit klsi_105_exit(void) | 986 | static void __exit klsi_105_exit(void) |
986 | { | 987 | { |
987 | usb_deregister(&kl5kusb105d_driver); | 988 | usb_deregister(&kl5kusb105d_driver); |
988 | usb_serial_deregister(&kl5kusb105d_device); | 989 | usb_serial_deregister(&kl5kusb105d_device); |
989 | } | 990 | } |
990 | 991 | ||
991 | 992 | ||
992 | module_init(klsi_105_init); | 993 | module_init(klsi_105_init); |
993 | module_exit(klsi_105_exit); | 994 | module_exit(klsi_105_exit); |
994 | 995 | ||
995 | MODULE_AUTHOR(DRIVER_AUTHOR); | 996 | MODULE_AUTHOR(DRIVER_AUTHOR); |
996 | MODULE_DESCRIPTION(DRIVER_DESC); | 997 | MODULE_DESCRIPTION(DRIVER_DESC); |
997 | MODULE_LICENSE("GPL"); | 998 | MODULE_LICENSE("GPL"); |
998 | 999 | ||
999 | 1000 | ||
1000 | module_param(debug, bool, S_IRUGO | S_IWUSR); | 1001 | module_param(debug, bool, S_IRUGO | S_IWUSR); |
1001 | MODULE_PARM_DESC(debug, "enable extensive debugging messages"); | 1002 | MODULE_PARM_DESC(debug, "enable extensive debugging messages"); |
1002 | 1003 | ||
1003 | /* vim: set sts=8 ts=8 sw=8: */ | 1004 | /* vim: set sts=8 ts=8 sw=8: */ |
1004 | 1005 |
drivers/usb/serial/mct_u232.c
1 | /* | 1 | /* |
2 | * MCT (Magic Control Technology Corp.) USB RS232 Converter Driver | 2 | * MCT (Magic Control Technology Corp.) USB RS232 Converter Driver |
3 | * | 3 | * |
4 | * Copyright (C) 2000 Wolfgang Grandegger (wolfgang@ces.ch) | 4 | * Copyright (C) 2000 Wolfgang Grandegger (wolfgang@ces.ch) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation; either version 2 of the License, or | 8 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. | 9 | * (at your option) any later version. |
10 | * | 10 | * |
11 | * This program is largely derived from the Belkin USB Serial Adapter Driver | 11 | * This program is largely derived from the Belkin USB Serial Adapter Driver |
12 | * (see belkin_sa.[ch]). All of the information about the device was acquired | 12 | * (see belkin_sa.[ch]). All of the information about the device was acquired |
13 | * by using SniffUSB on Windows98. For technical details see mct_u232.h. | 13 | * by using SniffUSB on Windows98. For technical details see mct_u232.h. |
14 | * | 14 | * |
15 | * William G. Greathouse and Greg Kroah-Hartman provided great help on how to | 15 | * William G. Greathouse and Greg Kroah-Hartman provided great help on how to |
16 | * do the reverse engineering and how to write a USB serial device driver. | 16 | * do the reverse engineering and how to write a USB serial device driver. |
17 | * | 17 | * |
18 | * TO BE DONE, TO BE CHECKED: | 18 | * TO BE DONE, TO BE CHECKED: |
19 | * DTR/RTS signal handling may be incomplete or incorrect. I have mainly | 19 | * DTR/RTS signal handling may be incomplete or incorrect. I have mainly |
20 | * implemented what I have seen with SniffUSB or found in belkin_sa.c. | 20 | * implemented what I have seen with SniffUSB or found in belkin_sa.c. |
21 | * For further TODOs check also belkin_sa.c. | 21 | * For further TODOs check also belkin_sa.c. |
22 | * | 22 | * |
23 | * TEST STATUS: | 23 | * TEST STATUS: |
24 | * Basic tests have been performed with minicom/zmodem transfers and | 24 | * Basic tests have been performed with minicom/zmodem transfers and |
25 | * modem dialing under Linux 2.4.0-test10 (for me it works fine). | 25 | * modem dialing under Linux 2.4.0-test10 (for me it works fine). |
26 | * | 26 | * |
27 | * 04-Nov-2003 Bill Marr <marr at flex dot com> | 27 | * 04-Nov-2003 Bill Marr <marr at flex dot com> |
28 | * - Mimic Windows driver by sending 2 USB 'device request' messages | 28 | * - Mimic Windows driver by sending 2 USB 'device request' messages |
29 | * following normal 'baud rate change' message. This allows data to be | 29 | * following normal 'baud rate change' message. This allows data to be |
30 | * transmitted to RS-232 devices which don't assert the 'CTS' signal. | 30 | * transmitted to RS-232 devices which don't assert the 'CTS' signal. |
31 | * | 31 | * |
32 | * 10-Nov-2001 Wolfgang Grandegger | 32 | * 10-Nov-2001 Wolfgang Grandegger |
33 | * - Fixed an endianess problem with the baudrate selection for PowerPC. | 33 | * - Fixed an endianess problem with the baudrate selection for PowerPC. |
34 | * | 34 | * |
35 | * 06-Dec-2001 Martin Hamilton <martinh@gnu.org> | 35 | * 06-Dec-2001 Martin Hamilton <martinh@gnu.org> |
36 | * - Added support for the Belkin F5U109 DB9 adaptor | 36 | * - Added support for the Belkin F5U109 DB9 adaptor |
37 | * | 37 | * |
38 | * 30-May-2001 Greg Kroah-Hartman | 38 | * 30-May-2001 Greg Kroah-Hartman |
39 | * - switched from using spinlock to a semaphore, which fixes lots of | 39 | * - switched from using spinlock to a semaphore, which fixes lots of |
40 | * problems. | 40 | * problems. |
41 | * | 41 | * |
42 | * 04-May-2001 Stelian Pop | 42 | * 04-May-2001 Stelian Pop |
43 | * - Set the maximum bulk output size for Sitecom U232-P25 model to 16 bytes | 43 | * - Set the maximum bulk output size for Sitecom U232-P25 model to 16 bytes |
44 | * instead of the device reported 32 (using 32 bytes causes many data | 44 | * instead of the device reported 32 (using 32 bytes causes many data |
45 | * loss, Windows driver uses 16 too). | 45 | * loss, Windows driver uses 16 too). |
46 | * | 46 | * |
47 | * 02-May-2001 Stelian Pop | 47 | * 02-May-2001 Stelian Pop |
48 | * - Fixed the baud calculation for Sitecom U232-P25 model | 48 | * - Fixed the baud calculation for Sitecom U232-P25 model |
49 | * | 49 | * |
50 | * 08-Apr-2001 gb | 50 | * 08-Apr-2001 gb |
51 | * - Identify version on module load. | 51 | * - Identify version on module load. |
52 | * | 52 | * |
53 | * 06-Jan-2001 Cornel Ciocirlan | 53 | * 06-Jan-2001 Cornel Ciocirlan |
54 | * - Added support for Sitecom U232-P25 model (Product Id 0x0230) | 54 | * - Added support for Sitecom U232-P25 model (Product Id 0x0230) |
55 | * - Added support for D-Link DU-H3SP USB BAY (Product Id 0x0200) | 55 | * - Added support for D-Link DU-H3SP USB BAY (Product Id 0x0200) |
56 | * | 56 | * |
57 | * 29-Nov-2000 Greg Kroah-Hartman | 57 | * 29-Nov-2000 Greg Kroah-Hartman |
58 | * - Added device id table to fit with 2.4.0-test11 structure. | 58 | * - Added device id table to fit with 2.4.0-test11 structure. |
59 | * - took out DEAL_WITH_TWO_INT_IN_ENDPOINTS #define as it's not needed | 59 | * - took out DEAL_WITH_TWO_INT_IN_ENDPOINTS #define as it's not needed |
60 | * (lots of things will change if/when the usb-serial core changes to | 60 | * (lots of things will change if/when the usb-serial core changes to |
61 | * handle these issues. | 61 | * handle these issues. |
62 | * | 62 | * |
63 | * 27-Nov-2000 Wolfgang Grandegge | 63 | * 27-Nov-2000 Wolfgang Grandegge |
64 | * A version for kernel 2.4.0-test10 released to the Linux community | 64 | * A version for kernel 2.4.0-test10 released to the Linux community |
65 | * (via linux-usb-devel). | 65 | * (via linux-usb-devel). |
66 | */ | 66 | */ |
67 | 67 | ||
68 | #include <linux/kernel.h> | 68 | #include <linux/kernel.h> |
69 | #include <linux/errno.h> | 69 | #include <linux/errno.h> |
70 | #include <linux/init.h> | 70 | #include <linux/init.h> |
71 | #include <linux/slab.h> | 71 | #include <linux/slab.h> |
72 | #include <linux/tty.h> | 72 | #include <linux/tty.h> |
73 | #include <linux/tty_driver.h> | 73 | #include <linux/tty_driver.h> |
74 | #include <linux/tty_flip.h> | 74 | #include <linux/tty_flip.h> |
75 | #include <linux/module.h> | 75 | #include <linux/module.h> |
76 | #include <linux/spinlock.h> | 76 | #include <linux/spinlock.h> |
77 | #include <linux/uaccess.h> | 77 | #include <linux/uaccess.h> |
78 | #include <linux/usb.h> | 78 | #include <linux/usb.h> |
79 | #include <linux/usb/serial.h> | 79 | #include <linux/usb/serial.h> |
80 | #include "mct_u232.h" | 80 | #include "mct_u232.h" |
81 | 81 | ||
82 | /* | 82 | /* |
83 | * Version Information | 83 | * Version Information |
84 | */ | 84 | */ |
85 | #define DRIVER_VERSION "z2.1" /* Linux in-kernel version */ | 85 | #define DRIVER_VERSION "z2.1" /* Linux in-kernel version */ |
86 | #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>" | 86 | #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>" |
87 | #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver" | 87 | #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver" |
88 | 88 | ||
89 | static int debug; | 89 | static int debug; |
90 | 90 | ||
91 | /* | 91 | /* |
92 | * Function prototypes | 92 | * Function prototypes |
93 | */ | 93 | */ |
94 | static int mct_u232_startup(struct usb_serial *serial); | 94 | static int mct_u232_startup(struct usb_serial *serial); |
95 | static void mct_u232_shutdown(struct usb_serial *serial); | 95 | static void mct_u232_shutdown(struct usb_serial *serial); |
96 | static int mct_u232_open(struct tty_struct *tty, | 96 | static int mct_u232_open(struct tty_struct *tty, |
97 | struct usb_serial_port *port, struct file *filp); | 97 | struct usb_serial_port *port, struct file *filp); |
98 | static void mct_u232_close(struct tty_struct *tty, | 98 | static void mct_u232_close(struct tty_struct *tty, |
99 | struct usb_serial_port *port, struct file *filp); | 99 | struct usb_serial_port *port, struct file *filp); |
100 | static void mct_u232_read_int_callback(struct urb *urb); | 100 | static void mct_u232_read_int_callback(struct urb *urb); |
101 | static void mct_u232_set_termios(struct tty_struct *tty, | 101 | static void mct_u232_set_termios(struct tty_struct *tty, |
102 | struct usb_serial_port *port, struct ktermios *old); | 102 | struct usb_serial_port *port, struct ktermios *old); |
103 | static void mct_u232_break_ctl(struct tty_struct *tty, int break_state); | 103 | static void mct_u232_break_ctl(struct tty_struct *tty, int break_state); |
104 | static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file); | 104 | static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file); |
105 | static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file, | 105 | static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file, |
106 | unsigned int set, unsigned int clear); | 106 | unsigned int set, unsigned int clear); |
107 | static void mct_u232_throttle(struct tty_struct *tty); | 107 | static void mct_u232_throttle(struct tty_struct *tty); |
108 | static void mct_u232_unthrottle(struct tty_struct *tty); | 108 | static void mct_u232_unthrottle(struct tty_struct *tty); |
109 | 109 | ||
110 | 110 | ||
111 | /* | 111 | /* |
112 | * All of the device info needed for the MCT USB-RS232 converter. | 112 | * All of the device info needed for the MCT USB-RS232 converter. |
113 | */ | 113 | */ |
114 | static struct usb_device_id id_table_combined [] = { | 114 | static struct usb_device_id id_table_combined [] = { |
115 | { USB_DEVICE(MCT_U232_VID, MCT_U232_PID) }, | 115 | { USB_DEVICE(MCT_U232_VID, MCT_U232_PID) }, |
116 | { USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) }, | 116 | { USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) }, |
117 | { USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) }, | 117 | { USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) }, |
118 | { USB_DEVICE(MCT_U232_BELKIN_F5U109_VID, MCT_U232_BELKIN_F5U109_PID) }, | 118 | { USB_DEVICE(MCT_U232_BELKIN_F5U109_VID, MCT_U232_BELKIN_F5U109_PID) }, |
119 | { } /* Terminating entry */ | 119 | { } /* Terminating entry */ |
120 | }; | 120 | }; |
121 | 121 | ||
122 | MODULE_DEVICE_TABLE(usb, id_table_combined); | 122 | MODULE_DEVICE_TABLE(usb, id_table_combined); |
123 | 123 | ||
124 | static struct usb_driver mct_u232_driver = { | 124 | static struct usb_driver mct_u232_driver = { |
125 | .name = "mct_u232", | 125 | .name = "mct_u232", |
126 | .probe = usb_serial_probe, | 126 | .probe = usb_serial_probe, |
127 | .disconnect = usb_serial_disconnect, | 127 | .disconnect = usb_serial_disconnect, |
128 | .id_table = id_table_combined, | 128 | .id_table = id_table_combined, |
129 | .no_dynamic_id = 1, | 129 | .no_dynamic_id = 1, |
130 | }; | 130 | }; |
131 | 131 | ||
132 | static struct usb_serial_driver mct_u232_device = { | 132 | static struct usb_serial_driver mct_u232_device = { |
133 | .driver = { | 133 | .driver = { |
134 | .owner = THIS_MODULE, | 134 | .owner = THIS_MODULE, |
135 | .name = "mct_u232", | 135 | .name = "mct_u232", |
136 | }, | 136 | }, |
137 | .description = "MCT U232", | 137 | .description = "MCT U232", |
138 | .usb_driver = &mct_u232_driver, | 138 | .usb_driver = &mct_u232_driver, |
139 | .id_table = id_table_combined, | 139 | .id_table = id_table_combined, |
140 | .num_ports = 1, | 140 | .num_ports = 1, |
141 | .open = mct_u232_open, | 141 | .open = mct_u232_open, |
142 | .close = mct_u232_close, | 142 | .close = mct_u232_close, |
143 | .throttle = mct_u232_throttle, | 143 | .throttle = mct_u232_throttle, |
144 | .unthrottle = mct_u232_unthrottle, | 144 | .unthrottle = mct_u232_unthrottle, |
145 | .read_int_callback = mct_u232_read_int_callback, | 145 | .read_int_callback = mct_u232_read_int_callback, |
146 | .set_termios = mct_u232_set_termios, | 146 | .set_termios = mct_u232_set_termios, |
147 | .break_ctl = mct_u232_break_ctl, | 147 | .break_ctl = mct_u232_break_ctl, |
148 | .tiocmget = mct_u232_tiocmget, | 148 | .tiocmget = mct_u232_tiocmget, |
149 | .tiocmset = mct_u232_tiocmset, | 149 | .tiocmset = mct_u232_tiocmset, |
150 | .attach = mct_u232_startup, | 150 | .attach = mct_u232_startup, |
151 | .shutdown = mct_u232_shutdown, | 151 | .shutdown = mct_u232_shutdown, |
152 | }; | 152 | }; |
153 | 153 | ||
154 | 154 | ||
155 | struct mct_u232_private { | 155 | struct mct_u232_private { |
156 | spinlock_t lock; | 156 | spinlock_t lock; |
157 | unsigned int control_state; /* Modem Line Setting (TIOCM) */ | 157 | unsigned int control_state; /* Modem Line Setting (TIOCM) */ |
158 | unsigned char last_lcr; /* Line Control Register */ | 158 | unsigned char last_lcr; /* Line Control Register */ |
159 | unsigned char last_lsr; /* Line Status Register */ | 159 | unsigned char last_lsr; /* Line Status Register */ |
160 | unsigned char last_msr; /* Modem Status Register */ | 160 | unsigned char last_msr; /* Modem Status Register */ |
161 | unsigned int rx_flags; /* Throttling flags */ | 161 | unsigned int rx_flags; /* Throttling flags */ |
162 | }; | 162 | }; |
163 | 163 | ||
164 | #define THROTTLED 0x01 | 164 | #define THROTTLED 0x01 |
165 | 165 | ||
166 | /* | 166 | /* |
167 | * Handle vendor specific USB requests | 167 | * Handle vendor specific USB requests |
168 | */ | 168 | */ |
169 | 169 | ||
170 | #define WDR_TIMEOUT 5000 /* default urb timeout */ | 170 | #define WDR_TIMEOUT 5000 /* default urb timeout */ |
171 | 171 | ||
172 | /* | 172 | /* |
173 | * Later day 2.6.0-test kernels have new baud rates like B230400 which | 173 | * Later day 2.6.0-test kernels have new baud rates like B230400 which |
174 | * we do not know how to support. We ignore them for the moment. | 174 | * we do not know how to support. We ignore them for the moment. |
175 | */ | 175 | */ |
176 | static int mct_u232_calculate_baud_rate(struct usb_serial *serial, | 176 | static int mct_u232_calculate_baud_rate(struct usb_serial *serial, |
177 | speed_t value, speed_t *result) | 177 | speed_t value, speed_t *result) |
178 | { | 178 | { |
179 | *result = value; | 179 | *result = value; |
180 | 180 | ||
181 | if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID | 181 | if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID |
182 | || le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) { | 182 | || le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) { |
183 | switch (value) { | 183 | switch (value) { |
184 | case 300: | 184 | case 300: |
185 | return 0x01; | 185 | return 0x01; |
186 | case 600: | 186 | case 600: |
187 | return 0x02; /* this one not tested */ | 187 | return 0x02; /* this one not tested */ |
188 | case 1200: | 188 | case 1200: |
189 | return 0x03; | 189 | return 0x03; |
190 | case 2400: | 190 | case 2400: |
191 | return 0x04; | 191 | return 0x04; |
192 | case 4800: | 192 | case 4800: |
193 | return 0x06; | 193 | return 0x06; |
194 | case 9600: | 194 | case 9600: |
195 | return 0x08; | 195 | return 0x08; |
196 | case 19200: | 196 | case 19200: |
197 | return 0x09; | 197 | return 0x09; |
198 | case 38400: | 198 | case 38400: |
199 | return 0x0a; | 199 | return 0x0a; |
200 | case 57600: | 200 | case 57600: |
201 | return 0x0b; | 201 | return 0x0b; |
202 | case 115200: | 202 | case 115200: |
203 | return 0x0c; | 203 | return 0x0c; |
204 | default: | 204 | default: |
205 | *result = 9600; | 205 | *result = 9600; |
206 | return 0x08; | 206 | return 0x08; |
207 | } | 207 | } |
208 | } else { | 208 | } else { |
209 | /* FIXME: Can we use any divider - should we do | 209 | /* FIXME: Can we use any divider - should we do |
210 | divider = 115200/value; | 210 | divider = 115200/value; |
211 | real baud = 115200/divider */ | 211 | real baud = 115200/divider */ |
212 | switch (value) { | 212 | switch (value) { |
213 | case 300: break; | 213 | case 300: break; |
214 | case 600: break; | 214 | case 600: break; |
215 | case 1200: break; | 215 | case 1200: break; |
216 | case 2400: break; | 216 | case 2400: break; |
217 | case 4800: break; | 217 | case 4800: break; |
218 | case 9600: break; | 218 | case 9600: break; |
219 | case 19200: break; | 219 | case 19200: break; |
220 | case 38400: break; | 220 | case 38400: break; |
221 | case 57600: break; | 221 | case 57600: break; |
222 | case 115200: break; | 222 | case 115200: break; |
223 | default: | 223 | default: |
224 | value = 9600; | 224 | value = 9600; |
225 | *result = 9600; | 225 | *result = 9600; |
226 | } | 226 | } |
227 | return 115200/value; | 227 | return 115200/value; |
228 | } | 228 | } |
229 | } | 229 | } |
230 | 230 | ||
231 | static int mct_u232_set_baud_rate(struct tty_struct *tty, | 231 | static int mct_u232_set_baud_rate(struct tty_struct *tty, |
232 | struct usb_serial *serial, struct usb_serial_port *port, speed_t value) | 232 | struct usb_serial *serial, struct usb_serial_port *port, speed_t value) |
233 | { | 233 | { |
234 | __le32 divisor; | 234 | __le32 divisor; |
235 | int rc; | 235 | int rc; |
236 | unsigned char zero_byte = 0; | 236 | unsigned char zero_byte = 0; |
237 | unsigned char cts_enable_byte = 0; | 237 | unsigned char cts_enable_byte = 0; |
238 | speed_t speed; | 238 | speed_t speed; |
239 | 239 | ||
240 | divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value, | 240 | divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value, |
241 | &speed)); | 241 | &speed)); |
242 | 242 | ||
243 | rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | 243 | rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), |
244 | MCT_U232_SET_BAUD_RATE_REQUEST, | 244 | MCT_U232_SET_BAUD_RATE_REQUEST, |
245 | MCT_U232_SET_REQUEST_TYPE, | 245 | MCT_U232_SET_REQUEST_TYPE, |
246 | 0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE, | 246 | 0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE, |
247 | WDR_TIMEOUT); | 247 | WDR_TIMEOUT); |
248 | if (rc < 0) /*FIXME: What value speed results */ | 248 | if (rc < 0) /*FIXME: What value speed results */ |
249 | dev_err(&port->dev, "Set BAUD RATE %d failed (error = %d)\n", | 249 | dev_err(&port->dev, "Set BAUD RATE %d failed (error = %d)\n", |
250 | value, rc); | 250 | value, rc); |
251 | else | 251 | else |
252 | tty_encode_baud_rate(tty, speed, speed); | 252 | tty_encode_baud_rate(tty, speed, speed); |
253 | dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor); | 253 | dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor); |
254 | 254 | ||
255 | /* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which | 255 | /* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which |
256 | always sends two extra USB 'device request' messages after the | 256 | always sends two extra USB 'device request' messages after the |
257 | 'baud rate change' message. The actual functionality of the | 257 | 'baud rate change' message. The actual functionality of the |
258 | request codes in these messages is not fully understood but these | 258 | request codes in these messages is not fully understood but these |
259 | particular codes are never seen in any operation besides a baud | 259 | particular codes are never seen in any operation besides a baud |
260 | rate change. Both of these messages send a single byte of data. | 260 | rate change. Both of these messages send a single byte of data. |
261 | In the first message, the value of this byte is always zero. | 261 | In the first message, the value of this byte is always zero. |
262 | 262 | ||
263 | The second message has been determined experimentally to control | 263 | The second message has been determined experimentally to control |
264 | whether data will be transmitted to a device which is not asserting | 264 | whether data will be transmitted to a device which is not asserting |
265 | the 'CTS' signal. If the second message's data byte is zero, data | 265 | the 'CTS' signal. If the second message's data byte is zero, data |
266 | will be transmitted even if 'CTS' is not asserted (i.e. no hardware | 266 | will be transmitted even if 'CTS' is not asserted (i.e. no hardware |
267 | flow control). if the second message's data byte is nonzero (a | 267 | flow control). if the second message's data byte is nonzero (a |
268 | value of 1 is used by this driver), data will not be transmitted to | 268 | value of 1 is used by this driver), data will not be transmitted to |
269 | a device which is not asserting 'CTS'. | 269 | a device which is not asserting 'CTS'. |
270 | */ | 270 | */ |
271 | 271 | ||
272 | rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | 272 | rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), |
273 | MCT_U232_SET_UNKNOWN1_REQUEST, | 273 | MCT_U232_SET_UNKNOWN1_REQUEST, |
274 | MCT_U232_SET_REQUEST_TYPE, | 274 | MCT_U232_SET_REQUEST_TYPE, |
275 | 0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE, | 275 | 0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE, |
276 | WDR_TIMEOUT); | 276 | WDR_TIMEOUT); |
277 | if (rc < 0) | 277 | if (rc < 0) |
278 | dev_err(&port->dev, "Sending USB device request code %d " | 278 | dev_err(&port->dev, "Sending USB device request code %d " |
279 | "failed (error = %d)\n", MCT_U232_SET_UNKNOWN1_REQUEST, | 279 | "failed (error = %d)\n", MCT_U232_SET_UNKNOWN1_REQUEST, |
280 | rc); | 280 | rc); |
281 | 281 | ||
282 | if (port && C_CRTSCTS(tty)) | 282 | if (port && C_CRTSCTS(tty)) |
283 | cts_enable_byte = 1; | 283 | cts_enable_byte = 1; |
284 | 284 | ||
285 | dbg("set_baud_rate: send second control message, data = %02X", | 285 | dbg("set_baud_rate: send second control message, data = %02X", |
286 | cts_enable_byte); | 286 | cts_enable_byte); |
287 | rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | 287 | rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), |
288 | MCT_U232_SET_CTS_REQUEST, | 288 | MCT_U232_SET_CTS_REQUEST, |
289 | MCT_U232_SET_REQUEST_TYPE, | 289 | MCT_U232_SET_REQUEST_TYPE, |
290 | 0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE, | 290 | 0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE, |
291 | WDR_TIMEOUT); | 291 | WDR_TIMEOUT); |
292 | if (rc < 0) | 292 | if (rc < 0) |
293 | dev_err(&port->dev, "Sending USB device request code %d " | 293 | dev_err(&port->dev, "Sending USB device request code %d " |
294 | "failed (error = %d)\n", MCT_U232_SET_CTS_REQUEST, rc); | 294 | "failed (error = %d)\n", MCT_U232_SET_CTS_REQUEST, rc); |
295 | 295 | ||
296 | return rc; | 296 | return rc; |
297 | } /* mct_u232_set_baud_rate */ | 297 | } /* mct_u232_set_baud_rate */ |
298 | 298 | ||
299 | static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr) | 299 | static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr) |
300 | { | 300 | { |
301 | int rc; | 301 | int rc; |
302 | rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | 302 | rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), |
303 | MCT_U232_SET_LINE_CTRL_REQUEST, | 303 | MCT_U232_SET_LINE_CTRL_REQUEST, |
304 | MCT_U232_SET_REQUEST_TYPE, | 304 | MCT_U232_SET_REQUEST_TYPE, |
305 | 0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE, | 305 | 0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE, |
306 | WDR_TIMEOUT); | 306 | WDR_TIMEOUT); |
307 | if (rc < 0) | 307 | if (rc < 0) |
308 | dev_err(&serial->dev->dev, | 308 | dev_err(&serial->dev->dev, |
309 | "Set LINE CTRL 0x%x failed (error = %d)\n", lcr, rc); | 309 | "Set LINE CTRL 0x%x failed (error = %d)\n", lcr, rc); |
310 | dbg("set_line_ctrl: 0x%x", lcr); | 310 | dbg("set_line_ctrl: 0x%x", lcr); |
311 | return rc; | 311 | return rc; |
312 | } /* mct_u232_set_line_ctrl */ | 312 | } /* mct_u232_set_line_ctrl */ |
313 | 313 | ||
314 | static int mct_u232_set_modem_ctrl(struct usb_serial *serial, | 314 | static int mct_u232_set_modem_ctrl(struct usb_serial *serial, |
315 | unsigned int control_state) | 315 | unsigned int control_state) |
316 | { | 316 | { |
317 | int rc; | 317 | int rc; |
318 | unsigned char mcr = MCT_U232_MCR_NONE; | 318 | unsigned char mcr = MCT_U232_MCR_NONE; |
319 | 319 | ||
320 | if (control_state & TIOCM_DTR) | 320 | if (control_state & TIOCM_DTR) |
321 | mcr |= MCT_U232_MCR_DTR; | 321 | mcr |= MCT_U232_MCR_DTR; |
322 | if (control_state & TIOCM_RTS) | 322 | if (control_state & TIOCM_RTS) |
323 | mcr |= MCT_U232_MCR_RTS; | 323 | mcr |= MCT_U232_MCR_RTS; |
324 | 324 | ||
325 | rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | 325 | rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), |
326 | MCT_U232_SET_MODEM_CTRL_REQUEST, | 326 | MCT_U232_SET_MODEM_CTRL_REQUEST, |
327 | MCT_U232_SET_REQUEST_TYPE, | 327 | MCT_U232_SET_REQUEST_TYPE, |
328 | 0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE, | 328 | 0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE, |
329 | WDR_TIMEOUT); | 329 | WDR_TIMEOUT); |
330 | if (rc < 0) | 330 | if (rc < 0) |
331 | dev_err(&serial->dev->dev, | 331 | dev_err(&serial->dev->dev, |
332 | "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc); | 332 | "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc); |
333 | dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr); | 333 | dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr); |
334 | 334 | ||
335 | return rc; | 335 | return rc; |
336 | } /* mct_u232_set_modem_ctrl */ | 336 | } /* mct_u232_set_modem_ctrl */ |
337 | 337 | ||
338 | static int mct_u232_get_modem_stat(struct usb_serial *serial, | 338 | static int mct_u232_get_modem_stat(struct usb_serial *serial, |
339 | unsigned char *msr) | 339 | unsigned char *msr) |
340 | { | 340 | { |
341 | int rc; | 341 | int rc; |
342 | rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | 342 | rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), |
343 | MCT_U232_GET_MODEM_STAT_REQUEST, | 343 | MCT_U232_GET_MODEM_STAT_REQUEST, |
344 | MCT_U232_GET_REQUEST_TYPE, | 344 | MCT_U232_GET_REQUEST_TYPE, |
345 | 0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE, | 345 | 0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE, |
346 | WDR_TIMEOUT); | 346 | WDR_TIMEOUT); |
347 | if (rc < 0) { | 347 | if (rc < 0) { |
348 | dev_err(&serial->dev->dev, | 348 | dev_err(&serial->dev->dev, |
349 | "Get MODEM STATus failed (error = %d)\n", rc); | 349 | "Get MODEM STATus failed (error = %d)\n", rc); |
350 | *msr = 0; | 350 | *msr = 0; |
351 | } | 351 | } |
352 | dbg("get_modem_stat: 0x%x", *msr); | 352 | dbg("get_modem_stat: 0x%x", *msr); |
353 | return rc; | 353 | return rc; |
354 | } /* mct_u232_get_modem_stat */ | 354 | } /* mct_u232_get_modem_stat */ |
355 | 355 | ||
356 | static void mct_u232_msr_to_state(unsigned int *control_state, | 356 | static void mct_u232_msr_to_state(unsigned int *control_state, |
357 | unsigned char msr) | 357 | unsigned char msr) |
358 | { | 358 | { |
359 | /* Translate Control Line states */ | 359 | /* Translate Control Line states */ |
360 | if (msr & MCT_U232_MSR_DSR) | 360 | if (msr & MCT_U232_MSR_DSR) |
361 | *control_state |= TIOCM_DSR; | 361 | *control_state |= TIOCM_DSR; |
362 | else | 362 | else |
363 | *control_state &= ~TIOCM_DSR; | 363 | *control_state &= ~TIOCM_DSR; |
364 | if (msr & MCT_U232_MSR_CTS) | 364 | if (msr & MCT_U232_MSR_CTS) |
365 | *control_state |= TIOCM_CTS; | 365 | *control_state |= TIOCM_CTS; |
366 | else | 366 | else |
367 | *control_state &= ~TIOCM_CTS; | 367 | *control_state &= ~TIOCM_CTS; |
368 | if (msr & MCT_U232_MSR_RI) | 368 | if (msr & MCT_U232_MSR_RI) |
369 | *control_state |= TIOCM_RI; | 369 | *control_state |= TIOCM_RI; |
370 | else | 370 | else |
371 | *control_state &= ~TIOCM_RI; | 371 | *control_state &= ~TIOCM_RI; |
372 | if (msr & MCT_U232_MSR_CD) | 372 | if (msr & MCT_U232_MSR_CD) |
373 | *control_state |= TIOCM_CD; | 373 | *control_state |= TIOCM_CD; |
374 | else | 374 | else |
375 | *control_state &= ~TIOCM_CD; | 375 | *control_state &= ~TIOCM_CD; |
376 | dbg("msr_to_state: msr=0x%x ==> state=0x%x", msr, *control_state); | 376 | dbg("msr_to_state: msr=0x%x ==> state=0x%x", msr, *control_state); |
377 | } /* mct_u232_msr_to_state */ | 377 | } /* mct_u232_msr_to_state */ |
378 | 378 | ||
379 | /* | 379 | /* |
380 | * Driver's tty interface functions | 380 | * Driver's tty interface functions |
381 | */ | 381 | */ |
382 | 382 | ||
383 | static int mct_u232_startup(struct usb_serial *serial) | 383 | static int mct_u232_startup(struct usb_serial *serial) |
384 | { | 384 | { |
385 | struct mct_u232_private *priv; | 385 | struct mct_u232_private *priv; |
386 | struct usb_serial_port *port, *rport; | 386 | struct usb_serial_port *port, *rport; |
387 | 387 | ||
388 | priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL); | 388 | priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL); |
389 | if (!priv) | 389 | if (!priv) |
390 | return -ENOMEM; | 390 | return -ENOMEM; |
391 | spin_lock_init(&priv->lock); | 391 | spin_lock_init(&priv->lock); |
392 | usb_set_serial_port_data(serial->port[0], priv); | 392 | usb_set_serial_port_data(serial->port[0], priv); |
393 | 393 | ||
394 | init_waitqueue_head(&serial->port[0]->write_wait); | 394 | init_waitqueue_head(&serial->port[0]->write_wait); |
395 | 395 | ||
396 | /* Puh, that's dirty */ | 396 | /* Puh, that's dirty */ |
397 | port = serial->port[0]; | 397 | port = serial->port[0]; |
398 | rport = serial->port[1]; | 398 | rport = serial->port[1]; |
399 | /* No unlinking, it wasn't submitted yet. */ | 399 | /* No unlinking, it wasn't submitted yet. */ |
400 | usb_free_urb(port->read_urb); | 400 | usb_free_urb(port->read_urb); |
401 | port->read_urb = rport->interrupt_in_urb; | 401 | port->read_urb = rport->interrupt_in_urb; |
402 | rport->interrupt_in_urb = NULL; | 402 | rport->interrupt_in_urb = NULL; |
403 | port->read_urb->context = port; | 403 | port->read_urb->context = port; |
404 | 404 | ||
405 | return 0; | 405 | return 0; |
406 | } /* mct_u232_startup */ | 406 | } /* mct_u232_startup */ |
407 | 407 | ||
408 | 408 | ||
409 | static void mct_u232_shutdown(struct usb_serial *serial) | 409 | static void mct_u232_shutdown(struct usb_serial *serial) |
410 | { | 410 | { |
411 | struct mct_u232_private *priv; | 411 | struct mct_u232_private *priv; |
412 | int i; | 412 | int i; |
413 | 413 | ||
414 | dbg("%s", __func__); | 414 | dbg("%s", __func__); |
415 | 415 | ||
416 | for (i = 0; i < serial->num_ports; ++i) { | 416 | for (i = 0; i < serial->num_ports; ++i) { |
417 | /* My special items, the standard routines free my urbs */ | 417 | /* My special items, the standard routines free my urbs */ |
418 | priv = usb_get_serial_port_data(serial->port[i]); | 418 | priv = usb_get_serial_port_data(serial->port[i]); |
419 | if (priv) { | 419 | if (priv) { |
420 | usb_set_serial_port_data(serial->port[i], NULL); | 420 | usb_set_serial_port_data(serial->port[i], NULL); |
421 | kfree(priv); | 421 | kfree(priv); |
422 | } | 422 | } |
423 | } | 423 | } |
424 | } /* mct_u232_shutdown */ | 424 | } /* mct_u232_shutdown */ |
425 | 425 | ||
426 | static int mct_u232_open(struct tty_struct *tty, | 426 | static int mct_u232_open(struct tty_struct *tty, |
427 | struct usb_serial_port *port, struct file *filp) | 427 | struct usb_serial_port *port, struct file *filp) |
428 | { | 428 | { |
429 | struct usb_serial *serial = port->serial; | 429 | struct usb_serial *serial = port->serial; |
430 | struct mct_u232_private *priv = usb_get_serial_port_data(port); | 430 | struct mct_u232_private *priv = usb_get_serial_port_data(port); |
431 | int retval = 0; | 431 | int retval = 0; |
432 | unsigned int control_state; | 432 | unsigned int control_state; |
433 | unsigned long flags; | 433 | unsigned long flags; |
434 | unsigned char last_lcr; | 434 | unsigned char last_lcr; |
435 | unsigned char last_msr; | 435 | unsigned char last_msr; |
436 | 436 | ||
437 | dbg("%s port %d", __func__, port->number); | 437 | dbg("%s port %d", __func__, port->number); |
438 | 438 | ||
439 | /* Compensate for a hardware bug: although the Sitecom U232-P25 | 439 | /* Compensate for a hardware bug: although the Sitecom U232-P25 |
440 | * device reports a maximum output packet size of 32 bytes, | 440 | * device reports a maximum output packet size of 32 bytes, |
441 | * it seems to be able to accept only 16 bytes (and that's what | 441 | * it seems to be able to accept only 16 bytes (and that's what |
442 | * SniffUSB says too...) | 442 | * SniffUSB says too...) |
443 | */ | 443 | */ |
444 | if (le16_to_cpu(serial->dev->descriptor.idProduct) | 444 | if (le16_to_cpu(serial->dev->descriptor.idProduct) |
445 | == MCT_U232_SITECOM_PID) | 445 | == MCT_U232_SITECOM_PID) |
446 | port->bulk_out_size = 16; | 446 | port->bulk_out_size = 16; |
447 | 447 | ||
448 | /* Do a defined restart: the normal serial device seems to | 448 | /* Do a defined restart: the normal serial device seems to |
449 | * always turn on DTR and RTS here, so do the same. I'm not | 449 | * always turn on DTR and RTS here, so do the same. I'm not |
450 | * sure if this is really necessary. But it should not harm | 450 | * sure if this is really necessary. But it should not harm |
451 | * either. | 451 | * either. |
452 | */ | 452 | */ |
453 | spin_lock_irqsave(&priv->lock, flags); | 453 | spin_lock_irqsave(&priv->lock, flags); |
454 | if (tty && (tty->termios->c_cflag & CBAUD)) | 454 | if (tty && (tty->termios->c_cflag & CBAUD)) |
455 | priv->control_state = TIOCM_DTR | TIOCM_RTS; | 455 | priv->control_state = TIOCM_DTR | TIOCM_RTS; |
456 | else | 456 | else |
457 | priv->control_state = 0; | 457 | priv->control_state = 0; |
458 | 458 | ||
459 | priv->last_lcr = (MCT_U232_DATA_BITS_8 | | 459 | priv->last_lcr = (MCT_U232_DATA_BITS_8 | |
460 | MCT_U232_PARITY_NONE | | 460 | MCT_U232_PARITY_NONE | |
461 | MCT_U232_STOP_BITS_1); | 461 | MCT_U232_STOP_BITS_1); |
462 | control_state = priv->control_state; | 462 | control_state = priv->control_state; |
463 | last_lcr = priv->last_lcr; | 463 | last_lcr = priv->last_lcr; |
464 | spin_unlock_irqrestore(&priv->lock, flags); | 464 | spin_unlock_irqrestore(&priv->lock, flags); |
465 | mct_u232_set_modem_ctrl(serial, control_state); | 465 | mct_u232_set_modem_ctrl(serial, control_state); |
466 | mct_u232_set_line_ctrl(serial, last_lcr); | 466 | mct_u232_set_line_ctrl(serial, last_lcr); |
467 | 467 | ||
468 | /* Read modem status and update control state */ | 468 | /* Read modem status and update control state */ |
469 | mct_u232_get_modem_stat(serial, &last_msr); | 469 | mct_u232_get_modem_stat(serial, &last_msr); |
470 | spin_lock_irqsave(&priv->lock, flags); | 470 | spin_lock_irqsave(&priv->lock, flags); |
471 | priv->last_msr = last_msr; | 471 | priv->last_msr = last_msr; |
472 | mct_u232_msr_to_state(&priv->control_state, priv->last_msr); | 472 | mct_u232_msr_to_state(&priv->control_state, priv->last_msr); |
473 | spin_unlock_irqrestore(&priv->lock, flags); | 473 | spin_unlock_irqrestore(&priv->lock, flags); |
474 | 474 | ||
475 | port->read_urb->dev = port->serial->dev; | 475 | port->read_urb->dev = port->serial->dev; |
476 | retval = usb_submit_urb(port->read_urb, GFP_KERNEL); | 476 | retval = usb_submit_urb(port->read_urb, GFP_KERNEL); |
477 | if (retval) { | 477 | if (retval) { |
478 | dev_err(&port->dev, | 478 | dev_err(&port->dev, |
479 | "usb_submit_urb(read bulk) failed pipe 0x%x err %d\n", | 479 | "usb_submit_urb(read bulk) failed pipe 0x%x err %d\n", |
480 | port->read_urb->pipe, retval); | 480 | port->read_urb->pipe, retval); |
481 | goto error; | 481 | goto error; |
482 | } | 482 | } |
483 | 483 | ||
484 | port->interrupt_in_urb->dev = port->serial->dev; | 484 | port->interrupt_in_urb->dev = port->serial->dev; |
485 | retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); | 485 | retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); |
486 | if (retval) { | 486 | if (retval) { |
487 | usb_kill_urb(port->read_urb); | 487 | usb_kill_urb(port->read_urb); |
488 | dev_err(&port->dev, | 488 | dev_err(&port->dev, |
489 | "usb_submit_urb(read int) failed pipe 0x%x err %d", | 489 | "usb_submit_urb(read int) failed pipe 0x%x err %d", |
490 | port->interrupt_in_urb->pipe, retval); | 490 | port->interrupt_in_urb->pipe, retval); |
491 | goto error; | 491 | goto error; |
492 | } | 492 | } |
493 | return 0; | 493 | return 0; |
494 | 494 | ||
495 | error: | 495 | error: |
496 | return retval; | 496 | return retval; |
497 | } /* mct_u232_open */ | 497 | } /* mct_u232_open */ |
498 | 498 | ||
499 | 499 | ||
500 | static void mct_u232_close(struct tty_struct *tty, | 500 | static void mct_u232_close(struct tty_struct *tty, |
501 | struct usb_serial_port *port, struct file *filp) | 501 | struct usb_serial_port *port, struct file *filp) |
502 | { | 502 | { |
503 | unsigned int c_cflag; | 503 | unsigned int c_cflag; |
504 | unsigned int control_state; | 504 | unsigned int control_state; |
505 | struct mct_u232_private *priv = usb_get_serial_port_data(port); | 505 | struct mct_u232_private *priv = usb_get_serial_port_data(port); |
506 | dbg("%s port %d", __func__, port->number); | 506 | dbg("%s port %d", __func__, port->number); |
507 | 507 | ||
508 | if (tty) { | 508 | if (tty) { |
509 | c_cflag = tty->termios->c_cflag; | 509 | c_cflag = tty->termios->c_cflag; |
510 | mutex_lock(&port->serial->disc_mutex); | 510 | mutex_lock(&port->serial->disc_mutex); |
511 | if (c_cflag & HUPCL && !port->serial->disconnected) { | 511 | if (c_cflag & HUPCL && !port->serial->disconnected) { |
512 | /* drop DTR and RTS */ | 512 | /* drop DTR and RTS */ |
513 | spin_lock_irq(&priv->lock); | 513 | spin_lock_irq(&priv->lock); |
514 | priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); | 514 | priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); |
515 | control_state = priv->control_state; | 515 | control_state = priv->control_state; |
516 | spin_unlock_irq(&priv->lock); | 516 | spin_unlock_irq(&priv->lock); |
517 | mct_u232_set_modem_ctrl(port->serial, control_state); | 517 | mct_u232_set_modem_ctrl(port->serial, control_state); |
518 | } | 518 | } |
519 | mutex_unlock(&port->serial->disc_mutex); | 519 | mutex_unlock(&port->serial->disc_mutex); |
520 | } | 520 | } |
521 | 521 | ||
522 | 522 | ||
523 | if (port->serial->dev) { | 523 | if (port->serial->dev) { |
524 | /* shutdown our urbs */ | 524 | /* shutdown our urbs */ |
525 | usb_kill_urb(port->write_urb); | 525 | usb_kill_urb(port->write_urb); |
526 | usb_kill_urb(port->read_urb); | 526 | usb_kill_urb(port->read_urb); |
527 | usb_kill_urb(port->interrupt_in_urb); | 527 | usb_kill_urb(port->interrupt_in_urb); |
528 | } | 528 | } |
529 | } /* mct_u232_close */ | 529 | } /* mct_u232_close */ |
530 | 530 | ||
531 | 531 | ||
532 | static void mct_u232_read_int_callback(struct urb *urb) | 532 | static void mct_u232_read_int_callback(struct urb *urb) |
533 | { | 533 | { |
534 | struct usb_serial_port *port = urb->context; | 534 | struct usb_serial_port *port = urb->context; |
535 | struct mct_u232_private *priv = usb_get_serial_port_data(port); | 535 | struct mct_u232_private *priv = usb_get_serial_port_data(port); |
536 | struct usb_serial *serial = port->serial; | 536 | struct usb_serial *serial = port->serial; |
537 | struct tty_struct *tty; | 537 | struct tty_struct *tty; |
538 | unsigned char *data = urb->transfer_buffer; | 538 | unsigned char *data = urb->transfer_buffer; |
539 | int retval; | 539 | int retval; |
540 | int status = urb->status; | 540 | int status = urb->status; |
541 | unsigned long flags; | 541 | unsigned long flags; |
542 | 542 | ||
543 | switch (status) { | 543 | switch (status) { |
544 | case 0: | 544 | case 0: |
545 | /* success */ | 545 | /* success */ |
546 | break; | 546 | break; |
547 | case -ECONNRESET: | 547 | case -ECONNRESET: |
548 | case -ENOENT: | 548 | case -ENOENT: |
549 | case -ESHUTDOWN: | 549 | case -ESHUTDOWN: |
550 | /* this urb is terminated, clean up */ | 550 | /* this urb is terminated, clean up */ |
551 | dbg("%s - urb shutting down with status: %d", | 551 | dbg("%s - urb shutting down with status: %d", |
552 | __func__, status); | 552 | __func__, status); |
553 | return; | 553 | return; |
554 | default: | 554 | default: |
555 | dbg("%s - nonzero urb status received: %d", | 555 | dbg("%s - nonzero urb status received: %d", |
556 | __func__, status); | 556 | __func__, status); |
557 | goto exit; | 557 | goto exit; |
558 | } | 558 | } |
559 | 559 | ||
560 | if (!serial) { | 560 | if (!serial) { |
561 | dbg("%s - bad serial pointer, exiting", __func__); | 561 | dbg("%s - bad serial pointer, exiting", __func__); |
562 | return; | 562 | return; |
563 | } | 563 | } |
564 | 564 | ||
565 | dbg("%s - port %d", __func__, port->number); | 565 | dbg("%s - port %d", __func__, port->number); |
566 | usb_serial_debug_data(debug, &port->dev, __func__, | 566 | usb_serial_debug_data(debug, &port->dev, __func__, |
567 | urb->actual_length, data); | 567 | urb->actual_length, data); |
568 | 568 | ||
569 | /* | 569 | /* |
570 | * Work-a-round: handle the 'usual' bulk-in pipe here | 570 | * Work-a-round: handle the 'usual' bulk-in pipe here |
571 | */ | 571 | */ |
572 | if (urb->transfer_buffer_length > 2) { | 572 | if (urb->transfer_buffer_length > 2) { |
573 | tty = tty_port_tty_get(&port->port); | 573 | tty = tty_port_tty_get(&port->port); |
574 | if (urb->actual_length) { | 574 | if (urb->actual_length) { |
575 | tty_insert_flip_string(tty, data, urb->actual_length); | 575 | tty_insert_flip_string(tty, data, urb->actual_length); |
576 | tty_flip_buffer_push(tty); | 576 | tty_flip_buffer_push(tty); |
577 | tty_kref_put(tty); | 577 | tty_kref_put(tty); |
578 | } | 578 | } |
579 | goto exit; | 579 | goto exit; |
580 | } | 580 | } |
581 | 581 | ||
582 | /* | 582 | /* |
583 | * The interrupt-in pipe signals exceptional conditions (modem line | 583 | * The interrupt-in pipe signals exceptional conditions (modem line |
584 | * signal changes and errors). data[0] holds MSR, data[1] holds LSR. | 584 | * signal changes and errors). data[0] holds MSR, data[1] holds LSR. |
585 | */ | 585 | */ |
586 | spin_lock_irqsave(&priv->lock, flags); | 586 | spin_lock_irqsave(&priv->lock, flags); |
587 | priv->last_msr = data[MCT_U232_MSR_INDEX]; | 587 | priv->last_msr = data[MCT_U232_MSR_INDEX]; |
588 | 588 | ||
589 | /* Record Control Line states */ | 589 | /* Record Control Line states */ |
590 | mct_u232_msr_to_state(&priv->control_state, priv->last_msr); | 590 | mct_u232_msr_to_state(&priv->control_state, priv->last_msr); |
591 | 591 | ||
592 | #if 0 | 592 | #if 0 |
593 | /* Not yet handled. See belkin_sa.c for further information */ | 593 | /* Not yet handled. See belkin_sa.c for further information */ |
594 | /* Now to report any errors */ | 594 | /* Now to report any errors */ |
595 | priv->last_lsr = data[MCT_U232_LSR_INDEX]; | 595 | priv->last_lsr = data[MCT_U232_LSR_INDEX]; |
596 | /* | 596 | /* |
597 | * fill in the flip buffer here, but I do not know the relation | 597 | * fill in the flip buffer here, but I do not know the relation |
598 | * to the current/next receive buffer or characters. I need | 598 | * to the current/next receive buffer or characters. I need |
599 | * to look in to this before committing any code. | 599 | * to look in to this before committing any code. |
600 | */ | 600 | */ |
601 | if (priv->last_lsr & MCT_U232_LSR_ERR) { | 601 | if (priv->last_lsr & MCT_U232_LSR_ERR) { |
602 | tty = tty_port_tty_get(&port->port); | 602 | tty = tty_port_tty_get(&port->port); |
603 | /* Overrun Error */ | 603 | /* Overrun Error */ |
604 | if (priv->last_lsr & MCT_U232_LSR_OE) { | 604 | if (priv->last_lsr & MCT_U232_LSR_OE) { |
605 | } | 605 | } |
606 | /* Parity Error */ | 606 | /* Parity Error */ |
607 | if (priv->last_lsr & MCT_U232_LSR_PE) { | 607 | if (priv->last_lsr & MCT_U232_LSR_PE) { |
608 | } | 608 | } |
609 | /* Framing Error */ | 609 | /* Framing Error */ |
610 | if (priv->last_lsr & MCT_U232_LSR_FE) { | 610 | if (priv->last_lsr & MCT_U232_LSR_FE) { |
611 | } | 611 | } |
612 | /* Break Indicator */ | 612 | /* Break Indicator */ |
613 | if (priv->last_lsr & MCT_U232_LSR_BI) { | 613 | if (priv->last_lsr & MCT_U232_LSR_BI) { |
614 | } | 614 | } |
615 | tty_kref_put(tty); | 615 | tty_kref_put(tty); |
616 | } | 616 | } |
617 | #endif | 617 | #endif |
618 | spin_unlock_irqrestore(&priv->lock, flags); | 618 | spin_unlock_irqrestore(&priv->lock, flags); |
619 | exit: | 619 | exit: |
620 | retval = usb_submit_urb(urb, GFP_ATOMIC); | 620 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
621 | if (retval) | 621 | if (retval) |
622 | dev_err(&port->dev, | 622 | dev_err(&port->dev, |
623 | "%s - usb_submit_urb failed with result %d\n", | 623 | "%s - usb_submit_urb failed with result %d\n", |
624 | __func__, retval); | 624 | __func__, retval); |
625 | } /* mct_u232_read_int_callback */ | 625 | } /* mct_u232_read_int_callback */ |
626 | 626 | ||
627 | static void mct_u232_set_termios(struct tty_struct *tty, | 627 | static void mct_u232_set_termios(struct tty_struct *tty, |
628 | struct usb_serial_port *port, | 628 | struct usb_serial_port *port, |
629 | struct ktermios *old_termios) | 629 | struct ktermios *old_termios) |
630 | { | 630 | { |
631 | struct usb_serial *serial = port->serial; | 631 | struct usb_serial *serial = port->serial; |
632 | struct mct_u232_private *priv = usb_get_serial_port_data(port); | 632 | struct mct_u232_private *priv = usb_get_serial_port_data(port); |
633 | struct ktermios *termios = tty->termios; | 633 | struct ktermios *termios = tty->termios; |
634 | unsigned int cflag = termios->c_cflag; | 634 | unsigned int cflag = termios->c_cflag; |
635 | unsigned int old_cflag = old_termios->c_cflag; | 635 | unsigned int old_cflag = old_termios->c_cflag; |
636 | unsigned long flags; | 636 | unsigned long flags; |
637 | unsigned int control_state; | 637 | unsigned int control_state; |
638 | unsigned char last_lcr; | 638 | unsigned char last_lcr; |
639 | 639 | ||
640 | /* get a local copy of the current port settings */ | 640 | /* get a local copy of the current port settings */ |
641 | spin_lock_irqsave(&priv->lock, flags); | 641 | spin_lock_irqsave(&priv->lock, flags); |
642 | control_state = priv->control_state; | 642 | control_state = priv->control_state; |
643 | spin_unlock_irqrestore(&priv->lock, flags); | 643 | spin_unlock_irqrestore(&priv->lock, flags); |
644 | last_lcr = 0; | 644 | last_lcr = 0; |
645 | 645 | ||
646 | /* | 646 | /* |
647 | * Update baud rate. | 647 | * Update baud rate. |
648 | * Do not attempt to cache old rates and skip settings, | 648 | * Do not attempt to cache old rates and skip settings, |
649 | * disconnects screw such tricks up completely. | 649 | * disconnects screw such tricks up completely. |
650 | * Premature optimization is the root of all evil. | 650 | * Premature optimization is the root of all evil. |
651 | */ | 651 | */ |
652 | 652 | ||
653 | /* reassert DTR and RTS on transition from B0 */ | 653 | /* reassert DTR and RTS on transition from B0 */ |
654 | if ((old_cflag & CBAUD) == B0) { | 654 | if ((old_cflag & CBAUD) == B0) { |
655 | dbg("%s: baud was B0", __func__); | 655 | dbg("%s: baud was B0", __func__); |
656 | control_state |= TIOCM_DTR | TIOCM_RTS; | 656 | control_state |= TIOCM_DTR | TIOCM_RTS; |
657 | mct_u232_set_modem_ctrl(serial, control_state); | 657 | mct_u232_set_modem_ctrl(serial, control_state); |
658 | } | 658 | } |
659 | 659 | ||
660 | mct_u232_set_baud_rate(tty, serial, port, tty_get_baud_rate(tty)); | 660 | mct_u232_set_baud_rate(tty, serial, port, tty_get_baud_rate(tty)); |
661 | 661 | ||
662 | if ((cflag & CBAUD) == B0) { | 662 | if ((cflag & CBAUD) == B0) { |
663 | dbg("%s: baud is B0", __func__); | 663 | dbg("%s: baud is B0", __func__); |
664 | /* Drop RTS and DTR */ | 664 | /* Drop RTS and DTR */ |
665 | control_state &= ~(TIOCM_DTR | TIOCM_RTS); | 665 | control_state &= ~(TIOCM_DTR | TIOCM_RTS); |
666 | mct_u232_set_modem_ctrl(serial, control_state); | 666 | mct_u232_set_modem_ctrl(serial, control_state); |
667 | } | 667 | } |
668 | 668 | ||
669 | /* | 669 | /* |
670 | * Update line control register (LCR) | 670 | * Update line control register (LCR) |
671 | */ | 671 | */ |
672 | 672 | ||
673 | /* set the parity */ | 673 | /* set the parity */ |
674 | if (cflag & PARENB) | 674 | if (cflag & PARENB) |
675 | last_lcr |= (cflag & PARODD) ? | 675 | last_lcr |= (cflag & PARODD) ? |
676 | MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN; | 676 | MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN; |
677 | else | 677 | else |
678 | last_lcr |= MCT_U232_PARITY_NONE; | 678 | last_lcr |= MCT_U232_PARITY_NONE; |
679 | 679 | ||
680 | /* set the number of data bits */ | 680 | /* set the number of data bits */ |
681 | switch (cflag & CSIZE) { | 681 | switch (cflag & CSIZE) { |
682 | case CS5: | 682 | case CS5: |
683 | last_lcr |= MCT_U232_DATA_BITS_5; break; | 683 | last_lcr |= MCT_U232_DATA_BITS_5; break; |
684 | case CS6: | 684 | case CS6: |
685 | last_lcr |= MCT_U232_DATA_BITS_6; break; | 685 | last_lcr |= MCT_U232_DATA_BITS_6; break; |
686 | case CS7: | 686 | case CS7: |
687 | last_lcr |= MCT_U232_DATA_BITS_7; break; | 687 | last_lcr |= MCT_U232_DATA_BITS_7; break; |
688 | case CS8: | 688 | case CS8: |
689 | last_lcr |= MCT_U232_DATA_BITS_8; break; | 689 | last_lcr |= MCT_U232_DATA_BITS_8; break; |
690 | default: | 690 | default: |
691 | dev_err(&port->dev, | 691 | dev_err(&port->dev, |
692 | "CSIZE was not CS5-CS8, using default of 8\n"); | 692 | "CSIZE was not CS5-CS8, using default of 8\n"); |
693 | last_lcr |= MCT_U232_DATA_BITS_8; | 693 | last_lcr |= MCT_U232_DATA_BITS_8; |
694 | break; | 694 | break; |
695 | } | 695 | } |
696 | 696 | ||
697 | termios->c_cflag &= ~CMSPAR; | 697 | termios->c_cflag &= ~CMSPAR; |
698 | 698 | ||
699 | /* set the number of stop bits */ | 699 | /* set the number of stop bits */ |
700 | last_lcr |= (cflag & CSTOPB) ? | 700 | last_lcr |= (cflag & CSTOPB) ? |
701 | MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1; | 701 | MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1; |
702 | 702 | ||
703 | mct_u232_set_line_ctrl(serial, last_lcr); | 703 | mct_u232_set_line_ctrl(serial, last_lcr); |
704 | 704 | ||
705 | /* save off the modified port settings */ | 705 | /* save off the modified port settings */ |
706 | spin_lock_irqsave(&priv->lock, flags); | 706 | spin_lock_irqsave(&priv->lock, flags); |
707 | priv->control_state = control_state; | 707 | priv->control_state = control_state; |
708 | priv->last_lcr = last_lcr; | 708 | priv->last_lcr = last_lcr; |
709 | spin_unlock_irqrestore(&priv->lock, flags); | 709 | spin_unlock_irqrestore(&priv->lock, flags); |
710 | } /* mct_u232_set_termios */ | 710 | } /* mct_u232_set_termios */ |
711 | 711 | ||
712 | static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) | 712 | static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) |
713 | { | 713 | { |
714 | struct usb_serial_port *port = tty->driver_data; | 714 | struct usb_serial_port *port = tty->driver_data; |
715 | struct usb_serial *serial = port->serial; | 715 | struct usb_serial *serial = port->serial; |
716 | struct mct_u232_private *priv = usb_get_serial_port_data(port); | 716 | struct mct_u232_private *priv = usb_get_serial_port_data(port); |
717 | unsigned char lcr; | 717 | unsigned char lcr; |
718 | unsigned long flags; | 718 | unsigned long flags; |
719 | 719 | ||
720 | dbg("%sstate=%d", __func__, break_state); | 720 | dbg("%sstate=%d", __func__, break_state); |
721 | 721 | ||
722 | spin_lock_irqsave(&priv->lock, flags); | 722 | spin_lock_irqsave(&priv->lock, flags); |
723 | lcr = priv->last_lcr; | 723 | lcr = priv->last_lcr; |
724 | spin_unlock_irqrestore(&priv->lock, flags); | ||
725 | 724 | ||
726 | if (break_state) | 725 | if (break_state) |
727 | lcr |= MCT_U232_SET_BREAK; | 726 | lcr |= MCT_U232_SET_BREAK; |
727 | spin_unlock_irqrestore(&priv->lock, flags); | ||
728 | 728 | ||
729 | mct_u232_set_line_ctrl(serial, lcr); | 729 | mct_u232_set_line_ctrl(serial, lcr); |
730 | } /* mct_u232_break_ctl */ | 730 | } /* mct_u232_break_ctl */ |
731 | 731 | ||
732 | 732 | ||
733 | static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file) | 733 | static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file) |
734 | { | 734 | { |
735 | struct usb_serial_port *port = tty->driver_data; | 735 | struct usb_serial_port *port = tty->driver_data; |
736 | struct mct_u232_private *priv = usb_get_serial_port_data(port); | 736 | struct mct_u232_private *priv = usb_get_serial_port_data(port); |
737 | unsigned int control_state; | 737 | unsigned int control_state; |
738 | unsigned long flags; | 738 | unsigned long flags; |
739 | 739 | ||
740 | dbg("%s", __func__); | 740 | dbg("%s", __func__); |
741 | 741 | ||
742 | spin_lock_irqsave(&priv->lock, flags); | 742 | spin_lock_irqsave(&priv->lock, flags); |
743 | control_state = priv->control_state; | 743 | control_state = priv->control_state; |
744 | spin_unlock_irqrestore(&priv->lock, flags); | 744 | spin_unlock_irqrestore(&priv->lock, flags); |
745 | 745 | ||
746 | return control_state; | 746 | return control_state; |
747 | } | 747 | } |
748 | 748 | ||
749 | static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file, | 749 | static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file, |
750 | unsigned int set, unsigned int clear) | 750 | unsigned int set, unsigned int clear) |
751 | { | 751 | { |
752 | struct usb_serial_port *port = tty->driver_data; | 752 | struct usb_serial_port *port = tty->driver_data; |
753 | struct usb_serial *serial = port->serial; | 753 | struct usb_serial *serial = port->serial; |
754 | struct mct_u232_private *priv = usb_get_serial_port_data(port); | 754 | struct mct_u232_private *priv = usb_get_serial_port_data(port); |
755 | unsigned int control_state; | 755 | unsigned int control_state; |
756 | unsigned long flags; | 756 | unsigned long flags; |
757 | 757 | ||
758 | dbg("%s", __func__); | 758 | dbg("%s", __func__); |
759 | 759 | ||
760 | spin_lock_irqsave(&priv->lock, flags); | 760 | spin_lock_irqsave(&priv->lock, flags); |
761 | control_state = priv->control_state; | 761 | control_state = priv->control_state; |
762 | 762 | ||
763 | if (set & TIOCM_RTS) | 763 | if (set & TIOCM_RTS) |
764 | control_state |= TIOCM_RTS; | 764 | control_state |= TIOCM_RTS; |
765 | if (set & TIOCM_DTR) | 765 | if (set & TIOCM_DTR) |
766 | control_state |= TIOCM_DTR; | 766 | control_state |= TIOCM_DTR; |
767 | if (clear & TIOCM_RTS) | 767 | if (clear & TIOCM_RTS) |
768 | control_state &= ~TIOCM_RTS; | 768 | control_state &= ~TIOCM_RTS; |
769 | if (clear & TIOCM_DTR) | 769 | if (clear & TIOCM_DTR) |
770 | control_state &= ~TIOCM_DTR; | 770 | control_state &= ~TIOCM_DTR; |
771 | 771 | ||
772 | priv->control_state = control_state; | 772 | priv->control_state = control_state; |
773 | spin_unlock_irqrestore(&priv->lock, flags); | 773 | spin_unlock_irqrestore(&priv->lock, flags); |
774 | return mct_u232_set_modem_ctrl(serial, control_state); | 774 | return mct_u232_set_modem_ctrl(serial, control_state); |
775 | } | 775 | } |
776 | 776 | ||
777 | static void mct_u232_throttle(struct tty_struct *tty) | 777 | static void mct_u232_throttle(struct tty_struct *tty) |
778 | { | 778 | { |
779 | struct usb_serial_port *port = tty->driver_data; | 779 | struct usb_serial_port *port = tty->driver_data; |
780 | struct mct_u232_private *priv = usb_get_serial_port_data(port); | 780 | struct mct_u232_private *priv = usb_get_serial_port_data(port); |
781 | unsigned long flags; | 781 | unsigned long flags; |
782 | unsigned int control_state; | 782 | unsigned int control_state; |
783 | 783 | ||
784 | dbg("%s - port %d", __func__, port->number); | 784 | dbg("%s - port %d", __func__, port->number); |
785 | 785 | ||
786 | spin_lock_irqsave(&priv->lock, flags); | 786 | spin_lock_irqsave(&priv->lock, flags); |
787 | priv->rx_flags |= THROTTLED; | 787 | priv->rx_flags |= THROTTLED; |
788 | if (C_CRTSCTS(tty)) { | 788 | if (C_CRTSCTS(tty)) { |
789 | priv->control_state &= ~TIOCM_RTS; | 789 | priv->control_state &= ~TIOCM_RTS; |
790 | control_state = priv->control_state; | 790 | control_state = priv->control_state; |
791 | spin_unlock_irqrestore(&priv->lock, flags); | 791 | spin_unlock_irqrestore(&priv->lock, flags); |
792 | (void) mct_u232_set_modem_ctrl(port->serial, control_state); | 792 | (void) mct_u232_set_modem_ctrl(port->serial, control_state); |
793 | } else { | 793 | } else { |
794 | spin_unlock_irqrestore(&priv->lock, flags); | 794 | spin_unlock_irqrestore(&priv->lock, flags); |
795 | } | 795 | } |
796 | } | 796 | } |
797 | 797 | ||
798 | 798 | ||
799 | static void mct_u232_unthrottle(struct tty_struct *tty) | 799 | static void mct_u232_unthrottle(struct tty_struct *tty) |
800 | { | 800 | { |
801 | struct usb_serial_port *port = tty->driver_data; | 801 | struct usb_serial_port *port = tty->driver_data; |
802 | struct mct_u232_private *priv = usb_get_serial_port_data(port); | 802 | struct mct_u232_private *priv = usb_get_serial_port_data(port); |
803 | unsigned long flags; | 803 | unsigned long flags; |
804 | unsigned int control_state; | 804 | unsigned int control_state; |
805 | 805 | ||
806 | dbg("%s - port %d", __func__, port->number); | 806 | dbg("%s - port %d", __func__, port->number); |
807 | 807 | ||
808 | spin_lock_irqsave(&priv->lock, flags); | 808 | spin_lock_irqsave(&priv->lock, flags); |
809 | if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) { | 809 | if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) { |
810 | priv->rx_flags &= ~THROTTLED; | 810 | priv->rx_flags &= ~THROTTLED; |
811 | priv->control_state |= TIOCM_RTS; | 811 | priv->control_state |= TIOCM_RTS; |
812 | control_state = priv->control_state; | 812 | control_state = priv->control_state; |
813 | spin_unlock_irqrestore(&priv->lock, flags); | 813 | spin_unlock_irqrestore(&priv->lock, flags); |
814 | (void) mct_u232_set_modem_ctrl(port->serial, control_state); | 814 | (void) mct_u232_set_modem_ctrl(port->serial, control_state); |
815 | } else { | 815 | } else { |
816 | spin_unlock_irqrestore(&priv->lock, flags); | 816 | spin_unlock_irqrestore(&priv->lock, flags); |
817 | } | 817 | } |
818 | } | 818 | } |
819 | 819 | ||
820 | static int __init mct_u232_init(void) | 820 | static int __init mct_u232_init(void) |
821 | { | 821 | { |
822 | int retval; | 822 | int retval; |
823 | retval = usb_serial_register(&mct_u232_device); | 823 | retval = usb_serial_register(&mct_u232_device); |
824 | if (retval) | 824 | if (retval) |
825 | goto failed_usb_serial_register; | 825 | goto failed_usb_serial_register; |
826 | retval = usb_register(&mct_u232_driver); | 826 | retval = usb_register(&mct_u232_driver); |
827 | if (retval) | 827 | if (retval) |
828 | goto failed_usb_register; | 828 | goto failed_usb_register; |
829 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | 829 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" |
830 | DRIVER_DESC "\n"); | 830 | DRIVER_DESC "\n"); |
831 | return 0; | 831 | return 0; |
832 | failed_usb_register: | 832 | failed_usb_register: |
833 | usb_serial_deregister(&mct_u232_device); | 833 | usb_serial_deregister(&mct_u232_device); |
834 | failed_usb_serial_register: | 834 | failed_usb_serial_register: |
835 | return retval; | 835 | return retval; |
836 | } | 836 | } |
837 | 837 | ||
838 | 838 | ||
839 | static void __exit mct_u232_exit(void) | 839 | static void __exit mct_u232_exit(void) |
840 | { | 840 | { |
841 | usb_deregister(&mct_u232_driver); | 841 | usb_deregister(&mct_u232_driver); |
842 | usb_serial_deregister(&mct_u232_device); | 842 | usb_serial_deregister(&mct_u232_device); |
843 | } | 843 | } |
844 | 844 | ||
845 | module_init(mct_u232_init); | 845 | module_init(mct_u232_init); |
846 | module_exit(mct_u232_exit); | 846 | module_exit(mct_u232_exit); |
847 | 847 | ||
848 | MODULE_AUTHOR(DRIVER_AUTHOR); | 848 | MODULE_AUTHOR(DRIVER_AUTHOR); |
849 | MODULE_DESCRIPTION(DRIVER_DESC); | 849 | MODULE_DESCRIPTION(DRIVER_DESC); |
850 | MODULE_LICENSE("GPL"); | 850 | MODULE_LICENSE("GPL"); |
851 | 851 | ||
852 | module_param(debug, bool, S_IRUGO | S_IWUSR); | 852 | module_param(debug, bool, S_IRUGO | S_IWUSR); |
853 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | 853 | MODULE_PARM_DESC(debug, "Debug enabled or not"); |
drivers/usb/serial/mos7840.c
1 | /* | 1 | /* |
2 | * This program is free software; you can redistribute it and/or modify | 2 | * This program is free software; you can redistribute it and/or modify |
3 | * it under the terms of the GNU General Public License as published by | 3 | * it under the terms of the GNU General Public License as published by |
4 | * the Free Software Foundation; either version 2 of the License, or | 4 | * the Free Software Foundation; either version 2 of the License, or |
5 | * (at your option) any later version. | 5 | * (at your option) any later version. |
6 | * | 6 | * |
7 | * This program is distributed in the hope that it will be useful, | 7 | * This program is distributed in the hope that it will be useful, |
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | * GNU General Public License for more details. | 10 | * GNU General Public License for more details. |
11 | * | 11 | * |
12 | * You should have received a copy of the GNU General Public License | 12 | * You should have received a copy of the GNU General Public License |
13 | * along with this program; if not, write to the Free Software | 13 | * along with this program; if not, write to the Free Software |
14 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 14 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
15 | * | 15 | * |
16 | * Clean ups from Moschip version and a few ioctl implementations by: | 16 | * Clean ups from Moschip version and a few ioctl implementations by: |
17 | * Paul B Schroeder <pschroeder "at" uplogix "dot" com> | 17 | * Paul B Schroeder <pschroeder "at" uplogix "dot" com> |
18 | * | 18 | * |
19 | * Originally based on drivers/usb/serial/io_edgeport.c which is: | 19 | * Originally based on drivers/usb/serial/io_edgeport.c which is: |
20 | * Copyright (C) 2000 Inside Out Networks, All rights reserved. | 20 | * Copyright (C) 2000 Inside Out Networks, All rights reserved. |
21 | * Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com> | 21 | * Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com> |
22 | * | 22 | * |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/tty.h> | 29 | #include <linux/tty.h> |
30 | #include <linux/tty_driver.h> | 30 | #include <linux/tty_driver.h> |
31 | #include <linux/tty_flip.h> | 31 | #include <linux/tty_flip.h> |
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/serial.h> | 33 | #include <linux/serial.h> |
34 | #include <linux/usb.h> | 34 | #include <linux/usb.h> |
35 | #include <linux/usb/serial.h> | 35 | #include <linux/usb/serial.h> |
36 | #include <linux/uaccess.h> | 36 | #include <linux/uaccess.h> |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * Version Information | 39 | * Version Information |
40 | */ | 40 | */ |
41 | #define DRIVER_VERSION "1.3.1" | 41 | #define DRIVER_VERSION "1.3.1" |
42 | #define DRIVER_DESC "Moschip 7840/7820 USB Serial Driver" | 42 | #define DRIVER_DESC "Moschip 7840/7820 USB Serial Driver" |
43 | 43 | ||
44 | /* | 44 | /* |
45 | * 16C50 UART register defines | 45 | * 16C50 UART register defines |
46 | */ | 46 | */ |
47 | 47 | ||
48 | #define LCR_BITS_5 0x00 /* 5 bits/char */ | 48 | #define LCR_BITS_5 0x00 /* 5 bits/char */ |
49 | #define LCR_BITS_6 0x01 /* 6 bits/char */ | 49 | #define LCR_BITS_6 0x01 /* 6 bits/char */ |
50 | #define LCR_BITS_7 0x02 /* 7 bits/char */ | 50 | #define LCR_BITS_7 0x02 /* 7 bits/char */ |
51 | #define LCR_BITS_8 0x03 /* 8 bits/char */ | 51 | #define LCR_BITS_8 0x03 /* 8 bits/char */ |
52 | #define LCR_BITS_MASK 0x03 /* Mask for bits/char field */ | 52 | #define LCR_BITS_MASK 0x03 /* Mask for bits/char field */ |
53 | 53 | ||
54 | #define LCR_STOP_1 0x00 /* 1 stop bit */ | 54 | #define LCR_STOP_1 0x00 /* 1 stop bit */ |
55 | #define LCR_STOP_1_5 0x04 /* 1.5 stop bits (if 5 bits/char) */ | 55 | #define LCR_STOP_1_5 0x04 /* 1.5 stop bits (if 5 bits/char) */ |
56 | #define LCR_STOP_2 0x04 /* 2 stop bits (if 6-8 bits/char) */ | 56 | #define LCR_STOP_2 0x04 /* 2 stop bits (if 6-8 bits/char) */ |
57 | #define LCR_STOP_MASK 0x04 /* Mask for stop bits field */ | 57 | #define LCR_STOP_MASK 0x04 /* Mask for stop bits field */ |
58 | 58 | ||
59 | #define LCR_PAR_NONE 0x00 /* No parity */ | 59 | #define LCR_PAR_NONE 0x00 /* No parity */ |
60 | #define LCR_PAR_ODD 0x08 /* Odd parity */ | 60 | #define LCR_PAR_ODD 0x08 /* Odd parity */ |
61 | #define LCR_PAR_EVEN 0x18 /* Even parity */ | 61 | #define LCR_PAR_EVEN 0x18 /* Even parity */ |
62 | #define LCR_PAR_MARK 0x28 /* Force parity bit to 1 */ | 62 | #define LCR_PAR_MARK 0x28 /* Force parity bit to 1 */ |
63 | #define LCR_PAR_SPACE 0x38 /* Force parity bit to 0 */ | 63 | #define LCR_PAR_SPACE 0x38 /* Force parity bit to 0 */ |
64 | #define LCR_PAR_MASK 0x38 /* Mask for parity field */ | 64 | #define LCR_PAR_MASK 0x38 /* Mask for parity field */ |
65 | 65 | ||
66 | #define LCR_SET_BREAK 0x40 /* Set Break condition */ | 66 | #define LCR_SET_BREAK 0x40 /* Set Break condition */ |
67 | #define LCR_DL_ENABLE 0x80 /* Enable access to divisor latch */ | 67 | #define LCR_DL_ENABLE 0x80 /* Enable access to divisor latch */ |
68 | 68 | ||
69 | #define MCR_DTR 0x01 /* Assert DTR */ | 69 | #define MCR_DTR 0x01 /* Assert DTR */ |
70 | #define MCR_RTS 0x02 /* Assert RTS */ | 70 | #define MCR_RTS 0x02 /* Assert RTS */ |
71 | #define MCR_OUT1 0x04 /* Loopback only: Sets state of RI */ | 71 | #define MCR_OUT1 0x04 /* Loopback only: Sets state of RI */ |
72 | #define MCR_MASTER_IE 0x08 /* Enable interrupt outputs */ | 72 | #define MCR_MASTER_IE 0x08 /* Enable interrupt outputs */ |
73 | #define MCR_LOOPBACK 0x10 /* Set internal (digital) loopback mode */ | 73 | #define MCR_LOOPBACK 0x10 /* Set internal (digital) loopback mode */ |
74 | #define MCR_XON_ANY 0x20 /* Enable any char to exit XOFF mode */ | 74 | #define MCR_XON_ANY 0x20 /* Enable any char to exit XOFF mode */ |
75 | 75 | ||
76 | #define MOS7840_MSR_CTS 0x10 /* Current state of CTS */ | 76 | #define MOS7840_MSR_CTS 0x10 /* Current state of CTS */ |
77 | #define MOS7840_MSR_DSR 0x20 /* Current state of DSR */ | 77 | #define MOS7840_MSR_DSR 0x20 /* Current state of DSR */ |
78 | #define MOS7840_MSR_RI 0x40 /* Current state of RI */ | 78 | #define MOS7840_MSR_RI 0x40 /* Current state of RI */ |
79 | #define MOS7840_MSR_CD 0x80 /* Current state of CD */ | 79 | #define MOS7840_MSR_CD 0x80 /* Current state of CD */ |
80 | 80 | ||
81 | /* | 81 | /* |
82 | * Defines used for sending commands to port | 82 | * Defines used for sending commands to port |
83 | */ | 83 | */ |
84 | 84 | ||
85 | #define WAIT_FOR_EVER (HZ * 0) /* timeout urb is wait for ever */ | 85 | #define WAIT_FOR_EVER (HZ * 0) /* timeout urb is wait for ever */ |
86 | #define MOS_WDR_TIMEOUT (HZ * 5) /* default urb timeout */ | 86 | #define MOS_WDR_TIMEOUT (HZ * 5) /* default urb timeout */ |
87 | 87 | ||
88 | #define MOS_PORT1 0x0200 | 88 | #define MOS_PORT1 0x0200 |
89 | #define MOS_PORT2 0x0300 | 89 | #define MOS_PORT2 0x0300 |
90 | #define MOS_VENREG 0x0000 | 90 | #define MOS_VENREG 0x0000 |
91 | #define MOS_MAX_PORT 0x02 | 91 | #define MOS_MAX_PORT 0x02 |
92 | #define MOS_WRITE 0x0E | 92 | #define MOS_WRITE 0x0E |
93 | #define MOS_READ 0x0D | 93 | #define MOS_READ 0x0D |
94 | 94 | ||
95 | /* Requests */ | 95 | /* Requests */ |
96 | #define MCS_RD_RTYPE 0xC0 | 96 | #define MCS_RD_RTYPE 0xC0 |
97 | #define MCS_WR_RTYPE 0x40 | 97 | #define MCS_WR_RTYPE 0x40 |
98 | #define MCS_RDREQ 0x0D | 98 | #define MCS_RDREQ 0x0D |
99 | #define MCS_WRREQ 0x0E | 99 | #define MCS_WRREQ 0x0E |
100 | #define MCS_CTRL_TIMEOUT 500 | 100 | #define MCS_CTRL_TIMEOUT 500 |
101 | #define VENDOR_READ_LENGTH (0x01) | 101 | #define VENDOR_READ_LENGTH (0x01) |
102 | 102 | ||
103 | #define MAX_NAME_LEN 64 | 103 | #define MAX_NAME_LEN 64 |
104 | 104 | ||
105 | #define ZLP_REG1 0x3A /* Zero_Flag_Reg1 58 */ | 105 | #define ZLP_REG1 0x3A /* Zero_Flag_Reg1 58 */ |
106 | #define ZLP_REG5 0x3E /* Zero_Flag_Reg5 62 */ | 106 | #define ZLP_REG5 0x3E /* Zero_Flag_Reg5 62 */ |
107 | 107 | ||
108 | /* For higher baud Rates use TIOCEXBAUD */ | 108 | /* For higher baud Rates use TIOCEXBAUD */ |
109 | #define TIOCEXBAUD 0x5462 | 109 | #define TIOCEXBAUD 0x5462 |
110 | 110 | ||
111 | /* vendor id and device id defines */ | 111 | /* vendor id and device id defines */ |
112 | 112 | ||
113 | /* The native mos7840/7820 component */ | 113 | /* The native mos7840/7820 component */ |
114 | #define USB_VENDOR_ID_MOSCHIP 0x9710 | 114 | #define USB_VENDOR_ID_MOSCHIP 0x9710 |
115 | #define MOSCHIP_DEVICE_ID_7840 0x7840 | 115 | #define MOSCHIP_DEVICE_ID_7840 0x7840 |
116 | #define MOSCHIP_DEVICE_ID_7820 0x7820 | 116 | #define MOSCHIP_DEVICE_ID_7820 0x7820 |
117 | /* The native component can have its vendor/device id's overridden | 117 | /* The native component can have its vendor/device id's overridden |
118 | * in vendor-specific implementations. Such devices can be handled | 118 | * in vendor-specific implementations. Such devices can be handled |
119 | * by making a change here, in moschip_port_id_table, and in | 119 | * by making a change here, in moschip_port_id_table, and in |
120 | * moschip_id_table_combined | 120 | * moschip_id_table_combined |
121 | */ | 121 | */ |
122 | #define USB_VENDOR_ID_BANDB 0x0856 | 122 | #define USB_VENDOR_ID_BANDB 0x0856 |
123 | #define BANDB_DEVICE_ID_USOPTL4_4 0xAC44 | 123 | #define BANDB_DEVICE_ID_USOPTL4_4 0xAC44 |
124 | #define BANDB_DEVICE_ID_USOPTL4_2 0xAC42 | 124 | #define BANDB_DEVICE_ID_USOPTL4_2 0xAC42 |
125 | 125 | ||
126 | /* Interrupt Routine Defines */ | 126 | /* Interrupt Routine Defines */ |
127 | 127 | ||
128 | #define SERIAL_IIR_RLS 0x06 | 128 | #define SERIAL_IIR_RLS 0x06 |
129 | #define SERIAL_IIR_MS 0x00 | 129 | #define SERIAL_IIR_MS 0x00 |
130 | 130 | ||
131 | /* | 131 | /* |
132 | * Emulation of the bit mask on the LINE STATUS REGISTER. | 132 | * Emulation of the bit mask on the LINE STATUS REGISTER. |
133 | */ | 133 | */ |
134 | #define SERIAL_LSR_DR 0x0001 | 134 | #define SERIAL_LSR_DR 0x0001 |
135 | #define SERIAL_LSR_OE 0x0002 | 135 | #define SERIAL_LSR_OE 0x0002 |
136 | #define SERIAL_LSR_PE 0x0004 | 136 | #define SERIAL_LSR_PE 0x0004 |
137 | #define SERIAL_LSR_FE 0x0008 | 137 | #define SERIAL_LSR_FE 0x0008 |
138 | #define SERIAL_LSR_BI 0x0010 | 138 | #define SERIAL_LSR_BI 0x0010 |
139 | 139 | ||
140 | #define MOS_MSR_DELTA_CTS 0x10 | 140 | #define MOS_MSR_DELTA_CTS 0x10 |
141 | #define MOS_MSR_DELTA_DSR 0x20 | 141 | #define MOS_MSR_DELTA_DSR 0x20 |
142 | #define MOS_MSR_DELTA_RI 0x40 | 142 | #define MOS_MSR_DELTA_RI 0x40 |
143 | #define MOS_MSR_DELTA_CD 0x80 | 143 | #define MOS_MSR_DELTA_CD 0x80 |
144 | 144 | ||
145 | /* Serial Port register Address */ | 145 | /* Serial Port register Address */ |
146 | #define INTERRUPT_ENABLE_REGISTER ((__u16)(0x01)) | 146 | #define INTERRUPT_ENABLE_REGISTER ((__u16)(0x01)) |
147 | #define FIFO_CONTROL_REGISTER ((__u16)(0x02)) | 147 | #define FIFO_CONTROL_REGISTER ((__u16)(0x02)) |
148 | #define LINE_CONTROL_REGISTER ((__u16)(0x03)) | 148 | #define LINE_CONTROL_REGISTER ((__u16)(0x03)) |
149 | #define MODEM_CONTROL_REGISTER ((__u16)(0x04)) | 149 | #define MODEM_CONTROL_REGISTER ((__u16)(0x04)) |
150 | #define LINE_STATUS_REGISTER ((__u16)(0x05)) | 150 | #define LINE_STATUS_REGISTER ((__u16)(0x05)) |
151 | #define MODEM_STATUS_REGISTER ((__u16)(0x06)) | 151 | #define MODEM_STATUS_REGISTER ((__u16)(0x06)) |
152 | #define SCRATCH_PAD_REGISTER ((__u16)(0x07)) | 152 | #define SCRATCH_PAD_REGISTER ((__u16)(0x07)) |
153 | #define DIVISOR_LATCH_LSB ((__u16)(0x00)) | 153 | #define DIVISOR_LATCH_LSB ((__u16)(0x00)) |
154 | #define DIVISOR_LATCH_MSB ((__u16)(0x01)) | 154 | #define DIVISOR_LATCH_MSB ((__u16)(0x01)) |
155 | 155 | ||
156 | #define CLK_MULTI_REGISTER ((__u16)(0x02)) | 156 | #define CLK_MULTI_REGISTER ((__u16)(0x02)) |
157 | #define CLK_START_VALUE_REGISTER ((__u16)(0x03)) | 157 | #define CLK_START_VALUE_REGISTER ((__u16)(0x03)) |
158 | 158 | ||
159 | #define SERIAL_LCR_DLAB ((__u16)(0x0080)) | 159 | #define SERIAL_LCR_DLAB ((__u16)(0x0080)) |
160 | 160 | ||
161 | /* | 161 | /* |
162 | * URB POOL related defines | 162 | * URB POOL related defines |
163 | */ | 163 | */ |
164 | #define NUM_URBS 16 /* URB Count */ | 164 | #define NUM_URBS 16 /* URB Count */ |
165 | #define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */ | 165 | #define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */ |
166 | 166 | ||
167 | 167 | ||
168 | static struct usb_device_id moschip_port_id_table[] = { | 168 | static struct usb_device_id moschip_port_id_table[] = { |
169 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, | 169 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, |
170 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, | 170 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, |
171 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, | 171 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, |
172 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, | 172 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, |
173 | {} /* terminating entry */ | 173 | {} /* terminating entry */ |
174 | }; | 174 | }; |
175 | 175 | ||
176 | static __devinitdata struct usb_device_id moschip_id_table_combined[] = { | 176 | static __devinitdata struct usb_device_id moschip_id_table_combined[] = { |
177 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, | 177 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, |
178 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, | 178 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, |
179 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, | 179 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, |
180 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, | 180 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, |
181 | {} /* terminating entry */ | 181 | {} /* terminating entry */ |
182 | }; | 182 | }; |
183 | 183 | ||
184 | MODULE_DEVICE_TABLE(usb, moschip_id_table_combined); | 184 | MODULE_DEVICE_TABLE(usb, moschip_id_table_combined); |
185 | 185 | ||
186 | /* This structure holds all of the local port information */ | 186 | /* This structure holds all of the local port information */ |
187 | 187 | ||
188 | struct moschip_port { | 188 | struct moschip_port { |
189 | int port_num; /*Actual port number in the device(1,2,etc) */ | 189 | int port_num; /*Actual port number in the device(1,2,etc) */ |
190 | struct urb *write_urb; /* write URB for this port */ | 190 | struct urb *write_urb; /* write URB for this port */ |
191 | struct urb *read_urb; /* read URB for this port */ | 191 | struct urb *read_urb; /* read URB for this port */ |
192 | struct urb *int_urb; | 192 | struct urb *int_urb; |
193 | __u8 shadowLCR; /* last LCR value received */ | 193 | __u8 shadowLCR; /* last LCR value received */ |
194 | __u8 shadowMCR; /* last MCR value received */ | 194 | __u8 shadowMCR; /* last MCR value received */ |
195 | char open; | 195 | char open; |
196 | char open_ports; | 196 | char open_ports; |
197 | char zombie; | 197 | char zombie; |
198 | wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ | 198 | wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ |
199 | wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */ | 199 | wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */ |
200 | int delta_msr_cond; | 200 | int delta_msr_cond; |
201 | struct async_icount icount; | 201 | struct async_icount icount; |
202 | struct usb_serial_port *port; /* loop back to the owner of this object */ | 202 | struct usb_serial_port *port; /* loop back to the owner of this object */ |
203 | 203 | ||
204 | /* Offsets */ | 204 | /* Offsets */ |
205 | __u8 SpRegOffset; | 205 | __u8 SpRegOffset; |
206 | __u8 ControlRegOffset; | 206 | __u8 ControlRegOffset; |
207 | __u8 DcrRegOffset; | 207 | __u8 DcrRegOffset; |
208 | /* for processing control URBS in interrupt context */ | 208 | /* for processing control URBS in interrupt context */ |
209 | struct urb *control_urb; | 209 | struct urb *control_urb; |
210 | struct usb_ctrlrequest *dr; | 210 | struct usb_ctrlrequest *dr; |
211 | char *ctrl_buf; | 211 | char *ctrl_buf; |
212 | int MsrLsr; | 212 | int MsrLsr; |
213 | 213 | ||
214 | spinlock_t pool_lock; | 214 | spinlock_t pool_lock; |
215 | struct urb *write_urb_pool[NUM_URBS]; | 215 | struct urb *write_urb_pool[NUM_URBS]; |
216 | char busy[NUM_URBS]; | 216 | char busy[NUM_URBS]; |
217 | }; | 217 | }; |
218 | 218 | ||
219 | 219 | ||
220 | static int debug; | 220 | static int debug; |
221 | 221 | ||
222 | /* | 222 | /* |
223 | * mos7840_set_reg_sync | 223 | * mos7840_set_reg_sync |
224 | * To set the Control register by calling usb_fill_control_urb function | 224 | * To set the Control register by calling usb_fill_control_urb function |
225 | * by passing usb_sndctrlpipe function as parameter. | 225 | * by passing usb_sndctrlpipe function as parameter. |
226 | */ | 226 | */ |
227 | 227 | ||
228 | static int mos7840_set_reg_sync(struct usb_serial_port *port, __u16 reg, | 228 | static int mos7840_set_reg_sync(struct usb_serial_port *port, __u16 reg, |
229 | __u16 val) | 229 | __u16 val) |
230 | { | 230 | { |
231 | struct usb_device *dev = port->serial->dev; | 231 | struct usb_device *dev = port->serial->dev; |
232 | val = val & 0x00ff; | 232 | val = val & 0x00ff; |
233 | dbg("mos7840_set_reg_sync offset is %x, value %x\n", reg, val); | 233 | dbg("mos7840_set_reg_sync offset is %x, value %x\n", reg, val); |
234 | 234 | ||
235 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ, | 235 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ, |
236 | MCS_WR_RTYPE, val, reg, NULL, 0, | 236 | MCS_WR_RTYPE, val, reg, NULL, 0, |
237 | MOS_WDR_TIMEOUT); | 237 | MOS_WDR_TIMEOUT); |
238 | } | 238 | } |
239 | 239 | ||
240 | /* | 240 | /* |
241 | * mos7840_get_reg_sync | 241 | * mos7840_get_reg_sync |
242 | * To set the Uart register by calling usb_fill_control_urb function by | 242 | * To set the Uart register by calling usb_fill_control_urb function by |
243 | * passing usb_rcvctrlpipe function as parameter. | 243 | * passing usb_rcvctrlpipe function as parameter. |
244 | */ | 244 | */ |
245 | 245 | ||
246 | static int mos7840_get_reg_sync(struct usb_serial_port *port, __u16 reg, | 246 | static int mos7840_get_reg_sync(struct usb_serial_port *port, __u16 reg, |
247 | __u16 *val) | 247 | __u16 *val) |
248 | { | 248 | { |
249 | struct usb_device *dev = port->serial->dev; | 249 | struct usb_device *dev = port->serial->dev; |
250 | int ret = 0; | 250 | int ret = 0; |
251 | 251 | ||
252 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, | 252 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, |
253 | MCS_RD_RTYPE, 0, reg, val, VENDOR_READ_LENGTH, | 253 | MCS_RD_RTYPE, 0, reg, val, VENDOR_READ_LENGTH, |
254 | MOS_WDR_TIMEOUT); | 254 | MOS_WDR_TIMEOUT); |
255 | dbg("mos7840_get_reg_sync offset is %x, return val %x\n", reg, *val); | 255 | dbg("mos7840_get_reg_sync offset is %x, return val %x\n", reg, *val); |
256 | *val = (*val) & 0x00ff; | 256 | *val = (*val) & 0x00ff; |
257 | return ret; | 257 | return ret; |
258 | } | 258 | } |
259 | 259 | ||
260 | /* | 260 | /* |
261 | * mos7840_set_uart_reg | 261 | * mos7840_set_uart_reg |
262 | * To set the Uart register by calling usb_fill_control_urb function by | 262 | * To set the Uart register by calling usb_fill_control_urb function by |
263 | * passing usb_sndctrlpipe function as parameter. | 263 | * passing usb_sndctrlpipe function as parameter. |
264 | */ | 264 | */ |
265 | 265 | ||
266 | static int mos7840_set_uart_reg(struct usb_serial_port *port, __u16 reg, | 266 | static int mos7840_set_uart_reg(struct usb_serial_port *port, __u16 reg, |
267 | __u16 val) | 267 | __u16 val) |
268 | { | 268 | { |
269 | 269 | ||
270 | struct usb_device *dev = port->serial->dev; | 270 | struct usb_device *dev = port->serial->dev; |
271 | val = val & 0x00ff; | 271 | val = val & 0x00ff; |
272 | /* For the UART control registers, the application number need | 272 | /* For the UART control registers, the application number need |
273 | to be Or'ed */ | 273 | to be Or'ed */ |
274 | if (port->serial->num_ports == 4) { | 274 | if (port->serial->num_ports == 4) { |
275 | val |= (((__u16) port->number - | 275 | val |= (((__u16) port->number - |
276 | (__u16) (port->serial->minor)) + 1) << 8; | 276 | (__u16) (port->serial->minor)) + 1) << 8; |
277 | dbg("mos7840_set_uart_reg application number is %x\n", val); | 277 | dbg("mos7840_set_uart_reg application number is %x\n", val); |
278 | } else { | 278 | } else { |
279 | if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) { | 279 | if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) { |
280 | val |= (((__u16) port->number - | 280 | val |= (((__u16) port->number - |
281 | (__u16) (port->serial->minor)) + 1) << 8; | 281 | (__u16) (port->serial->minor)) + 1) << 8; |
282 | dbg("mos7840_set_uart_reg application number is %x\n", | 282 | dbg("mos7840_set_uart_reg application number is %x\n", |
283 | val); | 283 | val); |
284 | } else { | 284 | } else { |
285 | val |= | 285 | val |= |
286 | (((__u16) port->number - | 286 | (((__u16) port->number - |
287 | (__u16) (port->serial->minor)) + 2) << 8; | 287 | (__u16) (port->serial->minor)) + 2) << 8; |
288 | dbg("mos7840_set_uart_reg application number is %x\n", | 288 | dbg("mos7840_set_uart_reg application number is %x\n", |
289 | val); | 289 | val); |
290 | } | 290 | } |
291 | } | 291 | } |
292 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ, | 292 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ, |
293 | MCS_WR_RTYPE, val, reg, NULL, 0, | 293 | MCS_WR_RTYPE, val, reg, NULL, 0, |
294 | MOS_WDR_TIMEOUT); | 294 | MOS_WDR_TIMEOUT); |
295 | 295 | ||
296 | } | 296 | } |
297 | 297 | ||
298 | /* | 298 | /* |
299 | * mos7840_get_uart_reg | 299 | * mos7840_get_uart_reg |
300 | * To set the Control register by calling usb_fill_control_urb function | 300 | * To set the Control register by calling usb_fill_control_urb function |
301 | * by passing usb_rcvctrlpipe function as parameter. | 301 | * by passing usb_rcvctrlpipe function as parameter. |
302 | */ | 302 | */ |
303 | static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg, | 303 | static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg, |
304 | __u16 *val) | 304 | __u16 *val) |
305 | { | 305 | { |
306 | struct usb_device *dev = port->serial->dev; | 306 | struct usb_device *dev = port->serial->dev; |
307 | int ret = 0; | 307 | int ret = 0; |
308 | __u16 Wval; | 308 | __u16 Wval; |
309 | 309 | ||
310 | /* dbg("application number is %4x \n", | 310 | /* dbg("application number is %4x \n", |
311 | (((__u16)port->number - (__u16)(port->serial->minor))+1)<<8); */ | 311 | (((__u16)port->number - (__u16)(port->serial->minor))+1)<<8); */ |
312 | /* Wval is same as application number */ | 312 | /* Wval is same as application number */ |
313 | if (port->serial->num_ports == 4) { | 313 | if (port->serial->num_ports == 4) { |
314 | Wval = | 314 | Wval = |
315 | (((__u16) port->number - (__u16) (port->serial->minor)) + | 315 | (((__u16) port->number - (__u16) (port->serial->minor)) + |
316 | 1) << 8; | 316 | 1) << 8; |
317 | dbg("mos7840_get_uart_reg application number is %x\n", Wval); | 317 | dbg("mos7840_get_uart_reg application number is %x\n", Wval); |
318 | } else { | 318 | } else { |
319 | if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) { | 319 | if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) { |
320 | Wval = (((__u16) port->number - | 320 | Wval = (((__u16) port->number - |
321 | (__u16) (port->serial->minor)) + 1) << 8; | 321 | (__u16) (port->serial->minor)) + 1) << 8; |
322 | dbg("mos7840_get_uart_reg application number is %x\n", | 322 | dbg("mos7840_get_uart_reg application number is %x\n", |
323 | Wval); | 323 | Wval); |
324 | } else { | 324 | } else { |
325 | Wval = (((__u16) port->number - | 325 | Wval = (((__u16) port->number - |
326 | (__u16) (port->serial->minor)) + 2) << 8; | 326 | (__u16) (port->serial->minor)) + 2) << 8; |
327 | dbg("mos7840_get_uart_reg application number is %x\n", | 327 | dbg("mos7840_get_uart_reg application number is %x\n", |
328 | Wval); | 328 | Wval); |
329 | } | 329 | } |
330 | } | 330 | } |
331 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, | 331 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, |
332 | MCS_RD_RTYPE, Wval, reg, val, VENDOR_READ_LENGTH, | 332 | MCS_RD_RTYPE, Wval, reg, val, VENDOR_READ_LENGTH, |
333 | MOS_WDR_TIMEOUT); | 333 | MOS_WDR_TIMEOUT); |
334 | *val = (*val) & 0x00ff; | 334 | *val = (*val) & 0x00ff; |
335 | return ret; | 335 | return ret; |
336 | } | 336 | } |
337 | 337 | ||
338 | static void mos7840_dump_serial_port(struct moschip_port *mos7840_port) | 338 | static void mos7840_dump_serial_port(struct moschip_port *mos7840_port) |
339 | { | 339 | { |
340 | 340 | ||
341 | dbg("***************************************\n"); | 341 | dbg("***************************************\n"); |
342 | dbg("SpRegOffset is %2x\n", mos7840_port->SpRegOffset); | 342 | dbg("SpRegOffset is %2x\n", mos7840_port->SpRegOffset); |
343 | dbg("ControlRegOffset is %2x \n", mos7840_port->ControlRegOffset); | 343 | dbg("ControlRegOffset is %2x \n", mos7840_port->ControlRegOffset); |
344 | dbg("DCRRegOffset is %2x \n", mos7840_port->DcrRegOffset); | 344 | dbg("DCRRegOffset is %2x \n", mos7840_port->DcrRegOffset); |
345 | dbg("***************************************\n"); | 345 | dbg("***************************************\n"); |
346 | 346 | ||
347 | } | 347 | } |
348 | 348 | ||
349 | /************************************************************************/ | 349 | /************************************************************************/ |
350 | /************************************************************************/ | 350 | /************************************************************************/ |
351 | /* I N T E R F A C E F U N C T I O N S */ | 351 | /* I N T E R F A C E F U N C T I O N S */ |
352 | /* I N T E R F A C E F U N C T I O N S */ | 352 | /* I N T E R F A C E F U N C T I O N S */ |
353 | /************************************************************************/ | 353 | /************************************************************************/ |
354 | /************************************************************************/ | 354 | /************************************************************************/ |
355 | 355 | ||
356 | static inline void mos7840_set_port_private(struct usb_serial_port *port, | 356 | static inline void mos7840_set_port_private(struct usb_serial_port *port, |
357 | struct moschip_port *data) | 357 | struct moschip_port *data) |
358 | { | 358 | { |
359 | usb_set_serial_port_data(port, (void *)data); | 359 | usb_set_serial_port_data(port, (void *)data); |
360 | } | 360 | } |
361 | 361 | ||
362 | static inline struct moschip_port *mos7840_get_port_private(struct | 362 | static inline struct moschip_port *mos7840_get_port_private(struct |
363 | usb_serial_port | 363 | usb_serial_port |
364 | *port) | 364 | *port) |
365 | { | 365 | { |
366 | return (struct moschip_port *)usb_get_serial_port_data(port); | 366 | return (struct moschip_port *)usb_get_serial_port_data(port); |
367 | } | 367 | } |
368 | 368 | ||
369 | static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr) | 369 | static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr) |
370 | { | 370 | { |
371 | struct moschip_port *mos7840_port; | 371 | struct moschip_port *mos7840_port; |
372 | struct async_icount *icount; | 372 | struct async_icount *icount; |
373 | mos7840_port = port; | 373 | mos7840_port = port; |
374 | icount = &mos7840_port->icount; | 374 | icount = &mos7840_port->icount; |
375 | if (new_msr & | 375 | if (new_msr & |
376 | (MOS_MSR_DELTA_CTS | MOS_MSR_DELTA_DSR | MOS_MSR_DELTA_RI | | 376 | (MOS_MSR_DELTA_CTS | MOS_MSR_DELTA_DSR | MOS_MSR_DELTA_RI | |
377 | MOS_MSR_DELTA_CD)) { | 377 | MOS_MSR_DELTA_CD)) { |
378 | icount = &mos7840_port->icount; | 378 | icount = &mos7840_port->icount; |
379 | 379 | ||
380 | /* update input line counters */ | 380 | /* update input line counters */ |
381 | if (new_msr & MOS_MSR_DELTA_CTS) { | 381 | if (new_msr & MOS_MSR_DELTA_CTS) { |
382 | icount->cts++; | 382 | icount->cts++; |
383 | smp_wmb(); | 383 | smp_wmb(); |
384 | } | 384 | } |
385 | if (new_msr & MOS_MSR_DELTA_DSR) { | 385 | if (new_msr & MOS_MSR_DELTA_DSR) { |
386 | icount->dsr++; | 386 | icount->dsr++; |
387 | smp_wmb(); | 387 | smp_wmb(); |
388 | } | 388 | } |
389 | if (new_msr & MOS_MSR_DELTA_CD) { | 389 | if (new_msr & MOS_MSR_DELTA_CD) { |
390 | icount->dcd++; | 390 | icount->dcd++; |
391 | smp_wmb(); | 391 | smp_wmb(); |
392 | } | 392 | } |
393 | if (new_msr & MOS_MSR_DELTA_RI) { | 393 | if (new_msr & MOS_MSR_DELTA_RI) { |
394 | icount->rng++; | 394 | icount->rng++; |
395 | smp_wmb(); | 395 | smp_wmb(); |
396 | } | 396 | } |
397 | } | 397 | } |
398 | } | 398 | } |
399 | 399 | ||
400 | static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr) | 400 | static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr) |
401 | { | 401 | { |
402 | struct async_icount *icount; | 402 | struct async_icount *icount; |
403 | 403 | ||
404 | dbg("%s - %02x", __func__, new_lsr); | 404 | dbg("%s - %02x", __func__, new_lsr); |
405 | 405 | ||
406 | if (new_lsr & SERIAL_LSR_BI) { | 406 | if (new_lsr & SERIAL_LSR_BI) { |
407 | /* | 407 | /* |
408 | * Parity and Framing errors only count if they | 408 | * Parity and Framing errors only count if they |
409 | * occur exclusive of a break being | 409 | * occur exclusive of a break being |
410 | * received. | 410 | * received. |
411 | */ | 411 | */ |
412 | new_lsr &= (__u8) (SERIAL_LSR_OE | SERIAL_LSR_BI); | 412 | new_lsr &= (__u8) (SERIAL_LSR_OE | SERIAL_LSR_BI); |
413 | } | 413 | } |
414 | 414 | ||
415 | /* update input line counters */ | 415 | /* update input line counters */ |
416 | icount = &port->icount; | 416 | icount = &port->icount; |
417 | if (new_lsr & SERIAL_LSR_BI) { | 417 | if (new_lsr & SERIAL_LSR_BI) { |
418 | icount->brk++; | 418 | icount->brk++; |
419 | smp_wmb(); | 419 | smp_wmb(); |
420 | } | 420 | } |
421 | if (new_lsr & SERIAL_LSR_OE) { | 421 | if (new_lsr & SERIAL_LSR_OE) { |
422 | icount->overrun++; | 422 | icount->overrun++; |
423 | smp_wmb(); | 423 | smp_wmb(); |
424 | } | 424 | } |
425 | if (new_lsr & SERIAL_LSR_PE) { | 425 | if (new_lsr & SERIAL_LSR_PE) { |
426 | icount->parity++; | 426 | icount->parity++; |
427 | smp_wmb(); | 427 | smp_wmb(); |
428 | } | 428 | } |
429 | if (new_lsr & SERIAL_LSR_FE) { | 429 | if (new_lsr & SERIAL_LSR_FE) { |
430 | icount->frame++; | 430 | icount->frame++; |
431 | smp_wmb(); | 431 | smp_wmb(); |
432 | } | 432 | } |
433 | } | 433 | } |
434 | 434 | ||
435 | /************************************************************************/ | 435 | /************************************************************************/ |
436 | /************************************************************************/ | 436 | /************************************************************************/ |
437 | /* U S B C A L L B A C K F U N C T I O N S */ | 437 | /* U S B C A L L B A C K F U N C T I O N S */ |
438 | /* U S B C A L L B A C K F U N C T I O N S */ | 438 | /* U S B C A L L B A C K F U N C T I O N S */ |
439 | /************************************************************************/ | 439 | /************************************************************************/ |
440 | /************************************************************************/ | 440 | /************************************************************************/ |
441 | 441 | ||
442 | static void mos7840_control_callback(struct urb *urb) | 442 | static void mos7840_control_callback(struct urb *urb) |
443 | { | 443 | { |
444 | unsigned char *data; | 444 | unsigned char *data; |
445 | struct moschip_port *mos7840_port; | 445 | struct moschip_port *mos7840_port; |
446 | __u8 regval = 0x0; | 446 | __u8 regval = 0x0; |
447 | int result = 0; | 447 | int result = 0; |
448 | int status = urb->status; | 448 | int status = urb->status; |
449 | 449 | ||
450 | mos7840_port = urb->context; | 450 | mos7840_port = urb->context; |
451 | 451 | ||
452 | switch (status) { | 452 | switch (status) { |
453 | case 0: | 453 | case 0: |
454 | /* success */ | 454 | /* success */ |
455 | break; | 455 | break; |
456 | case -ECONNRESET: | 456 | case -ECONNRESET: |
457 | case -ENOENT: | 457 | case -ENOENT: |
458 | case -ESHUTDOWN: | 458 | case -ESHUTDOWN: |
459 | /* this urb is terminated, clean up */ | 459 | /* this urb is terminated, clean up */ |
460 | dbg("%s - urb shutting down with status: %d", __func__, | 460 | dbg("%s - urb shutting down with status: %d", __func__, |
461 | status); | 461 | status); |
462 | return; | 462 | return; |
463 | default: | 463 | default: |
464 | dbg("%s - nonzero urb status received: %d", __func__, | 464 | dbg("%s - nonzero urb status received: %d", __func__, |
465 | status); | 465 | status); |
466 | goto exit; | 466 | goto exit; |
467 | } | 467 | } |
468 | 468 | ||
469 | dbg("%s urb buffer size is %d\n", __func__, urb->actual_length); | 469 | dbg("%s urb buffer size is %d\n", __func__, urb->actual_length); |
470 | dbg("%s mos7840_port->MsrLsr is %d port %d\n", __func__, | 470 | dbg("%s mos7840_port->MsrLsr is %d port %d\n", __func__, |
471 | mos7840_port->MsrLsr, mos7840_port->port_num); | 471 | mos7840_port->MsrLsr, mos7840_port->port_num); |
472 | data = urb->transfer_buffer; | 472 | data = urb->transfer_buffer; |
473 | regval = (__u8) data[0]; | 473 | regval = (__u8) data[0]; |
474 | dbg("%s data is %x\n", __func__, regval); | 474 | dbg("%s data is %x\n", __func__, regval); |
475 | if (mos7840_port->MsrLsr == 0) | 475 | if (mos7840_port->MsrLsr == 0) |
476 | mos7840_handle_new_msr(mos7840_port, regval); | 476 | mos7840_handle_new_msr(mos7840_port, regval); |
477 | else if (mos7840_port->MsrLsr == 1) | 477 | else if (mos7840_port->MsrLsr == 1) |
478 | mos7840_handle_new_lsr(mos7840_port, regval); | 478 | mos7840_handle_new_lsr(mos7840_port, regval); |
479 | 479 | ||
480 | exit: | 480 | exit: |
481 | spin_lock(&mos7840_port->pool_lock); | 481 | spin_lock(&mos7840_port->pool_lock); |
482 | if (!mos7840_port->zombie) | 482 | if (!mos7840_port->zombie) |
483 | result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC); | 483 | result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC); |
484 | spin_unlock(&mos7840_port->pool_lock); | 484 | spin_unlock(&mos7840_port->pool_lock); |
485 | if (result) { | 485 | if (result) { |
486 | dev_err(&urb->dev->dev, | 486 | dev_err(&urb->dev->dev, |
487 | "%s - Error %d submitting interrupt urb\n", | 487 | "%s - Error %d submitting interrupt urb\n", |
488 | __func__, result); | 488 | __func__, result); |
489 | } | 489 | } |
490 | } | 490 | } |
491 | 491 | ||
492 | static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, | 492 | static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, |
493 | __u16 *val) | 493 | __u16 *val) |
494 | { | 494 | { |
495 | struct usb_device *dev = mcs->port->serial->dev; | 495 | struct usb_device *dev = mcs->port->serial->dev; |
496 | struct usb_ctrlrequest *dr = mcs->dr; | 496 | struct usb_ctrlrequest *dr = mcs->dr; |
497 | unsigned char *buffer = mcs->ctrl_buf; | 497 | unsigned char *buffer = mcs->ctrl_buf; |
498 | int ret; | 498 | int ret; |
499 | 499 | ||
500 | dr->bRequestType = MCS_RD_RTYPE; | 500 | dr->bRequestType = MCS_RD_RTYPE; |
501 | dr->bRequest = MCS_RDREQ; | 501 | dr->bRequest = MCS_RDREQ; |
502 | dr->wValue = cpu_to_le16(Wval); /* 0 */ | 502 | dr->wValue = cpu_to_le16(Wval); /* 0 */ |
503 | dr->wIndex = cpu_to_le16(reg); | 503 | dr->wIndex = cpu_to_le16(reg); |
504 | dr->wLength = cpu_to_le16(2); | 504 | dr->wLength = cpu_to_le16(2); |
505 | 505 | ||
506 | usb_fill_control_urb(mcs->control_urb, dev, usb_rcvctrlpipe(dev, 0), | 506 | usb_fill_control_urb(mcs->control_urb, dev, usb_rcvctrlpipe(dev, 0), |
507 | (unsigned char *)dr, buffer, 2, | 507 | (unsigned char *)dr, buffer, 2, |
508 | mos7840_control_callback, mcs); | 508 | mos7840_control_callback, mcs); |
509 | mcs->control_urb->transfer_buffer_length = 2; | 509 | mcs->control_urb->transfer_buffer_length = 2; |
510 | ret = usb_submit_urb(mcs->control_urb, GFP_ATOMIC); | 510 | ret = usb_submit_urb(mcs->control_urb, GFP_ATOMIC); |
511 | return ret; | 511 | return ret; |
512 | } | 512 | } |
513 | 513 | ||
514 | /***************************************************************************** | 514 | /***************************************************************************** |
515 | * mos7840_interrupt_callback | 515 | * mos7840_interrupt_callback |
516 | * this is the callback function for when we have received data on the | 516 | * this is the callback function for when we have received data on the |
517 | * interrupt endpoint. | 517 | * interrupt endpoint. |
518 | *****************************************************************************/ | 518 | *****************************************************************************/ |
519 | 519 | ||
520 | static void mos7840_interrupt_callback(struct urb *urb) | 520 | static void mos7840_interrupt_callback(struct urb *urb) |
521 | { | 521 | { |
522 | int result; | 522 | int result; |
523 | int length; | 523 | int length; |
524 | struct moschip_port *mos7840_port; | 524 | struct moschip_port *mos7840_port; |
525 | struct usb_serial *serial; | 525 | struct usb_serial *serial; |
526 | __u16 Data; | 526 | __u16 Data; |
527 | unsigned char *data; | 527 | unsigned char *data; |
528 | __u8 sp[5], st; | 528 | __u8 sp[5], st; |
529 | int i, rv = 0; | 529 | int i, rv = 0; |
530 | __u16 wval, wreg = 0; | 530 | __u16 wval, wreg = 0; |
531 | int status = urb->status; | 531 | int status = urb->status; |
532 | 532 | ||
533 | dbg("%s", " : Entering\n"); | 533 | dbg("%s", " : Entering\n"); |
534 | 534 | ||
535 | switch (status) { | 535 | switch (status) { |
536 | case 0: | 536 | case 0: |
537 | /* success */ | 537 | /* success */ |
538 | break; | 538 | break; |
539 | case -ECONNRESET: | 539 | case -ECONNRESET: |
540 | case -ENOENT: | 540 | case -ENOENT: |
541 | case -ESHUTDOWN: | 541 | case -ESHUTDOWN: |
542 | /* this urb is terminated, clean up */ | 542 | /* this urb is terminated, clean up */ |
543 | dbg("%s - urb shutting down with status: %d", __func__, | 543 | dbg("%s - urb shutting down with status: %d", __func__, |
544 | status); | 544 | status); |
545 | return; | 545 | return; |
546 | default: | 546 | default: |
547 | dbg("%s - nonzero urb status received: %d", __func__, | 547 | dbg("%s - nonzero urb status received: %d", __func__, |
548 | status); | 548 | status); |
549 | goto exit; | 549 | goto exit; |
550 | } | 550 | } |
551 | 551 | ||
552 | length = urb->actual_length; | 552 | length = urb->actual_length; |
553 | data = urb->transfer_buffer; | 553 | data = urb->transfer_buffer; |
554 | 554 | ||
555 | serial = urb->context; | 555 | serial = urb->context; |
556 | 556 | ||
557 | /* Moschip get 5 bytes | 557 | /* Moschip get 5 bytes |
558 | * Byte 1 IIR Port 1 (port.number is 0) | 558 | * Byte 1 IIR Port 1 (port.number is 0) |
559 | * Byte 2 IIR Port 2 (port.number is 1) | 559 | * Byte 2 IIR Port 2 (port.number is 1) |
560 | * Byte 3 IIR Port 3 (port.number is 2) | 560 | * Byte 3 IIR Port 3 (port.number is 2) |
561 | * Byte 4 IIR Port 4 (port.number is 3) | 561 | * Byte 4 IIR Port 4 (port.number is 3) |
562 | * Byte 5 FIFO status for both */ | 562 | * Byte 5 FIFO status for both */ |
563 | 563 | ||
564 | if (length && length > 5) { | 564 | if (length && length > 5) { |
565 | dbg("%s \n", "Wrong data !!!"); | 565 | dbg("%s \n", "Wrong data !!!"); |
566 | return; | 566 | return; |
567 | } | 567 | } |
568 | 568 | ||
569 | sp[0] = (__u8) data[0]; | 569 | sp[0] = (__u8) data[0]; |
570 | sp[1] = (__u8) data[1]; | 570 | sp[1] = (__u8) data[1]; |
571 | sp[2] = (__u8) data[2]; | 571 | sp[2] = (__u8) data[2]; |
572 | sp[3] = (__u8) data[3]; | 572 | sp[3] = (__u8) data[3]; |
573 | st = (__u8) data[4]; | 573 | st = (__u8) data[4]; |
574 | 574 | ||
575 | for (i = 0; i < serial->num_ports; i++) { | 575 | for (i = 0; i < serial->num_ports; i++) { |
576 | mos7840_port = mos7840_get_port_private(serial->port[i]); | 576 | mos7840_port = mos7840_get_port_private(serial->port[i]); |
577 | wval = | 577 | wval = |
578 | (((__u16) serial->port[i]->number - | 578 | (((__u16) serial->port[i]->number - |
579 | (__u16) (serial->minor)) + 1) << 8; | 579 | (__u16) (serial->minor)) + 1) << 8; |
580 | if (mos7840_port->open) { | 580 | if (mos7840_port->open) { |
581 | if (sp[i] & 0x01) { | 581 | if (sp[i] & 0x01) { |
582 | dbg("SP%d No Interrupt !!!\n", i); | 582 | dbg("SP%d No Interrupt !!!\n", i); |
583 | } else { | 583 | } else { |
584 | switch (sp[i] & 0x0f) { | 584 | switch (sp[i] & 0x0f) { |
585 | case SERIAL_IIR_RLS: | 585 | case SERIAL_IIR_RLS: |
586 | dbg("Serial Port %d: Receiver status error or ", i); | 586 | dbg("Serial Port %d: Receiver status error or ", i); |
587 | dbg("address bit detected in 9-bit mode\n"); | 587 | dbg("address bit detected in 9-bit mode\n"); |
588 | mos7840_port->MsrLsr = 1; | 588 | mos7840_port->MsrLsr = 1; |
589 | wreg = LINE_STATUS_REGISTER; | 589 | wreg = LINE_STATUS_REGISTER; |
590 | break; | 590 | break; |
591 | case SERIAL_IIR_MS: | 591 | case SERIAL_IIR_MS: |
592 | dbg("Serial Port %d: Modem status change\n", i); | 592 | dbg("Serial Port %d: Modem status change\n", i); |
593 | mos7840_port->MsrLsr = 0; | 593 | mos7840_port->MsrLsr = 0; |
594 | wreg = MODEM_STATUS_REGISTER; | 594 | wreg = MODEM_STATUS_REGISTER; |
595 | break; | 595 | break; |
596 | } | 596 | } |
597 | spin_lock(&mos7840_port->pool_lock); | 597 | spin_lock(&mos7840_port->pool_lock); |
598 | if (!mos7840_port->zombie) { | 598 | if (!mos7840_port->zombie) { |
599 | rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data); | 599 | rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data); |
600 | } else { | 600 | } else { |
601 | spin_unlock(&mos7840_port->pool_lock); | 601 | spin_unlock(&mos7840_port->pool_lock); |
602 | return; | 602 | return; |
603 | } | 603 | } |
604 | spin_unlock(&mos7840_port->pool_lock); | 604 | spin_unlock(&mos7840_port->pool_lock); |
605 | } | 605 | } |
606 | } | 606 | } |
607 | } | 607 | } |
608 | if (!(rv < 0)) | 608 | if (!(rv < 0)) |
609 | /* the completion handler for the control urb will resubmit */ | 609 | /* the completion handler for the control urb will resubmit */ |
610 | return; | 610 | return; |
611 | exit: | 611 | exit: |
612 | result = usb_submit_urb(urb, GFP_ATOMIC); | 612 | result = usb_submit_urb(urb, GFP_ATOMIC); |
613 | if (result) { | 613 | if (result) { |
614 | dev_err(&urb->dev->dev, | 614 | dev_err(&urb->dev->dev, |
615 | "%s - Error %d submitting interrupt urb\n", | 615 | "%s - Error %d submitting interrupt urb\n", |
616 | __func__, result); | 616 | __func__, result); |
617 | } | 617 | } |
618 | } | 618 | } |
619 | 619 | ||
620 | static int mos7840_port_paranoia_check(struct usb_serial_port *port, | 620 | static int mos7840_port_paranoia_check(struct usb_serial_port *port, |
621 | const char *function) | 621 | const char *function) |
622 | { | 622 | { |
623 | if (!port) { | 623 | if (!port) { |
624 | dbg("%s - port == NULL", function); | 624 | dbg("%s - port == NULL", function); |
625 | return -1; | 625 | return -1; |
626 | } | 626 | } |
627 | if (!port->serial) { | 627 | if (!port->serial) { |
628 | dbg("%s - port->serial == NULL", function); | 628 | dbg("%s - port->serial == NULL", function); |
629 | return -1; | 629 | return -1; |
630 | } | 630 | } |
631 | 631 | ||
632 | return 0; | 632 | return 0; |
633 | } | 633 | } |
634 | 634 | ||
635 | /* Inline functions to check the sanity of a pointer that is passed to us */ | 635 | /* Inline functions to check the sanity of a pointer that is passed to us */ |
636 | static int mos7840_serial_paranoia_check(struct usb_serial *serial, | 636 | static int mos7840_serial_paranoia_check(struct usb_serial *serial, |
637 | const char *function) | 637 | const char *function) |
638 | { | 638 | { |
639 | if (!serial) { | 639 | if (!serial) { |
640 | dbg("%s - serial == NULL", function); | 640 | dbg("%s - serial == NULL", function); |
641 | return -1; | 641 | return -1; |
642 | } | 642 | } |
643 | if (!serial->type) { | 643 | if (!serial->type) { |
644 | dbg("%s - serial->type == NULL!", function); | 644 | dbg("%s - serial->type == NULL!", function); |
645 | return -1; | 645 | return -1; |
646 | } | 646 | } |
647 | 647 | ||
648 | return 0; | 648 | return 0; |
649 | } | 649 | } |
650 | 650 | ||
651 | static struct usb_serial *mos7840_get_usb_serial(struct usb_serial_port *port, | 651 | static struct usb_serial *mos7840_get_usb_serial(struct usb_serial_port *port, |
652 | const char *function) | 652 | const char *function) |
653 | { | 653 | { |
654 | /* if no port was specified, or it fails a paranoia check */ | 654 | /* if no port was specified, or it fails a paranoia check */ |
655 | if (!port || | 655 | if (!port || |
656 | mos7840_port_paranoia_check(port, function) || | 656 | mos7840_port_paranoia_check(port, function) || |
657 | mos7840_serial_paranoia_check(port->serial, function)) { | 657 | mos7840_serial_paranoia_check(port->serial, function)) { |
658 | /* then say that we don't have a valid usb_serial thing, | 658 | /* then say that we don't have a valid usb_serial thing, |
659 | * which will end up genrating -ENODEV return values */ | 659 | * which will end up genrating -ENODEV return values */ |
660 | return NULL; | 660 | return NULL; |
661 | } | 661 | } |
662 | 662 | ||
663 | return port->serial; | 663 | return port->serial; |
664 | } | 664 | } |
665 | 665 | ||
666 | /***************************************************************************** | 666 | /***************************************************************************** |
667 | * mos7840_bulk_in_callback | 667 | * mos7840_bulk_in_callback |
668 | * this is the callback function for when we have received data on the | 668 | * this is the callback function for when we have received data on the |
669 | * bulk in endpoint. | 669 | * bulk in endpoint. |
670 | *****************************************************************************/ | 670 | *****************************************************************************/ |
671 | 671 | ||
672 | static void mos7840_bulk_in_callback(struct urb *urb) | 672 | static void mos7840_bulk_in_callback(struct urb *urb) |
673 | { | 673 | { |
674 | int retval; | 674 | int retval; |
675 | unsigned char *data; | 675 | unsigned char *data; |
676 | struct usb_serial *serial; | 676 | struct usb_serial *serial; |
677 | struct usb_serial_port *port; | 677 | struct usb_serial_port *port; |
678 | struct moschip_port *mos7840_port; | 678 | struct moschip_port *mos7840_port; |
679 | struct tty_struct *tty; | 679 | struct tty_struct *tty; |
680 | int status = urb->status; | 680 | int status = urb->status; |
681 | 681 | ||
682 | if (status) { | 682 | if (status) { |
683 | dbg("nonzero read bulk status received: %d", status); | 683 | dbg("nonzero read bulk status received: %d", status); |
684 | return; | 684 | return; |
685 | } | 685 | } |
686 | 686 | ||
687 | mos7840_port = urb->context; | 687 | mos7840_port = urb->context; |
688 | if (!mos7840_port) { | 688 | if (!mos7840_port) { |
689 | dbg("%s", "NULL mos7840_port pointer \n"); | 689 | dbg("%s", "NULL mos7840_port pointer \n"); |
690 | return; | 690 | return; |
691 | } | 691 | } |
692 | 692 | ||
693 | port = (struct usb_serial_port *)mos7840_port->port; | 693 | port = (struct usb_serial_port *)mos7840_port->port; |
694 | if (mos7840_port_paranoia_check(port, __func__)) { | 694 | if (mos7840_port_paranoia_check(port, __func__)) { |
695 | dbg("%s", "Port Paranoia failed \n"); | 695 | dbg("%s", "Port Paranoia failed \n"); |
696 | return; | 696 | return; |
697 | } | 697 | } |
698 | 698 | ||
699 | serial = mos7840_get_usb_serial(port, __func__); | 699 | serial = mos7840_get_usb_serial(port, __func__); |
700 | if (!serial) { | 700 | if (!serial) { |
701 | dbg("%s\n", "Bad serial pointer "); | 701 | dbg("%s\n", "Bad serial pointer "); |
702 | return; | 702 | return; |
703 | } | 703 | } |
704 | 704 | ||
705 | dbg("%s\n", "Entering... \n"); | 705 | dbg("%s\n", "Entering... \n"); |
706 | 706 | ||
707 | data = urb->transfer_buffer; | 707 | data = urb->transfer_buffer; |
708 | 708 | ||
709 | dbg("%s", "Entering ........... \n"); | 709 | dbg("%s", "Entering ........... \n"); |
710 | 710 | ||
711 | if (urb->actual_length) { | 711 | if (urb->actual_length) { |
712 | tty = tty_port_tty_get(&mos7840_port->port->port); | 712 | tty = tty_port_tty_get(&mos7840_port->port->port); |
713 | if (tty) { | 713 | if (tty) { |
714 | tty_buffer_request_room(tty, urb->actual_length); | 714 | tty_buffer_request_room(tty, urb->actual_length); |
715 | tty_insert_flip_string(tty, data, urb->actual_length); | 715 | tty_insert_flip_string(tty, data, urb->actual_length); |
716 | dbg(" %s \n", data); | 716 | dbg(" %s \n", data); |
717 | tty_flip_buffer_push(tty); | 717 | tty_flip_buffer_push(tty); |
718 | tty_kref_put(tty); | 718 | tty_kref_put(tty); |
719 | } | 719 | } |
720 | mos7840_port->icount.rx += urb->actual_length; | 720 | mos7840_port->icount.rx += urb->actual_length; |
721 | smp_wmb(); | 721 | smp_wmb(); |
722 | dbg("mos7840_port->icount.rx is %d:\n", | 722 | dbg("mos7840_port->icount.rx is %d:\n", |
723 | mos7840_port->icount.rx); | 723 | mos7840_port->icount.rx); |
724 | } | 724 | } |
725 | 725 | ||
726 | if (!mos7840_port->read_urb) { | 726 | if (!mos7840_port->read_urb) { |
727 | dbg("%s", "URB KILLED !!!\n"); | 727 | dbg("%s", "URB KILLED !!!\n"); |
728 | return; | 728 | return; |
729 | } | 729 | } |
730 | 730 | ||
731 | 731 | ||
732 | mos7840_port->read_urb->dev = serial->dev; | 732 | mos7840_port->read_urb->dev = serial->dev; |
733 | 733 | ||
734 | retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); | 734 | retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); |
735 | 735 | ||
736 | if (retval) { | 736 | if (retval) { |
737 | dbg(" usb_submit_urb(read bulk) failed, retval = %d", | 737 | dbg(" usb_submit_urb(read bulk) failed, retval = %d", |
738 | retval); | 738 | retval); |
739 | } | 739 | } |
740 | } | 740 | } |
741 | 741 | ||
742 | /***************************************************************************** | 742 | /***************************************************************************** |
743 | * mos7840_bulk_out_data_callback | 743 | * mos7840_bulk_out_data_callback |
744 | * this is the callback function for when we have finished sending | 744 | * this is the callback function for when we have finished sending |
745 | * serial data on the bulk out endpoint. | 745 | * serial data on the bulk out endpoint. |
746 | *****************************************************************************/ | 746 | *****************************************************************************/ |
747 | 747 | ||
748 | static void mos7840_bulk_out_data_callback(struct urb *urb) | 748 | static void mos7840_bulk_out_data_callback(struct urb *urb) |
749 | { | 749 | { |
750 | struct moschip_port *mos7840_port; | 750 | struct moschip_port *mos7840_port; |
751 | struct tty_struct *tty; | 751 | struct tty_struct *tty; |
752 | int status = urb->status; | 752 | int status = urb->status; |
753 | int i; | 753 | int i; |
754 | 754 | ||
755 | mos7840_port = urb->context; | 755 | mos7840_port = urb->context; |
756 | spin_lock(&mos7840_port->pool_lock); | 756 | spin_lock(&mos7840_port->pool_lock); |
757 | for (i = 0; i < NUM_URBS; i++) { | 757 | for (i = 0; i < NUM_URBS; i++) { |
758 | if (urb == mos7840_port->write_urb_pool[i]) { | 758 | if (urb == mos7840_port->write_urb_pool[i]) { |
759 | mos7840_port->busy[i] = 0; | 759 | mos7840_port->busy[i] = 0; |
760 | break; | 760 | break; |
761 | } | 761 | } |
762 | } | 762 | } |
763 | spin_unlock(&mos7840_port->pool_lock); | 763 | spin_unlock(&mos7840_port->pool_lock); |
764 | 764 | ||
765 | if (status) { | 765 | if (status) { |
766 | dbg("nonzero write bulk status received:%d\n", status); | 766 | dbg("nonzero write bulk status received:%d\n", status); |
767 | return; | 767 | return; |
768 | } | 768 | } |
769 | 769 | ||
770 | if (mos7840_port_paranoia_check(mos7840_port->port, __func__)) { | 770 | if (mos7840_port_paranoia_check(mos7840_port->port, __func__)) { |
771 | dbg("%s", "Port Paranoia failed \n"); | 771 | dbg("%s", "Port Paranoia failed \n"); |
772 | return; | 772 | return; |
773 | } | 773 | } |
774 | 774 | ||
775 | dbg("%s \n", "Entering ........."); | 775 | dbg("%s \n", "Entering ........."); |
776 | 776 | ||
777 | tty = tty_port_tty_get(&mos7840_port->port->port); | 777 | tty = tty_port_tty_get(&mos7840_port->port->port); |
778 | if (tty && mos7840_port->open) | 778 | if (tty && mos7840_port->open) |
779 | tty_wakeup(tty); | 779 | tty_wakeup(tty); |
780 | tty_kref_put(tty); | 780 | tty_kref_put(tty); |
781 | 781 | ||
782 | } | 782 | } |
783 | 783 | ||
784 | /************************************************************************/ | 784 | /************************************************************************/ |
785 | /* D R I V E R T T Y I N T E R F A C E F U N C T I O N S */ | 785 | /* D R I V E R T T Y I N T E R F A C E F U N C T I O N S */ |
786 | /************************************************************************/ | 786 | /************************************************************************/ |
787 | #ifdef MCSSerialProbe | 787 | #ifdef MCSSerialProbe |
788 | static int mos7840_serial_probe(struct usb_serial *serial, | 788 | static int mos7840_serial_probe(struct usb_serial *serial, |
789 | const struct usb_device_id *id) | 789 | const struct usb_device_id *id) |
790 | { | 790 | { |
791 | 791 | ||
792 | /*need to implement the mode_reg reading and updating\ | 792 | /*need to implement the mode_reg reading and updating\ |
793 | structures usb_serial_ device_type\ | 793 | structures usb_serial_ device_type\ |
794 | (i.e num_ports, num_bulkin,bulkout etc) */ | 794 | (i.e num_ports, num_bulkin,bulkout etc) */ |
795 | /* Also we can update the changes attach */ | 795 | /* Also we can update the changes attach */ |
796 | return 1; | 796 | return 1; |
797 | } | 797 | } |
798 | #endif | 798 | #endif |
799 | 799 | ||
800 | /***************************************************************************** | 800 | /***************************************************************************** |
801 | * mos7840_open | 801 | * mos7840_open |
802 | * this function is called by the tty driver when a port is opened | 802 | * this function is called by the tty driver when a port is opened |
803 | * If successful, we return 0 | 803 | * If successful, we return 0 |
804 | * Otherwise we return a negative error number. | 804 | * Otherwise we return a negative error number. |
805 | *****************************************************************************/ | 805 | *****************************************************************************/ |
806 | 806 | ||
807 | static int mos7840_open(struct tty_struct *tty, | 807 | static int mos7840_open(struct tty_struct *tty, |
808 | struct usb_serial_port *port, struct file *filp) | 808 | struct usb_serial_port *port, struct file *filp) |
809 | { | 809 | { |
810 | int response; | 810 | int response; |
811 | int j; | 811 | int j; |
812 | struct usb_serial *serial; | 812 | struct usb_serial *serial; |
813 | struct urb *urb; | 813 | struct urb *urb; |
814 | __u16 Data; | 814 | __u16 Data; |
815 | int status; | 815 | int status; |
816 | struct moschip_port *mos7840_port; | 816 | struct moschip_port *mos7840_port; |
817 | struct moschip_port *port0; | 817 | struct moschip_port *port0; |
818 | 818 | ||
819 | if (mos7840_port_paranoia_check(port, __func__)) { | 819 | if (mos7840_port_paranoia_check(port, __func__)) { |
820 | dbg("%s", "Port Paranoia failed \n"); | 820 | dbg("%s", "Port Paranoia failed \n"); |
821 | return -ENODEV; | 821 | return -ENODEV; |
822 | } | 822 | } |
823 | 823 | ||
824 | serial = port->serial; | 824 | serial = port->serial; |
825 | 825 | ||
826 | if (mos7840_serial_paranoia_check(serial, __func__)) { | 826 | if (mos7840_serial_paranoia_check(serial, __func__)) { |
827 | dbg("%s", "Serial Paranoia failed \n"); | 827 | dbg("%s", "Serial Paranoia failed \n"); |
828 | return -ENODEV; | 828 | return -ENODEV; |
829 | } | 829 | } |
830 | 830 | ||
831 | mos7840_port = mos7840_get_port_private(port); | 831 | mos7840_port = mos7840_get_port_private(port); |
832 | port0 = mos7840_get_port_private(serial->port[0]); | 832 | port0 = mos7840_get_port_private(serial->port[0]); |
833 | 833 | ||
834 | if (mos7840_port == NULL || port0 == NULL) | 834 | if (mos7840_port == NULL || port0 == NULL) |
835 | return -ENODEV; | 835 | return -ENODEV; |
836 | 836 | ||
837 | usb_clear_halt(serial->dev, port->write_urb->pipe); | 837 | usb_clear_halt(serial->dev, port->write_urb->pipe); |
838 | usb_clear_halt(serial->dev, port->read_urb->pipe); | 838 | usb_clear_halt(serial->dev, port->read_urb->pipe); |
839 | port0->open_ports++; | 839 | port0->open_ports++; |
840 | 840 | ||
841 | /* Initialising the write urb pool */ | 841 | /* Initialising the write urb pool */ |
842 | for (j = 0; j < NUM_URBS; ++j) { | 842 | for (j = 0; j < NUM_URBS; ++j) { |
843 | urb = usb_alloc_urb(0, GFP_KERNEL); | 843 | urb = usb_alloc_urb(0, GFP_KERNEL); |
844 | mos7840_port->write_urb_pool[j] = urb; | 844 | mos7840_port->write_urb_pool[j] = urb; |
845 | 845 | ||
846 | if (urb == NULL) { | 846 | if (urb == NULL) { |
847 | dev_err(&port->dev, "No more urbs???\n"); | 847 | dev_err(&port->dev, "No more urbs???\n"); |
848 | continue; | 848 | continue; |
849 | } | 849 | } |
850 | 850 | ||
851 | urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, | 851 | urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, |
852 | GFP_KERNEL); | 852 | GFP_KERNEL); |
853 | if (!urb->transfer_buffer) { | 853 | if (!urb->transfer_buffer) { |
854 | usb_free_urb(urb); | 854 | usb_free_urb(urb); |
855 | mos7840_port->write_urb_pool[j] = NULL; | 855 | mos7840_port->write_urb_pool[j] = NULL; |
856 | dev_err(&port->dev, | 856 | dev_err(&port->dev, |
857 | "%s-out of memory for urb buffers.\n", | 857 | "%s-out of memory for urb buffers.\n", |
858 | __func__); | 858 | __func__); |
859 | continue; | 859 | continue; |
860 | } | 860 | } |
861 | } | 861 | } |
862 | 862 | ||
863 | /***************************************************************************** | 863 | /***************************************************************************** |
864 | * Initialize MCS7840 -- Write Init values to corresponding Registers | 864 | * Initialize MCS7840 -- Write Init values to corresponding Registers |
865 | * | 865 | * |
866 | * Register Index | 866 | * Register Index |
867 | * 1 : IER | 867 | * 1 : IER |
868 | * 2 : FCR | 868 | * 2 : FCR |
869 | * 3 : LCR | 869 | * 3 : LCR |
870 | * 4 : MCR | 870 | * 4 : MCR |
871 | * | 871 | * |
872 | * 0x08 : SP1/2 Control Reg | 872 | * 0x08 : SP1/2 Control Reg |
873 | *****************************************************************************/ | 873 | *****************************************************************************/ |
874 | 874 | ||
875 | /* NEED to check the following Block */ | 875 | /* NEED to check the following Block */ |
876 | 876 | ||
877 | Data = 0x0; | 877 | Data = 0x0; |
878 | status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data); | 878 | status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data); |
879 | if (status < 0) { | 879 | if (status < 0) { |
880 | dbg("Reading Spreg failed\n"); | 880 | dbg("Reading Spreg failed\n"); |
881 | return -1; | 881 | return -1; |
882 | } | 882 | } |
883 | Data |= 0x80; | 883 | Data |= 0x80; |
884 | status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); | 884 | status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); |
885 | if (status < 0) { | 885 | if (status < 0) { |
886 | dbg("writing Spreg failed\n"); | 886 | dbg("writing Spreg failed\n"); |
887 | return -1; | 887 | return -1; |
888 | } | 888 | } |
889 | 889 | ||
890 | Data &= ~0x80; | 890 | Data &= ~0x80; |
891 | status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); | 891 | status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); |
892 | if (status < 0) { | 892 | if (status < 0) { |
893 | dbg("writing Spreg failed\n"); | 893 | dbg("writing Spreg failed\n"); |
894 | return -1; | 894 | return -1; |
895 | } | 895 | } |
896 | /* End of block to be checked */ | 896 | /* End of block to be checked */ |
897 | 897 | ||
898 | Data = 0x0; | 898 | Data = 0x0; |
899 | status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, | 899 | status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, |
900 | &Data); | 900 | &Data); |
901 | if (status < 0) { | 901 | if (status < 0) { |
902 | dbg("Reading Controlreg failed\n"); | 902 | dbg("Reading Controlreg failed\n"); |
903 | return -1; | 903 | return -1; |
904 | } | 904 | } |
905 | Data |= 0x08; /* Driver done bit */ | 905 | Data |= 0x08; /* Driver done bit */ |
906 | Data |= 0x20; /* rx_disable */ | 906 | Data |= 0x20; /* rx_disable */ |
907 | status = mos7840_set_reg_sync(port, | 907 | status = mos7840_set_reg_sync(port, |
908 | mos7840_port->ControlRegOffset, Data); | 908 | mos7840_port->ControlRegOffset, Data); |
909 | if (status < 0) { | 909 | if (status < 0) { |
910 | dbg("writing Controlreg failed\n"); | 910 | dbg("writing Controlreg failed\n"); |
911 | return -1; | 911 | return -1; |
912 | } | 912 | } |
913 | /* do register settings here */ | 913 | /* do register settings here */ |
914 | /* Set all regs to the device default values. */ | 914 | /* Set all regs to the device default values. */ |
915 | /*********************************** | 915 | /*********************************** |
916 | * First Disable all interrupts. | 916 | * First Disable all interrupts. |
917 | ***********************************/ | 917 | ***********************************/ |
918 | Data = 0x00; | 918 | Data = 0x00; |
919 | status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); | 919 | status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); |
920 | if (status < 0) { | 920 | if (status < 0) { |
921 | dbg("disableing interrupts failed\n"); | 921 | dbg("disableing interrupts failed\n"); |
922 | return -1; | 922 | return -1; |
923 | } | 923 | } |
924 | /* Set FIFO_CONTROL_REGISTER to the default value */ | 924 | /* Set FIFO_CONTROL_REGISTER to the default value */ |
925 | Data = 0x00; | 925 | Data = 0x00; |
926 | status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); | 926 | status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); |
927 | if (status < 0) { | 927 | if (status < 0) { |
928 | dbg("Writing FIFO_CONTROL_REGISTER failed\n"); | 928 | dbg("Writing FIFO_CONTROL_REGISTER failed\n"); |
929 | return -1; | 929 | return -1; |
930 | } | 930 | } |
931 | 931 | ||
932 | Data = 0xcf; | 932 | Data = 0xcf; |
933 | status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); | 933 | status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); |
934 | if (status < 0) { | 934 | if (status < 0) { |
935 | dbg("Writing FIFO_CONTROL_REGISTER failed\n"); | 935 | dbg("Writing FIFO_CONTROL_REGISTER failed\n"); |
936 | return -1; | 936 | return -1; |
937 | } | 937 | } |
938 | 938 | ||
939 | Data = 0x03; | 939 | Data = 0x03; |
940 | status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | 940 | status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); |
941 | mos7840_port->shadowLCR = Data; | 941 | mos7840_port->shadowLCR = Data; |
942 | 942 | ||
943 | Data = 0x0b; | 943 | Data = 0x0b; |
944 | status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | 944 | status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); |
945 | mos7840_port->shadowMCR = Data; | 945 | mos7840_port->shadowMCR = Data; |
946 | 946 | ||
947 | Data = 0x00; | 947 | Data = 0x00; |
948 | status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); | 948 | status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); |
949 | mos7840_port->shadowLCR = Data; | 949 | mos7840_port->shadowLCR = Data; |
950 | 950 | ||
951 | Data |= SERIAL_LCR_DLAB; /* data latch enable in LCR 0x80 */ | 951 | Data |= SERIAL_LCR_DLAB; /* data latch enable in LCR 0x80 */ |
952 | status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | 952 | status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); |
953 | 953 | ||
954 | Data = 0x0c; | 954 | Data = 0x0c; |
955 | status = mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data); | 955 | status = mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data); |
956 | 956 | ||
957 | Data = 0x0; | 957 | Data = 0x0; |
958 | status = mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data); | 958 | status = mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data); |
959 | 959 | ||
960 | Data = 0x00; | 960 | Data = 0x00; |
961 | status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); | 961 | status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); |
962 | 962 | ||
963 | Data = Data & ~SERIAL_LCR_DLAB; | 963 | Data = Data & ~SERIAL_LCR_DLAB; |
964 | status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | 964 | status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); |
965 | mos7840_port->shadowLCR = Data; | 965 | mos7840_port->shadowLCR = Data; |
966 | 966 | ||
967 | /* clearing Bulkin and Bulkout Fifo */ | 967 | /* clearing Bulkin and Bulkout Fifo */ |
968 | Data = 0x0; | 968 | Data = 0x0; |
969 | status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data); | 969 | status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data); |
970 | 970 | ||
971 | Data = Data | 0x0c; | 971 | Data = Data | 0x0c; |
972 | status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); | 972 | status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); |
973 | 973 | ||
974 | Data = Data & ~0x0c; | 974 | Data = Data & ~0x0c; |
975 | status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); | 975 | status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); |
976 | /* Finally enable all interrupts */ | 976 | /* Finally enable all interrupts */ |
977 | Data = 0x0c; | 977 | Data = 0x0c; |
978 | status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); | 978 | status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); |
979 | 979 | ||
980 | /* clearing rx_disable */ | 980 | /* clearing rx_disable */ |
981 | Data = 0x0; | 981 | Data = 0x0; |
982 | status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, | 982 | status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, |
983 | &Data); | 983 | &Data); |
984 | Data = Data & ~0x20; | 984 | Data = Data & ~0x20; |
985 | status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, | 985 | status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, |
986 | Data); | 986 | Data); |
987 | 987 | ||
988 | /* rx_negate */ | 988 | /* rx_negate */ |
989 | Data = 0x0; | 989 | Data = 0x0; |
990 | status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, | 990 | status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, |
991 | &Data); | 991 | &Data); |
992 | Data = Data | 0x10; | 992 | Data = Data | 0x10; |
993 | status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, | 993 | status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, |
994 | Data); | 994 | Data); |
995 | 995 | ||
996 | /* force low_latency on so that our tty_push actually forces * | 996 | /* force low_latency on so that our tty_push actually forces * |
997 | * the data through,otherwise it is scheduled, and with * | 997 | * the data through,otherwise it is scheduled, and with * |
998 | * high data rates (like with OHCI) data can get lost. */ | 998 | * high data rates (like with OHCI) data can get lost. */ |
999 | if (tty) | 999 | if (tty) |
1000 | tty->low_latency = 1; | 1000 | tty->low_latency = 1; |
1001 | 1001 | ||
1002 | /* Check to see if we've set up our endpoint info yet * | 1002 | /* Check to see if we've set up our endpoint info yet * |
1003 | * (can't set it up in mos7840_startup as the structures * | 1003 | * (can't set it up in mos7840_startup as the structures * |
1004 | * were not set up at that time.) */ | 1004 | * were not set up at that time.) */ |
1005 | if (port0->open_ports == 1) { | 1005 | if (port0->open_ports == 1) { |
1006 | if (serial->port[0]->interrupt_in_buffer == NULL) { | 1006 | if (serial->port[0]->interrupt_in_buffer == NULL) { |
1007 | /* set up interrupt urb */ | 1007 | /* set up interrupt urb */ |
1008 | usb_fill_int_urb(serial->port[0]->interrupt_in_urb, | 1008 | usb_fill_int_urb(serial->port[0]->interrupt_in_urb, |
1009 | serial->dev, | 1009 | serial->dev, |
1010 | usb_rcvintpipe(serial->dev, | 1010 | usb_rcvintpipe(serial->dev, |
1011 | serial->port[0]->interrupt_in_endpointAddress), | 1011 | serial->port[0]->interrupt_in_endpointAddress), |
1012 | serial->port[0]->interrupt_in_buffer, | 1012 | serial->port[0]->interrupt_in_buffer, |
1013 | serial->port[0]->interrupt_in_urb-> | 1013 | serial->port[0]->interrupt_in_urb-> |
1014 | transfer_buffer_length, | 1014 | transfer_buffer_length, |
1015 | mos7840_interrupt_callback, | 1015 | mos7840_interrupt_callback, |
1016 | serial, | 1016 | serial, |
1017 | serial->port[0]->interrupt_in_urb->interval); | 1017 | serial->port[0]->interrupt_in_urb->interval); |
1018 | 1018 | ||
1019 | /* start interrupt read for mos7840 * | 1019 | /* start interrupt read for mos7840 * |
1020 | * will continue as long as mos7840 is connected */ | 1020 | * will continue as long as mos7840 is connected */ |
1021 | 1021 | ||
1022 | response = | 1022 | response = |
1023 | usb_submit_urb(serial->port[0]->interrupt_in_urb, | 1023 | usb_submit_urb(serial->port[0]->interrupt_in_urb, |
1024 | GFP_KERNEL); | 1024 | GFP_KERNEL); |
1025 | if (response) { | 1025 | if (response) { |
1026 | dev_err(&port->dev, "%s - Error %d submitting " | 1026 | dev_err(&port->dev, "%s - Error %d submitting " |
1027 | "interrupt urb\n", __func__, response); | 1027 | "interrupt urb\n", __func__, response); |
1028 | } | 1028 | } |
1029 | 1029 | ||
1030 | } | 1030 | } |
1031 | 1031 | ||
1032 | } | 1032 | } |
1033 | 1033 | ||
1034 | /* see if we've set up our endpoint info yet * | 1034 | /* see if we've set up our endpoint info yet * |
1035 | * (can't set it up in mos7840_startup as the * | 1035 | * (can't set it up in mos7840_startup as the * |
1036 | * structures were not set up at that time.) */ | 1036 | * structures were not set up at that time.) */ |
1037 | 1037 | ||
1038 | dbg("port number is %d \n", port->number); | 1038 | dbg("port number is %d \n", port->number); |
1039 | dbg("serial number is %d \n", port->serial->minor); | 1039 | dbg("serial number is %d \n", port->serial->minor); |
1040 | dbg("Bulkin endpoint is %d \n", port->bulk_in_endpointAddress); | 1040 | dbg("Bulkin endpoint is %d \n", port->bulk_in_endpointAddress); |
1041 | dbg("BulkOut endpoint is %d \n", port->bulk_out_endpointAddress); | 1041 | dbg("BulkOut endpoint is %d \n", port->bulk_out_endpointAddress); |
1042 | dbg("Interrupt endpoint is %d \n", port->interrupt_in_endpointAddress); | 1042 | dbg("Interrupt endpoint is %d \n", port->interrupt_in_endpointAddress); |
1043 | dbg("port's number in the device is %d\n", mos7840_port->port_num); | 1043 | dbg("port's number in the device is %d\n", mos7840_port->port_num); |
1044 | mos7840_port->read_urb = port->read_urb; | 1044 | mos7840_port->read_urb = port->read_urb; |
1045 | 1045 | ||
1046 | /* set up our bulk in urb */ | 1046 | /* set up our bulk in urb */ |
1047 | 1047 | ||
1048 | usb_fill_bulk_urb(mos7840_port->read_urb, | 1048 | usb_fill_bulk_urb(mos7840_port->read_urb, |
1049 | serial->dev, | 1049 | serial->dev, |
1050 | usb_rcvbulkpipe(serial->dev, | 1050 | usb_rcvbulkpipe(serial->dev, |
1051 | port->bulk_in_endpointAddress), | 1051 | port->bulk_in_endpointAddress), |
1052 | port->bulk_in_buffer, | 1052 | port->bulk_in_buffer, |
1053 | mos7840_port->read_urb->transfer_buffer_length, | 1053 | mos7840_port->read_urb->transfer_buffer_length, |
1054 | mos7840_bulk_in_callback, mos7840_port); | 1054 | mos7840_bulk_in_callback, mos7840_port); |
1055 | 1055 | ||
1056 | dbg("mos7840_open: bulkin endpoint is %d\n", | 1056 | dbg("mos7840_open: bulkin endpoint is %d\n", |
1057 | port->bulk_in_endpointAddress); | 1057 | port->bulk_in_endpointAddress); |
1058 | response = usb_submit_urb(mos7840_port->read_urb, GFP_KERNEL); | 1058 | response = usb_submit_urb(mos7840_port->read_urb, GFP_KERNEL); |
1059 | if (response) { | 1059 | if (response) { |
1060 | dev_err(&port->dev, "%s - Error %d submitting control urb\n", | 1060 | dev_err(&port->dev, "%s - Error %d submitting control urb\n", |
1061 | __func__, response); | 1061 | __func__, response); |
1062 | } | 1062 | } |
1063 | 1063 | ||
1064 | /* initialize our wait queues */ | 1064 | /* initialize our wait queues */ |
1065 | init_waitqueue_head(&mos7840_port->wait_chase); | 1065 | init_waitqueue_head(&mos7840_port->wait_chase); |
1066 | init_waitqueue_head(&mos7840_port->delta_msr_wait); | 1066 | init_waitqueue_head(&mos7840_port->delta_msr_wait); |
1067 | 1067 | ||
1068 | /* initialize our icount structure */ | 1068 | /* initialize our icount structure */ |
1069 | memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount)); | 1069 | memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount)); |
1070 | 1070 | ||
1071 | /* initialize our port settings */ | 1071 | /* initialize our port settings */ |
1072 | /* Must set to enable ints! */ | 1072 | /* Must set to enable ints! */ |
1073 | mos7840_port->shadowMCR = MCR_MASTER_IE; | 1073 | mos7840_port->shadowMCR = MCR_MASTER_IE; |
1074 | /* send a open port command */ | 1074 | /* send a open port command */ |
1075 | mos7840_port->open = 1; | 1075 | mos7840_port->open = 1; |
1076 | /* mos7840_change_port_settings(mos7840_port,old_termios); */ | 1076 | /* mos7840_change_port_settings(mos7840_port,old_termios); */ |
1077 | mos7840_port->icount.tx = 0; | 1077 | mos7840_port->icount.tx = 0; |
1078 | mos7840_port->icount.rx = 0; | 1078 | mos7840_port->icount.rx = 0; |
1079 | 1079 | ||
1080 | dbg("\n\nusb_serial serial:%p mos7840_port:%p\n usb_serial_port port:%p\n\n", | 1080 | dbg("\n\nusb_serial serial:%p mos7840_port:%p\n usb_serial_port port:%p\n\n", |
1081 | serial, mos7840_port, port); | 1081 | serial, mos7840_port, port); |
1082 | 1082 | ||
1083 | return 0; | 1083 | return 0; |
1084 | 1084 | ||
1085 | } | 1085 | } |
1086 | 1086 | ||
1087 | /***************************************************************************** | 1087 | /***************************************************************************** |
1088 | * mos7840_chars_in_buffer | 1088 | * mos7840_chars_in_buffer |
1089 | * this function is called by the tty driver when it wants to know how many | 1089 | * this function is called by the tty driver when it wants to know how many |
1090 | * bytes of data we currently have outstanding in the port (data that has | 1090 | * bytes of data we currently have outstanding in the port (data that has |
1091 | * been written, but hasn't made it out the port yet) | 1091 | * been written, but hasn't made it out the port yet) |
1092 | * If successful, we return the number of bytes left to be written in the | 1092 | * If successful, we return the number of bytes left to be written in the |
1093 | * system, | 1093 | * system, |
1094 | * Otherwise we return zero. | 1094 | * Otherwise we return zero. |
1095 | *****************************************************************************/ | 1095 | *****************************************************************************/ |
1096 | 1096 | ||
1097 | static int mos7840_chars_in_buffer(struct tty_struct *tty) | 1097 | static int mos7840_chars_in_buffer(struct tty_struct *tty) |
1098 | { | 1098 | { |
1099 | struct usb_serial_port *port = tty->driver_data; | 1099 | struct usb_serial_port *port = tty->driver_data; |
1100 | int i; | 1100 | int i; |
1101 | int chars = 0; | 1101 | int chars = 0; |
1102 | unsigned long flags; | 1102 | unsigned long flags; |
1103 | struct moschip_port *mos7840_port; | 1103 | struct moschip_port *mos7840_port; |
1104 | 1104 | ||
1105 | dbg("%s \n", " mos7840_chars_in_buffer:entering ..........."); | 1105 | dbg("%s \n", " mos7840_chars_in_buffer:entering ..........."); |
1106 | 1106 | ||
1107 | if (mos7840_port_paranoia_check(port, __func__)) { | 1107 | if (mos7840_port_paranoia_check(port, __func__)) { |
1108 | dbg("%s", "Invalid port \n"); | 1108 | dbg("%s", "Invalid port \n"); |
1109 | return 0; | 1109 | return 0; |
1110 | } | 1110 | } |
1111 | 1111 | ||
1112 | mos7840_port = mos7840_get_port_private(port); | 1112 | mos7840_port = mos7840_get_port_private(port); |
1113 | if (mos7840_port == NULL) { | 1113 | if (mos7840_port == NULL) { |
1114 | dbg("%s \n", "mos7840_break:leaving ..........."); | 1114 | dbg("%s \n", "mos7840_break:leaving ..........."); |
1115 | return 0; | 1115 | return 0; |
1116 | } | 1116 | } |
1117 | 1117 | ||
1118 | spin_lock_irqsave(&mos7840_port->pool_lock, flags); | 1118 | spin_lock_irqsave(&mos7840_port->pool_lock, flags); |
1119 | for (i = 0; i < NUM_URBS; ++i) | 1119 | for (i = 0; i < NUM_URBS; ++i) |
1120 | if (mos7840_port->busy[i]) | 1120 | if (mos7840_port->busy[i]) |
1121 | chars += URB_TRANSFER_BUFFER_SIZE; | 1121 | chars += URB_TRANSFER_BUFFER_SIZE; |
1122 | spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); | 1122 | spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); |
1123 | dbg("%s - returns %d", __func__, chars); | 1123 | dbg("%s - returns %d", __func__, chars); |
1124 | return chars; | 1124 | return chars; |
1125 | 1125 | ||
1126 | } | 1126 | } |
1127 | 1127 | ||
1128 | /************************************************************************ | 1128 | /************************************************************************ |
1129 | * | 1129 | * |
1130 | * mos7840_block_until_tx_empty | 1130 | * mos7840_block_until_tx_empty |
1131 | * | 1131 | * |
1132 | * This function will block the close until one of the following: | 1132 | * This function will block the close until one of the following: |
1133 | * 1. TX count are 0 | 1133 | * 1. TX count are 0 |
1134 | * 2. The mos7840 has stopped | 1134 | * 2. The mos7840 has stopped |
1135 | * 3. A timeout of 3 seconds without activity has expired | 1135 | * 3. A timeout of 3 seconds without activity has expired |
1136 | * | 1136 | * |
1137 | ************************************************************************/ | 1137 | ************************************************************************/ |
1138 | static void mos7840_block_until_tx_empty(struct tty_struct *tty, | 1138 | static void mos7840_block_until_tx_empty(struct tty_struct *tty, |
1139 | struct moschip_port *mos7840_port) | 1139 | struct moschip_port *mos7840_port) |
1140 | { | 1140 | { |
1141 | int timeout = HZ / 10; | 1141 | int timeout = HZ / 10; |
1142 | int wait = 30; | 1142 | int wait = 30; |
1143 | int count; | 1143 | int count; |
1144 | 1144 | ||
1145 | while (1) { | 1145 | while (1) { |
1146 | 1146 | ||
1147 | count = mos7840_chars_in_buffer(tty); | 1147 | count = mos7840_chars_in_buffer(tty); |
1148 | 1148 | ||
1149 | /* Check for Buffer status */ | 1149 | /* Check for Buffer status */ |
1150 | if (count <= 0) | 1150 | if (count <= 0) |
1151 | return; | 1151 | return; |
1152 | 1152 | ||
1153 | /* Block the thread for a while */ | 1153 | /* Block the thread for a while */ |
1154 | interruptible_sleep_on_timeout(&mos7840_port->wait_chase, | 1154 | interruptible_sleep_on_timeout(&mos7840_port->wait_chase, |
1155 | timeout); | 1155 | timeout); |
1156 | 1156 | ||
1157 | /* No activity.. count down section */ | 1157 | /* No activity.. count down section */ |
1158 | wait--; | 1158 | wait--; |
1159 | if (wait == 0) { | 1159 | if (wait == 0) { |
1160 | dbg("%s - TIMEOUT", __func__); | 1160 | dbg("%s - TIMEOUT", __func__); |
1161 | return; | 1161 | return; |
1162 | } else { | 1162 | } else { |
1163 | /* Reset timeout value back to seconds */ | 1163 | /* Reset timeout value back to seconds */ |
1164 | wait = 30; | 1164 | wait = 30; |
1165 | } | 1165 | } |
1166 | } | 1166 | } |
1167 | } | 1167 | } |
1168 | 1168 | ||
1169 | /***************************************************************************** | 1169 | /***************************************************************************** |
1170 | * mos7840_close | 1170 | * mos7840_close |
1171 | * this function is called by the tty driver when a port is closed | 1171 | * this function is called by the tty driver when a port is closed |
1172 | *****************************************************************************/ | 1172 | *****************************************************************************/ |
1173 | 1173 | ||
1174 | static void mos7840_close(struct tty_struct *tty, | 1174 | static void mos7840_close(struct tty_struct *tty, |
1175 | struct usb_serial_port *port, struct file *filp) | 1175 | struct usb_serial_port *port, struct file *filp) |
1176 | { | 1176 | { |
1177 | struct usb_serial *serial; | 1177 | struct usb_serial *serial; |
1178 | struct moschip_port *mos7840_port; | 1178 | struct moschip_port *mos7840_port; |
1179 | struct moschip_port *port0; | 1179 | struct moschip_port *port0; |
1180 | int j; | 1180 | int j; |
1181 | __u16 Data; | 1181 | __u16 Data; |
1182 | 1182 | ||
1183 | dbg("%s\n", "mos7840_close:entering..."); | 1183 | dbg("%s\n", "mos7840_close:entering..."); |
1184 | 1184 | ||
1185 | if (mos7840_port_paranoia_check(port, __func__)) { | 1185 | if (mos7840_port_paranoia_check(port, __func__)) { |
1186 | dbg("%s", "Port Paranoia failed \n"); | 1186 | dbg("%s", "Port Paranoia failed \n"); |
1187 | return; | 1187 | return; |
1188 | } | 1188 | } |
1189 | 1189 | ||
1190 | serial = mos7840_get_usb_serial(port, __func__); | 1190 | serial = mos7840_get_usb_serial(port, __func__); |
1191 | if (!serial) { | 1191 | if (!serial) { |
1192 | dbg("%s", "Serial Paranoia failed \n"); | 1192 | dbg("%s", "Serial Paranoia failed \n"); |
1193 | return; | 1193 | return; |
1194 | } | 1194 | } |
1195 | 1195 | ||
1196 | mos7840_port = mos7840_get_port_private(port); | 1196 | mos7840_port = mos7840_get_port_private(port); |
1197 | port0 = mos7840_get_port_private(serial->port[0]); | 1197 | port0 = mos7840_get_port_private(serial->port[0]); |
1198 | 1198 | ||
1199 | if (mos7840_port == NULL || port0 == NULL) | 1199 | if (mos7840_port == NULL || port0 == NULL) |
1200 | return; | 1200 | return; |
1201 | 1201 | ||
1202 | for (j = 0; j < NUM_URBS; ++j) | 1202 | for (j = 0; j < NUM_URBS; ++j) |
1203 | usb_kill_urb(mos7840_port->write_urb_pool[j]); | 1203 | usb_kill_urb(mos7840_port->write_urb_pool[j]); |
1204 | 1204 | ||
1205 | /* Freeing Write URBs */ | 1205 | /* Freeing Write URBs */ |
1206 | for (j = 0; j < NUM_URBS; ++j) { | 1206 | for (j = 0; j < NUM_URBS; ++j) { |
1207 | if (mos7840_port->write_urb_pool[j]) { | 1207 | if (mos7840_port->write_urb_pool[j]) { |
1208 | if (mos7840_port->write_urb_pool[j]->transfer_buffer) | 1208 | if (mos7840_port->write_urb_pool[j]->transfer_buffer) |
1209 | kfree(mos7840_port->write_urb_pool[j]-> | 1209 | kfree(mos7840_port->write_urb_pool[j]-> |
1210 | transfer_buffer); | 1210 | transfer_buffer); |
1211 | 1211 | ||
1212 | usb_free_urb(mos7840_port->write_urb_pool[j]); | 1212 | usb_free_urb(mos7840_port->write_urb_pool[j]); |
1213 | } | 1213 | } |
1214 | } | 1214 | } |
1215 | 1215 | ||
1216 | if (serial->dev) | 1216 | if (serial->dev) |
1217 | /* flush and block until tx is empty */ | 1217 | /* flush and block until tx is empty */ |
1218 | mos7840_block_until_tx_empty(tty, mos7840_port); | 1218 | mos7840_block_until_tx_empty(tty, mos7840_port); |
1219 | 1219 | ||
1220 | /* While closing port, shutdown all bulk read, write * | 1220 | /* While closing port, shutdown all bulk read, write * |
1221 | * and interrupt read if they exists */ | 1221 | * and interrupt read if they exists */ |
1222 | if (serial->dev) { | 1222 | if (serial->dev) { |
1223 | if (mos7840_port->write_urb) { | 1223 | if (mos7840_port->write_urb) { |
1224 | dbg("%s", "Shutdown bulk write\n"); | 1224 | dbg("%s", "Shutdown bulk write\n"); |
1225 | usb_kill_urb(mos7840_port->write_urb); | 1225 | usb_kill_urb(mos7840_port->write_urb); |
1226 | } | 1226 | } |
1227 | if (mos7840_port->read_urb) { | 1227 | if (mos7840_port->read_urb) { |
1228 | dbg("%s", "Shutdown bulk read\n"); | 1228 | dbg("%s", "Shutdown bulk read\n"); |
1229 | usb_kill_urb(mos7840_port->read_urb); | 1229 | usb_kill_urb(mos7840_port->read_urb); |
1230 | } | 1230 | } |
1231 | if ((&mos7840_port->control_urb)) { | 1231 | if ((&mos7840_port->control_urb)) { |
1232 | dbg("%s", "Shutdown control read\n"); | 1232 | dbg("%s", "Shutdown control read\n"); |
1233 | /*/ usb_kill_urb (mos7840_port->control_urb); */ | 1233 | /*/ usb_kill_urb (mos7840_port->control_urb); */ |
1234 | } | 1234 | } |
1235 | } | 1235 | } |
1236 | /* if(mos7840_port->ctrl_buf != NULL) */ | 1236 | /* if(mos7840_port->ctrl_buf != NULL) */ |
1237 | /* kfree(mos7840_port->ctrl_buf); */ | 1237 | /* kfree(mos7840_port->ctrl_buf); */ |
1238 | port0->open_ports--; | 1238 | port0->open_ports--; |
1239 | dbg("mos7840_num_open_ports in close%d:in port%d\n", | 1239 | dbg("mos7840_num_open_ports in close%d:in port%d\n", |
1240 | port0->open_ports, port->number); | 1240 | port0->open_ports, port->number); |
1241 | if (port0->open_ports == 0) { | 1241 | if (port0->open_ports == 0) { |
1242 | if (serial->port[0]->interrupt_in_urb) { | 1242 | if (serial->port[0]->interrupt_in_urb) { |
1243 | dbg("%s", "Shutdown interrupt_in_urb\n"); | 1243 | dbg("%s", "Shutdown interrupt_in_urb\n"); |
1244 | usb_kill_urb(serial->port[0]->interrupt_in_urb); | 1244 | usb_kill_urb(serial->port[0]->interrupt_in_urb); |
1245 | } | 1245 | } |
1246 | } | 1246 | } |
1247 | 1247 | ||
1248 | if (mos7840_port->write_urb) { | 1248 | if (mos7840_port->write_urb) { |
1249 | /* if this urb had a transfer buffer already (old tx) free it */ | 1249 | /* if this urb had a transfer buffer already (old tx) free it */ |
1250 | if (mos7840_port->write_urb->transfer_buffer != NULL) | 1250 | if (mos7840_port->write_urb->transfer_buffer != NULL) |
1251 | kfree(mos7840_port->write_urb->transfer_buffer); | 1251 | kfree(mos7840_port->write_urb->transfer_buffer); |
1252 | usb_free_urb(mos7840_port->write_urb); | 1252 | usb_free_urb(mos7840_port->write_urb); |
1253 | } | 1253 | } |
1254 | 1254 | ||
1255 | Data = 0x0; | 1255 | Data = 0x0; |
1256 | mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | 1256 | mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); |
1257 | 1257 | ||
1258 | Data = 0x00; | 1258 | Data = 0x00; |
1259 | mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); | 1259 | mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); |
1260 | 1260 | ||
1261 | mos7840_port->open = 0; | 1261 | mos7840_port->open = 0; |
1262 | 1262 | ||
1263 | dbg("%s \n", "Leaving ............"); | 1263 | dbg("%s \n", "Leaving ............"); |
1264 | } | 1264 | } |
1265 | 1265 | ||
1266 | /************************************************************************ | 1266 | /************************************************************************ |
1267 | * | 1267 | * |
1268 | * mos7840_block_until_chase_response | 1268 | * mos7840_block_until_chase_response |
1269 | * | 1269 | * |
1270 | * This function will block the close until one of the following: | 1270 | * This function will block the close until one of the following: |
1271 | * 1. Response to our Chase comes from mos7840 | 1271 | * 1. Response to our Chase comes from mos7840 |
1272 | * 2. A timeout of 10 seconds without activity has expired | 1272 | * 2. A timeout of 10 seconds without activity has expired |
1273 | * (1K of mos7840 data @ 2400 baud ==> 4 sec to empty) | 1273 | * (1K of mos7840 data @ 2400 baud ==> 4 sec to empty) |
1274 | * | 1274 | * |
1275 | ************************************************************************/ | 1275 | ************************************************************************/ |
1276 | 1276 | ||
1277 | static void mos7840_block_until_chase_response(struct tty_struct *tty, | 1277 | static void mos7840_block_until_chase_response(struct tty_struct *tty, |
1278 | struct moschip_port *mos7840_port) | 1278 | struct moschip_port *mos7840_port) |
1279 | { | 1279 | { |
1280 | int timeout = 1 * HZ; | 1280 | int timeout = 1 * HZ; |
1281 | int wait = 10; | 1281 | int wait = 10; |
1282 | int count; | 1282 | int count; |
1283 | 1283 | ||
1284 | while (1) { | 1284 | while (1) { |
1285 | count = mos7840_chars_in_buffer(tty); | 1285 | count = mos7840_chars_in_buffer(tty); |
1286 | 1286 | ||
1287 | /* Check for Buffer status */ | 1287 | /* Check for Buffer status */ |
1288 | if (count <= 0) | 1288 | if (count <= 0) |
1289 | return; | 1289 | return; |
1290 | 1290 | ||
1291 | /* Block the thread for a while */ | 1291 | /* Block the thread for a while */ |
1292 | interruptible_sleep_on_timeout(&mos7840_port->wait_chase, | 1292 | interruptible_sleep_on_timeout(&mos7840_port->wait_chase, |
1293 | timeout); | 1293 | timeout); |
1294 | /* No activity.. count down section */ | 1294 | /* No activity.. count down section */ |
1295 | wait--; | 1295 | wait--; |
1296 | if (wait == 0) { | 1296 | if (wait == 0) { |
1297 | dbg("%s - TIMEOUT", __func__); | 1297 | dbg("%s - TIMEOUT", __func__); |
1298 | return; | 1298 | return; |
1299 | } else { | 1299 | } else { |
1300 | /* Reset timeout value back to seconds */ | 1300 | /* Reset timeout value back to seconds */ |
1301 | wait = 10; | 1301 | wait = 10; |
1302 | } | 1302 | } |
1303 | } | 1303 | } |
1304 | 1304 | ||
1305 | } | 1305 | } |
1306 | 1306 | ||
1307 | /***************************************************************************** | 1307 | /***************************************************************************** |
1308 | * mos7840_break | 1308 | * mos7840_break |
1309 | * this function sends a break to the port | 1309 | * this function sends a break to the port |
1310 | *****************************************************************************/ | 1310 | *****************************************************************************/ |
1311 | static void mos7840_break(struct tty_struct *tty, int break_state) | 1311 | static void mos7840_break(struct tty_struct *tty, int break_state) |
1312 | { | 1312 | { |
1313 | struct usb_serial_port *port = tty->driver_data; | 1313 | struct usb_serial_port *port = tty->driver_data; |
1314 | unsigned char data; | 1314 | unsigned char data; |
1315 | struct usb_serial *serial; | 1315 | struct usb_serial *serial; |
1316 | struct moschip_port *mos7840_port; | 1316 | struct moschip_port *mos7840_port; |
1317 | 1317 | ||
1318 | dbg("%s \n", "Entering ..........."); | 1318 | dbg("%s \n", "Entering ..........."); |
1319 | dbg("mos7840_break: Start\n"); | 1319 | dbg("mos7840_break: Start\n"); |
1320 | 1320 | ||
1321 | if (mos7840_port_paranoia_check(port, __func__)) { | 1321 | if (mos7840_port_paranoia_check(port, __func__)) { |
1322 | dbg("%s", "Port Paranoia failed \n"); | 1322 | dbg("%s", "Port Paranoia failed \n"); |
1323 | return; | 1323 | return; |
1324 | } | 1324 | } |
1325 | 1325 | ||
1326 | serial = mos7840_get_usb_serial(port, __func__); | 1326 | serial = mos7840_get_usb_serial(port, __func__); |
1327 | if (!serial) { | 1327 | if (!serial) { |
1328 | dbg("%s", "Serial Paranoia failed \n"); | 1328 | dbg("%s", "Serial Paranoia failed \n"); |
1329 | return; | 1329 | return; |
1330 | } | 1330 | } |
1331 | 1331 | ||
1332 | mos7840_port = mos7840_get_port_private(port); | 1332 | mos7840_port = mos7840_get_port_private(port); |
1333 | 1333 | ||
1334 | if (mos7840_port == NULL) | 1334 | if (mos7840_port == NULL) |
1335 | return; | 1335 | return; |
1336 | 1336 | ||
1337 | if (serial->dev) | 1337 | if (serial->dev) |
1338 | /* flush and block until tx is empty */ | 1338 | /* flush and block until tx is empty */ |
1339 | mos7840_block_until_chase_response(tty, mos7840_port); | 1339 | mos7840_block_until_chase_response(tty, mos7840_port); |
1340 | 1340 | ||
1341 | if (break_state == -1) | 1341 | if (break_state == -1) |
1342 | data = mos7840_port->shadowLCR | LCR_SET_BREAK; | 1342 | data = mos7840_port->shadowLCR | LCR_SET_BREAK; |
1343 | else | 1343 | else |
1344 | data = mos7840_port->shadowLCR & ~LCR_SET_BREAK; | 1344 | data = mos7840_port->shadowLCR & ~LCR_SET_BREAK; |
1345 | 1345 | ||
1346 | /* FIXME: no locking on shadowLCR anywhere in driver */ | ||
1346 | mos7840_port->shadowLCR = data; | 1347 | mos7840_port->shadowLCR = data; |
1347 | dbg("mcs7840_break mos7840_port->shadowLCR is %x\n", | 1348 | dbg("mcs7840_break mos7840_port->shadowLCR is %x\n", |
1348 | mos7840_port->shadowLCR); | 1349 | mos7840_port->shadowLCR); |
1349 | mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, | 1350 | mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, |
1350 | mos7840_port->shadowLCR); | 1351 | mos7840_port->shadowLCR); |
1351 | 1352 | ||
1352 | return; | 1353 | return; |
1353 | } | 1354 | } |
1354 | 1355 | ||
1355 | /***************************************************************************** | 1356 | /***************************************************************************** |
1356 | * mos7840_write_room | 1357 | * mos7840_write_room |
1357 | * this function is called by the tty driver when it wants to know how many | 1358 | * this function is called by the tty driver when it wants to know how many |
1358 | * bytes of data we can accept for a specific port. | 1359 | * bytes of data we can accept for a specific port. |
1359 | * If successful, we return the amount of room that we have for this port | 1360 | * If successful, we return the amount of room that we have for this port |
1360 | * Otherwise we return a negative error number. | 1361 | * Otherwise we return a negative error number. |
1361 | *****************************************************************************/ | 1362 | *****************************************************************************/ |
1362 | 1363 | ||
1363 | static int mos7840_write_room(struct tty_struct *tty) | 1364 | static int mos7840_write_room(struct tty_struct *tty) |
1364 | { | 1365 | { |
1365 | struct usb_serial_port *port = tty->driver_data; | 1366 | struct usb_serial_port *port = tty->driver_data; |
1366 | int i; | 1367 | int i; |
1367 | int room = 0; | 1368 | int room = 0; |
1368 | unsigned long flags; | 1369 | unsigned long flags; |
1369 | struct moschip_port *mos7840_port; | 1370 | struct moschip_port *mos7840_port; |
1370 | 1371 | ||
1371 | dbg("%s \n", " mos7840_write_room:entering ..........."); | 1372 | dbg("%s \n", " mos7840_write_room:entering ..........."); |
1372 | 1373 | ||
1373 | if (mos7840_port_paranoia_check(port, __func__)) { | 1374 | if (mos7840_port_paranoia_check(port, __func__)) { |
1374 | dbg("%s", "Invalid port \n"); | 1375 | dbg("%s", "Invalid port \n"); |
1375 | dbg("%s \n", " mos7840_write_room:leaving ..........."); | 1376 | dbg("%s \n", " mos7840_write_room:leaving ..........."); |
1376 | return -1; | 1377 | return -1; |
1377 | } | 1378 | } |
1378 | 1379 | ||
1379 | mos7840_port = mos7840_get_port_private(port); | 1380 | mos7840_port = mos7840_get_port_private(port); |
1380 | if (mos7840_port == NULL) { | 1381 | if (mos7840_port == NULL) { |
1381 | dbg("%s \n", "mos7840_break:leaving ..........."); | 1382 | dbg("%s \n", "mos7840_break:leaving ..........."); |
1382 | return -1; | 1383 | return -1; |
1383 | } | 1384 | } |
1384 | 1385 | ||
1385 | spin_lock_irqsave(&mos7840_port->pool_lock, flags); | 1386 | spin_lock_irqsave(&mos7840_port->pool_lock, flags); |
1386 | for (i = 0; i < NUM_URBS; ++i) { | 1387 | for (i = 0; i < NUM_URBS; ++i) { |
1387 | if (!mos7840_port->busy[i]) | 1388 | if (!mos7840_port->busy[i]) |
1388 | room += URB_TRANSFER_BUFFER_SIZE; | 1389 | room += URB_TRANSFER_BUFFER_SIZE; |
1389 | } | 1390 | } |
1390 | spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); | 1391 | spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); |
1391 | 1392 | ||
1392 | room = (room == 0) ? 0 : room - URB_TRANSFER_BUFFER_SIZE + 1; | 1393 | room = (room == 0) ? 0 : room - URB_TRANSFER_BUFFER_SIZE + 1; |
1393 | dbg("%s - returns %d", __func__, room); | 1394 | dbg("%s - returns %d", __func__, room); |
1394 | return room; | 1395 | return room; |
1395 | 1396 | ||
1396 | } | 1397 | } |
1397 | 1398 | ||
1398 | /***************************************************************************** | 1399 | /***************************************************************************** |
1399 | * mos7840_write | 1400 | * mos7840_write |
1400 | * this function is called by the tty driver when data should be written to | 1401 | * this function is called by the tty driver when data should be written to |
1401 | * the port. | 1402 | * the port. |
1402 | * If successful, we return the number of bytes written, otherwise we | 1403 | * If successful, we return the number of bytes written, otherwise we |
1403 | * return a negative error number. | 1404 | * return a negative error number. |
1404 | *****************************************************************************/ | 1405 | *****************************************************************************/ |
1405 | 1406 | ||
1406 | static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, | 1407 | static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, |
1407 | const unsigned char *data, int count) | 1408 | const unsigned char *data, int count) |
1408 | { | 1409 | { |
1409 | int status; | 1410 | int status; |
1410 | int i; | 1411 | int i; |
1411 | int bytes_sent = 0; | 1412 | int bytes_sent = 0; |
1412 | int transfer_size; | 1413 | int transfer_size; |
1413 | unsigned long flags; | 1414 | unsigned long flags; |
1414 | 1415 | ||
1415 | struct moschip_port *mos7840_port; | 1416 | struct moschip_port *mos7840_port; |
1416 | struct usb_serial *serial; | 1417 | struct usb_serial *serial; |
1417 | struct urb *urb; | 1418 | struct urb *urb; |
1418 | /* __u16 Data; */ | 1419 | /* __u16 Data; */ |
1419 | const unsigned char *current_position = data; | 1420 | const unsigned char *current_position = data; |
1420 | unsigned char *data1; | 1421 | unsigned char *data1; |
1421 | dbg("%s \n", "entering ..........."); | 1422 | dbg("%s \n", "entering ..........."); |
1422 | /* dbg("mos7840_write: mos7840_port->shadowLCR is %x\n", | 1423 | /* dbg("mos7840_write: mos7840_port->shadowLCR is %x\n", |
1423 | mos7840_port->shadowLCR); */ | 1424 | mos7840_port->shadowLCR); */ |
1424 | 1425 | ||
1425 | #ifdef NOTMOS7840 | 1426 | #ifdef NOTMOS7840 |
1426 | Data = 0x00; | 1427 | Data = 0x00; |
1427 | status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); | 1428 | status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); |
1428 | mos7840_port->shadowLCR = Data; | 1429 | mos7840_port->shadowLCR = Data; |
1429 | dbg("mos7840_write: LINE_CONTROL_REGISTER is %x\n", Data); | 1430 | dbg("mos7840_write: LINE_CONTROL_REGISTER is %x\n", Data); |
1430 | dbg("mos7840_write: mos7840_port->shadowLCR is %x\n", | 1431 | dbg("mos7840_write: mos7840_port->shadowLCR is %x\n", |
1431 | mos7840_port->shadowLCR); | 1432 | mos7840_port->shadowLCR); |
1432 | 1433 | ||
1433 | /* Data = 0x03; */ | 1434 | /* Data = 0x03; */ |
1434 | /* status = mos7840_set_uart_reg(port,LINE_CONTROL_REGISTER,Data); */ | 1435 | /* status = mos7840_set_uart_reg(port,LINE_CONTROL_REGISTER,Data); */ |
1435 | /* mos7840_port->shadowLCR=Data;//Need to add later */ | 1436 | /* mos7840_port->shadowLCR=Data;//Need to add later */ |
1436 | 1437 | ||
1437 | Data |= SERIAL_LCR_DLAB; /* data latch enable in LCR 0x80 */ | 1438 | Data |= SERIAL_LCR_DLAB; /* data latch enable in LCR 0x80 */ |
1438 | status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | 1439 | status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); |
1439 | 1440 | ||
1440 | /* Data = 0x0c; */ | 1441 | /* Data = 0x0c; */ |
1441 | /* status = mos7840_set_uart_reg(port,DIVISOR_LATCH_LSB,Data); */ | 1442 | /* status = mos7840_set_uart_reg(port,DIVISOR_LATCH_LSB,Data); */ |
1442 | Data = 0x00; | 1443 | Data = 0x00; |
1443 | status = mos7840_get_uart_reg(port, DIVISOR_LATCH_LSB, &Data); | 1444 | status = mos7840_get_uart_reg(port, DIVISOR_LATCH_LSB, &Data); |
1444 | dbg("mos7840_write:DLL value is %x\n", Data); | 1445 | dbg("mos7840_write:DLL value is %x\n", Data); |
1445 | 1446 | ||
1446 | Data = 0x0; | 1447 | Data = 0x0; |
1447 | status = mos7840_get_uart_reg(port, DIVISOR_LATCH_MSB, &Data); | 1448 | status = mos7840_get_uart_reg(port, DIVISOR_LATCH_MSB, &Data); |
1448 | dbg("mos7840_write:DLM value is %x\n", Data); | 1449 | dbg("mos7840_write:DLM value is %x\n", Data); |
1449 | 1450 | ||
1450 | Data = Data & ~SERIAL_LCR_DLAB; | 1451 | Data = Data & ~SERIAL_LCR_DLAB; |
1451 | dbg("mos7840_write: mos7840_port->shadowLCR is %x\n", | 1452 | dbg("mos7840_write: mos7840_port->shadowLCR is %x\n", |
1452 | mos7840_port->shadowLCR); | 1453 | mos7840_port->shadowLCR); |
1453 | status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | 1454 | status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); |
1454 | #endif | 1455 | #endif |
1455 | 1456 | ||
1456 | if (mos7840_port_paranoia_check(port, __func__)) { | 1457 | if (mos7840_port_paranoia_check(port, __func__)) { |
1457 | dbg("%s", "Port Paranoia failed \n"); | 1458 | dbg("%s", "Port Paranoia failed \n"); |
1458 | return -1; | 1459 | return -1; |
1459 | } | 1460 | } |
1460 | 1461 | ||
1461 | serial = port->serial; | 1462 | serial = port->serial; |
1462 | if (mos7840_serial_paranoia_check(serial, __func__)) { | 1463 | if (mos7840_serial_paranoia_check(serial, __func__)) { |
1463 | dbg("%s", "Serial Paranoia failed \n"); | 1464 | dbg("%s", "Serial Paranoia failed \n"); |
1464 | return -1; | 1465 | return -1; |
1465 | } | 1466 | } |
1466 | 1467 | ||
1467 | mos7840_port = mos7840_get_port_private(port); | 1468 | mos7840_port = mos7840_get_port_private(port); |
1468 | if (mos7840_port == NULL) { | 1469 | if (mos7840_port == NULL) { |
1469 | dbg("%s", "mos7840_port is NULL\n"); | 1470 | dbg("%s", "mos7840_port is NULL\n"); |
1470 | return -1; | 1471 | return -1; |
1471 | } | 1472 | } |
1472 | 1473 | ||
1473 | /* try to find a free urb in the list */ | 1474 | /* try to find a free urb in the list */ |
1474 | urb = NULL; | 1475 | urb = NULL; |
1475 | 1476 | ||
1476 | spin_lock_irqsave(&mos7840_port->pool_lock, flags); | 1477 | spin_lock_irqsave(&mos7840_port->pool_lock, flags); |
1477 | for (i = 0; i < NUM_URBS; ++i) { | 1478 | for (i = 0; i < NUM_URBS; ++i) { |
1478 | if (!mos7840_port->busy[i]) { | 1479 | if (!mos7840_port->busy[i]) { |
1479 | mos7840_port->busy[i] = 1; | 1480 | mos7840_port->busy[i] = 1; |
1480 | urb = mos7840_port->write_urb_pool[i]; | 1481 | urb = mos7840_port->write_urb_pool[i]; |
1481 | dbg("\nURB:%d", i); | 1482 | dbg("\nURB:%d", i); |
1482 | break; | 1483 | break; |
1483 | } | 1484 | } |
1484 | } | 1485 | } |
1485 | spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); | 1486 | spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); |
1486 | 1487 | ||
1487 | if (urb == NULL) { | 1488 | if (urb == NULL) { |
1488 | dbg("%s - no more free urbs", __func__); | 1489 | dbg("%s - no more free urbs", __func__); |
1489 | goto exit; | 1490 | goto exit; |
1490 | } | 1491 | } |
1491 | 1492 | ||
1492 | if (urb->transfer_buffer == NULL) { | 1493 | if (urb->transfer_buffer == NULL) { |
1493 | urb->transfer_buffer = | 1494 | urb->transfer_buffer = |
1494 | kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); | 1495 | kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); |
1495 | 1496 | ||
1496 | if (urb->transfer_buffer == NULL) { | 1497 | if (urb->transfer_buffer == NULL) { |
1497 | dev_err(&port->dev, "%s no more kernel memory...\n", | 1498 | dev_err(&port->dev, "%s no more kernel memory...\n", |
1498 | __func__); | 1499 | __func__); |
1499 | goto exit; | 1500 | goto exit; |
1500 | } | 1501 | } |
1501 | } | 1502 | } |
1502 | transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE); | 1503 | transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE); |
1503 | 1504 | ||
1504 | memcpy(urb->transfer_buffer, current_position, transfer_size); | 1505 | memcpy(urb->transfer_buffer, current_position, transfer_size); |
1505 | 1506 | ||
1506 | /* fill urb with data and submit */ | 1507 | /* fill urb with data and submit */ |
1507 | usb_fill_bulk_urb(urb, | 1508 | usb_fill_bulk_urb(urb, |
1508 | serial->dev, | 1509 | serial->dev, |
1509 | usb_sndbulkpipe(serial->dev, | 1510 | usb_sndbulkpipe(serial->dev, |
1510 | port->bulk_out_endpointAddress), | 1511 | port->bulk_out_endpointAddress), |
1511 | urb->transfer_buffer, | 1512 | urb->transfer_buffer, |
1512 | transfer_size, | 1513 | transfer_size, |
1513 | mos7840_bulk_out_data_callback, mos7840_port); | 1514 | mos7840_bulk_out_data_callback, mos7840_port); |
1514 | 1515 | ||
1515 | data1 = urb->transfer_buffer; | 1516 | data1 = urb->transfer_buffer; |
1516 | dbg("\nbulkout endpoint is %d", port->bulk_out_endpointAddress); | 1517 | dbg("\nbulkout endpoint is %d", port->bulk_out_endpointAddress); |
1517 | 1518 | ||
1518 | /* send it down the pipe */ | 1519 | /* send it down the pipe */ |
1519 | status = usb_submit_urb(urb, GFP_ATOMIC); | 1520 | status = usb_submit_urb(urb, GFP_ATOMIC); |
1520 | 1521 | ||
1521 | if (status) { | 1522 | if (status) { |
1522 | mos7840_port->busy[i] = 0; | 1523 | mos7840_port->busy[i] = 0; |
1523 | dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed " | 1524 | dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed " |
1524 | "with status = %d\n", __func__, status); | 1525 | "with status = %d\n", __func__, status); |
1525 | bytes_sent = status; | 1526 | bytes_sent = status; |
1526 | goto exit; | 1527 | goto exit; |
1527 | } | 1528 | } |
1528 | bytes_sent = transfer_size; | 1529 | bytes_sent = transfer_size; |
1529 | mos7840_port->icount.tx += transfer_size; | 1530 | mos7840_port->icount.tx += transfer_size; |
1530 | smp_wmb(); | 1531 | smp_wmb(); |
1531 | dbg("mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx); | 1532 | dbg("mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx); |
1532 | exit: | 1533 | exit: |
1533 | return bytes_sent; | 1534 | return bytes_sent; |
1534 | 1535 | ||
1535 | } | 1536 | } |
1536 | 1537 | ||
1537 | /***************************************************************************** | 1538 | /***************************************************************************** |
1538 | * mos7840_throttle | 1539 | * mos7840_throttle |
1539 | * this function is called by the tty driver when it wants to stop the data | 1540 | * this function is called by the tty driver when it wants to stop the data |
1540 | * being read from the port. | 1541 | * being read from the port. |
1541 | *****************************************************************************/ | 1542 | *****************************************************************************/ |
1542 | 1543 | ||
1543 | static void mos7840_throttle(struct tty_struct *tty) | 1544 | static void mos7840_throttle(struct tty_struct *tty) |
1544 | { | 1545 | { |
1545 | struct usb_serial_port *port = tty->driver_data; | 1546 | struct usb_serial_port *port = tty->driver_data; |
1546 | struct moschip_port *mos7840_port; | 1547 | struct moschip_port *mos7840_port; |
1547 | int status; | 1548 | int status; |
1548 | 1549 | ||
1549 | if (mos7840_port_paranoia_check(port, __func__)) { | 1550 | if (mos7840_port_paranoia_check(port, __func__)) { |
1550 | dbg("%s", "Invalid port \n"); | 1551 | dbg("%s", "Invalid port \n"); |
1551 | return; | 1552 | return; |
1552 | } | 1553 | } |
1553 | 1554 | ||
1554 | dbg("- port %d\n", port->number); | 1555 | dbg("- port %d\n", port->number); |
1555 | 1556 | ||
1556 | mos7840_port = mos7840_get_port_private(port); | 1557 | mos7840_port = mos7840_get_port_private(port); |
1557 | 1558 | ||
1558 | if (mos7840_port == NULL) | 1559 | if (mos7840_port == NULL) |
1559 | return; | 1560 | return; |
1560 | 1561 | ||
1561 | if (!mos7840_port->open) { | 1562 | if (!mos7840_port->open) { |
1562 | dbg("%s\n", "port not opened"); | 1563 | dbg("%s\n", "port not opened"); |
1563 | return; | 1564 | return; |
1564 | } | 1565 | } |
1565 | 1566 | ||
1566 | dbg("%s", "Entering .......... \n"); | 1567 | dbg("%s", "Entering .......... \n"); |
1567 | 1568 | ||
1568 | /* if we are implementing XON/XOFF, send the stop character */ | 1569 | /* if we are implementing XON/XOFF, send the stop character */ |
1569 | if (I_IXOFF(tty)) { | 1570 | if (I_IXOFF(tty)) { |
1570 | unsigned char stop_char = STOP_CHAR(tty); | 1571 | unsigned char stop_char = STOP_CHAR(tty); |
1571 | status = mos7840_write(tty, port, &stop_char, 1); | 1572 | status = mos7840_write(tty, port, &stop_char, 1); |
1572 | if (status <= 0) | 1573 | if (status <= 0) |
1573 | return; | 1574 | return; |
1574 | } | 1575 | } |
1575 | /* if we are implementing RTS/CTS, toggle that line */ | 1576 | /* if we are implementing RTS/CTS, toggle that line */ |
1576 | if (tty->termios->c_cflag & CRTSCTS) { | 1577 | if (tty->termios->c_cflag & CRTSCTS) { |
1577 | mos7840_port->shadowMCR &= ~MCR_RTS; | 1578 | mos7840_port->shadowMCR &= ~MCR_RTS; |
1578 | status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, | 1579 | status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, |
1579 | mos7840_port->shadowMCR); | 1580 | mos7840_port->shadowMCR); |
1580 | if (status < 0) | 1581 | if (status < 0) |
1581 | return; | 1582 | return; |
1582 | } | 1583 | } |
1583 | 1584 | ||
1584 | return; | 1585 | return; |
1585 | } | 1586 | } |
1586 | 1587 | ||
1587 | /***************************************************************************** | 1588 | /***************************************************************************** |
1588 | * mos7840_unthrottle | 1589 | * mos7840_unthrottle |
1589 | * this function is called by the tty driver when it wants to resume | 1590 | * this function is called by the tty driver when it wants to resume |
1590 | * the data being read from the port (called after mos7840_throttle is | 1591 | * the data being read from the port (called after mos7840_throttle is |
1591 | * called) | 1592 | * called) |
1592 | *****************************************************************************/ | 1593 | *****************************************************************************/ |
1593 | static void mos7840_unthrottle(struct tty_struct *tty) | 1594 | static void mos7840_unthrottle(struct tty_struct *tty) |
1594 | { | 1595 | { |
1595 | struct usb_serial_port *port = tty->driver_data; | 1596 | struct usb_serial_port *port = tty->driver_data; |
1596 | int status; | 1597 | int status; |
1597 | struct moschip_port *mos7840_port = mos7840_get_port_private(port); | 1598 | struct moschip_port *mos7840_port = mos7840_get_port_private(port); |
1598 | 1599 | ||
1599 | if (mos7840_port_paranoia_check(port, __func__)) { | 1600 | if (mos7840_port_paranoia_check(port, __func__)) { |
1600 | dbg("%s", "Invalid port \n"); | 1601 | dbg("%s", "Invalid port \n"); |
1601 | return; | 1602 | return; |
1602 | } | 1603 | } |
1603 | 1604 | ||
1604 | if (mos7840_port == NULL) | 1605 | if (mos7840_port == NULL) |
1605 | return; | 1606 | return; |
1606 | 1607 | ||
1607 | if (!mos7840_port->open) { | 1608 | if (!mos7840_port->open) { |
1608 | dbg("%s - port not opened", __func__); | 1609 | dbg("%s - port not opened", __func__); |
1609 | return; | 1610 | return; |
1610 | } | 1611 | } |
1611 | 1612 | ||
1612 | dbg("%s", "Entering .......... \n"); | 1613 | dbg("%s", "Entering .......... \n"); |
1613 | 1614 | ||
1614 | /* if we are implementing XON/XOFF, send the start character */ | 1615 | /* if we are implementing XON/XOFF, send the start character */ |
1615 | if (I_IXOFF(tty)) { | 1616 | if (I_IXOFF(tty)) { |
1616 | unsigned char start_char = START_CHAR(tty); | 1617 | unsigned char start_char = START_CHAR(tty); |
1617 | status = mos7840_write(tty, port, &start_char, 1); | 1618 | status = mos7840_write(tty, port, &start_char, 1); |
1618 | if (status <= 0) | 1619 | if (status <= 0) |
1619 | return; | 1620 | return; |
1620 | } | 1621 | } |
1621 | 1622 | ||
1622 | /* if we are implementing RTS/CTS, toggle that line */ | 1623 | /* if we are implementing RTS/CTS, toggle that line */ |
1623 | if (tty->termios->c_cflag & CRTSCTS) { | 1624 | if (tty->termios->c_cflag & CRTSCTS) { |
1624 | mos7840_port->shadowMCR |= MCR_RTS; | 1625 | mos7840_port->shadowMCR |= MCR_RTS; |
1625 | status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, | 1626 | status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, |
1626 | mos7840_port->shadowMCR); | 1627 | mos7840_port->shadowMCR); |
1627 | if (status < 0) | 1628 | if (status < 0) |
1628 | return; | 1629 | return; |
1629 | } | 1630 | } |
1630 | } | 1631 | } |
1631 | 1632 | ||
1632 | static int mos7840_tiocmget(struct tty_struct *tty, struct file *file) | 1633 | static int mos7840_tiocmget(struct tty_struct *tty, struct file *file) |
1633 | { | 1634 | { |
1634 | struct usb_serial_port *port = tty->driver_data; | 1635 | struct usb_serial_port *port = tty->driver_data; |
1635 | struct moschip_port *mos7840_port; | 1636 | struct moschip_port *mos7840_port; |
1636 | unsigned int result; | 1637 | unsigned int result; |
1637 | __u16 msr; | 1638 | __u16 msr; |
1638 | __u16 mcr; | 1639 | __u16 mcr; |
1639 | int status; | 1640 | int status; |
1640 | mos7840_port = mos7840_get_port_private(port); | 1641 | mos7840_port = mos7840_get_port_private(port); |
1641 | 1642 | ||
1642 | dbg("%s - port %d", __func__, port->number); | 1643 | dbg("%s - port %d", __func__, port->number); |
1643 | 1644 | ||
1644 | if (mos7840_port == NULL) | 1645 | if (mos7840_port == NULL) |
1645 | return -ENODEV; | 1646 | return -ENODEV; |
1646 | 1647 | ||
1647 | status = mos7840_get_uart_reg(port, MODEM_STATUS_REGISTER, &msr); | 1648 | status = mos7840_get_uart_reg(port, MODEM_STATUS_REGISTER, &msr); |
1648 | status = mos7840_get_uart_reg(port, MODEM_CONTROL_REGISTER, &mcr); | 1649 | status = mos7840_get_uart_reg(port, MODEM_CONTROL_REGISTER, &mcr); |
1649 | result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) | 1650 | result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) |
1650 | | ((mcr & MCR_RTS) ? TIOCM_RTS : 0) | 1651 | | ((mcr & MCR_RTS) ? TIOCM_RTS : 0) |
1651 | | ((mcr & MCR_LOOPBACK) ? TIOCM_LOOP : 0) | 1652 | | ((mcr & MCR_LOOPBACK) ? TIOCM_LOOP : 0) |
1652 | | ((msr & MOS7840_MSR_CTS) ? TIOCM_CTS : 0) | 1653 | | ((msr & MOS7840_MSR_CTS) ? TIOCM_CTS : 0) |
1653 | | ((msr & MOS7840_MSR_CD) ? TIOCM_CAR : 0) | 1654 | | ((msr & MOS7840_MSR_CD) ? TIOCM_CAR : 0) |
1654 | | ((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0) | 1655 | | ((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0) |
1655 | | ((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0); | 1656 | | ((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0); |
1656 | 1657 | ||
1657 | dbg("%s - 0x%04X", __func__, result); | 1658 | dbg("%s - 0x%04X", __func__, result); |
1658 | 1659 | ||
1659 | return result; | 1660 | return result; |
1660 | } | 1661 | } |
1661 | 1662 | ||
1662 | static int mos7840_tiocmset(struct tty_struct *tty, struct file *file, | 1663 | static int mos7840_tiocmset(struct tty_struct *tty, struct file *file, |
1663 | unsigned int set, unsigned int clear) | 1664 | unsigned int set, unsigned int clear) |
1664 | { | 1665 | { |
1665 | struct usb_serial_port *port = tty->driver_data; | 1666 | struct usb_serial_port *port = tty->driver_data; |
1666 | struct moschip_port *mos7840_port; | 1667 | struct moschip_port *mos7840_port; |
1667 | unsigned int mcr; | 1668 | unsigned int mcr; |
1668 | int status; | 1669 | int status; |
1669 | 1670 | ||
1670 | dbg("%s - port %d", __func__, port->number); | 1671 | dbg("%s - port %d", __func__, port->number); |
1671 | 1672 | ||
1672 | mos7840_port = mos7840_get_port_private(port); | 1673 | mos7840_port = mos7840_get_port_private(port); |
1673 | 1674 | ||
1674 | if (mos7840_port == NULL) | 1675 | if (mos7840_port == NULL) |
1675 | return -ENODEV; | 1676 | return -ENODEV; |
1676 | 1677 | ||
1677 | /* FIXME: What locks the port registers ? */ | 1678 | /* FIXME: What locks the port registers ? */ |
1678 | mcr = mos7840_port->shadowMCR; | 1679 | mcr = mos7840_port->shadowMCR; |
1679 | if (clear & TIOCM_RTS) | 1680 | if (clear & TIOCM_RTS) |
1680 | mcr &= ~MCR_RTS; | 1681 | mcr &= ~MCR_RTS; |
1681 | if (clear & TIOCM_DTR) | 1682 | if (clear & TIOCM_DTR) |
1682 | mcr &= ~MCR_DTR; | 1683 | mcr &= ~MCR_DTR; |
1683 | if (clear & TIOCM_LOOP) | 1684 | if (clear & TIOCM_LOOP) |
1684 | mcr &= ~MCR_LOOPBACK; | 1685 | mcr &= ~MCR_LOOPBACK; |
1685 | 1686 | ||
1686 | if (set & TIOCM_RTS) | 1687 | if (set & TIOCM_RTS) |
1687 | mcr |= MCR_RTS; | 1688 | mcr |= MCR_RTS; |
1688 | if (set & TIOCM_DTR) | 1689 | if (set & TIOCM_DTR) |
1689 | mcr |= MCR_DTR; | 1690 | mcr |= MCR_DTR; |
1690 | if (set & TIOCM_LOOP) | 1691 | if (set & TIOCM_LOOP) |
1691 | mcr |= MCR_LOOPBACK; | 1692 | mcr |= MCR_LOOPBACK; |
1692 | 1693 | ||
1693 | mos7840_port->shadowMCR = mcr; | 1694 | mos7840_port->shadowMCR = mcr; |
1694 | 1695 | ||
1695 | status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mcr); | 1696 | status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mcr); |
1696 | if (status < 0) { | 1697 | if (status < 0) { |
1697 | dbg("setting MODEM_CONTROL_REGISTER Failed\n"); | 1698 | dbg("setting MODEM_CONTROL_REGISTER Failed\n"); |
1698 | return status; | 1699 | return status; |
1699 | } | 1700 | } |
1700 | 1701 | ||
1701 | return 0; | 1702 | return 0; |
1702 | } | 1703 | } |
1703 | 1704 | ||
1704 | /***************************************************************************** | 1705 | /***************************************************************************** |
1705 | * mos7840_calc_baud_rate_divisor | 1706 | * mos7840_calc_baud_rate_divisor |
1706 | * this function calculates the proper baud rate divisor for the specified | 1707 | * this function calculates the proper baud rate divisor for the specified |
1707 | * baud rate. | 1708 | * baud rate. |
1708 | *****************************************************************************/ | 1709 | *****************************************************************************/ |
1709 | static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor, | 1710 | static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor, |
1710 | __u16 *clk_sel_val) | 1711 | __u16 *clk_sel_val) |
1711 | { | 1712 | { |
1712 | 1713 | ||
1713 | dbg("%s - %d", __func__, baudRate); | 1714 | dbg("%s - %d", __func__, baudRate); |
1714 | 1715 | ||
1715 | if (baudRate <= 115200) { | 1716 | if (baudRate <= 115200) { |
1716 | *divisor = 115200 / baudRate; | 1717 | *divisor = 115200 / baudRate; |
1717 | *clk_sel_val = 0x0; | 1718 | *clk_sel_val = 0x0; |
1718 | } | 1719 | } |
1719 | if ((baudRate > 115200) && (baudRate <= 230400)) { | 1720 | if ((baudRate > 115200) && (baudRate <= 230400)) { |
1720 | *divisor = 230400 / baudRate; | 1721 | *divisor = 230400 / baudRate; |
1721 | *clk_sel_val = 0x10; | 1722 | *clk_sel_val = 0x10; |
1722 | } else if ((baudRate > 230400) && (baudRate <= 403200)) { | 1723 | } else if ((baudRate > 230400) && (baudRate <= 403200)) { |
1723 | *divisor = 403200 / baudRate; | 1724 | *divisor = 403200 / baudRate; |
1724 | *clk_sel_val = 0x20; | 1725 | *clk_sel_val = 0x20; |
1725 | } else if ((baudRate > 403200) && (baudRate <= 460800)) { | 1726 | } else if ((baudRate > 403200) && (baudRate <= 460800)) { |
1726 | *divisor = 460800 / baudRate; | 1727 | *divisor = 460800 / baudRate; |
1727 | *clk_sel_val = 0x30; | 1728 | *clk_sel_val = 0x30; |
1728 | } else if ((baudRate > 460800) && (baudRate <= 806400)) { | 1729 | } else if ((baudRate > 460800) && (baudRate <= 806400)) { |
1729 | *divisor = 806400 / baudRate; | 1730 | *divisor = 806400 / baudRate; |
1730 | *clk_sel_val = 0x40; | 1731 | *clk_sel_val = 0x40; |
1731 | } else if ((baudRate > 806400) && (baudRate <= 921600)) { | 1732 | } else if ((baudRate > 806400) && (baudRate <= 921600)) { |
1732 | *divisor = 921600 / baudRate; | 1733 | *divisor = 921600 / baudRate; |
1733 | *clk_sel_val = 0x50; | 1734 | *clk_sel_val = 0x50; |
1734 | } else if ((baudRate > 921600) && (baudRate <= 1572864)) { | 1735 | } else if ((baudRate > 921600) && (baudRate <= 1572864)) { |
1735 | *divisor = 1572864 / baudRate; | 1736 | *divisor = 1572864 / baudRate; |
1736 | *clk_sel_val = 0x60; | 1737 | *clk_sel_val = 0x60; |
1737 | } else if ((baudRate > 1572864) && (baudRate <= 3145728)) { | 1738 | } else if ((baudRate > 1572864) && (baudRate <= 3145728)) { |
1738 | *divisor = 3145728 / baudRate; | 1739 | *divisor = 3145728 / baudRate; |
1739 | *clk_sel_val = 0x70; | 1740 | *clk_sel_val = 0x70; |
1740 | } | 1741 | } |
1741 | return 0; | 1742 | return 0; |
1742 | 1743 | ||
1743 | #ifdef NOTMCS7840 | 1744 | #ifdef NOTMCS7840 |
1744 | 1745 | ||
1745 | for (i = 0; i < ARRAY_SIZE(mos7840_divisor_table); i++) { | 1746 | for (i = 0; i < ARRAY_SIZE(mos7840_divisor_table); i++) { |
1746 | if (mos7840_divisor_table[i].BaudRate == baudrate) { | 1747 | if (mos7840_divisor_table[i].BaudRate == baudrate) { |
1747 | *divisor = mos7840_divisor_table[i].Divisor; | 1748 | *divisor = mos7840_divisor_table[i].Divisor; |
1748 | return 0; | 1749 | return 0; |
1749 | } | 1750 | } |
1750 | } | 1751 | } |
1751 | 1752 | ||
1752 | /* After trying for all the standard baud rates * | 1753 | /* After trying for all the standard baud rates * |
1753 | * Try calculating the divisor for this baud rate */ | 1754 | * Try calculating the divisor for this baud rate */ |
1754 | 1755 | ||
1755 | if (baudrate > 75 && baudrate < 230400) { | 1756 | if (baudrate > 75 && baudrate < 230400) { |
1756 | /* get the divisor */ | 1757 | /* get the divisor */ |
1757 | custom = (__u16) (230400L / baudrate); | 1758 | custom = (__u16) (230400L / baudrate); |
1758 | 1759 | ||
1759 | /* Check for round off */ | 1760 | /* Check for round off */ |
1760 | round1 = (__u16) (2304000L / baudrate); | 1761 | round1 = (__u16) (2304000L / baudrate); |
1761 | round = (__u16) (round1 - (custom * 10)); | 1762 | round = (__u16) (round1 - (custom * 10)); |
1762 | if (round > 4) | 1763 | if (round > 4) |
1763 | custom++; | 1764 | custom++; |
1764 | *divisor = custom; | 1765 | *divisor = custom; |
1765 | 1766 | ||
1766 | dbg(" Baud %d = %d\n", baudrate, custom); | 1767 | dbg(" Baud %d = %d\n", baudrate, custom); |
1767 | return 0; | 1768 | return 0; |
1768 | } | 1769 | } |
1769 | 1770 | ||
1770 | dbg("%s\n", " Baud calculation Failed..."); | 1771 | dbg("%s\n", " Baud calculation Failed..."); |
1771 | return -1; | 1772 | return -1; |
1772 | #endif | 1773 | #endif |
1773 | } | 1774 | } |
1774 | 1775 | ||
1775 | /***************************************************************************** | 1776 | /***************************************************************************** |
1776 | * mos7840_send_cmd_write_baud_rate | 1777 | * mos7840_send_cmd_write_baud_rate |
1777 | * this function sends the proper command to change the baud rate of the | 1778 | * this function sends the proper command to change the baud rate of the |
1778 | * specified port. | 1779 | * specified port. |
1779 | *****************************************************************************/ | 1780 | *****************************************************************************/ |
1780 | 1781 | ||
1781 | static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, | 1782 | static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, |
1782 | int baudRate) | 1783 | int baudRate) |
1783 | { | 1784 | { |
1784 | int divisor = 0; | 1785 | int divisor = 0; |
1785 | int status; | 1786 | int status; |
1786 | __u16 Data; | 1787 | __u16 Data; |
1787 | unsigned char number; | 1788 | unsigned char number; |
1788 | __u16 clk_sel_val; | 1789 | __u16 clk_sel_val; |
1789 | struct usb_serial_port *port; | 1790 | struct usb_serial_port *port; |
1790 | 1791 | ||
1791 | if (mos7840_port == NULL) | 1792 | if (mos7840_port == NULL) |
1792 | return -1; | 1793 | return -1; |
1793 | 1794 | ||
1794 | port = (struct usb_serial_port *)mos7840_port->port; | 1795 | port = (struct usb_serial_port *)mos7840_port->port; |
1795 | if (mos7840_port_paranoia_check(port, __func__)) { | 1796 | if (mos7840_port_paranoia_check(port, __func__)) { |
1796 | dbg("%s", "Invalid port \n"); | 1797 | dbg("%s", "Invalid port \n"); |
1797 | return -1; | 1798 | return -1; |
1798 | } | 1799 | } |
1799 | 1800 | ||
1800 | if (mos7840_serial_paranoia_check(port->serial, __func__)) { | 1801 | if (mos7840_serial_paranoia_check(port->serial, __func__)) { |
1801 | dbg("%s", "Invalid Serial \n"); | 1802 | dbg("%s", "Invalid Serial \n"); |
1802 | return -1; | 1803 | return -1; |
1803 | } | 1804 | } |
1804 | 1805 | ||
1805 | dbg("%s", "Entering .......... \n"); | 1806 | dbg("%s", "Entering .......... \n"); |
1806 | 1807 | ||
1807 | number = mos7840_port->port->number - mos7840_port->port->serial->minor; | 1808 | number = mos7840_port->port->number - mos7840_port->port->serial->minor; |
1808 | 1809 | ||
1809 | dbg("%s - port = %d, baud = %d", __func__, | 1810 | dbg("%s - port = %d, baud = %d", __func__, |
1810 | mos7840_port->port->number, baudRate); | 1811 | mos7840_port->port->number, baudRate); |
1811 | /* reset clk_uart_sel in spregOffset */ | 1812 | /* reset clk_uart_sel in spregOffset */ |
1812 | if (baudRate > 115200) { | 1813 | if (baudRate > 115200) { |
1813 | #ifdef HW_flow_control | 1814 | #ifdef HW_flow_control |
1814 | /* NOTE: need to see the pther register to modify */ | 1815 | /* NOTE: need to see the pther register to modify */ |
1815 | /* setting h/w flow control bit to 1 */ | 1816 | /* setting h/w flow control bit to 1 */ |
1816 | Data = 0x2b; | 1817 | Data = 0x2b; |
1817 | mos7840_port->shadowMCR = Data; | 1818 | mos7840_port->shadowMCR = Data; |
1818 | status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, | 1819 | status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, |
1819 | Data); | 1820 | Data); |
1820 | if (status < 0) { | 1821 | if (status < 0) { |
1821 | dbg("Writing spreg failed in set_serial_baud\n"); | 1822 | dbg("Writing spreg failed in set_serial_baud\n"); |
1822 | return -1; | 1823 | return -1; |
1823 | } | 1824 | } |
1824 | #endif | 1825 | #endif |
1825 | 1826 | ||
1826 | } else { | 1827 | } else { |
1827 | #ifdef HW_flow_control | 1828 | #ifdef HW_flow_control |
1828 | / *setting h/w flow control bit to 0 */ | 1829 | / *setting h/w flow control bit to 0 */ |
1829 | Data = 0xb; | 1830 | Data = 0xb; |
1830 | mos7840_port->shadowMCR = Data; | 1831 | mos7840_port->shadowMCR = Data; |
1831 | status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, | 1832 | status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, |
1832 | Data); | 1833 | Data); |
1833 | if (status < 0) { | 1834 | if (status < 0) { |
1834 | dbg("Writing spreg failed in set_serial_baud\n"); | 1835 | dbg("Writing spreg failed in set_serial_baud\n"); |
1835 | return -1; | 1836 | return -1; |
1836 | } | 1837 | } |
1837 | #endif | 1838 | #endif |
1838 | 1839 | ||
1839 | } | 1840 | } |
1840 | 1841 | ||
1841 | if (1) { /* baudRate <= 115200) */ | 1842 | if (1) { /* baudRate <= 115200) */ |
1842 | clk_sel_val = 0x0; | 1843 | clk_sel_val = 0x0; |
1843 | Data = 0x0; | 1844 | Data = 0x0; |
1844 | status = mos7840_calc_baud_rate_divisor(baudRate, &divisor, | 1845 | status = mos7840_calc_baud_rate_divisor(baudRate, &divisor, |
1845 | &clk_sel_val); | 1846 | &clk_sel_val); |
1846 | status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, | 1847 | status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, |
1847 | &Data); | 1848 | &Data); |
1848 | if (status < 0) { | 1849 | if (status < 0) { |
1849 | dbg("reading spreg failed in set_serial_baud\n"); | 1850 | dbg("reading spreg failed in set_serial_baud\n"); |
1850 | return -1; | 1851 | return -1; |
1851 | } | 1852 | } |
1852 | Data = (Data & 0x8f) | clk_sel_val; | 1853 | Data = (Data & 0x8f) | clk_sel_val; |
1853 | status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, | 1854 | status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, |
1854 | Data); | 1855 | Data); |
1855 | if (status < 0) { | 1856 | if (status < 0) { |
1856 | dbg("Writing spreg failed in set_serial_baud\n"); | 1857 | dbg("Writing spreg failed in set_serial_baud\n"); |
1857 | return -1; | 1858 | return -1; |
1858 | } | 1859 | } |
1859 | /* Calculate the Divisor */ | 1860 | /* Calculate the Divisor */ |
1860 | 1861 | ||
1861 | if (status) { | 1862 | if (status) { |
1862 | dev_err(&port->dev, "%s - bad baud rate\n", __func__); | 1863 | dev_err(&port->dev, "%s - bad baud rate\n", __func__); |
1863 | return status; | 1864 | return status; |
1864 | } | 1865 | } |
1865 | /* Enable access to divisor latch */ | 1866 | /* Enable access to divisor latch */ |
1866 | Data = mos7840_port->shadowLCR | SERIAL_LCR_DLAB; | 1867 | Data = mos7840_port->shadowLCR | SERIAL_LCR_DLAB; |
1867 | mos7840_port->shadowLCR = Data; | 1868 | mos7840_port->shadowLCR = Data; |
1868 | mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | 1869 | mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); |
1869 | 1870 | ||
1870 | /* Write the divisor */ | 1871 | /* Write the divisor */ |
1871 | Data = (unsigned char)(divisor & 0xff); | 1872 | Data = (unsigned char)(divisor & 0xff); |
1872 | dbg("set_serial_baud Value to write DLL is %x\n", Data); | 1873 | dbg("set_serial_baud Value to write DLL is %x\n", Data); |
1873 | mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data); | 1874 | mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data); |
1874 | 1875 | ||
1875 | Data = (unsigned char)((divisor & 0xff00) >> 8); | 1876 | Data = (unsigned char)((divisor & 0xff00) >> 8); |
1876 | dbg("set_serial_baud Value to write DLM is %x\n", Data); | 1877 | dbg("set_serial_baud Value to write DLM is %x\n", Data); |
1877 | mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data); | 1878 | mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data); |
1878 | 1879 | ||
1879 | /* Disable access to divisor latch */ | 1880 | /* Disable access to divisor latch */ |
1880 | Data = mos7840_port->shadowLCR & ~SERIAL_LCR_DLAB; | 1881 | Data = mos7840_port->shadowLCR & ~SERIAL_LCR_DLAB; |
1881 | mos7840_port->shadowLCR = Data; | 1882 | mos7840_port->shadowLCR = Data; |
1882 | mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | 1883 | mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); |
1883 | 1884 | ||
1884 | } | 1885 | } |
1885 | return status; | 1886 | return status; |
1886 | } | 1887 | } |
1887 | 1888 | ||
1888 | /***************************************************************************** | 1889 | /***************************************************************************** |
1889 | * mos7840_change_port_settings | 1890 | * mos7840_change_port_settings |
1890 | * This routine is called to set the UART on the device to match | 1891 | * This routine is called to set the UART on the device to match |
1891 | * the specified new settings. | 1892 | * the specified new settings. |
1892 | *****************************************************************************/ | 1893 | *****************************************************************************/ |
1893 | 1894 | ||
1894 | static void mos7840_change_port_settings(struct tty_struct *tty, | 1895 | static void mos7840_change_port_settings(struct tty_struct *tty, |
1895 | struct moschip_port *mos7840_port, struct ktermios *old_termios) | 1896 | struct moschip_port *mos7840_port, struct ktermios *old_termios) |
1896 | { | 1897 | { |
1897 | int baud; | 1898 | int baud; |
1898 | unsigned cflag; | 1899 | unsigned cflag; |
1899 | unsigned iflag; | 1900 | unsigned iflag; |
1900 | __u8 lData; | 1901 | __u8 lData; |
1901 | __u8 lParity; | 1902 | __u8 lParity; |
1902 | __u8 lStop; | 1903 | __u8 lStop; |
1903 | int status; | 1904 | int status; |
1904 | __u16 Data; | 1905 | __u16 Data; |
1905 | struct usb_serial_port *port; | 1906 | struct usb_serial_port *port; |
1906 | struct usb_serial *serial; | 1907 | struct usb_serial *serial; |
1907 | 1908 | ||
1908 | if (mos7840_port == NULL) | 1909 | if (mos7840_port == NULL) |
1909 | return; | 1910 | return; |
1910 | 1911 | ||
1911 | port = (struct usb_serial_port *)mos7840_port->port; | 1912 | port = (struct usb_serial_port *)mos7840_port->port; |
1912 | 1913 | ||
1913 | if (mos7840_port_paranoia_check(port, __func__)) { | 1914 | if (mos7840_port_paranoia_check(port, __func__)) { |
1914 | dbg("%s", "Invalid port \n"); | 1915 | dbg("%s", "Invalid port \n"); |
1915 | return; | 1916 | return; |
1916 | } | 1917 | } |
1917 | 1918 | ||
1918 | if (mos7840_serial_paranoia_check(port->serial, __func__)) { | 1919 | if (mos7840_serial_paranoia_check(port->serial, __func__)) { |
1919 | dbg("%s", "Invalid Serial \n"); | 1920 | dbg("%s", "Invalid Serial \n"); |
1920 | return; | 1921 | return; |
1921 | } | 1922 | } |
1922 | 1923 | ||
1923 | serial = port->serial; | 1924 | serial = port->serial; |
1924 | 1925 | ||
1925 | dbg("%s - port %d", __func__, mos7840_port->port->number); | 1926 | dbg("%s - port %d", __func__, mos7840_port->port->number); |
1926 | 1927 | ||
1927 | if (!mos7840_port->open) { | 1928 | if (!mos7840_port->open) { |
1928 | dbg("%s - port not opened", __func__); | 1929 | dbg("%s - port not opened", __func__); |
1929 | return; | 1930 | return; |
1930 | } | 1931 | } |
1931 | 1932 | ||
1932 | dbg("%s", "Entering .......... \n"); | 1933 | dbg("%s", "Entering .......... \n"); |
1933 | 1934 | ||
1934 | lData = LCR_BITS_8; | 1935 | lData = LCR_BITS_8; |
1935 | lStop = LCR_STOP_1; | 1936 | lStop = LCR_STOP_1; |
1936 | lParity = LCR_PAR_NONE; | 1937 | lParity = LCR_PAR_NONE; |
1937 | 1938 | ||
1938 | cflag = tty->termios->c_cflag; | 1939 | cflag = tty->termios->c_cflag; |
1939 | iflag = tty->termios->c_iflag; | 1940 | iflag = tty->termios->c_iflag; |
1940 | 1941 | ||
1941 | /* Change the number of bits */ | 1942 | /* Change the number of bits */ |
1942 | if (cflag & CSIZE) { | 1943 | if (cflag & CSIZE) { |
1943 | switch (cflag & CSIZE) { | 1944 | switch (cflag & CSIZE) { |
1944 | case CS5: | 1945 | case CS5: |
1945 | lData = LCR_BITS_5; | 1946 | lData = LCR_BITS_5; |
1946 | break; | 1947 | break; |
1947 | 1948 | ||
1948 | case CS6: | 1949 | case CS6: |
1949 | lData = LCR_BITS_6; | 1950 | lData = LCR_BITS_6; |
1950 | break; | 1951 | break; |
1951 | 1952 | ||
1952 | case CS7: | 1953 | case CS7: |
1953 | lData = LCR_BITS_7; | 1954 | lData = LCR_BITS_7; |
1954 | break; | 1955 | break; |
1955 | default: | 1956 | default: |
1956 | case CS8: | 1957 | case CS8: |
1957 | lData = LCR_BITS_8; | 1958 | lData = LCR_BITS_8; |
1958 | break; | 1959 | break; |
1959 | } | 1960 | } |
1960 | } | 1961 | } |
1961 | /* Change the Parity bit */ | 1962 | /* Change the Parity bit */ |
1962 | if (cflag & PARENB) { | 1963 | if (cflag & PARENB) { |
1963 | if (cflag & PARODD) { | 1964 | if (cflag & PARODD) { |
1964 | lParity = LCR_PAR_ODD; | 1965 | lParity = LCR_PAR_ODD; |
1965 | dbg("%s - parity = odd", __func__); | 1966 | dbg("%s - parity = odd", __func__); |
1966 | } else { | 1967 | } else { |
1967 | lParity = LCR_PAR_EVEN; | 1968 | lParity = LCR_PAR_EVEN; |
1968 | dbg("%s - parity = even", __func__); | 1969 | dbg("%s - parity = even", __func__); |
1969 | } | 1970 | } |
1970 | 1971 | ||
1971 | } else { | 1972 | } else { |
1972 | dbg("%s - parity = none", __func__); | 1973 | dbg("%s - parity = none", __func__); |
1973 | } | 1974 | } |
1974 | 1975 | ||
1975 | if (cflag & CMSPAR) | 1976 | if (cflag & CMSPAR) |
1976 | lParity = lParity | 0x20; | 1977 | lParity = lParity | 0x20; |
1977 | 1978 | ||
1978 | /* Change the Stop bit */ | 1979 | /* Change the Stop bit */ |
1979 | if (cflag & CSTOPB) { | 1980 | if (cflag & CSTOPB) { |
1980 | lStop = LCR_STOP_2; | 1981 | lStop = LCR_STOP_2; |
1981 | dbg("%s - stop bits = 2", __func__); | 1982 | dbg("%s - stop bits = 2", __func__); |
1982 | } else { | 1983 | } else { |
1983 | lStop = LCR_STOP_1; | 1984 | lStop = LCR_STOP_1; |
1984 | dbg("%s - stop bits = 1", __func__); | 1985 | dbg("%s - stop bits = 1", __func__); |
1985 | } | 1986 | } |
1986 | 1987 | ||
1987 | /* Update the LCR with the correct value */ | 1988 | /* Update the LCR with the correct value */ |
1988 | mos7840_port->shadowLCR &= | 1989 | mos7840_port->shadowLCR &= |
1989 | ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK); | 1990 | ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK); |
1990 | mos7840_port->shadowLCR |= (lData | lParity | lStop); | 1991 | mos7840_port->shadowLCR |= (lData | lParity | lStop); |
1991 | 1992 | ||
1992 | dbg("mos7840_change_port_settings mos7840_port->shadowLCR is %x\n", | 1993 | dbg("mos7840_change_port_settings mos7840_port->shadowLCR is %x\n", |
1993 | mos7840_port->shadowLCR); | 1994 | mos7840_port->shadowLCR); |
1994 | /* Disable Interrupts */ | 1995 | /* Disable Interrupts */ |
1995 | Data = 0x00; | 1996 | Data = 0x00; |
1996 | mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); | 1997 | mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); |
1997 | 1998 | ||
1998 | Data = 0x00; | 1999 | Data = 0x00; |
1999 | mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); | 2000 | mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); |
2000 | 2001 | ||
2001 | Data = 0xcf; | 2002 | Data = 0xcf; |
2002 | mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); | 2003 | mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); |
2003 | 2004 | ||
2004 | /* Send the updated LCR value to the mos7840 */ | 2005 | /* Send the updated LCR value to the mos7840 */ |
2005 | Data = mos7840_port->shadowLCR; | 2006 | Data = mos7840_port->shadowLCR; |
2006 | 2007 | ||
2007 | mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); | 2008 | mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); |
2008 | 2009 | ||
2009 | Data = 0x00b; | 2010 | Data = 0x00b; |
2010 | mos7840_port->shadowMCR = Data; | 2011 | mos7840_port->shadowMCR = Data; |
2011 | mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | 2012 | mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); |
2012 | Data = 0x00b; | 2013 | Data = 0x00b; |
2013 | mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | 2014 | mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); |
2014 | 2015 | ||
2015 | /* set up the MCR register and send it to the mos7840 */ | 2016 | /* set up the MCR register and send it to the mos7840 */ |
2016 | 2017 | ||
2017 | mos7840_port->shadowMCR = MCR_MASTER_IE; | 2018 | mos7840_port->shadowMCR = MCR_MASTER_IE; |
2018 | if (cflag & CBAUD) | 2019 | if (cflag & CBAUD) |
2019 | mos7840_port->shadowMCR |= (MCR_DTR | MCR_RTS); | 2020 | mos7840_port->shadowMCR |= (MCR_DTR | MCR_RTS); |
2020 | 2021 | ||
2021 | if (cflag & CRTSCTS) | 2022 | if (cflag & CRTSCTS) |
2022 | mos7840_port->shadowMCR |= (MCR_XON_ANY); | 2023 | mos7840_port->shadowMCR |= (MCR_XON_ANY); |
2023 | else | 2024 | else |
2024 | mos7840_port->shadowMCR &= ~(MCR_XON_ANY); | 2025 | mos7840_port->shadowMCR &= ~(MCR_XON_ANY); |
2025 | 2026 | ||
2026 | Data = mos7840_port->shadowMCR; | 2027 | Data = mos7840_port->shadowMCR; |
2027 | mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | 2028 | mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); |
2028 | 2029 | ||
2029 | /* Determine divisor based on baud rate */ | 2030 | /* Determine divisor based on baud rate */ |
2030 | baud = tty_get_baud_rate(tty); | 2031 | baud = tty_get_baud_rate(tty); |
2031 | 2032 | ||
2032 | if (!baud) { | 2033 | if (!baud) { |
2033 | /* pick a default, any default... */ | 2034 | /* pick a default, any default... */ |
2034 | dbg("%s\n", "Picked default baud..."); | 2035 | dbg("%s\n", "Picked default baud..."); |
2035 | baud = 9600; | 2036 | baud = 9600; |
2036 | } | 2037 | } |
2037 | 2038 | ||
2038 | dbg("%s - baud rate = %d", __func__, baud); | 2039 | dbg("%s - baud rate = %d", __func__, baud); |
2039 | status = mos7840_send_cmd_write_baud_rate(mos7840_port, baud); | 2040 | status = mos7840_send_cmd_write_baud_rate(mos7840_port, baud); |
2040 | 2041 | ||
2041 | /* Enable Interrupts */ | 2042 | /* Enable Interrupts */ |
2042 | Data = 0x0c; | 2043 | Data = 0x0c; |
2043 | mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); | 2044 | mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); |
2044 | 2045 | ||
2045 | if (mos7840_port->read_urb->status != -EINPROGRESS) { | 2046 | if (mos7840_port->read_urb->status != -EINPROGRESS) { |
2046 | mos7840_port->read_urb->dev = serial->dev; | 2047 | mos7840_port->read_urb->dev = serial->dev; |
2047 | 2048 | ||
2048 | status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); | 2049 | status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); |
2049 | 2050 | ||
2050 | if (status) { | 2051 | if (status) { |
2051 | dbg(" usb_submit_urb(read bulk) failed, status = %d", | 2052 | dbg(" usb_submit_urb(read bulk) failed, status = %d", |
2052 | status); | 2053 | status); |
2053 | } | 2054 | } |
2054 | } | 2055 | } |
2055 | wake_up(&mos7840_port->delta_msr_wait); | 2056 | wake_up(&mos7840_port->delta_msr_wait); |
2056 | mos7840_port->delta_msr_cond = 1; | 2057 | mos7840_port->delta_msr_cond = 1; |
2057 | dbg("mos7840_change_port_settings mos7840_port->shadowLCR is End %x\n", | 2058 | dbg("mos7840_change_port_settings mos7840_port->shadowLCR is End %x\n", |
2058 | mos7840_port->shadowLCR); | 2059 | mos7840_port->shadowLCR); |
2059 | 2060 | ||
2060 | return; | 2061 | return; |
2061 | } | 2062 | } |
2062 | 2063 | ||
2063 | /***************************************************************************** | 2064 | /***************************************************************************** |
2064 | * mos7840_set_termios | 2065 | * mos7840_set_termios |
2065 | * this function is called by the tty driver when it wants to change | 2066 | * this function is called by the tty driver when it wants to change |
2066 | * the termios structure | 2067 | * the termios structure |
2067 | *****************************************************************************/ | 2068 | *****************************************************************************/ |
2068 | 2069 | ||
2069 | static void mos7840_set_termios(struct tty_struct *tty, | 2070 | static void mos7840_set_termios(struct tty_struct *tty, |
2070 | struct usb_serial_port *port, | 2071 | struct usb_serial_port *port, |
2071 | struct ktermios *old_termios) | 2072 | struct ktermios *old_termios) |
2072 | { | 2073 | { |
2073 | int status; | 2074 | int status; |
2074 | unsigned int cflag; | 2075 | unsigned int cflag; |
2075 | struct usb_serial *serial; | 2076 | struct usb_serial *serial; |
2076 | struct moschip_port *mos7840_port; | 2077 | struct moschip_port *mos7840_port; |
2077 | dbg("mos7840_set_termios: START\n"); | 2078 | dbg("mos7840_set_termios: START\n"); |
2078 | if (mos7840_port_paranoia_check(port, __func__)) { | 2079 | if (mos7840_port_paranoia_check(port, __func__)) { |
2079 | dbg("%s", "Invalid port \n"); | 2080 | dbg("%s", "Invalid port \n"); |
2080 | return; | 2081 | return; |
2081 | } | 2082 | } |
2082 | 2083 | ||
2083 | serial = port->serial; | 2084 | serial = port->serial; |
2084 | 2085 | ||
2085 | if (mos7840_serial_paranoia_check(serial, __func__)) { | 2086 | if (mos7840_serial_paranoia_check(serial, __func__)) { |
2086 | dbg("%s", "Invalid Serial \n"); | 2087 | dbg("%s", "Invalid Serial \n"); |
2087 | return; | 2088 | return; |
2088 | } | 2089 | } |
2089 | 2090 | ||
2090 | mos7840_port = mos7840_get_port_private(port); | 2091 | mos7840_port = mos7840_get_port_private(port); |
2091 | 2092 | ||
2092 | if (mos7840_port == NULL) | 2093 | if (mos7840_port == NULL) |
2093 | return; | 2094 | return; |
2094 | 2095 | ||
2095 | if (!mos7840_port->open) { | 2096 | if (!mos7840_port->open) { |
2096 | dbg("%s - port not opened", __func__); | 2097 | dbg("%s - port not opened", __func__); |
2097 | return; | 2098 | return; |
2098 | } | 2099 | } |
2099 | 2100 | ||
2100 | dbg("%s\n", "setting termios - "); | 2101 | dbg("%s\n", "setting termios - "); |
2101 | 2102 | ||
2102 | cflag = tty->termios->c_cflag; | 2103 | cflag = tty->termios->c_cflag; |
2103 | 2104 | ||
2104 | dbg("%s - clfag %08x iflag %08x", __func__, | 2105 | dbg("%s - clfag %08x iflag %08x", __func__, |
2105 | tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag)); | 2106 | tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag)); |
2106 | dbg("%s - old clfag %08x old iflag %08x", __func__, | 2107 | dbg("%s - old clfag %08x old iflag %08x", __func__, |
2107 | old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag)); | 2108 | old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag)); |
2108 | dbg("%s - port %d", __func__, port->number); | 2109 | dbg("%s - port %d", __func__, port->number); |
2109 | 2110 | ||
2110 | /* change the port settings to the new ones specified */ | 2111 | /* change the port settings to the new ones specified */ |
2111 | 2112 | ||
2112 | mos7840_change_port_settings(tty, mos7840_port, old_termios); | 2113 | mos7840_change_port_settings(tty, mos7840_port, old_termios); |
2113 | 2114 | ||
2114 | if (!mos7840_port->read_urb) { | 2115 | if (!mos7840_port->read_urb) { |
2115 | dbg("%s", "URB KILLED !!!!!\n"); | 2116 | dbg("%s", "URB KILLED !!!!!\n"); |
2116 | return; | 2117 | return; |
2117 | } | 2118 | } |
2118 | 2119 | ||
2119 | if (mos7840_port->read_urb->status != -EINPROGRESS) { | 2120 | if (mos7840_port->read_urb->status != -EINPROGRESS) { |
2120 | mos7840_port->read_urb->dev = serial->dev; | 2121 | mos7840_port->read_urb->dev = serial->dev; |
2121 | status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); | 2122 | status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); |
2122 | if (status) { | 2123 | if (status) { |
2123 | dbg(" usb_submit_urb(read bulk) failed, status = %d", | 2124 | dbg(" usb_submit_urb(read bulk) failed, status = %d", |
2124 | status); | 2125 | status); |
2125 | } | 2126 | } |
2126 | } | 2127 | } |
2127 | return; | 2128 | return; |
2128 | } | 2129 | } |
2129 | 2130 | ||
2130 | /***************************************************************************** | 2131 | /***************************************************************************** |
2131 | * mos7840_get_lsr_info - get line status register info | 2132 | * mos7840_get_lsr_info - get line status register info |
2132 | * | 2133 | * |
2133 | * Purpose: Let user call ioctl() to get info when the UART physically | 2134 | * Purpose: Let user call ioctl() to get info when the UART physically |
2134 | * is emptied. On bus types like RS485, the transmitter must | 2135 | * is emptied. On bus types like RS485, the transmitter must |
2135 | * release the bus after transmitting. This must be done when | 2136 | * release the bus after transmitting. This must be done when |
2136 | * the transmit shift register is empty, not be done when the | 2137 | * the transmit shift register is empty, not be done when the |
2137 | * transmit holding register is empty. This functionality | 2138 | * transmit holding register is empty. This functionality |
2138 | * allows an RS485 driver to be written in user space. | 2139 | * allows an RS485 driver to be written in user space. |
2139 | *****************************************************************************/ | 2140 | *****************************************************************************/ |
2140 | 2141 | ||
2141 | static int mos7840_get_lsr_info(struct tty_struct *tty, | 2142 | static int mos7840_get_lsr_info(struct tty_struct *tty, |
2142 | unsigned int __user *value) | 2143 | unsigned int __user *value) |
2143 | { | 2144 | { |
2144 | int count; | 2145 | int count; |
2145 | unsigned int result = 0; | 2146 | unsigned int result = 0; |
2146 | 2147 | ||
2147 | count = mos7840_chars_in_buffer(tty); | 2148 | count = mos7840_chars_in_buffer(tty); |
2148 | if (count == 0) { | 2149 | if (count == 0) { |
2149 | dbg("%s -- Empty", __func__); | 2150 | dbg("%s -- Empty", __func__); |
2150 | result = TIOCSER_TEMT; | 2151 | result = TIOCSER_TEMT; |
2151 | } | 2152 | } |
2152 | 2153 | ||
2153 | if (copy_to_user(value, &result, sizeof(int))) | 2154 | if (copy_to_user(value, &result, sizeof(int))) |
2154 | return -EFAULT; | 2155 | return -EFAULT; |
2155 | return 0; | 2156 | return 0; |
2156 | } | 2157 | } |
2157 | 2158 | ||
2158 | /***************************************************************************** | 2159 | /***************************************************************************** |
2159 | * mos7840_set_modem_info | 2160 | * mos7840_set_modem_info |
2160 | * function to set modem info | 2161 | * function to set modem info |
2161 | *****************************************************************************/ | 2162 | *****************************************************************************/ |
2162 | 2163 | ||
2163 | /* FIXME: Should be using the model control hooks */ | 2164 | /* FIXME: Should be using the model control hooks */ |
2164 | 2165 | ||
2165 | static int mos7840_set_modem_info(struct moschip_port *mos7840_port, | 2166 | static int mos7840_set_modem_info(struct moschip_port *mos7840_port, |
2166 | unsigned int cmd, unsigned int __user *value) | 2167 | unsigned int cmd, unsigned int __user *value) |
2167 | { | 2168 | { |
2168 | unsigned int mcr; | 2169 | unsigned int mcr; |
2169 | unsigned int arg; | 2170 | unsigned int arg; |
2170 | __u16 Data; | 2171 | __u16 Data; |
2171 | int status; | 2172 | int status; |
2172 | struct usb_serial_port *port; | 2173 | struct usb_serial_port *port; |
2173 | 2174 | ||
2174 | if (mos7840_port == NULL) | 2175 | if (mos7840_port == NULL) |
2175 | return -1; | 2176 | return -1; |
2176 | 2177 | ||
2177 | port = (struct usb_serial_port *)mos7840_port->port; | 2178 | port = (struct usb_serial_port *)mos7840_port->port; |
2178 | if (mos7840_port_paranoia_check(port, __func__)) { | 2179 | if (mos7840_port_paranoia_check(port, __func__)) { |
2179 | dbg("%s", "Invalid port \n"); | 2180 | dbg("%s", "Invalid port \n"); |
2180 | return -1; | 2181 | return -1; |
2181 | } | 2182 | } |
2182 | 2183 | ||
2183 | mcr = mos7840_port->shadowMCR; | 2184 | mcr = mos7840_port->shadowMCR; |
2184 | 2185 | ||
2185 | if (copy_from_user(&arg, value, sizeof(int))) | 2186 | if (copy_from_user(&arg, value, sizeof(int))) |
2186 | return -EFAULT; | 2187 | return -EFAULT; |
2187 | 2188 | ||
2188 | switch (cmd) { | 2189 | switch (cmd) { |
2189 | case TIOCMBIS: | 2190 | case TIOCMBIS: |
2190 | if (arg & TIOCM_RTS) | 2191 | if (arg & TIOCM_RTS) |
2191 | mcr |= MCR_RTS; | 2192 | mcr |= MCR_RTS; |
2192 | if (arg & TIOCM_DTR) | 2193 | if (arg & TIOCM_DTR) |
2193 | mcr |= MCR_RTS; | 2194 | mcr |= MCR_RTS; |
2194 | if (arg & TIOCM_LOOP) | 2195 | if (arg & TIOCM_LOOP) |
2195 | mcr |= MCR_LOOPBACK; | 2196 | mcr |= MCR_LOOPBACK; |
2196 | break; | 2197 | break; |
2197 | 2198 | ||
2198 | case TIOCMBIC: | 2199 | case TIOCMBIC: |
2199 | if (arg & TIOCM_RTS) | 2200 | if (arg & TIOCM_RTS) |
2200 | mcr &= ~MCR_RTS; | 2201 | mcr &= ~MCR_RTS; |
2201 | if (arg & TIOCM_DTR) | 2202 | if (arg & TIOCM_DTR) |
2202 | mcr &= ~MCR_RTS; | 2203 | mcr &= ~MCR_RTS; |
2203 | if (arg & TIOCM_LOOP) | 2204 | if (arg & TIOCM_LOOP) |
2204 | mcr &= ~MCR_LOOPBACK; | 2205 | mcr &= ~MCR_LOOPBACK; |
2205 | break; | 2206 | break; |
2206 | 2207 | ||
2207 | case TIOCMSET: | 2208 | case TIOCMSET: |
2208 | /* turn off the RTS and DTR and LOOPBACK | 2209 | /* turn off the RTS and DTR and LOOPBACK |
2209 | * and then only turn on what was asked to */ | 2210 | * and then only turn on what was asked to */ |
2210 | mcr &= ~(MCR_RTS | MCR_DTR | MCR_LOOPBACK); | 2211 | mcr &= ~(MCR_RTS | MCR_DTR | MCR_LOOPBACK); |
2211 | mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0); | 2212 | mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0); |
2212 | mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0); | 2213 | mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0); |
2213 | mcr |= ((arg & TIOCM_LOOP) ? MCR_LOOPBACK : 0); | 2214 | mcr |= ((arg & TIOCM_LOOP) ? MCR_LOOPBACK : 0); |
2214 | break; | 2215 | break; |
2215 | } | 2216 | } |
2216 | 2217 | ||
2218 | lock_kernel(); | ||
2217 | mos7840_port->shadowMCR = mcr; | 2219 | mos7840_port->shadowMCR = mcr; |
2218 | 2220 | ||
2219 | Data = mos7840_port->shadowMCR; | 2221 | Data = mos7840_port->shadowMCR; |
2220 | status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | 2222 | status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); |
2223 | unlock_kernel(); | ||
2221 | if (status < 0) { | 2224 | if (status < 0) { |
2222 | dbg("setting MODEM_CONTROL_REGISTER Failed\n"); | 2225 | dbg("setting MODEM_CONTROL_REGISTER Failed\n"); |
2223 | return -1; | 2226 | return -1; |
2224 | } | 2227 | } |
2225 | 2228 | ||
2226 | return 0; | 2229 | return 0; |
2227 | } | 2230 | } |
2228 | 2231 | ||
2229 | /***************************************************************************** | 2232 | /***************************************************************************** |
2230 | * mos7840_get_modem_info | 2233 | * mos7840_get_modem_info |
2231 | * function to get modem info | 2234 | * function to get modem info |
2232 | *****************************************************************************/ | 2235 | *****************************************************************************/ |
2233 | 2236 | ||
2234 | static int mos7840_get_modem_info(struct moschip_port *mos7840_port, | 2237 | static int mos7840_get_modem_info(struct moschip_port *mos7840_port, |
2235 | unsigned int __user *value) | 2238 | unsigned int __user *value) |
2236 | { | 2239 | { |
2237 | unsigned int result = 0; | 2240 | unsigned int result = 0; |
2238 | __u16 msr; | 2241 | __u16 msr; |
2239 | unsigned int mcr = mos7840_port->shadowMCR; | 2242 | unsigned int mcr = mos7840_port->shadowMCR; |
2240 | mos7840_get_uart_reg(mos7840_port->port, | 2243 | mos7840_get_uart_reg(mos7840_port->port, |
2241 | MODEM_STATUS_REGISTER, &msr); | 2244 | MODEM_STATUS_REGISTER, &msr); |
2242 | result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) /* 0x002 */ | 2245 | result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) /* 0x002 */ |
2243 | |((mcr & MCR_RTS) ? TIOCM_RTS : 0) /* 0x004 */ | 2246 | |((mcr & MCR_RTS) ? TIOCM_RTS : 0) /* 0x004 */ |
2244 | |((msr & MOS7840_MSR_CTS) ? TIOCM_CTS : 0) /* 0x020 */ | 2247 | |((msr & MOS7840_MSR_CTS) ? TIOCM_CTS : 0) /* 0x020 */ |
2245 | |((msr & MOS7840_MSR_CD) ? TIOCM_CAR : 0) /* 0x040 */ | 2248 | |((msr & MOS7840_MSR_CD) ? TIOCM_CAR : 0) /* 0x040 */ |
2246 | |((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0) /* 0x080 */ | 2249 | |((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0) /* 0x080 */ |
2247 | |((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0); /* 0x100 */ | 2250 | |((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0); /* 0x100 */ |
2248 | 2251 | ||
2249 | dbg("%s -- %x", __func__, result); | 2252 | dbg("%s -- %x", __func__, result); |
2250 | 2253 | ||
2251 | if (copy_to_user(value, &result, sizeof(int))) | 2254 | if (copy_to_user(value, &result, sizeof(int))) |
2252 | return -EFAULT; | 2255 | return -EFAULT; |
2253 | return 0; | 2256 | return 0; |
2254 | } | 2257 | } |
2255 | 2258 | ||
2256 | /***************************************************************************** | 2259 | /***************************************************************************** |
2257 | * mos7840_get_serial_info | 2260 | * mos7840_get_serial_info |
2258 | * function to get information about serial port | 2261 | * function to get information about serial port |
2259 | *****************************************************************************/ | 2262 | *****************************************************************************/ |
2260 | 2263 | ||
2261 | static int mos7840_get_serial_info(struct moschip_port *mos7840_port, | 2264 | static int mos7840_get_serial_info(struct moschip_port *mos7840_port, |
2262 | struct serial_struct __user *retinfo) | 2265 | struct serial_struct __user *retinfo) |
2263 | { | 2266 | { |
2264 | struct serial_struct tmp; | 2267 | struct serial_struct tmp; |
2265 | 2268 | ||
2266 | if (mos7840_port == NULL) | 2269 | if (mos7840_port == NULL) |
2267 | return -1; | 2270 | return -1; |
2268 | 2271 | ||
2269 | if (!retinfo) | 2272 | if (!retinfo) |
2270 | return -EFAULT; | 2273 | return -EFAULT; |
2271 | 2274 | ||
2272 | memset(&tmp, 0, sizeof(tmp)); | 2275 | memset(&tmp, 0, sizeof(tmp)); |
2273 | 2276 | ||
2274 | tmp.type = PORT_16550A; | 2277 | tmp.type = PORT_16550A; |
2275 | tmp.line = mos7840_port->port->serial->minor; | 2278 | tmp.line = mos7840_port->port->serial->minor; |
2276 | tmp.port = mos7840_port->port->number; | 2279 | tmp.port = mos7840_port->port->number; |
2277 | tmp.irq = 0; | 2280 | tmp.irq = 0; |
2278 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; | 2281 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; |
2279 | tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE; | 2282 | tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE; |
2280 | tmp.baud_base = 9600; | 2283 | tmp.baud_base = 9600; |
2281 | tmp.close_delay = 5 * HZ; | 2284 | tmp.close_delay = 5 * HZ; |
2282 | tmp.closing_wait = 30 * HZ; | 2285 | tmp.closing_wait = 30 * HZ; |
2283 | 2286 | ||
2284 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) | 2287 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) |
2285 | return -EFAULT; | 2288 | return -EFAULT; |
2286 | return 0; | 2289 | return 0; |
2287 | } | 2290 | } |
2288 | 2291 | ||
2289 | /***************************************************************************** | 2292 | /***************************************************************************** |
2290 | * SerialIoctl | 2293 | * SerialIoctl |
2291 | * this function handles any ioctl calls to the driver | 2294 | * this function handles any ioctl calls to the driver |
2292 | *****************************************************************************/ | 2295 | *****************************************************************************/ |
2293 | 2296 | ||
2294 | static int mos7840_ioctl(struct tty_struct *tty, struct file *file, | 2297 | static int mos7840_ioctl(struct tty_struct *tty, struct file *file, |
2295 | unsigned int cmd, unsigned long arg) | 2298 | unsigned int cmd, unsigned long arg) |
2296 | { | 2299 | { |
2297 | struct usb_serial_port *port = tty->driver_data; | 2300 | struct usb_serial_port *port = tty->driver_data; |
2298 | void __user *argp = (void __user *)arg; | 2301 | void __user *argp = (void __user *)arg; |
2299 | struct moschip_port *mos7840_port; | 2302 | struct moschip_port *mos7840_port; |
2300 | 2303 | ||
2301 | struct async_icount cnow; | 2304 | struct async_icount cnow; |
2302 | struct async_icount cprev; | 2305 | struct async_icount cprev; |
2303 | struct serial_icounter_struct icount; | 2306 | struct serial_icounter_struct icount; |
2304 | int mosret = 0; | 2307 | int mosret = 0; |
2305 | 2308 | ||
2306 | if (mos7840_port_paranoia_check(port, __func__)) { | 2309 | if (mos7840_port_paranoia_check(port, __func__)) { |
2307 | dbg("%s", "Invalid port \n"); | 2310 | dbg("%s", "Invalid port \n"); |
2308 | return -1; | 2311 | return -1; |
2309 | } | 2312 | } |
2310 | 2313 | ||
2311 | mos7840_port = mos7840_get_port_private(port); | 2314 | mos7840_port = mos7840_get_port_private(port); |
2312 | 2315 | ||
2313 | if (mos7840_port == NULL) | 2316 | if (mos7840_port == NULL) |
2314 | return -1; | 2317 | return -1; |
2315 | 2318 | ||
2316 | dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); | 2319 | dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); |
2317 | 2320 | ||
2318 | switch (cmd) { | 2321 | switch (cmd) { |
2319 | /* return number of bytes available */ | 2322 | /* return number of bytes available */ |
2320 | 2323 | ||
2321 | case TIOCSERGETLSR: | 2324 | case TIOCSERGETLSR: |
2322 | dbg("%s (%d) TIOCSERGETLSR", __func__, port->number); | 2325 | dbg("%s (%d) TIOCSERGETLSR", __func__, port->number); |
2323 | return mos7840_get_lsr_info(tty, argp); | 2326 | return mos7840_get_lsr_info(tty, argp); |
2324 | return 0; | 2327 | return 0; |
2325 | 2328 | ||
2326 | /* FIXME: use the modem hooks and remove this */ | 2329 | /* FIXME: use the modem hooks and remove this */ |
2327 | case TIOCMBIS: | 2330 | case TIOCMBIS: |
2328 | case TIOCMBIC: | 2331 | case TIOCMBIC: |
2329 | case TIOCMSET: | 2332 | case TIOCMSET: |
2330 | dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __func__, | 2333 | dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __func__, |
2331 | port->number); | 2334 | port->number); |
2332 | mosret = | 2335 | mosret = |
2333 | mos7840_set_modem_info(mos7840_port, cmd, argp); | 2336 | mos7840_set_modem_info(mos7840_port, cmd, argp); |
2334 | return mosret; | 2337 | return mosret; |
2335 | 2338 | ||
2336 | case TIOCMGET: | 2339 | case TIOCMGET: |
2337 | dbg("%s (%d) TIOCMGET", __func__, port->number); | 2340 | dbg("%s (%d) TIOCMGET", __func__, port->number); |
2338 | return mos7840_get_modem_info(mos7840_port, argp); | 2341 | return mos7840_get_modem_info(mos7840_port, argp); |
2339 | 2342 | ||
2340 | case TIOCGSERIAL: | 2343 | case TIOCGSERIAL: |
2341 | dbg("%s (%d) TIOCGSERIAL", __func__, port->number); | 2344 | dbg("%s (%d) TIOCGSERIAL", __func__, port->number); |
2342 | return mos7840_get_serial_info(mos7840_port, argp); | 2345 | return mos7840_get_serial_info(mos7840_port, argp); |
2343 | 2346 | ||
2344 | case TIOCSSERIAL: | 2347 | case TIOCSSERIAL: |
2345 | dbg("%s (%d) TIOCSSERIAL", __func__, port->number); | 2348 | dbg("%s (%d) TIOCSSERIAL", __func__, port->number); |
2346 | break; | 2349 | break; |
2347 | 2350 | ||
2348 | case TIOCMIWAIT: | 2351 | case TIOCMIWAIT: |
2349 | dbg("%s (%d) TIOCMIWAIT", __func__, port->number); | 2352 | dbg("%s (%d) TIOCMIWAIT", __func__, port->number); |
2350 | cprev = mos7840_port->icount; | 2353 | cprev = mos7840_port->icount; |
2351 | while (1) { | 2354 | while (1) { |
2352 | /* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */ | 2355 | /* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */ |
2353 | mos7840_port->delta_msr_cond = 0; | 2356 | mos7840_port->delta_msr_cond = 0; |
2354 | wait_event_interruptible(mos7840_port->delta_msr_wait, | 2357 | wait_event_interruptible(mos7840_port->delta_msr_wait, |
2355 | (mos7840_port-> | 2358 | (mos7840_port-> |
2356 | delta_msr_cond == 1)); | 2359 | delta_msr_cond == 1)); |
2357 | 2360 | ||
2358 | /* see if a signal did it */ | 2361 | /* see if a signal did it */ |
2359 | if (signal_pending(current)) | 2362 | if (signal_pending(current)) |
2360 | return -ERESTARTSYS; | 2363 | return -ERESTARTSYS; |
2361 | cnow = mos7840_port->icount; | 2364 | cnow = mos7840_port->icount; |
2362 | smp_rmb(); | 2365 | smp_rmb(); |
2363 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && | 2366 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && |
2364 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) | 2367 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) |
2365 | return -EIO; /* no change => error */ | 2368 | return -EIO; /* no change => error */ |
2366 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || | 2369 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || |
2367 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || | 2370 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || |
2368 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || | 2371 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || |
2369 | ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { | 2372 | ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { |
2370 | return 0; | 2373 | return 0; |
2371 | } | 2374 | } |
2372 | cprev = cnow; | 2375 | cprev = cnow; |
2373 | } | 2376 | } |
2374 | /* NOTREACHED */ | 2377 | /* NOTREACHED */ |
2375 | break; | 2378 | break; |
2376 | 2379 | ||
2377 | case TIOCGICOUNT: | 2380 | case TIOCGICOUNT: |
2378 | cnow = mos7840_port->icount; | 2381 | cnow = mos7840_port->icount; |
2379 | smp_rmb(); | 2382 | smp_rmb(); |
2380 | icount.cts = cnow.cts; | 2383 | icount.cts = cnow.cts; |
2381 | icount.dsr = cnow.dsr; | 2384 | icount.dsr = cnow.dsr; |
2382 | icount.rng = cnow.rng; | 2385 | icount.rng = cnow.rng; |
2383 | icount.dcd = cnow.dcd; | 2386 | icount.dcd = cnow.dcd; |
2384 | icount.rx = cnow.rx; | 2387 | icount.rx = cnow.rx; |
2385 | icount.tx = cnow.tx; | 2388 | icount.tx = cnow.tx; |
2386 | icount.frame = cnow.frame; | 2389 | icount.frame = cnow.frame; |
2387 | icount.overrun = cnow.overrun; | 2390 | icount.overrun = cnow.overrun; |
2388 | icount.parity = cnow.parity; | 2391 | icount.parity = cnow.parity; |
2389 | icount.brk = cnow.brk; | 2392 | icount.brk = cnow.brk; |
2390 | icount.buf_overrun = cnow.buf_overrun; | 2393 | icount.buf_overrun = cnow.buf_overrun; |
2391 | 2394 | ||
2392 | dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, | 2395 | dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, |
2393 | port->number, icount.rx, icount.tx); | 2396 | port->number, icount.rx, icount.tx); |
2394 | if (copy_to_user(argp, &icount, sizeof(icount))) | 2397 | if (copy_to_user(argp, &icount, sizeof(icount))) |
2395 | return -EFAULT; | 2398 | return -EFAULT; |
2396 | return 0; | 2399 | return 0; |
2397 | default: | 2400 | default: |
2398 | break; | 2401 | break; |
2399 | } | 2402 | } |
2400 | return -ENOIOCTLCMD; | 2403 | return -ENOIOCTLCMD; |
2401 | } | 2404 | } |
2402 | 2405 | ||
2403 | static int mos7840_calc_num_ports(struct usb_serial *serial) | 2406 | static int mos7840_calc_num_ports(struct usb_serial *serial) |
2404 | { | 2407 | { |
2405 | int mos7840_num_ports = 0; | 2408 | int mos7840_num_ports = 0; |
2406 | 2409 | ||
2407 | dbg("numberofendpoints: %d \n", | 2410 | dbg("numberofendpoints: %d \n", |
2408 | (int)serial->interface->cur_altsetting->desc.bNumEndpoints); | 2411 | (int)serial->interface->cur_altsetting->desc.bNumEndpoints); |
2409 | dbg("numberofendpoints: %d \n", | 2412 | dbg("numberofendpoints: %d \n", |
2410 | (int)serial->interface->altsetting->desc.bNumEndpoints); | 2413 | (int)serial->interface->altsetting->desc.bNumEndpoints); |
2411 | if (serial->interface->cur_altsetting->desc.bNumEndpoints == 5) { | 2414 | if (serial->interface->cur_altsetting->desc.bNumEndpoints == 5) { |
2412 | mos7840_num_ports = serial->num_ports = 2; | 2415 | mos7840_num_ports = serial->num_ports = 2; |
2413 | } else if (serial->interface->cur_altsetting->desc.bNumEndpoints == 9) { | 2416 | } else if (serial->interface->cur_altsetting->desc.bNumEndpoints == 9) { |
2414 | serial->num_bulk_in = 4; | 2417 | serial->num_bulk_in = 4; |
2415 | serial->num_bulk_out = 4; | 2418 | serial->num_bulk_out = 4; |
2416 | mos7840_num_ports = serial->num_ports = 4; | 2419 | mos7840_num_ports = serial->num_ports = 4; |
2417 | } | 2420 | } |
2418 | 2421 | ||
2419 | return mos7840_num_ports; | 2422 | return mos7840_num_ports; |
2420 | } | 2423 | } |
2421 | 2424 | ||
2422 | /**************************************************************************** | 2425 | /**************************************************************************** |
2423 | * mos7840_startup | 2426 | * mos7840_startup |
2424 | ****************************************************************************/ | 2427 | ****************************************************************************/ |
2425 | 2428 | ||
2426 | static int mos7840_startup(struct usb_serial *serial) | 2429 | static int mos7840_startup(struct usb_serial *serial) |
2427 | { | 2430 | { |
2428 | struct moschip_port *mos7840_port; | 2431 | struct moschip_port *mos7840_port; |
2429 | struct usb_device *dev; | 2432 | struct usb_device *dev; |
2430 | int i, status; | 2433 | int i, status; |
2431 | 2434 | ||
2432 | __u16 Data; | 2435 | __u16 Data; |
2433 | dbg("%s \n", " mos7840_startup :entering.........."); | 2436 | dbg("%s \n", " mos7840_startup :entering.........."); |
2434 | 2437 | ||
2435 | if (!serial) { | 2438 | if (!serial) { |
2436 | dbg("%s\n", "Invalid Handler"); | 2439 | dbg("%s\n", "Invalid Handler"); |
2437 | return -1; | 2440 | return -1; |
2438 | } | 2441 | } |
2439 | 2442 | ||
2440 | dev = serial->dev; | 2443 | dev = serial->dev; |
2441 | 2444 | ||
2442 | dbg("%s\n", "Entering..."); | 2445 | dbg("%s\n", "Entering..."); |
2443 | 2446 | ||
2444 | /* we set up the pointers to the endpoints in the mos7840_open * | 2447 | /* we set up the pointers to the endpoints in the mos7840_open * |
2445 | * function, as the structures aren't created yet. */ | 2448 | * function, as the structures aren't created yet. */ |
2446 | 2449 | ||
2447 | /* set up port private structures */ | 2450 | /* set up port private structures */ |
2448 | for (i = 0; i < serial->num_ports; ++i) { | 2451 | for (i = 0; i < serial->num_ports; ++i) { |
2449 | mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); | 2452 | mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); |
2450 | if (mos7840_port == NULL) { | 2453 | if (mos7840_port == NULL) { |
2451 | dev_err(&dev->dev, "%s - Out of memory\n", __func__); | 2454 | dev_err(&dev->dev, "%s - Out of memory\n", __func__); |
2452 | status = -ENOMEM; | 2455 | status = -ENOMEM; |
2453 | i--; /* don't follow NULL pointer cleaning up */ | 2456 | i--; /* don't follow NULL pointer cleaning up */ |
2454 | goto error; | 2457 | goto error; |
2455 | } | 2458 | } |
2456 | 2459 | ||
2457 | /* Initialize all port interrupt end point to port 0 int | 2460 | /* Initialize all port interrupt end point to port 0 int |
2458 | * endpoint. Our device has only one interrupt end point | 2461 | * endpoint. Our device has only one interrupt end point |
2459 | * common to all port */ | 2462 | * common to all port */ |
2460 | 2463 | ||
2461 | mos7840_port->port = serial->port[i]; | 2464 | mos7840_port->port = serial->port[i]; |
2462 | mos7840_set_port_private(serial->port[i], mos7840_port); | 2465 | mos7840_set_port_private(serial->port[i], mos7840_port); |
2463 | spin_lock_init(&mos7840_port->pool_lock); | 2466 | spin_lock_init(&mos7840_port->pool_lock); |
2464 | 2467 | ||
2465 | mos7840_port->port_num = ((serial->port[i]->number - | 2468 | mos7840_port->port_num = ((serial->port[i]->number - |
2466 | (serial->port[i]->serial->minor)) + | 2469 | (serial->port[i]->serial->minor)) + |
2467 | 1); | 2470 | 1); |
2468 | 2471 | ||
2469 | if (mos7840_port->port_num == 1) { | 2472 | if (mos7840_port->port_num == 1) { |
2470 | mos7840_port->SpRegOffset = 0x0; | 2473 | mos7840_port->SpRegOffset = 0x0; |
2471 | mos7840_port->ControlRegOffset = 0x1; | 2474 | mos7840_port->ControlRegOffset = 0x1; |
2472 | mos7840_port->DcrRegOffset = 0x4; | 2475 | mos7840_port->DcrRegOffset = 0x4; |
2473 | } else if ((mos7840_port->port_num == 2) | 2476 | } else if ((mos7840_port->port_num == 2) |
2474 | && (serial->num_ports == 4)) { | 2477 | && (serial->num_ports == 4)) { |
2475 | mos7840_port->SpRegOffset = 0x8; | 2478 | mos7840_port->SpRegOffset = 0x8; |
2476 | mos7840_port->ControlRegOffset = 0x9; | 2479 | mos7840_port->ControlRegOffset = 0x9; |
2477 | mos7840_port->DcrRegOffset = 0x16; | 2480 | mos7840_port->DcrRegOffset = 0x16; |
2478 | } else if ((mos7840_port->port_num == 2) | 2481 | } else if ((mos7840_port->port_num == 2) |
2479 | && (serial->num_ports == 2)) { | 2482 | && (serial->num_ports == 2)) { |
2480 | mos7840_port->SpRegOffset = 0xa; | 2483 | mos7840_port->SpRegOffset = 0xa; |
2481 | mos7840_port->ControlRegOffset = 0xb; | 2484 | mos7840_port->ControlRegOffset = 0xb; |
2482 | mos7840_port->DcrRegOffset = 0x19; | 2485 | mos7840_port->DcrRegOffset = 0x19; |
2483 | } else if ((mos7840_port->port_num == 3) | 2486 | } else if ((mos7840_port->port_num == 3) |
2484 | && (serial->num_ports == 4)) { | 2487 | && (serial->num_ports == 4)) { |
2485 | mos7840_port->SpRegOffset = 0xa; | 2488 | mos7840_port->SpRegOffset = 0xa; |
2486 | mos7840_port->ControlRegOffset = 0xb; | 2489 | mos7840_port->ControlRegOffset = 0xb; |
2487 | mos7840_port->DcrRegOffset = 0x19; | 2490 | mos7840_port->DcrRegOffset = 0x19; |
2488 | } else if ((mos7840_port->port_num == 4) | 2491 | } else if ((mos7840_port->port_num == 4) |
2489 | && (serial->num_ports == 4)) { | 2492 | && (serial->num_ports == 4)) { |
2490 | mos7840_port->SpRegOffset = 0xc; | 2493 | mos7840_port->SpRegOffset = 0xc; |
2491 | mos7840_port->ControlRegOffset = 0xd; | 2494 | mos7840_port->ControlRegOffset = 0xd; |
2492 | mos7840_port->DcrRegOffset = 0x1c; | 2495 | mos7840_port->DcrRegOffset = 0x1c; |
2493 | } | 2496 | } |
2494 | mos7840_dump_serial_port(mos7840_port); | 2497 | mos7840_dump_serial_port(mos7840_port); |
2495 | mos7840_set_port_private(serial->port[i], mos7840_port); | 2498 | mos7840_set_port_private(serial->port[i], mos7840_port); |
2496 | 2499 | ||
2497 | /* enable rx_disable bit in control register */ | 2500 | /* enable rx_disable bit in control register */ |
2498 | status = mos7840_get_reg_sync(serial->port[i], | 2501 | status = mos7840_get_reg_sync(serial->port[i], |
2499 | mos7840_port->ControlRegOffset, &Data); | 2502 | mos7840_port->ControlRegOffset, &Data); |
2500 | if (status < 0) { | 2503 | if (status < 0) { |
2501 | dbg("Reading ControlReg failed status-0x%x\n", status); | 2504 | dbg("Reading ControlReg failed status-0x%x\n", status); |
2502 | break; | 2505 | break; |
2503 | } else | 2506 | } else |
2504 | dbg("ControlReg Reading success val is %x, status%d\n", | 2507 | dbg("ControlReg Reading success val is %x, status%d\n", |
2505 | Data, status); | 2508 | Data, status); |
2506 | Data |= 0x08; /* setting driver done bit */ | 2509 | Data |= 0x08; /* setting driver done bit */ |
2507 | Data |= 0x04; /* sp1_bit to have cts change reflect in | 2510 | Data |= 0x04; /* sp1_bit to have cts change reflect in |
2508 | modem status reg */ | 2511 | modem status reg */ |
2509 | 2512 | ||
2510 | /* Data |= 0x20; //rx_disable bit */ | 2513 | /* Data |= 0x20; //rx_disable bit */ |
2511 | status = mos7840_set_reg_sync(serial->port[i], | 2514 | status = mos7840_set_reg_sync(serial->port[i], |
2512 | mos7840_port->ControlRegOffset, Data); | 2515 | mos7840_port->ControlRegOffset, Data); |
2513 | if (status < 0) { | 2516 | if (status < 0) { |
2514 | dbg("Writing ControlReg failed(rx_disable) status-0x%x\n", status); | 2517 | dbg("Writing ControlReg failed(rx_disable) status-0x%x\n", status); |
2515 | break; | 2518 | break; |
2516 | } else | 2519 | } else |
2517 | dbg("ControlReg Writing success(rx_disable) status%d\n", | 2520 | dbg("ControlReg Writing success(rx_disable) status%d\n", |
2518 | status); | 2521 | status); |
2519 | 2522 | ||
2520 | /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 | 2523 | /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 |
2521 | and 0x24 in DCR3 */ | 2524 | and 0x24 in DCR3 */ |
2522 | Data = 0x01; | 2525 | Data = 0x01; |
2523 | status = mos7840_set_reg_sync(serial->port[i], | 2526 | status = mos7840_set_reg_sync(serial->port[i], |
2524 | (__u16) (mos7840_port->DcrRegOffset + 0), Data); | 2527 | (__u16) (mos7840_port->DcrRegOffset + 0), Data); |
2525 | if (status < 0) { | 2528 | if (status < 0) { |
2526 | dbg("Writing DCR0 failed status-0x%x\n", status); | 2529 | dbg("Writing DCR0 failed status-0x%x\n", status); |
2527 | break; | 2530 | break; |
2528 | } else | 2531 | } else |
2529 | dbg("DCR0 Writing success status%d\n", status); | 2532 | dbg("DCR0 Writing success status%d\n", status); |
2530 | 2533 | ||
2531 | Data = 0x05; | 2534 | Data = 0x05; |
2532 | status = mos7840_set_reg_sync(serial->port[i], | 2535 | status = mos7840_set_reg_sync(serial->port[i], |
2533 | (__u16) (mos7840_port->DcrRegOffset + 1), Data); | 2536 | (__u16) (mos7840_port->DcrRegOffset + 1), Data); |
2534 | if (status < 0) { | 2537 | if (status < 0) { |
2535 | dbg("Writing DCR1 failed status-0x%x\n", status); | 2538 | dbg("Writing DCR1 failed status-0x%x\n", status); |
2536 | break; | 2539 | break; |
2537 | } else | 2540 | } else |
2538 | dbg("DCR1 Writing success status%d\n", status); | 2541 | dbg("DCR1 Writing success status%d\n", status); |
2539 | 2542 | ||
2540 | Data = 0x24; | 2543 | Data = 0x24; |
2541 | status = mos7840_set_reg_sync(serial->port[i], | 2544 | status = mos7840_set_reg_sync(serial->port[i], |
2542 | (__u16) (mos7840_port->DcrRegOffset + 2), Data); | 2545 | (__u16) (mos7840_port->DcrRegOffset + 2), Data); |
2543 | if (status < 0) { | 2546 | if (status < 0) { |
2544 | dbg("Writing DCR2 failed status-0x%x\n", status); | 2547 | dbg("Writing DCR2 failed status-0x%x\n", status); |
2545 | break; | 2548 | break; |
2546 | } else | 2549 | } else |
2547 | dbg("DCR2 Writing success status%d\n", status); | 2550 | dbg("DCR2 Writing success status%d\n", status); |
2548 | 2551 | ||
2549 | /* write values in clkstart0x0 and clkmulti 0x20 */ | 2552 | /* write values in clkstart0x0 and clkmulti 0x20 */ |
2550 | Data = 0x0; | 2553 | Data = 0x0; |
2551 | status = mos7840_set_reg_sync(serial->port[i], | 2554 | status = mos7840_set_reg_sync(serial->port[i], |
2552 | CLK_START_VALUE_REGISTER, Data); | 2555 | CLK_START_VALUE_REGISTER, Data); |
2553 | if (status < 0) { | 2556 | if (status < 0) { |
2554 | dbg("Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); | 2557 | dbg("Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); |
2555 | break; | 2558 | break; |
2556 | } else | 2559 | } else |
2557 | dbg("CLK_START_VALUE_REGISTER Writing success status%d\n", status); | 2560 | dbg("CLK_START_VALUE_REGISTER Writing success status%d\n", status); |
2558 | 2561 | ||
2559 | Data = 0x20; | 2562 | Data = 0x20; |
2560 | status = mos7840_set_reg_sync(serial->port[i], | 2563 | status = mos7840_set_reg_sync(serial->port[i], |
2561 | CLK_MULTI_REGISTER, Data); | 2564 | CLK_MULTI_REGISTER, Data); |
2562 | if (status < 0) { | 2565 | if (status < 0) { |
2563 | dbg("Writing CLK_MULTI_REGISTER failed status-0x%x\n", | 2566 | dbg("Writing CLK_MULTI_REGISTER failed status-0x%x\n", |
2564 | status); | 2567 | status); |
2565 | goto error; | 2568 | goto error; |
2566 | } else | 2569 | } else |
2567 | dbg("CLK_MULTI_REGISTER Writing success status%d\n", | 2570 | dbg("CLK_MULTI_REGISTER Writing success status%d\n", |
2568 | status); | 2571 | status); |
2569 | 2572 | ||
2570 | /* write value 0x0 to scratchpad register */ | 2573 | /* write value 0x0 to scratchpad register */ |
2571 | Data = 0x00; | 2574 | Data = 0x00; |
2572 | status = mos7840_set_uart_reg(serial->port[i], | 2575 | status = mos7840_set_uart_reg(serial->port[i], |
2573 | SCRATCH_PAD_REGISTER, Data); | 2576 | SCRATCH_PAD_REGISTER, Data); |
2574 | if (status < 0) { | 2577 | if (status < 0) { |
2575 | dbg("Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", | 2578 | dbg("Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", |
2576 | status); | 2579 | status); |
2577 | break; | 2580 | break; |
2578 | } else | 2581 | } else |
2579 | dbg("SCRATCH_PAD_REGISTER Writing success status%d\n", | 2582 | dbg("SCRATCH_PAD_REGISTER Writing success status%d\n", |
2580 | status); | 2583 | status); |
2581 | 2584 | ||
2582 | /* Zero Length flag register */ | 2585 | /* Zero Length flag register */ |
2583 | if ((mos7840_port->port_num != 1) | 2586 | if ((mos7840_port->port_num != 1) |
2584 | && (serial->num_ports == 2)) { | 2587 | && (serial->num_ports == 2)) { |
2585 | 2588 | ||
2586 | Data = 0xff; | 2589 | Data = 0xff; |
2587 | status = mos7840_set_reg_sync(serial->port[i], | 2590 | status = mos7840_set_reg_sync(serial->port[i], |
2588 | (__u16) (ZLP_REG1 + | 2591 | (__u16) (ZLP_REG1 + |
2589 | ((__u16)mos7840_port->port_num)), Data); | 2592 | ((__u16)mos7840_port->port_num)), Data); |
2590 | dbg("ZLIP offset%x\n", | 2593 | dbg("ZLIP offset%x\n", |
2591 | (__u16) (ZLP_REG1 + | 2594 | (__u16) (ZLP_REG1 + |
2592 | ((__u16) mos7840_port->port_num))); | 2595 | ((__u16) mos7840_port->port_num))); |
2593 | if (status < 0) { | 2596 | if (status < 0) { |
2594 | dbg("Writing ZLP_REG%d failed status-0x%x\n", | 2597 | dbg("Writing ZLP_REG%d failed status-0x%x\n", |
2595 | i + 2, status); | 2598 | i + 2, status); |
2596 | break; | 2599 | break; |
2597 | } else | 2600 | } else |
2598 | dbg("ZLP_REG%d Writing success status%d\n", | 2601 | dbg("ZLP_REG%d Writing success status%d\n", |
2599 | i + 2, status); | 2602 | i + 2, status); |
2600 | } else { | 2603 | } else { |
2601 | Data = 0xff; | 2604 | Data = 0xff; |
2602 | status = mos7840_set_reg_sync(serial->port[i], | 2605 | status = mos7840_set_reg_sync(serial->port[i], |
2603 | (__u16) (ZLP_REG1 + | 2606 | (__u16) (ZLP_REG1 + |
2604 | ((__u16)mos7840_port->port_num) - 0x1), Data); | 2607 | ((__u16)mos7840_port->port_num) - 0x1), Data); |
2605 | dbg("ZLIP offset%x\n", | 2608 | dbg("ZLIP offset%x\n", |
2606 | (__u16) (ZLP_REG1 + | 2609 | (__u16) (ZLP_REG1 + |
2607 | ((__u16) mos7840_port->port_num) - 0x1)); | 2610 | ((__u16) mos7840_port->port_num) - 0x1)); |
2608 | if (status < 0) { | 2611 | if (status < 0) { |
2609 | dbg("Writing ZLP_REG%d failed status-0x%x\n", | 2612 | dbg("Writing ZLP_REG%d failed status-0x%x\n", |
2610 | i + 1, status); | 2613 | i + 1, status); |
2611 | break; | 2614 | break; |
2612 | } else | 2615 | } else |
2613 | dbg("ZLP_REG%d Writing success status%d\n", | 2616 | dbg("ZLP_REG%d Writing success status%d\n", |
2614 | i + 1, status); | 2617 | i + 1, status); |
2615 | 2618 | ||
2616 | } | 2619 | } |
2617 | mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); | 2620 | mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); |
2618 | mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); | 2621 | mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); |
2619 | mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), | 2622 | mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), |
2620 | GFP_KERNEL); | 2623 | GFP_KERNEL); |
2621 | if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || | 2624 | if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || |
2622 | !mos7840_port->dr) { | 2625 | !mos7840_port->dr) { |
2623 | status = -ENOMEM; | 2626 | status = -ENOMEM; |
2624 | goto error; | 2627 | goto error; |
2625 | } | 2628 | } |
2626 | } | 2629 | } |
2627 | 2630 | ||
2628 | /* Zero Length flag enable */ | 2631 | /* Zero Length flag enable */ |
2629 | Data = 0x0f; | 2632 | Data = 0x0f; |
2630 | status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); | 2633 | status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); |
2631 | if (status < 0) { | 2634 | if (status < 0) { |
2632 | dbg("Writing ZLP_REG5 failed status-0x%x\n", status); | 2635 | dbg("Writing ZLP_REG5 failed status-0x%x\n", status); |
2633 | goto error; | 2636 | goto error; |
2634 | } else | 2637 | } else |
2635 | dbg("ZLP_REG5 Writing success status%d\n", status); | 2638 | dbg("ZLP_REG5 Writing success status%d\n", status); |
2636 | 2639 | ||
2637 | /* setting configuration feature to one */ | 2640 | /* setting configuration feature to one */ |
2638 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | 2641 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), |
2639 | (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5 * HZ); | 2642 | (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5 * HZ); |
2640 | return 0; | 2643 | return 0; |
2641 | error: | 2644 | error: |
2642 | for (/* nothing */; i >= 0; i--) { | 2645 | for (/* nothing */; i >= 0; i--) { |
2643 | mos7840_port = mos7840_get_port_private(serial->port[i]); | 2646 | mos7840_port = mos7840_get_port_private(serial->port[i]); |
2644 | 2647 | ||
2645 | kfree(mos7840_port->dr); | 2648 | kfree(mos7840_port->dr); |
2646 | kfree(mos7840_port->ctrl_buf); | 2649 | kfree(mos7840_port->ctrl_buf); |
2647 | usb_free_urb(mos7840_port->control_urb); | 2650 | usb_free_urb(mos7840_port->control_urb); |
2648 | kfree(mos7840_port); | 2651 | kfree(mos7840_port); |
2649 | serial->port[i] = NULL; | 2652 | serial->port[i] = NULL; |
2650 | } | 2653 | } |
2651 | return status; | 2654 | return status; |
2652 | } | 2655 | } |
2653 | 2656 | ||
2654 | /**************************************************************************** | 2657 | /**************************************************************************** |
2655 | * mos7840_shutdown | 2658 | * mos7840_shutdown |
2656 | * This function is called whenever the device is removed from the usb bus. | 2659 | * This function is called whenever the device is removed from the usb bus. |
2657 | ****************************************************************************/ | 2660 | ****************************************************************************/ |
2658 | 2661 | ||
2659 | static void mos7840_shutdown(struct usb_serial *serial) | 2662 | static void mos7840_shutdown(struct usb_serial *serial) |
2660 | { | 2663 | { |
2661 | int i; | 2664 | int i; |
2662 | unsigned long flags; | 2665 | unsigned long flags; |
2663 | struct moschip_port *mos7840_port; | 2666 | struct moschip_port *mos7840_port; |
2664 | dbg("%s \n", " shutdown :entering.........."); | 2667 | dbg("%s \n", " shutdown :entering.........."); |
2665 | 2668 | ||
2666 | if (!serial) { | 2669 | if (!serial) { |
2667 | dbg("%s", "Invalid Handler \n"); | 2670 | dbg("%s", "Invalid Handler \n"); |
2668 | return; | 2671 | return; |
2669 | } | 2672 | } |
2670 | 2673 | ||
2671 | /* check for the ports to be closed,close the ports and disconnect */ | 2674 | /* check for the ports to be closed,close the ports and disconnect */ |
2672 | 2675 | ||
2673 | /* free private structure allocated for serial port * | 2676 | /* free private structure allocated for serial port * |
2674 | * stop reads and writes on all ports */ | 2677 | * stop reads and writes on all ports */ |
2675 | 2678 | ||
2676 | for (i = 0; i < serial->num_ports; ++i) { | 2679 | for (i = 0; i < serial->num_ports; ++i) { |
2677 | mos7840_port = mos7840_get_port_private(serial->port[i]); | 2680 | mos7840_port = mos7840_get_port_private(serial->port[i]); |
2678 | spin_lock_irqsave(&mos7840_port->pool_lock, flags); | 2681 | spin_lock_irqsave(&mos7840_port->pool_lock, flags); |
2679 | mos7840_port->zombie = 1; | 2682 | mos7840_port->zombie = 1; |
2680 | spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); | 2683 | spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); |
2681 | usb_kill_urb(mos7840_port->control_urb); | 2684 | usb_kill_urb(mos7840_port->control_urb); |
2682 | kfree(mos7840_port->ctrl_buf); | 2685 | kfree(mos7840_port->ctrl_buf); |
2683 | kfree(mos7840_port->dr); | 2686 | kfree(mos7840_port->dr); |
2684 | kfree(mos7840_port); | 2687 | kfree(mos7840_port); |
2685 | mos7840_set_port_private(serial->port[i], NULL); | 2688 | mos7840_set_port_private(serial->port[i], NULL); |
2686 | } | 2689 | } |
2687 | 2690 | ||
2688 | dbg("%s\n", "Thank u :: "); | 2691 | dbg("%s\n", "Thank u :: "); |
2689 | 2692 | ||
2690 | } | 2693 | } |
2691 | 2694 | ||
2692 | static struct usb_driver io_driver = { | 2695 | static struct usb_driver io_driver = { |
2693 | .name = "mos7840", | 2696 | .name = "mos7840", |
2694 | .probe = usb_serial_probe, | 2697 | .probe = usb_serial_probe, |
2695 | .disconnect = usb_serial_disconnect, | 2698 | .disconnect = usb_serial_disconnect, |
2696 | .id_table = moschip_id_table_combined, | 2699 | .id_table = moschip_id_table_combined, |
2697 | .no_dynamic_id = 1, | 2700 | .no_dynamic_id = 1, |
2698 | }; | 2701 | }; |
2699 | 2702 | ||
2700 | static struct usb_serial_driver moschip7840_4port_device = { | 2703 | static struct usb_serial_driver moschip7840_4port_device = { |
2701 | .driver = { | 2704 | .driver = { |
2702 | .owner = THIS_MODULE, | 2705 | .owner = THIS_MODULE, |
2703 | .name = "mos7840", | 2706 | .name = "mos7840", |
2704 | }, | 2707 | }, |
2705 | .description = DRIVER_DESC, | 2708 | .description = DRIVER_DESC, |
2706 | .usb_driver = &io_driver, | 2709 | .usb_driver = &io_driver, |
2707 | .id_table = moschip_port_id_table, | 2710 | .id_table = moschip_port_id_table, |
2708 | .num_ports = 4, | 2711 | .num_ports = 4, |
2709 | .open = mos7840_open, | 2712 | .open = mos7840_open, |
2710 | .close = mos7840_close, | 2713 | .close = mos7840_close, |
2711 | .write = mos7840_write, | 2714 | .write = mos7840_write, |
2712 | .write_room = mos7840_write_room, | 2715 | .write_room = mos7840_write_room, |
2713 | .chars_in_buffer = mos7840_chars_in_buffer, | 2716 | .chars_in_buffer = mos7840_chars_in_buffer, |
2714 | .throttle = mos7840_throttle, | 2717 | .throttle = mos7840_throttle, |
2715 | .unthrottle = mos7840_unthrottle, | 2718 | .unthrottle = mos7840_unthrottle, |
2716 | .calc_num_ports = mos7840_calc_num_ports, | 2719 | .calc_num_ports = mos7840_calc_num_ports, |
2717 | #ifdef MCSSerialProbe | 2720 | #ifdef MCSSerialProbe |
2718 | .probe = mos7840_serial_probe, | 2721 | .probe = mos7840_serial_probe, |
2719 | #endif | 2722 | #endif |
2720 | .ioctl = mos7840_ioctl, | 2723 | .ioctl = mos7840_ioctl, |
2721 | .set_termios = mos7840_set_termios, | 2724 | .set_termios = mos7840_set_termios, |
2722 | .break_ctl = mos7840_break, | 2725 | .break_ctl = mos7840_break, |
2723 | .tiocmget = mos7840_tiocmget, | 2726 | .tiocmget = mos7840_tiocmget, |
2724 | .tiocmset = mos7840_tiocmset, | 2727 | .tiocmset = mos7840_tiocmset, |
2725 | .attach = mos7840_startup, | 2728 | .attach = mos7840_startup, |
2726 | .shutdown = mos7840_shutdown, | 2729 | .shutdown = mos7840_shutdown, |
2727 | .read_bulk_callback = mos7840_bulk_in_callback, | 2730 | .read_bulk_callback = mos7840_bulk_in_callback, |
2728 | .read_int_callback = mos7840_interrupt_callback, | 2731 | .read_int_callback = mos7840_interrupt_callback, |
2729 | }; | 2732 | }; |
2730 | 2733 | ||
2731 | /**************************************************************************** | 2734 | /**************************************************************************** |
2732 | * moschip7840_init | 2735 | * moschip7840_init |
2733 | * This is called by the module subsystem, or on startup to initialize us | 2736 | * This is called by the module subsystem, or on startup to initialize us |
2734 | ****************************************************************************/ | 2737 | ****************************************************************************/ |
2735 | static int __init moschip7840_init(void) | 2738 | static int __init moschip7840_init(void) |
2736 | { | 2739 | { |
2737 | int retval; | 2740 | int retval; |
2738 | 2741 | ||
2739 | dbg("%s \n", " mos7840_init :entering.........."); | 2742 | dbg("%s \n", " mos7840_init :entering.........."); |
2740 | 2743 | ||
2741 | /* Register with the usb serial */ | 2744 | /* Register with the usb serial */ |
2742 | retval = usb_serial_register(&moschip7840_4port_device); | 2745 | retval = usb_serial_register(&moschip7840_4port_device); |
2743 | 2746 | ||
2744 | if (retval) | 2747 | if (retval) |
2745 | goto failed_port_device_register; | 2748 | goto failed_port_device_register; |
2746 | 2749 | ||
2747 | dbg("%s\n", "Entring..."); | 2750 | dbg("%s\n", "Entring..."); |
2748 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | 2751 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" |
2749 | DRIVER_DESC "\n"); | 2752 | DRIVER_DESC "\n"); |
2750 | 2753 | ||
2751 | /* Register with the usb */ | 2754 | /* Register with the usb */ |
2752 | retval = usb_register(&io_driver); | 2755 | retval = usb_register(&io_driver); |
2753 | if (retval == 0) { | 2756 | if (retval == 0) { |
2754 | dbg("%s\n", "Leaving..."); | 2757 | dbg("%s\n", "Leaving..."); |
2755 | return 0; | 2758 | return 0; |
2756 | } | 2759 | } |
2757 | usb_serial_deregister(&moschip7840_4port_device); | 2760 | usb_serial_deregister(&moschip7840_4port_device); |
2758 | failed_port_device_register: | 2761 | failed_port_device_register: |
2759 | return retval; | 2762 | return retval; |
2760 | } | 2763 | } |
2761 | 2764 | ||
2762 | /**************************************************************************** | 2765 | /**************************************************************************** |
2763 | * moschip7840_exit | 2766 | * moschip7840_exit |
2764 | * Called when the driver is about to be unloaded. | 2767 | * Called when the driver is about to be unloaded. |
2765 | ****************************************************************************/ | 2768 | ****************************************************************************/ |
2766 | static void __exit moschip7840_exit(void) | 2769 | static void __exit moschip7840_exit(void) |
2767 | { | 2770 | { |
2768 | 2771 | ||
2769 | dbg("%s \n", " mos7840_exit :entering.........."); | 2772 | dbg("%s \n", " mos7840_exit :entering.........."); |
2770 | 2773 | ||
2771 | usb_deregister(&io_driver); | 2774 | usb_deregister(&io_driver); |
2772 | 2775 | ||
2773 | usb_serial_deregister(&moschip7840_4port_device); | 2776 | usb_serial_deregister(&moschip7840_4port_device); |
2774 | 2777 | ||
2775 | dbg("%s\n", "Entring..."); | 2778 | dbg("%s\n", "Entring..."); |
2776 | } | 2779 | } |
2777 | 2780 | ||
2778 | module_init(moschip7840_init); | 2781 | module_init(moschip7840_init); |
2779 | module_exit(moschip7840_exit); | 2782 | module_exit(moschip7840_exit); |
2780 | 2783 | ||
2781 | /* Module information */ | 2784 | /* Module information */ |
2782 | MODULE_DESCRIPTION(DRIVER_DESC); | 2785 | MODULE_DESCRIPTION(DRIVER_DESC); |
2783 | MODULE_LICENSE("GPL"); | 2786 | MODULE_LICENSE("GPL"); |
2784 | 2787 | ||
2785 | module_param(debug, bool, S_IRUGO | S_IWUSR); | 2788 | module_param(debug, bool, S_IRUGO | S_IWUSR); |
2786 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | 2789 | MODULE_PARM_DESC(debug, "Debug enabled or not"); |
2787 | 2790 |
drivers/usb/serial/usb-serial.c
1 | /* | 1 | /* |
2 | * USB Serial Converter driver | 2 | * USB Serial Converter driver |
3 | * | 3 | * |
4 | * Copyright (C) 1999 - 2005 Greg Kroah-Hartman (greg@kroah.com) | 4 | * Copyright (C) 1999 - 2005 Greg Kroah-Hartman (greg@kroah.com) |
5 | * Copyright (C) 2000 Peter Berger (pberger@brimson.com) | 5 | * Copyright (C) 2000 Peter Berger (pberger@brimson.com) |
6 | * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com) | 6 | * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com) |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License version | 9 | * modify it under the terms of the GNU General Public License version |
10 | * 2 as published by the Free Software Foundation. | 10 | * 2 as published by the Free Software Foundation. |
11 | * | 11 | * |
12 | * This driver was originally based on the ACM driver by Armin Fuerst (which was | 12 | * This driver was originally based on the ACM driver by Armin Fuerst (which was |
13 | * based on a driver by Brad Keryan) | 13 | * based on a driver by Brad Keryan) |
14 | * | 14 | * |
15 | * See Documentation/usb/usb-serial.txt for more information on using this | 15 | * See Documentation/usb/usb-serial.txt for more information on using this |
16 | * driver | 16 | * driver |
17 | * | 17 | * |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/errno.h> | 21 | #include <linux/errno.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/tty.h> | 24 | #include <linux/tty.h> |
25 | #include <linux/tty_driver.h> | 25 | #include <linux/tty_driver.h> |
26 | #include <linux/tty_flip.h> | 26 | #include <linux/tty_flip.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/moduleparam.h> | 28 | #include <linux/moduleparam.h> |
29 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
30 | #include <linux/mutex.h> | 30 | #include <linux/mutex.h> |
31 | #include <linux/list.h> | 31 | #include <linux/list.h> |
32 | #include <linux/uaccess.h> | 32 | #include <linux/uaccess.h> |
33 | #include <linux/usb.h> | 33 | #include <linux/usb.h> |
34 | #include <linux/usb/serial.h> | 34 | #include <linux/usb/serial.h> |
35 | #include "pl2303.h" | 35 | #include "pl2303.h" |
36 | 36 | ||
37 | /* | 37 | /* |
38 | * Version Information | 38 | * Version Information |
39 | */ | 39 | */ |
40 | #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/" | 40 | #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/" |
41 | #define DRIVER_DESC "USB Serial Driver core" | 41 | #define DRIVER_DESC "USB Serial Driver core" |
42 | 42 | ||
43 | static void port_free(struct usb_serial_port *port); | 43 | static void port_free(struct usb_serial_port *port); |
44 | 44 | ||
45 | /* Driver structure we register with the USB core */ | 45 | /* Driver structure we register with the USB core */ |
46 | static struct usb_driver usb_serial_driver = { | 46 | static struct usb_driver usb_serial_driver = { |
47 | .name = "usbserial", | 47 | .name = "usbserial", |
48 | .probe = usb_serial_probe, | 48 | .probe = usb_serial_probe, |
49 | .disconnect = usb_serial_disconnect, | 49 | .disconnect = usb_serial_disconnect, |
50 | .suspend = usb_serial_suspend, | 50 | .suspend = usb_serial_suspend, |
51 | .resume = usb_serial_resume, | 51 | .resume = usb_serial_resume, |
52 | .no_dynamic_id = 1, | 52 | .no_dynamic_id = 1, |
53 | }; | 53 | }; |
54 | 54 | ||
55 | /* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead | 55 | /* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead |
56 | the MODULE_DEVICE_TABLE declarations in each serial driver | 56 | the MODULE_DEVICE_TABLE declarations in each serial driver |
57 | cause the "hotplug" program to pull in whatever module is necessary | 57 | cause the "hotplug" program to pull in whatever module is necessary |
58 | via modprobe, and modprobe will load usbserial because the serial | 58 | via modprobe, and modprobe will load usbserial because the serial |
59 | drivers depend on it. | 59 | drivers depend on it. |
60 | */ | 60 | */ |
61 | 61 | ||
62 | static int debug; | 62 | static int debug; |
63 | /* initially all NULL */ | 63 | /* initially all NULL */ |
64 | static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; | 64 | static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; |
65 | static DEFINE_MUTEX(table_lock); | 65 | static DEFINE_MUTEX(table_lock); |
66 | static LIST_HEAD(usb_serial_driver_list); | 66 | static LIST_HEAD(usb_serial_driver_list); |
67 | 67 | ||
68 | struct usb_serial *usb_serial_get_by_index(unsigned index) | 68 | struct usb_serial *usb_serial_get_by_index(unsigned index) |
69 | { | 69 | { |
70 | struct usb_serial *serial; | 70 | struct usb_serial *serial; |
71 | 71 | ||
72 | mutex_lock(&table_lock); | 72 | mutex_lock(&table_lock); |
73 | serial = serial_table[index]; | 73 | serial = serial_table[index]; |
74 | 74 | ||
75 | if (serial) | 75 | if (serial) |
76 | kref_get(&serial->kref); | 76 | kref_get(&serial->kref); |
77 | mutex_unlock(&table_lock); | 77 | mutex_unlock(&table_lock); |
78 | return serial; | 78 | return serial; |
79 | } | 79 | } |
80 | 80 | ||
81 | static struct usb_serial *get_free_serial(struct usb_serial *serial, | 81 | static struct usb_serial *get_free_serial(struct usb_serial *serial, |
82 | int num_ports, unsigned int *minor) | 82 | int num_ports, unsigned int *minor) |
83 | { | 83 | { |
84 | unsigned int i, j; | 84 | unsigned int i, j; |
85 | int good_spot; | 85 | int good_spot; |
86 | 86 | ||
87 | dbg("%s %d", __func__, num_ports); | 87 | dbg("%s %d", __func__, num_ports); |
88 | 88 | ||
89 | *minor = 0; | 89 | *minor = 0; |
90 | mutex_lock(&table_lock); | 90 | mutex_lock(&table_lock); |
91 | for (i = 0; i < SERIAL_TTY_MINORS; ++i) { | 91 | for (i = 0; i < SERIAL_TTY_MINORS; ++i) { |
92 | if (serial_table[i]) | 92 | if (serial_table[i]) |
93 | continue; | 93 | continue; |
94 | 94 | ||
95 | good_spot = 1; | 95 | good_spot = 1; |
96 | for (j = 1; j <= num_ports-1; ++j) | 96 | for (j = 1; j <= num_ports-1; ++j) |
97 | if ((i+j >= SERIAL_TTY_MINORS) || (serial_table[i+j])) { | 97 | if ((i+j >= SERIAL_TTY_MINORS) || (serial_table[i+j])) { |
98 | good_spot = 0; | 98 | good_spot = 0; |
99 | i += j; | 99 | i += j; |
100 | break; | 100 | break; |
101 | } | 101 | } |
102 | if (good_spot == 0) | 102 | if (good_spot == 0) |
103 | continue; | 103 | continue; |
104 | 104 | ||
105 | *minor = i; | 105 | *minor = i; |
106 | j = 0; | 106 | j = 0; |
107 | dbg("%s - minor base = %d", __func__, *minor); | 107 | dbg("%s - minor base = %d", __func__, *minor); |
108 | for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) { | 108 | for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) { |
109 | serial_table[i] = serial; | 109 | serial_table[i] = serial; |
110 | serial->port[j++]->number = i; | 110 | serial->port[j++]->number = i; |
111 | } | 111 | } |
112 | mutex_unlock(&table_lock); | 112 | mutex_unlock(&table_lock); |
113 | return serial; | 113 | return serial; |
114 | } | 114 | } |
115 | mutex_unlock(&table_lock); | 115 | mutex_unlock(&table_lock); |
116 | return NULL; | 116 | return NULL; |
117 | } | 117 | } |
118 | 118 | ||
119 | static void return_serial(struct usb_serial *serial) | 119 | static void return_serial(struct usb_serial *serial) |
120 | { | 120 | { |
121 | int i; | 121 | int i; |
122 | 122 | ||
123 | dbg("%s", __func__); | 123 | dbg("%s", __func__); |
124 | 124 | ||
125 | for (i = 0; i < serial->num_ports; ++i) | 125 | for (i = 0; i < serial->num_ports; ++i) |
126 | serial_table[serial->minor + i] = NULL; | 126 | serial_table[serial->minor + i] = NULL; |
127 | } | 127 | } |
128 | 128 | ||
129 | static void destroy_serial(struct kref *kref) | 129 | static void destroy_serial(struct kref *kref) |
130 | { | 130 | { |
131 | struct usb_serial *serial; | 131 | struct usb_serial *serial; |
132 | struct usb_serial_port *port; | 132 | struct usb_serial_port *port; |
133 | int i; | 133 | int i; |
134 | 134 | ||
135 | serial = to_usb_serial(kref); | 135 | serial = to_usb_serial(kref); |
136 | 136 | ||
137 | dbg("%s - %s", __func__, serial->type->description); | 137 | dbg("%s - %s", __func__, serial->type->description); |
138 | 138 | ||
139 | serial->type->shutdown(serial); | 139 | serial->type->shutdown(serial); |
140 | 140 | ||
141 | /* return the minor range that this device had */ | 141 | /* return the minor range that this device had */ |
142 | if (serial->minor != SERIAL_TTY_NO_MINOR) | 142 | if (serial->minor != SERIAL_TTY_NO_MINOR) |
143 | return_serial(serial); | 143 | return_serial(serial); |
144 | 144 | ||
145 | for (i = 0; i < serial->num_ports; ++i) | 145 | for (i = 0; i < serial->num_ports; ++i) |
146 | serial->port[i]->port.count = 0; | 146 | serial->port[i]->port.count = 0; |
147 | 147 | ||
148 | /* the ports are cleaned up and released in port_release() */ | 148 | /* the ports are cleaned up and released in port_release() */ |
149 | for (i = 0; i < serial->num_ports; ++i) | 149 | for (i = 0; i < serial->num_ports; ++i) |
150 | if (serial->port[i]->dev.parent != NULL) { | 150 | if (serial->port[i]->dev.parent != NULL) { |
151 | device_unregister(&serial->port[i]->dev); | 151 | device_unregister(&serial->port[i]->dev); |
152 | serial->port[i] = NULL; | 152 | serial->port[i] = NULL; |
153 | } | 153 | } |
154 | 154 | ||
155 | /* If this is a "fake" port, we have to clean it up here, as it will | 155 | /* If this is a "fake" port, we have to clean it up here, as it will |
156 | * not get cleaned up in port_release() as it was never registered with | 156 | * not get cleaned up in port_release() as it was never registered with |
157 | * the driver core */ | 157 | * the driver core */ |
158 | if (serial->num_ports < serial->num_port_pointers) { | 158 | if (serial->num_ports < serial->num_port_pointers) { |
159 | for (i = serial->num_ports; | 159 | for (i = serial->num_ports; |
160 | i < serial->num_port_pointers; ++i) { | 160 | i < serial->num_port_pointers; ++i) { |
161 | port = serial->port[i]; | 161 | port = serial->port[i]; |
162 | if (!port) | 162 | if (!port) |
163 | continue; | 163 | continue; |
164 | port_free(port); | 164 | port_free(port); |
165 | } | 165 | } |
166 | } | 166 | } |
167 | 167 | ||
168 | usb_put_dev(serial->dev); | 168 | usb_put_dev(serial->dev); |
169 | 169 | ||
170 | /* free up any memory that we allocated */ | 170 | /* free up any memory that we allocated */ |
171 | kfree(serial); | 171 | kfree(serial); |
172 | } | 172 | } |
173 | 173 | ||
174 | void usb_serial_put(struct usb_serial *serial) | 174 | void usb_serial_put(struct usb_serial *serial) |
175 | { | 175 | { |
176 | mutex_lock(&table_lock); | 176 | mutex_lock(&table_lock); |
177 | kref_put(&serial->kref, destroy_serial); | 177 | kref_put(&serial->kref, destroy_serial); |
178 | mutex_unlock(&table_lock); | 178 | mutex_unlock(&table_lock); |
179 | } | 179 | } |
180 | 180 | ||
181 | /***************************************************************************** | 181 | /***************************************************************************** |
182 | * Driver tty interface functions | 182 | * Driver tty interface functions |
183 | *****************************************************************************/ | 183 | *****************************************************************************/ |
184 | static int serial_open (struct tty_struct *tty, struct file *filp) | 184 | static int serial_open (struct tty_struct *tty, struct file *filp) |
185 | { | 185 | { |
186 | struct usb_serial *serial; | 186 | struct usb_serial *serial; |
187 | struct usb_serial_port *port; | 187 | struct usb_serial_port *port; |
188 | unsigned int portNumber; | 188 | unsigned int portNumber; |
189 | int retval; | 189 | int retval; |
190 | 190 | ||
191 | dbg("%s", __func__); | 191 | dbg("%s", __func__); |
192 | 192 | ||
193 | /* get the serial object associated with this tty pointer */ | 193 | /* get the serial object associated with this tty pointer */ |
194 | serial = usb_serial_get_by_index(tty->index); | 194 | serial = usb_serial_get_by_index(tty->index); |
195 | if (!serial) { | 195 | if (!serial) { |
196 | tty->driver_data = NULL; | 196 | tty->driver_data = NULL; |
197 | return -ENODEV; | 197 | return -ENODEV; |
198 | } | 198 | } |
199 | 199 | ||
200 | portNumber = tty->index - serial->minor; | 200 | portNumber = tty->index - serial->minor; |
201 | port = serial->port[portNumber]; | 201 | port = serial->port[portNumber]; |
202 | if (!port) { | 202 | if (!port) { |
203 | retval = -ENODEV; | 203 | retval = -ENODEV; |
204 | goto bailout_kref_put; | 204 | goto bailout_kref_put; |
205 | } | 205 | } |
206 | 206 | ||
207 | if (mutex_lock_interruptible(&port->mutex)) { | 207 | if (mutex_lock_interruptible(&port->mutex)) { |
208 | retval = -ERESTARTSYS; | 208 | retval = -ERESTARTSYS; |
209 | goto bailout_kref_put; | 209 | goto bailout_kref_put; |
210 | } | 210 | } |
211 | 211 | ||
212 | ++port->port.count; | 212 | ++port->port.count; |
213 | 213 | ||
214 | /* set up our port structure making the tty driver | 214 | /* set up our port structure making the tty driver |
215 | * remember our port object, and us it */ | 215 | * remember our port object, and us it */ |
216 | tty->driver_data = port; | 216 | tty->driver_data = port; |
217 | tty_port_tty_set(&port->port, tty); | 217 | tty_port_tty_set(&port->port, tty); |
218 | 218 | ||
219 | if (port->port.count == 1) { | 219 | if (port->port.count == 1) { |
220 | 220 | ||
221 | /* lock this module before we call it | 221 | /* lock this module before we call it |
222 | * this may fail, which means we must bail out, | 222 | * this may fail, which means we must bail out, |
223 | * safe because we are called with BKL held */ | 223 | * safe because we are called with BKL held */ |
224 | if (!try_module_get(serial->type->driver.owner)) { | 224 | if (!try_module_get(serial->type->driver.owner)) { |
225 | retval = -ENODEV; | 225 | retval = -ENODEV; |
226 | goto bailout_mutex_unlock; | 226 | goto bailout_mutex_unlock; |
227 | } | 227 | } |
228 | 228 | ||
229 | retval = usb_autopm_get_interface(serial->interface); | 229 | retval = usb_autopm_get_interface(serial->interface); |
230 | if (retval) | 230 | if (retval) |
231 | goto bailout_module_put; | 231 | goto bailout_module_put; |
232 | /* only call the device specific open if this | 232 | /* only call the device specific open if this |
233 | * is the first time the port is opened */ | 233 | * is the first time the port is opened */ |
234 | retval = serial->type->open(tty, port, filp); | 234 | retval = serial->type->open(tty, port, filp); |
235 | if (retval) | 235 | if (retval) |
236 | goto bailout_interface_put; | 236 | goto bailout_interface_put; |
237 | } | 237 | } |
238 | 238 | ||
239 | mutex_unlock(&port->mutex); | 239 | mutex_unlock(&port->mutex); |
240 | return 0; | 240 | return 0; |
241 | 241 | ||
242 | bailout_interface_put: | 242 | bailout_interface_put: |
243 | usb_autopm_put_interface(serial->interface); | 243 | usb_autopm_put_interface(serial->interface); |
244 | bailout_module_put: | 244 | bailout_module_put: |
245 | module_put(serial->type->driver.owner); | 245 | module_put(serial->type->driver.owner); |
246 | bailout_mutex_unlock: | 246 | bailout_mutex_unlock: |
247 | port->port.count = 0; | 247 | port->port.count = 0; |
248 | tty->driver_data = NULL; | 248 | tty->driver_data = NULL; |
249 | tty_port_tty_set(&port->port, NULL); | 249 | tty_port_tty_set(&port->port, NULL); |
250 | mutex_unlock(&port->mutex); | 250 | mutex_unlock(&port->mutex); |
251 | bailout_kref_put: | 251 | bailout_kref_put: |
252 | usb_serial_put(serial); | 252 | usb_serial_put(serial); |
253 | return retval; | 253 | return retval; |
254 | } | 254 | } |
255 | 255 | ||
256 | static void serial_close(struct tty_struct *tty, struct file *filp) | 256 | static void serial_close(struct tty_struct *tty, struct file *filp) |
257 | { | 257 | { |
258 | struct usb_serial_port *port = tty->driver_data; | 258 | struct usb_serial_port *port = tty->driver_data; |
259 | 259 | ||
260 | if (!port) | 260 | if (!port) |
261 | return; | 261 | return; |
262 | 262 | ||
263 | dbg("%s - port %d", __func__, port->number); | 263 | dbg("%s - port %d", __func__, port->number); |
264 | 264 | ||
265 | mutex_lock(&port->mutex); | 265 | mutex_lock(&port->mutex); |
266 | 266 | ||
267 | if (port->port.count == 0) { | 267 | if (port->port.count == 0) { |
268 | mutex_unlock(&port->mutex); | 268 | mutex_unlock(&port->mutex); |
269 | return; | 269 | return; |
270 | } | 270 | } |
271 | 271 | ||
272 | if (port->port.count == 1) | 272 | if (port->port.count == 1) |
273 | /* only call the device specific close if this | 273 | /* only call the device specific close if this |
274 | * port is being closed by the last owner. Ensure we do | 274 | * port is being closed by the last owner. Ensure we do |
275 | * this before we drop the port count. The call is protected | 275 | * this before we drop the port count. The call is protected |
276 | * by the port mutex | 276 | * by the port mutex |
277 | */ | 277 | */ |
278 | port->serial->type->close(tty, port, filp); | 278 | port->serial->type->close(tty, port, filp); |
279 | 279 | ||
280 | if (port->port.count == (port->console ? 2 : 1)) { | 280 | if (port->port.count == (port->console ? 2 : 1)) { |
281 | struct tty_struct *tty = tty_port_tty_get(&port->port); | 281 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
282 | if (tty) { | 282 | if (tty) { |
283 | /* We must do this before we drop the port count to | 283 | /* We must do this before we drop the port count to |
284 | zero. */ | 284 | zero. */ |
285 | if (tty->driver_data) | 285 | if (tty->driver_data) |
286 | tty->driver_data = NULL; | 286 | tty->driver_data = NULL; |
287 | tty_port_tty_set(&port->port, NULL); | 287 | tty_port_tty_set(&port->port, NULL); |
288 | tty_kref_put(tty); | 288 | tty_kref_put(tty); |
289 | } | 289 | } |
290 | } | 290 | } |
291 | 291 | ||
292 | if (port->port.count == 1) { | 292 | if (port->port.count == 1) { |
293 | mutex_lock(&port->serial->disc_mutex); | 293 | mutex_lock(&port->serial->disc_mutex); |
294 | if (!port->serial->disconnected) | 294 | if (!port->serial->disconnected) |
295 | usb_autopm_put_interface(port->serial->interface); | 295 | usb_autopm_put_interface(port->serial->interface); |
296 | mutex_unlock(&port->serial->disc_mutex); | 296 | mutex_unlock(&port->serial->disc_mutex); |
297 | module_put(port->serial->type->driver.owner); | 297 | module_put(port->serial->type->driver.owner); |
298 | } | 298 | } |
299 | --port->port.count; | 299 | --port->port.count; |
300 | 300 | ||
301 | mutex_unlock(&port->mutex); | 301 | mutex_unlock(&port->mutex); |
302 | usb_serial_put(port->serial); | 302 | usb_serial_put(port->serial); |
303 | } | 303 | } |
304 | 304 | ||
305 | static int serial_write(struct tty_struct *tty, const unsigned char *buf, | 305 | static int serial_write(struct tty_struct *tty, const unsigned char *buf, |
306 | int count) | 306 | int count) |
307 | { | 307 | { |
308 | struct usb_serial_port *port = tty->driver_data; | 308 | struct usb_serial_port *port = tty->driver_data; |
309 | int retval = -ENODEV; | 309 | int retval = -ENODEV; |
310 | 310 | ||
311 | if (port->serial->dev->state == USB_STATE_NOTATTACHED) | 311 | if (port->serial->dev->state == USB_STATE_NOTATTACHED) |
312 | goto exit; | 312 | goto exit; |
313 | 313 | ||
314 | dbg("%s - port %d, %d byte(s)", __func__, port->number, count); | 314 | dbg("%s - port %d, %d byte(s)", __func__, port->number, count); |
315 | 315 | ||
316 | /* count is managed under the mutex lock for the tty so cannot | 316 | /* count is managed under the mutex lock for the tty so cannot |
317 | drop to zero until after the last close completes */ | 317 | drop to zero until after the last close completes */ |
318 | WARN_ON(!port->port.count); | 318 | WARN_ON(!port->port.count); |
319 | 319 | ||
320 | /* pass on to the driver specific version of this function */ | 320 | /* pass on to the driver specific version of this function */ |
321 | retval = port->serial->type->write(tty, port, buf, count); | 321 | retval = port->serial->type->write(tty, port, buf, count); |
322 | 322 | ||
323 | exit: | 323 | exit: |
324 | return retval; | 324 | return retval; |
325 | } | 325 | } |
326 | 326 | ||
327 | static int serial_write_room(struct tty_struct *tty) | 327 | static int serial_write_room(struct tty_struct *tty) |
328 | { | 328 | { |
329 | struct usb_serial_port *port = tty->driver_data; | 329 | struct usb_serial_port *port = tty->driver_data; |
330 | dbg("%s - port %d", __func__, port->number); | 330 | dbg("%s - port %d", __func__, port->number); |
331 | WARN_ON(!port->port.count); | 331 | WARN_ON(!port->port.count); |
332 | /* pass on to the driver specific version of this function */ | 332 | /* pass on to the driver specific version of this function */ |
333 | return port->serial->type->write_room(tty); | 333 | return port->serial->type->write_room(tty); |
334 | } | 334 | } |
335 | 335 | ||
336 | static int serial_chars_in_buffer(struct tty_struct *tty) | 336 | static int serial_chars_in_buffer(struct tty_struct *tty) |
337 | { | 337 | { |
338 | struct usb_serial_port *port = tty->driver_data; | 338 | struct usb_serial_port *port = tty->driver_data; |
339 | dbg("%s = port %d", __func__, port->number); | 339 | dbg("%s = port %d", __func__, port->number); |
340 | 340 | ||
341 | WARN_ON(!port->port.count); | 341 | WARN_ON(!port->port.count); |
342 | /* if the device was unplugged then any remaining characters | 342 | /* if the device was unplugged then any remaining characters |
343 | fell out of the connector ;) */ | 343 | fell out of the connector ;) */ |
344 | if (port->serial->disconnected) | 344 | if (port->serial->disconnected) |
345 | return 0; | 345 | return 0; |
346 | /* pass on to the driver specific version of this function */ | 346 | /* pass on to the driver specific version of this function */ |
347 | return port->serial->type->chars_in_buffer(tty); | 347 | return port->serial->type->chars_in_buffer(tty); |
348 | } | 348 | } |
349 | 349 | ||
350 | static void serial_throttle(struct tty_struct *tty) | 350 | static void serial_throttle(struct tty_struct *tty) |
351 | { | 351 | { |
352 | struct usb_serial_port *port = tty->driver_data; | 352 | struct usb_serial_port *port = tty->driver_data; |
353 | dbg("%s - port %d", __func__, port->number); | 353 | dbg("%s - port %d", __func__, port->number); |
354 | 354 | ||
355 | WARN_ON(!port->port.count); | 355 | WARN_ON(!port->port.count); |
356 | /* pass on to the driver specific version of this function */ | 356 | /* pass on to the driver specific version of this function */ |
357 | if (port->serial->type->throttle) | 357 | if (port->serial->type->throttle) |
358 | port->serial->type->throttle(tty); | 358 | port->serial->type->throttle(tty); |
359 | } | 359 | } |
360 | 360 | ||
361 | static void serial_unthrottle(struct tty_struct *tty) | 361 | static void serial_unthrottle(struct tty_struct *tty) |
362 | { | 362 | { |
363 | struct usb_serial_port *port = tty->driver_data; | 363 | struct usb_serial_port *port = tty->driver_data; |
364 | dbg("%s - port %d", __func__, port->number); | 364 | dbg("%s - port %d", __func__, port->number); |
365 | 365 | ||
366 | WARN_ON(!port->port.count); | 366 | WARN_ON(!port->port.count); |
367 | /* pass on to the driver specific version of this function */ | 367 | /* pass on to the driver specific version of this function */ |
368 | if (port->serial->type->unthrottle) | 368 | if (port->serial->type->unthrottle) |
369 | port->serial->type->unthrottle(tty); | 369 | port->serial->type->unthrottle(tty); |
370 | } | 370 | } |
371 | 371 | ||
372 | static int serial_ioctl(struct tty_struct *tty, struct file *file, | 372 | static int serial_ioctl(struct tty_struct *tty, struct file *file, |
373 | unsigned int cmd, unsigned long arg) | 373 | unsigned int cmd, unsigned long arg) |
374 | { | 374 | { |
375 | struct usb_serial_port *port = tty->driver_data; | 375 | struct usb_serial_port *port = tty->driver_data; |
376 | int retval = -ENODEV; | 376 | int retval = -ENODEV; |
377 | 377 | ||
378 | dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd); | 378 | dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd); |
379 | 379 | ||
380 | WARN_ON(!port->port.count); | 380 | WARN_ON(!port->port.count); |
381 | 381 | ||
382 | /* pass on to the driver specific version of this function | 382 | /* pass on to the driver specific version of this function |
383 | if it is available */ | 383 | if it is available */ |
384 | if (port->serial->type->ioctl) { | 384 | if (port->serial->type->ioctl) { |
385 | lock_kernel(); | ||
386 | retval = port->serial->type->ioctl(tty, file, cmd, arg); | 385 | retval = port->serial->type->ioctl(tty, file, cmd, arg); |
387 | unlock_kernel(); | ||
388 | } else | 386 | } else |
389 | retval = -ENOIOCTLCMD; | 387 | retval = -ENOIOCTLCMD; |
390 | return retval; | 388 | return retval; |
391 | } | 389 | } |
392 | 390 | ||
393 | static void serial_set_termios(struct tty_struct *tty, struct ktermios *old) | 391 | static void serial_set_termios(struct tty_struct *tty, struct ktermios *old) |
394 | { | 392 | { |
395 | struct usb_serial_port *port = tty->driver_data; | 393 | struct usb_serial_port *port = tty->driver_data; |
396 | dbg("%s - port %d", __func__, port->number); | 394 | dbg("%s - port %d", __func__, port->number); |
397 | 395 | ||
398 | WARN_ON(!port->port.count); | 396 | WARN_ON(!port->port.count); |
399 | /* pass on to the driver specific version of this function | 397 | /* pass on to the driver specific version of this function |
400 | if it is available */ | 398 | if it is available */ |
401 | if (port->serial->type->set_termios) | 399 | if (port->serial->type->set_termios) |
402 | port->serial->type->set_termios(tty, port, old); | 400 | port->serial->type->set_termios(tty, port, old); |
403 | else | 401 | else |
404 | tty_termios_copy_hw(tty->termios, old); | 402 | tty_termios_copy_hw(tty->termios, old); |
405 | } | 403 | } |
406 | 404 | ||
407 | static int serial_break(struct tty_struct *tty, int break_state) | 405 | static int serial_break(struct tty_struct *tty, int break_state) |
408 | { | 406 | { |
409 | struct usb_serial_port *port = tty->driver_data; | 407 | struct usb_serial_port *port = tty->driver_data; |
410 | 408 | ||
411 | dbg("%s - port %d", __func__, port->number); | 409 | dbg("%s - port %d", __func__, port->number); |
412 | 410 | ||
413 | WARN_ON(!port->port.count); | 411 | WARN_ON(!port->port.count); |
414 | /* pass on to the driver specific version of this function | 412 | /* pass on to the driver specific version of this function |
415 | if it is available */ | 413 | if it is available */ |
416 | if (port->serial->type->break_ctl) { | 414 | if (port->serial->type->break_ctl) |
417 | lock_kernel(); | ||
418 | port->serial->type->break_ctl(tty, break_state); | 415 | port->serial->type->break_ctl(tty, break_state); |
419 | unlock_kernel(); | ||
420 | } | ||
421 | return 0; | 416 | return 0; |
422 | } | 417 | } |
423 | 418 | ||
424 | static int serial_read_proc(char *page, char **start, off_t off, int count, | 419 | static int serial_read_proc(char *page, char **start, off_t off, int count, |
425 | int *eof, void *data) | 420 | int *eof, void *data) |
426 | { | 421 | { |
427 | struct usb_serial *serial; | 422 | struct usb_serial *serial; |
428 | int length = 0; | 423 | int length = 0; |
429 | int i; | 424 | int i; |
430 | off_t begin = 0; | 425 | off_t begin = 0; |
431 | char tmp[40]; | 426 | char tmp[40]; |
432 | 427 | ||
433 | dbg("%s", __func__); | 428 | dbg("%s", __func__); |
434 | length += sprintf(page, "usbserinfo:1.0 driver:2.0\n"); | 429 | length += sprintf(page, "usbserinfo:1.0 driver:2.0\n"); |
435 | for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) { | 430 | for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) { |
436 | serial = usb_serial_get_by_index(i); | 431 | serial = usb_serial_get_by_index(i); |
437 | if (serial == NULL) | 432 | if (serial == NULL) |
438 | continue; | 433 | continue; |
439 | 434 | ||
440 | length += sprintf(page+length, "%d:", i); | 435 | length += sprintf(page+length, "%d:", i); |
441 | if (serial->type->driver.owner) | 436 | if (serial->type->driver.owner) |
442 | length += sprintf(page+length, " module:%s", | 437 | length += sprintf(page+length, " module:%s", |
443 | module_name(serial->type->driver.owner)); | 438 | module_name(serial->type->driver.owner)); |
444 | length += sprintf(page+length, " name:\"%s\"", | 439 | length += sprintf(page+length, " name:\"%s\"", |
445 | serial->type->description); | 440 | serial->type->description); |
446 | length += sprintf(page+length, " vendor:%04x product:%04x", | 441 | length += sprintf(page+length, " vendor:%04x product:%04x", |
447 | le16_to_cpu(serial->dev->descriptor.idVendor), | 442 | le16_to_cpu(serial->dev->descriptor.idVendor), |
448 | le16_to_cpu(serial->dev->descriptor.idProduct)); | 443 | le16_to_cpu(serial->dev->descriptor.idProduct)); |
449 | length += sprintf(page+length, " num_ports:%d", | 444 | length += sprintf(page+length, " num_ports:%d", |
450 | serial->num_ports); | 445 | serial->num_ports); |
451 | length += sprintf(page+length, " port:%d", | 446 | length += sprintf(page+length, " port:%d", |
452 | i - serial->minor + 1); | 447 | i - serial->minor + 1); |
453 | usb_make_path(serial->dev, tmp, sizeof(tmp)); | 448 | usb_make_path(serial->dev, tmp, sizeof(tmp)); |
454 | length += sprintf(page+length, " path:%s", tmp); | 449 | length += sprintf(page+length, " path:%s", tmp); |
455 | 450 | ||
456 | length += sprintf(page+length, "\n"); | 451 | length += sprintf(page+length, "\n"); |
457 | if ((length + begin) > (off + count)) { | 452 | if ((length + begin) > (off + count)) { |
458 | usb_serial_put(serial); | 453 | usb_serial_put(serial); |
459 | goto done; | 454 | goto done; |
460 | } | 455 | } |
461 | if ((length + begin) < off) { | 456 | if ((length + begin) < off) { |
462 | begin += length; | 457 | begin += length; |
463 | length = 0; | 458 | length = 0; |
464 | } | 459 | } |
465 | usb_serial_put(serial); | 460 | usb_serial_put(serial); |
466 | } | 461 | } |
467 | *eof = 1; | 462 | *eof = 1; |
468 | done: | 463 | done: |
469 | if (off >= (length + begin)) | 464 | if (off >= (length + begin)) |
470 | return 0; | 465 | return 0; |
471 | *start = page + (off-begin); | 466 | *start = page + (off-begin); |
472 | return (count < begin+length-off) ? count : begin+length-off; | 467 | return (count < begin+length-off) ? count : begin+length-off; |
473 | } | 468 | } |
474 | 469 | ||
475 | static int serial_tiocmget(struct tty_struct *tty, struct file *file) | 470 | static int serial_tiocmget(struct tty_struct *tty, struct file *file) |
476 | { | 471 | { |
477 | struct usb_serial_port *port = tty->driver_data; | 472 | struct usb_serial_port *port = tty->driver_data; |
478 | 473 | ||
479 | dbg("%s - port %d", __func__, port->number); | 474 | dbg("%s - port %d", __func__, port->number); |
480 | 475 | ||
481 | WARN_ON(!port->port.count); | 476 | WARN_ON(!port->port.count); |
482 | if (port->serial->type->tiocmget) | 477 | if (port->serial->type->tiocmget) |
483 | return port->serial->type->tiocmget(tty, file); | 478 | return port->serial->type->tiocmget(tty, file); |
484 | return -EINVAL; | 479 | return -EINVAL; |
485 | } | 480 | } |
486 | 481 | ||
487 | static int serial_tiocmset(struct tty_struct *tty, struct file *file, | 482 | static int serial_tiocmset(struct tty_struct *tty, struct file *file, |
488 | unsigned int set, unsigned int clear) | 483 | unsigned int set, unsigned int clear) |
489 | { | 484 | { |
490 | struct usb_serial_port *port = tty->driver_data; | 485 | struct usb_serial_port *port = tty->driver_data; |
491 | 486 | ||
492 | dbg("%s - port %d", __func__, port->number); | 487 | dbg("%s - port %d", __func__, port->number); |
493 | 488 | ||
494 | WARN_ON(!port->port.count); | 489 | WARN_ON(!port->port.count); |
495 | if (port->serial->type->tiocmset) | 490 | if (port->serial->type->tiocmset) |
496 | return port->serial->type->tiocmset(tty, file, set, clear); | 491 | return port->serial->type->tiocmset(tty, file, set, clear); |
497 | return -EINVAL; | 492 | return -EINVAL; |
498 | } | 493 | } |
499 | 494 | ||
500 | /* | 495 | /* |
501 | * We would be calling tty_wakeup here, but unfortunately some line | 496 | * We would be calling tty_wakeup here, but unfortunately some line |
502 | * disciplines have an annoying habit of calling tty->write from | 497 | * disciplines have an annoying habit of calling tty->write from |
503 | * the write wakeup callback (e.g. n_hdlc.c). | 498 | * the write wakeup callback (e.g. n_hdlc.c). |
504 | */ | 499 | */ |
505 | void usb_serial_port_softint(struct usb_serial_port *port) | 500 | void usb_serial_port_softint(struct usb_serial_port *port) |
506 | { | 501 | { |
507 | schedule_work(&port->work); | 502 | schedule_work(&port->work); |
508 | } | 503 | } |
509 | EXPORT_SYMBOL_GPL(usb_serial_port_softint); | 504 | EXPORT_SYMBOL_GPL(usb_serial_port_softint); |
510 | 505 | ||
511 | static void usb_serial_port_work(struct work_struct *work) | 506 | static void usb_serial_port_work(struct work_struct *work) |
512 | { | 507 | { |
513 | struct usb_serial_port *port = | 508 | struct usb_serial_port *port = |
514 | container_of(work, struct usb_serial_port, work); | 509 | container_of(work, struct usb_serial_port, work); |
515 | struct tty_struct *tty; | 510 | struct tty_struct *tty; |
516 | 511 | ||
517 | dbg("%s - port %d", __func__, port->number); | 512 | dbg("%s - port %d", __func__, port->number); |
518 | 513 | ||
519 | if (!port) | 514 | if (!port) |
520 | return; | 515 | return; |
521 | 516 | ||
522 | tty = tty_port_tty_get(&port->port); | 517 | tty = tty_port_tty_get(&port->port); |
523 | if (!tty) | 518 | if (!tty) |
524 | return; | 519 | return; |
525 | 520 | ||
526 | tty_wakeup(tty); | 521 | tty_wakeup(tty); |
527 | tty_kref_put(tty); | 522 | tty_kref_put(tty); |
528 | } | 523 | } |
529 | 524 | ||
530 | static void port_release(struct device *dev) | 525 | static void port_release(struct device *dev) |
531 | { | 526 | { |
532 | struct usb_serial_port *port = to_usb_serial_port(dev); | 527 | struct usb_serial_port *port = to_usb_serial_port(dev); |
533 | 528 | ||
534 | dbg ("%s - %s", __func__, dev_name(dev)); | 529 | dbg ("%s - %s", __func__, dev_name(dev)); |
535 | port_free(port); | 530 | port_free(port); |
536 | } | 531 | } |
537 | 532 | ||
538 | static void kill_traffic(struct usb_serial_port *port) | 533 | static void kill_traffic(struct usb_serial_port *port) |
539 | { | 534 | { |
540 | usb_kill_urb(port->read_urb); | 535 | usb_kill_urb(port->read_urb); |
541 | usb_kill_urb(port->write_urb); | 536 | usb_kill_urb(port->write_urb); |
542 | /* | 537 | /* |
543 | * This is tricky. | 538 | * This is tricky. |
544 | * Some drivers submit the read_urb in the | 539 | * Some drivers submit the read_urb in the |
545 | * handler for the write_urb or vice versa | 540 | * handler for the write_urb or vice versa |
546 | * this order determines the order in which | 541 | * this order determines the order in which |
547 | * usb_kill_urb() must be used to reliably | 542 | * usb_kill_urb() must be used to reliably |
548 | * kill the URBs. As it is unknown here, | 543 | * kill the URBs. As it is unknown here, |
549 | * both orders must be used in turn. | 544 | * both orders must be used in turn. |
550 | * The call below is not redundant. | 545 | * The call below is not redundant. |
551 | */ | 546 | */ |
552 | usb_kill_urb(port->read_urb); | 547 | usb_kill_urb(port->read_urb); |
553 | usb_kill_urb(port->interrupt_in_urb); | 548 | usb_kill_urb(port->interrupt_in_urb); |
554 | usb_kill_urb(port->interrupt_out_urb); | 549 | usb_kill_urb(port->interrupt_out_urb); |
555 | } | 550 | } |
556 | 551 | ||
557 | static void port_free(struct usb_serial_port *port) | 552 | static void port_free(struct usb_serial_port *port) |
558 | { | 553 | { |
559 | kill_traffic(port); | 554 | kill_traffic(port); |
560 | usb_free_urb(port->read_urb); | 555 | usb_free_urb(port->read_urb); |
561 | usb_free_urb(port->write_urb); | 556 | usb_free_urb(port->write_urb); |
562 | usb_free_urb(port->interrupt_in_urb); | 557 | usb_free_urb(port->interrupt_in_urb); |
563 | usb_free_urb(port->interrupt_out_urb); | 558 | usb_free_urb(port->interrupt_out_urb); |
564 | kfree(port->bulk_in_buffer); | 559 | kfree(port->bulk_in_buffer); |
565 | kfree(port->bulk_out_buffer); | 560 | kfree(port->bulk_out_buffer); |
566 | kfree(port->interrupt_in_buffer); | 561 | kfree(port->interrupt_in_buffer); |
567 | kfree(port->interrupt_out_buffer); | 562 | kfree(port->interrupt_out_buffer); |
568 | flush_scheduled_work(); /* port->work */ | 563 | flush_scheduled_work(); /* port->work */ |
569 | kfree(port); | 564 | kfree(port); |
570 | } | 565 | } |
571 | 566 | ||
572 | static struct usb_serial *create_serial(struct usb_device *dev, | 567 | static struct usb_serial *create_serial(struct usb_device *dev, |
573 | struct usb_interface *interface, | 568 | struct usb_interface *interface, |
574 | struct usb_serial_driver *driver) | 569 | struct usb_serial_driver *driver) |
575 | { | 570 | { |
576 | struct usb_serial *serial; | 571 | struct usb_serial *serial; |
577 | 572 | ||
578 | serial = kzalloc(sizeof(*serial), GFP_KERNEL); | 573 | serial = kzalloc(sizeof(*serial), GFP_KERNEL); |
579 | if (!serial) { | 574 | if (!serial) { |
580 | dev_err(&dev->dev, "%s - out of memory\n", __func__); | 575 | dev_err(&dev->dev, "%s - out of memory\n", __func__); |
581 | return NULL; | 576 | return NULL; |
582 | } | 577 | } |
583 | serial->dev = usb_get_dev(dev); | 578 | serial->dev = usb_get_dev(dev); |
584 | serial->type = driver; | 579 | serial->type = driver; |
585 | serial->interface = interface; | 580 | serial->interface = interface; |
586 | kref_init(&serial->kref); | 581 | kref_init(&serial->kref); |
587 | mutex_init(&serial->disc_mutex); | 582 | mutex_init(&serial->disc_mutex); |
588 | serial->minor = SERIAL_TTY_NO_MINOR; | 583 | serial->minor = SERIAL_TTY_NO_MINOR; |
589 | 584 | ||
590 | return serial; | 585 | return serial; |
591 | } | 586 | } |
592 | 587 | ||
593 | static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf, | 588 | static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf, |
594 | struct usb_serial_driver *drv) | 589 | struct usb_serial_driver *drv) |
595 | { | 590 | { |
596 | struct usb_dynid *dynid; | 591 | struct usb_dynid *dynid; |
597 | 592 | ||
598 | spin_lock(&drv->dynids.lock); | 593 | spin_lock(&drv->dynids.lock); |
599 | list_for_each_entry(dynid, &drv->dynids.list, node) { | 594 | list_for_each_entry(dynid, &drv->dynids.list, node) { |
600 | if (usb_match_one_id(intf, &dynid->id)) { | 595 | if (usb_match_one_id(intf, &dynid->id)) { |
601 | spin_unlock(&drv->dynids.lock); | 596 | spin_unlock(&drv->dynids.lock); |
602 | return &dynid->id; | 597 | return &dynid->id; |
603 | } | 598 | } |
604 | } | 599 | } |
605 | spin_unlock(&drv->dynids.lock); | 600 | spin_unlock(&drv->dynids.lock); |
606 | return NULL; | 601 | return NULL; |
607 | } | 602 | } |
608 | 603 | ||
609 | static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv, | 604 | static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv, |
610 | struct usb_interface *intf) | 605 | struct usb_interface *intf) |
611 | { | 606 | { |
612 | const struct usb_device_id *id; | 607 | const struct usb_device_id *id; |
613 | 608 | ||
614 | id = usb_match_id(intf, drv->id_table); | 609 | id = usb_match_id(intf, drv->id_table); |
615 | if (id) { | 610 | if (id) { |
616 | dbg("static descriptor matches"); | 611 | dbg("static descriptor matches"); |
617 | goto exit; | 612 | goto exit; |
618 | } | 613 | } |
619 | id = match_dynamic_id(intf, drv); | 614 | id = match_dynamic_id(intf, drv); |
620 | if (id) | 615 | if (id) |
621 | dbg("dynamic descriptor matches"); | 616 | dbg("dynamic descriptor matches"); |
622 | exit: | 617 | exit: |
623 | return id; | 618 | return id; |
624 | } | 619 | } |
625 | 620 | ||
626 | static struct usb_serial_driver *search_serial_device( | 621 | static struct usb_serial_driver *search_serial_device( |
627 | struct usb_interface *iface) | 622 | struct usb_interface *iface) |
628 | { | 623 | { |
629 | const struct usb_device_id *id; | 624 | const struct usb_device_id *id; |
630 | struct usb_serial_driver *drv; | 625 | struct usb_serial_driver *drv; |
631 | 626 | ||
632 | /* Check if the usb id matches a known device */ | 627 | /* Check if the usb id matches a known device */ |
633 | list_for_each_entry(drv, &usb_serial_driver_list, driver_list) { | 628 | list_for_each_entry(drv, &usb_serial_driver_list, driver_list) { |
634 | id = get_iface_id(drv, iface); | 629 | id = get_iface_id(drv, iface); |
635 | if (id) | 630 | if (id) |
636 | return drv; | 631 | return drv; |
637 | } | 632 | } |
638 | 633 | ||
639 | return NULL; | 634 | return NULL; |
640 | } | 635 | } |
641 | 636 | ||
642 | int usb_serial_probe(struct usb_interface *interface, | 637 | int usb_serial_probe(struct usb_interface *interface, |
643 | const struct usb_device_id *id) | 638 | const struct usb_device_id *id) |
644 | { | 639 | { |
645 | struct usb_device *dev = interface_to_usbdev(interface); | 640 | struct usb_device *dev = interface_to_usbdev(interface); |
646 | struct usb_serial *serial = NULL; | 641 | struct usb_serial *serial = NULL; |
647 | struct usb_serial_port *port; | 642 | struct usb_serial_port *port; |
648 | struct usb_host_interface *iface_desc; | 643 | struct usb_host_interface *iface_desc; |
649 | struct usb_endpoint_descriptor *endpoint; | 644 | struct usb_endpoint_descriptor *endpoint; |
650 | struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS]; | 645 | struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS]; |
651 | struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS]; | 646 | struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS]; |
652 | struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS]; | 647 | struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS]; |
653 | struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS]; | 648 | struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS]; |
654 | struct usb_serial_driver *type = NULL; | 649 | struct usb_serial_driver *type = NULL; |
655 | int retval; | 650 | int retval; |
656 | unsigned int minor; | 651 | unsigned int minor; |
657 | int buffer_size; | 652 | int buffer_size; |
658 | int i; | 653 | int i; |
659 | int num_interrupt_in = 0; | 654 | int num_interrupt_in = 0; |
660 | int num_interrupt_out = 0; | 655 | int num_interrupt_out = 0; |
661 | int num_bulk_in = 0; | 656 | int num_bulk_in = 0; |
662 | int num_bulk_out = 0; | 657 | int num_bulk_out = 0; |
663 | int num_ports = 0; | 658 | int num_ports = 0; |
664 | int max_endpoints; | 659 | int max_endpoints; |
665 | 660 | ||
666 | lock_kernel(); /* guard against unloading a serial driver module */ | 661 | lock_kernel(); /* guard against unloading a serial driver module */ |
667 | type = search_serial_device(interface); | 662 | type = search_serial_device(interface); |
668 | if (!type) { | 663 | if (!type) { |
669 | unlock_kernel(); | 664 | unlock_kernel(); |
670 | dbg("none matched"); | 665 | dbg("none matched"); |
671 | return -ENODEV; | 666 | return -ENODEV; |
672 | } | 667 | } |
673 | 668 | ||
674 | serial = create_serial(dev, interface, type); | 669 | serial = create_serial(dev, interface, type); |
675 | if (!serial) { | 670 | if (!serial) { |
676 | unlock_kernel(); | 671 | unlock_kernel(); |
677 | dev_err(&interface->dev, "%s - out of memory\n", __func__); | 672 | dev_err(&interface->dev, "%s - out of memory\n", __func__); |
678 | return -ENOMEM; | 673 | return -ENOMEM; |
679 | } | 674 | } |
680 | 675 | ||
681 | /* if this device type has a probe function, call it */ | 676 | /* if this device type has a probe function, call it */ |
682 | if (type->probe) { | 677 | if (type->probe) { |
683 | const struct usb_device_id *id; | 678 | const struct usb_device_id *id; |
684 | 679 | ||
685 | if (!try_module_get(type->driver.owner)) { | 680 | if (!try_module_get(type->driver.owner)) { |
686 | unlock_kernel(); | 681 | unlock_kernel(); |
687 | dev_err(&interface->dev, | 682 | dev_err(&interface->dev, |
688 | "module get failed, exiting\n"); | 683 | "module get failed, exiting\n"); |
689 | kfree(serial); | 684 | kfree(serial); |
690 | return -EIO; | 685 | return -EIO; |
691 | } | 686 | } |
692 | 687 | ||
693 | id = get_iface_id(type, interface); | 688 | id = get_iface_id(type, interface); |
694 | retval = type->probe(serial, id); | 689 | retval = type->probe(serial, id); |
695 | module_put(type->driver.owner); | 690 | module_put(type->driver.owner); |
696 | 691 | ||
697 | if (retval) { | 692 | if (retval) { |
698 | unlock_kernel(); | 693 | unlock_kernel(); |
699 | dbg("sub driver rejected device"); | 694 | dbg("sub driver rejected device"); |
700 | kfree(serial); | 695 | kfree(serial); |
701 | return retval; | 696 | return retval; |
702 | } | 697 | } |
703 | } | 698 | } |
704 | 699 | ||
705 | /* descriptor matches, let's find the endpoints needed */ | 700 | /* descriptor matches, let's find the endpoints needed */ |
706 | /* check out the endpoints */ | 701 | /* check out the endpoints */ |
707 | iface_desc = interface->cur_altsetting; | 702 | iface_desc = interface->cur_altsetting; |
708 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | 703 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { |
709 | endpoint = &iface_desc->endpoint[i].desc; | 704 | endpoint = &iface_desc->endpoint[i].desc; |
710 | 705 | ||
711 | if (usb_endpoint_is_bulk_in(endpoint)) { | 706 | if (usb_endpoint_is_bulk_in(endpoint)) { |
712 | /* we found a bulk in endpoint */ | 707 | /* we found a bulk in endpoint */ |
713 | dbg("found bulk in on endpoint %d", i); | 708 | dbg("found bulk in on endpoint %d", i); |
714 | bulk_in_endpoint[num_bulk_in] = endpoint; | 709 | bulk_in_endpoint[num_bulk_in] = endpoint; |
715 | ++num_bulk_in; | 710 | ++num_bulk_in; |
716 | } | 711 | } |
717 | 712 | ||
718 | if (usb_endpoint_is_bulk_out(endpoint)) { | 713 | if (usb_endpoint_is_bulk_out(endpoint)) { |
719 | /* we found a bulk out endpoint */ | 714 | /* we found a bulk out endpoint */ |
720 | dbg("found bulk out on endpoint %d", i); | 715 | dbg("found bulk out on endpoint %d", i); |
721 | bulk_out_endpoint[num_bulk_out] = endpoint; | 716 | bulk_out_endpoint[num_bulk_out] = endpoint; |
722 | ++num_bulk_out; | 717 | ++num_bulk_out; |
723 | } | 718 | } |
724 | 719 | ||
725 | if (usb_endpoint_is_int_in(endpoint)) { | 720 | if (usb_endpoint_is_int_in(endpoint)) { |
726 | /* we found a interrupt in endpoint */ | 721 | /* we found a interrupt in endpoint */ |
727 | dbg("found interrupt in on endpoint %d", i); | 722 | dbg("found interrupt in on endpoint %d", i); |
728 | interrupt_in_endpoint[num_interrupt_in] = endpoint; | 723 | interrupt_in_endpoint[num_interrupt_in] = endpoint; |
729 | ++num_interrupt_in; | 724 | ++num_interrupt_in; |
730 | } | 725 | } |
731 | 726 | ||
732 | if (usb_endpoint_is_int_out(endpoint)) { | 727 | if (usb_endpoint_is_int_out(endpoint)) { |
733 | /* we found an interrupt out endpoint */ | 728 | /* we found an interrupt out endpoint */ |
734 | dbg("found interrupt out on endpoint %d", i); | 729 | dbg("found interrupt out on endpoint %d", i); |
735 | interrupt_out_endpoint[num_interrupt_out] = endpoint; | 730 | interrupt_out_endpoint[num_interrupt_out] = endpoint; |
736 | ++num_interrupt_out; | 731 | ++num_interrupt_out; |
737 | } | 732 | } |
738 | } | 733 | } |
739 | 734 | ||
740 | #if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE) | 735 | #if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE) |
741 | /* BEGIN HORRIBLE HACK FOR PL2303 */ | 736 | /* BEGIN HORRIBLE HACK FOR PL2303 */ |
742 | /* this is needed due to the looney way its endpoints are set up */ | 737 | /* this is needed due to the looney way its endpoints are set up */ |
743 | if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) && | 738 | if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) && |
744 | (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) || | 739 | (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) || |
745 | ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) && | 740 | ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) && |
746 | (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) || | 741 | (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) || |
747 | ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) && | 742 | ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) && |
748 | (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) || | 743 | (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) || |
749 | ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) && | 744 | ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) && |
750 | (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) { | 745 | (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) { |
751 | if (interface != dev->actconfig->interface[0]) { | 746 | if (interface != dev->actconfig->interface[0]) { |
752 | /* check out the endpoints of the other interface*/ | 747 | /* check out the endpoints of the other interface*/ |
753 | iface_desc = dev->actconfig->interface[0]->cur_altsetting; | 748 | iface_desc = dev->actconfig->interface[0]->cur_altsetting; |
754 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | 749 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { |
755 | endpoint = &iface_desc->endpoint[i].desc; | 750 | endpoint = &iface_desc->endpoint[i].desc; |
756 | if (usb_endpoint_is_int_in(endpoint)) { | 751 | if (usb_endpoint_is_int_in(endpoint)) { |
757 | /* we found a interrupt in endpoint */ | 752 | /* we found a interrupt in endpoint */ |
758 | dbg("found interrupt in for Prolific device on separate interface"); | 753 | dbg("found interrupt in for Prolific device on separate interface"); |
759 | interrupt_in_endpoint[num_interrupt_in] = endpoint; | 754 | interrupt_in_endpoint[num_interrupt_in] = endpoint; |
760 | ++num_interrupt_in; | 755 | ++num_interrupt_in; |
761 | } | 756 | } |
762 | } | 757 | } |
763 | } | 758 | } |
764 | 759 | ||
765 | /* Now make sure the PL-2303 is configured correctly. | 760 | /* Now make sure the PL-2303 is configured correctly. |
766 | * If not, give up now and hope this hack will work | 761 | * If not, give up now and hope this hack will work |
767 | * properly during a later invocation of usb_serial_probe | 762 | * properly during a later invocation of usb_serial_probe |
768 | */ | 763 | */ |
769 | if (num_bulk_in == 0 || num_bulk_out == 0) { | 764 | if (num_bulk_in == 0 || num_bulk_out == 0) { |
770 | unlock_kernel(); | 765 | unlock_kernel(); |
771 | dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); | 766 | dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); |
772 | kfree(serial); | 767 | kfree(serial); |
773 | return -ENODEV; | 768 | return -ENODEV; |
774 | } | 769 | } |
775 | } | 770 | } |
776 | /* END HORRIBLE HACK FOR PL2303 */ | 771 | /* END HORRIBLE HACK FOR PL2303 */ |
777 | #endif | 772 | #endif |
778 | 773 | ||
779 | #ifdef CONFIG_USB_SERIAL_GENERIC | 774 | #ifdef CONFIG_USB_SERIAL_GENERIC |
780 | if (type == &usb_serial_generic_device) { | 775 | if (type == &usb_serial_generic_device) { |
781 | num_ports = num_bulk_out; | 776 | num_ports = num_bulk_out; |
782 | if (num_ports == 0) { | 777 | if (num_ports == 0) { |
783 | unlock_kernel(); | 778 | unlock_kernel(); |
784 | dev_err(&interface->dev, | 779 | dev_err(&interface->dev, |
785 | "Generic device with no bulk out, not allowed.\n"); | 780 | "Generic device with no bulk out, not allowed.\n"); |
786 | kfree(serial); | 781 | kfree(serial); |
787 | return -EIO; | 782 | return -EIO; |
788 | } | 783 | } |
789 | } | 784 | } |
790 | #endif | 785 | #endif |
791 | if (!num_ports) { | 786 | if (!num_ports) { |
792 | /* if this device type has a calc_num_ports function, call it */ | 787 | /* if this device type has a calc_num_ports function, call it */ |
793 | if (type->calc_num_ports) { | 788 | if (type->calc_num_ports) { |
794 | if (!try_module_get(type->driver.owner)) { | 789 | if (!try_module_get(type->driver.owner)) { |
795 | unlock_kernel(); | 790 | unlock_kernel(); |
796 | dev_err(&interface->dev, | 791 | dev_err(&interface->dev, |
797 | "module get failed, exiting\n"); | 792 | "module get failed, exiting\n"); |
798 | kfree(serial); | 793 | kfree(serial); |
799 | return -EIO; | 794 | return -EIO; |
800 | } | 795 | } |
801 | num_ports = type->calc_num_ports(serial); | 796 | num_ports = type->calc_num_ports(serial); |
802 | module_put(type->driver.owner); | 797 | module_put(type->driver.owner); |
803 | } | 798 | } |
804 | if (!num_ports) | 799 | if (!num_ports) |
805 | num_ports = type->num_ports; | 800 | num_ports = type->num_ports; |
806 | } | 801 | } |
807 | 802 | ||
808 | serial->num_ports = num_ports; | 803 | serial->num_ports = num_ports; |
809 | serial->num_bulk_in = num_bulk_in; | 804 | serial->num_bulk_in = num_bulk_in; |
810 | serial->num_bulk_out = num_bulk_out; | 805 | serial->num_bulk_out = num_bulk_out; |
811 | serial->num_interrupt_in = num_interrupt_in; | 806 | serial->num_interrupt_in = num_interrupt_in; |
812 | serial->num_interrupt_out = num_interrupt_out; | 807 | serial->num_interrupt_out = num_interrupt_out; |
813 | 808 | ||
814 | /* found all that we need */ | 809 | /* found all that we need */ |
815 | dev_info(&interface->dev, "%s converter detected\n", | 810 | dev_info(&interface->dev, "%s converter detected\n", |
816 | type->description); | 811 | type->description); |
817 | 812 | ||
818 | /* create our ports, we need as many as the max endpoints */ | 813 | /* create our ports, we need as many as the max endpoints */ |
819 | /* we don't use num_ports here because some devices have more | 814 | /* we don't use num_ports here because some devices have more |
820 | endpoint pairs than ports */ | 815 | endpoint pairs than ports */ |
821 | max_endpoints = max(num_bulk_in, num_bulk_out); | 816 | max_endpoints = max(num_bulk_in, num_bulk_out); |
822 | max_endpoints = max(max_endpoints, num_interrupt_in); | 817 | max_endpoints = max(max_endpoints, num_interrupt_in); |
823 | max_endpoints = max(max_endpoints, num_interrupt_out); | 818 | max_endpoints = max(max_endpoints, num_interrupt_out); |
824 | max_endpoints = max(max_endpoints, (int)serial->num_ports); | 819 | max_endpoints = max(max_endpoints, (int)serial->num_ports); |
825 | serial->num_port_pointers = max_endpoints; | 820 | serial->num_port_pointers = max_endpoints; |
826 | unlock_kernel(); | 821 | unlock_kernel(); |
827 | 822 | ||
828 | dbg("%s - setting up %d port structures for this device", | 823 | dbg("%s - setting up %d port structures for this device", |
829 | __func__, max_endpoints); | 824 | __func__, max_endpoints); |
830 | for (i = 0; i < max_endpoints; ++i) { | 825 | for (i = 0; i < max_endpoints; ++i) { |
831 | port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL); | 826 | port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL); |
832 | if (!port) | 827 | if (!port) |
833 | goto probe_error; | 828 | goto probe_error; |
834 | tty_port_init(&port->port); | 829 | tty_port_init(&port->port); |
835 | port->serial = serial; | 830 | port->serial = serial; |
836 | spin_lock_init(&port->lock); | 831 | spin_lock_init(&port->lock); |
837 | mutex_init(&port->mutex); | 832 | mutex_init(&port->mutex); |
838 | INIT_WORK(&port->work, usb_serial_port_work); | 833 | INIT_WORK(&port->work, usb_serial_port_work); |
839 | serial->port[i] = port; | 834 | serial->port[i] = port; |
840 | } | 835 | } |
841 | 836 | ||
842 | /* set up the endpoint information */ | 837 | /* set up the endpoint information */ |
843 | for (i = 0; i < num_bulk_in; ++i) { | 838 | for (i = 0; i < num_bulk_in; ++i) { |
844 | endpoint = bulk_in_endpoint[i]; | 839 | endpoint = bulk_in_endpoint[i]; |
845 | port = serial->port[i]; | 840 | port = serial->port[i]; |
846 | port->read_urb = usb_alloc_urb(0, GFP_KERNEL); | 841 | port->read_urb = usb_alloc_urb(0, GFP_KERNEL); |
847 | if (!port->read_urb) { | 842 | if (!port->read_urb) { |
848 | dev_err(&interface->dev, "No free urbs available\n"); | 843 | dev_err(&interface->dev, "No free urbs available\n"); |
849 | goto probe_error; | 844 | goto probe_error; |
850 | } | 845 | } |
851 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); | 846 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); |
852 | port->bulk_in_size = buffer_size; | 847 | port->bulk_in_size = buffer_size; |
853 | port->bulk_in_endpointAddress = endpoint->bEndpointAddress; | 848 | port->bulk_in_endpointAddress = endpoint->bEndpointAddress; |
854 | port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); | 849 | port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); |
855 | if (!port->bulk_in_buffer) { | 850 | if (!port->bulk_in_buffer) { |
856 | dev_err(&interface->dev, | 851 | dev_err(&interface->dev, |
857 | "Couldn't allocate bulk_in_buffer\n"); | 852 | "Couldn't allocate bulk_in_buffer\n"); |
858 | goto probe_error; | 853 | goto probe_error; |
859 | } | 854 | } |
860 | usb_fill_bulk_urb(port->read_urb, dev, | 855 | usb_fill_bulk_urb(port->read_urb, dev, |
861 | usb_rcvbulkpipe(dev, | 856 | usb_rcvbulkpipe(dev, |
862 | endpoint->bEndpointAddress), | 857 | endpoint->bEndpointAddress), |
863 | port->bulk_in_buffer, buffer_size, | 858 | port->bulk_in_buffer, buffer_size, |
864 | serial->type->read_bulk_callback, port); | 859 | serial->type->read_bulk_callback, port); |
865 | } | 860 | } |
866 | 861 | ||
867 | for (i = 0; i < num_bulk_out; ++i) { | 862 | for (i = 0; i < num_bulk_out; ++i) { |
868 | endpoint = bulk_out_endpoint[i]; | 863 | endpoint = bulk_out_endpoint[i]; |
869 | port = serial->port[i]; | 864 | port = serial->port[i]; |
870 | port->write_urb = usb_alloc_urb(0, GFP_KERNEL); | 865 | port->write_urb = usb_alloc_urb(0, GFP_KERNEL); |
871 | if (!port->write_urb) { | 866 | if (!port->write_urb) { |
872 | dev_err(&interface->dev, "No free urbs available\n"); | 867 | dev_err(&interface->dev, "No free urbs available\n"); |
873 | goto probe_error; | 868 | goto probe_error; |
874 | } | 869 | } |
875 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); | 870 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); |
876 | port->bulk_out_size = buffer_size; | 871 | port->bulk_out_size = buffer_size; |
877 | port->bulk_out_endpointAddress = endpoint->bEndpointAddress; | 872 | port->bulk_out_endpointAddress = endpoint->bEndpointAddress; |
878 | port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL); | 873 | port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL); |
879 | if (!port->bulk_out_buffer) { | 874 | if (!port->bulk_out_buffer) { |
880 | dev_err(&interface->dev, | 875 | dev_err(&interface->dev, |
881 | "Couldn't allocate bulk_out_buffer\n"); | 876 | "Couldn't allocate bulk_out_buffer\n"); |
882 | goto probe_error; | 877 | goto probe_error; |
883 | } | 878 | } |
884 | usb_fill_bulk_urb(port->write_urb, dev, | 879 | usb_fill_bulk_urb(port->write_urb, dev, |
885 | usb_sndbulkpipe(dev, | 880 | usb_sndbulkpipe(dev, |
886 | endpoint->bEndpointAddress), | 881 | endpoint->bEndpointAddress), |
887 | port->bulk_out_buffer, buffer_size, | 882 | port->bulk_out_buffer, buffer_size, |
888 | serial->type->write_bulk_callback, port); | 883 | serial->type->write_bulk_callback, port); |
889 | } | 884 | } |
890 | 885 | ||
891 | if (serial->type->read_int_callback) { | 886 | if (serial->type->read_int_callback) { |
892 | for (i = 0; i < num_interrupt_in; ++i) { | 887 | for (i = 0; i < num_interrupt_in; ++i) { |
893 | endpoint = interrupt_in_endpoint[i]; | 888 | endpoint = interrupt_in_endpoint[i]; |
894 | port = serial->port[i]; | 889 | port = serial->port[i]; |
895 | port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); | 890 | port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); |
896 | if (!port->interrupt_in_urb) { | 891 | if (!port->interrupt_in_urb) { |
897 | dev_err(&interface->dev, | 892 | dev_err(&interface->dev, |
898 | "No free urbs available\n"); | 893 | "No free urbs available\n"); |
899 | goto probe_error; | 894 | goto probe_error; |
900 | } | 895 | } |
901 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); | 896 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); |
902 | port->interrupt_in_endpointAddress = | 897 | port->interrupt_in_endpointAddress = |
903 | endpoint->bEndpointAddress; | 898 | endpoint->bEndpointAddress; |
904 | port->interrupt_in_buffer = kmalloc(buffer_size, | 899 | port->interrupt_in_buffer = kmalloc(buffer_size, |
905 | GFP_KERNEL); | 900 | GFP_KERNEL); |
906 | if (!port->interrupt_in_buffer) { | 901 | if (!port->interrupt_in_buffer) { |
907 | dev_err(&interface->dev, | 902 | dev_err(&interface->dev, |
908 | "Couldn't allocate interrupt_in_buffer\n"); | 903 | "Couldn't allocate interrupt_in_buffer\n"); |
909 | goto probe_error; | 904 | goto probe_error; |
910 | } | 905 | } |
911 | usb_fill_int_urb(port->interrupt_in_urb, dev, | 906 | usb_fill_int_urb(port->interrupt_in_urb, dev, |
912 | usb_rcvintpipe(dev, | 907 | usb_rcvintpipe(dev, |
913 | endpoint->bEndpointAddress), | 908 | endpoint->bEndpointAddress), |
914 | port->interrupt_in_buffer, buffer_size, | 909 | port->interrupt_in_buffer, buffer_size, |
915 | serial->type->read_int_callback, port, | 910 | serial->type->read_int_callback, port, |
916 | endpoint->bInterval); | 911 | endpoint->bInterval); |
917 | } | 912 | } |
918 | } else if (num_interrupt_in) { | 913 | } else if (num_interrupt_in) { |
919 | dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined"); | 914 | dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined"); |
920 | } | 915 | } |
921 | 916 | ||
922 | if (serial->type->write_int_callback) { | 917 | if (serial->type->write_int_callback) { |
923 | for (i = 0; i < num_interrupt_out; ++i) { | 918 | for (i = 0; i < num_interrupt_out; ++i) { |
924 | endpoint = interrupt_out_endpoint[i]; | 919 | endpoint = interrupt_out_endpoint[i]; |
925 | port = serial->port[i]; | 920 | port = serial->port[i]; |
926 | port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); | 921 | port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); |
927 | if (!port->interrupt_out_urb) { | 922 | if (!port->interrupt_out_urb) { |
928 | dev_err(&interface->dev, | 923 | dev_err(&interface->dev, |
929 | "No free urbs available\n"); | 924 | "No free urbs available\n"); |
930 | goto probe_error; | 925 | goto probe_error; |
931 | } | 926 | } |
932 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); | 927 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); |
933 | port->interrupt_out_size = buffer_size; | 928 | port->interrupt_out_size = buffer_size; |
934 | port->interrupt_out_endpointAddress = | 929 | port->interrupt_out_endpointAddress = |
935 | endpoint->bEndpointAddress; | 930 | endpoint->bEndpointAddress; |
936 | port->interrupt_out_buffer = kmalloc(buffer_size, | 931 | port->interrupt_out_buffer = kmalloc(buffer_size, |
937 | GFP_KERNEL); | 932 | GFP_KERNEL); |
938 | if (!port->interrupt_out_buffer) { | 933 | if (!port->interrupt_out_buffer) { |
939 | dev_err(&interface->dev, | 934 | dev_err(&interface->dev, |
940 | "Couldn't allocate interrupt_out_buffer\n"); | 935 | "Couldn't allocate interrupt_out_buffer\n"); |
941 | goto probe_error; | 936 | goto probe_error; |
942 | } | 937 | } |
943 | usb_fill_int_urb(port->interrupt_out_urb, dev, | 938 | usb_fill_int_urb(port->interrupt_out_urb, dev, |
944 | usb_sndintpipe(dev, | 939 | usb_sndintpipe(dev, |
945 | endpoint->bEndpointAddress), | 940 | endpoint->bEndpointAddress), |
946 | port->interrupt_out_buffer, buffer_size, | 941 | port->interrupt_out_buffer, buffer_size, |
947 | serial->type->write_int_callback, port, | 942 | serial->type->write_int_callback, port, |
948 | endpoint->bInterval); | 943 | endpoint->bInterval); |
949 | } | 944 | } |
950 | } else if (num_interrupt_out) { | 945 | } else if (num_interrupt_out) { |
951 | dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined"); | 946 | dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined"); |
952 | } | 947 | } |
953 | 948 | ||
954 | /* if this device type has an attach function, call it */ | 949 | /* if this device type has an attach function, call it */ |
955 | if (type->attach) { | 950 | if (type->attach) { |
956 | if (!try_module_get(type->driver.owner)) { | 951 | if (!try_module_get(type->driver.owner)) { |
957 | dev_err(&interface->dev, | 952 | dev_err(&interface->dev, |
958 | "module get failed, exiting\n"); | 953 | "module get failed, exiting\n"); |
959 | goto probe_error; | 954 | goto probe_error; |
960 | } | 955 | } |
961 | retval = type->attach(serial); | 956 | retval = type->attach(serial); |
962 | module_put(type->driver.owner); | 957 | module_put(type->driver.owner); |
963 | if (retval < 0) | 958 | if (retval < 0) |
964 | goto probe_error; | 959 | goto probe_error; |
965 | if (retval > 0) { | 960 | if (retval > 0) { |
966 | /* quietly accept this device, but don't bind to a | 961 | /* quietly accept this device, but don't bind to a |
967 | serial port as it's about to disappear */ | 962 | serial port as it's about to disappear */ |
968 | goto exit; | 963 | goto exit; |
969 | } | 964 | } |
970 | } | 965 | } |
971 | 966 | ||
972 | if (get_free_serial(serial, num_ports, &minor) == NULL) { | 967 | if (get_free_serial(serial, num_ports, &minor) == NULL) { |
973 | dev_err(&interface->dev, "No more free serial devices\n"); | 968 | dev_err(&interface->dev, "No more free serial devices\n"); |
974 | goto probe_error; | 969 | goto probe_error; |
975 | } | 970 | } |
976 | serial->minor = minor; | 971 | serial->minor = minor; |
977 | 972 | ||
978 | /* register all of the individual ports with the driver core */ | 973 | /* register all of the individual ports with the driver core */ |
979 | for (i = 0; i < num_ports; ++i) { | 974 | for (i = 0; i < num_ports; ++i) { |
980 | port = serial->port[i]; | 975 | port = serial->port[i]; |
981 | port->dev.parent = &interface->dev; | 976 | port->dev.parent = &interface->dev; |
982 | port->dev.driver = NULL; | 977 | port->dev.driver = NULL; |
983 | port->dev.bus = &usb_serial_bus_type; | 978 | port->dev.bus = &usb_serial_bus_type; |
984 | port->dev.release = &port_release; | 979 | port->dev.release = &port_release; |
985 | 980 | ||
986 | dev_set_name(&port->dev, "ttyUSB%d", port->number); | 981 | dev_set_name(&port->dev, "ttyUSB%d", port->number); |
987 | dbg ("%s - registering %s", __func__, dev_name(&port->dev)); | 982 | dbg ("%s - registering %s", __func__, dev_name(&port->dev)); |
988 | retval = device_register(&port->dev); | 983 | retval = device_register(&port->dev); |
989 | if (retval) | 984 | if (retval) |
990 | dev_err(&port->dev, "Error registering port device, " | 985 | dev_err(&port->dev, "Error registering port device, " |
991 | "continuing\n"); | 986 | "continuing\n"); |
992 | } | 987 | } |
993 | 988 | ||
994 | usb_serial_console_init(debug, minor); | 989 | usb_serial_console_init(debug, minor); |
995 | 990 | ||
996 | exit: | 991 | exit: |
997 | /* success */ | 992 | /* success */ |
998 | usb_set_intfdata(interface, serial); | 993 | usb_set_intfdata(interface, serial); |
999 | return 0; | 994 | return 0; |
1000 | 995 | ||
1001 | probe_error: | 996 | probe_error: |
1002 | for (i = 0; i < num_bulk_in; ++i) { | 997 | for (i = 0; i < num_bulk_in; ++i) { |
1003 | port = serial->port[i]; | 998 | port = serial->port[i]; |
1004 | if (!port) | 999 | if (!port) |
1005 | continue; | 1000 | continue; |
1006 | usb_free_urb(port->read_urb); | 1001 | usb_free_urb(port->read_urb); |
1007 | kfree(port->bulk_in_buffer); | 1002 | kfree(port->bulk_in_buffer); |
1008 | } | 1003 | } |
1009 | for (i = 0; i < num_bulk_out; ++i) { | 1004 | for (i = 0; i < num_bulk_out; ++i) { |
1010 | port = serial->port[i]; | 1005 | port = serial->port[i]; |
1011 | if (!port) | 1006 | if (!port) |
1012 | continue; | 1007 | continue; |
1013 | usb_free_urb(port->write_urb); | 1008 | usb_free_urb(port->write_urb); |
1014 | kfree(port->bulk_out_buffer); | 1009 | kfree(port->bulk_out_buffer); |
1015 | } | 1010 | } |
1016 | for (i = 0; i < num_interrupt_in; ++i) { | 1011 | for (i = 0; i < num_interrupt_in; ++i) { |
1017 | port = serial->port[i]; | 1012 | port = serial->port[i]; |
1018 | if (!port) | 1013 | if (!port) |
1019 | continue; | 1014 | continue; |
1020 | usb_free_urb(port->interrupt_in_urb); | 1015 | usb_free_urb(port->interrupt_in_urb); |
1021 | kfree(port->interrupt_in_buffer); | 1016 | kfree(port->interrupt_in_buffer); |
1022 | } | 1017 | } |
1023 | for (i = 0; i < num_interrupt_out; ++i) { | 1018 | for (i = 0; i < num_interrupt_out; ++i) { |
1024 | port = serial->port[i]; | 1019 | port = serial->port[i]; |
1025 | if (!port) | 1020 | if (!port) |
1026 | continue; | 1021 | continue; |
1027 | usb_free_urb(port->interrupt_out_urb); | 1022 | usb_free_urb(port->interrupt_out_urb); |
1028 | kfree(port->interrupt_out_buffer); | 1023 | kfree(port->interrupt_out_buffer); |
1029 | } | 1024 | } |
1030 | 1025 | ||
1031 | /* free up any memory that we allocated */ | 1026 | /* free up any memory that we allocated */ |
1032 | for (i = 0; i < serial->num_port_pointers; ++i) | 1027 | for (i = 0; i < serial->num_port_pointers; ++i) |
1033 | kfree(serial->port[i]); | 1028 | kfree(serial->port[i]); |
1034 | kfree(serial); | 1029 | kfree(serial); |
1035 | return -EIO; | 1030 | return -EIO; |
1036 | } | 1031 | } |
1037 | EXPORT_SYMBOL_GPL(usb_serial_probe); | 1032 | EXPORT_SYMBOL_GPL(usb_serial_probe); |
1038 | 1033 | ||
1039 | void usb_serial_disconnect(struct usb_interface *interface) | 1034 | void usb_serial_disconnect(struct usb_interface *interface) |
1040 | { | 1035 | { |
1041 | int i; | 1036 | int i; |
1042 | struct usb_serial *serial = usb_get_intfdata(interface); | 1037 | struct usb_serial *serial = usb_get_intfdata(interface); |
1043 | struct device *dev = &interface->dev; | 1038 | struct device *dev = &interface->dev; |
1044 | struct usb_serial_port *port; | 1039 | struct usb_serial_port *port; |
1045 | 1040 | ||
1046 | usb_serial_console_disconnect(serial); | 1041 | usb_serial_console_disconnect(serial); |
1047 | dbg("%s", __func__); | 1042 | dbg("%s", __func__); |
1048 | 1043 | ||
1049 | mutex_lock(&serial->disc_mutex); | 1044 | mutex_lock(&serial->disc_mutex); |
1050 | usb_set_intfdata(interface, NULL); | 1045 | usb_set_intfdata(interface, NULL); |
1051 | /* must set a flag, to signal subdrivers */ | 1046 | /* must set a flag, to signal subdrivers */ |
1052 | serial->disconnected = 1; | 1047 | serial->disconnected = 1; |
1053 | for (i = 0; i < serial->num_ports; ++i) { | 1048 | for (i = 0; i < serial->num_ports; ++i) { |
1054 | port = serial->port[i]; | 1049 | port = serial->port[i]; |
1055 | if (port) { | 1050 | if (port) { |
1056 | struct tty_struct *tty = tty_port_tty_get(&port->port); | 1051 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
1057 | if (tty) { | 1052 | if (tty) { |
1058 | tty_hangup(tty); | 1053 | tty_hangup(tty); |
1059 | tty_kref_put(tty); | 1054 | tty_kref_put(tty); |
1060 | } | 1055 | } |
1061 | kill_traffic(port); | 1056 | kill_traffic(port); |
1062 | } | 1057 | } |
1063 | } | 1058 | } |
1064 | /* let the last holder of this object | 1059 | /* let the last holder of this object |
1065 | * cause it to be cleaned up */ | 1060 | * cause it to be cleaned up */ |
1066 | mutex_unlock(&serial->disc_mutex); | 1061 | mutex_unlock(&serial->disc_mutex); |
1067 | usb_serial_put(serial); | 1062 | usb_serial_put(serial); |
1068 | dev_info(dev, "device disconnected\n"); | 1063 | dev_info(dev, "device disconnected\n"); |
1069 | } | 1064 | } |
1070 | EXPORT_SYMBOL_GPL(usb_serial_disconnect); | 1065 | EXPORT_SYMBOL_GPL(usb_serial_disconnect); |
1071 | 1066 | ||
1072 | int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) | 1067 | int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) |
1073 | { | 1068 | { |
1074 | struct usb_serial *serial = usb_get_intfdata(intf); | 1069 | struct usb_serial *serial = usb_get_intfdata(intf); |
1075 | struct usb_serial_port *port; | 1070 | struct usb_serial_port *port; |
1076 | int i, r = 0; | 1071 | int i, r = 0; |
1077 | 1072 | ||
1078 | for (i = 0; i < serial->num_ports; ++i) { | 1073 | for (i = 0; i < serial->num_ports; ++i) { |
1079 | port = serial->port[i]; | 1074 | port = serial->port[i]; |
1080 | if (port) | 1075 | if (port) |
1081 | kill_traffic(port); | 1076 | kill_traffic(port); |
1082 | } | 1077 | } |
1083 | 1078 | ||
1084 | if (serial->type->suspend) | 1079 | if (serial->type->suspend) |
1085 | r = serial->type->suspend(serial, message); | 1080 | r = serial->type->suspend(serial, message); |
1086 | 1081 | ||
1087 | return r; | 1082 | return r; |
1088 | } | 1083 | } |
1089 | EXPORT_SYMBOL(usb_serial_suspend); | 1084 | EXPORT_SYMBOL(usb_serial_suspend); |
1090 | 1085 | ||
1091 | int usb_serial_resume(struct usb_interface *intf) | 1086 | int usb_serial_resume(struct usb_interface *intf) |
1092 | { | 1087 | { |
1093 | struct usb_serial *serial = usb_get_intfdata(intf); | 1088 | struct usb_serial *serial = usb_get_intfdata(intf); |
1094 | 1089 | ||
1095 | if (serial->type->resume) | 1090 | if (serial->type->resume) |
1096 | return serial->type->resume(serial); | 1091 | return serial->type->resume(serial); |
1097 | return 0; | 1092 | return 0; |
1098 | } | 1093 | } |
1099 | EXPORT_SYMBOL(usb_serial_resume); | 1094 | EXPORT_SYMBOL(usb_serial_resume); |
1100 | 1095 | ||
1101 | static const struct tty_operations serial_ops = { | 1096 | static const struct tty_operations serial_ops = { |
1102 | .open = serial_open, | 1097 | .open = serial_open, |
1103 | .close = serial_close, | 1098 | .close = serial_close, |
1104 | .write = serial_write, | 1099 | .write = serial_write, |
1105 | .write_room = serial_write_room, | 1100 | .write_room = serial_write_room, |
1106 | .ioctl = serial_ioctl, | 1101 | .ioctl = serial_ioctl, |
1107 | .set_termios = serial_set_termios, | 1102 | .set_termios = serial_set_termios, |
1108 | .throttle = serial_throttle, | 1103 | .throttle = serial_throttle, |
1109 | .unthrottle = serial_unthrottle, | 1104 | .unthrottle = serial_unthrottle, |
1110 | .break_ctl = serial_break, | 1105 | .break_ctl = serial_break, |
1111 | .chars_in_buffer = serial_chars_in_buffer, | 1106 | .chars_in_buffer = serial_chars_in_buffer, |
1112 | .read_proc = serial_read_proc, | 1107 | .read_proc = serial_read_proc, |
1113 | .tiocmget = serial_tiocmget, | 1108 | .tiocmget = serial_tiocmget, |
1114 | .tiocmset = serial_tiocmset, | 1109 | .tiocmset = serial_tiocmset, |
1115 | }; | 1110 | }; |
1116 | 1111 | ||
1117 | struct tty_driver *usb_serial_tty_driver; | 1112 | struct tty_driver *usb_serial_tty_driver; |
1118 | 1113 | ||
1119 | static int __init usb_serial_init(void) | 1114 | static int __init usb_serial_init(void) |
1120 | { | 1115 | { |
1121 | int i; | 1116 | int i; |
1122 | int result; | 1117 | int result; |
1123 | 1118 | ||
1124 | usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS); | 1119 | usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS); |
1125 | if (!usb_serial_tty_driver) | 1120 | if (!usb_serial_tty_driver) |
1126 | return -ENOMEM; | 1121 | return -ENOMEM; |
1127 | 1122 | ||
1128 | /* Initialize our global data */ | 1123 | /* Initialize our global data */ |
1129 | for (i = 0; i < SERIAL_TTY_MINORS; ++i) | 1124 | for (i = 0; i < SERIAL_TTY_MINORS; ++i) |
1130 | serial_table[i] = NULL; | 1125 | serial_table[i] = NULL; |
1131 | 1126 | ||
1132 | result = bus_register(&usb_serial_bus_type); | 1127 | result = bus_register(&usb_serial_bus_type); |
1133 | if (result) { | 1128 | if (result) { |
1134 | printk(KERN_ERR "usb-serial: %s - registering bus driver " | 1129 | printk(KERN_ERR "usb-serial: %s - registering bus driver " |
1135 | "failed\n", __func__); | 1130 | "failed\n", __func__); |
1136 | goto exit_bus; | 1131 | goto exit_bus; |
1137 | } | 1132 | } |
1138 | 1133 | ||
1139 | usb_serial_tty_driver->owner = THIS_MODULE; | 1134 | usb_serial_tty_driver->owner = THIS_MODULE; |
1140 | usb_serial_tty_driver->driver_name = "usbserial"; | 1135 | usb_serial_tty_driver->driver_name = "usbserial"; |
1141 | usb_serial_tty_driver->name = "ttyUSB"; | 1136 | usb_serial_tty_driver->name = "ttyUSB"; |
1142 | usb_serial_tty_driver->major = SERIAL_TTY_MAJOR; | 1137 | usb_serial_tty_driver->major = SERIAL_TTY_MAJOR; |
1143 | usb_serial_tty_driver->minor_start = 0; | 1138 | usb_serial_tty_driver->minor_start = 0; |
1144 | usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; | 1139 | usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; |
1145 | usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL; | 1140 | usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL; |
1146 | usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | | 1141 | usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | |
1147 | TTY_DRIVER_DYNAMIC_DEV; | 1142 | TTY_DRIVER_DYNAMIC_DEV; |
1148 | usb_serial_tty_driver->init_termios = tty_std_termios; | 1143 | usb_serial_tty_driver->init_termios = tty_std_termios; |
1149 | usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | 1144 | usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD |
1150 | | HUPCL | CLOCAL; | 1145 | | HUPCL | CLOCAL; |
1151 | usb_serial_tty_driver->init_termios.c_ispeed = 9600; | 1146 | usb_serial_tty_driver->init_termios.c_ispeed = 9600; |
1152 | usb_serial_tty_driver->init_termios.c_ospeed = 9600; | 1147 | usb_serial_tty_driver->init_termios.c_ospeed = 9600; |
1153 | tty_set_operations(usb_serial_tty_driver, &serial_ops); | 1148 | tty_set_operations(usb_serial_tty_driver, &serial_ops); |
1154 | result = tty_register_driver(usb_serial_tty_driver); | 1149 | result = tty_register_driver(usb_serial_tty_driver); |
1155 | if (result) { | 1150 | if (result) { |
1156 | printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n", | 1151 | printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n", |
1157 | __func__); | 1152 | __func__); |
1158 | goto exit_reg_driver; | 1153 | goto exit_reg_driver; |
1159 | } | 1154 | } |
1160 | 1155 | ||
1161 | /* register the USB driver */ | 1156 | /* register the USB driver */ |
1162 | result = usb_register(&usb_serial_driver); | 1157 | result = usb_register(&usb_serial_driver); |
1163 | if (result < 0) { | 1158 | if (result < 0) { |
1164 | printk(KERN_ERR "usb-serial: %s - usb_register failed\n", | 1159 | printk(KERN_ERR "usb-serial: %s - usb_register failed\n", |
1165 | __func__); | 1160 | __func__); |
1166 | goto exit_tty; | 1161 | goto exit_tty; |
1167 | } | 1162 | } |
1168 | 1163 | ||
1169 | /* register the generic driver, if we should */ | 1164 | /* register the generic driver, if we should */ |
1170 | result = usb_serial_generic_register(debug); | 1165 | result = usb_serial_generic_register(debug); |
1171 | if (result < 0) { | 1166 | if (result < 0) { |
1172 | printk(KERN_ERR "usb-serial: %s - registering generic " | 1167 | printk(KERN_ERR "usb-serial: %s - registering generic " |
1173 | "driver failed\n", __func__); | 1168 | "driver failed\n", __func__); |
1174 | goto exit_generic; | 1169 | goto exit_generic; |
1175 | } | 1170 | } |
1176 | 1171 | ||
1177 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); | 1172 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); |
1178 | 1173 | ||
1179 | return result; | 1174 | return result; |
1180 | 1175 | ||
1181 | exit_generic: | 1176 | exit_generic: |
1182 | usb_deregister(&usb_serial_driver); | 1177 | usb_deregister(&usb_serial_driver); |
1183 | 1178 | ||
1184 | exit_tty: | 1179 | exit_tty: |
1185 | tty_unregister_driver(usb_serial_tty_driver); | 1180 | tty_unregister_driver(usb_serial_tty_driver); |
1186 | 1181 | ||
1187 | exit_reg_driver: | 1182 | exit_reg_driver: |
1188 | bus_unregister(&usb_serial_bus_type); | 1183 | bus_unregister(&usb_serial_bus_type); |
1189 | 1184 | ||
1190 | exit_bus: | 1185 | exit_bus: |
1191 | printk(KERN_ERR "usb-serial: %s - returning with error %d\n", | 1186 | printk(KERN_ERR "usb-serial: %s - returning with error %d\n", |
1192 | __func__, result); | 1187 | __func__, result); |
1193 | put_tty_driver(usb_serial_tty_driver); | 1188 | put_tty_driver(usb_serial_tty_driver); |
1194 | return result; | 1189 | return result; |
1195 | } | 1190 | } |
1196 | 1191 | ||
1197 | 1192 | ||
1198 | static void __exit usb_serial_exit(void) | 1193 | static void __exit usb_serial_exit(void) |
1199 | { | 1194 | { |
1200 | usb_serial_console_exit(); | 1195 | usb_serial_console_exit(); |
1201 | 1196 | ||
1202 | usb_serial_generic_deregister(); | 1197 | usb_serial_generic_deregister(); |
1203 | 1198 | ||
1204 | usb_deregister(&usb_serial_driver); | 1199 | usb_deregister(&usb_serial_driver); |
1205 | tty_unregister_driver(usb_serial_tty_driver); | 1200 | tty_unregister_driver(usb_serial_tty_driver); |
1206 | put_tty_driver(usb_serial_tty_driver); | 1201 | put_tty_driver(usb_serial_tty_driver); |
1207 | bus_unregister(&usb_serial_bus_type); | 1202 | bus_unregister(&usb_serial_bus_type); |
1208 | } | 1203 | } |
1209 | 1204 | ||
1210 | 1205 | ||
1211 | module_init(usb_serial_init); | 1206 | module_init(usb_serial_init); |
1212 | module_exit(usb_serial_exit); | 1207 | module_exit(usb_serial_exit); |
1213 | 1208 | ||
1214 | #define set_to_generic_if_null(type, function) \ | 1209 | #define set_to_generic_if_null(type, function) \ |
1215 | do { \ | 1210 | do { \ |
1216 | if (!type->function) { \ | 1211 | if (!type->function) { \ |
1217 | type->function = usb_serial_generic_##function; \ | 1212 | type->function = usb_serial_generic_##function; \ |
1218 | dbg("Had to override the " #function \ | 1213 | dbg("Had to override the " #function \ |
1219 | " usb serial operation with the generic one.");\ | 1214 | " usb serial operation with the generic one.");\ |
1220 | } \ | 1215 | } \ |
1221 | } while (0) | 1216 | } while (0) |
1222 | 1217 | ||
1223 | static void fixup_generic(struct usb_serial_driver *device) | 1218 | static void fixup_generic(struct usb_serial_driver *device) |
1224 | { | 1219 | { |
1225 | set_to_generic_if_null(device, open); | 1220 | set_to_generic_if_null(device, open); |
1226 | set_to_generic_if_null(device, write); | 1221 | set_to_generic_if_null(device, write); |
1227 | set_to_generic_if_null(device, close); | 1222 | set_to_generic_if_null(device, close); |
1228 | set_to_generic_if_null(device, write_room); | 1223 | set_to_generic_if_null(device, write_room); |
1229 | set_to_generic_if_null(device, chars_in_buffer); | 1224 | set_to_generic_if_null(device, chars_in_buffer); |
1230 | set_to_generic_if_null(device, read_bulk_callback); | 1225 | set_to_generic_if_null(device, read_bulk_callback); |
1231 | set_to_generic_if_null(device, write_bulk_callback); | 1226 | set_to_generic_if_null(device, write_bulk_callback); |
1232 | set_to_generic_if_null(device, shutdown); | 1227 | set_to_generic_if_null(device, shutdown); |
1233 | set_to_generic_if_null(device, resume); | 1228 | set_to_generic_if_null(device, resume); |
1234 | } | 1229 | } |
1235 | 1230 | ||
1236 | int usb_serial_register(struct usb_serial_driver *driver) | 1231 | int usb_serial_register(struct usb_serial_driver *driver) |
1237 | { | 1232 | { |
1238 | /* must be called with BKL held */ | 1233 | /* must be called with BKL held */ |
1239 | int retval; | 1234 | int retval; |
1240 | 1235 | ||
1241 | fixup_generic(driver); | 1236 | fixup_generic(driver); |
1242 | 1237 | ||
1243 | if (!driver->description) | 1238 | if (!driver->description) |
1244 | driver->description = driver->driver.name; | 1239 | driver->description = driver->driver.name; |
1245 | 1240 | ||
1246 | /* Add this device to our list of devices */ | 1241 | /* Add this device to our list of devices */ |
1247 | list_add(&driver->driver_list, &usb_serial_driver_list); | 1242 | list_add(&driver->driver_list, &usb_serial_driver_list); |
1248 | 1243 | ||
1249 | retval = usb_serial_bus_register(driver); | 1244 | retval = usb_serial_bus_register(driver); |
1250 | if (retval) { | 1245 | if (retval) { |
1251 | printk(KERN_ERR "usb-serial: problem %d when registering " | 1246 | printk(KERN_ERR "usb-serial: problem %d when registering " |
1252 | "driver %s\n", retval, driver->description); | 1247 | "driver %s\n", retval, driver->description); |
1253 | list_del(&driver->driver_list); | 1248 | list_del(&driver->driver_list); |
1254 | } else | 1249 | } else |
1255 | printk(KERN_INFO "USB Serial support registered for %s\n", | 1250 | printk(KERN_INFO "USB Serial support registered for %s\n", |
1256 | driver->description); | 1251 | driver->description); |
1257 | 1252 | ||
1258 | return retval; | 1253 | return retval; |
1259 | } | 1254 | } |
1260 | EXPORT_SYMBOL_GPL(usb_serial_register); | 1255 | EXPORT_SYMBOL_GPL(usb_serial_register); |
1261 | 1256 | ||
1262 | 1257 | ||
1263 | void usb_serial_deregister(struct usb_serial_driver *device) | 1258 | void usb_serial_deregister(struct usb_serial_driver *device) |
1264 | { | 1259 | { |
1265 | /* must be called with BKL held */ | 1260 | /* must be called with BKL held */ |
1266 | printk(KERN_INFO "USB Serial deregistering driver %s\n", | 1261 | printk(KERN_INFO "USB Serial deregistering driver %s\n", |
1267 | device->description); | 1262 | device->description); |
1268 | list_del(&device->driver_list); | 1263 | list_del(&device->driver_list); |
1269 | usb_serial_bus_deregister(device); | 1264 | usb_serial_bus_deregister(device); |
1270 | } | 1265 | } |
1271 | EXPORT_SYMBOL_GPL(usb_serial_deregister); | 1266 | EXPORT_SYMBOL_GPL(usb_serial_deregister); |
1272 | 1267 | ||
1273 | /* Module information */ | 1268 | /* Module information */ |
1274 | MODULE_AUTHOR(DRIVER_AUTHOR); | 1269 | MODULE_AUTHOR(DRIVER_AUTHOR); |
1275 | MODULE_DESCRIPTION(DRIVER_DESC); | 1270 | MODULE_DESCRIPTION(DRIVER_DESC); |
1276 | MODULE_LICENSE("GPL"); | 1271 | MODULE_LICENSE("GPL"); |
1277 | 1272 | ||
1278 | module_param(debug, bool, S_IRUGO | S_IWUSR); | 1273 | module_param(debug, bool, S_IRUGO | S_IWUSR); |
1279 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | 1274 | MODULE_PARM_DESC(debug, "Debug enabled or not"); |
1280 | 1275 |