Skip to content

Commit e09525a

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 c8d9103 commit e09525a

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
@@ -142,10 +142,11 @@ struct modem_cmux {
142142

143143
/* State */
144144
enum modem_cmux_state state;
145-
bool flow_control_on;
145+
bool flow_control_on : 1;
146+
bool initiator : 1;
146147

147148
/* Work lock */
148-
bool attached;
149+
bool attached : 1;
149150
struct k_spinlock work_lock;
150151

151152
/* Receive state*/

subsys/modem/modem_cmux.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -460,12 +460,13 @@ static void modem_cmux_on_cld_command(struct modem_cmux *cmux, struct modem_cmux
460460
static void modem_cmux_on_control_frame_ua(struct modem_cmux *cmux)
461461
{
462462
if (cmux->state != MODEM_CMUX_STATE_CONNECTING) {
463-
LOG_DBG("Unexpected UA frame");
463+
LOG_DBG("Unexpected UA frame in state %d", cmux->state);
464464
return;
465465
}
466466

467467
LOG_DBG("CMUX connected");
468468
cmux->state = MODEM_CMUX_STATE_CONNECTED;
469+
cmux->initiator = true;
469470
k_mutex_lock(&cmux->transmit_rb_lock, K_FOREVER);
470471
cmux->flow_control_on = true;
471472
k_mutex_unlock(&cmux->transmit_rb_lock);
@@ -536,16 +537,16 @@ static void modem_cmux_connect_response_transmit(struct modem_cmux *cmux)
536537

537538
static void modem_cmux_on_control_frame_sabm(struct modem_cmux *cmux)
538539
{
539-
modem_cmux_connect_response_transmit(cmux);
540-
541540
if ((cmux->state == MODEM_CMUX_STATE_CONNECTED) ||
542541
(cmux->state == MODEM_CMUX_STATE_DISCONNECTING)) {
543542
LOG_DBG("Connect request not accepted");
544543
return;
545544
}
546545

547546
LOG_DBG("CMUX connection request received");
547+
cmux->initiator = false;
548548
cmux->state = MODEM_CMUX_STATE_CONNECTED;
549+
modem_cmux_connect_response_transmit(cmux);
549550
k_mutex_lock(&cmux->transmit_rb_lock, K_FOREVER);
550551
cmux->flow_control_on = true;
551552
k_mutex_unlock(&cmux->transmit_rb_lock);
@@ -558,6 +559,11 @@ static void modem_cmux_on_control_frame(struct modem_cmux *cmux)
558559
{
559560
modem_cmux_log_received_frame(&cmux->frame);
560561

562+
if (cmux->state == MODEM_CMUX_STATE_CONNECTED && cmux->frame.cr == cmux->initiator) {
563+
LOG_DBG("Received a response frame, dropping");
564+
return;
565+
}
566+
561567
switch (cmux->frame.type) {
562568
case MODEM_CMUX_FRAME_TYPE_UA:
563569
modem_cmux_on_control_frame_ua(cmux);
@@ -595,6 +601,12 @@ static struct modem_cmux_dlci *modem_cmux_find_dlci(struct modem_cmux *cmux)
595601

596602
static void modem_cmux_on_dlci_frame_ua(struct modem_cmux_dlci *dlci)
597603
{
604+
/* Drop invalid UA frames */
605+
if (dlci->cmux->frame.cr != dlci->cmux->initiator) {
606+
LOG_DBG("Received a response frame, dropping");
607+
return;
608+
}
609+
598610
switch (dlci->state) {
599611
case MODEM_CMUX_DLCI_STATE_OPENING:
600612
LOG_DBG("DLCI %u opened", dlci->dlci_address);
@@ -680,6 +692,11 @@ static void modem_cmux_on_dlci_frame(struct modem_cmux *cmux)
680692

681693
modem_cmux_log_received_frame(&cmux->frame);
682694

695+
if (cmux->state != MODEM_CMUX_STATE_CONNECTED) {
696+
LOG_DBG("Unexpected DLCI frame in state %d", cmux->state);
697+
return;
698+
}
699+
683700
dlci = modem_cmux_find_dlci(cmux);
684701
if (dlci == NULL) {
685702
LOG_WRN("Ignoring frame intended for unconfigured DLCI %u.",
@@ -1018,6 +1035,7 @@ static void modem_cmux_connect_handler(struct k_work *item)
10181035
cmux = CONTAINER_OF(dwork, struct modem_cmux, connect_work);
10191036

10201037
cmux->state = MODEM_CMUX_STATE_CONNECTING;
1038+
cmux->initiator = true;
10211039

10221040
static const struct modem_cmux_frame frame = {
10231041
.dlci_address = 0,
@@ -1050,7 +1068,7 @@ static void modem_cmux_disconnect_handler(struct k_work *item)
10501068

10511069
struct modem_cmux_frame frame = {
10521070
.dlci_address = 0,
1053-
.cr = true,
1071+
.cr = cmux->initiator,
10541072
.pf = false,
10551073
.type = MODEM_CMUX_FRAME_TYPE_UIH,
10561074
.data = data,
@@ -1129,7 +1147,7 @@ static int modem_cmux_dlci_pipe_api_transmit(void *data, const uint8_t *buf, siz
11291147

11301148
struct modem_cmux_frame frame = {
11311149
.dlci_address = dlci->dlci_address,
1132-
.cr = true,
1150+
.cr = cmux->initiator,
11331151
.pf = false,
11341152
.type = MODEM_CMUX_FRAME_TYPE_UIH,
11351153
.data = buf,
@@ -1204,7 +1222,7 @@ static void modem_cmux_dlci_open_handler(struct k_work *item)
12041222

12051223
struct modem_cmux_frame frame = {
12061224
.dlci_address = dlci->dlci_address,
1207-
.cr = true,
1225+
.cr = dlci->cmux->initiator,
12081226
.pf = true,
12091227
.type = MODEM_CMUX_FRAME_TYPE_SABM,
12101228
.data = NULL,
@@ -1233,7 +1251,7 @@ static void modem_cmux_dlci_close_handler(struct k_work *item)
12331251

12341252
struct modem_cmux_frame frame = {
12351253
.dlci_address = dlci->dlci_address,
1236-
.cr = true,
1254+
.cr = dlci->cmux->initiator,
12371255
.pf = true,
12381256
.type = MODEM_CMUX_FRAME_TYPE_DISC,
12391257
.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)