Skip to content

Commit 398867f

Browse files
dstarke-siemensgregkh
authored andcommitted
tty: n_gsm: fix wrong command frame length field encoding
n_gsm is based on the 3GPP 07.010 and its newer version is the 3GPP 27.010. See https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=1516 The changes from 07.010 to 27.010 are non-functional. Therefore, I refer to the newer 27.010 here. Chapter 5.4.6.1 states that each command frame shall be made up from type, length and value. Looking for example in chapter 5.4.6.3.5 at the description for the encoding of a flow control on command it becomes obvious, that the type and length field is always present whereas the value may be zero bytes long. The current implementation omits the length field if the value is not present. This is wrong. Correct this by always sending the length in gsm_control_transmit(). So far only the modem status command (MSC) has included a value and encoded its length directly. Therefore, also change gsmtty_modem_update(). Fixes: e1eaea4 ("tty: n_gsm line discipline") Cc: [email protected] Signed-off-by: Daniel Starke <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent d0bcdff commit 398867f

File tree

1 file changed

+11
-12
lines changed

1 file changed

+11
-12
lines changed

drivers/tty/n_gsm.c

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,11 +1327,12 @@ static void gsm_control_response(struct gsm_mux *gsm, unsigned int command,
13271327

13281328
static void gsm_control_transmit(struct gsm_mux *gsm, struct gsm_control *ctrl)
13291329
{
1330-
struct gsm_msg *msg = gsm_data_alloc(gsm, 0, ctrl->len + 1, gsm->ftype);
1330+
struct gsm_msg *msg = gsm_data_alloc(gsm, 0, ctrl->len + 2, gsm->ftype);
13311331
if (msg == NULL)
13321332
return;
1333-
msg->data[0] = (ctrl->cmd << 1) | 2 | EA; /* command */
1334-
memcpy(msg->data + 1, ctrl->data, ctrl->len);
1333+
msg->data[0] = (ctrl->cmd << 1) | CR | EA; /* command */
1334+
msg->data[1] = (ctrl->len << 1) | EA;
1335+
memcpy(msg->data + 2, ctrl->data, ctrl->len);
13351336
gsm_data_queue(gsm->dlci[0], msg);
13361337
}
13371338

@@ -2957,19 +2958,17 @@ static struct tty_ldisc_ops tty_ldisc_packet = {
29572958

29582959
static int gsmtty_modem_update(struct gsm_dlci *dlci, u8 brk)
29592960
{
2960-
u8 modembits[5];
2961+
u8 modembits[3];
29612962
struct gsm_control *ctrl;
29622963
int len = 2;
29632964

2964-
if (brk)
2965+
modembits[0] = (dlci->addr << 2) | 2 | EA; /* DLCI, Valid, EA */
2966+
modembits[1] = (gsm_encode_modem(dlci) << 1) | EA;
2967+
if (brk) {
2968+
modembits[2] = (brk << 4) | 2 | EA; /* Length, Break, EA */
29652969
len++;
2966-
2967-
modembits[0] = len << 1 | EA; /* Data bytes */
2968-
modembits[1] = dlci->addr << 2 | 3; /* DLCI, EA, 1 */
2969-
modembits[2] = gsm_encode_modem(dlci) << 1 | EA;
2970-
if (brk)
2971-
modembits[3] = brk << 4 | 2 | EA; /* Valid, EA */
2972-
ctrl = gsm_control_send(dlci->gsm, CMD_MSC, modembits, len + 1);
2970+
}
2971+
ctrl = gsm_control_send(dlci->gsm, CMD_MSC, modembits, len);
29732972
if (ctrl == NULL)
29742973
return -ENOMEM;
29752974
return gsm_control_wait(dlci->gsm, ctrl);

0 commit comments

Comments
 (0)