Skip to content

Commit 105952e

Browse files
committed
modem: cmux: Handle C/R bit from address field
The C/R bit in the address field should be handled as explained in 5.2.1.2 in the spec (3GPP TS 127.010). To detect if the frame is a command or a response, we need to know who was the initiator of the CMUX channel. > Initiator is the station that take the initiative to initialize > the multiplexer (i.e. sends the SABM command at DLCI 0 ) See the table from given section of the specification. Also, on UIH frames 5.4.3.1 says > The frames sent by the initiating station have the C/R bit set to 1 > and those sent by the responding station have the C/R bit set to 0. NOTE: This is different than a C/R bit in the Type field. Signed-off-by: Seppo Takalo <[email protected]>
1 parent 376ca57 commit 105952e

File tree

4 files changed

+30
-9
lines changed

4 files changed

+30
-9
lines changed

include/zephyr/modem/cmux.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,11 @@ struct modem_cmux {
139139

140140
/* State */
141141
enum modem_cmux_state state;
142-
bool flow_control_on;
142+
bool flow_control_on : 1;
143+
bool initiator : 1;
143144

144145
/* Work lock */
145-
bool attached;
146+
bool attached : 1;
146147
struct k_spinlock work_lock;
147148

148149
/* Receive state*/

subsys/modem/modem_cmux.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -451,11 +451,12 @@ static void modem_cmux_on_cld_command(struct modem_cmux *cmux, struct modem_cmux
451451
static void modem_cmux_on_control_frame_ua(struct modem_cmux *cmux)
452452
{
453453
if (cmux->state != MODEM_CMUX_STATE_CONNECTING) {
454-
LOG_DBG("Unexpected UA frame");
454+
LOG_DBG("Unexpected UA frame in state %d", cmux->state);
455455
return;
456456
}
457457

458458
cmux->state = MODEM_CMUX_STATE_CONNECTED;
459+
cmux->initiator = true;
459460
k_mutex_lock(&cmux->transmit_rb_lock, K_FOREVER);
460461
cmux->flow_control_on = true;
461462
k_mutex_unlock(&cmux->transmit_rb_lock);
@@ -526,15 +527,15 @@ static void modem_cmux_connect_response_transmit(struct modem_cmux *cmux)
526527

527528
static void modem_cmux_on_control_frame_sabm(struct modem_cmux *cmux)
528529
{
529-
modem_cmux_connect_response_transmit(cmux);
530-
531530
if ((cmux->state == MODEM_CMUX_STATE_CONNECTED) ||
532531
(cmux->state == MODEM_CMUX_STATE_DISCONNECTING)) {
533532
LOG_DBG("Connect request not accepted");
534533
return;
535534
}
536535

536+
cmux->initiator = false;
537537
cmux->state = MODEM_CMUX_STATE_CONNECTED;
538+
modem_cmux_connect_response_transmit(cmux);
538539
k_mutex_lock(&cmux->transmit_rb_lock, K_FOREVER);
539540
cmux->flow_control_on = true;
540541
k_mutex_unlock(&cmux->transmit_rb_lock);
@@ -547,6 +548,11 @@ static void modem_cmux_on_control_frame(struct modem_cmux *cmux)
547548
{
548549
modem_cmux_log_received_frame(&cmux->frame);
549550

551+
if (cmux->state == MODEM_CMUX_STATE_CONNECTED && cmux->frame.cr == cmux->initiator) {
552+
LOG_DBG("Received a response frame, dropping");
553+
return;
554+
}
555+
550556
switch (cmux->frame.type) {
551557
case MODEM_CMUX_FRAME_TYPE_UA:
552558
modem_cmux_on_control_frame_ua(cmux);
@@ -584,6 +590,12 @@ static struct modem_cmux_dlci *modem_cmux_find_dlci(struct modem_cmux *cmux)
584590

585591
static void modem_cmux_on_dlci_frame_ua(struct modem_cmux_dlci *dlci)
586592
{
593+
/* Drop invalid UA frames */
594+
if (dlci->cmux->frame.cr != dlci->cmux->initiator) {
595+
LOG_DBG("Received a response frame, dropping");
596+
return;
597+
}
598+
587599
switch (dlci->state) {
588600
case MODEM_CMUX_DLCI_STATE_OPENING:
589601
dlci->state = MODEM_CMUX_DLCI_STATE_OPEN;
@@ -665,6 +677,11 @@ static void modem_cmux_on_dlci_frame(struct modem_cmux *cmux)
665677

666678
modem_cmux_log_received_frame(&cmux->frame);
667679

680+
if (cmux->state != MODEM_CMUX_STATE_CONNECTED) {
681+
LOG_DBG("Unexpected DLCI frame in state %d", cmux->state);
682+
return;
683+
}
684+
668685
dlci = modem_cmux_find_dlci(cmux);
669686
if (dlci == NULL) {
670687
LOG_WRN("Ignoring frame intended for unconfigured DLCI %u.",
@@ -1007,6 +1024,7 @@ static void modem_cmux_connect_handler(struct k_work *item)
10071024
cmux = CONTAINER_OF(dwork, struct modem_cmux, connect_work);
10081025

10091026
cmux->state = MODEM_CMUX_STATE_CONNECTING;
1027+
cmux->initiator = true;
10101028

10111029
static const struct modem_cmux_frame frame = {
10121030
.dlci_address = 0,
@@ -1039,7 +1057,7 @@ static void modem_cmux_disconnect_handler(struct k_work *item)
10391057

10401058
struct modem_cmux_frame frame = {
10411059
.dlci_address = 0,
1042-
.cr = true,
1060+
.cr = cmux->initiator,
10431061
.pf = false,
10441062
.type = MODEM_CMUX_FRAME_TYPE_UIH,
10451063
.data = data,
@@ -1118,7 +1136,7 @@ static int modem_cmux_dlci_pipe_api_transmit(void *data, const uint8_t *buf, siz
11181136

11191137
struct modem_cmux_frame frame = {
11201138
.dlci_address = dlci->dlci_address,
1121-
.cr = true,
1139+
.cr = cmux->initiator,
11221140
.pf = false,
11231141
.type = MODEM_CMUX_FRAME_TYPE_UIH,
11241142
.data = buf,
@@ -1193,7 +1211,7 @@ static void modem_cmux_dlci_open_handler(struct k_work *item)
11931211

11941212
struct modem_cmux_frame frame = {
11951213
.dlci_address = dlci->dlci_address,
1196-
.cr = true,
1214+
.cr = dlci->cmux->initiator,
11971215
.pf = true,
11981216
.type = MODEM_CMUX_FRAME_TYPE_SABM,
11991217
.data = NULL,
@@ -1222,7 +1240,7 @@ static void modem_cmux_dlci_close_handler(struct k_work *item)
12221240

12231241
struct modem_cmux_frame frame = {
12241242
.dlci_address = dlci->dlci_address,
1225-
.cr = true,
1243+
.cr = dlci->cmux->initiator,
12261244
.pf = true,
12271245
.type = MODEM_CMUX_FRAME_TYPE_DISC,
12281246
.data = NULL,

tests/subsys/modem/modem_cmux/prj.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ CONFIG_MODEM_CMUX=y
88
CONFIG_MODEM_CMUX_MTU=64
99

1010
CONFIG_ZTEST=y
11+
CONFIG_MODEM_CMUX_LOG_LEVEL_DBG=y

tests/subsys/modem/modem_cmux_pair/prj.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ CONFIG_MODEM_CMUX=y
88
CONFIG_MODEM_CMUX_MTU=64
99

1010
CONFIG_ZTEST=y
11+
CONFIG_MODEM_CMUX_LOG_LEVEL_DBG=y

0 commit comments

Comments
 (0)