summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-11-15 18:11:53 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-11-15 18:11:53 +0800
commit6e0f30604dbdac542b8b76e4ec9521b3064c981c (patch)
tree1aa3883fbd7208e2eee0a3fb3ac757a1c9340467 /drivers/usb
parente47ff01b94b64f5cea3b43dbfa4f27bb605789a4 (diff)
parentc1a1f273d0825774c80896b8deb1c9ea1d0b91e3 (diff)
downloadlinux-6e0f30604dbdac542b8b76e4ec9521b3064c981c.tar.gz
linux-6e0f30604dbdac542b8b76e4ec9521b3064c981c.tar.bz2
linux-6e0f30604dbdac542b8b76e4ec9521b3064c981c.zip
Merge tag 'usb-serial-5.5-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-next
Johan writes: USB-serial updates for 5.5-rc1 Here are the USB-serial updates for 5.5-rc1, including: - support for a new class of pl2303 devices - improved divisor calculations for ch341 - fixes for a remote-wakeup bug in the moschip drivers - improved device-type handling in mos7840 - various cleanups of mos7840 Included are also some new device ids. All have been in linux-next with no reported issues. Signed-off-by: Johan Hovold <johan@kernel.org> * tag 'usb-serial-5.5-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial: USB: serial: ftdi_sio: add device IDs for U-Blox C099-F9P USB: serial: option: add support for Foxconn T77W968 LTE modules USB: serial: mos7840: drop port open flag USB: serial: mos7840: drop read-urb check USB: serial: mos7840: drop port driver data accessors USB: serial: mos7840: drop serial struct accessor USB: serial: mos7840: drop paranoid serial checks USB: serial: mos7840: drop paranoid port checks USB: serial: mos7840: drop redundant urb context check USB: serial: mos7840: rip out broken interrupt handling USB: serial: mos7840: fix probe error handling USB: serial: mos7840: document MCS7810 detection hack USB: serial: mos7840: clean up device-type handling USB: serial: mos7840: fix remote wakeup USB: serial: mos7720: fix remote wakeup USB: serial: option: add support for DW5821e with eSIM support USB: serial: mos7840: add USB ID to support Moxa UPort 2210 USB: serial: ch341: reimplement line-speed handling USB: serial: pl2303: add support for PL2303HXN
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/serial/ch341.c97
-rw-r--r--drivers/usb/serial/ftdi_sio.c3
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h7
-rw-r--r--drivers/usb/serial/mos7720.c4
-rw-r--r--drivers/usb/serial/mos7840.c762
-rw-r--r--drivers/usb/serial/option.c7
-rw-r--r--drivers/usb/serial/pl2303.c124
-rw-r--r--drivers/usb/serial/pl2303.h6
8 files changed, 300 insertions, 710 deletions
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 3bb1fff02bed..df582fe855f0 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -48,12 +48,6 @@
#define CH341_BIT_DCD 0x08
#define CH341_BITS_MODEM_STAT 0x0f /* all bits */
-/*******************************/
-/* baudrate calculation factor */
-/*******************************/
-#define CH341_BAUDBASE_FACTOR 1532620800
-#define CH341_BAUDBASE_DIVMAX 3
-
/* Break support - the information used to implement this was gleaned from
* the Net/FreeBSD uchcom.c driver by Takanori Watanabe. Domo arigato.
*/
@@ -144,37 +138,96 @@ static int ch341_control_in(struct usb_device *dev,
return 0;
}
+#define CH341_CLKRATE 48000000
+#define CH341_CLK_DIV(ps, fact) (1 << (12 - 3 * (ps) - (fact)))
+#define CH341_MIN_RATE(ps) (CH341_CLKRATE / (CH341_CLK_DIV((ps), 1) * 512))
+
+static const speed_t ch341_min_rates[] = {
+ CH341_MIN_RATE(0),
+ CH341_MIN_RATE(1),
+ CH341_MIN_RATE(2),
+ CH341_MIN_RATE(3),
+};
+
+/*
+ * The device line speed is given by the following equation:
+ *
+ * baudrate = 48000000 / (2^(12 - 3 * ps - fact) * div), where
+ *
+ * 0 <= ps <= 3,
+ * 0 <= fact <= 1,
+ * 2 <= div <= 256 if fact = 0, or
+ * 9 <= div <= 256 if fact = 1
+ */
+static int ch341_get_divisor(speed_t speed)
+{
+ unsigned int fact, div, clk_div;
+ int ps;
+
+ /*
+ * Clamp to supported range, this makes the (ps < 0) and (div < 2)
+ * sanity checks below redundant.
+ */
+ speed = clamp(speed, 46U, 3000000U);
+
+ /*
+ * Start with highest possible base clock (fact = 1) that will give a
+ * divisor strictly less than 512.
+ */
+ fact = 1;
+ for (ps = 3; ps >= 0; ps--) {
+ if (speed > ch341_min_rates[ps])
+ break;
+ }
+
+ if (ps < 0)
+ return -EINVAL;
+
+ /* Determine corresponding divisor, rounding down. */
+ clk_div = CH341_CLK_DIV(ps, fact);
+ div = CH341_CLKRATE / (clk_div * speed);
+
+ /* Halve base clock (fact = 0) if required. */
+ if (div < 9 || div > 255) {
+ div /= 2;
+ clk_div *= 2;
+ fact = 0;
+ }
+
+ if (div < 2)
+ return -EINVAL;
+
+ /*
+ * Pick next divisor if resulting rate is closer to the requested one,
+ * scale up to avoid rounding errors on low rates.
+ */
+ if (16 * CH341_CLKRATE / (clk_div * div) - 16 * speed >=
+ 16 * speed - 16 * CH341_CLKRATE / (clk_div * (div + 1)))
+ div++;
+
+ return (0x100 - div) << 8 | fact << 2 | ps;
+}
+
static int ch341_set_baudrate_lcr(struct usb_device *dev,
struct ch341_private *priv, u8 lcr)
{
- short a;
+ int val;
int r;
- unsigned long factor;
- short divisor;
if (!priv->baud_rate)
return -EINVAL;
- factor = (CH341_BAUDBASE_FACTOR / priv->baud_rate);
- divisor = CH341_BAUDBASE_DIVMAX;
-
- while ((factor > 0xfff0) && divisor) {
- factor >>= 3;
- divisor--;
- }
- if (factor > 0xfff0)
+ val = ch341_get_divisor(priv->baud_rate);
+ if (val < 0)
return -EINVAL;
- factor = 0x10000 - factor;
- a = (factor & 0xff00) | divisor;
-
/*
* CH341A buffers data until a full endpoint-size packet (32 bytes)
* has been received unless bit 7 is set.
*/
- a |= BIT(7);
+ val |= BIT(7);
- r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x1312, a);
+ r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x1312, val);
if (r)
return r;
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 25e81faf4c24..9ad44a96dfe3 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1033,6 +1033,9 @@ static const struct usb_device_id id_table_combined[] = {
/* Sienna devices */
{ USB_DEVICE(FTDI_VID, FTDI_SIENNA_PID) },
{ USB_DEVICE(ECHELON_VID, ECHELON_U20_PID) },
+ /* U-Blox devices */
+ { USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ZED_PID) },
+ { USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ODIN_PID) },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 22d66217cb41..e8373528264c 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -1558,3 +1558,10 @@
*/
#define UNJO_VID 0x22B7
#define UNJO_ISODEBUG_V1_PID 0x150D
+
+/*
+ * U-Blox products (http://www.u-blox.com).
+ */
+#define UBLOX_VID 0x1546
+#define UBLOX_C099F9P_ZED_PID 0x0502
+#define UBLOX_C099F9P_ODIN_PID 0x0503
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 18110225d506..2ec4eeacebc7 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -1833,10 +1833,6 @@ static int mos7720_startup(struct usb_serial *serial)
product = le16_to_cpu(serial->dev->descriptor.idProduct);
dev = serial->dev;
- /* setting configuration feature to one */
- usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5000);
-
if (product == MOSCHIP_DEVICE_ID_7715) {
struct urb *urb = serial->port[0]->interrupt_in_urb;
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index a698d46ba773..23f91d658cb4 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -89,17 +89,10 @@
/* For higher baud Rates use TIOCEXBAUD */
#define TIOCEXBAUD 0x5462
-/* vendor id and device id defines */
-
-/* The native mos7840/7820 component */
-#define USB_VENDOR_ID_MOSCHIP 0x9710
-#define MOSCHIP_DEVICE_ID_7840 0x7840
-#define MOSCHIP_DEVICE_ID_7843 0x7843
-#define MOSCHIP_DEVICE_ID_7820 0x7820
-#define MOSCHIP_DEVICE_ID_7810 0x7810
-/* The native component can have its vendor/device id's overridden
- * in vendor-specific implementations. Such devices can be handled
- * by making a change here, in id_table.
+/*
+ * Vendor id and device id defines
+ *
+ * NOTE: Do not add new defines, add entries directly to the id_table instead.
*/
#define USB_VENDOR_ID_BANDB 0x0856
#define BANDB_DEVICE_ID_USO9ML2_2 0xAC22
@@ -116,14 +109,6 @@
#define BANDB_DEVICE_ID_USOPTL4_4P 0xBC03
#define BANDB_DEVICE_ID_USOPTL2_4 0xAC24
-/* This driver also supports
- * ATEN UC2324 device using Moschip MCS7840
- * ATEN UC2322 device using Moschip MCS7820
- */
-#define USB_VENDOR_ID_ATENINTL 0x0557
-#define ATENINTL_DEVICE_ID_UC2324 0x2011
-#define ATENINTL_DEVICE_ID_UC2322 0x7820
-
/* Interrupt Routine Defines */
#define SERIAL_IIR_RLS 0x06
@@ -171,30 +156,37 @@
#define LED_OFF_MS 500
enum mos7840_flag {
- MOS7840_FLAG_CTRL_BUSY,
MOS7840_FLAG_LED_BUSY,
};
+#define MCS_PORT_MASK GENMASK(2, 0)
+#define MCS_PORTS(nr) ((nr) & MCS_PORT_MASK)
+#define MCS_LED BIT(3)
+
+#define MCS_DEVICE(vid, pid, flags) \
+ USB_DEVICE((vid), (pid)), .driver_info = (flags)
+
static const struct usb_device_id id_table[] = {
- {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
- {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7843)},
- {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
- {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7810)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4P)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2P)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4P)},
- {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)},
- {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
- {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)},
+ { MCS_DEVICE(0x0557, 0x2011, MCS_PORTS(4)) }, /* ATEN UC2324 */
+ { MCS_DEVICE(0x0557, 0x7820, MCS_PORTS(2)) }, /* ATEN UC2322 */
+ { MCS_DEVICE(0x110a, 0x2210, MCS_PORTS(2)) }, /* Moxa UPort 2210 */
+ { MCS_DEVICE(0x9710, 0x7810, MCS_PORTS(1) | MCS_LED) }, /* ASIX MCS7810 */
+ { MCS_DEVICE(0x9710, 0x7820, MCS_PORTS(2)) }, /* MosChip MCS7820 */
+ { MCS_DEVICE(0x9710, 0x7840, MCS_PORTS(4)) }, /* MosChip MCS7840 */
+ { MCS_DEVICE(0x9710, 0x7843, MCS_PORTS(3)) }, /* ASIX MCS7840 3 port */
+ { USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2) },
+ { USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P) },
+ { USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4) },
+ { USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4P) },
+ { USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2) },
+ { USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4) },
+ { USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2) },
+ { USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4) },
+ { USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2) },
+ { USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2P) },
+ { USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4) },
+ { USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4P) },
+ { USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4) },
{} /* terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table);
@@ -206,19 +198,12 @@ struct moschip_port {
struct urb *read_urb; /* read URB for this port */
__u8 shadowLCR; /* last LCR value received */
__u8 shadowMCR; /* last MCR value received */
- char open;
- char open_ports;
struct usb_serial_port *port; /* loop back to the owner of this object */
/* Offsets */
__u8 SpRegOffset;
__u8 ControlRegOffset;
__u8 DcrRegOffset;
- /* for processing control URBS in interrupt context */
- struct urb *control_urb;
- struct usb_ctrlrequest *dr;
- char *ctrl_buf;
- int MsrLsr;
spinlock_t pool_lock;
struct urb *write_urb_pool[NUM_URBS];
@@ -360,150 +345,11 @@ static void mos7840_dump_serial_port(struct usb_serial_port *port,
/************************************************************************/
/************************************************************************/
-/* I N T E R F A C E F U N C T I O N S */
-/* I N T E R F A C E F U N C T I O N S */
-/************************************************************************/
-/************************************************************************/
-
-static inline void mos7840_set_port_private(struct usb_serial_port *port,
- struct moschip_port *data)
-{
- usb_set_serial_port_data(port, (void *)data);
-}
-
-static inline struct moschip_port *mos7840_get_port_private(struct
- usb_serial_port
- *port)
-{
- return (struct moschip_port *)usb_get_serial_port_data(port);
-}
-
-static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)
-{
- struct moschip_port *mos7840_port;
- struct async_icount *icount;
- mos7840_port = port;
- if (new_msr &
- (MOS_MSR_DELTA_CTS | MOS_MSR_DELTA_DSR | MOS_MSR_DELTA_RI |
- MOS_MSR_DELTA_CD)) {
- icount = &mos7840_port->port->icount;
-
- /* update input line counters */
- if (new_msr & MOS_MSR_DELTA_CTS)
- icount->cts++;
- if (new_msr & MOS_MSR_DELTA_DSR)
- icount->dsr++;
- if (new_msr & MOS_MSR_DELTA_CD)
- icount->dcd++;
- if (new_msr & MOS_MSR_DELTA_RI)
- icount->rng++;
-
- wake_up_interruptible(&port->port->port.delta_msr_wait);
- }
-}
-
-static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
-{
- struct async_icount *icount;
-
- if (new_lsr & SERIAL_LSR_BI) {
- /*
- * Parity and Framing errors only count if they
- * occur exclusive of a break being
- * received.
- */
- new_lsr &= (__u8) (SERIAL_LSR_OE | SERIAL_LSR_BI);
- }
-
- /* update input line counters */
- icount = &port->port->icount;
- if (new_lsr & SERIAL_LSR_BI)
- icount->brk++;
- if (new_lsr & SERIAL_LSR_OE)
- icount->overrun++;
- if (new_lsr & SERIAL_LSR_PE)
- icount->parity++;
- if (new_lsr & SERIAL_LSR_FE)
- icount->frame++;
-}
-
-/************************************************************************/
-/************************************************************************/
/* U S B C A L L B A C K F U N C T I O N S */
/* U S B C A L L B A C K F U N C T I O N S */
/************************************************************************/
/************************************************************************/
-static void mos7840_control_callback(struct urb *urb)
-{
- unsigned char *data;
- struct moschip_port *mos7840_port;
- struct device *dev = &urb->dev->dev;
- __u8 regval = 0x0;
- int status = urb->status;
-
- mos7840_port = urb->context;
-
- switch (status) {
- case 0:
- /* success */
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- dev_dbg(dev, "%s - urb shutting down with status: %d\n", __func__, status);
- goto out;
- default:
- dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status);
- goto out;
- }
-
- dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length);
- if (urb->actual_length < 1)
- goto out;
-
- dev_dbg(dev, "%s mos7840_port->MsrLsr is %d port %d\n", __func__,
- mos7840_port->MsrLsr, mos7840_port->port_num);
- data = urb->transfer_buffer;
- regval = (__u8) data[0];
- dev_dbg(dev, "%s data is %x\n", __func__, regval);
- if (mos7840_port->MsrLsr == 0)
- mos7840_handle_new_msr(mos7840_port, regval);
- else if (mos7840_port->MsrLsr == 1)
- mos7840_handle_new_lsr(mos7840_port, regval);
-out:
- clear_bit_unlock(MOS7840_FLAG_CTRL_BUSY, &mos7840_port->flags);
-}
-
-static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
- __u16 *val)
-{
- struct usb_device *dev = mcs->port->serial->dev;
- struct usb_ctrlrequest *dr = mcs->dr;
- unsigned char *buffer = mcs->ctrl_buf;
- int ret;
-
- if (test_and_set_bit_lock(MOS7840_FLAG_CTRL_BUSY, &mcs->flags))
- return -EBUSY;
-
- dr->bRequestType = MCS_RD_RTYPE;
- dr->bRequest = MCS_RDREQ;
- dr->wValue = cpu_to_le16(Wval); /* 0 */
- dr->wIndex = cpu_to_le16(reg);
- dr->wLength = cpu_to_le16(2);
-
- usb_fill_control_urb(mcs->control_urb, dev, usb_rcvctrlpipe(dev, 0),
- (unsigned char *)dr, buffer, 2,
- mos7840_control_callback, mcs);
- mcs->control_urb->transfer_buffer_length = 2;
- ret = usb_submit_urb(mcs->control_urb, GFP_ATOMIC);
- if (ret)
- clear_bit_unlock(MOS7840_FLAG_CTRL_BUSY, &mcs->flags);
-
- return ret;
-}
-
static void mos7840_set_led_callback(struct urb *urb)
{
switch (urb->status) {
@@ -580,146 +426,6 @@ static void mos7840_led_activity(struct usb_serial_port *port)
}
/*****************************************************************************
- * mos7840_interrupt_callback
- * this is the callback function for when we have received data on the
- * interrupt endpoint.
- *****************************************************************************/
-
-static void mos7840_interrupt_callback(struct urb *urb)
-{
- int result;
- int length;
- struct moschip_port *mos7840_port;
- struct usb_serial *serial;
- __u16 Data;
- unsigned char *data;
- __u8 sp[5];
- int i, rv = 0;
- __u16 wval, wreg = 0;
- int status = urb->status;
-
- switch (status) {
- case 0:
- /* success */
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d\n",
- __func__, status);
- return;
- default:
- dev_dbg(&urb->dev->dev, "%s - nonzero urb status received: %d\n",
- __func__, status);
- goto exit;
- }
-
- length = urb->actual_length;
- data = urb->transfer_buffer;
-
- serial = urb->context;
-
- /* Moschip get 5 bytes
- * Byte 1 IIR Port 1 (port.number is 0)
- * Byte 2 IIR Port 2 (port.number is 1)
- * Byte 3 IIR Port 3 (port.number is 2)
- * Byte 4 IIR Port 4 (port.number is 3)
- * Byte 5 FIFO status for both */
-
- if (length > 5) {
- dev_dbg(&urb->dev->dev, "%s", "Wrong data !!!\n");
- return;
- }
-
- sp[0] = (__u8) data[0];
- sp[1] = (__u8) data[1];
- sp[2] = (__u8) data[2];
- sp[3] = (__u8) data[3];
-
- for (i = 0; i < serial->num_ports; i++) {
- mos7840_port = mos7840_get_port_private(serial->port[i]);
- wval = ((__u16)serial->port[i]->port_number + 1) << 8;
- if (mos7840_port->open) {
- if (sp[i] & 0x01) {
- dev_dbg(&urb->dev->dev, "SP%d No Interrupt !!!\n", i);
- } else {
- switch (sp[i] & 0x0f) {
- case SERIAL_IIR_RLS:
- dev_dbg(&urb->dev->dev, "Serial Port %d: Receiver status error or \n", i);
- dev_dbg(&urb->dev->dev, "address bit detected in 9-bit mode\n");
- mos7840_port->MsrLsr = 1;
- wreg = LINE_STATUS_REGISTER;
- break;
- case SERIAL_IIR_MS:
- dev_dbg(&urb->dev->dev, "Serial Port %d: Modem status change\n", i);
- mos7840_port->MsrLsr = 0;
- wreg = MODEM_STATUS_REGISTER;
- break;
- }
- rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
- }
- }
- }
- if (!(rv < 0))
- /* the completion handler for the control urb will resubmit */
- return;
-exit:
- result = usb_submit_urb(urb, GFP_ATOMIC);
- if (result) {
- dev_err(&urb->dev->dev,
- "%s - Error %d submitting interrupt urb\n",
- __func__, result);
- }
-}
-
-static int mos7840_port_paranoia_check(struct usb_serial_port *port,
- const char *function)
-{
- if (!port) {
- pr_debug("%s - port == NULL\n", function);
- return -1;
- }
- if (!port->serial) {
- pr_debug("%s - port->serial == NULL\n", function);
- return -1;
- }
-
- return 0;
-}
-
-/* Inline functions to check the sanity of a pointer that is passed to us */
-static int mos7840_serial_paranoia_check(struct usb_serial *serial,
- const char *function)
-{
- if (!serial) {
- pr_debug("%s - serial == NULL\n", function);
- return -1;
- }
- if (!serial->type) {
- pr_debug("%s - serial->type == NULL!\n", function);
- return -1;
- }
-
- return 0;
-}
-
-static struct usb_serial *mos7840_get_usb_serial(struct usb_serial_port *port,
- const char *function)
-{
- /* if no port was specified, or it fails a paranoia check */
- if (!port ||
- mos7840_port_paranoia_check(port, function) ||
- mos7840_serial_paranoia_check(port->serial, function)) {
- /* then say that we don't have a valid usb_serial thing,
- * which will end up genrating -ENODEV return values */
- return NULL;
- }
-
- return port->serial;
-}
-
-/*****************************************************************************
* mos7840_bulk_in_callback
* this is the callback function for when we have received data on the
* bulk in endpoint.
@@ -727,35 +433,18 @@ static struct usb_serial *mos7840_get_usb_serial(struct usb_serial_port *port,
static void mos7840_bulk_in_callback(struct urb *urb)
{
+ struct moschip_port *mos7840_port = urb->context;
+ struct usb_serial_port *port = mos7840_port->port;
int retval;
unsigned char *data;
- struct usb_serial *serial;
- struct usb_serial_port *port;
- struct moschip_port *mos7840_port;
int status = urb->status;
- mos7840_port = urb->context;
- if (!mos7840_port)
- return;
-
if (status) {
dev_dbg(&urb->dev->dev, "nonzero read bulk status received: %d\n", status);
mos7840_port->read_urb_busy = false;
return;
}
- port = mos7840_port->port;
- if (mos7840_port_paranoia_check(port, __func__)) {
- mos7840_port->read_urb_busy = false;
- return;
- }
-
- serial = mos7840_get_usb_serial(port, __func__);
- if (!serial) {
- mos7840_port->read_urb_busy = false;
- return;
- }
-
data = urb->transfer_buffer;
usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
@@ -767,12 +456,6 @@ static void mos7840_bulk_in_callback(struct urb *urb)
dev_dbg(&port->dev, "icount.rx is %d:\n", port->icount.rx);
}
- if (!mos7840_port->read_urb) {
- dev_dbg(&port->dev, "%s", "URB KILLED !!!\n");
- mos7840_port->read_urb_busy = false;
- return;
- }
-
if (mos7840_port->has_led)
mos7840_led_activity(port);
@@ -793,14 +476,12 @@ static void mos7840_bulk_in_callback(struct urb *urb)
static void mos7840_bulk_out_data_callback(struct urb *urb)
{
- struct moschip_port *mos7840_port;
- struct usb_serial_port *port;
+ struct moschip_port *mos7840_port = urb->context;
+ struct usb_serial_port *port = mos7840_port->port;
int status = urb->status;
unsigned long flags;
int i;
- mos7840_port = urb->context;
- port = mos7840_port->port;
spin_lock_irqsave(&mos7840_port->pool_lock, flags);
for (i = 0; i < NUM_URBS; i++) {
if (urb == mos7840_port->write_urb_pool[i]) {
@@ -815,11 +496,7 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
return;
}
- if (mos7840_port_paranoia_check(port, __func__))
- return;
-
- if (mos7840_port->open)
- tty_port_tty_wakeup(&port->port);
+ tty_port_tty_wakeup(&port->port);
}
@@ -836,32 +513,16 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
{
+ struct moschip_port *mos7840_port = usb_get_serial_port_data(port);
+ struct usb_serial *serial = port->serial;
int response;
int j;
- struct usb_serial *serial;
struct urb *urb;
__u16 Data;
int status;
- struct moschip_port *mos7840_port;
- struct moschip_port *port0;
-
- if (mos7840_port_paranoia_check(port, __func__))
- return -ENODEV;
-
- serial = port->serial;
-
- if (mos7840_serial_paranoia_check(serial, __func__))
- return -ENODEV;
-
- mos7840_port = mos7840_get_port_private(port);
- port0 = mos7840_get_port_private(serial->port[0]);
-
- if (mos7840_port == NULL || port0 == NULL)
- return -ENODEV;
usb_clear_halt(serial->dev, port->write_urb->pipe);
usb_clear_halt(serial->dev, port->read_urb->pipe);
- port0->open_ports++;
/* Initialising the write urb pool */
for (j = 0; j < NUM_URBS; ++j) {
@@ -1012,41 +673,6 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset,
Data);
- /* Check to see if we've set up our endpoint info yet *
- * (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,
- serial->dev,
- usb_rcvintpipe(serial->dev,
- serial->port[0]->interrupt_in_endpointAddress),
- serial->port[0]->interrupt_in_buffer,
- serial->port[0]->interrupt_in_urb->
- transfer_buffer_length,
- mos7840_interrupt_callback,
- serial,
- serial->port[0]->interrupt_in_urb->interval);
-
- /* start interrupt read for mos7840 */
- response =
- usb_submit_urb(serial->port[0]->interrupt_in_urb,
- GFP_KERNEL);
- if (response) {
- dev_err(&port->dev, "%s - Error %d submitting "
- "interrupt urb\n", __func__, response);
- }
-
- }
-
- }
-
- /* see if we've set up our endpoint info yet *
- * (can't set it up in mos7840_startup as the *
- * structures were not set up at that time.) */
-
dev_dbg(&port->dev, "port number is %d\n", port->port_number);
dev_dbg(&port->dev, "minor number is %d\n", port->minor);
dev_dbg(&port->dev, "Bulkin endpoint is %d\n", port->bulk_in_endpointAddress);
@@ -1086,9 +712,6 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
/* initialize our port settings */
/* Must set to enable ints! */
mos7840_port->shadowMCR = MCR_MASTER_IE;
- /* send a open port command */
- mos7840_port->open = 1;
- /* mos7840_change_port_settings(mos7840_port,old_termios); */
return 0;
err:
@@ -1115,17 +738,10 @@ err:
static int mos7840_chars_in_buffer(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
+ struct moschip_port *mos7840_port = usb_get_serial_port_data(port);
int i;
int chars = 0;
unsigned long flags;
- struct moschip_port *mos7840_port;
-
- if (mos7840_port_paranoia_check(port, __func__))
- return 0;
-
- mos7840_port = mos7840_get_port_private(port);
- if (mos7840_port == NULL)
- return 0;
spin_lock_irqsave(&mos7840_port->pool_lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
@@ -1147,25 +763,10 @@ static int mos7840_chars_in_buffer(struct tty_struct *tty)
static void mos7840_close(struct usb_serial_port *port)
{
- struct usb_serial *serial;
- struct moschip_port *mos7840_port;
- struct moschip_port *port0;
+ struct moschip_port *mos7840_port = usb_get_serial_port_data(port);
int j;
__u16 Data;
- if (mos7840_port_paranoia_check(port, __func__))
- return;
-
- serial = mos7840_get_usb_serial(port, __func__);
- if (!serial)
- return;
-
- mos7840_port = mos7840_get_port_private(port);
- port0 = mos7840_get_port_private(serial->port[0]);
-
- if (mos7840_port == NULL || port0 == NULL)
- return;
-
for (j = 0; j < NUM_URBS; ++j)
usb_kill_urb(mos7840_port->write_urb_pool[j]);
@@ -1180,22 +781,11 @@ static void mos7840_close(struct usb_serial_port *port)
usb_kill_urb(mos7840_port->read_urb);
mos7840_port->read_urb_busy = false;
- port0->open_ports--;
- dev_dbg(&port->dev, "%s in close%d\n", __func__, port0->open_ports);
- if (port0->open_ports == 0) {
- if (serial->port[0]->interrupt_in_urb) {
- dev_dbg(&port->dev, "Shutdown interrupt_in_urb\n");
- usb_kill_urb(serial->port[0]->interrupt_in_urb);
- }
- }
-
Data = 0x0;
mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
Data = 0x00;
mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
-
- mos7840_port->open = 0;
}
/*****************************************************************************
@@ -1205,21 +795,8 @@ static void mos7840_close(struct usb_serial_port *port)
static void mos7840_break(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
+ struct moschip_port *mos7840_port = usb_get_serial_port_data(port);
unsigned char data;
- struct usb_serial *serial;
- struct moschip_port *mos7840_port;
-
- if (mos7840_port_paranoia_check(port, __func__))
- return;
-
- serial = mos7840_get_usb_serial(port, __func__);
- if (!serial)
- return;
-
- mos7840_port = mos7840_get_port_private(port);
-
- if (mos7840_port == NULL)
- return;
if (break_state == -1)
data = mos7840_port->shadowLCR | LCR_SET_BREAK;
@@ -1244,17 +821,10 @@ static void mos7840_break(struct tty_struct *tty, int break_state)
static int mos7840_write_room(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
+ struct moschip_port *mos7840_port = usb_get_serial_port_data(port);
int i;
int room = 0;
unsigned long flags;
- struct moschip_port *mos7840_port;
-
- if (mos7840_port_paranoia_check(port, __func__))
- return -1;
-
- mos7840_port = mos7840_get_port_private(port);
- if (mos7840_port == NULL)
- return -1;
spin_lock_irqsave(&mos7840_port->pool_lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
@@ -1280,29 +850,17 @@ static int mos7840_write_room(struct tty_struct *tty)
static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *data, int count)
{
+ struct moschip_port *mos7840_port = usb_get_serial_port_data(port);
+ struct usb_serial *serial = port->serial;
int status;
int i;
int bytes_sent = 0;
int transfer_size;
unsigned long flags;
-
- struct moschip_port *mos7840_port;
- struct usb_serial *serial;
struct urb *urb;
/* __u16 Data; */
const unsigned char *current_position = data;
- if (mos7840_port_paranoia_check(port, __func__))
- return -1;
-
- serial = port->serial;
- if (mos7840_serial_paranoia_check(serial, __func__))
- return -1;
-
- mos7840_port = mos7840_get_port_private(port);
- if (mos7840_port == NULL)
- return -1;
-
/* try to find a free urb in the list */
urb = NULL;
@@ -1383,22 +941,9 @@ exit:
static void mos7840_throttle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- struct moschip_port *mos7840_port;
+ struct moschip_port *mos7840_port = usb_get_serial_port_data(port);
int status;
- if (mos7840_port_paranoia_check(port, __func__))
- return;
-
- mos7840_port = mos7840_get_port_private(port);
-
- if (mos7840_port == NULL)
- return;
-
- if (!mos7840_port->open) {
- dev_dbg(&port->dev, "%s", "port not opened\n");
- return;
- }
-
/* if we are implementing XON/XOFF, send the stop character */
if (I_IXOFF(tty)) {
unsigned char stop_char = STOP_CHAR(tty);
@@ -1425,19 +970,8 @@ static void mos7840_throttle(struct tty_struct *tty)
static void mos7840_unthrottle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
+ struct moschip_port *mos7840_port = usb_get_serial_port_data(port);
int status;
- struct moschip_port *mos7840_port = mos7840_get_port_private(port);
-
- if (mos7840_port_paranoia_check(port, __func__))
- return;
-
- if (mos7840_port == NULL)
- return;
-
- if (!mos7840_port->open) {
- dev_dbg(&port->dev, "%s - port not opened\n", __func__);
- return;
- }
/* if we are implementing XON/XOFF, send the start character */
if (I_IXOFF(tty)) {
@@ -1460,15 +994,10 @@ static void mos7840_unthrottle(struct tty_struct *tty)
static int mos7840_tiocmget(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- struct moschip_port *mos7840_port;
unsigned int result;
__u16 msr;
__u16 mcr;
int status;
- mos7840_port = mos7840_get_port_private(port);
-
- if (mos7840_port == NULL)
- return -ENODEV;
status = mos7840_get_uart_reg(port, MODEM_STATUS_REGISTER, &msr);
if (status < 0)
@@ -1493,15 +102