USB-serial updates for v4.11-rc1
These updates include - a new driver for Renesas uPD78F0730-based devices - several fixes of failures to check for short transfers, some of which could lead to minor information leaks, and in one case a loop-condition underflow - a fix of a long-standing regression in the ftdi_sio driver which resulted in excessive bulk-in interrupts - a fix for ftdi_sio line-status over-reporting which could lead to an endless stream of NULL-characters being forwarded to user space - a fix for a regression in the console driver - a fix for another mos7840 NULL-pointer dereference due to a missing endpoint sanity check Included are also some clean ups and fixes for various minor issues, as well as a couple of new device IDs that came in late. All but the final patch have been in linux-next with no reported issues. Signed-off-by: Johan Hovold <johan@kernel.org> -----BEGIN PGP SIGNATURE----- iQIuBAABCAAYBQJYnGAqERxqb2hhbkBrZXJuZWwub3JnAAoJEEEN5E/e4bSVONQP /ixZnWgUgAkDk0lHuXwZvYrmXssM2cEAuN1CZkddKyp8h0LhNSVy8Nat4zGJh4kc Nvdln6qPunaKrCL0nV7uaBLRKlCYFmmMLwGRSXOXe3CkQ05oM+o5SOvI+f8qqHWZ efEUtfBc24FAp7gM521sQkPVK6bwj2OzaLXw2DVYhuPip5ZvjNHiqjvpjMddV8mz mF+tE/qpbIWWP+QXuMPUZ4+gDPA7rq+AIeWAH3JDtZIXCivJBlDYWbX8GGEy7kFU p50xSZfcLjcfpz0UGhFPfRXGbABjWegVzwWrRBngeXoY1kyRuz4BtUKM22NcAOff IHCo+/9mu3lFa3Il9c7i23EbhTeY5Vrl4xiwuF9FWYiwNj0N8GZkFaoVuH3tofn2 4S3oJhHvwe8IgKWAo9mnuk5Et9dGCh4WblTueucHwExfLwddaiM1Xv/y7SKGEeTd IZKxInXHn9niDcjMBeod91BMZBvrlt1Wri147LvF5kUk7eeB/i0M2IiflYXTfVAl Qq/5FAfDLvmjUWsZFRYQCTGd4ykuGeU2vAKeL8kaG6cadvJhBZfnz2J9UYYoVgLi zUKdCXcppumainjP4AxiR0hOk9wCEMjWtAuSWUNh5gfxTDMB1ObadIOBaWFuZSSI goj5jqNCc1xlzLsPmtUQmCBS8/Bv3ux67fxk2ys3tgKR =Ma49 -----END PGP SIGNATURE----- Merge tag 'usb-serial-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-next Johan writes: USB-serial updates for v4.11-rc1 These updates include - a new driver for Renesas uPD78F0730-based devices - several fixes of failures to check for short transfers, some of which could lead to minor information leaks, and in one case a loop-condition underflow - a fix of a long-standing regression in the ftdi_sio driver which resulted in excessive bulk-in interrupts - a fix for ftdi_sio line-status over-reporting which could lead to an endless stream of NULL-characters being forwarded to user space - a fix for a regression in the console driver - a fix for another mos7840 NULL-pointer dereference due to a missing endpoint sanity check Included are also some clean ups and fixes for various minor issues, as well as a couple of new device IDs that came in late. All but the final patch have been in linux-next with no reported issues. Signed-off-by: Johan Hovold <johan@kernel.org>
This commit is contained in:
Коммит
54a21903df
|
@ -713,6 +713,15 @@ config USB_SERIAL_QT2
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called quatech-serial.
|
||||
|
||||
config USB_SERIAL_UPD78F0730
|
||||
tristate "USB Renesas uPD78F0730 Single Port Serial Driver"
|
||||
help
|
||||
Say Y here if you want to use the Renesas uPD78F0730
|
||||
serial driver.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called upd78f0730.
|
||||
|
||||
config USB_SERIAL_DEBUG
|
||||
tristate "USB Debugging Device"
|
||||
help
|
||||
|
|
|
@ -56,6 +56,7 @@ obj-$(CONFIG_USB_SERIAL_SSU100) += ssu100.o
|
|||
obj-$(CONFIG_USB_SERIAL_SYMBOL) += symbolserial.o
|
||||
obj-$(CONFIG_USB_SERIAL_WWAN) += usb_wwan.o
|
||||
obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o
|
||||
obj-$(CONFIG_USB_SERIAL_UPD78F0730) += upd78f0730.o
|
||||
obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o
|
||||
obj-$(CONFIG_USB_SERIAL_WISHBONE) += wishbone-serial.o
|
||||
obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o
|
||||
|
|
|
@ -99,10 +99,17 @@ static int ark3116_read_reg(struct usb_serial *serial,
|
|||
usb_rcvctrlpipe(serial->dev, 0),
|
||||
0xfe, 0xc0, 0, reg,
|
||||
buf, 1, ARK_TIMEOUT);
|
||||
if (result < 0)
|
||||
if (result < 1) {
|
||||
dev_err(&serial->interface->dev,
|
||||
"failed to read register %u: %d\n",
|
||||
reg, result);
|
||||
if (result >= 0)
|
||||
result = -EIO;
|
||||
|
||||
return result;
|
||||
else
|
||||
return buf[0];
|
||||
}
|
||||
|
||||
return buf[0];
|
||||
}
|
||||
|
||||
static inline int calc_divisor(int bps)
|
||||
|
@ -118,17 +125,11 @@ static inline int calc_divisor(int bps)
|
|||
static int ark3116_attach(struct usb_serial *serial)
|
||||
{
|
||||
/* make sure we have our end-points */
|
||||
if ((serial->num_bulk_in == 0) ||
|
||||
(serial->num_bulk_out == 0) ||
|
||||
(serial->num_interrupt_in == 0)) {
|
||||
dev_err(&serial->dev->dev,
|
||||
"%s - missing endpoint - "
|
||||
"bulk in: %d, bulk out: %d, int in %d\n",
|
||||
KBUILD_MODNAME,
|
||||
serial->num_bulk_in,
|
||||
serial->num_bulk_out,
|
||||
serial->num_interrupt_in);
|
||||
return -EINVAL;
|
||||
if (serial->num_bulk_in == 0 ||
|
||||
serial->num_bulk_out == 0 ||
|
||||
serial->num_interrupt_in == 0) {
|
||||
dev_err(&serial->interface->dev, "missing endpoint\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -186,10 +187,8 @@ static int ark3116_port_probe(struct usb_serial_port *port)
|
|||
if (priv->irda)
|
||||
ark3116_write_reg(serial, 0x9, 0);
|
||||
|
||||
dev_info(&serial->dev->dev,
|
||||
"%s using %s mode\n",
|
||||
KBUILD_MODNAME,
|
||||
priv->irda ? "IrDA" : "RS232");
|
||||
dev_info(&port->dev, "using %s mode\n", priv->irda ? "IrDA" : "RS232");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -325,9 +324,8 @@ static void ark3116_set_termios(struct tty_struct *tty,
|
|||
|
||||
/* check for software flow control */
|
||||
if (I_IXOFF(tty) || I_IXON(tty)) {
|
||||
dev_warn(&serial->dev->dev,
|
||||
"%s: don't know how to do software flow control\n",
|
||||
KBUILD_MODNAME);
|
||||
dev_warn(&port->dev,
|
||||
"software flow control not implemented\n");
|
||||
}
|
||||
|
||||
/* Don't rewrite B0 */
|
||||
|
@ -346,8 +344,8 @@ static void ark3116_close(struct usb_serial_port *port)
|
|||
ark3116_write_reg(serial, UART_IER, 0);
|
||||
|
||||
usb_serial_generic_close(port);
|
||||
if (serial->num_interrupt_in)
|
||||
usb_kill_urb(port->interrupt_in_urb);
|
||||
|
||||
usb_kill_urb(port->interrupt_in_urb);
|
||||
}
|
||||
|
||||
static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)
|
||||
|
@ -366,23 +364,29 @@ static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
dev_dbg(&port->dev,
|
||||
"%s - usb_serial_generic_open failed: %d\n",
|
||||
__func__, result);
|
||||
goto err_out;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
/* remove any data still left: also clears error state */
|
||||
ark3116_read_reg(serial, UART_RX, buf);
|
||||
|
||||
/* read modem status */
|
||||
priv->msr = ark3116_read_reg(serial, UART_MSR, buf);
|
||||
result = ark3116_read_reg(serial, UART_MSR, buf);
|
||||
if (result < 0)
|
||||
goto err_close;
|
||||
priv->msr = *buf;
|
||||
|
||||
/* read line status */
|
||||
priv->lsr = ark3116_read_reg(serial, UART_LSR, buf);
|
||||
result = ark3116_read_reg(serial, UART_LSR, buf);
|
||||
if (result < 0)
|
||||
goto err_close;
|
||||
priv->lsr = *buf;
|
||||
|
||||
result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
|
||||
if (result) {
|
||||
dev_err(&port->dev, "submit irq_in urb failed %d\n",
|
||||
result);
|
||||
ark3116_close(port);
|
||||
goto err_out;
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
/* activate interrupts */
|
||||
|
@ -395,8 +399,15 @@ static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
if (tty)
|
||||
ark3116_set_termios(tty, port, NULL);
|
||||
|
||||
err_out:
|
||||
kfree(buf);
|
||||
|
||||
return 0;
|
||||
|
||||
err_close:
|
||||
usb_serial_generic_close(port);
|
||||
err_free:
|
||||
kfree(buf);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -602,9 +613,8 @@ static void ark3116_read_int_callback(struct urb *urb)
|
|||
|
||||
result = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (result)
|
||||
dev_err(&urb->dev->dev,
|
||||
"%s - Error %d submitting interrupt urb\n",
|
||||
__func__, result);
|
||||
dev_err(&port->dev, "failed to resubmit interrupt urb: %d\n",
|
||||
result);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -93,8 +93,8 @@ MODULE_DEVICE_TABLE(usb, id_table);
|
|||
struct ch341_private {
|
||||
spinlock_t lock; /* access lock */
|
||||
unsigned baud_rate; /* set baud rate */
|
||||
u8 line_control; /* set line control value RTS/DTR */
|
||||
u8 line_status; /* active status of modem control inputs */
|
||||
u8 mcr;
|
||||
u8 msr;
|
||||
u8 lcr;
|
||||
};
|
||||
|
||||
|
@ -107,8 +107,8 @@ static int ch341_control_out(struct usb_device *dev, u8 request,
|
|||
{
|
||||
int r;
|
||||
|
||||
dev_dbg(&dev->dev, "ch341_control_out(%02x,%02x,%04x,%04x)\n",
|
||||
USB_DIR_OUT|0x40, (int)request, (int)value, (int)index);
|
||||
dev_dbg(&dev->dev, "%s - (%02x,%04x,%04x)\n", __func__,
|
||||
request, value, index);
|
||||
|
||||
r = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
|
||||
|
@ -125,9 +125,8 @@ static int ch341_control_in(struct usb_device *dev,
|
|||
{
|
||||
int r;
|
||||
|
||||
dev_dbg(&dev->dev, "ch341_control_in(%02x,%02x,%04x,%04x,%p,%u)\n",
|
||||
USB_DIR_IN|0x40, (int)request, (int)value, (int)index, buf,
|
||||
(int)bufsize);
|
||||
dev_dbg(&dev->dev, "%s - (%02x,%04x,%04x,%u)\n", __func__,
|
||||
request, value, index, bufsize);
|
||||
|
||||
r = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
|
||||
|
@ -210,7 +209,7 @@ static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv)
|
|||
goto out;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->line_status = (~(*buffer)) & CH341_BITS_MODEM_STAT;
|
||||
priv->msr = (~(*buffer)) & CH341_BITS_MODEM_STAT;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
out: kfree(buffer);
|
||||
|
@ -239,30 +238,11 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
|
|||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
/* expect two bytes 0x56 0x00 */
|
||||
r = ch341_control_in(dev, CH341_REQ_READ_REG, 0x2518, 0, buffer, size);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x2518, 0x0050);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
/* expect 0xff 0xee */
|
||||
r = ch341_get_status(dev, priv);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
r = ch341_set_baudrate_lcr(dev, priv, priv->lcr);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
r = ch341_set_handshake(dev, priv->line_control);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
/* expect 0x9f 0xee */
|
||||
r = ch341_get_status(dev, priv);
|
||||
r = ch341_set_handshake(dev, priv->mcr);
|
||||
|
||||
out: kfree(buffer);
|
||||
return r;
|
||||
|
@ -279,6 +259,11 @@ static int ch341_port_probe(struct usb_serial_port *port)
|
|||
|
||||
spin_lock_init(&priv->lock);
|
||||
priv->baud_rate = DEFAULT_BAUD_RATE;
|
||||
/*
|
||||
* Some CH340 devices appear unable to change the initial LCR
|
||||
* settings, so set a sane 8N1 default.
|
||||
*/
|
||||
priv->lcr = CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX | CH341_LCR_CS8;
|
||||
|
||||
r = ch341_configure(port->serial->dev, priv);
|
||||
if (r < 0)
|
||||
|
@ -304,7 +289,7 @@ static int ch341_port_remove(struct usb_serial_port *port)
|
|||
static int ch341_carrier_raised(struct usb_serial_port *port)
|
||||
{
|
||||
struct ch341_private *priv = usb_get_serial_port_data(port);
|
||||
if (priv->line_status & CH341_BIT_DCD)
|
||||
if (priv->msr & CH341_BIT_DCD)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -317,11 +302,11 @@ static void ch341_dtr_rts(struct usb_serial_port *port, int on)
|
|||
/* drop DTR and RTS */
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
if (on)
|
||||
priv->line_control |= CH341_BIT_RTS | CH341_BIT_DTR;
|
||||
priv->mcr |= CH341_BIT_RTS | CH341_BIT_DTR;
|
||||
else
|
||||
priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR);
|
||||
priv->mcr &= ~(CH341_BIT_RTS | CH341_BIT_DTR);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
ch341_set_handshake(port->serial->dev, priv->line_control);
|
||||
ch341_set_handshake(port->serial->dev, priv->mcr);
|
||||
}
|
||||
|
||||
static void ch341_close(struct usb_serial_port *port)
|
||||
|
@ -334,14 +319,9 @@ static void ch341_close(struct usb_serial_port *port)
|
|||
/* open this device, set default parameters */
|
||||
static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
|
||||
{
|
||||
struct usb_serial *serial = port->serial;
|
||||
struct ch341_private *priv = usb_get_serial_port_data(port);
|
||||
int r;
|
||||
|
||||
r = ch341_configure(serial->dev, priv);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (tty)
|
||||
ch341_set_termios(tty, port, NULL);
|
||||
|
||||
|
@ -353,6 +333,12 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
return r;
|
||||
}
|
||||
|
||||
r = ch341_get_status(port->serial->dev, priv);
|
||||
if (r < 0) {
|
||||
dev_err(&port->dev, "failed to read modem status: %d\n", r);
|
||||
goto err_kill_interrupt_urb;
|
||||
}
|
||||
|
||||
r = usb_serial_generic_open(tty, port);
|
||||
if (r)
|
||||
goto err_kill_interrupt_urb;
|
||||
|
@ -374,7 +360,7 @@ static void ch341_set_termios(struct tty_struct *tty,
|
|||
struct ch341_private *priv = usb_get_serial_port_data(port);
|
||||
unsigned baud_rate;
|
||||
unsigned long flags;
|
||||
unsigned char ctrl;
|
||||
u8 lcr;
|
||||
int r;
|
||||
|
||||
/* redundant changes may cause the chip to lose bytes */
|
||||
|
@ -383,54 +369,54 @@ static void ch341_set_termios(struct tty_struct *tty,
|
|||
|
||||
baud_rate = tty_get_baud_rate(tty);
|
||||
|
||||
ctrl = CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX;
|
||||
lcr = CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX;
|
||||
|
||||
switch (C_CSIZE(tty)) {
|
||||
case CS5:
|
||||
ctrl |= CH341_LCR_CS5;
|
||||
lcr |= CH341_LCR_CS5;
|
||||
break;
|
||||
case CS6:
|
||||
ctrl |= CH341_LCR_CS6;
|
||||
lcr |= CH341_LCR_CS6;
|
||||
break;
|
||||
case CS7:
|
||||
ctrl |= CH341_LCR_CS7;
|
||||
lcr |= CH341_LCR_CS7;
|
||||
break;
|
||||
case CS8:
|
||||
ctrl |= CH341_LCR_CS8;
|
||||
lcr |= CH341_LCR_CS8;
|
||||
break;
|
||||
}
|
||||
|
||||
if (C_PARENB(tty)) {
|
||||
ctrl |= CH341_LCR_ENABLE_PAR;
|
||||
lcr |= CH341_LCR_ENABLE_PAR;
|
||||
if (C_PARODD(tty) == 0)
|
||||
ctrl |= CH341_LCR_PAR_EVEN;
|
||||
lcr |= CH341_LCR_PAR_EVEN;
|
||||
if (C_CMSPAR(tty))
|
||||
ctrl |= CH341_LCR_MARK_SPACE;
|
||||
lcr |= CH341_LCR_MARK_SPACE;
|
||||
}
|
||||
|
||||
if (C_CSTOPB(tty))
|
||||
ctrl |= CH341_LCR_STOP_BITS_2;
|
||||
lcr |= CH341_LCR_STOP_BITS_2;
|
||||
|
||||
if (baud_rate) {
|
||||
priv->baud_rate = baud_rate;
|
||||
|
||||
r = ch341_set_baudrate_lcr(port->serial->dev, priv, ctrl);
|
||||
r = ch341_set_baudrate_lcr(port->serial->dev, priv, lcr);
|
||||
if (r < 0 && old_termios) {
|
||||
priv->baud_rate = tty_termios_baud_rate(old_termios);
|
||||
tty_termios_copy_hw(&tty->termios, old_termios);
|
||||
} else if (r == 0) {
|
||||
priv->lcr = ctrl;
|
||||
priv->lcr = lcr;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
if (C_BAUD(tty) == B0)
|
||||
priv->line_control &= ~(CH341_BIT_DTR | CH341_BIT_RTS);
|
||||
priv->mcr &= ~(CH341_BIT_DTR | CH341_BIT_RTS);
|
||||
else if (old_termios && (old_termios->c_cflag & CBAUD) == B0)
|
||||
priv->line_control |= (CH341_BIT_DTR | CH341_BIT_RTS);
|
||||
priv->mcr |= (CH341_BIT_DTR | CH341_BIT_RTS);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
ch341_set_handshake(port->serial->dev, priv->line_control);
|
||||
ch341_set_handshake(port->serial->dev, priv->mcr);
|
||||
}
|
||||
|
||||
static void ch341_break_ctl(struct tty_struct *tty, int break_state)
|
||||
|
@ -486,20 +472,20 @@ static int ch341_tiocmset(struct tty_struct *tty,
|
|||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
if (set & TIOCM_RTS)
|
||||
priv->line_control |= CH341_BIT_RTS;
|
||||
priv->mcr |= CH341_BIT_RTS;
|
||||
if (set & TIOCM_DTR)
|
||||
priv->line_control |= CH341_BIT_DTR;
|
||||
priv->mcr |= CH341_BIT_DTR;
|
||||
if (clear & TIOCM_RTS)
|
||||
priv->line_control &= ~CH341_BIT_RTS;
|
||||
priv->mcr &= ~CH341_BIT_RTS;
|
||||
if (clear & TIOCM_DTR)
|
||||
priv->line_control &= ~CH341_BIT_DTR;
|
||||
control = priv->line_control;
|
||||
priv->mcr &= ~CH341_BIT_DTR;
|
||||
control = priv->mcr;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
return ch341_set_handshake(port->serial->dev, control);
|
||||
}
|
||||
|
||||
static void ch341_update_line_status(struct usb_serial_port *port,
|
||||
static void ch341_update_status(struct usb_serial_port *port,
|
||||
unsigned char *data, size_t len)
|
||||
{
|
||||
struct ch341_private *priv = usb_get_serial_port_data(port);
|
||||
|
@ -514,8 +500,8 @@ static void ch341_update_line_status(struct usb_serial_port *port,
|
|||
status = ~data[2] & CH341_BITS_MODEM_STAT;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
delta = status ^ priv->line_status;
|
||||
priv->line_status = status;
|
||||
delta = status ^ priv->msr;
|
||||
priv->msr = status;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
if (data[1] & CH341_MULT_STAT)
|
||||
|
@ -568,7 +554,7 @@ static void ch341_read_int_callback(struct urb *urb)
|
|||
}
|
||||
|
||||
usb_serial_debug_data(&port->dev, __func__, len, data);
|
||||
ch341_update_line_status(port, data, len);
|
||||
ch341_update_status(port, data, len);
|
||||
exit:
|
||||
status = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (status) {
|
||||
|
@ -587,8 +573,8 @@ static int ch341_tiocmget(struct tty_struct *tty)
|
|||
unsigned int result;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
mcr = priv->line_control;
|
||||
status = priv->line_status;
|
||||
mcr = priv->mcr;
|
||||
status = priv->msr;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
result = ((mcr & CH341_BIT_DTR) ? TIOCM_DTR : 0)
|
||||
|
@ -619,6 +605,12 @@ static int ch341_reset_resume(struct usb_serial *serial)
|
|||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ch341_get_status(port->serial->dev, priv);
|
||||
if (ret < 0) {
|
||||
dev_err(&port->dev, "failed to read modem status: %d\n",
|
||||
ret);
|
||||
}
|
||||
}
|
||||
|
||||
return usb_serial_generic_resume(serial);
|
||||
|
|
|
@ -143,6 +143,7 @@ static int usb_console_setup(struct console *co, char *options)
|
|||
tty->driver = usb_serial_tty_driver;
|
||||
tty->index = co->index;
|
||||
init_ldsem(&tty->ldisc_sem);
|
||||
spin_lock_init(&tty->files_lock);
|
||||
INIT_LIST_HEAD(&tty->tty_files);
|
||||
kref_get(&tty->driver->kref);
|
||||
__module_get(tty->driver->owner);
|
||||
|
@ -264,8 +265,7 @@ static struct console usbcons = {
|
|||
|
||||
void usb_serial_console_disconnect(struct usb_serial *serial)
|
||||
{
|
||||
if (serial && serial->port && serial->port[0]
|
||||
&& serial->port[0] == usbcons_info.port) {
|
||||
if (serial->port[0] == usbcons_info.port) {
|
||||
usb_serial_console_exit();
|
||||
usb_serial_put(serial);
|
||||
}
|
||||
|
|
|
@ -178,6 +178,8 @@ static const struct usb_device_id id_table[] = {
|
|||
{ USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */
|
||||
{ USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */
|
||||
{ USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */
|
||||
{ USB_DEVICE(0x1901, 0x0195) }, /* GE B850/B650/B450 CP2104 DP UART interface */
|
||||
{ USB_DEVICE(0x1901, 0x0196) }, /* GE B850 CP2105 DP UART interface */
|
||||
{ USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */
|
||||
{ USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
|
||||
{ USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */
|
||||
|
|
|
@ -1069,7 +1069,6 @@ static void cypress_read_int_callback(struct urb *urb)
|
|||
unsigned char *data = urb->transfer_buffer;
|
||||
unsigned long flags;
|
||||
char tty_flag = TTY_NORMAL;
|
||||
int havedata = 0;
|
||||
int bytes = 0;
|
||||
int result;
|
||||
int i = 0;
|
||||
|
@ -1118,16 +1117,12 @@ static void cypress_read_int_callback(struct urb *urb)
|
|||
priv->current_status = data[0] & 0xF8;
|
||||
bytes = data[1] + 2;
|
||||
i = 2;
|
||||
if (bytes > 2)
|
||||
havedata = 1;
|
||||
break;
|
||||
case packet_format_2:
|
||||
/* This is for the CY7C63743... */
|
||||
priv->current_status = data[0] & 0xF8;
|
||||
bytes = (data[0] & 0x07) + 1;
|
||||
i = 1;
|
||||
if (bytes > 1)
|
||||
havedata = 1;
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
|
|
@ -1398,25 +1398,30 @@ static int digi_read_inb_callback(struct urb *urb)
|
|||
{
|
||||
struct usb_serial_port *port = urb->context;
|
||||
struct digi_port *priv = usb_get_serial_port_data(port);
|
||||
int opcode = ((unsigned char *)urb->transfer_buffer)[0];
|
||||
int len = ((unsigned char *)urb->transfer_buffer)[1];
|
||||
int port_status = ((unsigned char *)urb->transfer_buffer)[2];
|
||||
unsigned char *data = ((unsigned char *)urb->transfer_buffer) + 3;
|
||||
unsigned char *buf = urb->transfer_buffer;
|
||||
int opcode;
|
||||
int len;
|
||||
int port_status;
|
||||
unsigned char *data;
|
||||
int flag, throttled;
|
||||
int status = urb->status;
|
||||
|
||||
/* do not process callbacks on closed ports */
|
||||
/* but do continue the read chain */
|
||||
if (urb->status == -ENOENT)
|
||||
return 0;
|
||||
|
||||
/* short/multiple packet check */
|
||||
if (urb->actual_length < 2) {
|
||||
dev_warn(&port->dev, "short packet received\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
opcode = buf[0];
|
||||
len = buf[1];
|
||||
|
||||
if (urb->actual_length != len + 2) {
|
||||
dev_err(&port->dev, "%s: INCOMPLETE OR MULTIPLE PACKET, "
|
||||
"status=%d, port=%d, opcode=%d, len=%d, "
|
||||
"actual_length=%d, status=%d\n", __func__, status,
|
||||
priv->dp_port_num, opcode, len, urb->actual_length,
|
||||
port_status);
|
||||
dev_err(&port->dev, "malformed packet received: port=%d, opcode=%d, len=%d, actual_length=%u\n",
|
||||
priv->dp_port_num, opcode, len, urb->actual_length);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (opcode == DIGI_CMD_RECEIVE_DATA && len < 1) {
|
||||
dev_err(&port->dev, "malformed data packet received\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1430,6 +1435,9 @@ static int digi_read_inb_callback(struct urb *urb)
|
|||
|
||||
/* receive data */
|
||||
if (opcode == DIGI_CMD_RECEIVE_DATA) {
|
||||
port_status = buf[2];
|
||||
data = &buf[3];
|
||||
|
||||
/* get flag from port_status */
|
||||
flag = 0;
|
||||
|
||||
|
@ -1482,16 +1490,20 @@ static int digi_read_oob_callback(struct urb *urb)
|
|||
struct usb_serial *serial = port->serial;
|
||||
struct tty_struct *tty;
|
||||
struct digi_port *priv = usb_get_serial_port_data(port);
|
||||
unsigned char *buf = urb->transfer_buffer;
|
||||
int opcode, line, status, val;
|
||||
int i;
|
||||
unsigned int rts;
|
||||
|
||||
if (urb->actual_length < 4)
|
||||
return -1;
|
||||
|
||||
/* handle each oob command */
|
||||
for (i = 0; i < urb->actual_length - 3;) {
|
||||
opcode = ((unsigned char *)urb->transfer_buffer)[i++];
|
||||
line = ((unsigned char *)urb->transfer_buffer)[i++];
|
||||
status = ((unsigned char *)urb->transfer_buffer)[i++];
|
||||
val = ((unsigned char *)urb->transfer_buffer)[i++];
|
||||
for (i = 0; i < urb->actual_length - 4; i += 4) {
|
||||
opcode = buf[i];
|
||||
line = buf[i + 1];
|
||||
status = buf[i + 2];
|
||||
val = buf[i + 3];
|
||||
|
||||
dev_dbg(&port->dev, "digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d\n",
|
||||
opcode, line, status, val);
|
||||
|
|
|
@ -1439,10 +1439,13 @@ static int read_latency_timer(struct usb_serial_port *port)
|
|||
FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE,
|
||||
0, priv->interface,
|
||||
buf, 1, WDR_TIMEOUT);
|
||||
if (rv < 0)
|
||||
if (rv < 1) {
|
||||
dev_err(&port->dev, "Unable to read latency timer: %i\n", rv);
|
||||
else
|
||||
if (rv >= 0)
|
||||
rv = -EIO;
|
||||
} else {
|
||||
priv->latency = buf[0];
|
||||
}
|
||||
|
||||
kfree(buf);
|
||||
|
||||
|
@ -1531,7 +1534,7 @@ check_and_exit:
|
|||
}
|
||||
|
||||
static int get_lsr_info(struct usb_serial_port *port,
|
||||
struct serial_struct __user *retinfo)
|
||||
unsigned int __user *retinfo)
|
||||
{
|
||||
struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||||
unsigned int result = 0;
|
||||
|
@ -1802,8 +1805,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
|
|||
|
||||
mutex_init(&priv->cfg_lock);
|
||||
|
||||
priv->flags = ASYNC_LOW_LATENCY;
|
||||
|
||||
if (quirk && quirk->port_probe)
|
||||
quirk->port_probe(priv);
|
||||
|
||||
|
@ -2067,6 +2068,20 @@ static int ftdi_process_packet(struct usb_serial_port *port,
|
|||
priv->prev_status = status;
|
||||
}
|
||||
|
||||
/* save if the transmitter is empty or not */
|
||||
if (packet[1] & FTDI_RS_TEMT)
|
||||
priv->transmit_empty = 1;
|
||||
else
|
||||
priv->transmit_empty = 0;
|
||||
|
||||
len -= 2;
|
||||
if (!len)
|
||||
return 0; /* status only */
|
||||
|
||||
/*
|
||||
* Break and error status must only be processed for packets with
|
||||
* data payload to avoid over-reporting.
|
||||
*/
|
||||
flag = TTY_NORMAL;
|
||||
if (packet[1] & FTDI_RS_ERR_MASK) {
|
||||
/* Break takes precedence over parity, which takes precedence
|
||||
|
@ -2089,15 +2104,6 @@ static int ftdi_process_packet(struct usb_serial_port *port,
|
|||
}
|
||||
}
|
||||
|
||||
/* save if the transmitter is empty or not */
|
||||
if (packet[1] & FTDI_RS_TEMT)
|
||||
priv->transmit_empty = 1;
|
||||
else
|
||||
priv->transmit_empty = 0;
|
||||
|
||||
len -= 2;
|
||||
if (!len)
|
||||
return 0; /* status only */
|
||||
port->icount.rx += len;
|
||||
ch = packet + 2;
|
||||
|
||||
|
@ -2428,8 +2434,12 @@ static int ftdi_get_modem_status(struct usb_serial_port *port,
|
|||
FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
|
||||
0, priv->interface,
|
||||
buf, len, WDR_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
|
||||
/* NOTE: We allow short responses and handle that below. */
|
||||
if (ret < 1) {
|
||||
dev_err(&port->dev, "failed to get modem status: %d\n", ret);
|
||||
if (ret >= 0)
|
||||
ret = -EIO;
|
||||
ret = usb_translate_errors(ret);
|
||||
goto out;
|
||||
}
|
||||
|
@ -2480,20 +2490,15 @@ static int ftdi_ioctl(struct tty_struct *tty,
|
|||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
void __user *argp = (void __user *)arg;
|
||||
|
||||
/* Based on code from acm.c and others */
|
||||
switch (cmd) {
|
||||
|
||||
case TIOCGSERIAL: /* gets serial port data */
|
||||
return get_serial_info(port,
|
||||
(struct serial_struct __user *) arg);
|
||||
|
||||
case TIOCSSERIAL: /* sets serial port data */
|
||||
return set_serial_info(tty, port,
|
||||
(struct serial_struct __user *) arg);
|
||||
case TIOCGSERIAL:
|
||||
return get_serial_info(port, argp);
|
||||
case TIOCSSERIAL:
|
||||
return set_serial_info(tty, port, argp);
|
||||
case TIOCSERGETLSR:
|
||||
return get_lsr_info(port, (struct serial_struct __user *)arg);
|
||||
break;
|
||||
return get_lsr_info(port, argp);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -492,20 +492,24 @@ static int get_epic_descriptor(struct edgeport_serial *ep)
|
|||
int result;
|
||||
struct usb_serial *serial = ep->serial;
|
||||
struct edgeport_product_info *product_info = &ep->product_info;
|
||||
struct edge_compatibility_descriptor *epic = &ep->epic_descriptor;
|
||||
struct edge_compatibility_descriptor *epic;
|
||||
struct edge_compatibility_bits *bits;
|
||||
struct device *dev = &serial->dev->dev;
|
||||
|
||||
ep->is_epic = 0;
|
||||
|
||||
epic = kmalloc(sizeof(*epic), GFP_KERNEL);
|
||||
if (!epic)
|
||||
return -ENOMEM;
|
||||
|
||||
result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
|
||||
USB_REQUEST_ION_GET_EPIC_DESC,
|
||||
0xC0, 0x00, 0x00,
|
||||
&ep->epic_descriptor,
|
||||
sizeof(struct edge_compatibility_descriptor),
|
||||
epic, sizeof(*epic),
|
||||
300);
|
||||
|
||||
if (result > 0) {
|
||||
if (result == sizeof(*epic)) {
|
||||
ep->is_epic = 1;
|
||||
memcpy(&ep->epic_descriptor, epic, sizeof(*epic));
|
||||
memset(product_info, 0, sizeof(struct edgeport_product_info));
|
||||
|
||||
product_info->NumPorts = epic->NumPorts;
|
||||
|
@ -534,8 +538,16 @@ static int get_epic_descriptor(struct edgeport_serial *ep)
|
|||
dev_dbg(dev, " IOSPWriteLCR : %s\n", bits->IOSPWriteLCR ? "TRUE": "FALSE");
|
||||
dev_dbg(dev, " IOSPSetBaudRate : %s\n", bits->IOSPSetBaudRate ? "TRUE": "FALSE");
|
||||
dev_dbg(dev, " TrueEdgeport : %s\n", bits->TrueEdgeport ? "TRUE": "FALSE");
|
||||
|
||||
result = 0;
|
||||
} else if (result >= 0) {
|
||||
dev_warn(&serial->interface->dev, "short epic descriptor received: %d\n",
|
||||
result);
|
||||
result = -EIO;
|
||||
}
|
||||
|
||||
kfree(epic);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1560,7 +1572,6 @@ static int get_serial_info(struct edgeport_port *edge_port,
|
|||
tmp.line = edge_port->port->minor;
|
||||
tmp.port = edge_port->port->port_number;
|
||||
tmp.irq = 0;
|
||||
tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
|
||||
tmp.xmit_fifo_size = edge_port->maxTxCredits;
|
||||
tmp.baud_base = 9600;
|
||||
tmp.close_delay = 5*HZ;
|
||||
|
@ -2090,8 +2101,7 @@ static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr,
|
|||
* rom_read
|
||||
* reads a number of bytes from the Edgeport device starting at the given
|
||||
* address.
|
||||
* If successful returns the number of bytes read, otherwise it returns
|
||||
* a negative error number of the problem.
|
||||
* Returns zero on success or a negative error number.
|
||||
****************************************************************************/
|
||||
static int rom_read(struct usb_serial *serial, __u16 extAddr,
|
||||
__u16 addr, __u16 length, __u8 *data)
|
||||
|
@ -2116,12 +2126,17 @@ static int rom_read(struct usb_serial *serial, __u16 extAddr,
|
|||
USB_REQUEST_ION_READ_ROM,
|
||||
0xC0, addr, extAddr, transfer_buffer,
|
||||
current_length, 300);
|
||||
if (result < 0)
|
||||
if (result < current_length) {
|
||||
if (result >= 0)
|
||||
result = -EIO;
|
||||
break;
|
||||
}
|
||||
memcpy(data, transfer_buffer, current_length);
|
||||
length -= current_length;
|
||||
addr += current_length;
|
||||
data += current_length;
|
||||
|
||||
result = 0;
|
||||
}
|
||||
|
||||
kfree(transfer_buffer);
|
||||
|
@ -2575,9 +2590,10 @@ static void get_manufacturing_desc(struct edgeport_serial *edge_serial)
|
|||
EDGE_MANUF_DESC_LEN,
|
||||
(__u8 *)(&edge_serial->manuf_descriptor));
|
||||
|
||||
if (response < 1)
|
||||
dev_err(dev, "error in getting manufacturer descriptor\n");
|
||||
else {
|
||||
if (response < 0) {
|
||||
dev_err(dev, "error in getting manufacturer descriptor: %d\n",
|
||||
response);
|
||||
} else {
|
||||
char string[30];
|
||||
dev_dbg(dev, "**Manufacturer Descriptor\n");
|
||||
dev_dbg(dev, " RomSize: %dK\n",
|
||||
|
@ -2634,9 +2650,10 @@ static void get_boot_desc(struct edgeport_serial *edge_serial)
|
|||
EDGE_BOOT_DESC_LEN,
|
||||
(__u8 *)(&edge_serial->boot_descriptor));
|
||||
|
||||
if (response < 1)
|
||||
dev_err(dev, "error in getting boot descriptor\n");
|
||||
else {
|
||||
if (response < 0) {
|
||||
dev_err(dev, "error in getting boot descriptor: %d\n",
|
||||
response);
|
||||
} else {
|
||||
dev_dbg(dev, "**Boot Descriptor:\n");
|
||||
dev_dbg(dev, " BootCodeLength: %d\n",
|
||||
le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength));
|
||||
|
@ -2779,7 +2796,7 @@ static int edge_startup(struct usb_serial *serial)
|
|||
dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name);
|
||||
|
||||
/* Read the epic descriptor */
|
||||
if (get_epic_descriptor(edge_serial) <= 0) {
|
||||
if (get_epic_descriptor(edge_serial) < 0) {
|
||||
/* memcpy descriptor to Supports structures */
|
||||
memcpy(&edge_serial->epic_descriptor.Supports, descriptor,
|
||||
sizeof(struct edge_compatibility_bits));
|
||||
|
|
|
@ -2468,7 +2468,6 @@ static int get_serial_info(struct edgeport_port *edge_port,
|
|||
tmp.line = edge_port->port->minor;
|
||||
tmp.port = edge_port->port->port_number;
|
||||
tmp.irq = 0;
|
||||
tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
|
||||
tmp.xmit_fifo_size = edge_port->port->bulk_out_size;
|
||||
tmp.baud_base = 9600;
|
||||
tmp.close_delay = 5*HZ;
|
||||
|
|
|
@ -976,7 +976,6 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
{
|
||||
struct usb_serial *serial = port->serial;
|
||||
struct device *dev = &port->dev;
|
||||
u8 *buf;
|
||||
int result;
|
||||
int baud;
|
||||
u32 actual;
|
||||
|
@ -991,20 +990,8 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
usb_clear_halt(serial->dev, port->write_urb->pipe);
|
||||
usb_clear_halt(serial->dev, port->read_urb->pipe);
|
||||
|
||||
buf = kmalloc(10, GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->poll = 0;
|
||||
|
||||
/* initialize writebuf */
|
||||
#define FISH(a, b, c, d) do { \
|
||||
result = usb_control_msg(port->serial->dev, \
|
||||
usb_rcvctrlpipe(port->serial->dev, 0), \
|
||||
b, a, c, d, buf, 1, 1000); \
|
||||
dev_dbg(dev, "0x%x:0x%x:0x%x:0x%x %d - %x\n", a, b, c, d, result, \
|
||||
buf[0]); } while (0);
|
||||
|
||||
#define SOUP(a, b, c, d) do { \
|
||||
result = usb_control_msg(port->serial->dev, \
|
||||
usb_sndctrlpipe(port->serial->dev, 0), \
|
||||
|
@ -1017,7 +1004,7 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
/* sprintf(buf ,"%c%c%c%c",0x03,0x02,0x02,0x0); */
|
||||
|
||||
SOUP(0x03, 0x02, 0x02, 0x0);
|
||||
kfree(buf);
|
||||
|
||||
iuu_led(port, 0xF000, 0xF000, 0, 0xFF);
|
||||
iuu_uart_on(port);
|
||||
if (boost < 100)
|
||||
|
|
|
@ -139,6 +139,7 @@ static void keyspan_pda_rx_interrupt(struct urb *urb)
|
|||
{
|
||||
struct usb_serial_port *port = urb->context;
|
||||
unsigned char *data = urb->transfer_buffer;
|
||||
unsigned int len = urb->actual_length;
|
||||
int retval;
|
||||
int status = urb->status;
|
||||
struct keyspan_pda_private *priv;
|
||||
|
@ -159,18 +160,26 @@ static void keyspan_pda_rx_interrupt(struct urb *urb)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (len < 1) {
|
||||
dev_warn(&port->dev, "short message received\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* see if the message is data or a status interrupt */
|
||||
switch (data[0]) {
|
||||
case 0:
|
||||
/* rest of message is rx data */
|
||||
if (urb->actual_length) {
|
||||
tty_insert_flip_string(&port->port, data + 1,
|
||||
urb->actual_length - 1);
|
||||
tty_flip_buffer_push(&port->port);
|
||||
}
|
||||
if (len < 2)
|
||||
break;
|
||||
tty_insert_flip_string(&port->port, data + 1, len - 1);
|
||||
tty_flip_buffer_push(&port->port);
|
||||
break;
|
||||
case 1:
|
||||
/* status interrupt */
|
||||
if (len < 3) {
|
||||
dev_warn(&port->dev, "short interrupt message received\n");
|
||||
break;
|
||||
}
|
||||
dev_dbg(&port->dev, "rx int, d1=%d, d2=%d\n", data[1], data[2]);
|
||||
switch (data[1]) {
|
||||
case 1: /* modemline change */
|
||||
|
|
|
@ -89,7 +89,6 @@ static struct usb_serial_driver kl5kusb105d_device = {
|
|||
.open = klsi_105_open,
|
||||
.close = klsi_105_close,
|
||||
.set_termios = klsi_105_set_termios,
|
||||
/*.break_ctl = klsi_105_break_ctl,*/
|
||||
.tiocmget = klsi_105_tiocmget,
|
||||
.port_probe = klsi_105_port_probe,
|
||||
.port_remove = klsi_105_port_remove,
|
||||
|
@ -104,16 +103,15 @@ static struct usb_serial_driver * const serial_drivers[] = {
|
|||
};
|
||||
|
||||
struct klsi_105_port_settings {
|
||||
__u8 pktlen; /* always 5, it seems */
|
||||
__u8 baudrate;
|
||||
__u8 databits;
|
||||
__u8 unknown1;
|
||||
__u8 unknown2;
|
||||
} __attribute__ ((packed));
|
||||
u8 pktlen; /* always 5, it seems */
|
||||
u8 baudrate;
|
||||
u8 databits;
|
||||
u8 unknown1;
|
||||
u8 unknown2;
|
||||
};
|
||||
|
||||
struct klsi_105_private {
|
||||
struct klsi_105_port_settings cfg;
|
||||
struct ktermios termios;
|
||||
unsigned long line_state; /* modem line settings */
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
@ -143,10 +141,12 @@ static int klsi_105_chg_port_settings(struct usb_serial_port *port,
|
|||
if (rc < 0)
|
||||
dev_err(&port->dev,
|
||||
"Change port settings failed (error = %d)\n", rc);
|
||||
dev_info(&port->serial->dev->dev,
|
||||
"%d byte block, baudrate %x, databits %d, u1 %d, u2 %d\n",
|
||||
settings->pktlen, settings->baudrate, settings->databits,
|
||||
settings->unknown1, settings->unknown2);
|
||||
|
||||
dev_dbg(&port->dev,
|
||||
"pktlen %u, baudrate 0x%02x, databits %u, u1 %u, u2 %u\n",
|
||||
settings->pktlen, settings->baudrate, settings->databits,
|
||||
settings->unknown1, settings->unknown2);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -175,8 +175,6 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
|
|||
u8 *status_buf;
|
||||
__u16 status;
|
||||
|
||||
dev_info(&port->serial->dev->dev, "sending SIO Poll request\n");
|
||||
|
||||
status_buf = kmalloc(KLSI_STATUSBUF_LEN, GFP_KERNEL);
|
||||
if (!status_buf)
|
||||
return -ENOMEM;
|
||||
|
@ -199,8 +197,8 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
|
|||
} else {
|
||||
status = get_unaligned_le16(status_buf);
|
||||
|
||||
dev_info(&port->serial->dev->dev, "read status %x %x\n",
|
||||
status_buf[0], status_buf[1]);
|
||||
dev_dbg(&port->dev, "read status %02x %02x\n",
|
||||
status_buf[0], status_buf[1]);
|
||||
|
||||
*line_state_p = klsi_105_status2linestate(status);
|
||||
}
|
||||
|
@ -233,8 +231,6 @@ static int klsi_105_port_probe(struct usb_serial_port *port)
|
|||
|
||||
spin_lock_init(&priv->lock);
|
||||
|
||||
/* priv->termios is left uninitialized until port opening */
|
||||
|
||||
usb_set_serial_port_data(port, priv);
|
||||
|
||||
return 0;
|
||||
|
@ -255,7 +251,6 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
struct klsi_105_private *priv = usb_get_serial_port_data(port);
|
||||
int retval = 0;
|
||||
int rc;
|
||||
int i;
|
||||
unsigned long line_state;
|
||||
struct klsi_105_port_settings *cfg;
|
||||
unsigned long flags;
|
||||
|
@ -278,14 +273,7 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
cfg->unknown2 = 1;
|
||||
klsi_105_chg_port_settings(port, cfg);
|
||||
|
||||
/* set up termios structure */
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->termios.c_iflag = tty->termios.c_iflag;
|
||||
priv->termios.c_oflag = tty->termios.c_oflag;
|
||||
priv->termios.c_cflag = tty->termios.c_cflag;
|
||||
priv->termios.c_lflag = tty->termios.c_lflag;
|
||||
for (i = 0; i < NCCS; i++)
|
||||
priv->termios.c_cc[i] = tty->termios.c_cc[i];
|
||||
priv->cfg.pktlen = cfg->pktlen;
|
||||
priv->cfg.baudrate = cfg->baudrate;
|
||||
priv->cfg.databits = cfg->databits;
|
||||
|
@ -438,19 +426,6 @@ static void klsi_105_set_termios(struct tty_struct *tty,
|
|||
*/
|
||||
baud = tty_get_baud_rate(tty);
|
||||
|
||||
if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
|
||||
/* reassert DTR and (maybe) RTS on transition from B0 */
|
||||
if ((old_cflag & CBAUD) == B0) {
|
||||
dev_dbg(dev, "%s: baud was B0\n", __func__);
|
||||
#if 0
|
||||
priv->control_state |= TIOCM_DTR;
|
||||
/* don't set RTS if using hardware flow control */
|
||||
if (!(old_cflag & CRTSCTS))
|
||||
priv->control_state |= TIOCM_RTS;
|
||||
mct_u232_set_modem_ctrl(serial, priv->control_state);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
switch (baud) {
|
||||
case 0: /* handled below */
|
||||
break;
|
||||
|
@ -484,17 +459,14 @@ static void klsi_105_set_termios(struct tty_struct *tty,
|
|||
baud = 9600;
|
||||
break;
|
||||
}
|
||||
if ((cflag & CBAUD) == B0) {
|
||||
dev_dbg(dev, "%s: baud is B0\n", __func__);
|
||||
/* Drop RTS and DTR */
|
||||
/* maybe this should be simulated by sending read
|
||||
* disable and read enable messages?
|
||||
*/
|
||||
#if 0
|
||||
priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
|
||||
mct_u232_set_modem_ctrl(serial, priv->control_state);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: implement B0 handling
|
||||
*
|
||||
* Maybe this should be simulated by sending read disable and read
|
||||
* enable messages?
|
||||
*/
|
||||
|
||||
tty_encode_baud_rate(tty, baud, baud);
|
||||
|
||||
if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
|
||||
|
@ -528,22 +500,6 @@ static void klsi_105_set_termios(struct tty_struct *tty,
|
|||
|| (cflag & CSTOPB) != (old_cflag & CSTOPB)) {
|
||||
/* Not currently supported */
|
||||
tty->termios.c_cflag &= ~(PARENB|PARODD|CSTOPB);
|
||||
#if 0
|
||||
priv->last_lcr = 0;
|
||||
|
||||
/* set the parity */
|
||||
if (cflag & PARENB)
|
||||
priv->last_lcr |= (cflag & PARODD) ?
|
||||
MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
|
||||
else
|
||||
priv->last_lcr |= MCT_U232_PARITY_NONE;
|
||||
|
||||
/* set the number of stop bits */
|
||||
priv->last_lcr |= (cflag & CSTOPB) ?
|
||||
MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
|
||||
|
||||
mct_u232_set_line_ctrl(serial, priv->last_lcr);
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Set flow control: well, I do not really now how to handle DTR/RTS.
|
||||
|
@ -554,14 +510,6 @@ static void klsi_105_set_termios(struct tty_struct *tty,
|
|||
|| (cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
|
||||
/* Not currently supported */
|
||||
tty->termios.c_cflag &= ~CRTSCTS;
|
||||
/* Drop DTR/RTS if no flow control otherwise assert */
|
||||
#if 0
|
||||
if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS))
|
||||
priv->control_state |= TIOCM_DTR | TIOCM_RTS;
|
||||
else
|
||||
priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
|
||||
mct_u232_set_modem_ctrl(serial, priv->control_state);
|
||||
#endif
|
||||
}
|
||||
memcpy(cfg, &priv->cfg, sizeof(*cfg));
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
@ -572,25 +520,6 @@ err:
|
|||
kfree(cfg);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
|
||||
{
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
struct usb_serial *serial = port->serial;
|
||||
struct mct_u232_private *priv =
|
||||
(struct mct_u232_private *)port->private;
|
||||
unsigned char lcr = priv->last_lcr;
|
||||
|
||||
dev_dbg(&port->dev, "%s - state=%d\n", __func__, break_state);
|
||||
|
||||
/* LOCKING */
|
||||
if (break_state)
|
||||
lcr |= MCT_U232_SET_BREAK;
|
||||
|
||||
mct_u232_set_line_ctrl(serial, lcr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int klsi_105_tiocmget(struct tty_struct *tty)
|
||||
{
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
|
|
|
@ -322,8 +322,12 @@ static int mct_u232_get_modem_stat(struct usb_serial_port *port,
|
|||
MCT_U232_GET_REQUEST_TYPE,
|
||||
0, 0, buf, MCT_U232_GET_MODEM_STAT_SIZE,
|
||||
WDR_TIMEOUT);
|
||||
if (rc < 0) {
|
||||
if (rc < MCT_U232_GET_MODEM_STAT_SIZE) {
|
||||
dev_err(&port->dev, "Get MODEM STATus failed (error = %d)\n", rc);
|
||||
|
||||
if (rc >= 0)
|
||||
rc = -EIO;
|
||||
|
||||
*msr = 0;
|
||||
} else {
|
||||
*msr = buf[0];
|
||||
|
|
|
@ -135,23 +135,8 @@ static void metrousb_read_int_callback(struct urb *urb)
|
|||
throttled = metro_priv->throttled;
|
||||
spin_unlock_irqrestore(&metro_priv->lock, flags);
|
||||
|
||||
/* Continue trying to read if set. */
|
||||
if (!throttled) {
|
||||
usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
|
||||
usb_rcvintpipe(port->serial->dev, port->interrupt_in_endpointAddress),
|
||||
port->interrupt_in_urb->transfer_buffer,
|
||||
port->interrupt_in_urb->transfer_buffer_length,
|
||||
metrousb_read_int_callback, port, 1);
|
||||
|
||||
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
|
||||
|
||||
if (result)
|
||||
dev_err(&port->dev,
|
||||
"%s - failed submitting interrupt in urb, error code=%d\n",
|
||||
__func__, result);
|
||||
}
|
||||
return;
|
||||
|
||||
if (throttled)
|
||||
return;
|
||||
exit:
|
||||
/* Try to resubmit the urb. */
|
||||
result = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
|
@ -161,19 +146,8 @@ exit:
|
|||
__func__, result);
|
||||
}
|
||||
|
||||
static void metrousb_write_int_callback(struct urb *urb)
|
||||
{
|
||||
struct usb_serial_port *port = urb->context;
|
||||
|
||||
dev_warn(&port->dev, "%s not implemented yet.\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
static void metrousb_cleanup(struct usb_serial_port *port)
|
||||
{
|
||||
dev_dbg(&port->dev, "%s\n", __func__);
|
||||
|
||||
usb_unlink_urb(port->interrupt_in_urb);
|
||||
usb_kill_urb(port->interrupt_in_urb);
|
||||
|
||||
metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port);
|
||||
|
@ -186,8 +160,6 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
unsigned long flags = 0;
|
||||
int result = 0;
|
||||
|
||||
dev_dbg(&port->dev, "%s\n", __func__);
|
||||
|
||||
/* Make sure the urb is initialized. */
|
||||
if (!port->interrupt_in_urb) {
|
||||
dev_err(&port->dev, "%s - interrupt urb not initialized\n",
|
||||
|
@ -227,8 +199,6 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
__func__, result);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
dev_dbg(&port->dev, "%s - port open\n", __func__);
|
||||
exit:
|
||||
return result;
|
||||
}
|
||||
|
@ -290,8 +260,6 @@ static void metrousb_throttle(struct tty_struct *tty)
|
|||
struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
|
||||
unsigned long flags = 0;
|
||||
|
||||
dev_dbg(tty->dev, "%s\n", __func__);
|
||||
|
||||
/* Set the private information for the port to stop reading data. */
|
||||
spin_lock_irqsave(&metro_priv->lock, flags);
|
||||
metro_priv->throttled = 1;
|
||||
|
@ -305,8 +273,6 @@ static int metrousb_tiocmget(struct tty_struct *tty)
|
|||
struct metrousb_private *metro_priv = usb_get_serial_port_data(port);
|
||||
unsigned long flags = 0;
|
||||
|
||||
dev_dbg(tty->dev, "%s\n", __func__);
|
||||
|
||||
spin_lock_irqsave(&metro_priv->lock, flags);
|
||||
control_state = metro_priv->control_state;
|
||||
spin_unlock_irqrestore(&metro_priv->lock, flags);
|
||||
|
@ -350,15 +316,12 @@ static void metrousb_unthrottle(struct tty_struct *tty)
|
|||
unsigned long flags = 0;
|
||||
int result = 0;
|
||||
|
||||
dev_dbg(tty->dev, "%s\n", __func__);
|
||||
|
||||
/* Set the private information for the port to resume reading data. */
|
||||
spin_lock_irqsave(&metro_priv->lock, flags);
|
||||
metro_priv->throttled = 0;
|
||||
spin_unlock_irqrestore(&metro_priv->lock, flags);
|
||||
|
||||
/* Submit the urb to read from the port. */
|
||||
port->interrupt_in_urb->dev = port->serial->dev;
|
||||
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
|
||||
if (result)
|
||||
dev_err(tty->dev,
|
||||
|
@ -377,7 +340,6 @@ static struct usb_serial_driver metrousb_device = {
|
|||
.open = metrousb_open,
|
||||
.close = metrousb_cleanup,
|
||||
.read_int_callback = metrousb_read_int_callback,
|
||||
.write_int_callback = metrousb_write_int_callback,
|
||||
.port_probe = metrousb_port_probe,
|
||||
.port_remove = metrousb_port_remove,
|
||||
.throttle = metrousb_throttle,
|
||||
|
|
|
@ -234,11 +234,16 @@ static int read_mos_reg(struct usb_serial *serial, unsigned int serial_portnum,
|
|||
|
||||
status = usb_control_msg(usbdev, pipe, request, requesttype, value,
|
||||
index, buf, 1, MOS_WDR_TIMEOUT);
|
||||
if (status == 1)
|
||||
if (status == 1) {
|
||||
*data = *buf;
|
||||
else if (status < 0)
|
||||
} else {
|
||||
dev_err(&usbdev->dev,
|
||||
"mos7720: usb_control_msg() failed: %d\n", status);
|
||||
if (status >= 0)
|
||||
status = -EIO;
|
||||
*data = 0;
|
||||
}
|
||||
|
||||
kfree(buf);
|
||||
|
||||
return status;
|
||||
|
@ -1846,7 +1851,6 @@ static int get_serial_info(struct moschip_port *mos7720_port,
|
|||
tmp.line = mos7720_port->port->minor;
|
||||
tmp.port = mos7720_port->port->port_number;
|
||||
tmp.irq = 0;
|
||||
tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
|
||||
tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE;
|
||||
tmp.baud_base = 9600;
|
||||
tmp.close_delay = 5*HZ;
|
||||
|
|
|
@ -284,9 +284,15 @@ static int mos7840_get_reg_sync(struct usb_serial_port *port, __u16 reg,
|
|||
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,
|
||||
MCS_RD_RTYPE, 0, reg, buf, VENDOR_READ_LENGTH,
|
||||
MOS_WDR_TIMEOUT);
|
||||
if (ret < VENDOR_READ_LENGTH) {
|
||||
if (ret >= 0)
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*val = buf[0];
|
||||
dev_dbg(&port->dev, "%s offset is %x, return val %x\n", __func__, reg, *val);
|
||||
|
||||
out:
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
@ -352,8 +358,13 @@ static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg,
|
|||
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,
|
||||
MCS_RD_RTYPE, Wval, reg, buf, VENDOR_READ_LENGTH,
|
||||
MOS_WDR_TIMEOUT);
|
||||
if (ret < VENDOR_READ_LENGTH) {
|
||||
if (ret >= 0)
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
*val = buf[0];
|
||||
|
||||
out:
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1023,6 +1034,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
* (can't set it up in mos7840_startup as the structures *
|
||||
* were not set up at that time.) */
|
||||
if (port0->open_ports == 1) {
|
||||
/* FIXME: Buffer never NULL, so URB is not submitted. */
|
||||
if (serial->port[0]->interrupt_in_buffer == NULL) {
|
||||
/* set up interrupt urb */
|
||||
usb_fill_int_urb(serial->port[0]->interrupt_in_urb,
|
||||
|
@ -1479,10 +1491,10 @@ static int mos7840_tiocmget(struct tty_struct *tty)
|
|||
return -ENODEV;
|
||||
|
||||
status = mos7840_get_uart_reg(port, MODEM_STATUS_REGISTER, &msr);
|
||||
if (status != 1)
|
||||
if (status < 0)
|
||||
return -EIO;
|
||||
status = mos7840_get_uart_reg(port, MODEM_CONTROL_REGISTER, &mcr);
|
||||
if (status != 1)
|
||||
if (status < 0)
|
||||
return -EIO;
|
||||
result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0)
|
||||
| ((mcr & MCR_RTS) ? TIOCM_RTS : 0)
|
||||
|
@ -1952,7 +1964,6 @@ static int mos7840_get_serial_info(struct moschip_port *mos7840_port,
|
|||
tmp.line = mos7840_port->port->minor;
|
||||
tmp.port = mos7840_port->port->port_number;
|
||||
tmp.irq = 0;
|
||||
tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
|
||||
tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE;
|
||||
tmp.baud_base = 9600;
|
||||
tmp.close_delay = 5 * HZ;
|
||||
|
@ -2106,7 +2117,8 @@ static int mos7840_calc_num_ports(struct usb_serial *serial)
|
|||
static int mos7840_attach(struct usb_serial *serial)
|
||||
{
|
||||
if (serial->num_bulk_in < serial->num_ports ||
|
||||
serial->num_bulk_out < serial->num_ports) {
|
||||
serial->num_bulk_out < serial->num_ports ||
|
||||
serial->num_interrupt_in < 1) {
|
||||
dev_err(&serial->interface->dev, "missing endpoints\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
|
|
@ -142,7 +142,7 @@ static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
usb_clear_halt(port->serial->dev, port->read_urb->pipe);
|
||||
|
||||
res = usb_serial_generic_open(tty, port);
|
||||
if (!res)
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
/* Request CTS line state, sometimes during opening the current
|
||||
|
@ -343,7 +343,6 @@ static int get_serial_info(struct usb_serial_port *port,
|
|||
tmp.line = port->minor;
|
||||
tmp.port = 0;
|
||||
tmp.irq = 0;
|
||||
tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
|
||||
tmp.xmit_fifo_size = 1024;
|
||||
tmp.baud_base = 9600;
|
||||
tmp.close_delay = 5*HZ;
|
||||
|
|
|
@ -450,7 +450,7 @@ static int pl2303_get_line_request(struct usb_serial_port *port,
|
|||
if (ret != 7) {
|
||||
dev_err(&port->dev, "%s - failed: %d\n", __func__, ret);
|
||||
|
||||
if (ret > 0)
|
||||
if (ret >= 0)
|
||||
ret = -EIO;
|
||||
|
||||
return ret;
|
||||
|
@ -470,12 +470,8 @@ static int pl2303_set_line_request(struct usb_serial_port *port,
|
|||
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE,
|
||||
0, 0, buf, 7, 100);
|
||||
if (ret != 7) {
|
||||
if (ret < 0) {
|
||||
dev_err(&port->dev, "%s - failed: %d\n", __func__, ret);
|
||||
|
||||
if (ret > 0)
|
||||
ret = -EIO;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -188,22 +188,22 @@ static inline int qt2_setdevice(struct usb_device *dev, u8 *data)
|
|||
}
|
||||
|
||||
|
||||
static inline int qt2_getdevice(struct usb_device *dev, u8 *data)
|
||||
{
|
||||
return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||
QT_SET_GET_DEVICE, 0xc0, 0, 0,
|
||||
data, 3, QT2_USB_TIMEOUT);
|
||||
}
|
||||
|
||||
static inline int qt2_getregister(struct usb_device *dev,
|
||||
u8 uart,
|
||||
u8 reg,
|
||||
u8 *data)
|
||||
{
|
||||
return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||
QT_SET_GET_REGISTER, 0xc0, reg,
|
||||
uart, data, sizeof(*data), QT2_USB_TIMEOUT);
|
||||
int ret;
|
||||
|
||||
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||
QT_SET_GET_REGISTER, 0xc0, reg,
|
||||
uart, data, sizeof(*data), QT2_USB_TIMEOUT);
|
||||
if (ret < sizeof(*data)) {
|
||||
if (ret >= 0)
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int qt2_setregister(struct usb_device *dev,
|
||||
|
@ -372,9 +372,11 @@ static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
0xc0, 0,
|
||||
device_port, data, 2, QT2_USB_TIMEOUT);
|
||||
|
||||
if (status < 0) {
|
||||
if (status < 2) {
|
||||
dev_err(&port->dev, "%s - open port failed %i\n", __func__,
|
||||
status);
|
||||
if (status >= 0)
|
||||
status = -EIO;
|
||||
kfree(data);
|
||||
return status;
|
||||
}
|
||||
|
@ -463,7 +465,6 @@ static int get_serial_info(struct usb_serial_port *port,
|
|||
tmp.line = port->minor;
|
||||
tmp.port = 0;
|
||||
tmp.irq = 0;
|
||||
tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
|
||||
tmp.xmit_fifo_size = port->bulk_out_size;
|
||||
tmp.baud_base = 9600;
|
||||
tmp.close_delay = 5*HZ;
|
||||
|
|
|
@ -137,24 +137,9 @@ static int is_himemory(const u8 ifnum,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int sierra_calc_interface(struct usb_serial *serial)
|
||||
static u8 sierra_interface_num(struct usb_serial *serial)
|
||||
{
|
||||
int interface;
|
||||
struct usb_interface *p_interface;
|
||||
struct usb_host_interface *p_host_interface;
|
||||
|
||||
/* Get the interface structure pointer from the serial struct */
|
||||
p_interface = serial->interface;
|
||||
|
||||
/* Get a pointer to the host interface structure */
|
||||
p_host_interface = p_interface->cur_altsetting;
|
||||
|
||||
/* read the interface descriptor for this active altsetting
|
||||
* to find out the interface number we are on
|
||||
*/
|
||||
interface = p_host_interface->desc.bInterfaceNumber;
|
||||
|
||||
return interface;
|
||||
return serial->interface->cur_altsetting->desc.bInterfaceNumber;
|
||||
}
|
||||
|
||||
static int sierra_probe(struct usb_serial *serial,
|
||||
|
@ -165,7 +150,7 @@ static int sierra_probe(struct usb_serial *serial,
|
|||
u8 ifnum;
|
||||
|
||||
udev = serial->dev;
|
||||
ifnum = sierra_calc_interface(serial);
|
||||
ifnum = sierra_interface_num(serial);
|
||||
|
||||
/*
|
||||
* If this interface supports more than 1 alternate
|
||||
|
@ -178,9 +163,6 @@ static int sierra_probe(struct usb_serial *serial,
|
|||
usb_set_interface(udev, ifnum, 1);
|
||||
}
|
||||
|
||||
/* ifnum could have changed - by calling usb_set_interface */
|
||||
ifnum = sierra_calc_interface(serial);
|
||||
|
||||
if (is_blacklisted(ifnum,
|
||||
(struct sierra_iface_info *)id->driver_info)) {
|
||||
dev_dbg(&serial->dev->dev,
|
||||
|
@ -342,7 +324,7 @@ static int sierra_send_setup(struct usb_serial_port *port)
|
|||
|
||||
/* If composite device then properly report interface */
|
||||
if (serial->num_ports == 1) {
|
||||
interface = sierra_calc_interface(serial);
|
||||
interface = sierra_interface_num(serial);
|
||||
/* Control message is sent only to interfaces with
|
||||
* interrupt_in endpoints
|
||||
*/
|
||||
|
@ -916,7 +898,7 @@ static int sierra_port_probe(struct usb_serial_port *port)
|
|||
/* Determine actual memory requirements */
|
||||
if (serial->num_ports == 1) {
|
||||
/* Get interface number for composite device */
|
||||
ifnum = sierra_calc_interface(serial);
|
||||
ifnum = sierra_interface_num(serial);
|
||||
himemoryp = &typeB_interface_list;
|
||||
} else {
|
||||
/* This is really the usb-serial port number of the interface
|
||||
|
|
|
@ -232,11 +232,17 @@ static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status)
|
|||
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||
GET_UART_STATUS, GET_UART_STATUS_TYPE,
|
||||
0, GET_UART_STATUS_MSR, buf, 1, 100);
|
||||
if (ret < 0)
|
||||
if (ret < 1) {
|
||||
dev_err(&port->dev, "failed to get modem status: %d\n", ret);
|
||||
if (ret >= 0)
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_dbg(&port->dev, "0xc0:0x22:0:6 %d - 0x02%x\n", ret, *buf);
|
||||
*status = *buf;
|
||||
ret = 0;
|
||||
out:
|
||||
kfree(buf);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -80,9 +80,17 @@ static inline int ssu100_setdevice(struct usb_device *dev, u8 *data)
|
|||
|
||||
static inline int ssu100_getdevice(struct usb_device *dev, u8 *data)
|
||||
{
|
||||
return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||
QT_SET_GET_DEVICE, 0xc0, 0, 0,
|
||||
data, 3, 300);
|
||||
int ret;
|
||||
|
||||
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||
QT_SET_GET_DEVICE, 0xc0, 0, 0,
|
||||
data, 3, 300);
|
||||
if (ret < 3) {
|
||||
if (ret >= 0)
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int ssu100_getregister(struct usb_device *dev,
|
||||
|
@ -90,10 +98,17 @@ static inline int ssu100_getregister(struct usb_device *dev,
|
|||
unsigned short reg,
|
||||
u8 *data)
|
||||
{
|
||||
return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||
QT_SET_GET_REGISTER, 0xc0, reg,
|
||||
uart, data, sizeof(*data), 300);
|
||||
int ret;
|
||||
|
||||
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||
QT_SET_GET_REGISTER, 0xc0, reg,
|
||||
uart, data, sizeof(*data), 300);
|
||||
if (ret < sizeof(*data)) {
|
||||
if (ret >= 0)
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -289,8 +304,10 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
|
|||
QT_OPEN_CLOSE_CHANNEL,
|
||||
QT_TRANSFER_IN, 0x01,
|
||||
0, data, 2, 300);
|
||||
if (result < 0) {
|
||||
if (result < 2) {
|
||||
dev_dbg(&port->dev, "%s - open failed %i\n", __func__, result);
|
||||
if (result >= 0)
|
||||
result = -EIO;
|
||||
kfree(data);
|
||||
return result;
|
||||
}
|
||||
|
@ -322,7 +339,6 @@ static int get_serial_info(struct usb_serial_port *port,
|
|||
tmp.line = port->minor;
|
||||
tmp.port = 0;
|
||||
tmp.irq = 0;
|
||||
tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
|
||||
tmp.xmit_fifo_size = port->bulk_out_size;
|
||||
tmp.baud_base = 9600;
|
||||
tmp.close_delay = 5*HZ;
|
||||
|
|
|
@ -1553,13 +1553,10 @@ static int ti_command_out_sync(struct ti_device *tdev, __u8 command,
|
|||
(USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT),
|
||||
value, moduleid, data, size, 1000);
|
||||
|
||||
if (status == size)
|
||||
status = 0;
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
if (status > 0)
|
||||
status = -ECOMM;
|
||||
|
||||
return status;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1575,8 +1572,7 @@ static int ti_command_in_sync(struct ti_device *tdev, __u8 command,
|
|||
|
||||
if (status == size)
|
||||
status = 0;
|
||||
|
||||
if (status > 0)
|
||||
else if (status >= 0)
|
||||
status = -ECOMM;
|
||||
|
||||
return status;
|
||||
|
|
|
@ -0,0 +1,440 @@
|
|||
/*
|
||||
* Renesas Electronics uPD78F0730 USB to serial converter driver
|
||||
*
|
||||
* Copyright (C) 2014,2016 Maksim Salau <maksim.salau@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* Protocol of the adaptor is described in the application note U19660EJ1V0AN00
|
||||
* μPD78F0730 8-bit Single-Chip Microcontroller
|
||||
* USB-to-Serial Conversion Software
|
||||
* <https://www.renesas.com/en-eu/doc/DocumentServer/026/U19660EJ1V0AN00.pdf>
|
||||
*
|
||||
* The adaptor functionality is limited to the following:
|
||||
* - data bits: 7 or 8
|
||||
* - stop bits: 1 or 2
|
||||
* - parity: even, odd or none
|
||||
* - flow control: none
|
||||
* - baud rates: 0, 2400, 4800, 9600, 19200, 38400, 57600, 115200
|
||||
* - signals: DTR, RTS and BREAK
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/serial.h>
|
||||
|
||||
#define DRIVER_DESC "Renesas uPD78F0730 USB to serial converter driver"
|
||||
|
||||
#define DRIVER_AUTHOR "Maksim Salau <maksim.salau@gmail.com>"
|
||||
|
||||
static const struct usb_device_id id_table[] = {
|
||||
{ USB_DEVICE(0x045B, 0x0212) }, /* YRPBRL78G13, YRPBRL78G14 */
|
||||
{ USB_DEVICE(0x0409, 0x0063) }, /* V850ESJX3-STICK */
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, id_table);
|
||||
|
||||
/*
|
||||
* Each adaptor is associated with a private structure, that holds the current
|
||||
* state of control signals (DTR, RTS and BREAK).
|
||||
*/
|
||||
struct upd78f0730_port_private {
|
||||
struct mutex lock; /* mutex to protect line_signals */
|
||||
u8 line_signals;
|
||||
};
|
||||
|
||||
/* Op-codes of control commands */
|
||||
#define UPD78F0730_CMD_LINE_CONTROL 0x00
|
||||
#define UPD78F0730_CMD_SET_DTR_RTS 0x01
|
||||
#define UPD78F0730_CMD_SET_XON_XOFF_CHR 0x02
|
||||
#define UPD78F0730_CMD_OPEN_CLOSE 0x03
|
||||
#define UPD78F0730_CMD_SET_ERR_CHR 0x04
|
||||
|
||||
/* Data sizes in UPD78F0730_CMD_LINE_CONTROL command */
|
||||
#define UPD78F0730_DATA_SIZE_7_BITS 0x00
|
||||
#define UPD78F0730_DATA_SIZE_8_BITS 0x01
|
||||
#define UPD78F0730_DATA_SIZE_MASK 0x01
|
||||
|
||||
/* Stop-bit modes in UPD78F0730_CMD_LINE_CONTROL command */
|
||||
#define UPD78F0730_STOP_BIT_1_BIT 0x00
|
||||
#define UPD78F0730_STOP_BIT_2_BIT 0x02
|
||||
#define UPD78F0730_STOP_BIT_MASK 0x02
|
||||
|
||||
/* Parity modes in UPD78F0730_CMD_LINE_CONTROL command */
|
||||
#define UPD78F0730_PARITY_NONE 0x00
|
||||
#define UPD78F0730_PARITY_EVEN 0x04
|
||||
#define UPD78F0730_PARITY_ODD 0x08
|
||||
#define UPD78F0730_PARITY_MASK 0x0C
|
||||
|
||||
/* Flow control modes in UPD78F0730_CMD_LINE_CONTROL command */
|
||||
#define UPD78F0730_FLOW_CONTROL_NONE 0x00
|
||||
#define UPD78F0730_FLOW_CONTROL_HW 0x10
|
||||
#define UPD78F0730_FLOW_CONTROL_SW 0x20
|
||||
#define UPD78F0730_FLOW_CONTROL_MASK 0x30
|
||||
|
||||
/* Control signal bits in UPD78F0730_CMD_SET_DTR_RTS command */
|
||||
#define UPD78F0730_RTS 0x01
|
||||
#define UPD78F0730_DTR 0x02
|
||||
#define UPD78F0730_BREAK 0x04
|
||||
|
||||
/* Port modes in UPD78F0730_CMD_OPEN_CLOSE command */
|
||||
#define UPD78F0730_PORT_CLOSE 0x00
|
||||
#define UPD78F0730_PORT_OPEN 0x01
|
||||
|
||||
/* Error character substitution modes in UPD78F0730_CMD_SET_ERR_CHR command */
|
||||
#define UPD78F0730_ERR_CHR_DISABLED 0x00
|
||||
#define UPD78F0730_ERR_CHR_ENABLED 0x01
|
||||
|
||||
/*
|
||||
* Declaration of command structures
|
||||
*/
|
||||
|
||||
/* UPD78F0730_CMD_LINE_CONTROL command */
|
||||
struct upd78f0730_line_control {
|
||||
u8 opcode;
|
||||
__le32 baud_rate;
|
||||
u8 params;
|
||||
} __packed;
|
||||
|
||||
/* UPD78F0730_CMD_SET_DTR_RTS command */
|
||||
struct upd78f0730_set_dtr_rts {
|
||||
u8 opcode;
|
||||
u8 params;
|
||||
};
|
||||
|
||||
/* UPD78F0730_CMD_SET_XON_OFF_CHR command */
|
||||
struct upd78f0730_set_xon_xoff_chr {
|
||||
u8 opcode;
|
||||
u8 xon;
|
||||
u8 xoff;
|
||||
};
|
||||
|
||||
/* UPD78F0730_CMD_OPEN_CLOSE command */
|
||||
struct upd78f0730_open_close {
|
||||
u8 opcode;
|
||||
u8 state;
|
||||
};
|
||||
|
||||
/* UPD78F0730_CMD_SET_ERR_CHR command */
|
||||
struct upd78f0730_set_err_chr {
|
||||
u8 opcode;
|
||||
u8 state;
|
||||
u8 err_char;
|
||||
};
|
||||
|
||||
static int upd78f0730_send_ctl(struct usb_serial_port *port,
|
||||
const void *data, int size)
|
||||
{
|
||||
struct usb_device *usbdev = port->serial->dev;
|
||||
void *buf;
|
||||
int res;
|
||||
|
||||
if (size <= 0 || !data)
|
||||
return -EINVAL;
|
||||
|
||||
buf = kmemdup(data, size, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
res = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x00,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
|
||||
0x0000, 0x0000, buf, size, USB_CTRL_SET_TIMEOUT);
|
||||
|
||||
kfree(buf);
|
||||
|
||||
if (res != size) {
|
||||
struct device *dev = &port->dev;
|
||||
|
||||
dev_err(dev, "failed to send control request %02x: %d\n",
|
||||
*(u8 *)data, res);
|
||||
/* The maximum expected length of a transfer is 6 bytes */
|
||||
if (res >= 0)
|
||||
res = -EIO;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int upd78f0730_port_probe(struct usb_serial_port *port)
|
||||
{
|
||||
struct upd78f0730_port_private *private;
|
||||
|
||||
private = kzalloc(sizeof(*private), GFP_KERNEL);
|
||||
if (!private)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&private->lock);
|
||||
usb_set_serial_port_data(port, private);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int upd78f0730_port_remove(struct usb_serial_port *port)
|
||||
{
|
||||
struct upd78f0730_port_private *private;
|
||||
|
||||
private = usb_get_serial_port_data(port);
|
||||
mutex_destroy(&private->lock);
|
||||
kfree(private);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int upd78f0730_tiocmget(struct tty_struct *tty)
|
||||
{
|
||||
struct device *dev = tty->dev;
|
||||
struct upd78f0730_port_private *private;
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
int signals;
|
||||
int res;
|
||||
|
||||
private = usb_get_serial_port_data(port);
|
||||
|
||||
mutex_lock(&private->lock);
|
||||
signals = private->line_signals;
|
||||
mutex_unlock(&private->lock);
|
||||
|
||||
res = ((signals & UPD78F0730_DTR) ? TIOCM_DTR : 0) |
|
||||
((signals & UPD78F0730_RTS) ? TIOCM_RTS : 0);
|
||||
|
||||
dev_dbg(dev, "%s - res = %x\n", __func__, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int upd78f0730_tiocmset(struct tty_struct *tty,
|
||||
unsigned int set, unsigned int clear)
|
||||
{
|
||||
struct device *dev = tty->dev;
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
struct upd78f0730_port_private *private;
|
||||
struct upd78f0730_set_dtr_rts request;
|
||||
int res;
|
||||
|
||||
private = usb_get_serial_port_data(port);
|
||||
|
||||
mutex_lock(&private->lock);
|
||||
if (set & TIOCM_DTR) {
|
||||
private->line_signals |= UPD78F0730_DTR;
|
||||
dev_dbg(dev, "%s - set DTR\n", __func__);
|
||||
}
|
||||
if (set & TIOCM_RTS) {
|
||||
private->line_signals |= UPD78F0730_RTS;
|
||||
dev_dbg(dev, "%s - set RTS\n", __func__);
|
||||
}
|
||||
if (clear & TIOCM_DTR) {
|
||||
private->line_signals &= ~UPD78F0730_DTR;
|
||||
dev_dbg(dev, "%s - clear DTR\n", __func__);
|
||||
}
|
||||
if (clear & TIOCM_RTS) {
|
||||
private->line_signals &= ~UPD78F0730_RTS;
|
||||
dev_dbg(dev, "%s - clear RTS\n", __func__);
|
||||
}
|
||||
request.opcode = UPD78F0730_CMD_SET_DTR_RTS;
|
||||
request.params = private->line_signals;
|
||||
|
||||
res = upd78f0730_send_ctl(port, &request, sizeof(request));
|
||||
mutex_unlock(&private->lock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void upd78f0730_break_ctl(struct tty_struct *tty, int break_state)
|
||||
{
|
||||
struct device *dev = tty->dev;
|
||||
struct upd78f0730_port_private *private;
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
struct upd78f0730_set_dtr_rts request;
|
||||
|
||||
private = usb_get_serial_port_data(port);
|
||||
|
||||
mutex_lock(&private->lock);
|
||||
if (break_state) {
|
||||
private->line_signals |= UPD78F0730_BREAK;
|
||||
dev_dbg(dev, "%s - set BREAK\n", __func__);
|
||||
} else {
|
||||
private->line_signals &= ~UPD78F0730_BREAK;
|
||||
dev_dbg(dev, "%s - clear BREAK\n", __func__);
|
||||
}
|
||||
request.opcode = UPD78F0730_CMD_SET_DTR_RTS;
|
||||
request.params = private->line_signals;
|
||||
|
||||
upd78f0730_send_ctl(port, &request, sizeof(request));
|
||||
mutex_unlock(&private->lock);
|
||||
}
|
||||
|
||||
static void upd78f0730_dtr_rts(struct usb_serial_port *port, int on)
|
||||
{
|
||||
struct tty_struct *tty = port->port.tty;
|
||||
unsigned int set = 0;
|
||||
unsigned int clear = 0;
|
||||
|
||||
if (on)
|
||||
set = TIOCM_DTR | TIOCM_RTS;
|
||||
else
|
||||
clear = TIOCM_DTR | TIOCM_RTS;
|
||||
|
||||
upd78f0730_tiocmset(tty, set, clear);
|
||||
}
|
||||
|
||||
static speed_t upd78f0730_get_baud_rate(struct tty_struct *tty)
|
||||
{
|
||||
const speed_t baud_rate = tty_get_baud_rate(tty);
|
||||
const speed_t supported[] = {
|
||||
0, 2400, 4800, 9600, 19200, 38400, 57600, 115200
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = ARRAY_SIZE(supported) - 1; i >= 0; i--) {
|
||||
if (baud_rate == supported[i])
|
||||
return baud_rate;
|
||||
}
|
||||
|
||||
/* If the baud rate is not supported, switch to the default one */
|
||||
tty_encode_baud_rate(tty, 9600, 9600);
|
||||
|
||||
return tty_get_baud_rate(tty);
|
||||
}
|
||||
|
||||
static void upd78f0730_set_termios(struct tty_struct *tty,
|
||||
struct usb_serial_port *port,
|
||||
struct ktermios *old_termios)
|
||||
{
|
||||
struct device *dev = &port->dev;
|
||||
struct upd78f0730_line_control request;
|
||||
speed_t baud_rate;
|
||||
|
||||
if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios))
|
||||
return;
|
||||
|
||||
if (C_BAUD(tty) == B0)
|
||||
upd78f0730_dtr_rts(port, 0);
|
||||
else if (old_termios && (old_termios->c_cflag & CBAUD) == B0)
|
||||
upd78f0730_dtr_rts(port, 1);
|
||||
|
||||
baud_rate = upd78f0730_get_baud_rate(tty);
|
||||
request.opcode = UPD78F0730_CMD_LINE_CONTROL;
|
||||
request.baud_rate = cpu_to_le32(baud_rate);
|
||||
request.params = 0;
|
||||
dev_dbg(dev, "%s - baud rate = %d\n", __func__, baud_rate);
|
||||
|
||||
switch (C_CSIZE(tty)) {
|
||||
case CS7:
|
||||
request.params |= UPD78F0730_DATA_SIZE_7_BITS;
|
||||
dev_dbg(dev, "%s - 7 data bits\n", __func__);
|
||||
break;
|
||||
default:
|
||||
tty->termios.c_cflag &= ~CSIZE;
|
||||
tty->termios.c_cflag |= CS8;
|
||||
dev_warn(dev, "data size is not supported, using 8 bits\n");
|
||||
/* fall through */
|
||||
case CS8:
|
||||
request.params |= UPD78F0730_DATA_SIZE_8_BITS;
|
||||
dev_dbg(dev, "%s - 8 data bits\n", __func__);
|
||||
break;
|
||||
}
|
||||
|
||||
if (C_PARENB(tty)) {
|
||||
if (C_PARODD(tty)) {
|
||||
request.params |= UPD78F0730_PARITY_ODD;
|
||||
dev_dbg(dev, "%s - odd parity\n", __func__);
|
||||
} else {
|
||||
request.params |= UPD78F0730_PARITY_EVEN;
|
||||
dev_dbg(dev, "%s - even parity\n", __func__);
|
||||
}
|
||||
|
||||
if (C_CMSPAR(tty)) {
|
||||
tty->termios.c_cflag &= ~CMSPAR;
|
||||
dev_warn(dev, "MARK/SPACE parity is not supported\n");
|
||||
}
|
||||
} else {
|
||||
request.params |= UPD78F0730_PARITY_NONE;
|
||||
dev_dbg(dev, "%s - no parity\n", __func__);
|
||||
}
|
||||
|
||||
if (C_CSTOPB(tty)) {
|
||||
request.params |= UPD78F0730_STOP_BIT_2_BIT;
|
||||
dev_dbg(dev, "%s - 2 stop bits\n", __func__);
|
||||
} else {
|
||||
request.params |= UPD78F0730_STOP_BIT_1_BIT;
|
||||
dev_dbg(dev, "%s - 1 stop bit\n", __func__);
|
||||
}
|
||||
|
||||
if (C_CRTSCTS(tty)) {
|
||||
tty->termios.c_cflag &= ~CRTSCTS;
|
||||
dev_warn(dev, "RTSCTS flow control is not supported\n");
|
||||
}
|
||||
if (I_IXOFF(tty) || I_IXON(tty)) {
|
||||
tty->termios.c_iflag &= ~(IXOFF | IXON);
|
||||
dev_warn(dev, "XON/XOFF flow control is not supported\n");
|
||||
}
|
||||
request.params |= UPD78F0730_FLOW_CONTROL_NONE;
|
||||
dev_dbg(dev, "%s - no flow control\n", __func__);
|
||||
|
||||
upd78f0730_send_ctl(port, &request, sizeof(request));
|
||||
}
|
||||
|
||||
static int upd78f0730_open(struct tty_struct *tty, struct usb_serial_port *port)
|
||||
{
|
||||
struct upd78f0730_open_close request = {
|
||||
.opcode = UPD78F0730_CMD_OPEN_CLOSE,
|
||||
.state = UPD78F0730_PORT_OPEN
|
||||
};
|
||||
int res;
|
||||
|
||||
res = upd78f0730_send_ctl(port, &request, sizeof(request));
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
if (tty)
|
||||
upd78f0730_set_termios(tty, port, NULL);
|
||||
|
||||
return usb_serial_generic_open(tty, port);
|
||||
}
|
||||
|
||||
static void upd78f0730_close(struct usb_serial_port *port)
|
||||
{
|
||||
struct upd78f0730_open_close request = {
|
||||
.opcode = UPD78F0730_CMD_OPEN_CLOSE,
|
||||
.state = UPD78F0730_PORT_CLOSE
|
||||
};
|
||||
|
||||
usb_serial_generic_close(port);
|
||||
upd78f0730_send_ctl(port, &request, sizeof(request));
|
||||
}
|
||||
|
||||
static struct usb_serial_driver upd78f0730_device = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "upd78f0730",
|
||||
},
|
||||
.id_table = id_table,
|
||||
.num_ports = 1,
|
||||
.port_probe = upd78f0730_port_probe,
|
||||
.port_remove = upd78f0730_port_remove,
|
||||
.open = upd78f0730_open,
|
||||
.close = upd78f0730_close,
|
||||
.set_termios = upd78f0730_set_termios,
|
||||
.tiocmget = upd78f0730_tiocmget,
|
||||
.tiocmset = upd78f0730_tiocmset,
|
||||
.dtr_rts = upd78f0730_dtr_rts,
|
||||
.break_ctl = upd78f0730_break_ctl,
|
||||
};
|
||||
|
||||
static struct usb_serial_driver * const serial_drivers[] = {
|
||||
&upd78f0730_device,
|
||||
NULL
|
||||
};
|
||||
|
||||
module_usb_serial_driver(serial_drivers, id_table);
|
||||
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -487,7 +487,6 @@ static int whiteheat_ioctl(struct tty_struct *tty,
|
|||
serstruct.type = PORT_16654;
|
||||
serstruct.line = port->minor;
|
||||
serstruct.port = port->port_number;
|
||||
serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
|
||||
serstruct.xmit_fifo_size = kfifo_size(&port->write_fifo);
|
||||
serstruct.custom_divisor = 0;
|
||||
serstruct.baud_base = 460800;
|
||||
|
|
Загрузка…
Ссылка в новой задаче