diff options
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 119 |
1 files changed, 54 insertions, 65 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index da1c6f7f82b8..7b1673a44077 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -271,26 +271,58 @@ static int debug; | |||
271 | static __u16 vendor = FTDI_VID; | 271 | static __u16 vendor = FTDI_VID; |
272 | static __u16 product; | 272 | static __u16 product; |
273 | 273 | ||
274 | struct ftdi_private { | ||
275 | ftdi_chip_type_t chip_type; | ||
276 | /* type of the device, either SIO or FT8U232AM */ | ||
277 | int baud_base; /* baud base clock for divisor setting */ | ||
278 | int custom_divisor; /* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */ | ||
279 | __u16 last_set_data_urb_value ; | ||
280 | /* the last data state set - needed for doing a break */ | ||
281 | int write_offset; /* This is the offset in the usb data block to write the serial data - | ||
282 | * it is different between devices | ||
283 | */ | ||
284 | int flags; /* some ASYNC_xxxx flags are supported */ | ||
285 | unsigned long last_dtr_rts; /* saved modem control outputs */ | ||
286 | wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ | ||
287 | char prev_status, diff_status; /* Used for TIOCMIWAIT */ | ||
288 | __u8 rx_flags; /* receive state flags (throttling) */ | ||
289 | spinlock_t rx_lock; /* spinlock for receive state */ | ||
290 | struct delayed_work rx_work; | ||
291 | struct usb_serial_port *port; | ||
292 | int rx_processed; | ||
293 | unsigned long rx_bytes; | ||
294 | |||
295 | __u16 interface; /* FT2232C port interface (0 for FT232/245) */ | ||
296 | |||
297 | int force_baud; /* if non-zero, force the baud rate to this value */ | ||
298 | int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */ | ||
299 | |||
300 | spinlock_t tx_lock; /* spinlock for transmit state */ | ||
301 | unsigned long tx_bytes; | ||
302 | unsigned long tx_outstanding_bytes; | ||
303 | unsigned long tx_outstanding_urbs; | ||
304 | }; | ||
305 | |||
274 | /* struct ftdi_sio_quirk is used by devices requiring special attention. */ | 306 | /* struct ftdi_sio_quirk is used by devices requiring special attention. */ |
275 | struct ftdi_sio_quirk { | 307 | struct ftdi_sio_quirk { |
276 | int (*probe)(struct usb_serial *); | 308 | int (*probe)(struct usb_serial *); |
277 | void (*setup)(struct usb_serial *); /* Special settings during startup. */ | 309 | void (*port_probe)(struct ftdi_private *); /* Special settings for probed ports. */ |
278 | }; | 310 | }; |
279 | 311 | ||
280 | static int ftdi_olimex_probe (struct usb_serial *serial); | 312 | static int ftdi_olimex_probe (struct usb_serial *serial); |
281 | static void ftdi_USB_UIRT_setup (struct usb_serial *serial); | 313 | static void ftdi_USB_UIRT_setup (struct ftdi_private *priv); |
282 | static void ftdi_HE_TIRA1_setup (struct usb_serial *serial); | 314 | static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv); |
283 | 315 | ||
284 | static struct ftdi_sio_quirk ftdi_olimex_quirk = { | 316 | static struct ftdi_sio_quirk ftdi_olimex_quirk = { |
285 | .probe = ftdi_olimex_probe, | 317 | .probe = ftdi_olimex_probe, |
286 | }; | 318 | }; |
287 | 319 | ||
288 | static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = { | 320 | static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = { |
289 | .setup = ftdi_USB_UIRT_setup, | 321 | .port_probe = ftdi_USB_UIRT_setup, |
290 | }; | 322 | }; |
291 | 323 | ||
292 | static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { | 324 | static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { |
293 | .setup = ftdi_HE_TIRA1_setup, | 325 | .port_probe = ftdi_HE_TIRA1_setup, |
294 | }; | 326 | }; |
295 | 327 | ||
296 | /* | 328 | /* |
@@ -567,38 +599,6 @@ static const char *ftdi_chip_name[] = { | |||
567 | #define THROTTLED 0x01 | 599 | #define THROTTLED 0x01 |
568 | #define ACTUALLY_THROTTLED 0x02 | 600 | #define ACTUALLY_THROTTLED 0x02 |
569 | 601 | ||
570 | struct ftdi_private { | ||
571 | ftdi_chip_type_t chip_type; | ||
572 | /* type of the device, either SIO or FT8U232AM */ | ||
573 | int baud_base; /* baud base clock for divisor setting */ | ||
574 | int custom_divisor; /* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */ | ||
575 | __u16 last_set_data_urb_value ; | ||
576 | /* the last data state set - needed for doing a break */ | ||
577 | int write_offset; /* This is the offset in the usb data block to write the serial data - | ||
578 | * it is different between devices | ||
579 | */ | ||
580 | int flags; /* some ASYNC_xxxx flags are supported */ | ||
581 | unsigned long last_dtr_rts; /* saved modem control outputs */ | ||
582 | wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ | ||
583 | char prev_status, diff_status; /* Used for TIOCMIWAIT */ | ||
584 | __u8 rx_flags; /* receive state flags (throttling) */ | ||
585 | spinlock_t rx_lock; /* spinlock for receive state */ | ||
586 | struct delayed_work rx_work; | ||
587 | struct usb_serial_port *port; | ||
588 | int rx_processed; | ||
589 | unsigned long rx_bytes; | ||
590 | |||
591 | __u16 interface; /* FT2232C port interface (0 for FT232/245) */ | ||
592 | |||
593 | int force_baud; /* if non-zero, force the baud rate to this value */ | ||
594 | int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */ | ||
595 | |||
596 | spinlock_t tx_lock; /* spinlock for transmit state */ | ||
597 | unsigned long tx_bytes; | ||
598 | unsigned long tx_outstanding_bytes; | ||
599 | unsigned long tx_outstanding_urbs; | ||
600 | }; | ||
601 | |||
602 | /* Used for TIOCMIWAIT */ | 602 | /* Used for TIOCMIWAIT */ |
603 | #define FTDI_STATUS_B0_MASK (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD) | 603 | #define FTDI_STATUS_B0_MASK (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD) |
604 | #define FTDI_STATUS_B1_MASK (FTDI_RS_BI) | 604 | #define FTDI_STATUS_B1_MASK (FTDI_RS_BI) |
@@ -609,7 +609,6 @@ struct ftdi_private { | |||
609 | 609 | ||
610 | /* function prototypes for a FTDI serial converter */ | 610 | /* function prototypes for a FTDI serial converter */ |
611 | static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id); | 611 | static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id); |
612 | static int ftdi_sio_attach (struct usb_serial *serial); | ||
613 | static void ftdi_shutdown (struct usb_serial *serial); | 612 | static void ftdi_shutdown (struct usb_serial *serial); |
614 | static int ftdi_sio_port_probe (struct usb_serial_port *port); | 613 | static int ftdi_sio_port_probe (struct usb_serial_port *port); |
615 | static int ftdi_sio_port_remove (struct usb_serial_port *port); | 614 | static int ftdi_sio_port_remove (struct usb_serial_port *port); |
@@ -663,7 +662,6 @@ static struct usb_serial_driver ftdi_sio_device = { | |||
663 | .ioctl = ftdi_ioctl, | 662 | .ioctl = ftdi_ioctl, |
664 | .set_termios = ftdi_set_termios, | 663 | .set_termios = ftdi_set_termios, |
665 | .break_ctl = ftdi_break_ctl, | 664 | .break_ctl = ftdi_break_ctl, |
666 | .attach = ftdi_sio_attach, | ||
667 | .shutdown = ftdi_shutdown, | 665 | .shutdown = ftdi_shutdown, |
668 | }; | 666 | }; |
669 | 667 | ||
@@ -1149,7 +1147,9 @@ static int create_sysfs_attrs(struct usb_serial_port *port) | |||
1149 | dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]); | 1147 | dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]); |
1150 | retval = device_create_file(&port->dev, &dev_attr_event_char); | 1148 | retval = device_create_file(&port->dev, &dev_attr_event_char); |
1151 | if ((!retval) && | 1149 | if ((!retval) && |
1152 | (priv->chip_type == FT232BM || priv->chip_type == FT2232C)) { | 1150 | (priv->chip_type == FT232BM || |
1151 | priv->chip_type == FT2232C || | ||
1152 | priv->chip_type == FT232RL)) { | ||
1153 | retval = device_create_file(&port->dev, | 1153 | retval = device_create_file(&port->dev, |
1154 | &dev_attr_latency_timer); | 1154 | &dev_attr_latency_timer); |
1155 | } | 1155 | } |
@@ -1198,6 +1198,8 @@ static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id | |||
1198 | static int ftdi_sio_port_probe(struct usb_serial_port *port) | 1198 | static int ftdi_sio_port_probe(struct usb_serial_port *port) |
1199 | { | 1199 | { |
1200 | struct ftdi_private *priv; | 1200 | struct ftdi_private *priv; |
1201 | struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial); | ||
1202 | |||
1201 | 1203 | ||
1202 | dbg("%s",__FUNCTION__); | 1204 | dbg("%s",__FUNCTION__); |
1203 | 1205 | ||
@@ -1214,6 +1216,9 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) | |||
1214 | than queue a task to deliver them */ | 1216 | than queue a task to deliver them */ |
1215 | priv->flags = ASYNC_LOW_LATENCY; | 1217 | priv->flags = ASYNC_LOW_LATENCY; |
1216 | 1218 | ||
1219 | if (quirk && quirk->port_probe) | ||
1220 | quirk->port_probe(priv); | ||
1221 | |||
1217 | /* Increase the size of read buffers */ | 1222 | /* Increase the size of read buffers */ |
1218 | kfree(port->bulk_in_buffer); | 1223 | kfree(port->bulk_in_buffer); |
1219 | port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL); | 1224 | port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL); |
@@ -1244,29 +1249,13 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) | |||
1244 | return 0; | 1249 | return 0; |
1245 | } | 1250 | } |
1246 | 1251 | ||
1247 | /* attach subroutine */ | ||
1248 | static int ftdi_sio_attach (struct usb_serial *serial) | ||
1249 | { | ||
1250 | /* Check for device requiring special set up. */ | ||
1251 | struct ftdi_sio_quirk *quirk = usb_get_serial_data(serial); | ||
1252 | |||
1253 | if (quirk && quirk->setup) | ||
1254 | quirk->setup(serial); | ||
1255 | |||
1256 | return 0; | ||
1257 | } /* ftdi_sio_attach */ | ||
1258 | |||
1259 | |||
1260 | /* Setup for the USB-UIRT device, which requires hardwired | 1252 | /* Setup for the USB-UIRT device, which requires hardwired |
1261 | * baudrate (38400 gets mapped to 312500) */ | 1253 | * baudrate (38400 gets mapped to 312500) */ |
1262 | /* Called from usbserial:serial_probe */ | 1254 | /* Called from usbserial:serial_probe */ |
1263 | static void ftdi_USB_UIRT_setup (struct usb_serial *serial) | 1255 | static void ftdi_USB_UIRT_setup (struct ftdi_private *priv) |
1264 | { | 1256 | { |
1265 | struct ftdi_private *priv; | ||
1266 | |||
1267 | dbg("%s",__FUNCTION__); | 1257 | dbg("%s",__FUNCTION__); |
1268 | 1258 | ||
1269 | priv = usb_get_serial_port_data(serial->port[0]); | ||
1270 | priv->flags |= ASYNC_SPD_CUST; | 1259 | priv->flags |= ASYNC_SPD_CUST; |
1271 | priv->custom_divisor = 77; | 1260 | priv->custom_divisor = 77; |
1272 | priv->force_baud = B38400; | 1261 | priv->force_baud = B38400; |
@@ -1274,13 +1263,10 @@ static void ftdi_USB_UIRT_setup (struct usb_serial *serial) | |||
1274 | 1263 | ||
1275 | /* Setup for the HE-TIRA1 device, which requires hardwired | 1264 | /* Setup for the HE-TIRA1 device, which requires hardwired |
1276 | * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled. */ | 1265 | * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled. */ |
1277 | static void ftdi_HE_TIRA1_setup (struct usb_serial *serial) | 1266 | static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv) |
1278 | { | 1267 | { |
1279 | struct ftdi_private *priv; | ||
1280 | |||
1281 | dbg("%s",__FUNCTION__); | 1268 | dbg("%s",__FUNCTION__); |
1282 | 1269 | ||
1283 | priv = usb_get_serial_port_data(serial->port[0]); | ||
1284 | priv->flags |= ASYNC_SPD_CUST; | 1270 | priv->flags |= ASYNC_SPD_CUST; |
1285 | priv->custom_divisor = 240; | 1271 | priv->custom_divisor = 240; |
1286 | priv->force_baud = B38400; | 1272 | priv->force_baud = B38400; |
@@ -1574,14 +1560,15 @@ static void ftdi_write_bulk_callback (struct urb *urb) | |||
1574 | struct ftdi_private *priv; | 1560 | struct ftdi_private *priv; |
1575 | int data_offset; /* will be 1 for the SIO and 0 otherwise */ | 1561 | int data_offset; /* will be 1 for the SIO and 0 otherwise */ |
1576 | unsigned long countback; | 1562 | unsigned long countback; |
1563 | int status = urb->status; | ||
1577 | 1564 | ||
1578 | /* free up the transfer buffer, as usb_free_urb() does not do this */ | 1565 | /* free up the transfer buffer, as usb_free_urb() does not do this */ |
1579 | kfree (urb->transfer_buffer); | 1566 | kfree (urb->transfer_buffer); |
1580 | 1567 | ||
1581 | dbg("%s - port %d", __FUNCTION__, port->number); | 1568 | dbg("%s - port %d", __FUNCTION__, port->number); |
1582 | 1569 | ||
1583 | if (urb->status) { | 1570 | if (status) { |
1584 | dbg("nonzero write bulk status received: %d", urb->status); | 1571 | dbg("nonzero write bulk status received: %d", status); |
1585 | return; | 1572 | return; |
1586 | } | 1573 | } |
1587 | 1574 | ||
@@ -1657,6 +1644,7 @@ static void ftdi_read_bulk_callback (struct urb *urb) | |||
1657 | struct ftdi_private *priv; | 1644 | struct ftdi_private *priv; |
1658 | unsigned long countread; | 1645 | unsigned long countread; |
1659 | unsigned long flags; | 1646 | unsigned long flags; |
1647 | int status = urb->status; | ||
1660 | 1648 | ||
1661 | if (urb->number_of_packets > 0) { | 1649 | if (urb->number_of_packets > 0) { |
1662 | err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__, | 1650 | err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__, |
@@ -1685,9 +1673,10 @@ static void ftdi_read_bulk_callback (struct urb *urb) | |||
1685 | err("%s - Not my urb!", __FUNCTION__); | 1673 | err("%s - Not my urb!", __FUNCTION__); |
1686 | } | 1674 | } |
1687 | 1675 | ||
1688 | if (urb->status) { | 1676 | if (status) { |
1689 | /* This will happen at close every time so it is a dbg not an err */ | 1677 | /* This will happen at close every time so it is a dbg not an err */ |
1690 | dbg("(this is ok on close) nonzero read bulk status received: %d", urb->status); | 1678 | dbg("(this is ok on close) nonzero read bulk status received: " |
1679 | "%d", status); | ||
1691 | return; | 1680 | return; |
1692 | } | 1681 | } |
1693 | 1682 | ||