* [PATCH 0/5] USB: serial: cp210x: add support for line-status events
@ 2020-07-13 10:55 Johan Hovold
2020-07-13 10:55 ` [PATCH 1/5] USB: serial: cp210x: disable interface on errors in open Johan Hovold
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Johan Hovold @ 2020-07-13 10:55 UTC (permalink / raw)
To: linux-usb; +Cc: Jaromír Škorpil, Johan Hovold
This series add supports for line-status events that specifically can be
used to detect parity errors.
The implementation relies on the device's event-insertion mode, which
can also be used to detect line-breaks and modem status changes. But as
this doesn't seem to work as expected on CP2102, support has been left
unimplemented for now.
Included are also a couple of cleanups.
Johan
Changes since RFC [1]:
- drop sysrq support which relies on break detection
- use 0xec (instead of 0xff) as escape character
[1] https://lore.kernel.org/r/20200703150104.GE3453@localhost
Johan Hovold (5):
USB: serial: cp210x: disable interface on errors in open
USB: serial: cp210x: add support for line-status events
USB: serial: cp210x: add support for TIOCGICOUNT
USB: serial: cp210x: drop unnecessary packed attributes
USB: serial: cp210x: use in-kernel types in port data
drivers/usb/serial/cp210x.c | 209 ++++++++++++++++++++++++++++++++++--
1 file changed, 201 insertions(+), 8 deletions(-)
--
2.26.2
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/5] USB: serial: cp210x: disable interface on errors in open
2020-07-13 10:55 [PATCH 0/5] USB: serial: cp210x: add support for line-status events Johan Hovold
@ 2020-07-13 10:55 ` Johan Hovold
2020-07-13 10:55 ` [PATCH 2/5] USB: serial: cp210x: add support for line-status events Johan Hovold
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Johan Hovold @ 2020-07-13 10:55 UTC (permalink / raw)
To: linux-usb; +Cc: Jaromír Škorpil, Johan Hovold
Try to disable the serial interface in the unlikely event that generic
open() fails.
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/usb/serial/cp210x.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index a90801ef0055..c01c7863dd1a 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -824,7 +824,16 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
if (tty)
cp210x_change_speed(tty, port, NULL);
- return usb_serial_generic_open(tty, port);
+ result = usb_serial_generic_open(tty, port);
+ if (result)
+ goto err_disable;
+
+ return 0;
+
+err_disable:
+ cp210x_write_u16_reg(port, CP210X_IFC_ENABLE, UART_DISABLE);
+
+ return result;
}
static void cp210x_close(struct usb_serial_port *port)
--
2.26.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/5] USB: serial: cp210x: add support for line-status events
2020-07-13 10:55 [PATCH 0/5] USB: serial: cp210x: add support for line-status events Johan Hovold
2020-07-13 10:55 ` [PATCH 1/5] USB: serial: cp210x: disable interface on errors in open Johan Hovold
@ 2020-07-13 10:55 ` Johan Hovold
2020-07-13 10:55 ` [PATCH 3/5] USB: serial: cp210x: add support for TIOCGICOUNT Johan Hovold
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Johan Hovold @ 2020-07-13 10:55 UTC (permalink / raw)
To: linux-usb; +Cc: Jaromír Škorpil, Johan Hovold
Add support for line-status events that specifically can be used to
detect and report parity errors.
Enable the device's event-insertion mode whenever input-parity checking
is requested. This will insert line and modem status events into the
data stream.
Note that modem-status changes appear to be buffered until a character
is received (at least on CP2102) and support is therefore left
unimplemented.
On at least one type of these chips (CP2102), line breaks are not
reported as expected either (regardless of whether SERIAL_BREAK_CHAR is
set) so do not enable event-mode when !IGNBRK is requested for now.
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/usb/serial/cp210x.c | 189 +++++++++++++++++++++++++++++++++++-
1 file changed, 186 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index c01c7863dd1a..02e4acb2823b 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -50,6 +50,9 @@ static void cp210x_release(struct usb_serial *);
static int cp210x_port_probe(struct usb_serial_port *);
static int cp210x_port_remove(struct usb_serial_port *);
static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
+static void cp210x_process_read_urb(struct urb *urb);
+static void cp210x_enable_event_mode(struct usb_serial_port *port);
+static void cp210x_disable_event_mode(struct usb_serial_port *port);
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x045B, 0x0053) }, /* Renesas RX610 RX-Stick */
@@ -253,9 +256,21 @@ struct cp210x_serial_private {
bool use_actual_rate;
};
+enum cp210x_event_state {
+ ES_DATA,
+ ES_ESCAPE,
+ ES_LSR,
+ ES_LSR_DATA_0,
+ ES_LSR_DATA_1,
+ ES_MSR
+};
+
struct cp210x_port_private {
__u8 bInterfaceNumber;
bool has_swapped_line_ctl;
+ bool event_mode;
+ enum cp210x_event_state event_state;
+ u8 lsr;
};
static struct usb_serial_driver cp210x_device = {
@@ -281,7 +296,8 @@ static struct usb_serial_driver cp210x_device = {
.release = cp210x_release,
.port_probe = cp210x_port_probe,
.port_remove = cp210x_port_remove,
- .dtr_rts = cp210x_dtr_rts
+ .dtr_rts = cp210x_dtr_rts,
+ .process_read_urb = cp210x_process_read_urb,
};
static struct usb_serial_driver * const serial_drivers[] = {
@@ -403,6 +419,15 @@ struct cp210x_comm_status {
*/
#define PURGE_ALL 0x000f
+/* CP210X_EMBED_EVENTS */
+#define CP210X_ESCCHAR 0xec
+
+#define CP210X_LSR_OVERRUN BIT(1)
+#define CP210X_LSR_PARITY BIT(2)
+#define CP210X_LSR_FRAME BIT(3)
+#define CP210X_LSR_BREAK BIT(4)
+
+
/* CP210X_GET_FLOW/CP210X_SET_FLOW read/write these 0x10 bytes */
struct cp210x_flow_ctl {
__le32 ulControlHandshake;
@@ -809,6 +834,7 @@ static int cp210x_get_line_ctl(struct usb_serial_port *port, u16 *ctl)
static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
{
+ struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
int result;
result = cp210x_write_u16_reg(port, CP210X_IFC_ENABLE, UART_ENABLE);
@@ -820,10 +846,14 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
/* Configure the termios structure */
cp210x_get_termios(tty, port);
- /* The baud rate must be initialised on cp2104 */
- if (tty)
+ if (tty) {
+ /* The baud rate must be initialised on cp2104 */
cp210x_change_speed(tty, port, NULL);
+ if (I_INPCK(tty))
+ cp210x_enable_event_mode(port);
+ }
+
result = usb_serial_generic_open(tty, port);
if (result)
goto err_disable;
@@ -832,18 +862,128 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
err_disable:
cp210x_write_u16_reg(port, CP210X_IFC_ENABLE, UART_DISABLE);
+ port_priv->event_mode = false;
return result;
}
static void cp210x_close(struct usb_serial_port *port)
{
+ struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
+
usb_serial_generic_close(port);
/* Clear both queues; cp2108 needs this to avoid an occasional hang */
cp210x_write_u16_reg(port, CP210X_PURGE, PURGE_ALL);
cp210x_write_u16_reg(port, CP210X_IFC_ENABLE, UART_DISABLE);
+
+ /* Disabling the interface disables event-insertion mode. */
+ port_priv->event_mode = false;
+}
+
+static void cp210x_process_lsr(struct usb_serial_port *port, unsigned char lsr, char *flag)
+{
+ if (lsr & CP210X_LSR_BREAK) {
+ port->icount.brk++;
+ *flag = TTY_BREAK;
+ } else if (lsr & CP210X_LSR_PARITY) {
+ port->icount.parity++;
+ *flag = TTY_PARITY;
+ } else if (lsr & CP210X_LSR_FRAME) {
+ port->icount.frame++;
+ *flag = TTY_FRAME;
+ }
+
+ if (lsr & CP210X_LSR_OVERRUN) {
+ port->icount.overrun++;
+ tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
+ }
+}
+
+static bool cp210x_process_char(struct usb_serial_port *port, unsigned char *ch, char *flag)
+{
+ struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
+
+ switch (port_priv->event_state) {
+ case ES_DATA:
+ if (*ch == CP210X_ESCCHAR) {
+ port_priv->event_state = ES_ESCAPE;
+ break;
+ }
+ return false;
+ case ES_ESCAPE:
+ switch (*ch) {
+ case 0:
+ dev_dbg(&port->dev, "%s - escape char\n", __func__);
+ *ch = CP210X_ESCCHAR;
+ port_priv->event_state = ES_DATA;
+ return false;
+ case 1:
+ port_priv->event_state = ES_LSR_DATA_0;
+ break;
+ case 2:
+ port_priv->event_state = ES_LSR;
+ break;
+ case 3:
+ port_priv->event_state = ES_MSR;
+ break;
+ default:
+ dev_err(&port->dev, "malformed event 0x%02x\n", *ch);
+ port_priv->event_state = ES_DATA;
+ break;
+ }
+ break;
+ case ES_LSR_DATA_0:
+ port_priv->lsr = *ch;
+ port_priv->event_state = ES_LSR_DATA_1;
+ break;
+ case ES_LSR_DATA_1:
+ dev_dbg(&port->dev, "%s - lsr = 0x%02x, data = 0x%02x\n",
+ __func__, port_priv->lsr, *ch);
+ cp210x_process_lsr(port, port_priv->lsr, flag);
+ port_priv->event_state = ES_DATA;
+ return false;
+ case ES_LSR:
+ dev_dbg(&port->dev, "%s - lsr = 0x%02x\n", __func__, *ch);
+ port_priv->lsr = *ch;
+ cp210x_process_lsr(port, port_priv->lsr, flag);
+ port_priv->event_state = ES_DATA;
+ break;
+ case ES_MSR:
+ dev_dbg(&port->dev, "%s - msr = 0x%02x\n", __func__, *ch);
+ /* unimplemented */
+ port_priv->event_state = ES_DATA;
+ break;
+ }
+
+ return true;
+}
+
+static void cp210x_process_read_urb(struct urb *urb)
+{
+ struct usb_serial_port *port = urb->context;
+ struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
+ unsigned char *ch = urb->transfer_buffer;
+ char flag;
+ int i;
+
+ if (!urb->actual_length)
+ return;
+
+ if (port_priv->event_mode) {
+ for (i = 0; i < urb->actual_length; i++, ch++) {
+ flag = TTY_NORMAL;
+
+ if (cp210x_process_char(port, ch, &flag))
+ continue;
+
+ tty_insert_flip_char(&port->port, *ch, flag);
+ }
+ } else {
+ tty_insert_flip_string(&port->port, ch, urb->actual_length);
+ }
+ tty_flip_buffer_push(&port->port);
}
/*
@@ -1176,6 +1316,41 @@ static void cp210x_change_speed(struct tty_struct *tty,
tty_encode_baud_rate(tty, baud, baud);
}
+static void cp210x_enable_event_mode(struct usb_serial_port *port)
+{
+ struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
+ int ret;
+
+ if (port_priv->event_mode)
+ return;
+
+ port_priv->event_state = ES_DATA;
+ port_priv->event_mode = true;
+
+ ret = cp210x_write_u16_reg(port, CP210X_EMBED_EVENTS, CP210X_ESCCHAR);
+ if (ret) {
+ dev_err(&port->dev, "failed to enable events: %d\n", ret);
+ port_priv->event_mode = false;
+ }
+}
+
+static void cp210x_disable_event_mode(struct usb_serial_port *port)
+{
+ struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
+ int ret;
+
+ if (!port_priv->event_mode)
+ return;
+
+ ret = cp210x_write_u16_reg(port, CP210X_EMBED_EVENTS, 0);
+ if (ret) {
+ dev_err(&port->dev, "failed to disable events: %d\n", ret);
+ return;
+ }
+
+ port_priv->event_mode = false;
+}
+
static void cp210x_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
@@ -1298,6 +1473,14 @@ static void cp210x_set_termios(struct tty_struct *tty,
sizeof(flow_ctl));
}
+ /*
+ * Enable event-insertion mode only if input parity checking is
+ * enabled for now.
+ */
+ if (I_INPCK(tty))
+ cp210x_enable_event_mode(port);
+ else
+ cp210x_disable_event_mode(port);
}
static int cp210x_tiocmset(struct tty_struct *tty,
--
2.26.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/5] USB: serial: cp210x: add support for TIOCGICOUNT
2020-07-13 10:55 [PATCH 0/5] USB: serial: cp210x: add support for line-status events Johan Hovold
2020-07-13 10:55 ` [PATCH 1/5] USB: serial: cp210x: disable interface on errors in open Johan Hovold
2020-07-13 10:55 ` [PATCH 2/5] USB: serial: cp210x: add support for line-status events Johan Hovold
@ 2020-07-13 10:55 ` Johan Hovold
2020-07-13 10:55 ` [PATCH 4/5] USB: serial: cp210x: drop unnecessary packed attributes Johan Hovold
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Johan Hovold @ 2020-07-13 10:55 UTC (permalink / raw)
To: linux-usb; +Cc: Jaromír Škorpil, Johan Hovold
Enable TIOCGICOUNT to allow reading out the (unused) interrupt counters
and error statistics.
Note that modem-status events are currently left unimplemented as they
appear to be buffered on at least CP2102 and therefore cannot be used to
implement TIOCMIWAIT.
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/usb/serial/cp210x.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 02e4acb2823b..3a65be4a0ec0 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -291,6 +291,7 @@ static struct usb_serial_driver cp210x_device = {
.unthrottle = usb_serial_generic_unthrottle,
.tiocmget = cp210x_tiocmget,
.tiocmset = cp210x_tiocmset,
+ .get_icount = usb_serial_generic_get_icount,
.attach = cp210x_attach,
.disconnect = cp210x_disconnect,
.release = cp210x_release,
--
2.26.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/5] USB: serial: cp210x: drop unnecessary packed attributes
2020-07-13 10:55 [PATCH 0/5] USB: serial: cp210x: add support for line-status events Johan Hovold
` (2 preceding siblings ...)
2020-07-13 10:55 ` [PATCH 3/5] USB: serial: cp210x: add support for TIOCGICOUNT Johan Hovold
@ 2020-07-13 10:55 ` Johan Hovold
2020-07-13 10:55 ` [PATCH 5/5] USB: serial: cp210x: use in-kernel types in port data Johan Hovold
2020-07-13 13:41 ` [PATCH 0/5] USB: serial: cp210x: add support for line-status events Greg KH
5 siblings, 0 replies; 8+ messages in thread
From: Johan Hovold @ 2020-07-13 10:55 UTC (permalink / raw)
To: linux-usb; +Cc: Jaromír Škorpil, Johan Hovold
Drop unnecessary packed attributes from structs without padding.
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/usb/serial/cp210x.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 3a65be4a0ec0..09445b7a8f64 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -435,7 +435,7 @@ struct cp210x_flow_ctl {
__le32 ulFlowReplace;
__le32 ulXonLimit;
__le32 ulXoffLimit;
-} __packed;
+};
/* cp210x_flow_ctl::ulControlHandshake */
#define CP210X_SERIAL_DTR_MASK GENMASK(1, 0)
@@ -469,7 +469,7 @@ struct cp210x_flow_ctl {
struct cp210x_pin_mode {
u8 eci;
u8 sci;
-} __packed;
+};
#define CP210X_PIN_MODE_MODEM 0
#define CP210X_PIN_MODE_GPIO BIT(0)
@@ -532,7 +532,7 @@ struct cp210x_single_port_config {
struct cp210x_gpio_write {
u8 mask;
u8 state;
-} __packed;
+};
/*
* Helper to get interface number when we only have struct usb_serial.
--
2.26.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 5/5] USB: serial: cp210x: use in-kernel types in port data
2020-07-13 10:55 [PATCH 0/5] USB: serial: cp210x: add support for line-status events Johan Hovold
` (3 preceding siblings ...)
2020-07-13 10:55 ` [PATCH 4/5] USB: serial: cp210x: drop unnecessary packed attributes Johan Hovold
@ 2020-07-13 10:55 ` Johan Hovold
2020-07-13 13:41 ` [PATCH 0/5] USB: serial: cp210x: add support for line-status events Greg KH
5 siblings, 0 replies; 8+ messages in thread
From: Johan Hovold @ 2020-07-13 10:55 UTC (permalink / raw)
To: linux-usb; +Cc: Jaromír Škorpil, Johan Hovold
The port data is not exported to user space so use the in-kernel u8
type.
Signed-off-by: Johan Hovold <johan@kernel.org>
---
drivers/usb/serial/cp210x.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 09445b7a8f64..d0c05aa8a0d6 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -266,7 +266,7 @@ enum cp210x_event_state {
};
struct cp210x_port_private {
- __u8 bInterfaceNumber;
+ u8 bInterfaceNumber;
bool has_swapped_line_ctl;
bool event_mode;
enum cp210x_event_state event_state;
--
2.26.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 0/5] USB: serial: cp210x: add support for line-status events
2020-07-13 10:55 [PATCH 0/5] USB: serial: cp210x: add support for line-status events Johan Hovold
` (4 preceding siblings ...)
2020-07-13 10:55 ` [PATCH 5/5] USB: serial: cp210x: use in-kernel types in port data Johan Hovold
@ 2020-07-13 13:41 ` Greg KH
2020-07-14 9:55 ` Johan Hovold
5 siblings, 1 reply; 8+ messages in thread
From: Greg KH @ 2020-07-13 13:41 UTC (permalink / raw)
To: Johan Hovold; +Cc: linux-usb, Jaromír Škorpil
On Mon, Jul 13, 2020 at 12:55:12PM +0200, Johan Hovold wrote:
> This series add supports for line-status events that specifically can be
> used to detect parity errors.
>
> The implementation relies on the device's event-insertion mode, which
> can also be used to detect line-breaks and modem status changes. But as
> this doesn't seem to work as expected on CP2102, support has been left
> unimplemented for now.
>
> Included are also a couple of cleanups.
>
> Johan
>
> Changes since RFC [1]:
> - drop sysrq support which relies on break detection
> - use 0xec (instead of 0xff) as escape character
>
> [1] https://lore.kernel.org/r/20200703150104.GE3453@localhost
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/5] USB: serial: cp210x: add support for line-status events
2020-07-13 13:41 ` [PATCH 0/5] USB: serial: cp210x: add support for line-status events Greg KH
@ 2020-07-14 9:55 ` Johan Hovold
0 siblings, 0 replies; 8+ messages in thread
From: Johan Hovold @ 2020-07-14 9:55 UTC (permalink / raw)
To: Greg KH; +Cc: Johan Hovold, linux-usb, Jaromír Škorpil
On Mon, Jul 13, 2020 at 03:41:29PM +0200, Greg Kroah-Hartman wrote:
> On Mon, Jul 13, 2020 at 12:55:12PM +0200, Johan Hovold wrote:
> > This series add supports for line-status events that specifically can be
> > used to detect parity errors.
> >
> > The implementation relies on the device's event-insertion mode, which
> > can also be used to detect line-breaks and modem status changes. But as
> > this doesn't seem to work as expected on CP2102, support has been left
> > unimplemented for now.
> >
> > Included are also a couple of cleanups.
> >
> > Johan
> >
> > Changes since RFC [1]:
> > - drop sysrq support which relies on break detection
> > - use 0xec (instead of 0xff) as escape character
> >
> > [1] https://lore.kernel.org/r/20200703150104.GE3453@localhost
>
>
> Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Thanks. Now applied.
Johan
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2020-07-14 9:55 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-13 10:55 [PATCH 0/5] USB: serial: cp210x: add support for line-status events Johan Hovold
2020-07-13 10:55 ` [PATCH 1/5] USB: serial: cp210x: disable interface on errors in open Johan Hovold
2020-07-13 10:55 ` [PATCH 2/5] USB: serial: cp210x: add support for line-status events Johan Hovold
2020-07-13 10:55 ` [PATCH 3/5] USB: serial: cp210x: add support for TIOCGICOUNT Johan Hovold
2020-07-13 10:55 ` [PATCH 4/5] USB: serial: cp210x: drop unnecessary packed attributes Johan Hovold
2020-07-13 10:55 ` [PATCH 5/5] USB: serial: cp210x: use in-kernel types in port data Johan Hovold
2020-07-13 13:41 ` [PATCH 0/5] USB: serial: cp210x: add support for line-status events Greg KH
2020-07-14 9:55 ` Johan Hovold
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.