aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2013-03-21 07:37:29 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-03-25 16:52:28 -0400
commit4d63143db1426342f186cfe258db73571bf57897 (patch)
tree88b144ffda0d920f500cee80983352a319507828 /drivers/usb/serial
parent0a967f62e6623a2a7bb3a5707352b6667c0c649e (diff)
USB: spcp8x5: reimplement device type detection
Reimplement device type detection using the device id table and quirks. Device type was used to detect one device type which did not support to control functions. Add quirks to the device table and store them in the private port data at probe instead. Signed-off-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r--drivers/usb/serial/spcp8x5.c70
1 files changed, 21 insertions, 49 deletions
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index e0093dd22238..a454a3f1acb3 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -28,6 +28,9 @@
28 28
29#define DRIVER_DESC "SPCP8x5 USB to serial adaptor driver" 29#define DRIVER_DESC "SPCP8x5 USB to serial adaptor driver"
30 30
31#define SPCP825_QUIRK_NO_UART_STATUS 0x01
32#define SPCP825_QUIRK_NO_WORK_MODE 0x02
33
31#define SPCP8x5_007_VID 0x04FC 34#define SPCP8x5_007_VID 0x04FC
32#define SPCP8x5_007_PID 0x0201 35#define SPCP8x5_007_PID 0x0201
33#define SPCP8x5_008_VID 0x04fc 36#define SPCP8x5_008_VID 0x04fc
@@ -44,7 +47,9 @@ static const struct usb_device_id id_table[] = {
44 { USB_DEVICE(SPCP8x5_INTERMATIC_VID, SPCP8x5_INTERMATIC_PID)}, 47 { USB_DEVICE(SPCP8x5_INTERMATIC_VID, SPCP8x5_INTERMATIC_PID)},
45 { USB_DEVICE(SPCP8x5_835_VID, SPCP8x5_835_PID)}, 48 { USB_DEVICE(SPCP8x5_835_VID, SPCP8x5_835_PID)},
46 { USB_DEVICE(SPCP8x5_008_VID, SPCP8x5_008_PID)}, 49 { USB_DEVICE(SPCP8x5_008_VID, SPCP8x5_008_PID)},
47 { USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID)}, 50 { USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID),
51 .driver_info = SPCP825_QUIRK_NO_UART_STATUS |
52 SPCP825_QUIRK_NO_WORK_MODE },
48 { } /* Terminating entry */ 53 { } /* Terminating entry */
49}; 54};
50MODULE_DEVICE_TABLE(usb, id_table); 55MODULE_DEVICE_TABLE(usb, id_table);
@@ -136,47 +141,32 @@ struct spcp8x5_usb_ctrl_arg {
136#define UART_OVERRUN_ERROR 0x40 141#define UART_OVERRUN_ERROR 0x40
137#define UART_CTS 0x80 142#define UART_CTS 0x80
138 143
139enum spcp8x5_type {
140 SPCP825_007_TYPE,
141 SPCP825_008_TYPE,
142 SPCP825_PHILIP_TYPE,
143 SPCP825_INTERMATIC_TYPE,
144 SPCP835_TYPE,
145};
146
147struct spcp8x5_private { 144struct spcp8x5_private {
145 unsigned quirks;
148 spinlock_t lock; 146 spinlock_t lock;
149 enum spcp8x5_type type;
150 u8 line_control; 147 u8 line_control;
151 u8 line_status; 148 u8 line_status;
152}; 149};
153 150
151static int spcp8x5_probe(struct usb_serial *serial,
152 const struct usb_device_id *id)
153{
154 usb_set_serial_data(serial, (void *)id);
155
156 return 0;
157}
158
154static int spcp8x5_port_probe(struct usb_serial_port *port) 159static int spcp8x5_port_probe(struct usb_serial_port *port)
155{ 160{
156 struct usb_serial *serial = port->serial; 161 const struct usb_device_id *id = usb_get_serial_data(port->serial);
157 struct spcp8x5_private *priv; 162 struct spcp8x5_private *priv;
158 enum spcp8x5_type type = SPCP825_007_TYPE;
159 u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
160
161 if (product == 0x0201)
162 type = SPCP825_007_TYPE;
163 else if (product == 0x0231)
164 type = SPCP835_TYPE;
165 else if (product == 0x0235)
166 type = SPCP825_008_TYPE;
167 else if (product == 0x0204)
168 type = SPCP825_INTERMATIC_TYPE;
169 else if (product == 0x0471 &&
170 serial->dev->descriptor.idVendor == cpu_to_le16(0x081e))
171 type = SPCP825_PHILIP_TYPE;
172 dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type);
173 163
174 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 164 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
175 if (!priv) 165 if (!priv)
176 return -ENOMEM; 166 return -ENOMEM;
177 167
178 spin_lock_init(&priv->lock); 168 spin_lock_init(&priv->lock);
179 priv->type = type; 169 priv->quirks = id->driver_info;
180 170
181 usb_set_serial_port_data(port, priv); 171 usb_set_serial_port_data(port, priv);
182 172
@@ -193,18 +183,13 @@ static int spcp8x5_port_remove(struct usb_serial_port *port)
193 return 0; 183 return 0;
194} 184}
195 185
196/*
197 * Set the modem control line of the device.
198 *
199 * NOTE: not supported by spcp825-007
200 */
201static int spcp8x5_set_ctrl_line(struct usb_serial_port *port, u8 mcr) 186static int spcp8x5_set_ctrl_line(struct usb_serial_port *port, u8 mcr)
202{ 187{
203 struct spcp8x5_private *priv = usb_get_serial_port_data(port); 188 struct spcp8x5_private *priv = usb_get_serial_port_data(port);
204 struct usb_device *dev = port->serial->dev; 189 struct usb_device *dev = port->serial->dev;
205 int retval; 190 int retval;
206 191
207 if (priv->type == SPCP825_007_TYPE) 192 if (priv->quirks & SPCP825_QUIRK_NO_UART_STATUS)
208 return -EPERM; 193 return -EPERM;
209 194
210 retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 195 retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
@@ -217,11 +202,6 @@ static int spcp8x5_set_ctrl_line(struct usb_serial_port *port, u8 mcr)
217 return retval; 202 return retval;
218} 203}
219 204
220/*
221 * Get the modem status register of the device.
222 *
223 * NOTE: not supported by spcp825-007
224 */
225static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status) 205static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status)
226{ 206{
227 struct spcp8x5_private *priv = usb_get_serial_port_data(port); 207 struct spcp8x5_private *priv = usb_get_serial_port_data(port);
@@ -229,9 +209,7 @@ static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status)
229 u8 *buf; 209 u8 *buf;
230 int ret; 210 int ret;
231 211
232 /* I return Permited not support here but seem inval device 212 if (priv->quirks & SPCP825_QUIRK_NO_UART_STATUS)
233 * is more fix */
234 if (priv->type == SPCP825_007_TYPE)
235 return -EPERM; 213 return -EPERM;
236 214
237 buf = kzalloc(1, GFP_KERNEL); 215 buf = kzalloc(1, GFP_KERNEL);
@@ -251,11 +229,6 @@ static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status)
251 return ret; 229 return ret;
252} 230}
253 231
254/*
255 * Select the work mode.
256 *
257 * NOTE: not supported by spcp825-007
258 */
259static void spcp8x5_set_work_mode(struct usb_serial_port *port, u16 value, 232static void spcp8x5_set_work_mode(struct usb_serial_port *port, u16 value,
260 u16 index) 233 u16 index)
261{ 234{
@@ -263,9 +236,7 @@ static void spcp8x5_set_work_mode(struct usb_serial_port *port, u16 value,
263 struct usb_device *dev = port->serial->dev; 236 struct usb_device *dev = port->serial->dev;
264 int ret; 237 int ret;
265 238
266 /* I return Permited not support here but seem inval device 239 if (priv->quirks & SPCP825_QUIRK_NO_WORK_MODE)
267 * is more fix */
268 if (priv->type == SPCP825_007_TYPE)
269 return; 240 return;
270 241
271 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 242 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
@@ -518,6 +489,7 @@ static struct usb_serial_driver spcp8x5_device = {
518 .init_termios = spcp8x5_init_termios, 489 .init_termios = spcp8x5_init_termios,
519 .tiocmget = spcp8x5_tiocmget, 490 .tiocmget = spcp8x5_tiocmget,
520 .tiocmset = spcp8x5_tiocmset, 491 .tiocmset = spcp8x5_tiocmset,
492 .probe = spcp8x5_probe,
521 .port_probe = spcp8x5_port_probe, 493 .port_probe = spcp8x5_port_probe,
522 .port_remove = spcp8x5_port_remove, 494 .port_remove = spcp8x5_port_remove,
523}; 495};