Skip to content

Commit 9de7d61

Browse files
SeppoTakalojhedberg
authored andcommitted
modem: cmux: Implement DM and NSC responses
Implement following responses from 3GPP TS 27.010: 5.4.6.3.8 Non Supported Command Response (NSC) 5.3.3 Disconnected Mode (DM) response Close DLC when receiving DM response. Signed-off-by: Seppo Takalo <[email protected]>
1 parent f5dddbf commit 9de7d61

File tree

1 file changed

+73
-6
lines changed

1 file changed

+73
-6
lines changed

subsys/modem/modem_cmux.c

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ static bool modem_cmux_transmit_cmd_frame(struct modem_cmux *cmux,
338338

339339
if (space < MODEM_CMUX_CMD_FRAME_SIZE_MAX) {
340340
k_mutex_unlock(&cmux->transmit_rb_lock);
341+
LOG_WRN("CMD buffer overflow");
341342
return false;
342343
}
343344

@@ -475,6 +476,41 @@ static void modem_cmux_on_control_frame_ua(struct modem_cmux *cmux)
475476
k_event_post(&cmux->event, MODEM_CMUX_EVENT_CONNECTED_BIT);
476477
}
477478

479+
static void modem_cmux_respond_unsupported_cmd(struct modem_cmux *cmux)
480+
{
481+
struct modem_cmux_frame frame = cmux->frame;
482+
struct modem_cmux_command *cmd;
483+
484+
if (modem_cmux_wrap_command(&cmd, frame.data, frame.data_len) < 0) {
485+
LOG_WRN("Invalid command");
486+
return;
487+
}
488+
489+
struct {
490+
/* 3GPP TS 27.010: 5.4.6.3.8 Non Supported Command Response (NSC) */
491+
struct modem_cmux_command nsc;
492+
struct modem_cmux_command_type value;
493+
} nsc_cmd = {
494+
.nsc = {
495+
.type = {
496+
.ea = 1,
497+
.cr = 0,
498+
.value = MODEM_CMUX_COMMAND_NSC,
499+
},
500+
.length = {
501+
.ea = 1,
502+
.value = 1,
503+
},
504+
},
505+
.value = cmd->type,
506+
};
507+
508+
frame.data = (uint8_t *)&nsc_cmd;
509+
frame.data_len = sizeof(nsc_cmd);
510+
511+
modem_cmux_transmit_cmd_frame(cmux, &frame);
512+
}
513+
478514
static void modem_cmux_on_control_frame_uih(struct modem_cmux *cmux)
479515
{
480516
struct modem_cmux_command *command;
@@ -511,6 +547,7 @@ static void modem_cmux_on_control_frame_uih(struct modem_cmux *cmux)
511547

512548
default:
513549
LOG_DBG("Unknown control command");
550+
modem_cmux_respond_unsupported_cmd(cmux);
514551
break;
515552
}
516553
}
@@ -534,6 +571,26 @@ static void modem_cmux_connect_response_transmit(struct modem_cmux *cmux)
534571
modem_cmux_transmit_cmd_frame(cmux, &frame);
535572
}
536573

574+
static void modem_cmux_dm_response_transmit(struct modem_cmux *cmux)
575+
{
576+
if (cmux == NULL) {
577+
return;
578+
}
579+
580+
/* 3GPP TS 27.010: 5.3.3 Disconnected Mode (DM) response */
581+
struct modem_cmux_frame frame = {
582+
.dlci_address = cmux->frame.dlci_address,
583+
.cr = cmux->frame.cr,
584+
.pf = 1,
585+
.type = MODEM_CMUX_FRAME_TYPE_DM,
586+
.data = NULL,
587+
.data_len = 0,
588+
};
589+
590+
LOG_DBG("Send DM response");
591+
modem_cmux_transmit_cmd_frame(cmux, &frame);
592+
}
593+
537594
static void modem_cmux_on_control_frame_sabm(struct modem_cmux *cmux)
538595
{
539596
modem_cmux_connect_response_transmit(cmux);
@@ -593,6 +650,13 @@ static struct modem_cmux_dlci *modem_cmux_find_dlci(struct modem_cmux *cmux)
593650
return NULL;
594651
}
595652

653+
static void modem_cmux_on_dlci_frame_dm(struct modem_cmux_dlci *dlci)
654+
{
655+
dlci->state = MODEM_CMUX_DLCI_STATE_CLOSED;
656+
modem_pipe_notify_closed(&dlci->pipe);
657+
k_work_cancel_delayable(&dlci->close_work);
658+
}
659+
596660
static void modem_cmux_on_dlci_frame_ua(struct modem_cmux_dlci *dlci)
597661
{
598662
switch (dlci->state) {
@@ -608,9 +672,7 @@ static void modem_cmux_on_dlci_frame_ua(struct modem_cmux_dlci *dlci)
608672

609673
case MODEM_CMUX_DLCI_STATE_CLOSING:
610674
LOG_DBG("DLCI %u closed", dlci->dlci_address);
611-
dlci->state = MODEM_CMUX_DLCI_STATE_CLOSED;
612-
modem_pipe_notify_closed(&dlci->pipe);
613-
k_work_cancel_delayable(&dlci->close_work);
675+
modem_cmux_on_dlci_frame_dm(dlci);
614676
break;
615677

616678
default:
@@ -619,6 +681,8 @@ static void modem_cmux_on_dlci_frame_ua(struct modem_cmux_dlci *dlci)
619681
}
620682
}
621683

684+
685+
622686
static void modem_cmux_on_dlci_frame_uih(struct modem_cmux_dlci *dlci)
623687
{
624688
struct modem_cmux *cmux = dlci->cmux;
@@ -665,7 +729,7 @@ static void modem_cmux_on_dlci_frame_disc(struct modem_cmux_dlci *dlci)
665729
modem_cmux_connect_response_transmit(cmux);
666730

667731
if (dlci->state != MODEM_CMUX_DLCI_STATE_OPEN) {
668-
LOG_DBG("Unexpected Disc frame");
732+
modem_cmux_dm_response_transmit(cmux);
669733
return;
670734
}
671735

@@ -682,8 +746,9 @@ static void modem_cmux_on_dlci_frame(struct modem_cmux *cmux)
682746

683747
dlci = modem_cmux_find_dlci(cmux);
684748
if (dlci == NULL) {
685-
LOG_WRN("Ignoring frame intended for unconfigured DLCI %u.",
749+
LOG_WRN("Frame intended for unconfigured DLCI %u.",
686750
cmux->frame.dlci_address);
751+
modem_cmux_dm_response_transmit(cmux);
687752
return;
688753
}
689754

@@ -703,7 +768,9 @@ static void modem_cmux_on_dlci_frame(struct modem_cmux *cmux)
703768
case MODEM_CMUX_FRAME_TYPE_DISC:
704769
modem_cmux_on_dlci_frame_disc(dlci);
705770
break;
706-
771+
case MODEM_CMUX_FRAME_TYPE_DM:
772+
modem_cmux_on_dlci_frame_dm(dlci);
773+
break;
707774
default:
708775
LOG_WRN("Unknown %s frame type (%d, DLCI %d)", "DLCI", cmux->frame.type,
709776
cmux->frame.dlci_address);

0 commit comments

Comments
 (0)