diff options
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
| -rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 129 | 
1 files changed, 99 insertions, 30 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index c45f9c0a1b3..8a3813be1b2 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -33,7 +33,6 @@  #include <linux/kernel.h>  #include <linux/errno.h> -#include <linux/init.h>  #include <linux/slab.h>  #include <linux/tty.h>  #include <linux/tty_driver.h> @@ -145,7 +144,7 @@ static struct ftdi_sio_quirk ftdi_8u2232c_quirk = {   * Device ID not listed? Test it using   * /sys/bus/usb-serial/drivers/ftdi_sio/new_id and send a patch or report.   */ -static struct usb_device_id id_table_combined [] = { +static const struct usb_device_id id_table_combined[] = {  	{ USB_DEVICE(FTDI_VID, FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) }, @@ -153,6 +152,7 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_NXTCAM_PID) }, +	{ USB_DEVICE(FTDI_VID, FTDI_EV3CON_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_1_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_2_PID) }, @@ -192,6 +192,8 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },  	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_SPROG_II) }, +	{ USB_DEVICE(FTDI_VID, FTDI_TAGSYS_LP101_PID) }, +	{ USB_DEVICE(FTDI_VID, FTDI_TAGSYS_P200X_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_LENZ_LIUSB_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) }, @@ -578,6 +580,8 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_TIAO_UMPA_PID),  		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, +	{ USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID), +		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },  	/*  	 * ELV devices:  	 */ @@ -716,7 +720,8 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) }, -	{ USB_DEVICE(TESTO_VID, TESTO_USB_INTERFACE_PID) }, +	{ USB_DEVICE(TESTO_VID, TESTO_1_PID) }, +	{ USB_DEVICE(TESTO_VID, TESTO_3_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_GAMMA_SCOUT_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13M_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) }, @@ -904,6 +909,44 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) },  	/* Crucible Devices */  	{ USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) }, +	{ USB_DEVICE(FTDI_VID, FTDI_Z3X_PID) }, +	/* Cressi Devices */ +	{ USB_DEVICE(FTDI_VID, FTDI_CRESSI_PID) }, +	/* Brainboxes Devices */ +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_001_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_012_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_023_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_034_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_101_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_1_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_2_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_3_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_4_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_5_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_6_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_7_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_8_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_257_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_1_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_2_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_3_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_4_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_313_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_324_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_1_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_2_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_357_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_1_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_2_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_3_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_701_1_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_701_2_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_1_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_2_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_3_PID) }, +	{ USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_4_PID) }, +	/* Infineon Devices */ +	{ USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) },  	{ }					/* Terminating entry */  }; @@ -1526,14 +1569,17 @@ static void ftdi_set_max_packet_size(struct usb_serial_port *port)  	struct usb_device *udev = serial->dev;  	struct usb_interface *interface = serial->interface; -	struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc; +	struct usb_endpoint_descriptor *ep_desc;  	unsigned num_endpoints; -	int i; +	unsigned i;  	num_endpoints = interface->cur_altsetting->desc.bNumEndpoints;  	dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints); +	if (!num_endpoints) +		return; +  	/* NOTE: some customers have programmed FT232R/FT245R devices  	 * with an endpoint size of 0 - not good.  In this case, we  	 * want to override the endpoint descriptor setting and use a @@ -1694,11 +1740,8 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)  	priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL); -	if (!priv) { -		dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__, -					sizeof(struct ftdi_private)); +	if (!priv)  		return -ENOMEM; -	}  	mutex_init(&priv->cfg_lock); @@ -1966,8 +2009,16 @@ static int ftdi_process_packet(struct usb_serial_port *port,  			port->icount.dsr++;  		if (diff_status & FTDI_RS0_RI)  			port->icount.rng++; -		if (diff_status & FTDI_RS0_RLSD) +		if (diff_status & FTDI_RS0_RLSD) { +			struct tty_struct *tty; +  			port->icount.dcd++; +			tty = tty_port_tty_get(&port->port); +			if (tty) +				usb_serial_handle_dcd_change(port, tty, +						status & FTDI_RS0_RLSD); +			tty_kref_put(tty); +		}  		wake_up_interruptible(&port->port.delta_msr_wait);  		priv->prev_status = status; @@ -2114,6 +2165,30 @@ static void ftdi_set_termios(struct tty_struct *tty,  		termios->c_cflag |= CRTSCTS;  	} +	/* +	 * All FTDI UART chips are limited to CS7/8. We shouldn't pretend to +	 * support CS5/6 and revert the CSIZE setting instead. +	 * +	 * CS5 however is used to control some smartcard readers which abuse +	 * this limitation to switch modes. Original FTDI chips fall back to +	 * eight data bits. +	 * +	 * TODO: Implement a quirk to only allow this with mentioned +	 *       readers. One I know of (Argolis Smartreader V1) +	 *       returns "USB smartcard server" as iInterface string. +	 *       The vendor didn't bother with a custom VID/PID of +	 *       course. +	 */ +	if (C_CSIZE(tty) == CS6) { +		dev_warn(ddev, "requested CSIZE setting not supported\n"); + +		termios->c_cflag &= ~CSIZE; +		if (old_termios) +			termios->c_cflag |= old_termios->c_cflag & CSIZE; +		else +			termios->c_cflag |= CS8; +	} +  	cflag = termios->c_cflag;  	if (!old_termios) @@ -2150,19 +2225,19 @@ no_skip:  	} else {  		urb_value |= FTDI_SIO_SET_DATA_PARITY_NONE;  	} -	if (cflag & CSIZE) { -		switch (cflag & CSIZE) { -		case CS7: -			urb_value |= 7; -			dev_dbg(ddev, "Setting CS7\n"); -			break; -		case CS8: -			urb_value |= 8; -			dev_dbg(ddev, "Setting CS8\n"); -			break; -		default: -			dev_err(ddev, "CSIZE was set but not CS7-CS8\n"); -		} +	switch (cflag & CSIZE) { +	case CS5: +		dev_dbg(ddev, "Setting CS5 quirk\n"); +		break; +	case CS7: +		urb_value |= 7; +		dev_dbg(ddev, "Setting CS7\n"); +		break; +	default: +	case CS8: +		urb_value |= 8; +		dev_dbg(ddev, "Setting CS8\n"); +		break;  	}  	/* This is needed by the break command since it uses the same command @@ -2363,8 +2438,6 @@ static int ftdi_ioctl(struct tty_struct *tty,  {  	struct usb_serial_port *port = tty->driver_data; -	dev_dbg(&port->dev, "%s cmd 0x%04x\n", __func__, cmd); -  	/* Based on code from acm.c and others */  	switch (cmd) { @@ -2381,11 +2454,7 @@ static int ftdi_ioctl(struct tty_struct *tty,  	default:  		break;  	} -	/* This is not necessarily an error - turns out the higher layers -	 * will do some ioctls themselves (see comment above) -	 */ -	dev_dbg(&port->dev, "%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h\n", -		__func__, cmd); +  	return -ENOIOCTLCMD;  }  | 
