Skip to content

Commit 6d6be1c

Browse files
committed
modem: cmux: Implement DM and NSC responses
Implement Disconnect Mode(DM) and Non-Supported Command(NSC) responses. Close DLC when receiving DM response. Signed-off-by: Seppo Takalo <[email protected]>
1 parent 376ca57 commit 6d6be1c

File tree

1 file changed

+74
-6
lines changed

1 file changed

+74
-6
lines changed

subsys/modem/modem_cmux.c

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,43 @@ static void modem_cmux_on_control_frame_ua(struct modem_cmux *cmux)
465465
k_event_post(&cmux->event, MODEM_CMUX_EVENT_CONNECTED_BIT);
466466
}
467467

468+
static void modem_cmux_respond_unsupported_cmd(struct modem_cmux *cmux)
469+
{
470+
struct modem_cmux_frame frame;
471+
struct modem_cmux_command *cmd;
472+
473+
memcpy(&frame, &cmux->frame, sizeof(cmux->frame));
474+
if (modem_cmux_wrap_command(&cmd, frame.data, frame.data_len) < 0) {
475+
LOG_WRN("Invalid command");
476+
return;
477+
}
478+
479+
struct {
480+
struct modem_cmux_command nsc;
481+
struct modem_cmux_command_type value;
482+
} nsc_cmd = {
483+
.nsc = {
484+
.type = {
485+
.ea = 1,
486+
.cr = 0,
487+
.value = MODEM_CMUX_COMMAND_NSC,
488+
},
489+
.length = {
490+
.ea = 1,
491+
.value = 1,
492+
},
493+
},
494+
.value = cmd->type,
495+
};
496+
497+
frame.data = (uint8_t *)&nsc_cmd;
498+
frame.data_len = sizeof(nsc_cmd);
499+
500+
if (modem_cmux_transmit_cmd_frame(cmux, &frame) == false) {
501+
LOG_WRN("CMD response buffer overflow");
502+
}
503+
}
504+
468505
static void modem_cmux_on_control_frame_uih(struct modem_cmux *cmux)
469506
{
470507
struct modem_cmux_command *command;
@@ -501,6 +538,7 @@ static void modem_cmux_on_control_frame_uih(struct modem_cmux *cmux)
501538

502539
default:
503540
LOG_DBG("Unknown control command");
541+
modem_cmux_respond_unsupported_cmd(cmux);
504542
break;
505543
}
506544
}
@@ -524,6 +562,25 @@ static void modem_cmux_connect_response_transmit(struct modem_cmux *cmux)
524562
modem_cmux_transmit_cmd_frame(cmux, &frame);
525563
}
526564

565+
static void modem_cmux_dm_response_transmit(struct modem_cmux *cmux)
566+
{
567+
if (cmux == NULL) {
568+
return;
569+
}
570+
571+
struct modem_cmux_frame frame = {
572+
.dlci_address = cmux->frame.dlci_address,
573+
.cr = cmux->frame.cr,
574+
.pf = 1,
575+
.type = MODEM_CMUX_FRAME_TYPE_DM,
576+
.data = NULL,
577+
.data_len = 0,
578+
};
579+
580+
LOG_DBG("Send DM response");
581+
modem_cmux_transmit_cmd_frame(cmux, &frame);
582+
}
583+
527584
static void modem_cmux_on_control_frame_sabm(struct modem_cmux *cmux)
528585
{
529586
modem_cmux_connect_response_transmit(cmux);
@@ -582,6 +639,13 @@ static struct modem_cmux_dlci *modem_cmux_find_dlci(struct modem_cmux *cmux)
582639
return NULL;
583640
}
584641

642+
static void modem_cmux_on_dlci_frame_dm(struct modem_cmux_dlci *dlci)
643+
{
644+
dlci->state = MODEM_CMUX_DLCI_STATE_CLOSED;
645+
modem_pipe_notify_closed(&dlci->pipe);
646+
k_work_cancel_delayable(&dlci->close_work);
647+
}
648+
585649
static void modem_cmux_on_dlci_frame_ua(struct modem_cmux_dlci *dlci)
586650
{
587651
switch (dlci->state) {
@@ -595,9 +659,8 @@ static void modem_cmux_on_dlci_frame_ua(struct modem_cmux_dlci *dlci)
595659
break;
596660

597661
case MODEM_CMUX_DLCI_STATE_CLOSING:
598-
dlci->state = MODEM_CMUX_DLCI_STATE_CLOSED;
599-
modem_pipe_notify_closed(&dlci->pipe);
600-
k_work_cancel_delayable(&dlci->close_work);
662+
/* Closing is handled same way in DM or as UA reply to DISC */
663+
modem_cmux_on_dlci_frame_dm(dlci);
601664
break;
602665

603666
default:
@@ -606,6 +669,8 @@ static void modem_cmux_on_dlci_frame_ua(struct modem_cmux_dlci *dlci)
606669
}
607670
}
608671

672+
673+
609674
static void modem_cmux_on_dlci_frame_uih(struct modem_cmux_dlci *dlci)
610675
{
611676
struct modem_cmux *cmux = dlci->cmux;
@@ -651,7 +716,7 @@ static void modem_cmux_on_dlci_frame_disc(struct modem_cmux_dlci *dlci)
651716
modem_cmux_connect_response_transmit(cmux);
652717

653718
if (dlci->state != MODEM_CMUX_DLCI_STATE_OPEN) {
654-
LOG_DBG("Unexpected Disc frame");
719+
modem_cmux_dm_response_transmit(cmux);
655720
return;
656721
}
657722

@@ -667,8 +732,9 @@ static void modem_cmux_on_dlci_frame(struct modem_cmux *cmux)
667732

668733
dlci = modem_cmux_find_dlci(cmux);
669734
if (dlci == NULL) {
670-
LOG_WRN("Ignoring frame intended for unconfigured DLCI %u.",
735+
LOG_WRN("Frame intended for unconfigured DLCI %u.",
671736
cmux->frame.dlci_address);
737+
modem_cmux_dm_response_transmit(cmux);
672738
return;
673739
}
674740

@@ -688,7 +754,9 @@ static void modem_cmux_on_dlci_frame(struct modem_cmux *cmux)
688754
case MODEM_CMUX_FRAME_TYPE_DISC:
689755
modem_cmux_on_dlci_frame_disc(dlci);
690756
break;
691-
757+
case MODEM_CMUX_FRAME_TYPE_DM:
758+
modem_cmux_on_dlci_frame_dm(dlci);
759+
break;
692760
default:
693761
LOG_WRN("Unknown %s frame type", "DLCI");
694762
break;

0 commit comments

Comments
 (0)