Skip to content

Commit 684ae4f

Browse files
dstarke-siemensgregkh
authored andcommitted
tty: n_gsm: add TIOCMIWAIT support
Add support for the TIOCMIWAIT ioctl on the virtual ttys. This enables the user to wait for virtual modem signals like RING. More work is needed to support also TIOCGICOUNT. Signed-off-by: Daniel Starke <daniel.starke@siemens.com> Link: https://lore.kernel.org/r/20230206114606.2133-4-daniel.starke@siemens.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 42ec0b9 commit 684ae4f

1 file changed

Lines changed: 32 additions & 1 deletion

File tree

drivers/tty/n_gsm.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1536,6 +1536,7 @@ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci,
15361536
if (brk & 0x01)
15371537
tty_insert_flip_char(&dlci->port, 0, TTY_BREAK);
15381538
dlci->modem_rx = mlines;
1539+
wake_up_interruptible(&dlci->gsm->event);
15391540
}
15401541

15411542
/**
@@ -2071,7 +2072,7 @@ static void gsm_dlci_close(struct gsm_dlci *dlci)
20712072
/* A DLCI 0 close is a MUX termination so we need to kick that
20722073
back to userspace somehow */
20732074
gsm_dlci_data_kick(dlci);
2074-
wake_up(&dlci->gsm->event);
2075+
wake_up_all(&dlci->gsm->event);
20752076
}
20762077

20772078
/**
@@ -2272,6 +2273,7 @@ static void gsm_dlci_begin_close(struct gsm_dlci *dlci)
22722273
dlci->state = DLCI_CLOSING;
22732274
gsm_command(dlci->gsm, dlci->addr, DISC|PF);
22742275
mod_timer(&dlci->t1, jiffies + gsm->t1 * HZ / 100);
2276+
wake_up_interruptible(&gsm->event);
22752277
}
22762278

22772279
/**
@@ -3775,6 +3777,33 @@ static int gsm_modem_update(struct gsm_dlci *dlci, u8 brk)
37753777
return -EPROTONOSUPPORT;
37763778
}
37773779

3780+
/**
3781+
* gsm_wait_modem_change - wait for modem status line change
3782+
* @dlci: channel
3783+
* @mask: modem status line bits
3784+
*
3785+
* The function returns if:
3786+
* - any given modem status line bit changed
3787+
* - the wait event function got interrupted (e.g. by a signal)
3788+
* - the underlying DLCI was closed
3789+
* - the underlying ldisc device was removed
3790+
*/
3791+
static int gsm_wait_modem_change(struct gsm_dlci *dlci, u32 mask)
3792+
{
3793+
struct gsm_mux *gsm = dlci->gsm;
3794+
u32 old = dlci->modem_rx;
3795+
int ret;
3796+
3797+
ret = wait_event_interruptible(gsm->event, gsm->dead ||
3798+
dlci->state != DLCI_OPEN ||
3799+
(old ^ dlci->modem_rx) & mask);
3800+
if (gsm->dead)
3801+
return -ENODEV;
3802+
if (dlci->state != DLCI_OPEN)
3803+
return -EL2NSYNC;
3804+
return ret;
3805+
}
3806+
37783807
static bool gsm_carrier_raised(struct tty_port *port)
37793808
{
37803809
struct gsm_dlci *dlci = container_of(port, struct gsm_dlci, port);
@@ -4034,6 +4063,8 @@ static int gsmtty_ioctl(struct tty_struct *tty,
40344063
gsm_destroy_network(dlci);
40354064
mutex_unlock(&dlci->mutex);
40364065
return 0;
4066+
case TIOCMIWAIT:
4067+
return gsm_wait_modem_change(dlci, (u32)arg);
40374068
default:
40384069
return -ENOIOCTLCMD;
40394070
}

0 commit comments

Comments
 (0)