mirror of https://gitee.com/openkylin/linux.git
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:
commit
7e25c20df4
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue