mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
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:
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user