forked from luck/tmp_suning_uos_patched
USB-serial updates for 5.9-rc1
Here are the USB-serial updates for 5.9-rc1, including: - console flow-control support - simulated line-breaks on some ch341 - hardware flow-control fixes for cp210x - break-detection and sysrq fixes for ftdi_sio - sysrq optimisations - input parity checking for cp210x Included are also some new device ids and various clean ups. All have been in linux-next with no reported issues. -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQQHbPq+cpGvN/peuzMLxc3C7H1lCAUCXyAjIwAKCRALxc3C7H1l CHruAQDTSejnRcrxMqU6mqL2AuEw+fABGUxjE+ah/HbXMf7CDwD/d0XQFimA8U8J ovxTVm35R+vYQ7T7jTNuVxso6nWGxw8= =15J7 -----END PGP SIGNATURE----- Merge tag 'usb-serial-5.9-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-next Johan writes: USB-serial updates for 5.9-rc1 Here are the USB-serial updates for 5.9-rc1, including: - console flow-control support - simulated line-breaks on some ch341 - hardware flow-control fixes for cp210x - break-detection and sysrq fixes for ftdi_sio - sysrq optimisations - input parity checking for cp210x Included are also some new device ids and various clean ups. All have been in linux-next with no reported issues. * tag 'usb-serial-5.9-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial: (31 commits) USB: serial: qcserial: add EM7305 QDL product ID USB: serial: iuu_phoenix: fix led-activity helpers USB: serial: sierra: clean up special-interface handling USB: serial: cp210x: use in-kernel types in port data USB: serial: cp210x: drop unnecessary packed attributes USB: serial: cp210x: add support for TIOCGICOUNT USB: serial: cp210x: add support for line-status events USB: serial: cp210x: disable interface on errors in open USB: serial: drop redundant transfer-buffer casts USB: serial: drop extern keyword from function declarations USB: serial: drop unnecessary sysrq include USB: serial: add sysrq break-handler dummy USB: serial: inline sysrq dummy function USB: serial: only process sysrq when enabled USB: serial: only set sysrq timestamp for consoles USB: serial: ftdi_sio: fix break and sysrq handling USB: serial: ftdi_sio: clean up receive processing USB: serial: ftdi_sio: make process-packet buffer unsigned USB: serial: use fallthrough pseudo-keyword USB: serial: ch341: fix missing simulated-break margin ...
This commit is contained in:
commit
fa56dd9152
|
@ -117,7 +117,7 @@ static int aircable_process_packet(struct usb_serial_port *port,
|
|||
static void aircable_process_read_urb(struct urb *urb)
|
||||
{
|
||||
struct usb_serial_port *port = urb->context;
|
||||
char *data = (char *)urb->transfer_buffer;
|
||||
char *data = urb->transfer_buffer;
|
||||
int has_headers;
|
||||
int count;
|
||||
int len;
|
||||
|
|
|
@ -59,7 +59,11 @@
|
|||
#define CH341_REQ_MODEM_CTRL 0xA4
|
||||
|
||||
#define CH341_REG_BREAK 0x05
|
||||
#define CH341_REG_PRESCALER 0x12
|
||||
#define CH341_REG_DIVISOR 0x13
|
||||
#define CH341_REG_LCR 0x18
|
||||
#define CH341_REG_LCR2 0x25
|
||||
|
||||
#define CH341_NBREAK_BITS 0x01
|
||||
|
||||
#define CH341_LCR_ENABLE_RX 0x80
|
||||
|
@ -74,6 +78,7 @@
|
|||
#define CH341_LCR_CS5 0x00
|
||||
|
||||
#define CH341_QUIRK_LIMITED_PRESCALER BIT(0)
|
||||
#define CH341_QUIRK_SIMULATE_BREAK BIT(1)
|
||||
|
||||
static const struct usb_device_id id_table[] = {
|
||||
{ USB_DEVICE(0x4348, 0x5523) },
|
||||
|
@ -91,6 +96,7 @@ struct ch341_private {
|
|||
u8 msr;
|
||||
u8 lcr;
|
||||
unsigned long quirks;
|
||||
unsigned long break_end;
|
||||
};
|
||||
|
||||
static void ch341_set_termios(struct tty_struct *tty,
|
||||
|
@ -153,6 +159,10 @@ static const speed_t ch341_min_rates[] = {
|
|||
CH341_MIN_RATE(3),
|
||||
};
|
||||
|
||||
/* Supported range is 46 to 3000000 bps. */
|
||||
#define CH341_MIN_BPS DIV_ROUND_UP(CH341_CLKRATE, CH341_CLK_DIV(0, 0) * 256)
|
||||
#define CH341_MAX_BPS (CH341_CLKRATE / (CH341_CLK_DIV(3, 0) * 2))
|
||||
|
||||
/*
|
||||
* The device line speed is given by the following equation:
|
||||
*
|
||||
|
@ -163,10 +173,9 @@ static const speed_t ch341_min_rates[] = {
|
|||
* 2 <= div <= 256 if fact = 0, or
|
||||
* 9 <= div <= 256 if fact = 1
|
||||
*/
|
||||
static int ch341_get_divisor(struct ch341_private *priv)
|
||||
static int ch341_get_divisor(struct ch341_private *priv, speed_t speed)
|
||||
{
|
||||
unsigned int fact, div, clk_div;
|
||||
speed_t speed = priv->baud_rate;
|
||||
bool force_fact0 = false;
|
||||
int ps;
|
||||
|
||||
|
@ -174,7 +183,7 @@ static int ch341_get_divisor(struct ch341_private *priv)
|
|||
* Clamp to supported range, this makes the (ps < 0) and (div < 2)
|
||||
* sanity checks below redundant.
|
||||
*/
|
||||
speed = clamp(speed, 46U, 3000000U);
|
||||
speed = clamp_val(speed, CH341_MIN_BPS, CH341_MAX_BPS);
|
||||
|
||||
/*
|
||||
* Start with highest possible base clock (fact = 1) that will give a
|
||||
|
@ -229,15 +238,16 @@ static int ch341_get_divisor(struct ch341_private *priv)
|
|||
}
|
||||
|
||||
static int ch341_set_baudrate_lcr(struct usb_device *dev,
|
||||
struct ch341_private *priv, u8 lcr)
|
||||
struct ch341_private *priv,
|
||||
speed_t baud_rate, u8 lcr)
|
||||
{
|
||||
int val;
|
||||
int r;
|
||||
|
||||
if (!priv->baud_rate)
|
||||
if (!baud_rate)
|
||||
return -EINVAL;
|
||||
|
||||
val = ch341_get_divisor(priv);
|
||||
val = ch341_get_divisor(priv, baud_rate);
|
||||
if (val < 0)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -247,11 +257,20 @@ static int ch341_set_baudrate_lcr(struct usb_device *dev,
|
|||
*/
|
||||
val |= BIT(7);
|
||||
|
||||
r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x1312, val);
|
||||
r = ch341_control_out(dev, CH341_REQ_WRITE_REG,
|
||||
CH341_REG_DIVISOR << 8 | CH341_REG_PRESCALER,
|
||||
val);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x2518, lcr);
|
||||
/*
|
||||
* Chip versions before version 0x30 as read using
|
||||
* CH341_REQ_READ_VERSION used separate registers for line control
|
||||
* (stop bits, parity and word length). Version 0x30 and above use
|
||||
* CH341_REG_LCR only and CH341_REG_LCR2 is always set to zero.
|
||||
*/
|
||||
r = ch341_control_out(dev, CH341_REQ_WRITE_REG,
|
||||
CH341_REG_LCR2 << 8 | CH341_REG_LCR, lcr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -308,7 +327,7 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
|
|||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
r = ch341_set_baudrate_lcr(dev, priv, priv->lcr);
|
||||
r = ch341_set_baudrate_lcr(dev, priv, priv->baud_rate, priv->lcr);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
|
@ -341,8 +360,8 @@ static int ch341_detect_quirks(struct usb_serial_port *port)
|
|||
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
|
||||
CH341_REG_BREAK, 0, buffer, size, DEFAULT_TIMEOUT);
|
||||
if (r == -EPIPE) {
|
||||
dev_dbg(&port->dev, "break control not supported\n");
|
||||
quirks = CH341_QUIRK_LIMITED_PRESCALER;
|
||||
dev_info(&port->dev, "break control not supported, using simulated break\n");
|
||||
quirks = CH341_QUIRK_LIMITED_PRESCALER | CH341_QUIRK_SIMULATE_BREAK;
|
||||
r = 0;
|
||||
goto out;
|
||||
}
|
||||
|
@ -523,7 +542,8 @@ static void ch341_set_termios(struct tty_struct *tty,
|
|||
if (baud_rate) {
|
||||
priv->baud_rate = baud_rate;
|
||||
|
||||
r = ch341_set_baudrate_lcr(port->serial->dev, priv, lcr);
|
||||
r = ch341_set_baudrate_lcr(port->serial->dev, priv,
|
||||
priv->baud_rate, lcr);
|
||||
if (r < 0 && old_termios) {
|
||||
priv->baud_rate = tty_termios_baud_rate(old_termios);
|
||||
tty_termios_copy_hw(&tty->termios, old_termios);
|
||||
|
@ -542,15 +562,98 @@ static void ch341_set_termios(struct tty_struct *tty,
|
|||
ch341_set_handshake(port->serial->dev, priv->mcr);
|
||||
}
|
||||
|
||||
/*
|
||||
* A subset of all CH34x devices don't support a real break condition and
|
||||
* reading CH341_REG_BREAK fails (see also ch341_detect_quirks). This function
|
||||
* simulates a break condition by lowering the baud rate to the minimum
|
||||
* supported by the hardware upon enabling the break condition and sending
|
||||
* a NUL byte.
|
||||
*
|
||||
* Incoming data is corrupted while the break condition is being simulated.
|
||||
*
|
||||
* Normally the duration of the break condition can be controlled individually
|
||||
* by userspace using TIOCSBRK and TIOCCBRK or by passing an argument to
|
||||
* TCSBRKP. Due to how the simulation is implemented the duration can't be
|
||||
* controlled. The duration is always about (1s / 46bd * 9bit) = 196ms.
|
||||
*/
|
||||
static void ch341_simulate_break(struct tty_struct *tty, int break_state)
|
||||
{
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
struct ch341_private *priv = usb_get_serial_port_data(port);
|
||||
unsigned long now, delay;
|
||||
int r;
|
||||
|
||||
if (break_state != 0) {
|
||||
dev_dbg(&port->dev, "enter break state requested\n");
|
||||
|
||||
r = ch341_set_baudrate_lcr(port->serial->dev, priv,
|
||||
CH341_MIN_BPS,
|
||||
CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX | CH341_LCR_CS8);
|
||||
if (r < 0) {
|
||||
dev_err(&port->dev,
|
||||
"failed to change baud rate to %u: %d\n",
|
||||
CH341_MIN_BPS, r);
|
||||
goto restore;
|
||||
}
|
||||
|
||||
r = tty_put_char(tty, '\0');
|
||||
if (r < 0) {
|
||||
dev_err(&port->dev,
|
||||
"failed to write NUL byte for simulated break condition: %d\n",
|
||||
r);
|
||||
goto restore;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute expected transmission duration including safety
|
||||
* margin. The original baud rate is only restored after the
|
||||
* computed point in time.
|
||||
*
|
||||
* 11 bits = 1 start, 8 data, 1 stop, 1 margin
|
||||
*/
|
||||
priv->break_end = jiffies + (11 * HZ / CH341_MIN_BPS);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
dev_dbg(&port->dev, "leave break state requested\n");
|
||||
|
||||
now = jiffies;
|
||||
|
||||
if (time_before(now, priv->break_end)) {
|
||||
/* Wait until NUL byte is written */
|
||||
delay = priv->break_end - now;
|
||||
dev_dbg(&port->dev,
|
||||
"wait %d ms while transmitting NUL byte at %u baud\n",
|
||||
jiffies_to_msecs(delay), CH341_MIN_BPS);
|
||||
schedule_timeout_interruptible(delay);
|
||||
}
|
||||
|
||||
restore:
|
||||
/* Restore original baud rate */
|
||||
r = ch341_set_baudrate_lcr(port->serial->dev, priv, priv->baud_rate,
|
||||
priv->lcr);
|
||||
if (r < 0)
|
||||
dev_err(&port->dev,
|
||||
"restoring original baud rate of %u failed: %d\n",
|
||||
priv->baud_rate, r);
|
||||
}
|
||||
|
||||
static void ch341_break_ctl(struct tty_struct *tty, int break_state)
|
||||
{
|
||||
const uint16_t ch341_break_reg =
|
||||
((uint16_t) CH341_REG_LCR << 8) | CH341_REG_BREAK;
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
struct ch341_private *priv = usb_get_serial_port_data(port);
|
||||
int r;
|
||||
uint16_t reg_contents;
|
||||
uint8_t *break_reg;
|
||||
|
||||
if (priv->quirks & CH341_QUIRK_SIMULATE_BREAK) {
|
||||
ch341_simulate_break(tty, break_state);
|
||||
return;
|
||||
}
|
||||
|
||||
break_reg = kmalloc(2, GFP_KERNEL);
|
||||
if (!break_reg)
|
||||
return;
|
||||
|
|
|
@ -79,7 +79,7 @@ static int usb_console_setup(struct console *co, char *options)
|
|||
if (*s)
|
||||
doflow = (*s++ == 'r');
|
||||
}
|
||||
|
||||
|
||||
/* Sane default */
|
||||
if (baud == 0)
|
||||
baud = 9600;
|
||||
|
@ -102,6 +102,9 @@ static int usb_console_setup(struct console *co, char *options)
|
|||
break;
|
||||
}
|
||||
|
||||
if (doflow)
|
||||
cflag |= CRTSCTS;
|
||||
|
||||
/*
|
||||
* no need to check the index here: if the index is wrong, console
|
||||
* code won't call us
|
||||
|
|
|
@ -50,6 +50,9 @@ static void cp210x_release(struct usb_serial *);
|
|||
static int cp210x_port_probe(struct usb_serial_port *);
|
||||
static int cp210x_port_remove(struct usb_serial_port *);
|
||||
static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
|
||||
static void cp210x_process_read_urb(struct urb *urb);
|
||||
static void cp210x_enable_event_mode(struct usb_serial_port *port);
|
||||
static void cp210x_disable_event_mode(struct usb_serial_port *port);
|
||||
|
||||
static const struct usb_device_id id_table[] = {
|
||||
{ USB_DEVICE(0x045B, 0x0053) }, /* Renesas RX610 RX-Stick */
|
||||
|
@ -253,9 +256,21 @@ struct cp210x_serial_private {
|
|||
bool use_actual_rate;
|
||||
};
|
||||
|
||||
enum cp210x_event_state {
|
||||
ES_DATA,
|
||||
ES_ESCAPE,
|
||||
ES_LSR,
|
||||
ES_LSR_DATA_0,
|
||||
ES_LSR_DATA_1,
|
||||
ES_MSR
|
||||
};
|
||||
|
||||
struct cp210x_port_private {
|
||||
__u8 bInterfaceNumber;
|
||||
u8 bInterfaceNumber;
|
||||
bool has_swapped_line_ctl;
|
||||
bool event_mode;
|
||||
enum cp210x_event_state event_state;
|
||||
u8 lsr;
|
||||
};
|
||||
|
||||
static struct usb_serial_driver cp210x_device = {
|
||||
|
@ -272,14 +287,18 @@ static struct usb_serial_driver cp210x_device = {
|
|||
.break_ctl = cp210x_break_ctl,
|
||||
.set_termios = cp210x_set_termios,
|
||||
.tx_empty = cp210x_tx_empty,
|
||||
.throttle = usb_serial_generic_throttle,
|
||||
.unthrottle = usb_serial_generic_unthrottle,
|
||||
.tiocmget = cp210x_tiocmget,
|
||||
.tiocmset = cp210x_tiocmset,
|
||||
.get_icount = usb_serial_generic_get_icount,
|
||||
.attach = cp210x_attach,
|
||||
.disconnect = cp210x_disconnect,
|
||||
.release = cp210x_release,
|
||||
.port_probe = cp210x_port_probe,
|
||||
.port_remove = cp210x_port_remove,
|
||||
.dtr_rts = cp210x_dtr_rts
|
||||
.dtr_rts = cp210x_dtr_rts,
|
||||
.process_read_urb = cp210x_process_read_urb,
|
||||
};
|
||||
|
||||
static struct usb_serial_driver * const serial_drivers[] = {
|
||||
|
@ -401,13 +420,22 @@ struct cp210x_comm_status {
|
|||
*/
|
||||
#define PURGE_ALL 0x000f
|
||||
|
||||
/* CP210X_EMBED_EVENTS */
|
||||
#define CP210X_ESCCHAR 0xec
|
||||
|
||||
#define CP210X_LSR_OVERRUN BIT(1)
|
||||
#define CP210X_LSR_PARITY BIT(2)
|
||||
#define CP210X_LSR_FRAME BIT(3)
|
||||
#define CP210X_LSR_BREAK BIT(4)
|
||||
|
||||
|
||||
/* CP210X_GET_FLOW/CP210X_SET_FLOW read/write these 0x10 bytes */
|
||||
struct cp210x_flow_ctl {
|
||||
__le32 ulControlHandshake;
|
||||
__le32 ulFlowReplace;
|
||||
__le32 ulXonLimit;
|
||||
__le32 ulXoffLimit;
|
||||
} __packed;
|
||||
};
|
||||
|
||||
/* cp210x_flow_ctl::ulControlHandshake */
|
||||
#define CP210X_SERIAL_DTR_MASK GENMASK(1, 0)
|
||||
|
@ -441,7 +469,7 @@ struct cp210x_flow_ctl {
|
|||
struct cp210x_pin_mode {
|
||||
u8 eci;
|
||||
u8 sci;
|
||||
} __packed;
|
||||
};
|
||||
|
||||
#define CP210X_PIN_MODE_MODEM 0
|
||||
#define CP210X_PIN_MODE_GPIO BIT(0)
|
||||
|
@ -504,7 +532,7 @@ struct cp210x_single_port_config {
|
|||
struct cp210x_gpio_write {
|
||||
u8 mask;
|
||||
u8 state;
|
||||
} __packed;
|
||||
};
|
||||
|
||||
/*
|
||||
* Helper to get interface number when we only have struct usb_serial.
|
||||
|
@ -807,6 +835,7 @@ static int cp210x_get_line_ctl(struct usb_serial_port *port, u16 *ctl)
|
|||
|
||||
static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
|
||||
{
|
||||
struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
|
||||
int result;
|
||||
|
||||
result = cp210x_write_u16_reg(port, CP210X_IFC_ENABLE, UART_ENABLE);
|
||||
|
@ -818,21 +847,144 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
/* Configure the termios structure */
|
||||
cp210x_get_termios(tty, port);
|
||||
|
||||
/* The baud rate must be initialised on cp2104 */
|
||||
if (tty)
|
||||
if (tty) {
|
||||
/* The baud rate must be initialised on cp2104 */
|
||||
cp210x_change_speed(tty, port, NULL);
|
||||
|
||||
return usb_serial_generic_open(tty, port);
|
||||
if (I_INPCK(tty))
|
||||
cp210x_enable_event_mode(port);
|
||||
}
|
||||
|
||||
result = usb_serial_generic_open(tty, port);
|
||||
if (result)
|
||||
goto err_disable;
|
||||
|
||||
return 0;
|
||||
|
||||
err_disable:
|
||||
cp210x_write_u16_reg(port, CP210X_IFC_ENABLE, UART_DISABLE);
|
||||
port_priv->event_mode = false;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void cp210x_close(struct usb_serial_port *port)
|
||||
{
|
||||
struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
|
||||
|
||||
usb_serial_generic_close(port);
|
||||
|
||||
/* Clear both queues; cp2108 needs this to avoid an occasional hang */
|
||||
cp210x_write_u16_reg(port, CP210X_PURGE, PURGE_ALL);
|
||||
|
||||
cp210x_write_u16_reg(port, CP210X_IFC_ENABLE, UART_DISABLE);
|
||||
|
||||
/* Disabling the interface disables event-insertion mode. */
|
||||
port_priv->event_mode = false;
|
||||
}
|
||||
|
||||
static void cp210x_process_lsr(struct usb_serial_port *port, unsigned char lsr, char *flag)
|
||||
{
|
||||
if (lsr & CP210X_LSR_BREAK) {
|
||||
port->icount.brk++;
|
||||
*flag = TTY_BREAK;
|
||||
} else if (lsr & CP210X_LSR_PARITY) {
|
||||
port->icount.parity++;
|
||||
*flag = TTY_PARITY;
|
||||
} else if (lsr & CP210X_LSR_FRAME) {
|
||||
port->icount.frame++;
|
||||
*flag = TTY_FRAME;
|
||||
}
|
||||
|
||||
if (lsr & CP210X_LSR_OVERRUN) {
|
||||
port->icount.overrun++;
|
||||
tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
|
||||
}
|
||||
}
|
||||
|
||||
static bool cp210x_process_char(struct usb_serial_port *port, unsigned char *ch, char *flag)
|
||||
{
|
||||
struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
|
||||
|
||||
switch (port_priv->event_state) {
|
||||
case ES_DATA:
|
||||
if (*ch == CP210X_ESCCHAR) {
|
||||
port_priv->event_state = ES_ESCAPE;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
case ES_ESCAPE:
|
||||
switch (*ch) {
|
||||
case 0:
|
||||
dev_dbg(&port->dev, "%s - escape char\n", __func__);
|
||||
*ch = CP210X_ESCCHAR;
|
||||
port_priv->event_state = ES_DATA;
|
||||
return false;
|
||||
case 1:
|
||||
port_priv->event_state = ES_LSR_DATA_0;
|
||||
break;
|
||||
case 2:
|
||||
port_priv->event_state = ES_LSR;
|
||||
break;
|
||||
case 3:
|
||||
port_priv->event_state = ES_MSR;
|
||||
break;
|
||||
default:
|
||||
dev_err(&port->dev, "malformed event 0x%02x\n", *ch);
|
||||
port_priv->event_state = ES_DATA;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ES_LSR_DATA_0:
|
||||
port_priv->lsr = *ch;
|
||||
port_priv->event_state = ES_LSR_DATA_1;
|
||||
break;
|
||||
case ES_LSR_DATA_1:
|
||||
dev_dbg(&port->dev, "%s - lsr = 0x%02x, data = 0x%02x\n",
|
||||
__func__, port_priv->lsr, *ch);
|
||||
cp210x_process_lsr(port, port_priv->lsr, flag);
|
||||
port_priv->event_state = ES_DATA;
|
||||
return false;
|
||||
case ES_LSR:
|
||||
dev_dbg(&port->dev, "%s - lsr = 0x%02x\n", __func__, *ch);
|
||||
port_priv->lsr = *ch;
|
||||
cp210x_process_lsr(port, port_priv->lsr, flag);
|
||||
port_priv->event_state = ES_DATA;
|
||||
break;
|
||||
case ES_MSR:
|
||||
dev_dbg(&port->dev, "%s - msr = 0x%02x\n", __func__, *ch);
|
||||
/* unimplemented */
|
||||
port_priv->event_state = ES_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void cp210x_process_read_urb(struct urb *urb)
|
||||
{
|
||||
struct usb_serial_port *port = urb->context;
|
||||
struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
|
||||
unsigned char *ch = urb->transfer_buffer;
|
||||
char flag;
|
||||
int i;
|
||||
|
||||
if (!urb->actual_length)
|
||||
return;
|
||||
|
||||
if (port_priv->event_mode) {
|
||||
for (i = 0; i < urb->actual_length; i++, ch++) {
|
||||
flag = TTY_NORMAL;
|
||||
|
||||
if (cp210x_process_char(port, ch, &flag))
|
||||
continue;
|
||||
|
||||
tty_insert_flip_char(&port->port, *ch, flag);
|
||||
}
|
||||
} else {
|
||||
tty_insert_flip_string(&port->port, ch, urb->actual_length);
|
||||
}
|
||||
tty_flip_buffer_push(&port->port);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -915,6 +1067,7 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
|
|||
u32 baud;
|
||||
u16 bits;
|
||||
u32 ctl_hs;
|
||||
u32 flow_repl;
|
||||
|
||||
cp210x_read_u32_reg(port, CP210X_GET_BAUDRATE, &baud);
|
||||
|
||||
|
@ -1015,6 +1168,22 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
|
|||
ctl_hs = le32_to_cpu(flow_ctl.ulControlHandshake);
|
||||
if (ctl_hs & CP210X_SERIAL_CTS_HANDSHAKE) {
|
||||
dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__);
|
||||
/*
|
||||
* When the port is closed, the CP210x hardware disables
|
||||
* auto-RTS and RTS is deasserted but it leaves auto-CTS when
|
||||
* in hardware flow control mode. When re-opening the port, if
|
||||
* auto-CTS is enabled on the cp210x, then auto-RTS must be
|
||||
* re-enabled in the driver.
|
||||
*/
|
||||
flow_repl = le32_to_cpu(flow_ctl.ulFlowReplace);
|
||||
flow_repl &= ~CP210X_SERIAL_RTS_MASK;
|
||||
flow_repl |= CP210X_SERIAL_RTS_SHIFT(CP210X_SERIAL_RTS_FLOW_CTL);
|
||||
flow_ctl.ulFlowReplace = cpu_to_le32(flow_repl);
|
||||
cp210x_write_reg_block(port,
|
||||
CP210X_SET_FLOW,
|
||||
&flow_ctl,
|
||||
sizeof(flow_ctl));
|
||||
|
||||
cflag |= CRTSCTS;
|
||||
} else {
|
||||
dev_dbg(dev, "%s - flow control = NONE\n", __func__);
|
||||
|
@ -1148,6 +1317,41 @@ static void cp210x_change_speed(struct tty_struct *tty,
|
|||
tty_encode_baud_rate(tty, baud, baud);
|
||||
}
|
||||
|
||||
static void cp210x_enable_event_mode(struct usb_serial_port *port)
|
||||
{
|
||||
struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
|
||||
int ret;
|
||||
|
||||
if (port_priv->event_mode)
|
||||
return;
|
||||
|
||||
port_priv->event_state = ES_DATA;
|
||||
port_priv->event_mode = true;
|
||||
|
||||
ret = cp210x_write_u16_reg(port, CP210X_EMBED_EVENTS, CP210X_ESCCHAR);
|
||||
if (ret) {
|
||||
dev_err(&port->dev, "failed to enable events: %d\n", ret);
|
||||
port_priv->event_mode = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void cp210x_disable_event_mode(struct usb_serial_port *port)
|
||||
{
|
||||
struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
|
||||
int ret;
|
||||
|
||||
if (!port_priv->event_mode)
|
||||
return;
|
||||
|
||||
ret = cp210x_write_u16_reg(port, CP210X_EMBED_EVENTS, 0);
|
||||
if (ret) {
|
||||
dev_err(&port->dev, "failed to disable events: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
port_priv->event_mode = false;
|
||||
}
|
||||
|
||||
static void cp210x_set_termios(struct tty_struct *tty,
|
||||
struct usb_serial_port *port, struct ktermios *old_termios)
|
||||
{
|
||||
|
@ -1270,6 +1474,14 @@ static void cp210x_set_termios(struct tty_struct *tty,
|
|||
sizeof(flow_ctl));
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable event-insertion mode only if input parity checking is
|
||||
* enabled for now.
|
||||
*/
|
||||
if (I_INPCK(tty))
|
||||
cp210x_enable_event_mode(port);
|
||||
else
|
||||
cp210x_disable_event_mode(port);
|
||||
}
|
||||
|
||||
static int cp210x_tiocmset(struct tty_struct *tty,
|
||||
|
|
|
@ -1048,7 +1048,7 @@ static void cypress_read_int_callback(struct urb *urb)
|
|||
return;
|
||||
case -EPIPE:
|
||||
/* Can't call usb_clear_halt while in_interrupt */
|
||||
/* FALLS THROUGH */
|
||||
fallthrough;
|
||||
default:
|
||||
/* something ugly is going on... */
|
||||
dev_err(dev, "%s - unexpected nonzero read status received: %d\n",
|
||||
|
@ -1197,7 +1197,7 @@ static void cypress_write_int_callback(struct urb *urb)
|
|||
return;
|
||||
case -EPIPE:
|
||||
/* Cannot call usb_clear_halt while in_interrupt */
|
||||
/* FALLTHROUGH */
|
||||
fallthrough;
|
||||
default:
|
||||
dev_err(dev, "%s - unexpected nonzero write status received: %d\n",
|
||||
__func__, status);
|
||||
|
|
|
@ -424,7 +424,7 @@ static void f81232_process_read_urb(struct urb *urb)
|
|||
lsr = data[i];
|
||||
tty_flag = f81232_handle_lsr(port, lsr);
|
||||
|
||||
if (port->port.console && port->sysrq) {
|
||||
if (port->sysrq) {
|
||||
if (usb_serial_handle_sysrq_char(port, data[i + 1]))
|
||||
continue;
|
||||
}
|
||||
|
@ -461,7 +461,7 @@ static void f81534a_process_read_urb(struct urb *urb)
|
|||
lsr = data[len - 1];
|
||||
tty_flag = f81232_handle_lsr(port, lsr);
|
||||
|
||||
if (port->port.console && port->sysrq) {
|
||||
if (port->sysrq) {
|
||||
for (i = 1; i < len - 1; ++i) {
|
||||
if (!usb_serial_handle_sysrq_char(port, data[i])) {
|
||||
tty_insert_flip_char(&port->port, data[i],
|
||||
|
|
|
@ -1238,7 +1238,7 @@ static void f81534_process_per_serial_block(struct usb_serial_port *port,
|
|||
schedule_work(&port_priv->lsr_work);
|
||||
}
|
||||
|
||||
if (port->port.console && port->sysrq) {
|
||||
if (port->sysrq) {
|
||||
if (usb_serial_handle_sysrq_char(port, data[i]))
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -2480,12 +2480,12 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port,
|
|||
#define FTDI_RS_ERR_MASK (FTDI_RS_BI | FTDI_RS_PE | FTDI_RS_FE | FTDI_RS_OE)
|
||||
|
||||
static int ftdi_process_packet(struct usb_serial_port *port,
|
||||
struct ftdi_private *priv, char *packet, int len)
|
||||
struct ftdi_private *priv, unsigned char *buf, int len)
|
||||
{
|
||||
unsigned char status;
|
||||
bool brkint = false;
|
||||
int i;
|
||||
char status;
|
||||
char flag;
|
||||
char *ch;
|
||||
|
||||
if (len < 2) {
|
||||
dev_dbg(&port->dev, "malformed packet\n");
|
||||
|
@ -2495,7 +2495,7 @@ static int ftdi_process_packet(struct usb_serial_port *port,
|
|||
/* Compare new line status to the old one, signal if different/
|
||||
N.B. packet may be processed more than once, but differences
|
||||
are only processed once. */
|
||||
status = packet[0] & FTDI_STATUS_B0_MASK;
|
||||
status = buf[0] & FTDI_STATUS_B0_MASK;
|
||||
if (status != priv->prev_status) {
|
||||
char diff_status = status ^ priv->prev_status;
|
||||
|
||||
|
@ -2521,13 +2521,12 @@ static int ftdi_process_packet(struct usb_serial_port *port,
|
|||
}
|
||||
|
||||
/* save if the transmitter is empty or not */
|
||||
if (packet[1] & FTDI_RS_TEMT)
|
||||
if (buf[1] & FTDI_RS_TEMT)
|
||||
priv->transmit_empty = 1;
|
||||
else
|
||||
priv->transmit_empty = 0;
|
||||
|
||||
len -= 2;
|
||||
if (!len)
|
||||
if (len == 2)
|
||||
return 0; /* status only */
|
||||
|
||||
/*
|
||||
|
@ -2535,47 +2534,57 @@ static int ftdi_process_packet(struct usb_serial_port *port,
|
|||
* data payload to avoid over-reporting.
|
||||
*/
|
||||
flag = TTY_NORMAL;
|
||||
if (packet[1] & FTDI_RS_ERR_MASK) {
|
||||
/* Break takes precedence over parity, which takes precedence
|
||||
* over framing errors */
|
||||
if (packet[1] & FTDI_RS_BI) {
|
||||
flag = TTY_BREAK;
|
||||
if (buf[1] & FTDI_RS_ERR_MASK) {
|
||||
/*
|
||||
* Break takes precedence over parity, which takes precedence
|
||||
* over framing errors. Note that break is only associated
|
||||
* with the last character in the buffer and only when it's a
|
||||
* NUL.
|
||||
*/
|
||||
if (buf[1] & FTDI_RS_BI && buf[len - 1] == '\0') {
|
||||
port->icount.brk++;
|
||||
usb_serial_handle_break(port);
|
||||
} else if (packet[1] & FTDI_RS_PE) {
|
||||
brkint = true;
|
||||
}
|
||||
if (buf[1] & FTDI_RS_PE) {
|
||||
flag = TTY_PARITY;
|
||||
port->icount.parity++;
|
||||
} else if (packet[1] & FTDI_RS_FE) {
|
||||
} else if (buf[1] & FTDI_RS_FE) {
|
||||
flag = TTY_FRAME;
|
||||
port->icount.frame++;
|
||||
}
|
||||
/* Overrun is special, not associated with a char */
|
||||
if (packet[1] & FTDI_RS_OE) {
|
||||
if (buf[1] & FTDI_RS_OE) {
|
||||
port->icount.overrun++;
|
||||
tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
|
||||
}
|
||||
}
|
||||
|
||||
port->icount.rx += len;
|
||||
ch = packet + 2;
|
||||
port->icount.rx += len - 2;
|
||||
|
||||
if (port->port.console && port->sysrq) {
|
||||
for (i = 0; i < len; i++, ch++) {
|
||||
if (!usb_serial_handle_sysrq_char(port, *ch))
|
||||
tty_insert_flip_char(&port->port, *ch, flag);
|
||||
if (brkint || port->sysrq) {
|
||||
for (i = 2; i < len; i++) {
|
||||
if (brkint && i == len - 1) {
|
||||
if (usb_serial_handle_break(port))
|
||||
return len - 3;
|
||||
flag = TTY_BREAK;
|
||||
}
|
||||
if (usb_serial_handle_sysrq_char(port, buf[i]))
|
||||
continue;
|
||||
tty_insert_flip_char(&port->port, buf[i], flag);
|
||||
}
|
||||
} else {
|
||||
tty_insert_flip_string_fixed_flag(&port->port, ch, flag, len);
|
||||
tty_insert_flip_string_fixed_flag(&port->port, buf + 2, flag,
|
||||
len - 2);
|
||||
}
|
||||
|
||||
return len;
|
||||
return len - 2;
|
||||
}
|
||||
|
||||
static void ftdi_process_read_urb(struct urb *urb)
|
||||
{
|
||||
struct usb_serial_port *port = urb->context;
|
||||
struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||||
char *data = (char *)urb->transfer_buffer;
|
||||
char *data = urb->transfer_buffer;
|
||||
int i;
|
||||
int len;
|
||||
int count = 0;
|
||||
|
|
|
@ -179,19 +179,22 @@ static unsigned char const GARMIN_START_SESSION_REPLY[]
|
|||
= { 0, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0 };
|
||||
static unsigned char const GARMIN_BULK_IN_AVAIL_REPLY[]
|
||||
= { 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 };
|
||||
static unsigned char const GARMIN_STOP_TRANSFER_REQ[]
|
||||
= { 20, 0, 0, 0, 10, 0, 0, 0, 2, 0, 0, 0, 0, 0 };
|
||||
static unsigned char const GARMIN_STOP_TRANSFER_REQ_V2[]
|
||||
= { 20, 0, 0, 0, 10, 0, 0, 0, 1, 0, 0, 0, 0 };
|
||||
|
||||
/* packets currently unused, left as documentation */
|
||||
#if 0
|
||||
static unsigned char const GARMIN_APP_LAYER_REPLY[]
|
||||
= { 0x14, 0, 0, 0 };
|
||||
static unsigned char const GARMIN_START_PVT_REQ[]
|
||||
= { 20, 0, 0, 0, 10, 0, 0, 0, 2, 0, 0, 0, 49, 0 };
|
||||
static unsigned char const GARMIN_STOP_PVT_REQ[]
|
||||
= { 20, 0, 0, 0, 10, 0, 0, 0, 2, 0, 0, 0, 50, 0 };
|
||||
static unsigned char const GARMIN_STOP_TRANSFER_REQ[]
|
||||
= { 20, 0, 0, 0, 10, 0, 0, 0, 2, 0, 0, 0, 0, 0 };
|
||||
static unsigned char const GARMIN_STOP_TRANSFER_REQ_V2[]
|
||||
= { 20, 0, 0, 0, 10, 0, 0, 0, 1, 0, 0, 0, 0 };
|
||||
static unsigned char const PRIVATE_REQ[]
|
||||
= { 0x4B, 0x6E, 0x10, 0x01, 0xFF, 0, 0, 0, 0xFF, 0, 0, 0 };
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static const struct usb_device_id id_table[] = {
|
||||
|
|
|
@ -345,7 +345,7 @@ EXPORT_SYMBOL_GPL(usb_serial_generic_submit_read_urbs);
|
|||
void usb_serial_generic_process_read_urb(struct urb *urb)
|
||||
{
|
||||
struct usb_serial_port *port = urb->context;
|
||||
char *ch = (char *)urb->transfer_buffer;
|
||||
char *ch = urb->transfer_buffer;
|
||||
int i;
|
||||
|
||||
if (!urb->actual_length)
|
||||
|
@ -355,13 +355,13 @@ void usb_serial_generic_process_read_urb(struct urb *urb)
|
|||
* stuff like 3G modems, so shortcircuit it in the 99.9999999% of
|
||||
* cases where the USB serial is not a console anyway.
|
||||
*/
|
||||
if (!port->port.console || !port->sysrq) {
|
||||
tty_insert_flip_string(&port->port, ch, urb->actual_length);
|
||||
} else {
|
||||
if (port->sysrq) {
|
||||
for (i = 0; i < urb->actual_length; i++, ch++) {
|
||||
if (!usb_serial_handle_sysrq_char(port, *ch))
|
||||
tty_insert_flip_char(&port->port, *ch, TTY_NORMAL);
|
||||
}
|
||||
} else {
|
||||
tty_insert_flip_string(&port->port, ch, urb->actual_length);
|
||||
}
|
||||
tty_flip_buffer_push(&port->port);
|
||||
}
|
||||
|
@ -571,10 +571,10 @@ int usb_serial_generic_get_icount(struct tty_struct *tty,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(usb_serial_generic_get_icount);
|
||||
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
#if defined(CONFIG_USB_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
||||
int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
|
||||
{
|
||||
if (port->sysrq && port->port.console) {
|
||||
if (port->sysrq) {
|
||||
if (ch && time_before(jiffies, port->sysrq)) {
|
||||
handle_sysrq(ch);
|
||||
port->sysrq = 0;
|
||||
|
@ -584,16 +584,13 @@ int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
EXPORT_SYMBOL_GPL(usb_serial_handle_sysrq_char);
|
||||
|
||||
int usb_serial_handle_break(struct usb_serial_port *port)
|
||||
{
|
||||
if (!port->port.console)
|
||||
return 0;
|
||||
|
||||
if (!port->sysrq) {
|
||||
port->sysrq = jiffies + HZ*5;
|
||||
return 1;
|
||||
|
@ -602,6 +599,7 @@ int usb_serial_handle_break(struct usb_serial_port *port)
|
|||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_serial_handle_break);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* usb_serial_handle_dcd_change - handle a change of carrier detect state
|
||||
|
|
|
@ -1752,7 +1752,7 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,
|
|||
edge_serial->rxState = EXPECT_HDR2;
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
fallthrough;
|
||||
case EXPECT_HDR2:
|
||||
edge_serial->rxHeader2 = *buffer;
|
||||
++buffer;
|
||||
|
@ -1804,7 +1804,7 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,
|
|||
edge_serial->rxState = EXPECT_DATA;
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
fallthrough;
|
||||
case EXPECT_DATA: /* Expect data */
|
||||
if (bufferLength < edge_serial->rxBytesRemaining) {
|
||||
rxLen = bufferLength;
|
||||
|
|
|
@ -158,7 +158,6 @@ static int iuu_tiocmget(struct tty_struct *tty)
|
|||
static void iuu_rxcmd(struct urb *urb)
|
||||
{
|
||||
struct usb_serial_port *port = urb->context;
|
||||
int result;
|
||||
int status = urb->status;
|
||||
|
||||
if (status) {
|
||||
|
@ -174,7 +173,7 @@ static void iuu_rxcmd(struct urb *urb)
|
|||
port->bulk_out_endpointAddress),
|
||||
port->write_urb->transfer_buffer, 1,
|
||||
read_rxcmd_callback, port);
|
||||
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
|
||||
usb_submit_urb(port->write_urb, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
static int iuu_reset(struct usb_serial_port *port, u8 wt)
|
||||
|
@ -241,7 +240,6 @@ static void iuu_update_status_callback(struct urb *urb)
|
|||
static void iuu_status_callback(struct urb *urb)
|
||||
{
|
||||
struct usb_serial_port *port = urb->context;
|
||||
int result;
|
||||
int status = urb->status;
|
||||
|
||||
dev_dbg(&port->dev, "%s - status = %d\n", __func__, status);
|
||||
|
@ -250,7 +248,7 @@ static void iuu_status_callback(struct urb *urb)
|
|||
port->bulk_in_endpointAddress),
|
||||
port->read_urb->transfer_buffer, 256,
|
||||
iuu_update_status_callback, port);
|
||||
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
|
||||
usb_submit_urb(port->read_urb, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
static int iuu_status(struct usb_serial_port *port)
|
||||
|
@ -351,12 +349,12 @@ static void iuu_rgbf_fill_buffer(u8 *buf, u8 r1, u8 r2, u8 g1, u8 g2, u8 b1,
|
|||
static void iuu_led_activity_on(struct urb *urb)
|
||||
{
|
||||
struct usb_serial_port *port = urb->context;
|
||||
int result;
|
||||
char *buf_ptr = port->write_urb->transfer_buffer;
|
||||
*buf_ptr++ = IUU_SET_LED;
|
||||
|
||||
if (xmas) {
|
||||
get_random_bytes(buf_ptr, 6);
|
||||
*(buf_ptr+7) = 1;
|
||||
buf_ptr[0] = IUU_SET_LED;
|
||||
get_random_bytes(buf_ptr + 1, 6);
|
||||
buf_ptr[7] = 1;
|
||||
} else {
|
||||
iuu_rgbf_fill_buffer(buf_ptr, 255, 255, 0, 0, 0, 0, 255);
|
||||
}
|
||||
|
@ -366,27 +364,27 @@ static void iuu_led_activity_on(struct urb *urb)
|
|||
port->bulk_out_endpointAddress),
|
||||
port->write_urb->transfer_buffer, 8 ,
|
||||
iuu_rxcmd, port);
|
||||
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
|
||||
usb_submit_urb(port->write_urb, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
static void iuu_led_activity_off(struct urb *urb)
|
||||
{
|
||||
struct usb_serial_port *port = urb->context;
|
||||
int result;
|
||||
char *buf_ptr = port->write_urb->transfer_buffer;
|
||||
|
||||
if (xmas) {
|
||||
iuu_rxcmd(urb);
|
||||
return;
|
||||
} else {
|
||||
*buf_ptr++ = IUU_SET_LED;
|
||||
iuu_rgbf_fill_buffer(buf_ptr, 0, 0, 255, 255, 0, 0, 255);
|
||||
}
|
||||
|
||||
iuu_rgbf_fill_buffer(buf_ptr, 0, 0, 255, 255, 0, 0, 255);
|
||||
|
||||
usb_fill_bulk_urb(port->write_urb, port->serial->dev,
|
||||
usb_sndbulkpipe(port->serial->dev,
|
||||
port->bulk_out_endpointAddress),
|
||||
port->write_urb->transfer_buffer, 8 ,
|
||||
iuu_rxcmd, port);
|
||||
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
|
||||
usb_submit_urb(port->write_urb, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -664,11 +664,10 @@ static void keyspan_pda_close(struct usb_serial_port *port)
|
|||
/* download the firmware to a "fake" device (pre-renumeration) */
|
||||
static int keyspan_pda_fake_startup(struct usb_serial *serial)
|
||||
{
|
||||
int response;
|
||||
const char *fw_name;
|
||||
|
||||
/* download the firmware here ... */
|
||||
response = ezusb_fx1_set_reset(serial->dev, 1);
|
||||
ezusb_fx1_set_reset(serial->dev, 1);
|
||||
|
||||
if (0) { ; }
|
||||
#ifdef KEYSPAN
|
||||
|
|
|
@ -499,7 +499,7 @@ static void kobil_set_termios(struct tty_struct *tty,
|
|||
break;
|
||||
default:
|
||||
speed = 9600;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case 9600:
|
||||
urb_val = SUSBCR_SBR_9600;
|
||||
break;
|
||||
|
@ -526,6 +526,10 @@ static void kobil_set_termios(struct tty_struct *tty,
|
|||
0,
|
||||
KOBIL_TIMEOUT
|
||||
);
|
||||
if (result) {
|
||||
dev_err(&port->dev, "failed to update line settings: %d\n",
|
||||
result);
|
||||
}
|
||||
}
|
||||
|
||||
static int kobil_ioctl(struct tty_struct *tty,
|
||||
|
|
|
@ -327,14 +327,14 @@ static void mxuport_process_read_urb_data(struct usb_serial_port *port,
|
|||
{
|
||||
int i;
|
||||
|
||||
if (!port->port.console || !port->sysrq) {
|
||||
tty_insert_flip_string(&port->port, data, size);
|
||||
} else {
|
||||
if (port->sysrq) {
|
||||
for (i = 0; i < size; i++, data++) {
|
||||
if (!usb_serial_handle_sysrq_char(port, *data))
|
||||
tty_insert_flip_char(&port->port, *data,
|
||||
TTY_NORMAL);
|
||||
}
|
||||
} else {
|
||||
tty_insert_flip_string(&port->port, data, size);
|
||||
}
|
||||
tty_flip_buffer_push(&port->port);
|
||||
}
|
||||
|
|
|
@ -2157,8 +2157,7 @@ static void option_instat_callback(struct urb *urb)
|
|||
dev_dbg(dev, "%s: urb %p port %p has data %p\n", __func__, urb, port, portdata);
|
||||
|
||||
if (status == 0) {
|
||||
struct usb_ctrlrequest *req_pkt =
|
||||
(struct usb_ctrlrequest *)urb->transfer_buffer;
|
||||
struct usb_ctrlrequest *req_pkt = urb->transfer_buffer;
|
||||
|
||||
if (!req_pkt) {
|
||||
dev_dbg(dev, "%s: NULL req_pkt\n", __func__);
|
||||
|
|
|
@ -1101,7 +1101,7 @@ static void pl2303_process_read_urb(struct urb *urb)
|
|||
if (line_status & UART_OVERRUN_ERROR)
|
||||
tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
|
||||
|
||||
if (port->port.console && port->sysrq) {
|
||||
if (port->sysrq) {
|
||||
for (i = 0; i < urb->actual_length; ++i)
|
||||
if (!usb_serial_handle_sysrq_char(port, data[i]))
|
||||
tty_insert_flip_char(&port->port, data[i],
|
||||
|
|
|
@ -155,6 +155,7 @@ static const struct usb_device_id id_table[] = {
|
|||
{DEVICE_SWI(0x1199, 0x9056)}, /* Sierra Wireless Modem */
|
||||
{DEVICE_SWI(0x1199, 0x9060)}, /* Sierra Wireless Modem */
|
||||
{DEVICE_SWI(0x1199, 0x9061)}, /* Sierra Wireless Modem */
|
||||
{DEVICE_SWI(0x1199, 0x9062)}, /* Sierra Wireless EM7305 QDL */
|
||||
{DEVICE_SWI(0x1199, 0x9063)}, /* Sierra Wireless EM7305 */
|
||||
{DEVICE_SWI(0x1199, 0x9070)}, /* Sierra Wireless MC74xx */
|
||||
{DEVICE_SWI(0x1199, 0x9071)}, /* Sierra Wireless MC74xx */
|
||||
|
|
|
@ -480,21 +480,6 @@ static void qt2_process_status(struct usb_serial_port *port, unsigned char *ch)
|
|||
}
|
||||
}
|
||||
|
||||
/* not needed, kept to document functionality */
|
||||
static void qt2_process_xmit_empty(struct usb_serial_port *port,
|
||||
unsigned char *ch)
|
||||
{
|
||||
int bytes_written;
|
||||
|
||||
bytes_written = (int)(*ch) + (int)(*(ch + 1) << 4);
|
||||
}
|
||||
|
||||
/* not needed, kept to document functionality */
|
||||
static void qt2_process_flush(struct usb_serial_port *port, unsigned char *ch)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void qt2_process_read_urb(struct urb *urb)
|
||||
{
|
||||
struct usb_serial *serial;
|
||||
|
@ -540,7 +525,7 @@ static void qt2_process_read_urb(struct urb *urb)
|
|||
__func__);
|
||||
break;
|
||||
}
|
||||
qt2_process_xmit_empty(port, ch + 3);
|
||||
/* bytes_written = (ch[1] << 4) + ch[0]; */
|
||||
i += 4;
|
||||
escapeflag = true;
|
||||
break;
|
||||
|
@ -569,7 +554,6 @@ static void qt2_process_read_urb(struct urb *urb)
|
|||
break;
|
||||
case QT2_REC_FLUSH:
|
||||
case QT2_XMIT_FLUSH:
|
||||
qt2_process_flush(port, ch + 2);
|
||||
i += 2;
|
||||
escapeflag = true;
|
||||
break;
|
||||
|
|
|
@ -45,10 +45,9 @@
|
|||
|
||||
static bool nmea;
|
||||
|
||||
/* Used in interface quirks */
|
||||
struct sierra_iface_quirk {
|
||||
const u32 infolen; /* number of interface numbers on the list */
|
||||
const u8 *ifaceinfo; /* pointer to the array holding the numbers */
|
||||
struct sierra_iface_list {
|
||||
const u8 *nums; /* array of interface numbers */
|
||||
size_t count; /* number of elements in array */
|
||||
};
|
||||
|
||||
struct sierra_intf_private {
|
||||
|
@ -101,20 +100,19 @@ static int sierra_calc_num_ports(struct usb_serial *serial,
|
|||
return num_ports;
|
||||
}
|
||||
|
||||
static int is_quirk(const u8 ifnum, const struct sierra_iface_quirk *quirk)
|
||||
static bool is_listed(const u8 ifnum, const struct sierra_iface_list *list)
|
||||
{
|
||||
const u8 *info;
|
||||
int i;
|
||||
|
||||
if (quirk) {
|
||||
info = quirk->ifaceinfo;
|
||||
if (!list)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < quirk->infolen; i++) {
|
||||
if (info[i] == ifnum)
|
||||
return 1;
|
||||
}
|
||||
for (i = 0; i < list->count; i++) {
|
||||
if (list->nums[i] == ifnum)
|
||||
return true;
|
||||
}
|
||||
return 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static u8 sierra_interface_num(struct usb_serial *serial)
|
||||
|
@ -125,6 +123,7 @@ static u8 sierra_interface_num(struct usb_serial *serial)
|
|||
static int sierra_probe(struct usb_serial *serial,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
const struct sierra_iface_list *ignore_list;
|
||||
int result = 0;
|
||||
struct usb_device *udev;
|
||||
u8 ifnum;
|
||||
|
@ -143,9 +142,10 @@ static int sierra_probe(struct usb_serial *serial,
|
|||
usb_set_interface(udev, ifnum, 1);
|
||||
}
|
||||
|
||||
if (is_quirk(ifnum, (struct sierra_iface_quirk *)id->driver_info)) {
|
||||
dev_dbg(&serial->dev->dev,
|
||||
"Ignoring interface #%d\n", ifnum);
|
||||
ignore_list = (const struct sierra_iface_list *)id->driver_info;
|
||||
|
||||
if (is_listed(ifnum, ignore_list)) {
|
||||
dev_dbg(&serial->dev->dev, "Ignoring interface #%d\n", ifnum);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -154,22 +154,22 @@ static int sierra_probe(struct usb_serial *serial,
|
|||
|
||||
/* interfaces with higher memory requirements */
|
||||
static const u8 hi_memory_typeA_ifaces[] = { 0, 2 };
|
||||
static const struct sierra_iface_quirk typeA_interface_list = {
|
||||
.infolen = ARRAY_SIZE(hi_memory_typeA_ifaces),
|
||||
.ifaceinfo = hi_memory_typeA_ifaces,
|
||||
static const struct sierra_iface_list typeA_interface_list = {
|
||||
.nums = hi_memory_typeA_ifaces,
|
||||
.count = ARRAY_SIZE(hi_memory_typeA_ifaces),
|
||||
};
|
||||
|
||||
static const u8 hi_memory_typeB_ifaces[] = { 3, 4, 5, 6 };
|
||||
static const struct sierra_iface_quirk typeB_interface_list = {
|
||||
.infolen = ARRAY_SIZE(hi_memory_typeB_ifaces),
|
||||
.ifaceinfo = hi_memory_typeB_ifaces,
|
||||
static const struct sierra_iface_list typeB_interface_list = {
|
||||
.nums = hi_memory_typeB_ifaces,
|
||||
.count = ARRAY_SIZE(hi_memory_typeB_ifaces),
|
||||
};
|
||||
|
||||
/* 'ignorelist' of interfaces not served by this driver */
|
||||
static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11, 19, 20 };
|
||||
static const struct sierra_iface_quirk direct_ip_interface_ignore = {
|
||||
.infolen = ARRAY_SIZE(direct_ip_non_serial_ifaces),
|
||||
.ifaceinfo = direct_ip_non_serial_ifaces,
|
||||
static const struct sierra_iface_list direct_ip_interface_ignore = {
|
||||
.nums = direct_ip_non_serial_ifaces,
|
||||
.count = ARRAY_SIZE(direct_ip_non_serial_ifaces),
|
||||
};
|
||||
|
||||
static const struct usb_device_id id_table[] = {
|
||||
|
@ -570,8 +570,7 @@ static void sierra_instat_callback(struct urb *urb)
|
|||
urb, port, portdata);
|
||||
|
||||
if (status == 0) {
|
||||
struct usb_ctrlrequest *req_pkt =
|
||||
(struct usb_ctrlrequest *)urb->transfer_buffer;
|
||||
struct usb_ctrlrequest *req_pkt = urb->transfer_buffer;
|
||||
|
||||
if (!req_pkt) {
|
||||
dev_dbg(&port->dev, "%s: NULL req_pkt\n",
|
||||
|
@ -860,7 +859,7 @@ static int sierra_port_probe(struct usb_serial_port *port)
|
|||
{
|
||||
struct usb_serial *serial = port->serial;
|
||||
struct sierra_port_private *portdata;
|
||||
const struct sierra_iface_quirk *himemoryp;
|
||||
const struct sierra_iface_list *himemory_list;
|
||||
u8 ifnum;
|
||||
|
||||
portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
|
||||
|
@ -879,16 +878,16 @@ static int sierra_port_probe(struct usb_serial_port *port)
|
|||
if (serial->num_ports == 1) {
|
||||
/* Get interface number for composite device */
|
||||
ifnum = sierra_interface_num(serial);
|
||||
himemoryp = &typeB_interface_list;
|
||||
himemory_list = &typeB_interface_list;
|
||||
} else {
|
||||
/* This is really the usb-serial port number of the interface
|
||||
* rather than the interface number.
|
||||
*/
|
||||
ifnum = port->port_number;
|
||||
himemoryp = &typeA_interface_list;
|
||||
himemory_list = &typeA_interface_list;
|
||||
}
|
||||
|
||||
if (is_quirk(ifnum, himemoryp)) {
|
||||
if (is_listed(ifnum, himemory_list)) {
|
||||
portdata->num_out_urbs = N_OUT_URB_HM;
|
||||
portdata->num_in_urbs = N_IN_URB_HM;
|
||||
}
|
||||
|
|
|
@ -495,7 +495,7 @@ static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr,
|
|||
static void ssu100_process_read_urb(struct urb *urb)
|
||||
{
|
||||
struct usb_serial_port *port = urb->context;
|
||||
char *packet = (char *)urb->transfer_buffer;
|
||||
char *packet = urb->transfer_buffer;
|
||||
char flag = TTY_NORMAL;
|
||||
u32 len = urb->actual_length;
|
||||
int i;
|
||||
|
@ -517,13 +517,14 @@ static void ssu100_process_read_urb(struct urb *urb)
|
|||
if (!len)
|
||||
return; /* status only */
|
||||
|
||||
if (port->port.console && port->sysrq) {
|
||||
if (port->sysrq) {
|
||||
for (i = 0; i < len; i++, ch++) {
|
||||
if (!usb_serial_handle_sysrq_char(port, *ch))
|
||||
tty_insert_flip_char(&port->port, *ch, flag);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
tty_insert_flip_string_fixed_flag(&port->port, ch, flag, len);
|
||||
}
|
||||
|
||||
tty_flip_buffer_push(&port->port);
|
||||
}
|
||||
|
|
|
@ -332,7 +332,7 @@ static void upd78f0730_set_termios(struct tty_struct *tty,
|
|||
tty->termios.c_cflag &= ~CSIZE;
|
||||
tty->termios.c_cflag |= CS8;
|
||||
dev_warn(dev, "data size is not supported, using 8 bits\n");
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case CS8:
|
||||
request.params |= UPD78F0730_DATA_SIZE_8_BITS;
|
||||
dev_dbg(dev, "%s - 8 data bits\n", __func__);
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include <linux/kref.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/kfifo.h>
|
||||
|
||||
/* The maximum number of ports one device can grab at once */
|
||||
|
@ -316,19 +315,19 @@ struct usb_serial_driver {
|
|||
#define to_usb_serial_driver(d) \
|
||||
container_of(d, struct usb_serial_driver, driver)
|
||||
|
||||
extern int usb_serial_register_drivers(struct usb_serial_driver *const serial_drivers[],
|
||||
int usb_serial_register_drivers(struct usb_serial_driver *const serial_drivers[],
|
||||
const char *name, const struct usb_device_id *id_table);
|
||||
extern void usb_serial_deregister_drivers(struct usb_serial_driver *const serial_drivers[]);
|
||||
extern void usb_serial_port_softint(struct usb_serial_port *port);
|
||||
void usb_serial_deregister_drivers(struct usb_serial_driver *const serial_drivers[]);
|
||||
void usb_serial_port_softint(struct usb_serial_port *port);
|
||||
|
||||
extern int usb_serial_suspend(struct usb_interface *intf, pm_message_t message);
|
||||
extern int usb_serial_resume(struct usb_interface *intf);
|
||||
int usb_serial_suspend(struct usb_interface *intf, pm_message_t message);
|
||||
int usb_serial_resume(struct usb_interface *intf);
|
||||
|
||||
/* USB Serial console functions */
|
||||
#ifdef CONFIG_USB_SERIAL_CONSOLE
|
||||
extern void usb_serial_console_init(int minor);
|
||||
extern void usb_serial_console_exit(void);
|
||||
extern void usb_serial_console_disconnect(struct usb_serial *serial);
|
||||
void usb_serial_console_init(int minor);
|
||||
void usb_serial_console_exit(void);
|
||||
void usb_serial_console_disconnect(struct usb_serial *serial);
|
||||
#else
|
||||
static inline void usb_serial_console_init(int minor) { }
|
||||
static inline void usb_serial_console_exit(void) { }
|
||||
|
@ -336,45 +335,49 @@ static inline void usb_serial_console_disconnect(struct usb_serial *serial) {}
|
|||
#endif
|
||||
|
||||
/* Functions needed by other parts of the usbserial core */
|
||||
extern struct usb_serial_port *usb_serial_port_get_by_minor(unsigned int minor);
|
||||
extern void usb_serial_put(struct usb_serial *serial);
|
||||
extern int usb_serial_generic_open(struct tty_struct *tty,
|
||||
struct usb_serial_port *port);
|
||||
extern int usb_serial_generic_write_start(struct usb_serial_port *port,
|
||||
gfp_t mem_flags);
|
||||
extern int usb_serial_generic_write(struct tty_struct *tty,
|
||||
struct usb_serial_port *port, const unsigned char *buf, int count);
|
||||
extern void usb_serial_generic_close(struct usb_serial_port *port);
|
||||
extern int usb_serial_generic_resume(struct usb_serial *serial);
|
||||
extern int usb_serial_generic_write_room(struct tty_struct *tty);
|
||||
extern int usb_serial_generic_chars_in_buffer(struct tty_struct *tty);
|
||||
extern void usb_serial_generic_wait_until_sent(struct tty_struct *tty,
|
||||
long timeout);
|
||||
extern void usb_serial_generic_read_bulk_callback(struct urb *urb);
|
||||
extern void usb_serial_generic_write_bulk_callback(struct urb *urb);
|
||||
extern void usb_serial_generic_throttle(struct tty_struct *tty);
|
||||
extern void usb_serial_generic_unthrottle(struct tty_struct *tty);
|
||||
extern int usb_serial_generic_tiocmiwait(struct tty_struct *tty,
|
||||
unsigned long arg);
|
||||
extern int usb_serial_generic_get_icount(struct tty_struct *tty,
|
||||
struct serial_icounter_struct *icount);
|
||||
extern int usb_serial_generic_register(void);
|
||||
extern void usb_serial_generic_deregister(void);
|
||||
extern int usb_serial_generic_submit_read_urbs(struct usb_serial_port *port,
|
||||
gfp_t mem_flags);
|
||||
extern void usb_serial_generic_process_read_urb(struct urb *urb);
|
||||
extern int usb_serial_generic_prepare_write_buffer(struct usb_serial_port *port,
|
||||
void *dest, size_t size);
|
||||
extern int usb_serial_handle_sysrq_char(struct usb_serial_port *port,
|
||||
unsigned int ch);
|
||||
extern int usb_serial_handle_break(struct usb_serial_port *port);
|
||||
extern void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port,
|
||||
struct tty_struct *tty,
|
||||
unsigned int status);
|
||||
struct usb_serial_port *usb_serial_port_get_by_minor(unsigned int minor);
|
||||
void usb_serial_put(struct usb_serial *serial);
|
||||
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,
|
||||
const unsigned char *buf, int count);
|
||||
void usb_serial_generic_close(struct usb_serial_port *port);
|
||||
int usb_serial_generic_resume(struct usb_serial *serial);
|
||||
int usb_serial_generic_write_room(struct tty_struct *tty);
|
||||
int usb_serial_generic_chars_in_buffer(struct tty_struct *tty);
|
||||
void usb_serial_generic_wait_until_sent(struct tty_struct *tty, long timeout);
|
||||
void usb_serial_generic_read_bulk_callback(struct urb *urb);
|
||||
void usb_serial_generic_write_bulk_callback(struct urb *urb);
|
||||
void usb_serial_generic_throttle(struct tty_struct *tty);
|
||||
void usb_serial_generic_unthrottle(struct tty_struct *tty);
|
||||
int usb_serial_generic_tiocmiwait(struct tty_struct *tty, unsigned long arg);
|
||||
int usb_serial_generic_get_icount(struct tty_struct *tty, struct serial_icounter_struct *icount);
|
||||
int usb_serial_generic_register(void);
|
||||
void usb_serial_generic_deregister(void);
|
||||
int usb_serial_generic_submit_read_urbs(struct usb_serial_port *port, gfp_t mem_flags);
|
||||
void usb_serial_generic_process_read_urb(struct urb *urb);
|
||||
int usb_serial_generic_prepare_write_buffer(struct usb_serial_port *port, void *dest, size_t size);
|
||||
|
||||
#if defined(CONFIG_USB_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
||||
int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch);
|
||||
int usb_serial_handle_break(struct usb_serial_port *port);
|
||||
#else
|
||||
static inline int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int usb_serial_handle_break(struct usb_serial_port *port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port,
|
||||
struct tty_struct *tty, unsigned int status);
|
||||
|
||||
|
||||
extern int usb_serial_bus_register(struct usb_serial_driver *device);
|
||||
extern void usb_serial_bus_deregister(struct usb_serial_driver *device);
|
||||
int usb_serial_bus_register(struct usb_serial_driver *device);
|
||||
void usb_serial_bus_deregister(struct usb_serial_driver *device);
|
||||
|
||||
extern struct bus_type usb_serial_bus_type;
|
||||
extern struct tty_driver *usb_serial_tty_driver;
|
||||
|
|
Loading…
Reference in New Issue
Block a user