Skip to content

Commit 687f9ad

Browse files
dstarke-siemensgregkh
authored andcommitted
tty: n_gsm: fix wrong modem processing in convergence layer type 2
The function gsm_process_modem() exists to handle modem status bits of incoming frames. This includes incoming MSC (modem status command) frames and convergence layer type 2 data frames. The function, however, was only designed to handle MSC frames as it expects the command length. Within gsm_dlci_data() it is wrongly assumed that this is the same as the data frame length. This is only true if the data frame contains only 1 byte of payload. This patch names the length parameter of gsm_process_modem() in a generic manner to reflect its association. It also corrects all calls to the function to handle the variable number of modem status octets correctly in both cases. Fixes: 7263287 ("tty: n_gsm: Fixed logic to decode break signal from modem status") Cc: stable@vger.kernel.org Signed-off-by: Daniel Starke <daniel.starke@siemens.com> Link: https://lore.kernel.org/r/20220218073123.2121-6-daniel.starke@siemens.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent c19d935 commit 687f9ad

1 file changed

Lines changed: 14 additions & 9 deletions

File tree

drivers/tty/n_gsm.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,25 +1021,25 @@ static void gsm_control_reply(struct gsm_mux *gsm, int cmd, const u8 *data,
10211021
* @tty: virtual tty bound to the DLCI
10221022
* @dlci: DLCI to affect
10231023
* @modem: modem bits (full EA)
1024-
* @clen: command length
1024+
* @slen: number of signal octets
10251025
*
10261026
* Used when a modem control message or line state inline in adaption
10271027
* layer 2 is processed. Sort out the local modem state and throttles
10281028
*/
10291029

10301030
static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci,
1031-
u32 modem, int clen)
1031+
u32 modem, int slen)
10321032
{
10331033
int mlines = 0;
10341034
u8 brk = 0;
10351035
int fc;
10361036

1037-
/* The modem status command can either contain one octet (v.24 signals)
1038-
or two octets (v.24 signals + break signals). The length field will
1039-
either be 2 or 3 respectively. This is specified in section
1040-
5.4.6.3.7 of the 27.010 mux spec. */
1037+
/* The modem status command can either contain one octet (V.24 signals)
1038+
* or two octets (V.24 signals + break signals). This is specified in
1039+
* section 5.4.6.3.7 of the 07.10 mux spec.
1040+
*/
10411041

1042-
if (clen == 2)
1042+
if (slen == 1)
10431043
modem = modem & 0x7f;
10441044
else {
10451045
brk = modem & 0x7f;
@@ -1096,6 +1096,7 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen)
10961096
unsigned int brk = 0;
10971097
struct gsm_dlci *dlci;
10981098
int len = clen;
1099+
int slen;
10991100
const u8 *dp = data;
11001101
struct tty_struct *tty;
11011102

@@ -1115,6 +1116,7 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen)
11151116
return;
11161117
dlci = gsm->dlci[addr];
11171118

1119+
slen = len;
11181120
while (gsm_read_ea(&modem, *dp++) == 0) {
11191121
len--;
11201122
if (len == 0)
@@ -1131,7 +1133,7 @@ static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen)
11311133
modem |= (brk & 0x7f);
11321134
}
11331135
tty = tty_port_tty_get(&dlci->port);
1134-
gsm_process_modem(tty, dlci, modem, clen);
1136+
gsm_process_modem(tty, dlci, modem, slen);
11351137
if (tty) {
11361138
tty_wakeup(tty);
11371139
tty_kref_put(tty);
@@ -1597,6 +1599,7 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, const u8 *data, int clen)
15971599
struct tty_struct *tty;
15981600
unsigned int modem = 0;
15991601
int len = clen;
1602+
int slen = 0;
16001603

16011604
if (debug & 16)
16021605
pr_debug("%d bytes for tty\n", len);
@@ -1609,12 +1612,14 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, const u8 *data, int clen)
16091612
case 2: /* Asynchronous serial with line state in each frame */
16101613
while (gsm_read_ea(&modem, *data++) == 0) {
16111614
len--;
1615+
slen++;
16121616
if (len == 0)
16131617
return;
16141618
}
1619+
slen++;
16151620
tty = tty_port_tty_get(port);
16161621
if (tty) {
1617-
gsm_process_modem(tty, dlci, modem, clen);
1622+
gsm_process_modem(tty, dlci, modem, slen);
16181623
tty_kref_put(tty);
16191624
}
16201625
fallthrough;

0 commit comments

Comments
 (0)