USB-serial updates for 5.13-rc1

Here are the USB-serial updates for 5.13-rc1, including:
 
  - better type detection for pl2303
  - support for more line speeds for pl2303 (TA/TB)
  - fixed CSIZE handling for the new xr driver
  - core support for multi-interface functions
  - TIOCGSERIAL and TIOCSSERIAL fixes
  - generic TIOCSSERIAL support (e.g. for closing_wait)
  - fixed return value for unsupported ioctls
  - support for gpio valid masks in cp210x
  - drain-delay fixes and improvements
  - support for multi-port devices for xr
  - generalisation of the xr driver to support three new device classes
    (XR21B142X, XR21B1411 and XR2280X)
 
 Included are also various clean ups.
 
 All have been in linux-next with no reported issues.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQQHbPq+cpGvN/peuzMLxc3C7H1lCAUCYIE2iwAKCRALxc3C7H1l
 CFJsAQCd6rX6VyteR6RUmmTjmGDyRwxsXGniw9bf36dzhlKncwEAga2E+47FGHYm
 YiNQzfcETfjGO21usS1BWhNvzf/gsgs=
 =1FU1
 -----END PGP SIGNATURE-----

Merge tag 'usb-serial-5.13-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-next

Johan writes:

USB-serial updates for 5.13-rc1

Here are the USB-serial updates for 5.13-rc1, including:

 - better type detection for pl2303
 - support for more line speeds for pl2303 (TA/TB)
 - fixed CSIZE handling for the new xr driver
 - core support for multi-interface functions
 - TIOCGSERIAL and TIOCSSERIAL fixes
 - generic TIOCSSERIAL support (e.g. for closing_wait)
 - fixed return value for unsupported ioctls
 - support for gpio valid masks in cp210x
 - drain-delay fixes and improvements
 - support for multi-port devices for xr
 - generalisation of the xr driver to support three new device classes
   (XR21B142X, XR21B1411 and XR2280X)

Included are also various clean ups.

All have been in linux-next with no reported issues.

* tag 'usb-serial-5.13-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial: (72 commits)
  USB: cdc-acm: add more Maxlinear/Exar models to ignore list
  USB: serial: xr: add copyright notice
  USB: serial: xr: reset FIFOs on open
  USB: serial: xr: add support for XR22801, XR22802, XR22804
  USB: serial: xr: add support for XR21B1411
  USB: serial: xr: add support for XR21B1421, XR21B1422 and XR21B1424
  USB: serial: xr: add type abstraction
  USB: serial: xr: drop type prefix from shared defines
  USB: serial: xr: move pin configuration to probe
  USB: serial: xr: rename GPIO-pin defines
  USB: serial: xr: rename GPIO-mode defines
  USB: serial: xr: add support for XR21V1412 and XR21V1414
  USB: serial: ti_usb_3410_5052: clean up termios CSIZE handling
  USB: serial: ti_usb_3410_5052: use kernel types consistently
  USB: serial: ti_usb_3410_5052: add port-command helpers
  USB: serial: ti_usb_3410_5052: clean up vendor-request helpers
  USB: serial: ti_usb_3410_5052: drop unnecessary packed attributes
  USB: serial: io_ti: drop unnecessary packed attributes
  USB: serial: io_ti: use kernel types consistently
  USB: serial: io_ti: add read-port-command helper
  ...
This commit is contained in:
Greg Kroah-Hartman 2021-04-22 11:19:49 +02:00
commit 7e25c20df4
28 changed files with 1149 additions and 913 deletions

View File

@ -1913,9 +1913,17 @@ static const struct usb_device_id acm_ids[] = {
#endif
#if IS_ENABLED(CONFIG_USB_SERIAL_XR)
{ USB_DEVICE(0x04e2, 0x1410), /* Ignore XR21V141X USB to Serial converter */
.driver_info = IGNORE_DEVICE,
},
{ USB_DEVICE(0x04e2, 0x1400), .driver_info = IGNORE_DEVICE },
{ USB_DEVICE(0x04e2, 0x1401), .driver_info = IGNORE_DEVICE },
{ USB_DEVICE(0x04e2, 0x1402), .driver_info = IGNORE_DEVICE },
{ USB_DEVICE(0x04e2, 0x1403), .driver_info = IGNORE_DEVICE },
{ USB_DEVICE(0x04e2, 0x1410), .driver_info = IGNORE_DEVICE },
{ USB_DEVICE(0x04e2, 0x1411), .driver_info = IGNORE_DEVICE },
{ USB_DEVICE(0x04e2, 0x1412), .driver_info = IGNORE_DEVICE },
{ USB_DEVICE(0x04e2, 0x1414), .driver_info = IGNORE_DEVICE },
{ USB_DEVICE(0x04e2, 0x1420), .driver_info = IGNORE_DEVICE },
{ USB_DEVICE(0x04e2, 0x1422), .driver_info = IGNORE_DEVICE },
{ USB_DEVICE(0x04e2, 0x1424), .driver_info = IGNORE_DEVICE },
#endif
/*Samsung phone in firmware update mode */

View File

@ -385,18 +385,6 @@ static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)
return result;
}
static int ark3116_get_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
ss->type = PORT_16654;
ss->line = port->minor;
ss->port = port->port_number;
ss->baud_base = 460800;
return 0;
}
static int ark3116_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
@ -633,7 +621,6 @@ static struct usb_serial_driver ark3116_device = {
.port_probe = ark3116_port_probe,
.port_remove = ark3116_port_remove,
.set_termios = ark3116_set_termios,
.get_serial = ark3116_get_serial_info,
.tiocmget = ark3116_tiocmget,
.tiocmset = ark3116_tiocmset,
.tiocmiwait = usb_serial_generic_tiocmiwait,

View File

@ -1410,17 +1410,6 @@ static void cp210x_break_ctl(struct tty_struct *tty, int break_state)
}
#ifdef CONFIG_GPIOLIB
static int cp210x_gpio_request(struct gpio_chip *gc, unsigned int offset)
{
struct usb_serial *serial = gpiochip_get_data(gc);
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
if (priv->gpio_altfunc & BIT(offset))
return -ENODEV;
return 0;
}
static int cp210x_gpio_get(struct gpio_chip *gc, unsigned int gpio)
{
struct usb_serial *serial = gpiochip_get_data(gc);
@ -1549,6 +1538,24 @@ static int cp210x_gpio_set_config(struct gpio_chip *gc, unsigned int gpio,
return -ENOTSUPP;
}
static int cp210x_gpio_init_valid_mask(struct gpio_chip *gc,
unsigned long *valid_mask, unsigned int ngpios)
{
struct usb_serial *serial = gpiochip_get_data(gc);
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
struct device *dev = &serial->interface->dev;
unsigned long altfunc_mask = priv->gpio_altfunc;
bitmap_complement(valid_mask, &altfunc_mask, ngpios);
if (bitmap_empty(valid_mask, ngpios))
dev_dbg(dev, "no pin configured for GPIO\n");
else
dev_dbg(dev, "GPIO.%*pbl configured for GPIO\n", ngpios,
valid_mask);
return 0;
}
/*
* This function is for configuring GPIO using shared pins, where other signals
* are made unavailable by configuring the use of GPIO. This is believed to be
@ -1786,13 +1793,13 @@ static int cp210x_gpio_init(struct usb_serial *serial)
return result;
priv->gc.label = "cp210x";
priv->gc.request = cp210x_gpio_request;
priv->gc.get_direction = cp210x_gpio_direction_get;
priv->gc.direction_input = cp210x_gpio_direction_input;
priv->gc.direction_output = cp210x_gpio_direction_output;
priv->gc.get = cp210x_gpio_get;
priv->gc.set = cp210x_gpio_set;
priv->gc.set_config = cp210x_gpio_set_config;
priv->gc.init_valid_mask = cp210x_gpio_init_valid_mask;
priv->gc.owner = THIS_MODULE;
priv->gc.parent = &serial->interface->dev;
priv->gc.base = -1;

View File

@ -820,17 +820,12 @@ static int f81232_carrier_raised(struct usb_serial_port *port)
return 0;
}
static int f81232_get_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
static void f81232_get_serial(struct tty_struct *tty, struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
struct f81232_private *priv = usb_get_serial_port_data(port);
ss->type = PORT_16550A;
ss->line = port->minor;
ss->port = port->port_number;
ss->baud_base = priv->baud_base;
return 0;
}
static void f81232_interrupt_work(struct work_struct *work)
@ -953,7 +948,6 @@ static int f81232_port_probe(struct usb_serial_port *port)
usb_set_serial_port_data(port, priv);
port->port.drain_delay = 256;
priv->port = port;
return 0;
@ -1021,7 +1015,7 @@ static struct usb_serial_driver f81232_device = {
.close = f81232_close,
.dtr_rts = f81232_dtr_rts,
.carrier_raised = f81232_carrier_raised,
.get_serial = f81232_get_serial_info,
.get_serial = f81232_get_serial,
.break_ctl = f81232_break_ctl,
.set_termios = f81232_set_termios,
.tiocmget = f81232_tiocmget,
@ -1046,7 +1040,7 @@ static struct usb_serial_driver f81534a_device = {
.close = f81232_close,
.dtr_rts = f81232_dtr_rts,
.carrier_raised = f81232_carrier_raised,
.get_serial = f81232_get_serial_info,
.get_serial = f81232_get_serial,
.break_ctl = f81232_break_ctl,
.set_termios = f81232_set_termios,
.tiocmget = f81232_tiocmget,

View File

@ -1140,19 +1140,14 @@ static void f81534_close(struct usb_serial_port *port)
mutex_unlock(&serial_priv->urb_mutex);
}
static int f81534_get_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
static void f81534_get_serial_info(struct tty_struct *tty, struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
struct f81534_port_private *port_priv;
port_priv = usb_get_serial_port_data(port);
ss->type = PORT_16550A;
ss->port = port->port_number;
ss->line = port->minor;
ss->baud_base = port_priv->baud_base;
return 0;
}
static void f81534_process_per_serial_block(struct usb_serial_port *port,

View File

@ -1082,8 +1082,7 @@ static int ftdi_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
static int ftdi_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg);
static int get_serial_info(struct tty_struct *tty,
struct serial_struct *ss);
static void get_serial_info(struct tty_struct *tty, struct serial_struct *ss);
static int set_serial_info(struct tty_struct *tty,
struct serial_struct *ss);
static void ftdi_break_ctl(struct tty_struct *tty, int break_state);
@ -1477,8 +1476,7 @@ static int read_latency_timer(struct usb_serial_port *port)
return 0;
}
static int get_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
static void get_serial_info(struct tty_struct *tty, struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
@ -1486,49 +1484,34 @@ static int get_serial_info(struct tty_struct *tty,
ss->flags = priv->flags;
ss->baud_base = priv->baud_base;
ss->custom_divisor = priv->custom_divisor;
return 0;
}
static int set_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
struct ftdi_private old_priv;
int old_flags, old_divisor;
mutex_lock(&priv->cfg_lock);
old_priv = *priv;
/* Do error checking and permission checking */
if (!capable(CAP_SYS_ADMIN)) {
if ((ss->flags ^ priv->flags) & ~ASYNC_USR_MASK) {
mutex_unlock(&priv->cfg_lock);
return -EPERM;
}
priv->flags = ((priv->flags & ~ASYNC_USR_MASK) |
(ss->flags & ASYNC_USR_MASK));
priv->custom_divisor = ss->custom_divisor;
goto check_and_exit;
}
if (ss->baud_base != priv->baud_base) {
mutex_unlock(&priv->cfg_lock);
return -EINVAL;
}
old_flags = priv->flags;
old_divisor = priv->custom_divisor;
/* Make the changes - these are privileged changes! */
priv->flags = ((priv->flags & ~ASYNC_FLAGS) |
(ss->flags & ASYNC_FLAGS));
priv->flags = ss->flags & ASYNC_FLAGS;
priv->custom_divisor = ss->custom_divisor;
check_and_exit:
write_latency_timer(port);
if ((priv->flags ^ old_priv.flags) & ASYNC_SPD_MASK ||
if ((priv->flags ^ old_flags) & ASYNC_SPD_MASK ||
((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST &&
priv->custom_divisor != old_priv.custom_divisor)) {
priv->custom_divisor != old_divisor)) {
/* warn about deprecation unless clearing */
if (priv->flags & ASYNC_SPD_MASK)

View File

@ -263,39 +263,9 @@ static const struct divisor_table_entry divisor_table[] = {
static atomic_t CmdUrbs = ATOMIC_INIT(0);
/* local function prototypes */
/* function prototypes */
/* function prototypes for all URB callbacks */
static void edge_interrupt_callback(struct urb *urb);
static void edge_bulk_in_callback(struct urb *urb);
static void edge_bulk_out_data_callback(struct urb *urb);
static void edge_bulk_out_cmd_callback(struct urb *urb);
/* function prototypes for the usbserial callbacks */
static int edge_open(struct tty_struct *tty, struct usb_serial_port *port);
static void edge_close(struct usb_serial_port *port);
static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
static int edge_write_room(struct tty_struct *tty);
static int edge_chars_in_buffer(struct tty_struct *tty);
static void edge_throttle(struct tty_struct *tty);
static void edge_unthrottle(struct tty_struct *tty);
static void edge_set_termios(struct tty_struct *tty,
struct usb_serial_port *port,
struct ktermios *old_termios);
static int edge_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg);
static void edge_break(struct tty_struct *tty, int break_state);
static int edge_tiocmget(struct tty_struct *tty);
static int edge_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
static int edge_startup(struct usb_serial *serial);
static void edge_disconnect(struct usb_serial *serial);
static void edge_release(struct usb_serial *serial);
static int edge_port_probe(struct usb_serial_port *port);
static void edge_port_remove(struct usb_serial_port *port);
/* function prototypes for all of our local functions */
static void process_rcvd_data(struct edgeport_serial *edge_serial,
unsigned char *buffer, __u16 bufferLength);
@ -309,8 +279,6 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData,
static int send_iosp_ext_cmd(struct edgeport_port *edge_port, __u8 command,
__u8 param);
static int calc_baud_rate_divisor(struct device *dev, int baud_rate, int *divisor);
static int send_cmd_write_baud_rate(struct edgeport_port *edge_port,
int baudRate);
static void change_port_settings(struct tty_struct *tty,
struct edgeport_port *edge_port,
struct ktermios *old_termios);
@ -321,19 +289,8 @@ static int write_cmd_usb(struct edgeport_port *edge_port,
static void send_more_port_data(struct edgeport_serial *edge_serial,
struct edgeport_port *edge_port);
static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr,
__u16 length, const __u8 *data);
static int rom_read(struct usb_serial *serial, __u16 extAddr, __u16 addr,
__u16 length, __u8 *data);
static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr,
__u16 length, const __u8 *data);
static void get_manufacturing_desc(struct edgeport_serial *edge_serial);
static void get_boot_desc(struct edgeport_serial *edge_serial);
static void load_application_firmware(struct edgeport_serial *edge_serial);
static void unicode_to_ascii(char *string, int buflen,
__le16 *unicode, int unicode_size);
/* ************************************************************************ */
/* ************************************************************************ */
@ -1637,24 +1594,6 @@ static int edge_tiocmget(struct tty_struct *tty)
return result;
}
static int get_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
ss->type = PORT_16550A;
ss->line = edge_port->port->minor;
ss->port = edge_port->port->port_number;
ss->irq = 0;
ss->xmit_fifo_size = edge_port->maxTxCredits;
ss->baud_base = 9600;
ss->close_delay = 5*HZ;
ss->closing_wait = 30*HZ;
return 0;
}
/*****************************************************************************
* SerialIoctl
* this function handles any ioctl calls to the driver
@ -3116,7 +3055,6 @@ static struct usb_serial_driver edgeport_2port_device = {
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
.get_serial = get_serial_info,
.tiocmiwait = usb_serial_generic_tiocmiwait,
.get_icount = usb_serial_generic_get_icount,
.write = edge_write,
@ -3152,7 +3090,6 @@ static struct usb_serial_driver edgeport_4port_device = {
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
.get_serial = get_serial_info,
.tiocmiwait = usb_serial_generic_tiocmiwait,
.get_icount = usb_serial_generic_get_icount,
.write = edge_write,
@ -3188,7 +3125,6 @@ static struct usb_serial_driver edgeport_8port_device = {
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
.get_serial = get_serial_info,
.tiocmiwait = usb_serial_generic_tiocmiwait,
.get_icount = usb_serial_generic_get_icount,
.write = edge_write,
@ -3224,7 +3160,6 @@ static struct usb_serial_driver epic_device = {
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
.get_serial = get_serial_info,
.tiocmiwait = usb_serial_generic_tiocmiwait,
.get_icount = usb_serial_generic_get_icount,
.write = edge_write,

View File

@ -10,7 +10,6 @@
#if !defined(_IO_EDGEPORT_H_)
#define _IO_EDGEPORT_H_
#define MAX_RS232_PORTS 8 /* Max # of RS-232 ports per device */
/* typedefs that the insideout headers need */
@ -21,57 +20,8 @@
#define HIGH8(a) ((unsigned char)((a & 0xff00) >> 8))
#endif
#ifndef __KERNEL__
#define __KERNEL__
#endif
#include "io_usbvend.h"
/* The following table is used to map the USBx port number to
* the device serial number (or physical USB path), */
#define MAX_EDGEPORTS 64
struct comMapper {
char SerialNumber[MAX_SERIALNUMBER_LEN+1]; /* Serial number/usb path */
int numPorts; /* Number of ports */
int Original[MAX_RS232_PORTS]; /* Port numbers set by IOCTL */
int Port[MAX_RS232_PORTS]; /* Actual used port numbers */
};
#define EDGEPORT_CONFIG_DEVICE "/proc/edgeport"
/* /proc/edgeport Interface
* This interface uses read/write/lseek interface to talk to the edgeport driver
* the following read functions are supported: */
#define PROC_GET_MAPPING_TO_PATH 1
#define PROC_GET_COM_ENTRY 2
#define PROC_GET_EDGE_MANUF_DESCRIPTOR 3
#define PROC_GET_BOOT_DESCRIPTOR 4
#define PROC_GET_PRODUCT_INFO 5
#define PROC_GET_STRINGS 6
#define PROC_GET_CURRENT_COM_MAPPING 7
/* The parameters to the lseek() for the read is: */
#define PROC_READ_SETUP(Command, Argument) ((Command) + ((Argument)<<8))
/* the following write functions are supported: */
#define PROC_SET_COM_MAPPING 1
#define PROC_SET_COM_ENTRY 2
/* The following structure is passed to the write */
struct procWrite {
int Command;
union {
struct comMapper Entry;
int ComMappingBasedOnUSBPort; /* Boolean value */
} u;
};
/*
* Product information read from the Edgeport
*/
@ -108,22 +58,4 @@ struct edgeport_product_info {
struct edge_compatibility_bits Epic;
};
/*
* Edgeport Stringblock String locations
*/
#define EDGESTRING_MANUFNAME 1 /* Manufacture Name */
#define EDGESTRING_PRODNAME 2 /* Product Name */
#define EDGESTRING_SERIALNUM 3 /* Serial Number */
#define EDGESTRING_ASSEMNUM 4 /* Assembly Number */
#define EDGESTRING_OEMASSEMNUM 5 /* OEM Assembly Number */
#define EDGESTRING_MANUFDATE 6 /* Manufacture Date */
#define EDGESTRING_ORIGSERIALNUM 7 /* Serial Number */
struct string_block {
__u16 NumStrings; /* Number of strings in block */
__u16 Strings[1]; /* Start of string block */
};
#endif

View File

@ -60,14 +60,12 @@
#define EDGE_READ_URB_STOPPING 1
#define EDGE_READ_URB_STOPPED 2
#define EDGE_CLOSING_WAIT 4000 /* in .01 sec */
/* Product information read from the Edgeport */
struct product_info {
int TiMode; /* Current TI Mode */
__u8 hardware_type; /* Type of hardware */
} __attribute__((packed));
u8 hardware_type; /* Type of hardware */
} __packed;
/*
* Edgeport firmware header
@ -89,13 +87,13 @@ struct edgeport_fw_hdr {
} __packed;
struct edgeport_port {
__u16 uart_base;
__u16 dma_address;
__u8 shadow_msr;
__u8 shadow_mcr;
__u8 shadow_lsr;
__u8 lsr_mask;
__u32 ump_read_timeout; /*
u16 uart_base;
u16 dma_address;
u8 shadow_msr;
u8 shadow_mcr;
u8 shadow_lsr;
u8 lsr_mask;
u32 ump_read_timeout; /*
* Number of milliseconds the UMP will
* wait without data before completing
* a read short
@ -106,7 +104,7 @@ struct edgeport_port {
struct edgeport_serial *edge_serial;
struct usb_serial_port *port;
__u8 bUartMode; /* Port type, 0: RS232, etc. */
u8 bUartMode; /* Port type, 0: RS232, etc. */
spinlock_t ep_lock;
int ep_read_urb_state;
int ep_write_urb_in_use;
@ -211,7 +209,6 @@ static const struct usb_device_id id_table_combined[] = {
MODULE_DEVICE_TABLE(usb, id_table_combined);
static int closing_wait = EDGE_CLOSING_WAIT;
static bool ignore_cpu_rev;
static int default_uart_mode; /* RS232 */
@ -255,8 +252,8 @@ static int edge_remove_sysfs_attrs(struct usb_serial_port *port);
#define TI_VSEND_TIMEOUT_DEFAULT 1000
#define TI_VSEND_TIMEOUT_FW_DOWNLOAD 10000
static int ti_vread_sync(struct usb_device *dev, __u8 request,
__u16 value, __u16 index, u8 *data, int size)
static int ti_vread_sync(struct usb_device *dev, u8 request, u16 value,
u16 index, void *data, int size)
{
int status;
@ -274,7 +271,7 @@ static int ti_vread_sync(struct usb_device *dev, __u8 request,
}
static int ti_vsend_sync(struct usb_device *dev, u8 request, u16 value,
u16 index, u8 *data, int size, int timeout)
u16 index, void *data, int size, int timeout)
{
int status;
@ -287,27 +284,30 @@ static int ti_vsend_sync(struct usb_device *dev, u8 request, u16 value,
return 0;
}
static int send_cmd(struct usb_device *dev, __u8 command,
__u8 moduleid, __u16 value, u8 *data,
int size)
static int read_port_cmd(struct usb_serial_port *port, u8 command, u16 value,
void *data, int size)
{
return ti_vsend_sync(dev, command, value, moduleid, data, size,
TI_VSEND_TIMEOUT_DEFAULT);
return ti_vread_sync(port->serial->dev, command, value,
UMPM_UART1_PORT + port->port_number,
data, size);
}
static int send_port_cmd(struct usb_serial_port *port, u8 command, u16 value,
void *data, int size)
{
return ti_vsend_sync(port->serial->dev, command, value,
UMPM_UART1_PORT + port->port_number,
data, size, TI_VSEND_TIMEOUT_DEFAULT);
}
/* clear tx/rx buffers and fifo in TI UMP */
static int purge_port(struct usb_serial_port *port, __u16 mask)
static int purge_port(struct usb_serial_port *port, u16 mask)
{
int port_number = port->port_number;
dev_dbg(&port->dev, "%s - port %d, mask %x\n", __func__, port_number, mask);
return send_cmd(port->serial->dev,
UMPC_PURGE_PORT,
(__u8)(UMPM_UART1_PORT + port_number),
mask,
NULL,
0);
return send_port_cmd(port, UMPC_PURGE_PORT, mask, NULL, 0);
}
/**
@ -319,10 +319,10 @@ static int purge_port(struct usb_serial_port *port, __u16 mask)
* @buffer: pointer to input data buffer
*/
static int read_download_mem(struct usb_device *dev, int start_address,
int length, __u8 address_type, __u8 *buffer)
int length, u8 address_type, u8 *buffer)
{
int status = 0;
__u8 read_length;
u8 read_length;
u16 be_start_address;
dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, length);
@ -335,7 +335,7 @@ static int read_download_mem(struct usb_device *dev, int start_address,
if (length > 64)
read_length = 64;
else
read_length = (__u8)length;
read_length = (u8)length;
if (read_length > 1) {
dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, read_length);
@ -346,7 +346,7 @@ static int read_download_mem(struct usb_device *dev, int start_address,
*/
be_start_address = swab16((u16)start_address);
status = ti_vread_sync(dev, UMPC_MEMORY_READ,
(__u16)address_type,
(u16)address_type,
be_start_address,
buffer, read_length);
@ -368,7 +368,7 @@ static int read_download_mem(struct usb_device *dev, int start_address,
}
static int read_ram(struct usb_device *dev, int start_address,
int length, __u8 *buffer)
int length, u8 *buffer)
{
return read_download_mem(dev, start_address, length,
DTK_ADDR_SPACE_XDATA, buffer);
@ -376,7 +376,7 @@ static int read_ram(struct usb_device *dev, int start_address,
/* Read edgeport memory to a given block */
static int read_boot_mem(struct edgeport_serial *serial,
int start_address, int length, __u8 *buffer)
int start_address, int length, u8 *buffer)
{
int status = 0;
int i;
@ -384,7 +384,7 @@ static int read_boot_mem(struct edgeport_serial *serial,
for (i = 0; i < length; i++) {
status = ti_vread_sync(serial->serial->dev,
UMPC_MEMORY_READ, serial->TI_I2C_Type,
(__u16)(start_address+i), &buffer[i], 0x01);
(u16)(start_address+i), &buffer[i], 0x01);
if (status) {
dev_dbg(&serial->serial->dev->dev, "%s - ERROR %x\n", __func__, status);
return status;
@ -402,7 +402,7 @@ static int read_boot_mem(struct edgeport_serial *serial,
/* Write given block to TI EPROM memory */
static int write_boot_mem(struct edgeport_serial *serial,
int start_address, int length, __u8 *buffer)
int start_address, int length, u8 *buffer)
{
int status = 0;
int i;
@ -436,7 +436,7 @@ static int write_boot_mem(struct edgeport_serial *serial,
/* Write edgeport I2C memory to TI chip */
static int write_i2c_mem(struct edgeport_serial *serial,
int start_address, int length, __u8 address_type, __u8 *buffer)
int start_address, int length, u8 address_type, u8 *buffer)
{
struct device *dev = &serial->serial->dev->dev;
int status = 0;
@ -522,7 +522,7 @@ static int tx_active(struct edgeport_port *port)
{
int status;
struct out_endpoint_desc_block *oedb;
__u8 *lsr;
u8 *lsr;
int bytes_left = 0;
oedb = kmalloc(sizeof(*oedb), GFP_KERNEL);
@ -593,7 +593,7 @@ static int choose_config(struct usb_device *dev)
}
static int read_rom(struct edgeport_serial *serial,
int start_address, int length, __u8 *buffer)
int start_address, int length, u8 *buffer)
{
int status;
@ -611,7 +611,7 @@ static int read_rom(struct edgeport_serial *serial,
}
static int write_rom(struct edgeport_serial *serial, int start_address,
int length, __u8 *buffer)
int length, u8 *buffer)
{
if (serial->product_info.TiMode == TI_MODE_BOOT)
return write_boot_mem(serial, start_address, length,
@ -636,7 +636,7 @@ static int get_descriptor_addr(struct edgeport_serial *serial,
status = read_rom(serial,
start_address,
sizeof(struct ti_i2c_desc),
(__u8 *)rom_desc);
(u8 *)rom_desc);
if (status)
return 0;
@ -652,13 +652,13 @@ static int get_descriptor_addr(struct edgeport_serial *serial,
}
/* Validate descriptor checksum */
static int valid_csum(struct ti_i2c_desc *rom_desc, __u8 *buffer)
static int valid_csum(struct ti_i2c_desc *rom_desc, u8 *buffer)
{
__u16 i;
__u8 cs = 0;
u16 i;
u8 cs = 0;
for (i = 0; i < le16_to_cpu(rom_desc->Size); i++)
cs = (__u8)(cs + buffer[i]);
cs = (u8)(cs + buffer[i]);
if (cs != rom_desc->CheckSum) {
pr_debug("%s - Mismatch %x - %x", __func__, rom_desc->CheckSum, cs);
@ -674,8 +674,8 @@ static int check_i2c_image(struct edgeport_serial *serial)
int status = 0;
struct ti_i2c_desc *rom_desc;
int start_address = 2;
__u8 *buffer;
__u16 ttype;
u8 *buffer;
u16 ttype;
rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
if (!rom_desc)
@ -703,7 +703,7 @@ static int check_i2c_image(struct edgeport_serial *serial)
status = read_rom(serial,
start_address,
sizeof(struct ti_i2c_desc),
(__u8 *)rom_desc);
(u8 *)rom_desc);
if (status)
break;
@ -748,7 +748,7 @@ static int check_i2c_image(struct edgeport_serial *serial)
return status;
}
static int get_manuf_info(struct edgeport_serial *serial, __u8 *buffer)
static int get_manuf_info(struct edgeport_serial *serial, u8 *buffer)
{
int status;
int start_address;
@ -793,10 +793,10 @@ static int get_manuf_info(struct edgeport_serial *serial, __u8 *buffer)
/* Build firmware header used for firmware update */
static int build_i2c_fw_hdr(u8 *header, const struct firmware *fw)
{
__u8 *buffer;
u8 *buffer;
int buffer_size;
int i;
__u8 cs = 0;
u8 cs = 0;
struct ti_i2c_desc *i2c_header;
struct ti_i2c_image_header *img_header;
struct ti_i2c_firmware_rec *firmware_rec;
@ -840,7 +840,7 @@ static int build_i2c_fw_hdr(u8 *header, const struct firmware *fw)
le16_to_cpu(img_header->Length));
for (i=0; i < buffer_size; i++) {
cs = (__u8)(cs + buffer[i]);
cs = (u8)(cs + buffer[i]);
}
kfree(buffer);
@ -916,7 +916,7 @@ static int bulk_xfer(struct usb_serial *serial, void *buffer,
}
/* Download given firmware image to the device (IN BOOT MODE) */
static int download_code(struct edgeport_serial *serial, __u8 *image,
static int download_code(struct edgeport_serial *serial, u8 *image,
int image_length)
{
int status = 0;
@ -1090,7 +1090,7 @@ static int do_download_mode(struct edgeport_serial *serial,
if (!ti_manuf_desc)
return -ENOMEM;
status = get_manuf_info(serial, (__u8 *)ti_manuf_desc);
status = get_manuf_info(serial, (u8 *)ti_manuf_desc);
if (status) {
kfree(ti_manuf_desc);
return status;
@ -1135,7 +1135,7 @@ static int do_download_mode(struct edgeport_serial *serial,
status = read_rom(serial, start_address +
sizeof(struct ti_i2c_desc),
sizeof(struct ti_i2c_firmware_rec),
(__u8 *)firmware_version);
(u8 *)firmware_version);
if (status) {
kfree(firmware_version);
kfree(rom_desc);
@ -1261,8 +1261,8 @@ static int do_download_mode(struct edgeport_serial *serial,
if (start_address != 0) {
#define HEADER_SIZE (sizeof(struct ti_i2c_desc) + \
sizeof(struct ti_i2c_firmware_rec))
__u8 *header;
__u8 *vheader;
u8 *header;
u8 *vheader;
header = kmalloc(HEADER_SIZE, GFP_KERNEL);
if (!header) {
@ -1408,8 +1408,8 @@ static int do_boot_mode(struct edgeport_serial *serial,
if (!check_i2c_image(serial)) {
struct ti_i2c_image_header *header;
int i;
__u8 cs = 0;
__u8 *buffer;
u8 cs = 0;
u8 *buffer;
int buffer_size;
/*
@ -1420,7 +1420,7 @@ static int do_boot_mode(struct edgeport_serial *serial,
if (!ti_manuf_desc)
return -ENOMEM;
status = get_manuf_info(serial, (__u8 *)ti_manuf_desc);
status = get_manuf_info(serial, (u8 *)ti_manuf_desc);
if (status) {
kfree(ti_manuf_desc);
goto stayinbootmode;
@ -1463,13 +1463,13 @@ static int do_boot_mode(struct edgeport_serial *serial,
for (i = sizeof(struct ti_i2c_image_header);
i < buffer_size; i++) {
cs = (__u8)(cs + buffer[i]);
cs = (u8)(cs + buffer[i]);
}
header = (struct ti_i2c_image_header *)buffer;
/* update length and checksum after padding */
header->Length = cpu_to_le16((__u16)(buffer_size -
header->Length = cpu_to_le16((u16)(buffer_size -
sizeof(struct ti_i2c_image_header)));
header->CheckSum = cs;
@ -1504,15 +1504,12 @@ static int do_boot_mode(struct edgeport_serial *serial,
static int ti_do_config(struct edgeport_port *port, int feature, int on)
{
int port_number = port->port->port_number;
on = !!on; /* 1 or 0 not bitmask */
return send_cmd(port->port->serial->dev,
feature, (__u8)(UMPM_UART1_PORT + port_number),
on, NULL, 0);
return send_port_cmd(port->port, feature, on, NULL, 0);
}
static int restore_mcr(struct edgeport_port *port, __u8 mcr)
static int restore_mcr(struct edgeport_port *port, u8 mcr)
{
int status = 0;
@ -1528,9 +1525,9 @@ static int restore_mcr(struct edgeport_port *port, __u8 mcr)
}
/* Convert TI LSR to standard UART flags */
static __u8 map_line_status(__u8 ti_lsr)
static u8 map_line_status(u8 ti_lsr)
{
__u8 lsr = 0;
u8 lsr = 0;
#define MAP_FLAG(flagUmp, flagUart) \
if (ti_lsr & flagUmp) \
@ -1548,7 +1545,7 @@ static __u8 map_line_status(__u8 ti_lsr)
return lsr;
}
static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
static void handle_new_msr(struct edgeport_port *edge_port, u8 msr)
{
struct async_icount *icount;
struct tty_struct *tty;
@ -1584,10 +1581,10 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
}
static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,
__u8 lsr, __u8 data)
u8 lsr, u8 data)
{
struct async_icount *icount;
__u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR |
u8 new_lsr = (u8)(lsr & (u8)(LSR_OVER_ERR | LSR_PAR_ERR |
LSR_FRM_ERR | LSR_BREAK));
dev_dbg(&edge_port->port->dev, "%s - %02x\n", __func__, new_lsr);
@ -1599,7 +1596,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,
* Parity and Framing errors only count if they
* occur exclusive of a break being received.
*/
new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK);
new_lsr &= (u8)(LSR_OVER_ERR | LSR_BREAK);
/* Place LSR data byte into Rx buffer */
if (lsr_data)
@ -1628,8 +1625,8 @@ static void edge_interrupt_callback(struct urb *urb)
int port_number;
int function;
int retval;
__u8 lsr;
__u8 msr;
u8 lsr;
u8 msr;
int status = urb->status;
switch (status) {
@ -1837,7 +1834,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
struct edgeport_serial *edge_serial;
struct usb_device *dev;
struct urb *urb;
int port_number;
int status;
u16 open_settings;
u8 transaction_timeout;
@ -1845,8 +1841,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
if (edge_port == NULL)
return -ENODEV;
port_number = port->port_number;
dev = port->serial->dev;
/* turn off loopback */
@ -1878,8 +1872,7 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
dev_dbg(&port->dev, "%s - Sending UMPC_OPEN_PORT\n", __func__);
/* Tell TI to open and start the port */
status = send_cmd(dev, UMPC_OPEN_PORT,
(u8)(UMPM_UART1_PORT + port_number), open_settings, NULL, 0);
status = send_port_cmd(port, UMPC_OPEN_PORT, open_settings, NULL, 0);
if (status) {
dev_err(&port->dev, "%s - cannot send open command, %d\n",
__func__, status);
@ -1887,8 +1880,7 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
}
/* Start the DMA? */
status = send_cmd(dev, UMPC_START_PORT,
(u8)(UMPM_UART1_PORT + port_number), 0, NULL, 0);
status = send_port_cmd(port, UMPC_START_PORT, 0, NULL, 0);
if (status) {
dev_err(&port->dev, "%s - cannot send start DMA command, %d\n",
__func__, status);
@ -1905,9 +1897,7 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
}
/* Read Initial MSR */
status = ti_vread_sync(dev, UMPC_READ_MSR, 0,
(__u16)(UMPM_UART1_PORT + port_number),
&edge_port->shadow_msr, 1);
status = read_port_cmd(port, UMPC_READ_MSR, 0, &edge_port->shadow_msr, 1);
if (status) {
dev_err(&port->dev, "%s - cannot send read MSR command, %d\n",
__func__, status);
@ -1971,9 +1961,7 @@ static void edge_close(struct usb_serial_port *port)
{
struct edgeport_serial *edge_serial;
struct edgeport_port *edge_port;
struct usb_serial *serial = port->serial;
unsigned long flags;
int port_number;
edge_serial = usb_get_serial_data(port->serial);
edge_port = usb_get_serial_port_data(port);
@ -1994,9 +1982,7 @@ static void edge_close(struct usb_serial_port *port)
spin_unlock_irqrestore(&edge_port->ep_lock, flags);
dev_dbg(&port->dev, "%s - send umpc_close_port\n", __func__);
port_number = port->port_number;
send_cmd(serial->dev, UMPC_CLOSE_PORT,
(__u8)(UMPM_UART1_PORT + port_number), 0, NULL, 0);
send_port_cmd(port, UMPC_CLOSE_PORT, 0, NULL, 0);
mutex_lock(&edge_serial->es_lock);
--edge_port->edge_serial->num_ports_open;
@ -2229,7 +2215,6 @@ static void change_port_settings(struct tty_struct *tty,
int baud;
unsigned cflag;
int status;
int port_number = edge_port->port->port_number;
config = kmalloc (sizeof (*config), GFP_KERNEL);
if (!config) {
@ -2244,7 +2229,7 @@ static void change_port_settings(struct tty_struct *tty,
/* These flags must be set */
config->wFlags |= UMP_MASK_UART_FLAGS_RECEIVE_MS_INT;
config->wFlags |= UMP_MASK_UART_FLAGS_AUTO_START_ON_ERR;
config->bUartMode = (__u8)(edge_port->bUartMode);
config->bUartMode = (u8)(edge_port->bUartMode);
switch (cflag & CSIZE) {
case CS5:
@ -2336,7 +2321,7 @@ static void change_port_settings(struct tty_struct *tty,
}
edge_port->baud_rate = baud;
config->wBaudRate = (__u16)((461550L + baud/2) / baud);
config->wBaudRate = (u16)((461550L + baud/2) / baud);
/* FIXME: Recompute actual baud from divisor here */
@ -2355,9 +2340,8 @@ static void change_port_settings(struct tty_struct *tty,
cpu_to_be16s(&config->wFlags);
cpu_to_be16s(&config->wBaudRate);
status = send_cmd(edge_port->port->serial->dev, UMPC_SET_CONFIG,
(__u8)(UMPM_UART1_PORT + port_number),
0, (__u8 *)config, sizeof(*config));
status = send_port_cmd(edge_port->port, UMPC_SET_CONFIG, 0, config,
sizeof(*config));
if (status)
dev_dbg(dev, "%s - error %d when trying to write config to device\n",
__func__, status);
@ -2433,28 +2417,6 @@ static int edge_tiocmget(struct tty_struct *tty)
return result;
}
static int get_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned cwait;
cwait = edge_port->port->port.closing_wait;
if (cwait != ASYNC_CLOSING_WAIT_NONE)
cwait = jiffies_to_msecs(cwait) / 10;
ss->type = PORT_16550A;
ss->line = edge_port->port->minor;
ss->port = edge_port->port->port_number;
ss->irq = 0;
ss->xmit_fifo_size = edge_port->port->bulk_out_size;
ss->baud_base = 9600;
ss->close_delay = 5*HZ;
ss->closing_wait = cwait;
return 0;
}
static void edge_break(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
@ -2615,7 +2577,10 @@ static int edge_port_probe(struct usb_serial_port *port)
if (ret)
goto err;
port->port.closing_wait = msecs_to_jiffies(closing_wait * 10);
/*
* The LSR does not tell when the transmitter shift register has
* emptied so add a one-character drain delay.
*/
port->port.drain_delay = 1;
return 0;
@ -2713,7 +2678,6 @@ static struct usb_serial_driver edgeport_1port_device = {
.release = edge_release,
.port_probe = edge_port_probe,
.port_remove = edge_port_remove,
.get_serial = get_serial_info,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
@ -2752,7 +2716,6 @@ static struct usb_serial_driver edgeport_2port_device = {
.release = edge_release,
.port_probe = edge_port_probe,
.port_remove = edge_port_remove,
.get_serial = get_serial_info,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
@ -2783,9 +2746,6 @@ MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("edgeport/down3.bin");
module_param(closing_wait, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain, in .01 secs");
module_param(ignore_cpu_rev, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(ignore_cpu_rev,
"Ignore the cpu revision when connecting to a device");

View File

@ -133,15 +133,15 @@
#define UMPD_OEDB2_ADDRESS 0xFF10
struct out_endpoint_desc_block {
__u8 Configuration;
__u8 XBufAddr;
__u8 XByteCount;
__u8 Unused1;
__u8 Unused2;
__u8 YBufAddr;
__u8 YByteCount;
__u8 BufferSize;
} __attribute__((packed));
u8 Configuration;
u8 XBufAddr;
u8 XByteCount;
u8 Unused1;
u8 Unused2;
u8 YBufAddr;
u8 YByteCount;
u8 BufferSize;
};
/*
@ -150,16 +150,16 @@ struct out_endpoint_desc_block {
*/
/* UART settings */
struct ump_uart_config {
__u16 wBaudRate; /* Baud rate */
__u16 wFlags; /* Bitmap mask of flags */
__u8 bDataBits; /* 5..8 - data bits per character */
__u8 bParity; /* Parity settings */
__u8 bStopBits; /* Stop bits settings */
u16 wBaudRate; /* Baud rate */
u16 wFlags; /* Bitmap mask of flags */
u8 bDataBits; /* 5..8 - data bits per character */
u8 bParity; /* Parity settings */
u8 bStopBits; /* Stop bits settings */
char cXon; /* XON character */
char cXoff; /* XOFF character */
__u8 bUartMode; /* Will be updated when a user */
u8 bUartMode; /* Will be updated when a user */
/* interface is defined */
} __attribute__((packed));
};
/*
@ -168,9 +168,9 @@ struct ump_uart_config {
*/
/* Interrupt packet structure */
struct ump_interrupt {
__u8 bICode; /* Interrupt code (interrupt num) */
__u8 bIInfo; /* Interrupt information */
} __attribute__((packed));
u8 bICode; /* Interrupt code (interrupt num) */
u8 bIInfo; /* Interrupt information */
};
#define TIUMP_GET_PORT_FROM_CODE(c) (((c) >> 6) & 0x01)

View File

@ -643,7 +643,6 @@ static void iuu_uart_read_callback(struct urb *urb)
struct iuu_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
int status = urb->status;
int error = 0;
int len = 0;
unsigned char *data = urb->transfer_buffer;
priv->poll++;
@ -660,12 +659,11 @@ static void iuu_uart_read_callback(struct urb *urb)
if (urb->actual_length > 1) {
dev_dbg(&port->dev, "%s - urb->actual_length = %i\n", __func__,
urb->actual_length);
error = 1;
return;
}
/* if len > 0 call readbuf */
if (len > 0 && error == 0) {
if (len > 0) {
dev_dbg(&port->dev, "%s - call read buf - len to read is %i\n",
__func__, len);
status = iuu_read_buf(port, len);

View File

@ -41,27 +41,7 @@
#define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
#define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
/* Function prototypes for Keyspan serial converter */
static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port);
static void keyspan_close(struct usb_serial_port *port);
static void keyspan_dtr_rts(struct usb_serial_port *port, int on);
static int keyspan_startup(struct usb_serial *serial);
static void keyspan_disconnect(struct usb_serial *serial);
static void keyspan_release(struct usb_serial *serial);
static int keyspan_port_probe(struct usb_serial_port *port);
static void keyspan_port_remove(struct usb_serial_port *port);
static int keyspan_write_room(struct tty_struct *tty);
static int keyspan_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
static void keyspan_send_setup(struct usb_serial_port *port, int reset_port);
static void keyspan_set_termios(struct tty_struct *tty,
struct usb_serial_port *port,
struct ktermios *old);
static void keyspan_break_ctl(struct tty_struct *tty, int break_state);
static int keyspan_tiocmget(struct tty_struct *tty);
static int keyspan_tiocmset(struct tty_struct *tty, unsigned int set,
unsigned int clear);
static int keyspan_fake_startup(struct usb_serial *serial);
static int keyspan_usa19_calc_baud(struct usb_serial_port *port,
u32 baud_rate, u32 baudclk,

View File

@ -299,7 +299,7 @@ static int metrousb_tiocmset(struct tty_struct *tty,
unsigned long flags = 0;
unsigned long control_state = 0;
dev_dbg(tty->dev, "%s - set=%d, clear=%d\n", __func__, set, clear);
dev_dbg(&port->dev, "%s - set=%d, clear=%d\n", __func__, set, clear);
spin_lock_irqsave(&metro_priv->lock, flags);
control_state = metro_priv->control_state;
@ -334,7 +334,7 @@ static void metrousb_unthrottle(struct tty_struct *tty)
/* Submit the urb to read from the port. */
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
if (result)
dev_err(tty->dev,
dev_err(&port->dev,
"failed submitting interrupt in urb error code=%d\n",
result);
}

View File

@ -1634,23 +1634,6 @@ static int mos7720_tiocmset(struct tty_struct *tty,
return 0;
}
static int get_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7720_port = usb_get_serial_port_data(port);
ss->type = PORT_16550A;
ss->line = mos7720_port->port->minor;
ss->port = mos7720_port->port->port_number;
ss->irq = 0;
ss->xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE;
ss->baud_base = 9600;
ss->close_delay = 5*HZ;
ss->closing_wait = 30*HZ;
return 0;
}
static int mos7720_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
@ -1790,7 +1773,6 @@ static struct usb_serial_driver moschip7720_2port_driver = {
.ioctl = mos7720_ioctl,
.tiocmget = mos7720_tiocmget,
.tiocmset = mos7720_tiocmset,
.get_serial = get_serial_info,
.set_termios = mos7720_set_termios,
.write = mos7720_write,
.write_room = mos7720_write_room,

View File

@ -1383,28 +1383,6 @@ static int mos7840_get_lsr_info(struct tty_struct *tty,
return 0;
}
/*****************************************************************************
* mos7840_get_serial_info
* function to get information about serial port
*****************************************************************************/
static int mos7840_get_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
struct moschip_port *mos7840_port = usb_get_serial_port_data(port);
ss->type = PORT_16550A;
ss->line = mos7840_port->port->minor;
ss->port = mos7840_port->port->port_number;
ss->irq = 0;
ss->xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE;
ss->baud_base = 9600;
ss->close_delay = 5 * HZ;
ss->closing_wait = 30 * HZ;
return 0;
}
/*****************************************************************************
* SerialIoctl
* this function handles any ioctl calls to the driver
@ -1783,7 +1761,6 @@ static struct usb_serial_driver moschip7840_4port_device = {
.probe = mos7840_probe,
.attach = mos7840_attach,
.ioctl = mos7840_ioctl,
.get_serial = mos7840_get_serial_info,
.set_termios = mos7840_set_termios,
.break_ctl = mos7840_break,
.tiocmget = mos7840_tiocmget,

View File

@ -352,23 +352,6 @@ static int opticon_tiocmset(struct tty_struct *tty,
return 0;
}
static int get_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
/* fake emulate a 16550 uart to make userspace code happy */
ss->type = PORT_16550A;
ss->line = port->minor;
ss->port = 0;
ss->irq = 0;
ss->xmit_fifo_size = 1024;
ss->baud_base = 9600;
ss->close_delay = 5*HZ;
ss->closing_wait = 30*HZ;
return 0;
}
static int opticon_port_probe(struct usb_serial_port *port)
{
struct opticon_private *priv;
@ -410,7 +393,6 @@ static struct usb_serial_driver opticon_device = {
.chars_in_buffer = opticon_chars_in_buffer,
.throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle,
.get_serial = get_serial_info,
.tiocmget = opticon_tiocmget,
.tiocmset = opticon_tiocmset,
.process_read_urb = opticon_process_read_urb,

View File

@ -2095,8 +2095,6 @@ static struct usb_serial_driver option_1port_device = {
.chars_in_buffer = usb_wwan_chars_in_buffer,
.tiocmget = usb_wwan_tiocmget,
.tiocmset = usb_wwan_tiocmset,
.get_serial = usb_wwan_get_serial_info,
.set_serial = usb_wwan_set_serial_info,
.attach = option_attach,
.release = option_release,
.port_probe = usb_wwan_port_probe,

View File

@ -173,17 +173,22 @@ MODULE_DEVICE_TABLE(usb, id_table);
static void pl2303_set_break(struct usb_serial_port *port, bool enable);
enum pl2303_type {
TYPE_01, /* Type 0 and 1 (difference unknown) */
TYPE_HX, /* HX version of the pl2303 chip */
TYPE_HXN, /* HXN version of the pl2303 chip */
TYPE_H,
TYPE_HX,
TYPE_TA,
TYPE_TB,
TYPE_HXD,
TYPE_HXN,
TYPE_COUNT
};
struct pl2303_type_data {
const char *name;
speed_t max_baud_rate;
unsigned long quirks;
unsigned int no_autoxonxoff:1;
unsigned int no_divisors:1;
unsigned int alt_divisors:1;
};
struct pl2303_serial_private {
@ -200,15 +205,32 @@ struct pl2303_private {
};
static const struct pl2303_type_data pl2303_type_data[TYPE_COUNT] = {
[TYPE_01] = {
[TYPE_H] = {
.name = "H",
.max_baud_rate = 1228800,
.quirks = PL2303_QUIRK_LEGACY,
.no_autoxonxoff = true,
},
[TYPE_HX] = {
.name = "HX",
.max_baud_rate = 6000000,
},
[TYPE_TA] = {
.name = "TA",
.max_baud_rate = 6000000,
.alt_divisors = true,
},
[TYPE_TB] = {
.name = "TB",
.max_baud_rate = 12000000,
.alt_divisors = true,
},
[TYPE_HXD] = {
.name = "HXD",
.max_baud_rate = 12000000,
},
[TYPE_HXN] = {
.name = "G",
.max_baud_rate = 12000000,
.no_divisors = true,
},
@ -362,42 +384,82 @@ static int pl2303_calc_num_ports(struct usb_serial *serial,
return 1;
}
static bool pl2303_supports_hx_status(struct usb_serial *serial)
{
int ret;
u8 buf;
ret = usb_control_msg_recv(serial->dev, 0, VENDOR_READ_REQUEST,
VENDOR_READ_REQUEST_TYPE, PL2303_READ_TYPE_HX_STATUS,
0, &buf, 1, 100, GFP_KERNEL);
return ret == 0;
}
static int pl2303_detect_type(struct usb_serial *serial)
{
struct usb_device_descriptor *desc = &serial->dev->descriptor;
u16 bcdDevice, bcdUSB;
/*
* Legacy PL2303H, variants 0 and 1 (difference unknown).
*/
if (desc->bDeviceClass == 0x02)
return TYPE_H; /* variant 0 */
if (desc->bMaxPacketSize0 != 0x40) {
if (desc->bDeviceClass == 0x00 || desc->bDeviceClass == 0xff)
return TYPE_H; /* variant 1 */
return TYPE_H; /* variant 0 */
}
bcdDevice = le16_to_cpu(desc->bcdDevice);
bcdUSB = le16_to_cpu(desc->bcdUSB);
switch (bcdDevice) {
case 0x100:
/*
* Assume it's an HXN-type if the device doesn't support the old read
* request value.
*/
if (bcdUSB == 0x200 && !pl2303_supports_hx_status(serial))
return TYPE_HXN;
break;
case 0x300:
if (bcdUSB == 0x200)
return TYPE_TA;
return TYPE_HX;
case 0x400:
return TYPE_HXD;
case 0x500:
return TYPE_TB;
}
dev_err(&serial->interface->dev,
"unknown device type, please report to linux-usb@vger.kernel.org\n");
return -ENODEV;
}
static int pl2303_startup(struct usb_serial *serial)
{
struct pl2303_serial_private *spriv;
enum pl2303_type type = TYPE_01;
enum pl2303_type type;
unsigned char *buf;
int res;
int ret;
ret = pl2303_detect_type(serial);
if (ret < 0)
return ret;
type = ret;
dev_dbg(&serial->interface->dev, "device type: %s\n", pl2303_type_data[type].name);
spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
if (!spriv)
return -ENOMEM;
buf = kmalloc(1, GFP_KERNEL);
if (!buf) {
kfree(spriv);
return -ENOMEM;
}
if (serial->dev->descriptor.bDeviceClass == 0x02)
type = TYPE_01; /* type 0 */
else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40)
type = TYPE_HX;
else if (serial->dev->descriptor.bDeviceClass == 0x00)
type = TYPE_01; /* type 1 */
else if (serial->dev->descriptor.bDeviceClass == 0xFF)
type = TYPE_01; /* type 1 */
dev_dbg(&serial->interface->dev, "device type: %d\n", type);
if (type == TYPE_HX) {
res = usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE,
PL2303_READ_TYPE_HX_STATUS, 0, buf, 1, 100);
if (res != 1)
type = TYPE_HXN;
}
spriv->type = &pl2303_type_data[type];
spriv->quirks = (unsigned long)usb_get_serial_data(serial);
spriv->quirks |= spriv->type->quirks;
@ -405,6 +467,12 @@ static int pl2303_startup(struct usb_serial *serial)
usb_set_serial_data(serial, spriv);
if (type != TYPE_HXN) {
buf = kmalloc(1, GFP_KERNEL);
if (!buf) {
kfree(spriv);
return -ENOMEM;
}
pl2303_vendor_read(serial, 0x8484, buf);
pl2303_vendor_write(serial, 0x0404, 0);
pl2303_vendor_read(serial, 0x8484, buf);
@ -419,9 +487,9 @@ static int pl2303_startup(struct usb_serial *serial)
pl2303_vendor_write(serial, 2, 0x24);
else
pl2303_vendor_write(serial, 2, 0x44);
}
kfree(buf);
kfree(buf);
}
return 0;
}
@ -553,6 +621,45 @@ static speed_t pl2303_encode_baud_rate_divisor(unsigned char buf[4],
return baud;
}
static speed_t pl2303_encode_baud_rate_divisor_alt(unsigned char buf[4],
speed_t baud)
{
unsigned int baseline, mantissa, exponent;
/*
* Apparently, for the TA version the formula is:
* baudrate = 12M * 32 / (mantissa * 2^exponent)
* where
* mantissa = buf[10:0]
* exponent = buf[15:13 16]
*/
baseline = 12000000 * 32;
mantissa = baseline / baud;
if (mantissa == 0)
mantissa = 1; /* Avoid dividing by zero if baud > 32*12M. */
exponent = 0;
while (mantissa >= 2048) {
if (exponent < 15) {
mantissa >>= 1; /* divide by 2 */
exponent++;
} else {
/* Exponent is maxed. Trim mantissa and leave. */
mantissa = 2047;
break;
}
}
buf[3] = 0x80;
buf[2] = exponent & 0x01;
buf[1] = (exponent & ~0x01) << 4 | mantissa >> 8;
buf[0] = mantissa & 0xff;
/* Calculate and return the exact baud rate. */
baud = (baseline / mantissa) >> exponent;
return baud;
}
static void pl2303_encode_baud_rate(struct tty_struct *tty,
struct usb_serial_port *port,
u8 buf[4])
@ -580,6 +687,8 @@ static void pl2303_encode_baud_rate(struct tty_struct *tty,
if (baud == baud_sup)
baud = pl2303_encode_baud_rate_direct(buf, baud);
else if (spriv->type->alt_divisors)
baud = pl2303_encode_baud_rate_divisor_alt(buf, baud);
else
baud = pl2303_encode_baud_rate_divisor(buf, baud);
@ -939,18 +1048,6 @@ static int pl2303_carrier_raised(struct usb_serial_port *port)
return 0;
}
static int pl2303_get_serial(struct tty_struct *tty,
struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
ss->type = PORT_16654;
ss->line = port->minor;
ss->port = port->port_number;
ss->baud_base = 460800;
return 0;
}
static void pl2303_set_break(struct usb_serial_port *port, bool enable)
{
struct usb_serial *serial = port->serial;
@ -1134,7 +1231,6 @@ static struct usb_serial_driver pl2303_device = {
.close = pl2303_close,
.dtr_rts = pl2303_dtr_rts,
.carrier_raised = pl2303_carrier_raised,
.get_serial = pl2303_get_serial,
.break_ctl = pl2303_break_ctl,
.set_termios = pl2303_set_termios,
.tiocmget = pl2303_tiocmget,

View File

@ -453,21 +453,6 @@ static void qt2_disconnect(struct usb_serial *serial)
usb_kill_urb(serial_priv->read_urb);
}
static int get_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
ss->line = port->minor;
ss->port = 0;
ss->irq = 0;
ss->xmit_fifo_size = port->bulk_out_size;
ss->baud_base = 9600;
ss->close_delay = 5*HZ;
ss->closing_wait = 30*HZ;
return 0;
}
static void qt2_process_status(struct usb_serial_port *port, unsigned char *ch)
{
switch (*ch) {
@ -978,7 +963,6 @@ static struct usb_serial_driver qt2_device = {
.tiocmset = qt2_tiocmset,
.tiocmiwait = usb_serial_generic_tiocmiwait,
.get_icount = usb_serial_generic_get_icount,
.get_serial = get_serial_info,
.set_termios = qt2_set_termios,
};

View File

@ -331,21 +331,6 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
return usb_serial_generic_open(tty, port);
}
static int get_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
ss->line = port->minor;
ss->port = 0;
ss->irq = 0;
ss->xmit_fifo_size = port->bulk_out_size;
ss->baud_base = 9600;
ss->close_delay = 5*HZ;
ss->closing_wait = 30*HZ;
return 0;
}
static int ssu100_attach(struct usb_serial *serial)
{
return ssu100_initdevice(serial->dev);
@ -545,7 +530,6 @@ static struct usb_serial_driver ssu100_device = {
.tiocmset = ssu100_tiocmset,
.tiocmiwait = usb_serial_generic_tiocmiwait,
.get_icount = usb_serial_generic_get_icount,
.get_serial = get_serial_info,
.set_termios = ssu100_set_termios,
};

View File

@ -121,6 +121,7 @@
#define TI_LSR_ERROR 0x0F
#define TI_LSR_RX_FULL 0x10
#define TI_LSR_TX_EMPTY 0x20
#define TI_LSR_TX_EMPTY_BOTH 0x40
/* Line control */
#define TI_LCR_BREAK 0x40
@ -183,7 +184,7 @@ struct ti_uart_config {
char cXon;
char cXoff;
u8 bUartMode;
} __packed;
};
/* Get port status */
struct ti_port_status {
@ -192,7 +193,7 @@ struct ti_port_status {
u8 bErrorCode;
u8 bMSR;
u8 bLSR;
} __packed;
};
/* Purge modes */
#define TI_PURGE_OUTPUT 0x00
@ -223,25 +224,25 @@ struct ti_write_data_bytes {
} __packed;
struct ti_read_data_request {
__u8 bAddrType;
__u8 bDataType;
__u8 bDataCounter;
u8 bAddrType;
u8 bDataType;
u8 bDataCounter;
__be16 wBaseAddrHi;
__be16 wBaseAddrLo;
} __packed;
struct ti_read_data_bytes {
__u8 bCmdCode;
__u8 bModuleId;
__u8 bErrorCode;
__u8 bData[];
} __packed;
u8 bCmdCode;
u8 bModuleId;
u8 bErrorCode;
u8 bData[];
};
/* Interrupt struct */
struct ti_interrupt {
__u8 bICode;
__u8 bIInfo;
} __packed;
u8 bICode;
u8 bIInfo;
};
/* Interrupt codes */
#define TI_CODE_HARDWARE_ERROR 0xFF
@ -270,8 +271,6 @@ struct ti_firmware_header {
#define TI_TRANSFER_TIMEOUT 2
#define TI_DEFAULT_CLOSING_WAIT 4000 /* in .01 secs */
/* read urb states */
#define TI_READ_URB_RUNNING 0
#define TI_READ_URB_STOPPING 1
@ -328,27 +327,26 @@ static void ti_recv(struct usb_serial_port *port, unsigned char *data,
static void ti_send(struct ti_port *tport);
static int ti_set_mcr(struct ti_port *tport, unsigned int mcr);
static int ti_get_lsr(struct ti_port *tport, u8 *lsr);
static int ti_get_serial_info(struct tty_struct *tty,
struct serial_struct *ss);
static int ti_set_serial_info(struct tty_struct *tty,
struct serial_struct *ss);
static void ti_get_serial_info(struct tty_struct *tty, struct serial_struct *ss);
static void ti_handle_new_msr(struct ti_port *tport, u8 msr);
static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty);
static int ti_restart_read(struct ti_port *tport, struct tty_struct *tty);
static int ti_command_out_sync(struct ti_device *tdev, __u8 command,
__u16 moduleid, __u16 value, __u8 *data, int size);
static int ti_command_in_sync(struct ti_device *tdev, __u8 command,
__u16 moduleid, __u16 value, __u8 *data, int size);
static int ti_command_out_sync(struct usb_device *udev, u8 command,
u16 moduleid, u16 value, void *data, int size);
static int ti_command_in_sync(struct usb_device *udev, u8 command,
u16 moduleid, u16 value, void *data, int size);
static int ti_port_cmd_out(struct usb_serial_port *port, u8 command,
u16 value, void *data, int size);
static int ti_port_cmd_in(struct usb_serial_port *port, u8 command,
u16 value, void *data, int size);
static int ti_write_byte(struct usb_serial_port *port, struct ti_device *tdev,
unsigned long addr, u8 mask, u8 byte);
static int ti_download_firmware(struct ti_device *tdev);
static int closing_wait = TI_DEFAULT_CLOSING_WAIT;
static const struct usb_device_id ti_id_table_3410[] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
@ -435,7 +433,6 @@ static struct usb_serial_driver ti_1port_device = {
.throttle = ti_throttle,
.unthrottle = ti_unthrottle,
.get_serial = ti_get_serial_info,
.set_serial = ti_set_serial_info,
.set_termios = ti_set_termios,
.tiocmget = ti_tiocmget,
.tiocmset = ti_tiocmset,
@ -469,7 +466,6 @@ static struct usb_serial_driver ti_2port_device = {
.throttle = ti_throttle,
.unthrottle = ti_unthrottle,
.get_serial = ti_get_serial_info,
.set_serial = ti_set_serial_info,
.set_termios = ti_set_termios,
.tiocmget = ti_tiocmget,
.tiocmset = ti_tiocmset,
@ -502,10 +498,6 @@ MODULE_FIRMWARE("moxa/moxa-1131.fw");
MODULE_FIRMWARE("moxa/moxa-1150.fw");
MODULE_FIRMWARE("moxa/moxa-1151.fw");
module_param(closing_wait, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(closing_wait,
"Maximum wait for data to drain in close, in .01 secs, default is 4000");
MODULE_DEVICE_TABLE(usb, ti_id_table_combined);
module_usb_serial_driver(serial_drivers, ti_id_table_combined);
@ -613,7 +605,6 @@ static int ti_port_probe(struct usb_serial_port *port)
tport->tp_uart_base_addr = TI_UART1_BASE_ADDR;
else
tport->tp_uart_base_addr = TI_UART2_BASE_ADDR;
port->port.closing_wait = msecs_to_jiffies(10 * closing_wait);
tport->tp_port = port;
tport->tp_tdev = usb_get_serial_data(port->serial);
@ -624,7 +615,12 @@ static int ti_port_probe(struct usb_serial_port *port)
usb_set_serial_port_data(port, tport);
port->port.drain_delay = 3;
/*
* The TUSB5052 LSR does not tell when the transmitter shift register
* has emptied so add a one-character drain delay.
*/
if (!tport->tp_tdev->td_is_3410)
port->port.drain_delay = 1;
return 0;
}
@ -643,7 +639,6 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
struct ti_device *tdev;
struct usb_device *dev;
struct urb *urb;
int port_number;
int status;
u16 open_settings;
@ -658,8 +653,6 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
if (mutex_lock_interruptible(&tdev->td_open_close_lock))
return -ERESTARTSYS;
port_number = port->port_number;
tport->tp_msr = 0;
tport->tp_shadow_mcr |= (TI_MCR_RTS | TI_MCR_DTR);
@ -683,31 +676,27 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
if (tty)
ti_set_termios(tty, port, &tty->termios);
status = ti_command_out_sync(tdev, TI_OPEN_PORT,
(__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0);
status = ti_port_cmd_out(port, TI_OPEN_PORT, open_settings, NULL, 0);
if (status) {
dev_err(&port->dev, "%s - cannot send open command, %d\n",
__func__, status);
goto unlink_int_urb;
}
status = ti_command_out_sync(tdev, TI_START_PORT,
(__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
status = ti_port_cmd_out(port, TI_START_PORT, 0, NULL, 0);
if (status) {
dev_err(&port->dev, "%s - cannot send start command, %d\n",
__func__, status);
goto unlink_int_urb;
}
status = ti_command_out_sync(tdev, TI_PURGE_PORT,
(__u8)(TI_UART1_PORT + port_number), TI_PURGE_INPUT, NULL, 0);
status = ti_port_cmd_out(port, TI_PURGE_PORT, TI_PURGE_INPUT, NULL, 0);
if (status) {
dev_err(&port->dev, "%s - cannot clear input buffers, %d\n",
__func__, status);
goto unlink_int_urb;
}
status = ti_command_out_sync(tdev, TI_PURGE_PORT,
(__u8)(TI_UART1_PORT + port_number), TI_PURGE_OUTPUT, NULL, 0);
status = ti_port_cmd_out(port, TI_PURGE_PORT, TI_PURGE_OUTPUT, NULL, 0);
if (status) {
dev_err(&port->dev, "%s - cannot clear output buffers, %d\n",
__func__, status);
@ -722,16 +711,14 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
if (tty)
ti_set_termios(tty, port, &tty->termios);
status = ti_command_out_sync(tdev, TI_OPEN_PORT,
(__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0);
status = ti_port_cmd_out(port, TI_OPEN_PORT, open_settings, NULL, 0);
if (status) {
dev_err(&port->dev, "%s - cannot send open command (2), %d\n",
__func__, status);
goto unlink_int_urb;
}
status = ti_command_out_sync(tdev, TI_START_PORT,
(__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
status = ti_port_cmd_out(port, TI_START_PORT, 0, NULL, 0);
if (status) {
dev_err(&port->dev, "%s - cannot send start command (2), %d\n",
__func__, status);
@ -772,7 +759,6 @@ static void ti_close(struct usb_serial_port *port)
{
struct ti_device *tdev;
struct ti_port *tport;
int port_number;
int status;
unsigned long flags;
@ -788,10 +774,7 @@ static void ti_close(struct usb_serial_port *port)
kfifo_reset_out(&port->write_fifo);
spin_unlock_irqrestore(&tport->tp_lock, flags);
port_number = port->port_number;
status = ti_command_out_sync(tdev, TI_CLOSE_PORT,
(__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
status = ti_port_cmd_out(port, TI_CLOSE_PORT, 0, NULL, 0);
if (status)
dev_err(&port->dev,
"%s - cannot send close port command, %d\n"
@ -861,11 +844,20 @@ static int ti_chars_in_buffer(struct tty_struct *tty)
static bool ti_tx_empty(struct usb_serial_port *port)
{
struct ti_port *tport = usb_get_serial_port_data(port);
u8 lsr, mask;
int ret;
u8 lsr;
/*
* TUSB5052 does not have the TEMT bit to tell if the shift register
* is empty.
*/
if (tport->tp_tdev->td_is_3410)
mask = TI_LSR_TX_EMPTY_BOTH;
else
mask = TI_LSR_TX_EMPTY;
ret = ti_get_lsr(tport, &lsr);
if (!ret && !(lsr & TI_LSR_TX_EMPTY))
if (!ret && !(lsr & mask))
return false;
return true;
@ -903,7 +895,6 @@ static void ti_set_termios(struct tty_struct *tty,
struct ti_uart_config *config;
int baud;
int status;
int port_number = port->port_number;
unsigned int mcr;
u16 wbaudrate;
u16 wflags = 0;
@ -919,18 +910,18 @@ static void ti_set_termios(struct tty_struct *tty,
switch (C_CSIZE(tty)) {
case CS5:
config->bDataBits = TI_UART_5_DATA_BITS;
break;
config->bDataBits = TI_UART_5_DATA_BITS;
break;
case CS6:
config->bDataBits = TI_UART_6_DATA_BITS;
break;
config->bDataBits = TI_UART_6_DATA_BITS;
break;
case CS7:
config->bDataBits = TI_UART_7_DATA_BITS;
break;
config->bDataBits = TI_UART_7_DATA_BITS;
break;
default:
case CS8:
config->bDataBits = TI_UART_8_DATA_BITS;
break;
config->bDataBits = TI_UART_8_DATA_BITS;
break;
}
/* CMSPAR isn't supported by this driver */
@ -997,12 +988,11 @@ static void ti_set_termios(struct tty_struct *tty,
config->wBaudRate = cpu_to_be16(wbaudrate);
config->wFlags = cpu_to_be16(wflags);
status = ti_command_out_sync(tport->tp_tdev, TI_SET_CONFIG,
(__u8)(TI_UART1_PORT + port_number), 0, (__u8 *)config,
sizeof(*config));
status = ti_port_cmd_out(port, TI_SET_CONFIG, 0, config,
sizeof(*config));
if (status)
dev_err(&port->dev, "%s - cannot set config on port %d, %d\n",
__func__, port_number, status);
__func__, port->port_number, status);
/* SET_CONFIG asserts RTS and DTR, reset them correctly */
mcr = tport->tp_shadow_mcr;
@ -1011,9 +1001,8 @@ static void ti_set_termios(struct tty_struct *tty,
mcr &= ~(TI_MCR_DTR | TI_MCR_RTS);
status = ti_set_mcr(tport, mcr);
if (status)
dev_err(&port->dev,
"%s - cannot set modem control on port %d, %d\n",
__func__, port_number, status);
dev_err(&port->dev, "%s - cannot set modem control on port %d, %d\n",
__func__, port->port_number, status);
kfree(config);
}
@ -1364,9 +1353,7 @@ static int ti_set_mcr(struct ti_port *tport, unsigned int mcr)
static int ti_get_lsr(struct ti_port *tport, u8 *lsr)
{
int size, status;
struct ti_device *tdev = tport->tp_tdev;
struct usb_serial_port *port = tport->tp_port;
int port_number = port->port_number;
struct ti_port_status *data;
size = sizeof(struct ti_port_status);
@ -1374,8 +1361,7 @@ static int ti_get_lsr(struct ti_port *tport, u8 *lsr)
if (!data)
return -ENOMEM;
status = ti_command_in_sync(tdev, TI_GET_PORT_STATUS,
(__u8)(TI_UART1_PORT+port_number), 0, (__u8 *)data, size);
status = ti_port_cmd_in(port, TI_GET_PORT_STATUS, 0, data, size);
if (status) {
dev_err(&port->dev,
"%s - get port status command failed, %d\n",
@ -1393,41 +1379,12 @@ static int ti_get_lsr(struct ti_port *tport, u8 *lsr)
}
static int ti_get_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
static void ti_get_serial_info(struct tty_struct *tty, struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
unsigned cwait;
cwait = port->port.closing_wait;
if (cwait != ASYNC_CLOSING_WAIT_NONE)
cwait = jiffies_to_msecs(cwait) / 10;
ss->type = PORT_16550A;
ss->line = port->minor;
ss->port = port->port_number;
ss->xmit_fifo_size = kfifo_size(&port->write_fifo);
ss->baud_base = tport->tp_tdev->td_is_3410 ? 921600 : 460800;
ss->closing_wait = cwait;
return 0;
}
static int ti_set_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
struct ti_port *tport = usb_get_serial_port_data(port);
unsigned cwait;
cwait = ss->closing_wait;
if (cwait != ASYNC_CLOSING_WAIT_NONE)
cwait = msecs_to_jiffies(10 * ss->closing_wait);
tport->tp_port->port.closing_wait = cwait;
return 0;
}
@ -1501,34 +1458,28 @@ static int ti_restart_read(struct ti_port *tport, struct tty_struct *tty)
return status;
}
static int ti_command_out_sync(struct ti_device *tdev, __u8 command,
__u16 moduleid, __u16 value, __u8 *data, int size)
static int ti_command_out_sync(struct usb_device *udev, u8 command,
u16 moduleid, u16 value, void *data, int size)
{
int status;
status = usb_control_msg(tdev->td_serial->dev,
usb_sndctrlpipe(tdev->td_serial->dev, 0), command,
(USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT),
value, moduleid, data, size, 1000);
status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), command,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
value, moduleid, data, size, 1000);
if (status < 0)
return status;
return 0;
}
static int ti_command_in_sync(struct ti_device *tdev, __u8 command,
__u16 moduleid, __u16 value, __u8 *data, int size)
static int ti_command_in_sync(struct usb_device *udev, u8 command,
u16 moduleid, u16 value, void *data, int size)
{
int status;
status = usb_control_msg(tdev->td_serial->dev,
usb_rcvctrlpipe(tdev->td_serial->dev, 0), command,
(USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN),
value, moduleid, data, size, 1000);
status = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), command,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
value, moduleid, data, size, 1000);
if (status == size)
status = 0;
else if (status >= 0)
@ -1537,6 +1488,21 @@ static int ti_command_in_sync(struct ti_device *tdev, __u8 command,
return status;
}
static int ti_port_cmd_out(struct usb_serial_port *port, u8 command,
u16 value, void *data, int size)
{
return ti_command_out_sync(port->serial->dev, command,
TI_UART1_PORT + port->port_number,
value, data, size);
}
static int ti_port_cmd_in(struct usb_serial_port *port, u8 command,
u16 value, void *data, int size)
{
return ti_command_in_sync(port->serial->dev, command,
TI_UART1_PORT + port->port_number,
value, data, size);
}
static int ti_write_byte(struct usb_serial_port *port,
struct ti_device *tdev, unsigned long addr,
@ -1562,9 +1528,8 @@ static int ti_write_byte(struct usb_serial_port *port,
data->bData[0] = mask;
data->bData[1] = byte;
status = ti_command_out_sync(tdev, TI_WRITE_DATA, TI_RAM_PORT, 0,
(__u8 *)data, size);
status = ti_command_out_sync(port->serial->dev, TI_WRITE_DATA,
TI_RAM_PORT, 0, data, size);
if (status < 0)
dev_err(&port->dev, "%s - failed, %d\n", __func__, status);

View File

@ -182,7 +182,6 @@ static void upd78f0730_port_remove(struct usb_serial_port *port)
static int upd78f0730_tiocmget(struct tty_struct *tty)
{
struct device *dev = tty->dev;
struct upd78f0730_port_private *private;
struct usb_serial_port *port = tty->driver_data;
int signals;
@ -197,7 +196,7 @@ static int upd78f0730_tiocmget(struct tty_struct *tty)
res = ((signals & UPD78F0730_DTR) ? TIOCM_DTR : 0) |
((signals & UPD78F0730_RTS) ? TIOCM_RTS : 0);
dev_dbg(dev, "%s - res = %x\n", __func__, res);
dev_dbg(&port->dev, "%s - res = %x\n", __func__, res);
return res;
}
@ -205,10 +204,10 @@ static int upd78f0730_tiocmget(struct tty_struct *tty)
static int upd78f0730_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct device *dev = tty->dev;
struct usb_serial_port *port = tty->driver_data;
struct upd78f0730_port_private *private;
struct upd78f0730_set_dtr_rts request;
struct device *dev = &port->dev;
int res;
private = usb_get_serial_port_data(port);
@ -241,10 +240,10 @@ static int upd78f0730_tiocmset(struct tty_struct *tty,
static void upd78f0730_break_ctl(struct tty_struct *tty, int break_state)
{
struct device *dev = tty->dev;
struct upd78f0730_port_private *private;
struct usb_serial_port *port = tty->driver_data;
struct upd78f0730_set_dtr_rts request;
struct device *dev = &port->dev;
private = usb_get_serial_port_data(port);

View File

@ -121,6 +121,44 @@ static void release_minors(struct usb_serial *serial)
serial->minors_reserved = 0;
}
int usb_serial_claim_interface(struct usb_serial *serial, struct usb_interface *intf)
{
struct usb_driver *driver = serial->type->usb_driver;
int ret;
if (serial->sibling)
return -EBUSY;
ret = usb_driver_claim_interface(driver, intf, serial);
if (ret) {
dev_err(&serial->interface->dev,
"failed to claim sibling interface: %d\n", ret);
return ret;
}
serial->sibling = intf;
return 0;
}
EXPORT_SYMBOL_GPL(usb_serial_claim_interface);
static void release_sibling(struct usb_serial *serial, struct usb_interface *intf)
{
struct usb_driver *driver = serial->type->usb_driver;
struct usb_interface *sibling;
if (!serial->sibling)
return;
if (intf == serial->sibling)
sibling = serial->interface;
else
sibling = serial->sibling;
usb_set_intfdata(sibling, NULL);
usb_driver_release_interface(driver, sibling);
}
static void destroy_serial(struct kref *kref)
{
struct usb_serial *serial;
@ -243,7 +281,7 @@ static int serial_open(struct tty_struct *tty, struct file *filp)
{
struct usb_serial_port *port = tty->driver_data;
dev_dbg(tty->dev, "%s\n", __func__);
dev_dbg(&port->dev, "%s\n", __func__);
return tty_port_open(&port->port, tty, filp);
}
@ -272,7 +310,7 @@ static void serial_hangup(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
dev_dbg(tty->dev, "%s\n", __func__);
dev_dbg(&port->dev, "%s\n", __func__);
tty_port_hangup(&port->port);
}
@ -281,7 +319,7 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
{
struct usb_serial_port *port = tty->driver_data;
dev_dbg(tty->dev, "%s\n", __func__);
dev_dbg(&port->dev, "%s\n", __func__);
tty_port_close(&port->port, tty, filp);
}
@ -301,7 +339,7 @@ static void serial_cleanup(struct tty_struct *tty)
struct usb_serial *serial;
struct module *owner;
dev_dbg(tty->dev, "%s\n", __func__);
dev_dbg(&port->dev, "%s\n", __func__);
/* The console is magical. Do not hang up the console hardware
* or there will be tears.
@ -329,7 +367,7 @@ static int serial_write(struct tty_struct *tty, const unsigned char *buf,
if (port->serial->dev->state == USB_STATE_NOTATTACHED)
goto exit;
dev_dbg(tty->dev, "%s - %d byte(s)\n", __func__, count);
dev_dbg(&port->dev, "%s - %d byte(s)\n", __func__, count);
retval = port->serial->type->write(tty, port, buf, count);
if (retval < 0)
@ -342,7 +380,7 @@ static int serial_write_room(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
dev_dbg(tty->dev, "%s\n", __func__);
dev_dbg(&port->dev, "%s\n", __func__);
return port->serial->type->write_room(tty);
}
@ -352,7 +390,7 @@ static int serial_chars_in_buffer(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
dev_dbg(tty->dev, "%s\n", __func__);
dev_dbg(&port->dev, "%s\n", __func__);
if (serial->disconnected)
return 0;
@ -365,7 +403,7 @@ static void serial_wait_until_sent(struct tty_struct *tty, int timeout)
struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
dev_dbg(tty->dev, "%s\n", __func__);
dev_dbg(&port->dev, "%s\n", __func__);
if (!port->serial->type->wait_until_sent)
return;
@ -380,7 +418,7 @@ static void serial_throttle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
dev_dbg(tty->dev, "%s\n", __func__);
dev_dbg(&port->dev, "%s\n", __func__);
if (port->serial->type->throttle)
port->serial->type->throttle(tty);
@ -390,7 +428,7 @@ static void serial_unthrottle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
dev_dbg(tty->dev, "%s\n", __func__);
dev_dbg(&port->dev, "%s\n", __func__);
if (port->serial->type->unthrottle)
port->serial->type->unthrottle(tty);
@ -399,19 +437,62 @@ static void serial_unthrottle(struct tty_struct *tty)
static int serial_get_serial(struct tty_struct *tty, struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
struct tty_port *tport = &port->port;
unsigned int close_delay, closing_wait;
mutex_lock(&tport->mutex);
close_delay = jiffies_to_msecs(tport->close_delay) / 10;
closing_wait = tport->closing_wait;
if (closing_wait != ASYNC_CLOSING_WAIT_NONE)
closing_wait = jiffies_to_msecs(closing_wait) / 10;
ss->line = port->minor;
ss->close_delay = close_delay;
ss->closing_wait = closing_wait;
if (port->serial->type->get_serial)
return port->serial->type->get_serial(tty, ss);
return -ENOTTY;
port->serial->type->get_serial(tty, ss);
mutex_unlock(&tport->mutex);
return 0;
}
static int serial_set_serial(struct tty_struct *tty, struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
struct tty_port *tport = &port->port;
unsigned int close_delay, closing_wait;
int ret = 0;
if (port->serial->type->set_serial)
return port->serial->type->set_serial(tty, ss);
return -ENOTTY;
close_delay = msecs_to_jiffies(ss->close_delay * 10);
closing_wait = ss->closing_wait;
if (closing_wait != ASYNC_CLOSING_WAIT_NONE)
closing_wait = msecs_to_jiffies(closing_wait * 10);
mutex_lock(&tport->mutex);
if (!capable(CAP_SYS_ADMIN)) {
if (close_delay != tport->close_delay ||
closing_wait != tport->closing_wait) {
ret = -EPERM;
goto out_unlock;
}
}
if (port->serial->type->set_serial) {
ret = port->serial->type->set_serial(tty, ss);
if (ret)
goto out_unlock;
}
tport->close_delay = close_delay;
tport->closing_wait = closing_wait;
out_unlock:
mutex_unlock(&tport->mutex);
return ret;
}
static int serial_ioctl(struct tty_struct *tty,
@ -420,7 +501,7 @@ static int serial_ioctl(struct tty_struct *tty,
struct usb_serial_port *port = tty->driver_data;
int retval = -ENOIOCTLCMD;
dev_dbg(tty->dev, "%s - cmd 0x%04x\n", __func__, cmd);
dev_dbg(&port->dev, "%s - cmd 0x%04x\n", __func__, cmd);
switch (cmd) {
case TIOCMIWAIT:
@ -439,7 +520,7 @@ static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
{
struct usb_serial_port *port = tty->driver_data;
dev_dbg(tty->dev, "%s\n", __func__);
dev_dbg(&port->dev, "%s\n", __func__);
if (port->serial->type->set_termios)
port->serial->type->set_termios(tty, port, old);
@ -451,7 +532,7 @@ static int serial_break(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
dev_dbg(tty->dev, "%s\n", __func__);
dev_dbg(&port->dev, "%s\n", __func__);
if (port->serial->type->break_ctl)
port->serial->type->break_ctl(tty, break_state);
@ -498,11 +579,11 @@ static int serial_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
dev_dbg(tty->dev, "%s\n", __func__);
dev_dbg(&port->dev, "%s\n", __func__);
if (port->serial->type->tiocmget)
return port->serial->type->tiocmget(tty);
return -EINVAL;
return -ENOTTY;
}
static int serial_tiocmset(struct tty_struct *tty,
@ -510,11 +591,11 @@ static int serial_tiocmset(struct tty_struct *tty,
{
struct usb_serial_port *port = tty->driver_data;
dev_dbg(tty->dev, "%s\n", __func__);
dev_dbg(&port->dev, "%s\n", __func__);
if (port->serial->type->tiocmset)
return port->serial->type->tiocmset(tty, set, clear);
return -EINVAL;
return -ENOTTY;
}
static int serial_get_icount(struct tty_struct *tty,
@ -522,11 +603,11 @@ static int serial_get_icount(struct tty_struct *tty,
{
struct usb_serial_port *port = tty->driver_data;
dev_dbg(tty->dev, "%s\n", __func__);
dev_dbg(&port->dev, "%s\n", __func__);
if (port->serial->type->get_icount)
return port->serial->type->get_icount(tty, icount);
return -EINVAL;
return -ENOTTY;
}
/*
@ -711,36 +792,48 @@ static const struct tty_port_operations serial_port_ops = {
.shutdown = serial_port_shutdown,
};
static void find_endpoints(struct usb_serial *serial,
struct usb_serial_endpoints *epds)
static void store_endpoint(struct usb_serial *serial,
struct usb_serial_endpoints *epds,
struct usb_endpoint_descriptor *epd)
{
struct device *dev = &serial->interface->dev;
u8 addr = epd->bEndpointAddress;
if (usb_endpoint_is_bulk_in(epd)) {
if (epds->num_bulk_in == ARRAY_SIZE(epds->bulk_in))
return;
dev_dbg(dev, "found bulk in endpoint %02x\n", addr);
epds->bulk_in[epds->num_bulk_in++] = epd;
} else if (usb_endpoint_is_bulk_out(epd)) {
if (epds->num_bulk_out == ARRAY_SIZE(epds->bulk_out))
return;
dev_dbg(dev, "found bulk out endpoint %02x\n", addr);
epds->bulk_out[epds->num_bulk_out++] = epd;
} else if (usb_endpoint_is_int_in(epd)) {
if (epds->num_interrupt_in == ARRAY_SIZE(epds->interrupt_in))
return;
dev_dbg(dev, "found interrupt in endpoint %02x\n", addr);
epds->interrupt_in[epds->num_interrupt_in++] = epd;
} else if (usb_endpoint_is_int_out(epd)) {
if (epds->num_interrupt_out == ARRAY_SIZE(epds->interrupt_out))
return;
dev_dbg(dev, "found interrupt out endpoint %02x\n", addr);
epds->interrupt_out[epds->num_interrupt_out++] = epd;
}
}
static void find_endpoints(struct usb_serial *serial,
struct usb_serial_endpoints *epds,
struct usb_interface *intf)
{
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *epd;
unsigned int i;
BUILD_BUG_ON(ARRAY_SIZE(epds->bulk_in) < USB_MAXENDPOINTS / 2);
BUILD_BUG_ON(ARRAY_SIZE(epds->bulk_out) < USB_MAXENDPOINTS / 2);
BUILD_BUG_ON(ARRAY_SIZE(epds->interrupt_in) < USB_MAXENDPOINTS / 2);
BUILD_BUG_ON(ARRAY_SIZE(epds->interrupt_out) < USB_MAXENDPOINTS / 2);
iface_desc = serial->interface->cur_altsetting;
iface_desc = intf->cur_altsetting;
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
epd = &iface_desc->endpoint[i].desc;
if (usb_endpoint_is_bulk_in(epd)) {
dev_dbg(dev, "found bulk in on endpoint %u\n", i);
epds->bulk_in[epds->num_bulk_in++] = epd;
} else if (usb_endpoint_is_bulk_out(epd)) {
dev_dbg(dev, "found bulk out on endpoint %u\n", i);
epds->bulk_out[epds->num_bulk_out++] = epd;
} else if (usb_endpoint_is_int_in(epd)) {
dev_dbg(dev, "found interrupt in on endpoint %u\n", i);
epds->interrupt_in[epds->num_interrupt_in++] = epd;
} else if (usb_endpoint_is_int_out(epd)) {
dev_dbg(dev, "found interrupt out on endpoint %u\n", i);
epds->interrupt_out[epds->num_interrupt_out++] = epd;
}
store_endpoint(serial, epds, epd);
}
}
@ -906,7 +999,7 @@ static int usb_serial_probe(struct usb_interface *interface,
if (retval) {
dev_dbg(ddev, "sub driver rejected device\n");
goto err_put_serial;
goto err_release_sibling;
}
}
@ -914,10 +1007,12 @@ static int usb_serial_probe(struct usb_interface *interface,
epds = kzalloc(sizeof(*epds), GFP_KERNEL);
if (!epds) {
retval = -ENOMEM;
goto err_put_serial;
goto err_release_sibling;
}
find_endpoints(serial, epds);
find_endpoints(serial, epds, interface);
if (serial->sibling)
find_endpoints(serial, epds, serial->sibling);
if (epds->num_bulk_in < type->num_bulk_in ||
epds->num_bulk_out < type->num_bulk_out ||
@ -1065,7 +1160,8 @@ static int usb_serial_probe(struct usb_interface *interface,
err_free_epds:
kfree(epds);
err_put_serial:
err_release_sibling:
release_sibling(serial, interface);
usb_serial_put(serial);
err_put_module:
module_put(type->driver.owner);
@ -1081,6 +1177,10 @@ static void usb_serial_disconnect(struct usb_interface *interface)
struct usb_serial_port *port;
struct tty_struct *tty;
/* sibling interface is cleaning up */
if (!serial)
return;
usb_serial_console_disconnect(serial);
mutex_lock(&serial->disc_mutex);
@ -1104,6 +1204,8 @@ static void usb_serial_disconnect(struct usb_interface *interface)
if (serial->type->disconnect)
serial->type->disconnect(serial);
release_sibling(serial, interface);
/* let the last holder of this object cause it to be cleaned up */
usb_serial_put(serial);
dev_info(dev, "device disconnected\n");
@ -1112,9 +1214,11 @@ static void usb_serial_disconnect(struct usb_interface *interface)
int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
{
struct usb_serial *serial = usb_get_intfdata(intf);
int i, r = 0;
int i, r;
serial->suspending = 1;
/* suspend when called for first sibling interface */
if (serial->suspend_count++)
return 0;
/*
* serial->type->suspend() MUST return 0 in system sleep context,
@ -1124,15 +1228,15 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
if (serial->type->suspend) {
r = serial->type->suspend(serial, message);
if (r < 0) {
serial->suspending = 0;
goto err_out;
serial->suspend_count--;
return r;
}
}
for (i = 0; i < serial->num_ports; ++i)
usb_serial_port_poison_urbs(serial->port[i]);
err_out:
return r;
return 0;
}
EXPORT_SYMBOL(usb_serial_suspend);
@ -1149,9 +1253,12 @@ int usb_serial_resume(struct usb_interface *intf)
struct usb_serial *serial = usb_get_intfdata(intf);
int rv;
/* resume when called for last sibling interface */
if (--serial->suspend_count)
return 0;
usb_serial_unpoison_port_urbs(serial);
serial->suspending = 0;
if (serial->type->resume)
rv = serial->type->resume(serial);
else
@ -1166,9 +1273,12 @@ static int usb_serial_reset_resume(struct usb_interface *intf)
struct usb_serial *serial = usb_get_intfdata(intf);
int rv;
/* resume when called for last sibling interface */
if (--serial->suspend_count)
return 0;
usb_serial_unpoison_port_urbs(serial);
serial->suspending = 0;
if (serial->type->reset_resume) {
rv = serial->type->reset_resume(serial);
} else {

View File

@ -15,10 +15,6 @@ extern int usb_wwan_write_room(struct tty_struct *tty);
extern int usb_wwan_tiocmget(struct tty_struct *tty);
extern int usb_wwan_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
extern int usb_wwan_get_serial_info(struct tty_struct *tty,
struct serial_struct *ss);
extern int usb_wwan_set_serial_info(struct tty_struct *tty,
struct serial_struct *ss);
extern int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
extern int usb_wwan_chars_in_buffer(struct tty_struct *tty);

View File

@ -132,51 +132,6 @@ int usb_wwan_tiocmset(struct tty_struct *tty,
}
EXPORT_SYMBOL(usb_wwan_tiocmset);
int usb_wwan_get_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
ss->line = port->minor;
ss->port = port->port_number;
ss->baud_base = tty_get_baud_rate(port->port.tty);
ss->close_delay = port->port.close_delay / 10;
ss->closing_wait = port->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
ASYNC_CLOSING_WAIT_NONE :
port->port.closing_wait / 10;
return 0;
}
EXPORT_SYMBOL(usb_wwan_get_serial_info);
int usb_wwan_set_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
unsigned int closing_wait, close_delay;
int retval = 0;
close_delay = ss->close_delay * 10;
closing_wait = ss->closing_wait == ASYNC_CLOSING_WAIT_NONE ?
ASYNC_CLOSING_WAIT_NONE : ss->closing_wait * 10;
mutex_lock(&port->port.mutex);
if (!capable(CAP_SYS_ADMIN)) {
if ((close_delay != port->port.close_delay) ||
(closing_wait != port->port.closing_wait))
retval = -EPERM;
else
retval = -EOPNOTSUPP;
} else {
port->port.close_delay = close_delay;
port->port.closing_wait = closing_wait;
}
mutex_unlock(&port->port.mutex);
return retval;
}
EXPORT_SYMBOL(usb_wwan_set_serial_info);
int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{

View File

@ -83,7 +83,7 @@ static void whiteheat_port_remove(struct usb_serial_port *port);
static int whiteheat_open(struct tty_struct *tty,
struct usb_serial_port *port);
static void whiteheat_close(struct usb_serial_port *port);
static int whiteheat_get_serial(struct tty_struct *tty,
static void whiteheat_get_serial(struct tty_struct *tty,
struct serial_struct *ss);
static void whiteheat_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
@ -170,7 +170,6 @@ static int firm_report_tx_done(struct usb_serial_port *port);
#define COMMAND_PORT 4
#define COMMAND_TIMEOUT (2*HZ) /* 2 second timeout for a command */
#define COMMAND_TIMEOUT_MS 2000
#define CLOSING_DELAY (30 * HZ)
/*****************************************************************************
@ -440,21 +439,9 @@ static int whiteheat_tiocmset(struct tty_struct *tty,
}
static int whiteheat_get_serial(struct tty_struct *tty,
struct serial_struct *ss)
static void whiteheat_get_serial(struct tty_struct *tty, struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
ss->type = PORT_16654;
ss->line = port->minor;
ss->port = port->port_number;
ss->xmit_fifo_size = kfifo_size(&port->write_fifo);
ss->custom_divisor = 0;
ss->baud_base = 460800;
ss->close_delay = CLOSING_DELAY;
ss->closing_wait = CLOSING_DELAY;
return 0;
}

View File

@ -3,6 +3,7 @@
* MaxLinear/Exar USB to Serial driver
*
* Copyright (c) 2020 Manivannan Sadhasivam <mani@kernel.org>
* Copyright (c) 2021 Johan Hovold <johan@kernel.org>
*
* Based on the initial driver written by Patong Yang:
*
@ -16,6 +17,7 @@
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/usb.h>
#include <linux/usb/cdc.h>
#include <linux/usb/serial.h>
struct xr_txrx_clk_mask {
@ -28,10 +30,12 @@ struct xr_txrx_clk_mask {
#define XR21V141X_MIN_SPEED 46U
#define XR21V141X_MAX_SPEED XR_INT_OSC_HZ
/* USB Requests */
#define XR21V141X_SET_REQ 0
#define XR21V141X_GET_REQ 1
/* XR21V141X register blocks */
#define XR21V141X_UART_REG_BLOCK 0
#define XR21V141X_UM_REG_BLOCK 4
#define XR21V141X_UART_CUSTOM_BLOCK 0x66
/* XR21V141X UART registers */
#define XR21V141X_CLOCK_DIVISOR_0 0x04
#define XR21V141X_CLOCK_DIVISOR_1 0x05
#define XR21V141X_CLOCK_DIVISOR_2 0x06
@ -39,13 +43,9 @@ struct xr_txrx_clk_mask {
#define XR21V141X_TX_CLOCK_MASK_1 0x08
#define XR21V141X_RX_CLOCK_MASK_0 0x09
#define XR21V141X_RX_CLOCK_MASK_1 0x0a
#define XR21V141X_REG_FORMAT 0x0b
/* XR21V141X register blocks */
#define XR21V141X_UART_REG_BLOCK 0
#define XR21V141X_UM_REG_BLOCK 4
#define XR21V141X_UART_CUSTOM_BLOCK 0x66
/* XR21V141X UART Manager Registers */
/* XR21V141X UART Manager registers */
#define XR21V141X_UM_FIFO_ENABLE_REG 0x10
#define XR21V141X_UM_ENABLE_TX_FIFO 0x01
#define XR21V141X_UM_ENABLE_RX_FIFO 0x02
@ -53,72 +53,203 @@ struct xr_txrx_clk_mask {
#define XR21V141X_UM_RX_FIFO_RESET 0x18
#define XR21V141X_UM_TX_FIFO_RESET 0x1c
#define XR21V141X_UART_ENABLE_TX 0x1
#define XR21V141X_UART_ENABLE_RX 0x2
#define XR_UART_ENABLE_TX 0x1
#define XR_UART_ENABLE_RX 0x2
#define XR21V141X_UART_MODE_RI BIT(0)
#define XR21V141X_UART_MODE_CD BIT(1)
#define XR21V141X_UART_MODE_DSR BIT(2)
#define XR21V141X_UART_MODE_DTR BIT(3)
#define XR21V141X_UART_MODE_CTS BIT(4)
#define XR21V141X_UART_MODE_RTS BIT(5)
#define XR_GPIO_RI BIT(0)
#define XR_GPIO_CD BIT(1)
#define XR_GPIO_DSR BIT(2)
#define XR_GPIO_DTR BIT(3)
#define XR_GPIO_CTS BIT(4)
#define XR_GPIO_RTS BIT(5)
#define XR_GPIO_CLK BIT(6)
#define XR_GPIO_XEN BIT(7)
#define XR_GPIO_TXT BIT(8)
#define XR_GPIO_RXT BIT(9)
#define XR21V141X_UART_BREAK_ON 0xff
#define XR21V141X_UART_BREAK_OFF 0
#define XR_UART_DATA_MASK GENMASK(3, 0)
#define XR_UART_DATA_7 0x7
#define XR_UART_DATA_8 0x8
#define XR21V141X_UART_DATA_MASK GENMASK(3, 0)
#define XR21V141X_UART_DATA_7 0x7
#define XR21V141X_UART_DATA_8 0x8
#define XR_UART_PARITY_MASK GENMASK(6, 4)
#define XR_UART_PARITY_SHIFT 4
#define XR_UART_PARITY_NONE (0x0 << XR_UART_PARITY_SHIFT)
#define XR_UART_PARITY_ODD (0x1 << XR_UART_PARITY_SHIFT)
#define XR_UART_PARITY_EVEN (0x2 << XR_UART_PARITY_SHIFT)
#define XR_UART_PARITY_MARK (0x3 << XR_UART_PARITY_SHIFT)
#define XR_UART_PARITY_SPACE (0x4 << XR_UART_PARITY_SHIFT)
#define XR21V141X_UART_PARITY_MASK GENMASK(6, 4)
#define XR21V141X_UART_PARITY_SHIFT 4
#define XR21V141X_UART_PARITY_NONE (0x0 << XR21V141X_UART_PARITY_SHIFT)
#define XR21V141X_UART_PARITY_ODD (0x1 << XR21V141X_UART_PARITY_SHIFT)
#define XR21V141X_UART_PARITY_EVEN (0x2 << XR21V141X_UART_PARITY_SHIFT)
#define XR21V141X_UART_PARITY_MARK (0x3 << XR21V141X_UART_PARITY_SHIFT)
#define XR21V141X_UART_PARITY_SPACE (0x4 << XR21V141X_UART_PARITY_SHIFT)
#define XR_UART_STOP_MASK BIT(7)
#define XR_UART_STOP_SHIFT 7
#define XR_UART_STOP_1 (0x0 << XR_UART_STOP_SHIFT)
#define XR_UART_STOP_2 (0x1 << XR_UART_STOP_SHIFT)
#define XR21V141X_UART_STOP_MASK BIT(7)
#define XR21V141X_UART_STOP_SHIFT 7
#define XR21V141X_UART_STOP_1 (0x0 << XR21V141X_UART_STOP_SHIFT)
#define XR21V141X_UART_STOP_2 (0x1 << XR21V141X_UART_STOP_SHIFT)
#define XR_UART_FLOW_MODE_NONE 0x0
#define XR_UART_FLOW_MODE_HW 0x1
#define XR_UART_FLOW_MODE_SW 0x2
#define XR21V141X_UART_FLOW_MODE_NONE 0x0
#define XR21V141X_UART_FLOW_MODE_HW 0x1
#define XR21V141X_UART_FLOW_MODE_SW 0x2
#define XR_GPIO_MODE_SEL_MASK GENMASK(2, 0)
#define XR_GPIO_MODE_SEL_RTS_CTS 0x1
#define XR_GPIO_MODE_SEL_DTR_DSR 0x2
#define XR_GPIO_MODE_SEL_RS485 0x3
#define XR_GPIO_MODE_SEL_RS485_ADDR 0x4
#define XR_GPIO_MODE_TX_TOGGLE 0x100
#define XR_GPIO_MODE_RX_TOGGLE 0x200
#define XR21V141X_UART_MODE_GPIO_MASK GENMASK(2, 0)
#define XR21V141X_UART_MODE_RTS_CTS 0x1
#define XR21V141X_UART_MODE_DTR_DSR 0x2
#define XR21V141X_UART_MODE_RS485 0x3
#define XR21V141X_UART_MODE_RS485_ADDR 0x4
#define XR_FIFO_RESET 0x1
#define XR21V141X_REG_ENABLE 0x03
#define XR21V141X_REG_FORMAT 0x0b
#define XR21V141X_REG_FLOW_CTRL 0x0c
#define XR21V141X_REG_XON_CHAR 0x10
#define XR21V141X_REG_XOFF_CHAR 0x11
#define XR21V141X_REG_LOOPBACK 0x12
#define XR21V141X_REG_TX_BREAK 0x14
#define XR21V141X_REG_RS845_DELAY 0x15
#define XR21V141X_REG_GPIO_MODE 0x1a
#define XR21V141X_REG_GPIO_DIR 0x1b
#define XR21V141X_REG_GPIO_INT_MASK 0x1c
#define XR21V141X_REG_GPIO_SET 0x1d
#define XR21V141X_REG_GPIO_CLR 0x1e
#define XR21V141X_REG_GPIO_STATUS 0x1f
#define XR_CUSTOM_DRIVER_ACTIVE 0x1
static int xr_set_reg(struct usb_serial_port *port, u8 block, u8 reg, u8 val)
static int xr21v141x_uart_enable(struct usb_serial_port *port);
static int xr21v141x_uart_disable(struct usb_serial_port *port);
static int xr21v141x_fifo_reset(struct usb_serial_port *port);
static void xr21v141x_set_line_settings(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios);
struct xr_type {
int reg_width;
u8 reg_recipient;
u8 set_reg;
u8 get_reg;
u16 uart_enable;
u16 flow_control;
u16 xon_char;
u16 xoff_char;
u16 tx_break;
u16 gpio_mode;
u16 gpio_direction;
u16 gpio_set;
u16 gpio_clear;
u16 gpio_status;
u16 tx_fifo_reset;
u16 rx_fifo_reset;
u16 custom_driver;
bool have_5_6_bit_mode;
bool have_xmit_toggle;
int (*enable)(struct usb_serial_port *port);
int (*disable)(struct usb_serial_port *port);
int (*fifo_reset)(struct usb_serial_port *port);
void (*set_line_settings)(struct tty_struct *tty,
struct usb_serial_port *port,
struct ktermios *old_termios);
};
enum xr_type_id {
XR21V141X,
XR21B142X,
XR21B1411,
XR2280X,
XR_TYPE_COUNT,
};
static const struct xr_type xr_types[] = {
[XR21V141X] = {
.reg_width = 8,
.reg_recipient = USB_RECIP_DEVICE,
.set_reg = 0x00,
.get_reg = 0x01,
.uart_enable = 0x03,
.flow_control = 0x0c,
.xon_char = 0x10,
.xoff_char = 0x11,
.tx_break = 0x14,
.gpio_mode = 0x1a,
.gpio_direction = 0x1b,
.gpio_set = 0x1d,
.gpio_clear = 0x1e,
.gpio_status = 0x1f,
.enable = xr21v141x_uart_enable,
.disable = xr21v141x_uart_disable,
.fifo_reset = xr21v141x_fifo_reset,
.set_line_settings = xr21v141x_set_line_settings,
},
[XR21B142X] = {
.reg_width = 16,
.reg_recipient = USB_RECIP_INTERFACE,
.set_reg = 0x00,
.get_reg = 0x00,
.uart_enable = 0x00,
.flow_control = 0x06,
.xon_char = 0x07,
.xoff_char = 0x08,
.tx_break = 0x0a,
.gpio_mode = 0x0c,
.gpio_direction = 0x0d,
.gpio_set = 0x0e,
.gpio_clear = 0x0f,
.gpio_status = 0x10,
.tx_fifo_reset = 0x40,
.rx_fifo_reset = 0x43,
.custom_driver = 0x60,
.have_5_6_bit_mode = true,
.have_xmit_toggle = true,
},
[XR21B1411] = {
.reg_width = 12,
.reg_recipient = USB_RECIP_DEVICE,
.set_reg = 0x00,
.get_reg = 0x01,
.uart_enable = 0xc00,
.flow_control = 0xc06,
.xon_char = 0xc07,
.xoff_char = 0xc08,
.tx_break = 0xc0a,
.gpio_mode = 0xc0c,
.gpio_direction = 0xc0d,
.gpio_set = 0xc0e,
.gpio_clear = 0xc0f,
.gpio_status = 0xc10,
.tx_fifo_reset = 0xc80,
.rx_fifo_reset = 0xcc0,
.custom_driver = 0x20d,
},
[XR2280X] = {
.reg_width = 16,
.reg_recipient = USB_RECIP_DEVICE,
.set_reg = 0x05,
.get_reg = 0x05,
.uart_enable = 0x40,
.flow_control = 0x46,
.xon_char = 0x47,
.xoff_char = 0x48,
.tx_break = 0x4a,
.gpio_mode = 0x4c,
.gpio_direction = 0x4d,
.gpio_set = 0x4e,
.gpio_clear = 0x4f,
.gpio_status = 0x50,
.tx_fifo_reset = 0x60,
.rx_fifo_reset = 0x63,
.custom_driver = 0x81,
},
};
struct xr_data {
const struct xr_type *type;
u8 channel; /* zero-based index or interface number */
};
static int xr_set_reg(struct usb_serial_port *port, u8 channel, u16 reg, u16 val)
{
struct xr_data *data = usb_get_serial_port_data(port);
const struct xr_type *type = data->type;
struct usb_serial *serial = port->serial;
int ret;
ret = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
XR21V141X_SET_REQ,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
val, reg | (block << 8), NULL, 0,
USB_CTRL_SET_TIMEOUT);
ret = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
type->set_reg,
USB_DIR_OUT | USB_TYPE_VENDOR | type->reg_recipient,
val, (channel << 8) | reg, NULL, 0,
USB_CTRL_SET_TIMEOUT);
if (ret < 0) {
dev_err(&port->dev, "Failed to set reg 0x%02x: %d\n", reg, ret);
return ret;
@ -127,24 +258,33 @@ static int xr_set_reg(struct usb_serial_port *port, u8 block, u8 reg, u8 val)
return 0;
}
static int xr_get_reg(struct usb_serial_port *port, u8 block, u8 reg, u8 *val)
static int xr_get_reg(struct usb_serial_port *port, u8 channel, u16 reg, u16 *val)
{
struct xr_data *data = usb_get_serial_port_data(port);
const struct xr_type *type = data->type;
struct usb_serial *serial = port->serial;
u8 *dmabuf;
int ret;
int ret, len;
dmabuf = kmalloc(1, GFP_KERNEL);
if (type->reg_width == 8)
len = 1;
else
len = 2;
dmabuf = kmalloc(len, GFP_KERNEL);
if (!dmabuf)
return -ENOMEM;
ret = usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
XR21V141X_GET_REQ,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, reg | (block << 8), dmabuf, 1,
USB_CTRL_GET_TIMEOUT);
if (ret == 1) {
*val = *dmabuf;
ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
type->get_reg,
USB_DIR_IN | USB_TYPE_VENDOR | type->reg_recipient,
0, (channel << 8) | reg, dmabuf, len,
USB_CTRL_GET_TIMEOUT);
if (ret == len) {
if (len == 2)
*val = le16_to_cpup((__le16 *)dmabuf);
else
*val = *dmabuf;
ret = 0;
} else {
dev_err(&port->dev, "Failed to get reg 0x%02x: %d\n", reg, ret);
@ -157,21 +297,45 @@ static int xr_get_reg(struct usb_serial_port *port, u8 block, u8 reg, u8 *val)
return ret;
}
static int xr_set_reg_uart(struct usb_serial_port *port, u8 reg, u8 val)
static int xr_set_reg_uart(struct usb_serial_port *port, u16 reg, u16 val)
{
return xr_set_reg(port, XR21V141X_UART_REG_BLOCK, reg, val);
struct xr_data *data = usb_get_serial_port_data(port);
return xr_set_reg(port, data->channel, reg, val);
}
static int xr_get_reg_uart(struct usb_serial_port *port, u8 reg, u8 *val)
static int xr_get_reg_uart(struct usb_serial_port *port, u16 reg, u16 *val)
{
return xr_get_reg(port, XR21V141X_UART_REG_BLOCK, reg, val);
struct xr_data *data = usb_get_serial_port_data(port);
return xr_get_reg(port, data->channel, reg, val);
}
static int xr_set_reg_um(struct usb_serial_port *port, u8 reg, u8 val)
static int xr_set_reg_um(struct usb_serial_port *port, u8 reg_base, u8 val)
{
struct xr_data *data = usb_get_serial_port_data(port);
u8 reg;
reg = reg_base + data->channel;
return xr_set_reg(port, XR21V141X_UM_REG_BLOCK, reg, val);
}
static int __xr_uart_enable(struct usb_serial_port *port)
{
struct xr_data *data = usb_get_serial_port_data(port);
return xr_set_reg_uart(port, data->type->uart_enable,
XR_UART_ENABLE_TX | XR_UART_ENABLE_RX);
}
static int __xr_uart_disable(struct usb_serial_port *port)
{
struct xr_data *data = usb_get_serial_port_data(port);
return xr_set_reg_uart(port, data->type->uart_enable, 0);
}
/*
* According to datasheet, below is the recommended sequence for enabling UART
* module in XR21V141X:
@ -180,7 +344,7 @@ static int xr_set_reg_um(struct usb_serial_port *port, u8 reg, u8 val)
* Enable Tx and Rx
* Enable Rx FIFO
*/
static int xr_uart_enable(struct usb_serial_port *port)
static int xr21v141x_uart_enable(struct usb_serial_port *port)
{
int ret;
@ -189,25 +353,23 @@ static int xr_uart_enable(struct usb_serial_port *port)
if (ret)
return ret;
ret = xr_set_reg_uart(port, XR21V141X_REG_ENABLE,
XR21V141X_UART_ENABLE_TX | XR21V141X_UART_ENABLE_RX);
ret = __xr_uart_enable(port);
if (ret)
return ret;
ret = xr_set_reg_um(port, XR21V141X_UM_FIFO_ENABLE_REG,
XR21V141X_UM_ENABLE_TX_FIFO | XR21V141X_UM_ENABLE_RX_FIFO);
if (ret)
xr_set_reg_uart(port, XR21V141X_REG_ENABLE, 0);
__xr_uart_disable(port);
return ret;
}
static int xr_uart_disable(struct usb_serial_port *port)
static int xr21v141x_uart_disable(struct usb_serial_port *port)
{
int ret;
ret = xr_set_reg_uart(port, XR21V141X_REG_ENABLE, 0);
ret = __xr_uart_disable(port);
if (ret)
return ret;
@ -216,13 +378,68 @@ static int xr_uart_disable(struct usb_serial_port *port)
return ret;
}
static int xr_uart_enable(struct usb_serial_port *port)
{
struct xr_data *data = usb_get_serial_port_data(port);
if (data->type->enable)
return data->type->enable(port);
return __xr_uart_enable(port);
}
static int xr_uart_disable(struct usb_serial_port *port)
{
struct xr_data *data = usb_get_serial_port_data(port);
if (data->type->disable)
return data->type->disable(port);
return __xr_uart_disable(port);
}
static int xr21v141x_fifo_reset(struct usb_serial_port *port)
{
int ret;
ret = xr_set_reg_um(port, XR21V141X_UM_TX_FIFO_RESET, XR_FIFO_RESET);
if (ret)
return ret;
ret = xr_set_reg_um(port, XR21V141X_UM_RX_FIFO_RESET, XR_FIFO_RESET);
if (ret)
return ret;
return 0;
}
static int xr_fifo_reset(struct usb_serial_port *port)
{
struct xr_data *data = usb_get_serial_port_data(port);
int ret;
if (data->type->fifo_reset)
return data->type->fifo_reset(port);
ret = xr_set_reg_uart(port, data->type->tx_fifo_reset, XR_FIFO_RESET);
if (ret)
return ret;
ret = xr_set_reg_uart(port, data->type->rx_fifo_reset, XR_FIFO_RESET);
if (ret)
return ret;
return 0;
}
static int xr_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
u8 status;
struct xr_data *data = usb_get_serial_port_data(port);
u16 status;
int ret;
ret = xr_get_reg_uart(port, XR21V141X_REG_GPIO_STATUS, &status);
ret = xr_get_reg_uart(port, data->type->gpio_status, &status);
if (ret)
return ret;
@ -230,12 +447,12 @@ static int xr_tiocmget(struct tty_struct *tty)
* Modem control pins are active low, so reading '0' means it is active
* and '1' means not active.
*/
ret = ((status & XR21V141X_UART_MODE_DTR) ? 0 : TIOCM_DTR) |
((status & XR21V141X_UART_MODE_RTS) ? 0 : TIOCM_RTS) |
((status & XR21V141X_UART_MODE_CTS) ? 0 : TIOCM_CTS) |
((status & XR21V141X_UART_MODE_DSR) ? 0 : TIOCM_DSR) |
((status & XR21V141X_UART_MODE_RI) ? 0 : TIOCM_RI) |
((status & XR21V141X_UART_MODE_CD) ? 0 : TIOCM_CD);
ret = ((status & XR_GPIO_DTR) ? 0 : TIOCM_DTR) |
((status & XR_GPIO_RTS) ? 0 : TIOCM_RTS) |
((status & XR_GPIO_CTS) ? 0 : TIOCM_CTS) |
((status & XR_GPIO_DSR) ? 0 : TIOCM_DSR) |
((status & XR_GPIO_RI) ? 0 : TIOCM_RI) |
((status & XR_GPIO_CD) ? 0 : TIOCM_CD);
return ret;
}
@ -243,26 +460,28 @@ static int xr_tiocmget(struct tty_struct *tty)
static int xr_tiocmset_port(struct usb_serial_port *port,
unsigned int set, unsigned int clear)
{
u8 gpio_set = 0;
u8 gpio_clr = 0;
struct xr_data *data = usb_get_serial_port_data(port);
const struct xr_type *type = data->type;
u16 gpio_set = 0;
u16 gpio_clr = 0;
int ret = 0;
/* Modem control pins are active low, so set & clr are swapped */
if (set & TIOCM_RTS)
gpio_clr |= XR21V141X_UART_MODE_RTS;
gpio_clr |= XR_GPIO_RTS;
if (set & TIOCM_DTR)
gpio_clr |= XR21V141X_UART_MODE_DTR;
gpio_clr |= XR_GPIO_DTR;
if (clear & TIOCM_RTS)
gpio_set |= XR21V141X_UART_MODE_RTS;
gpio_set |= XR_GPIO_RTS;
if (clear & TIOCM_DTR)
gpio_set |= XR21V141X_UART_MODE_DTR;
gpio_set |= XR_GPIO_DTR;
/* Writing '0' to gpio_{set/clr} bits has no effect, so no need to do */
if (gpio_clr)
ret = xr_set_reg_uart(port, XR21V141X_REG_GPIO_CLR, gpio_clr);
ret = xr_set_reg_uart(port, type->gpio_clear, gpio_clr);
if (gpio_set)
ret = xr_set_reg_uart(port, XR21V141X_REG_GPIO_SET, gpio_set);
ret = xr_set_reg_uart(port, type->gpio_set, gpio_set);
return ret;
}
@ -286,16 +505,18 @@ static void xr_dtr_rts(struct usb_serial_port *port, int on)
static void xr_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
u8 state;
struct xr_data *data = usb_get_serial_port_data(port);
const struct xr_type *type = data->type;
u16 state;
if (break_state == 0)
state = XR21V141X_UART_BREAK_OFF;
state = 0;
else
state = XR21V141X_UART_BREAK_ON;
state = GENMASK(type->reg_width - 1, 0);
dev_dbg(&port->dev, "Turning break %s\n",
state == XR21V141X_UART_BREAK_OFF ? "off" : "on");
xr_set_reg_uart(port, XR21V141X_REG_TX_BREAK, state);
dev_dbg(&port->dev, "Turning break %s\n", state == 0 ? "off" : "on");
xr_set_reg_uart(port, type->tx_break, state);
}
/* Tx and Rx clock mask values obtained from section 3.3.4 of datasheet */
@ -334,8 +555,7 @@ static const struct xr_txrx_clk_mask xr21v141x_txrx_clk_masks[] = {
{ 0xfff, 0xffe, 0xffd },
};
static int xr_set_baudrate(struct tty_struct *tty,
struct usb_serial_port *port)
static int xr21v141x_set_baudrate(struct tty_struct *tty, struct usb_serial_port *port)
{
u32 divisor, baud, idx;
u16 tx_mask, rx_mask;
@ -405,43 +625,47 @@ static void xr_set_flow_mode(struct tty_struct *tty,
struct usb_serial_port *port,
struct ktermios *old_termios)
{
u8 flow, gpio_mode;
struct xr_data *data = usb_get_serial_port_data(port);
const struct xr_type *type = data->type;
u16 flow, gpio_mode;
int ret;
ret = xr_get_reg_uart(port, XR21V141X_REG_GPIO_MODE, &gpio_mode);
ret = xr_get_reg_uart(port, type->gpio_mode, &gpio_mode);
if (ret)
return;
/*
* According to the datasheets, the UART needs to be disabled while
* writing to the FLOW_CONTROL register (XR21V141X), or any register
* but GPIO_SET, GPIO_CLEAR, TX_BREAK and ERROR_STATUS (XR21B142X).
*/
xr_uart_disable(port);
/* Set GPIO mode for controlling the pins manually by default. */
gpio_mode &= ~XR21V141X_UART_MODE_GPIO_MASK;
gpio_mode &= ~XR_GPIO_MODE_SEL_MASK;
if (C_CRTSCTS(tty) && C_BAUD(tty) != B0) {
dev_dbg(&port->dev, "Enabling hardware flow ctrl\n");
gpio_mode |= XR21V141X_UART_MODE_RTS_CTS;
flow = XR21V141X_UART_FLOW_MODE_HW;
gpio_mode |= XR_GPIO_MODE_SEL_RTS_CTS;
flow = XR_UART_FLOW_MODE_HW;
} else if (I_IXON(tty)) {
u8 start_char = START_CHAR(tty);
u8 stop_char = STOP_CHAR(tty);
dev_dbg(&port->dev, "Enabling sw flow ctrl\n");
flow = XR21V141X_UART_FLOW_MODE_SW;
flow = XR_UART_FLOW_MODE_SW;
xr_set_reg_uart(port, XR21V141X_REG_XON_CHAR, start_char);
xr_set_reg_uart(port, XR21V141X_REG_XOFF_CHAR, stop_char);
xr_set_reg_uart(port, type->xon_char, start_char);
xr_set_reg_uart(port, type->xoff_char, stop_char);
} else {
dev_dbg(&port->dev, "Disabling flow ctrl\n");
flow = XR21V141X_UART_FLOW_MODE_NONE;
flow = XR_UART_FLOW_MODE_NONE;
}
/*
* As per the datasheet, UART needs to be disabled while writing to
* FLOW_CONTROL register.
*/
xr_uart_disable(port);
xr_set_reg_uart(port, XR21V141X_REG_FLOW_CTRL, flow);
xr_uart_enable(port);
xr_set_reg_uart(port, type->flow_control, flow);
xr_set_reg_uart(port, type->gpio_mode, gpio_mode);
xr_set_reg_uart(port, XR21V141X_REG_GPIO_MODE, gpio_mode);
xr_uart_enable(port);
if (C_BAUD(tty) == B0)
xr_dtr_rts(port, 0);
@ -449,16 +673,15 @@ static void xr_set_flow_mode(struct tty_struct *tty,
xr_dtr_rts(port, 1);
}
static void xr_set_termios(struct tty_struct *tty,
struct usb_serial_port *port,
struct ktermios *old_termios)
static void xr21v141x_set_line_settings(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
struct ktermios *termios = &tty->termios;
u8 bits = 0;
int ret;
if (!old_termios || (tty->termios.c_ospeed != old_termios->c_ospeed))
xr_set_baudrate(tty, port);
xr21v141x_set_baudrate(tty, port);
switch (C_CSIZE(tty)) {
case CS5:
@ -468,61 +691,154 @@ static void xr_set_termios(struct tty_struct *tty,
if (old_termios)
termios->c_cflag |= old_termios->c_cflag & CSIZE;
else
bits |= XR21V141X_UART_DATA_8;
termios->c_cflag |= CS8;
if (C_CSIZE(tty) == CS7)
bits |= XR_UART_DATA_7;
else
bits |= XR_UART_DATA_8;
break;
case CS7:
bits |= XR21V141X_UART_DATA_7;
bits |= XR_UART_DATA_7;
break;
case CS8:
default:
bits |= XR21V141X_UART_DATA_8;
bits |= XR_UART_DATA_8;
break;
}
if (C_PARENB(tty)) {
if (C_CMSPAR(tty)) {
if (C_PARODD(tty))
bits |= XR21V141X_UART_PARITY_MARK;
bits |= XR_UART_PARITY_MARK;
else
bits |= XR21V141X_UART_PARITY_SPACE;
bits |= XR_UART_PARITY_SPACE;
} else {
if (C_PARODD(tty))
bits |= XR21V141X_UART_PARITY_ODD;
bits |= XR_UART_PARITY_ODD;
else
bits |= XR21V141X_UART_PARITY_EVEN;
bits |= XR_UART_PARITY_EVEN;
}
}
if (C_CSTOPB(tty))
bits |= XR21V141X_UART_STOP_2;
bits |= XR_UART_STOP_2;
else
bits |= XR21V141X_UART_STOP_1;
bits |= XR_UART_STOP_1;
ret = xr_set_reg_uart(port, XR21V141X_REG_FORMAT, bits);
if (ret)
return;
}
static void xr_cdc_set_line_coding(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
struct xr_data *data = usb_get_serial_port_data(port);
struct usb_host_interface *alt = port->serial->interface->cur_altsetting;
struct usb_device *udev = port->serial->dev;
struct usb_cdc_line_coding *lc;
int ret;
lc = kzalloc(sizeof(*lc), GFP_KERNEL);
if (!lc)
return;
if (tty->termios.c_ospeed)
lc->dwDTERate = cpu_to_le32(tty->termios.c_ospeed);
else if (old_termios)
lc->dwDTERate = cpu_to_le32(old_termios->c_ospeed);
else
lc->dwDTERate = cpu_to_le32(9600);
if (C_CSTOPB(tty))
lc->bCharFormat = USB_CDC_2_STOP_BITS;
else
lc->bCharFormat = USB_CDC_1_STOP_BITS;
if (C_PARENB(tty)) {
if (C_CMSPAR(tty)) {
if (C_PARODD(tty))
lc->bParityType = USB_CDC_MARK_PARITY;
else
lc->bParityType = USB_CDC_SPACE_PARITY;
} else {
if (C_PARODD(tty))
lc->bParityType = USB_CDC_ODD_PARITY;
else
lc->bParityType = USB_CDC_EVEN_PARITY;
}
} else {
lc->bParityType = USB_CDC_NO_PARITY;
}
if (!data->type->have_5_6_bit_mode &&
(C_CSIZE(tty) == CS5 || C_CSIZE(tty) == CS6)) {
tty->termios.c_cflag &= ~CSIZE;
if (old_termios)
tty->termios.c_cflag |= old_termios->c_cflag & CSIZE;
else
tty->termios.c_cflag |= CS8;
}
switch (C_CSIZE(tty)) {
case CS5:
lc->bDataBits = 5;
break;
case CS6:
lc->bDataBits = 6;
break;
case CS7:
lc->bDataBits = 7;
break;
case CS8:
default:
lc->bDataBits = 8;
break;
}
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
USB_CDC_REQ_SET_LINE_CODING,
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, alt->desc.bInterfaceNumber,
lc, sizeof(*lc), USB_CTRL_SET_TIMEOUT);
if (ret < 0)
dev_err(&port->dev, "Failed to set line coding: %d\n", ret);
kfree(lc);
}
static void xr_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
struct xr_data *data = usb_get_serial_port_data(port);
/*
* XR21V141X does not have a CUSTOM_DRIVER flag and always enters CDC
* mode upon receiving CDC requests.
*/
if (data->type->set_line_settings)
data->type->set_line_settings(tty, port, old_termios);
else
xr_cdc_set_line_coding(tty, port, old_termios);
xr_set_flow_mode(tty, port, old_termios);
}
static int xr_open(struct tty_struct *tty, struct usb_serial_port *port)
{
u8 gpio_dir;
int ret;
ret = xr_fifo_reset(port);
if (ret)
return ret;
ret = xr_uart_enable(port);
if (ret) {
dev_err(&port->dev, "Failed to enable UART\n");
return ret;
}
/*
* Configure DTR and RTS as outputs and RI, CD, DSR and CTS as
* inputs.
*/
gpio_dir = XR21V141X_UART_MODE_DTR | XR21V141X_UART_MODE_RTS;
xr_set_reg_uart(port, XR21V141X_REG_GPIO_DIR, gpio_dir);
/* Setup termios */
if (tty)
xr_set_termios(tty, port, NULL);
@ -545,15 +861,133 @@ static void xr_close(struct usb_serial_port *port)
static int xr_probe(struct usb_serial *serial, const struct usb_device_id *id)
{
/* Don't bind to control interface */
if (serial->interface->cur_altsetting->desc.bInterfaceNumber == 0)
struct usb_interface *control = serial->interface;
struct usb_host_interface *alt = control->cur_altsetting;
struct usb_cdc_parsed_header hdrs;
struct usb_cdc_union_desc *desc;
struct usb_interface *data;
int ret;
ret = cdc_parse_cdc_header(&hdrs, control, alt->extra, alt->extralen);
if (ret < 0)
return -ENODEV;
desc = hdrs.usb_cdc_union_desc;
if (!desc)
return -ENODEV;
data = usb_ifnum_to_if(serial->dev, desc->bSlaveInterface0);
if (!data)
return -ENODEV;
ret = usb_serial_claim_interface(serial, data);
if (ret)
return ret;
usb_set_serial_data(serial, (void *)id->driver_info);
return 0;
}
static int xr_gpio_init(struct usb_serial_port *port, const struct xr_type *type)
{
u16 mask, mode;
int ret;
/*
* Configure all pins as GPIO except for Receive and Transmit Toggle.
*/
mode = 0;
if (type->have_xmit_toggle)
mode |= XR_GPIO_MODE_RX_TOGGLE | XR_GPIO_MODE_TX_TOGGLE;
ret = xr_set_reg_uart(port, type->gpio_mode, mode);
if (ret)
return ret;
/*
* Configure DTR and RTS as outputs and make sure they are deasserted
* (active low), and configure RI, CD, DSR and CTS as inputs.
*/
mask = XR_GPIO_DTR | XR_GPIO_RTS;
ret = xr_set_reg_uart(port, type->gpio_direction, mask);
if (ret)
return ret;
ret = xr_set_reg_uart(port, type->gpio_set, mask);
if (ret)
return ret;
return 0;
}
static int xr_port_probe(struct usb_serial_port *port)
{
struct usb_interface_descriptor *desc;
const struct xr_type *type;
struct xr_data *data;
enum xr_type_id type_id;
int ret;
type_id = (int)(unsigned long)usb_get_serial_data(port->serial);
type = &xr_types[type_id];
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->type = type;
desc = &port->serial->interface->cur_altsetting->desc;
if (type_id == XR21V141X)
data->channel = desc->bInterfaceNumber / 2;
else
data->channel = desc->bInterfaceNumber;
usb_set_serial_port_data(port, data);
if (type->custom_driver) {
ret = xr_set_reg_uart(port, type->custom_driver,
XR_CUSTOM_DRIVER_ACTIVE);
if (ret)
goto err_free;
}
ret = xr_gpio_init(port, type);
if (ret)
goto err_free;
return 0;
err_free:
kfree(data);
return ret;
}
static void xr_port_remove(struct usb_serial_port *port)
{
struct xr_data *data = usb_get_serial_port_data(port);
kfree(data);
}
#define XR_DEVICE(vid, pid, type) \
USB_DEVICE_INTERFACE_CLASS((vid), (pid), USB_CLASS_COMM), \
.driver_info = (type)
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x04e2, 0x1410) }, /* XR21V141X */
{ XR_DEVICE(0x04e2, 0x1400, XR2280X) },
{ XR_DEVICE(0x04e2, 0x1401, XR2280X) },
{ XR_DEVICE(0x04e2, 0x1402, XR2280X) },
{ XR_DEVICE(0x04e2, 0x1403, XR2280X) },
{ XR_DEVICE(0x04e2, 0x1410, XR21V141X) },
{ XR_DEVICE(0x04e2, 0x1411, XR21B1411) },
{ XR_DEVICE(0x04e2, 0x1412, XR21V141X) },
{ XR_DEVICE(0x04e2, 0x1414, XR21V141X) },
{ XR_DEVICE(0x04e2, 0x1420, XR21B142X) },
{ XR_DEVICE(0x04e2, 0x1422, XR21B142X) },
{ XR_DEVICE(0x04e2, 0x1424, XR21B142X) },
{ }
};
MODULE_DEVICE_TABLE(usb, id_table);
@ -566,6 +1000,8 @@ static struct usb_serial_driver xr_device = {
.id_table = id_table,
.num_ports = 1,
.probe = xr_probe,
.port_probe = xr_port_probe,
.port_remove = xr_port_remove,
.open = xr_open,
.close = xr_close,
.break_ctl = xr_break_ctl,

View File

@ -130,6 +130,8 @@ static inline void usb_set_serial_port_data(struct usb_serial_port *port,
* @dev: pointer to the struct usb_device for this device
* @type: pointer to the struct usb_serial_driver for this device
* @interface: pointer to the struct usb_interface for this device
* @sibling: pointer to the struct usb_interface of any sibling interface
* @suspend_count: number of suspended (sibling) interfaces
* @num_ports: the number of ports this device has
* @num_interrupt_in: number of interrupt in endpoints we have
* @num_interrupt_out: number of interrupt out endpoints we have
@ -145,8 +147,9 @@ struct usb_serial {
struct usb_device *dev;
struct usb_serial_driver *type;
struct usb_interface *interface;
struct usb_interface *sibling;
unsigned int suspend_count;
unsigned char disconnected:1;
unsigned char suspending:1;
unsigned char attached:1;
unsigned char minors_reserved:1;
unsigned char num_ports;
@ -276,7 +279,7 @@ struct usb_serial_driver {
int (*write_room)(struct tty_struct *tty);
int (*ioctl)(struct tty_struct *tty,
unsigned int cmd, unsigned long arg);
int (*get_serial)(struct tty_struct *tty, struct serial_struct *ss);
void (*get_serial)(struct tty_struct *tty, struct serial_struct *ss);
int (*set_serial)(struct tty_struct *tty, struct serial_struct *ss);
void (*set_termios)(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old);
@ -335,6 +338,9 @@ static inline void usb_serial_console_disconnect(struct usb_serial *serial) {}
/* Functions needed by other parts of the usbserial core */
struct usb_serial_port *usb_serial_port_get_by_minor(unsigned int minor);
void usb_serial_put(struct usb_serial *serial);
int usb_serial_claim_interface(struct usb_serial *serial, struct usb_interface *intf);
int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port);
int usb_serial_generic_write_start(struct usb_serial_port *port, gfp_t mem_flags);
int usb_serial_generic_write(struct tty_struct *tty, struct usb_serial_port *port,