Commit fa56dd91 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'usb-serial-5.9-rc1' of...

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
  ...
parents 25252919 d2a4309c
...@@ -117,7 +117,7 @@ static int aircable_process_packet(struct usb_serial_port *port, ...@@ -117,7 +117,7 @@ static int aircable_process_packet(struct usb_serial_port *port,
static void aircable_process_read_urb(struct urb *urb) static void aircable_process_read_urb(struct urb *urb)
{ {
struct usb_serial_port *port = urb->context; struct usb_serial_port *port = urb->context;
char *data = (char *)urb->transfer_buffer; char *data = urb->transfer_buffer;
int has_headers; int has_headers;
int count; int count;
int len; int len;
......
...@@ -59,7 +59,11 @@ ...@@ -59,7 +59,11 @@
#define CH341_REQ_MODEM_CTRL 0xA4 #define CH341_REQ_MODEM_CTRL 0xA4
#define CH341_REG_BREAK 0x05 #define CH341_REG_BREAK 0x05
#define CH341_REG_PRESCALER 0x12
#define CH341_REG_DIVISOR 0x13
#define CH341_REG_LCR 0x18 #define CH341_REG_LCR 0x18
#define CH341_REG_LCR2 0x25
#define CH341_NBREAK_BITS 0x01 #define CH341_NBREAK_BITS 0x01
#define CH341_LCR_ENABLE_RX 0x80 #define CH341_LCR_ENABLE_RX 0x80
...@@ -74,6 +78,7 @@ ...@@ -74,6 +78,7 @@
#define CH341_LCR_CS5 0x00 #define CH341_LCR_CS5 0x00
#define CH341_QUIRK_LIMITED_PRESCALER BIT(0) #define CH341_QUIRK_LIMITED_PRESCALER BIT(0)
#define CH341_QUIRK_SIMULATE_BREAK BIT(1)
static const struct usb_device_id id_table[] = { static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x4348, 0x5523) }, { USB_DEVICE(0x4348, 0x5523) },
...@@ -91,6 +96,7 @@ struct ch341_private { ...@@ -91,6 +96,7 @@ struct ch341_private {
u8 msr; u8 msr;
u8 lcr; u8 lcr;
unsigned long quirks; unsigned long quirks;
unsigned long break_end;
}; };
static void ch341_set_termios(struct tty_struct *tty, static void ch341_set_termios(struct tty_struct *tty,
...@@ -153,6 +159,10 @@ static const speed_t ch341_min_rates[] = { ...@@ -153,6 +159,10 @@ static const speed_t ch341_min_rates[] = {
CH341_MIN_RATE(3), 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: * The device line speed is given by the following equation:
* *
...@@ -163,10 +173,9 @@ static const speed_t ch341_min_rates[] = { ...@@ -163,10 +173,9 @@ static const speed_t ch341_min_rates[] = {
* 2 <= div <= 256 if fact = 0, or * 2 <= div <= 256 if fact = 0, or
* 9 <= div <= 256 if fact = 1 * 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; unsigned int fact, div, clk_div;
speed_t speed = priv->baud_rate;
bool force_fact0 = false; bool force_fact0 = false;
int ps; int ps;
...@@ -174,7 +183,7 @@ static int ch341_get_divisor(struct ch341_private *priv) ...@@ -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) * Clamp to supported range, this makes the (ps < 0) and (div < 2)
* sanity checks below redundant. * 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 * 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) ...@@ -229,15 +238,16 @@ static int ch341_get_divisor(struct ch341_private *priv)
} }
static int ch341_set_baudrate_lcr(struct usb_device *dev, 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 val;
int r; int r;
if (!priv->baud_rate) if (!baud_rate)
return -EINVAL; return -EINVAL;
val = ch341_get_divisor(priv); val = ch341_get_divisor(priv, baud_rate);
if (val < 0) if (val < 0)
return -EINVAL; return -EINVAL;
...@@ -247,11 +257,20 @@ static int ch341_set_baudrate_lcr(struct usb_device *dev, ...@@ -247,11 +257,20 @@ static int ch341_set_baudrate_lcr(struct usb_device *dev,
*/ */
val |= BIT(7); 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) if (r)
return 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) if (r)
return r; return r;
...@@ -308,7 +327,7 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) ...@@ -308,7 +327,7 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
if (r < 0) if (r < 0)
goto out; 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) if (r < 0)
goto out; goto out;
...@@ -341,8 +360,8 @@ static int ch341_detect_quirks(struct usb_serial_port *port) ...@@ -341,8 +360,8 @@ static int ch341_detect_quirks(struct usb_serial_port *port)
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
CH341_REG_BREAK, 0, buffer, size, DEFAULT_TIMEOUT); CH341_REG_BREAK, 0, buffer, size, DEFAULT_TIMEOUT);
if (r == -EPIPE) { if (r == -EPIPE) {
dev_dbg(&port->dev, "break control not supported\n"); dev_info(&port->dev, "break control not supported, using simulated break\n");
quirks = CH341_QUIRK_LIMITED_PRESCALER; quirks = CH341_QUIRK_LIMITED_PRESCALER | CH341_QUIRK_SIMULATE_BREAK;
r = 0; r = 0;
goto out; goto out;
} }
...@@ -523,7 +542,8 @@ static void ch341_set_termios(struct tty_struct *tty, ...@@ -523,7 +542,8 @@ static void ch341_set_termios(struct tty_struct *tty,
if (baud_rate) { if (baud_rate) {
priv->baud_rate = 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) { if (r < 0 && old_termios) {
priv->baud_rate = tty_termios_baud_rate(old_termios); priv->baud_rate = tty_termios_baud_rate(old_termios);
tty_termios_copy_hw(&tty->termios, old_termios); tty_termios_copy_hw(&tty->termios, old_termios);
...@@ -542,15 +562,98 @@ static void ch341_set_termios(struct tty_struct *tty, ...@@ -542,15 +562,98 @@ static void ch341_set_termios(struct tty_struct *tty,
ch341_set_handshake(port->serial->dev, priv->mcr); 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) static void ch341_break_ctl(struct tty_struct *tty, int break_state)
{ {
const uint16_t ch341_break_reg = const uint16_t ch341_break_reg =
((uint16_t) CH341_REG_LCR << 8) | CH341_REG_BREAK; ((uint16_t) CH341_REG_LCR << 8) | CH341_REG_BREAK;
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
struct ch341_private *priv = usb_get_serial_port_data(port);
int r; int r;
uint16_t reg_contents; uint16_t reg_contents;
uint8_t *break_reg; uint8_t *break_reg;
if (priv->quirks & CH341_QUIRK_SIMULATE_BREAK) {
ch341_simulate_break(tty, break_state);
return;
}
break_reg = kmalloc(2, GFP_KERNEL); break_reg = kmalloc(2, GFP_KERNEL);
if (!break_reg) if (!break_reg)
return; return;
......
...@@ -102,6 +102,9 @@ static int usb_console_setup(struct console *co, char *options) ...@@ -102,6 +102,9 @@ static int usb_console_setup(struct console *co, char *options)
break; break;
} }
if (doflow)
cflag |= CRTSCTS;
/* /*
* no need to check the index here: if the index is wrong, console * no need to check the index here: if the index is wrong, console
* code won't call us * code won't call us
......
...@@ -50,6 +50,9 @@ static void cp210x_release(struct usb_serial *); ...@@ -50,6 +50,9 @@ static void cp210x_release(struct usb_serial *);
static int cp210x_port_probe(struct usb_serial_port *); static int cp210x_port_probe(struct usb_serial_port *);
static int cp210x_port_remove(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_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[] = { static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x045B, 0x0053) }, /* Renesas RX610 RX-Stick */ { USB_DEVICE(0x045B, 0x0053) }, /* Renesas RX610 RX-Stick */
...@@ -253,9 +256,21 @@ struct cp210x_serial_private { ...@@ -253,9 +256,21 @@ struct cp210x_serial_private {
bool use_actual_rate; 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 { struct cp210x_port_private {
__u8 bInterfaceNumber; u8 bInterfaceNumber;
bool has_swapped_line_ctl; bool has_swapped_line_ctl;
bool event_mode;
enum cp210x_event_state event_state;
u8 lsr;
}; };
static struct usb_serial_driver cp210x_device = { static struct usb_serial_driver cp210x_device = {
...@@ -272,14 +287,18 @@ static struct usb_serial_driver cp210x_device = { ...@@ -272,14 +287,18 @@ static struct usb_serial_driver cp210x_device = {
.break_ctl = cp210x_break_ctl, .break_ctl = cp210x_break_ctl,
.set_termios = cp210x_set_termios, .set_termios = cp210x_set_termios,
.tx_empty = cp210x_tx_empty, .tx_empty = cp210x_tx_empty,
.throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle,
.tiocmget = cp210x_tiocmget, .tiocmget = cp210x_tiocmget,
.tiocmset = cp210x_tiocmset, .tiocmset = cp210x_tiocmset,
.get_icount = usb_serial_generic_get_icount,
.attach = cp210x_attach, .attach = cp210x_attach,
.disconnect = cp210x_disconnect, .disconnect = cp210x_disconnect,
.release = cp210x_release, .release = cp210x_release,
.port_probe = cp210x_port_probe, .port_probe = cp210x_port_probe,
.port_remove = cp210x_port_remove, .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[] = { static struct usb_serial_driver * const serial_drivers[] = {
...@@ -401,13 +420,22 @@ struct cp210x_comm_status { ...@@ -401,13 +420,22 @@ struct cp210x_comm_status {
*/ */
#define PURGE_ALL 0x000f #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 */ /* CP210X_GET_FLOW/CP210X_SET_FLOW read/write these 0x10 bytes */
struct cp210x_flow_ctl { struct cp210x_flow_ctl {
__le32 ulControlHandshake; __le32 ulControlHandshake;
__le32 ulFlowReplace; __le32 ulFlowReplace;
__le32 ulXonLimit; __le32 ulXonLimit;
__le32 ulXoffLimit; __le32 ulXoffLimit;
} __packed; };
/* cp210x_flow_ctl::ulControlHandshake */ /* cp210x_flow_ctl::ulControlHandshake */
#define CP210X_SERIAL_DTR_MASK GENMASK(1, 0) #define CP210X_SERIAL_DTR_MASK GENMASK(1, 0)
...@@ -441,7 +469,7 @@ struct cp210x_flow_ctl { ...@@ -441,7 +469,7 @@ struct cp210x_flow_ctl {
struct cp210x_pin_mode { struct cp210x_pin_mode {
u8 eci; u8 eci;
u8 sci; u8 sci;
} __packed; };
#define CP210X_PIN_MODE_MODEM 0 #define CP210X_PIN_MODE_MODEM 0
#define CP210X_PIN_MODE_GPIO BIT(0) #define CP210X_PIN_MODE_GPIO BIT(0)
...@@ -504,7 +532,7 @@ struct cp210x_single_port_config { ...@@ -504,7 +532,7 @@ struct cp210x_single_port_config {
struct cp210x_gpio_write { struct cp210x_gpio_write {
u8 mask; u8 mask;
u8 state; u8 state;
} __packed; };
/* /*
* Helper to get interface number when we only have struct usb_serial. * 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) ...@@ -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) 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; int result;
result = cp210x_write_u16_reg(port, CP210X_IFC_ENABLE, UART_ENABLE); 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) ...@@ -818,21 +847,144 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
/* Configure the termios structure */ /* Configure the termios structure */
cp210x_get_termios(tty, port); cp210x_get_termios(tty, port);
if (tty) {
/* The baud rate must be initialised on cp2104 */ /* The baud rate must be initialised on cp2104 */
if (tty)
cp210x_change_speed(tty, port, NULL); 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) 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); usb_serial_generic_close(port);
/* Clear both queues; cp2108 needs this to avoid an occasional hang */ /* 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_PURGE, PURGE_ALL);
cp210x_write_u16_reg(port, CP210X_IFC_ENABLE, UART_DISABLE); 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, ...@@ -915,6 +1067,7 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
u32 baud; u32 baud;
u16 bits; u16 bits;
u32 ctl_hs; u32 ctl_hs;
u32 flow_repl;
cp210x_read_u32_reg(port, CP210X_GET_BAUDRATE, &baud); cp210x_read_u32_reg(port, CP210X_GET_BAUDRATE, &baud);
...@@ -1015,6 +1168,22 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, ...@@ -1015,6 +1168,22 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
ctl_hs = le32_to_cpu(flow_ctl.ulControlHandshake); ctl_hs = le32_to_cpu(flow_ctl.ulControlHandshake);
if (ctl_hs & CP210X_SERIAL_CTS_HANDSHAKE) { if (ctl_hs & CP210X_SERIAL_CTS_HANDSHAKE) {
dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__); 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; cflag |= CRTSCTS;
} else { } else {
dev_dbg(dev, "%s - flow control = NONE\n", __func__); dev_dbg(dev, "%s - flow control = NONE\n", __func__);
...@@ -1148,6 +1317,41 @@ static void cp210x_change_speed(struct tty_struct *tty, ...@@ -1148,6 +1317,41 @@ static void cp210x_change_speed(struct tty_struct *tty,
tty_encode_baud_rate(tty, baud, baud); 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, static void cp210x_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios) struct usb_serial_port *port, struct ktermios *old_termios)
{ {
...@@ -1270,6 +1474,14 @@ static void cp210x_set_termios(struct tty_struct *tty, ...@@ -1270,6 +1474,14 @@ static void cp210x_set_termios(struct tty_struct *tty,
sizeof(flow_ctl)); 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, static int cp210x_tiocmset(struct tty_struct *tty,
......
...@@ -1048,7 +1048,7 @@ static void cypress_read_int_callback(struct urb *urb) ...@@ -1048,7 +1048,7 @@ static void cypress_read_int_callback(struct urb *urb)
return; return;
case -EPIPE: case -EPIPE:
/* Can't call usb_clear_halt while in_interrupt */ /* Can't call usb_clear_halt while in_interrupt */
/* FALLS THROUGH */ fallthrough;
default: default:
/* something ugly is going on... */ /* something ugly is going on... */
dev_err(dev, "%s - unexpected nonzero read status received: %d\n", dev_err(dev, "%s - unexpected nonzero read status received: %d\n",
...@@ -1197,7 +1197,7 @@ static void cypress_write_int_callback(struct urb *urb) ...@@ -1197,7 +1197,7 @@ static void cypress_write_int_callback(struct urb *urb)
return; return;
case -EPIPE: case -EPIPE:
/* Cannot call usb_clear_halt while in_interrupt */ /* Cannot call usb_clear_halt while in_interrupt */
/* FALLTHROUGH */ fallthrough;
default: default:
dev_err(dev, "%s - unexpected nonzero write status received: %d\n", dev_err(dev, "%s - unexpected nonzero write status received: %d\n",
__func__, status); __func__, status);
......
...@@ -424,7 +424,7 @@ static void f81232_process_read_urb(struct urb *urb) ...@@ -424,7 +424,7 @@ static void f81232_process_read_urb(struct urb *urb)
lsr = data[i]; lsr = data[i];
tty_flag = f81232_handle_lsr(port, lsr); 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])) if (usb_serial_handle_sysrq_char(port, data[i + 1]))
continue; continue;
} }
...@@ -461,7 +461,7 @@ static void f81534a_process_read_urb(struct urb *urb) ...@@ -461,7 +461,7 @@ static void f81534a_process_read_urb(struct urb *urb)
lsr = data[len - 1]; lsr = data[len - 1];
tty_flag = f81232_handle_lsr(port, lsr); tty_flag = f81232_handle_lsr(port, lsr);
if (port->port.console && port->sysrq) { if (port->sysrq) {
for (i = 1; i < len - 1; ++i) { for (i = 1; i < len - 1; ++i) {
if (!usb_serial_handle_sysrq_char(port, data[i])) { if (!usb_serial_handle_sysrq_char(port, data[i])) {
tty_insert_flip_char(&port->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, ...@@ -1238,7 +1238,7 @@ static void f81534_process_per_serial_block(struct usb_serial_port *port,
schedule_work(&port_priv->lsr_work); schedule_work(&port_priv->lsr_work);
} }
if (port->port.console && port->sysrq) { if (port->sysrq) {
if (usb_serial_handle_sysrq_char(port, data[i])) if (usb_serial_handle_sysrq_char(port, data[i]))
continue; continue;
} }
......
...@@ -2480,12 +2480,12 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port, ...@@ -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) #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, 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; int i;
char status;
char flag; char flag;
char *ch;
if (len < 2) { if (len < 2) {
dev_dbg(&port->dev, "malformed packet\n"); dev_dbg(&port->dev, "malformed packet\n");
...@@ -2495,7 +2495,7 @@ static int ftdi_process_packet(struct usb_serial_port *port, ...@@ -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/ /* Compare new line status to the old one, signal if different/
N.B. packet may be processed more than once, but differences N.B. packet may be processed more than once, but differences
are only processed once. */ are only processed once. */
status = packet[0] & FTDI_STATUS_B0_MASK; status = buf[0] & FTDI_STATUS_B0_MASK;
if (status != priv->prev_status) { if (status != priv->prev_status) {
char diff_status = 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, ...@@ -2521,13 +2521,12 @@ static int ftdi_process_packet(struct usb_serial_port *port,
} }
/* save if the transmitter is empty or not */ /* save if the transmitter is empty or not */
if (packet[1] & FTDI_RS_TEMT) if (buf[1] & FTDI_RS_TEMT)
priv->transmit_empty = 1; priv->transmit_empty = 1;
else else
priv->transmit_empty = 0; priv->transmit_empty = 0;
len -= 2; if (len == 2)
if (!len)
return 0; /* status only */ return 0; /* status only */
/* /*
...@@ -2535,47 +2534,57 @@ static int ftdi_process_packet(struct usb_serial_port *port, ...@@ -2535,47 +2534,57 @@ static int ftdi_process_packet(struct usb_serial_port *port,
* data payload to avoid over-reporting. * data payload to avoid over-reporting.
*/ */
flag = TTY_NORMAL; flag = TTY_NORMAL;
if (packet[1] & FTDI_RS_ERR_MASK) { if (buf[1] & FTDI_RS_ERR_MASK) {
/* Break takes precedence over parity, which takes precedence /*
* over framing errors */ * Break takes precedence over parity, which takes precedence
if (packet[1] & FTDI_RS_BI) { * over framing errors. Note that break is only associated
flag = TTY_BREAK; * 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++; port->icount.brk++;
usb_serial_handle_break(port); brkint = true;
} else if (packet[1] & FTDI_RS_PE) { }
if (buf[1] & FTDI_RS_PE) {
flag = TTY_PARITY; flag = TTY_PARITY;
port->icount.parity++; port->icount.parity++;
} else if (packet[1] & FTDI_RS_FE) { } else if (buf[1] & FTDI_RS_FE) {
flag = TTY_FRAME; flag = TTY_FRAME;
port->icount.frame++; port->icount.frame++;
} }
/* Overrun is special, not associated with a char */ /* Overrun is special, not associated with a char */
if (packet[1] & FTDI_RS_OE) { if (buf[1] & FTDI_RS_OE) {
port->icount.overrun++; port->icount.overrun++;
tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
} }
} }
port->icount.rx += len; port->icount.rx += len - 2;
ch = packet + 2;
if (port->port.console && port->sysrq) { if (brkint || port->sysrq) {
for (i = 0; i < len; i++, ch++) { for (i = 2; i < len; i++) {
if (!usb_serial_handle_sysrq_char(port, *ch)) if (brkint && i == len - 1) {
tty_insert_flip_char(&port->port, *ch, flag); 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 { } 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) static void ftdi_process_read_urb(struct urb *urb)
{ {
struct usb_serial_port *port = urb->context; struct usb_serial_port *port = urb->context;
struct ftdi_private *priv = usb_get_serial_port_data(port); struct ftdi_private *priv = usb_get_serial_port_data(port);
char *data = (char *)urb->transfer_buffer; char *data = urb->transfer_buffer;
int i; int i;
int len; int len;
int count = 0; int count = 0;
......
...@@ -179,19 +179,22 @@ static unsigned char const GARMIN_START_SESSION_REPLY[] ...@@ -179,19 +179,22 @@ static unsigned char const GARMIN_START_SESSION_REPLY[]
= { 0, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0 }; = { 0, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0 };
static unsigned char const GARMIN_BULK_IN_AVAIL_REPLY[] static unsigned char const GARMIN_BULK_IN_AVAIL_REPLY[]
= { 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 }; = { 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[] static unsigned char const GARMIN_APP_LAYER_REPLY[]
= { 0x14, 0, 0, 0 }; = { 0x14, 0, 0, 0 };
static unsigned char const GARMIN_START_PVT_REQ[] static unsigned char const GARMIN_START_PVT_REQ[]
= { 20, 0, 0, 0, 10, 0, 0, 0, 2, 0, 0, 0, 49, 0 }; = { 20, 0, 0, 0, 10, 0, 0, 0, 2, 0, 0, 0, 49, 0 };
static unsigned char const GARMIN_STOP_PVT_REQ[] static unsigned char const GARMIN_STOP_PVT_REQ[]
= { 20, 0, 0, 0, 10, 0, 0, 0, 2, 0, 0, 0, 50, 0 }; = { 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[] static unsigned char const PRIVATE_REQ[]
= { 0x4B, 0x6E, 0x10, 0x01, 0xFF, 0, 0, 0, 0xFF, 0, 0, 0 }; = { 0x4B, 0x6E, 0x10, 0x01, 0xFF, 0, 0, 0, 0xFF, 0, 0, 0 };
#endif
static const struct usb_device_id id_table[] = { static const struct usb_device_id id_table[] = {
......
...@@ -345,7 +345,7 @@ EXPORT_SYMBOL_GPL(usb_serial_generic_submit_read_urbs); ...@@ -345,7 +345,7 @@ EXPORT_SYMBOL_GPL(usb_serial_generic_submit_read_urbs);
void usb_serial_generic_process_read_urb(struct urb *urb) void usb_serial_generic_process_read_urb(struct urb *urb)
{ {
struct usb_serial_port *port = urb->context; struct usb_serial_port *port = urb->context;
char *ch = (char *)urb->transfer_buffer; char *ch = urb->transfer_buffer;
int i; int i;
if (!urb->actual_length) if (!urb->actual_length)
...@@ -355,13 +355,13 @@ void usb_serial_generic_process_read_urb(struct urb *urb) ...@@ -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 * stuff like 3G modems, so shortcircuit it in the 99.9999999% of
* cases where the USB serial is not a console anyway. * cases where the USB serial is not a console anyway.
*/ */
if (!port->port.console || !port->sysrq) { if (port->sysrq) {
tty_insert_flip_string(&port->port, ch, urb->actual_length);
} else {
for (i = 0; i < urb->actual_length; i++, ch++) { for (i = 0; i < urb->actual_length; i++, ch++) {
if (!usb_serial_handle_sysrq_char(port, *ch)) if (!usb_serial_handle_sysrq_char(port, *ch))
tty_insert_flip_char(&port->port, *ch, TTY_NORMAL); 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); tty_flip_buffer_push(&port->port);
} }
...@@ -571,10 +571,10 @@ int usb_serial_generic_get_icount(struct tty_struct *tty, ...@@ -571,10 +571,10 @@ int usb_serial_generic_get_icount(struct tty_struct *tty,
} }
EXPORT_SYMBOL_GPL(usb_serial_generic_get_icount); 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) 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)) { if (ch && time_before(jiffies, port->sysrq)) {
handle_sysrq(ch); handle_sysrq(ch);
port->sysrq = 0; port->sysrq = 0;
...@@ -584,16 +584,13 @@ int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch) ...@@ -584,16 +584,13 @@ int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
} }
return 0; 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); EXPORT_SYMBOL_GPL(usb_serial_handle_sysrq_char);
int usb_serial_handle_break(struct usb_serial_port *port) int usb_serial_handle_break(struct usb_serial_port *port)
{ {
if (!port->port.console)
return 0;
if (!port->sysrq) { if (!port->sysrq) {
port->sysrq = jiffies + HZ*5; port->sysrq = jiffies + HZ*5;
return 1; return 1;
...@@ -602,6 +599,7 @@ int usb_serial_handle_break(struct usb_serial_port *port) ...@@ -602,6 +599,7 @@ int usb_serial_handle_break(struct usb_serial_port *port)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(usb_serial_handle_break); EXPORT_SYMBOL_GPL(usb_serial_handle_break);
#endif
/** /**
* usb_serial_handle_dcd_change - handle a change of carrier detect state * 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, ...@@ -1752,7 +1752,7 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,
edge_serial->rxState = EXPECT_HDR2; edge_serial->rxState = EXPECT_HDR2;
break; break;
} }
/* Fall through */ fallthrough;
case EXPECT_HDR2: case EXPECT_HDR2:
edge_serial->rxHeader2 = *buffer; edge_serial->rxHeader2 = *buffer;
++buffer; ++buffer;
...@@ -1804,7 +1804,7 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial, ...@@ -1804,7 +1804,7 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,
edge_serial->rxState = EXPECT_DATA; edge_serial->rxState = EXPECT_DATA;
break; break;
} }
/* Fall through */ fallthrough;
case EXPECT_DATA: /* Expect data */ case EXPECT_DATA: /* Expect data */
if (bufferLength < edge_serial->rxBytesRemaining) { if (bufferLength < edge_serial->rxBytesRemaining) {
rxLen = bufferLength; rxLen = bufferLength;
......
...@@ -158,7 +158,6 @@ static int iuu_tiocmget(struct tty_struct *tty) ...@@ -158,7 +158,6 @@ static int iuu_tiocmget(struct tty_struct *tty)
static void iuu_rxcmd(struct urb *urb) static void iuu_rxcmd(struct urb *urb)
{ {
struct usb_serial_port *port = urb->context; struct usb_serial_port *port = urb->context;
int result;
int status = urb->status; int status = urb->status;
if (status) { if (status) {
...@@ -174,7 +173,7 @@ static void iuu_rxcmd(struct urb *urb) ...@@ -174,7 +173,7 @@ static void iuu_rxcmd(struct urb *urb)
port->bulk_out_endpointAddress), port->bulk_out_endpointAddress),
port->write_urb->transfer_buffer, 1, port->write_urb->transfer_buffer, 1,
read_rxcmd_callback, port); 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) static int iuu_reset(struct usb_serial_port *port, u8 wt)
...@@ -241,7 +240,6 @@ static void iuu_update_status_callback(struct urb *urb) ...@@ -241,7 +240,6 @@ static void iuu_update_status_callback(struct urb *urb)
static void iuu_status_callback(struct urb *urb) static void iuu_status_callback(struct urb *urb)
{ {
struct usb_serial_port *port = urb->context; struct usb_serial_port *port = urb->context;
int result;
int status = urb->status; int status = urb->status;
dev_dbg(&port->dev, "%s - status = %d\n", __func__, status); dev_dbg(&port->dev, "%s - status = %d\n", __func__, status);
...@@ -250,7 +248,7 @@ static void iuu_status_callback(struct urb *urb) ...@@ -250,7 +248,7 @@ static void iuu_status_callback(struct urb *urb)
port->bulk_in_endpointAddress), port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer, 256, port->read_urb->transfer_buffer, 256,
iuu_update_status_callback, port); 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) 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, ...@@ -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) static void iuu_led_activity_on(struct urb *urb)
{ {
struct usb_serial_port *port = urb->context; struct usb_serial_port *port = urb->context;
int result;
char *buf_ptr = port->write_urb->transfer_buffer; char *buf_ptr = port->write_urb->transfer_buffer;
*buf_ptr++ = IUU_SET_LED;
if (xmas) { if (xmas) {
get_random_bytes(buf_ptr, 6); buf_ptr[0] = IUU_SET_LED;
*(buf_ptr+7) = 1; get_random_bytes(buf_ptr + 1, 6);
buf_ptr[7] = 1;
} else { } else {
iuu_rgbf_fill_buffer(buf_ptr, 255, 255, 0, 0, 0, 0, 255); 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) ...@@ -366,27 +364,27 @@ static void iuu_led_activity_on(struct urb *urb)
port->bulk_out_endpointAddress), port->bulk_out_endpointAddress),
port->write_urb->transfer_buffer, 8 , port->write_urb->transfer_buffer, 8 ,
iuu_rxcmd, port); 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) static void iuu_led_activity_off(struct urb *urb)
{ {
struct usb_serial_port *port = urb->context; struct usb_serial_port *port = urb->context;
int result;
char *buf_ptr = port->write_urb->transfer_buffer; char *buf_ptr = port->write_urb->transfer_buffer;
if (xmas) { if (xmas) {
iuu_rxcmd(urb); iuu_rxcmd(urb);
return; 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_fill_bulk_urb(port->write_urb, port->serial->dev,
usb_sndbulkpipe(port->serial->dev, usb_sndbulkpipe(port->serial->dev,
port->bulk_out_endpointAddress), port->bulk_out_endpointAddress),
port->write_urb->transfer_buffer, 8 , port->write_urb->transfer_buffer, 8 ,
iuu_rxcmd, port); 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) ...@@ -664,11 +664,10 @@ static void keyspan_pda_close(struct usb_serial_port *port)
/* download the firmware to a "fake" device (pre-renumeration) */ /* download the firmware to a "fake" device (pre-renumeration) */
static int keyspan_pda_fake_startup(struct usb_serial *serial) static int keyspan_pda_fake_startup(struct usb_serial *serial)
{ {
int response;
const char *fw_name; const char *fw_name;
/* download the firmware here ... */ /* download the firmware here ... */
response = ezusb_fx1_set_reset(serial->dev, 1); ezusb_fx1_set_reset(serial->dev, 1);
if (0) { ; } if (0) { ; }
#ifdef KEYSPAN #ifdef KEYSPAN
......
...@@ -499,7 +499,7 @@ static void kobil_set_termios(struct tty_struct *tty, ...@@ -499,7 +499,7 @@ static void kobil_set_termios(struct tty_struct *tty,
break; break;
default: default:
speed = 9600; speed = 9600;
/* fall through */ fallthrough;
case 9600: case 9600:
urb_val = SUSBCR_SBR_9600; urb_val = SUSBCR_SBR_9600;
break; break;
...@@ -526,6 +526,10 @@ static void kobil_set_termios(struct tty_struct *tty, ...@@ -526,6 +526,10 @@ static void kobil_set_termios(struct tty_struct *tty,
0, 0,
KOBIL_TIMEOUT KOBIL_TIMEOUT
); );
if (result) {
dev_err(&port->dev, "failed to update line settings: %d\n",
result);
}
} }
static int kobil_ioctl(struct tty_struct *tty, static int kobil_ioctl(struct tty_struct *tty,
......
...@@ -327,14 +327,14 @@ static void mxuport_process_read_urb_data(struct usb_serial_port *port, ...@@ -327,14 +327,14 @@ static void mxuport_process_read_urb_data(struct usb_serial_port *port,
{ {
int i; int i;
if (!port->port.console || !port->sysrq) { if (port->sysrq) {
tty_insert_flip_string(&port->port, data, size);
} else {
for (i = 0; i < size; i++, data++) { for (i = 0; i < size; i++, data++) {
if (!usb_serial_handle_sysrq_char(port, *data)) if (!usb_serial_handle_sysrq_char(port, *data))
tty_insert_flip_char(&port->port, *data, tty_insert_flip_char(&port->port, *data,
TTY_NORMAL); TTY_NORMAL);
} }
} else {
tty_insert_flip_string(&port->port, data, size);
} }
tty_flip_buffer_push(&port->port); tty_flip_buffer_push(&port->port);
} }
......
...@@ -2157,8 +2157,7 @@ static void option_instat_callback(struct urb *urb) ...@@ -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); dev_dbg(dev, "%s: urb %p port %p has data %p\n", __func__, urb, port, portdata);
if (status == 0) { if (status == 0) {
struct usb_ctrlrequest *req_pkt = struct usb_ctrlrequest *req_pkt = urb->transfer_buffer;
(struct usb_ctrlrequest *)urb->transfer_buffer;
if (!req_pkt) { if (!req_pkt) {
dev_dbg(dev, "%s: NULL req_pkt\n", __func__); dev_dbg(dev, "%s: NULL req_pkt\n", __func__);
......
...@@ -1101,7 +1101,7 @@ static void pl2303_process_read_urb(struct urb *urb) ...@@ -1101,7 +1101,7 @@ static void pl2303_process_read_urb(struct urb *urb)
if (line_status & UART_OVERRUN_ERROR) if (line_status & UART_OVERRUN_ERROR)
tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); 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) for (i = 0; i < urb->actual_length; ++i)
if (!usb_serial_handle_sysrq_char(port, data[i])) if (!usb_serial_handle_sysrq_char(port, data[i]))
tty_insert_flip_char(&port->port, data[i], tty_insert_flip_char(&port->port, data[i],
......
...@@ -155,6 +155,7 @@ static const struct usb_device_id id_table[] = { ...@@ -155,6 +155,7 @@ static const struct usb_device_id id_table[] = {
{DEVICE_SWI(0x1199, 0x9056)}, /* Sierra Wireless Modem */ {DEVICE_SWI(0x1199, 0x9056)}, /* Sierra Wireless Modem */
{DEVICE_SWI(0x1199, 0x9060)}, /* Sierra Wireless Modem */ {DEVICE_SWI(0x1199, 0x9060)}, /* Sierra Wireless Modem */
{DEVICE_SWI(0x1199, 0x9061)}, /* 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, 0x9063)}, /* Sierra Wireless EM7305 */
{DEVICE_SWI(0x1199, 0x9070)}, /* Sierra Wireless MC74xx */ {DEVICE_SWI(0x1199, 0x9070)}, /* Sierra Wireless MC74xx */
{DEVICE_SWI(0x1199, 0x9071)}, /* 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) ...@@ -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) static void qt2_process_read_urb(struct urb *urb)
{ {
struct usb_serial *serial; struct usb_serial *serial;
...@@ -540,7 +525,7 @@ static void qt2_process_read_urb(struct urb *urb) ...@@ -540,7 +525,7 @@ static void qt2_process_read_urb(struct urb *urb)
__func__); __func__);
break; break;
} }
qt2_process_xmit_empty(port, ch + 3); /* bytes_written = (ch[1] << 4) + ch[0]; */
i += 4; i += 4;
escapeflag = true; escapeflag = true;
break; break;
...@@ -569,7 +554,6 @@ static void qt2_process_read_urb(struct urb *urb) ...@@ -569,7 +554,6 @@ static void qt2_process_read_urb(struct urb *urb)
break; break;
case QT2_REC_FLUSH: case QT2_REC_FLUSH:
case QT2_XMIT_FLUSH: case QT2_XMIT_FLUSH:
qt2_process_flush(port, ch + 2);
i += 2; i += 2;
escapeflag = true; escapeflag = true;
break; break;
......
...@@ -45,10 +45,9 @@ ...@@ -45,10 +45,9 @@
static bool nmea; static bool nmea;
/* Used in interface quirks */ struct sierra_iface_list {
struct sierra_iface_quirk { const u8 *nums; /* array of interface numbers */
const u32 infolen; /* number of interface numbers on the list */ size_t count; /* number of elements in array */
const u8 *ifaceinfo; /* pointer to the array holding the numbers */
}; };
struct sierra_intf_private { struct sierra_intf_private {
...@@ -101,20 +100,19 @@ static int sierra_calc_num_ports(struct usb_serial *serial, ...@@ -101,20 +100,19 @@ static int sierra_calc_num_ports(struct usb_serial *serial,
return num_ports; 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; int i;
if (quirk) { if (!list)
info = quirk->ifaceinfo; return false;
for (i = 0; i < quirk->infolen; i++) { for (i = 0; i < list->count; i++) {
if (info[i] == ifnum) if (list->nums[i] == ifnum)
return 1; return true;
} }
}
return 0; return false;
} }
static u8 sierra_interface_num(struct usb_serial *serial) static u8 sierra_interface_num(struct usb_serial *serial)
...@@ -125,6 +123,7 @@ 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, static int sierra_probe(struct usb_serial *serial,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
const struct sierra_iface_list *ignore_list;
int result = 0; int result = 0;
struct usb_device *udev; struct usb_device *udev;
u8 ifnum; u8 ifnum;
...@@ -143,9 +142,10 @@ static int sierra_probe(struct usb_serial *serial, ...@@ -143,9 +142,10 @@ static int sierra_probe(struct usb_serial *serial,
usb_set_interface(udev, ifnum, 1); usb_set_interface(udev, ifnum, 1);
} }
if (is_quirk(ifnum, (struct sierra_iface_quirk *)id->driver_info)) { ignore_list = (const struct sierra_iface_list *)id->driver_info;
dev_dbg(&serial->dev->dev,
"Ignoring interface #%d\n", ifnum); if (is_listed(ifnum, ignore_list)) {
dev_dbg(&serial->dev->dev, "Ignoring interface #%d\n", ifnum);
return -ENODEV; return -ENODEV;
} }
...@@ -154,22 +154,22 @@ static int sierra_probe(struct usb_serial *serial, ...@@ -154,22 +154,22 @@ static int sierra_probe(struct usb_serial *serial,
/* interfaces with higher memory requirements */ /* interfaces with higher memory requirements */
static const u8 hi_memory_typeA_ifaces[] = { 0, 2 }; static const u8 hi_memory_typeA_ifaces[] = { 0, 2 };
static const struct sierra_iface_quirk typeA_interface_list = { static const struct sierra_iface_list typeA_interface_list = {
.infolen = ARRAY_SIZE(hi_memory_typeA_ifaces), .nums = hi_memory_typeA_ifaces,
.ifaceinfo = hi_memory_typeA_ifaces, .count = ARRAY_SIZE(hi_memory_typeA_ifaces),
}; };
static const u8 hi_memory_typeB_ifaces[] = { 3, 4, 5, 6 }; static const u8 hi_memory_typeB_ifaces[] = { 3, 4, 5, 6 };
static const struct sierra_iface_quirk typeB_interface_list = { static const struct sierra_iface_list typeB_interface_list = {
.infolen = ARRAY_SIZE(hi_memory_typeB_ifaces), .nums = hi_memory_typeB_ifaces,
.ifaceinfo = hi_memory_typeB_ifaces, .count = ARRAY_SIZE(hi_memory_typeB_ifaces),
}; };
/* 'ignorelist' of interfaces not served by this driver */ /* '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 u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11, 19, 20 };
static const struct sierra_iface_quirk direct_ip_interface_ignore = { static const struct sierra_iface_list direct_ip_interface_ignore = {
.infolen = ARRAY_SIZE(direct_ip_non_serial_ifaces), .nums = direct_ip_non_serial_ifaces,
.ifaceinfo = direct_ip_non_serial_ifaces, .count = ARRAY_SIZE(direct_ip_non_serial_ifaces),
}; };
static const struct usb_device_id id_table[] = { static const struct usb_device_id id_table[] = {
...@@ -570,8 +570,7 @@ static void sierra_instat_callback(struct urb *urb) ...@@ -570,8 +570,7 @@ static void sierra_instat_callback(struct urb *urb)
urb, port, portdata); urb, port, portdata);
if (status == 0) { if (status == 0) {
struct usb_ctrlrequest *req_pkt = struct usb_ctrlrequest *req_pkt = urb->transfer_buffer;
(struct usb_ctrlrequest *)urb->transfer_buffer;
if (!req_pkt) { if (!req_pkt) {
dev_dbg(&port->dev, "%s: NULL req_pkt\n", dev_dbg(&port->dev, "%s: NULL req_pkt\n",
...@@ -860,7 +859,7 @@ static int sierra_port_probe(struct usb_serial_port *port) ...@@ -860,7 +859,7 @@ static int sierra_port_probe(struct usb_serial_port *port)
{ {
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
struct sierra_port_private *portdata; struct sierra_port_private *portdata;
const struct sierra_iface_quirk *himemoryp; const struct sierra_iface_list *himemory_list;
u8 ifnum; u8 ifnum;
portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
...@@ -879,16 +878,16 @@ static int sierra_port_probe(struct usb_serial_port *port) ...@@ -879,16 +878,16 @@ static int sierra_port_probe(struct usb_serial_port *port)
if (serial->num_ports == 1) { if (serial->num_ports == 1) {
/* Get interface number for composite device */ /* Get interface number for composite device */
ifnum = sierra_interface_num(serial); ifnum = sierra_interface_num(serial);
himemoryp = &typeB_interface_list; himemory_list = &typeB_interface_list;
} else { } else {
/* This is really the usb-serial port number of the interface /* This is really the usb-serial port number of the interface
* rather than the interface number. * rather than the interface number.
*/ */
ifnum = port->port_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_out_urbs = N_OUT_URB_HM;
portdata->num_in_urbs = N_IN_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, ...@@ -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) static void ssu100_process_read_urb(struct urb *urb)
{ {
struct usb_serial_port *port = urb->context; struct usb_serial_port *port = urb->context;
char *packet = (char *)urb->transfer_buffer; char *packet = urb->transfer_buffer;
char flag = TTY_NORMAL; char flag = TTY_NORMAL;
u32 len = urb->actual_length; u32 len = urb->actual_length;
int i; int i;
...@@ -517,13 +517,14 @@ static void ssu100_process_read_urb(struct urb *urb) ...@@ -517,13 +517,14 @@ static void ssu100_process_read_urb(struct urb *urb)
if (!len) if (!len)
return; /* status only */ return; /* status only */
if (port->port.console && port->sysrq) { if (port->sysrq) {
for (i = 0; i < len; i++, ch++) { for (i = 0; i < len; i++, ch++) {
if (!usb_serial_handle_sysrq_char(port, *ch)) if (!usb_serial_handle_sysrq_char(port, *ch))
tty_insert_flip_char(&port->port, *ch, flag); tty_insert_flip_char(&port->port, *ch, flag);
} }
} else } else {
tty_insert_flip_string_fixed_flag(&port->port, ch, flag, len); tty_insert_flip_string_fixed_flag(&port->port, ch, flag, len);
}
tty_flip_buffer_push(&port->port); tty_flip_buffer_push(&port->port);
} }
......
...@@ -332,7 +332,7 @@ static void upd78f0730_set_termios(struct tty_struct *tty, ...@@ -332,7 +332,7 @@ static void upd78f0730_set_termios(struct tty_struct *tty,
tty->termios.c_cflag &= ~CSIZE; tty->termios.c_cflag &= ~CSIZE;
tty->termios.c_cflag |= CS8; tty->termios.c_cflag |= CS8;
dev_warn(dev, "data size is not supported, using 8 bits\n"); dev_warn(dev, "data size is not supported, using 8 bits\n");
/* fall through */ fallthrough;
case CS8: case CS8:
request.params |= UPD78F0730_DATA_SIZE_8_BITS; request.params |= UPD78F0730_DATA_SIZE_8_BITS;
dev_dbg(dev, "%s - 8 data bits\n", __func__); dev_dbg(dev, "%s - 8 data bits\n", __func__);
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include <linux/kref.h> #include <linux/kref.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/sysrq.h>
#include <linux/kfifo.h> #include <linux/kfifo.h>
/* The maximum number of ports one device can grab at once */ /* The maximum number of ports one device can grab at once */
...@@ -316,19 +315,19 @@ struct usb_serial_driver { ...@@ -316,19 +315,19 @@ struct usb_serial_driver {
#define to_usb_serial_driver(d) \ #define to_usb_serial_driver(d) \
container_of(d, struct usb_serial_driver, driver) 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); const char *name, const struct usb_device_id *id_table);
extern void usb_serial_deregister_drivers(struct usb_serial_driver *const serial_drivers[]); 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_port_softint(struct usb_serial_port *port);
extern int usb_serial_suspend(struct usb_interface *intf, pm_message_t message); int usb_serial_suspend(struct usb_interface *intf, pm_message_t message);
extern int usb_serial_resume(struct usb_interface *intf); int usb_serial_resume(struct usb_interface *intf);
/* USB Serial console functions */ /* USB Serial console functions */
#ifdef CONFIG_USB_SERIAL_CONSOLE #ifdef CONFIG_USB_SERIAL_CONSOLE
extern void usb_serial_console_init(int minor); void usb_serial_console_init(int minor);
extern void usb_serial_console_exit(void); void usb_serial_console_exit(void);
extern void usb_serial_console_disconnect(struct usb_serial *serial); void usb_serial_console_disconnect(struct usb_serial *serial);
#else #else
static inline void usb_serial_console_init(int minor) { } static inline void usb_serial_console_init(int minor) { }
static inline void usb_serial_console_exit(void) { } static inline void usb_serial_console_exit(void) { }
...@@ -336,45 +335,49 @@ static inline void usb_serial_console_disconnect(struct usb_serial *serial) {} ...@@ -336,45 +335,49 @@ static inline void usb_serial_console_disconnect(struct usb_serial *serial) {}
#endif #endif
/* Functions needed by other parts of the usbserial core */ /* Functions needed by other parts of the usbserial core */
extern struct usb_serial_port *usb_serial_port_get_by_minor(unsigned int minor); struct usb_serial_port *usb_serial_port_get_by_minor(unsigned int minor);
extern void usb_serial_put(struct usb_serial *serial); void usb_serial_put(struct usb_serial *serial);
extern int usb_serial_generic_open(struct tty_struct *tty, int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port);
struct usb_serial_port *port); int usb_serial_generic_write_start(struct usb_serial_port *port, gfp_t mem_flags);
extern int usb_serial_generic_write_start(struct usb_serial_port *port, int usb_serial_generic_write(struct tty_struct *tty, struct usb_serial_port *port,
gfp_t mem_flags); const unsigned char *buf, int count);
extern int usb_serial_generic_write(struct tty_struct *tty, void usb_serial_generic_close(struct usb_serial_port *port);
struct usb_serial_port *port, const unsigned char *buf, int count); int usb_serial_generic_resume(struct usb_serial *serial);
extern void usb_serial_generic_close(struct usb_serial_port *port); int usb_serial_generic_write_room(struct tty_struct *tty);
extern int usb_serial_generic_resume(struct usb_serial *serial); int usb_serial_generic_chars_in_buffer(struct tty_struct *tty);
extern int usb_serial_generic_write_room(struct tty_struct *tty); void usb_serial_generic_wait_until_sent(struct tty_struct *tty, long timeout);
extern int usb_serial_generic_chars_in_buffer(struct tty_struct *tty); void usb_serial_generic_read_bulk_callback(struct urb *urb);
extern void usb_serial_generic_wait_until_sent(struct tty_struct *tty, void usb_serial_generic_write_bulk_callback(struct urb *urb);
long timeout); void usb_serial_generic_throttle(struct tty_struct *tty);
extern void usb_serial_generic_read_bulk_callback(struct urb *urb); void usb_serial_generic_unthrottle(struct tty_struct *tty);
extern void usb_serial_generic_write_bulk_callback(struct urb *urb); int usb_serial_generic_tiocmiwait(struct tty_struct *tty, unsigned long arg);
extern void usb_serial_generic_throttle(struct tty_struct *tty); int usb_serial_generic_get_icount(struct tty_struct *tty, struct serial_icounter_struct *icount);
extern void usb_serial_generic_unthrottle(struct tty_struct *tty); int usb_serial_generic_register(void);
extern int usb_serial_generic_tiocmiwait(struct tty_struct *tty, void usb_serial_generic_deregister(void);
unsigned long arg); int usb_serial_generic_submit_read_urbs(struct usb_serial_port *port, gfp_t mem_flags);
extern int usb_serial_generic_get_icount(struct tty_struct *tty, void usb_serial_generic_process_read_urb(struct urb *urb);
struct serial_icounter_struct *icount); int usb_serial_generic_prepare_write_buffer(struct usb_serial_port *port, void *dest, size_t size);
extern int usb_serial_generic_register(void);
extern void usb_serial_generic_deregister(void); #if defined(CONFIG_USB_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
extern int usb_serial_generic_submit_read_urbs(struct usb_serial_port *port, int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch);
gfp_t mem_flags); int usb_serial_handle_break(struct usb_serial_port *port);
extern void usb_serial_generic_process_read_urb(struct urb *urb); #else
extern int usb_serial_generic_prepare_write_buffer(struct usb_serial_port *port, static inline int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
void *dest, size_t size); {
extern int usb_serial_handle_sysrq_char(struct usb_serial_port *port, return 0;
unsigned int ch); }
extern int usb_serial_handle_break(struct usb_serial_port *port); static inline 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, return 0;
unsigned int status); }
#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); int usb_serial_bus_register(struct usb_serial_driver *device);
extern void usb_serial_bus_deregister(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 bus_type usb_serial_bus_type;
extern struct tty_driver *usb_serial_tty_driver; extern struct tty_driver *usb_serial_tty_driver;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment