gadget: u_serial: Add tiocmset/tiocmget functionality

Change-Id: Iab5d800aaaddb973408cb8f148f76c2c153a373e
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Hertz Wang <wangh@rock-chips.com>
This commit is contained in:
Hertz Wang
2019-07-03 11:59:44 +08:00
committed by Tao Huang
parent 2aea5b0720
commit 9eae80e2fe
2 changed files with 85 additions and 2 deletions

View File

@@ -613,7 +613,8 @@ static void gs_write_complete(struct usb_ep *ep, struct usb_request *req)
/* FALL THROUGH */
case 0:
/* normal completion */
gs_start_tx(port);
if (port->port_usb)
gs_start_tx(port);
break;
case -ESHUTDOWN:
@@ -1012,6 +1013,78 @@ static int gs_break_ctl(struct tty_struct *tty, int duration)
return status;
}
static int gs_tiocmget(struct tty_struct *tty)
{
struct gs_port *port = tty->driver_data;
struct gserial *gser;
unsigned int result = 0;
spin_lock_irq(&port->port_lock);
gser = port->port_usb;
if (!gser) {
result = -ENODEV;
goto fail;
}
if (gser->get_dtr)
result |= (gser->get_dtr(gser) ? TIOCM_DTR : 0);
if (gser->get_rts)
result |= (gser->get_rts(gser) ? TIOCM_RTS : 0);
if (gser->serial_state & TIOCM_CD)
result |= TIOCM_CD;
if (gser->serial_state & TIOCM_RI)
result |= TIOCM_RI;
fail:
spin_unlock_irq(&port->port_lock);
return result;
}
static int gs_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct gs_port *port = tty->driver_data;
struct gserial *gser;
int status = 0;
spin_lock_irq(&port->port_lock);
gser = port->port_usb;
if (!gser) {
status = -ENODEV;
goto fail;
}
if (set & TIOCM_RI) {
if (gser->send_ring_indicator) {
gser->serial_state |= TIOCM_RI;
status = gser->send_ring_indicator(gser, 1);
}
}
if (clear & TIOCM_RI) {
if (gser->send_ring_indicator) {
gser->serial_state &= ~TIOCM_RI;
status = gser->send_ring_indicator(gser, 0);
}
}
if (set & TIOCM_CD) {
if (gser->send_carrier_detect) {
gser->serial_state |= TIOCM_CD;
status = gser->send_carrier_detect(gser, 1);
}
}
if (clear & TIOCM_CD) {
if (gser->send_carrier_detect) {
gser->serial_state &= ~TIOCM_CD;
status = gser->send_carrier_detect(gser, 0);
}
}
fail:
spin_unlock_irq(&port->port_lock);
return status;
}
static const struct tty_operations gs_tty_ops = {
.open = gs_open,
.close = gs_close,
@@ -1022,6 +1095,8 @@ static const struct tty_operations gs_tty_ops = {
.chars_in_buffer = gs_chars_in_buffer,
.unthrottle = gs_unthrottle,
.break_ctl = gs_break_ctl,
.tiocmget = gs_tiocmget,
.tiocmset = gs_tiocmset,
};
/*-------------------------------------------------------------------------*/
@@ -1301,7 +1376,8 @@ static int userial_init(void)
gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV
| TTY_DRIVER_RESET_TERMIOS;
gs_tty_driver->init_termios = tty_std_termios;
/* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on

View File

@@ -45,11 +45,18 @@ struct gserial {
/* REVISIT avoid this CDC-ACM support harder ... */
struct usb_cdc_line_coding port_line_coding; /* 9600-8-N-1 etc */
u16 serial_state;
/* control signal callbacks*/
unsigned int (*get_dtr)(struct gserial *p);
unsigned int (*get_rts)(struct gserial *p);
/* notification callbacks */
void (*connect)(struct gserial *p);
void (*disconnect)(struct gserial *p);
int (*send_break)(struct gserial *p, int duration);
unsigned int (*send_carrier_detect)(struct gserial *p, unsigned int);
unsigned int (*send_ring_indicator)(struct gserial *p, unsigned int);
};
/* utilities to allocate/free request and buffer */