Skip to content

Commit 093efc4

Browse files
Juha Heiskanenfabiobaltieri
authored andcommitted
modem: modem_cmux: Support modem CMUX DCE role
Added missing command and message handling for use existing modem cmux for DCE role. DCE CMUX connection can be now initialized from DTE side. Signed-off-by: Juha Heiskanen <[email protected]>
1 parent 72bb10d commit 093efc4

File tree

1 file changed

+99
-9
lines changed

1 file changed

+99
-9
lines changed

subsys/modem/modem_cmux.c

Lines changed: 99 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -340,9 +340,11 @@ static void modem_cmux_acknowledge_received_frame(struct modem_cmux *cmux)
340340
}
341341
}
342342

343-
static void modem_cmux_on_msc_command(struct modem_cmux *cmux)
343+
static void modem_cmux_on_msc_command(struct modem_cmux *cmux, struct modem_cmux_command *command)
344344
{
345-
modem_cmux_acknowledge_received_frame(cmux);
345+
if (command->type.cr) {
346+
modem_cmux_acknowledge_received_frame(cmux);
347+
}
346348
}
347349

348350
static void modem_cmux_on_fcon_command(struct modem_cmux *cmux)
@@ -361,17 +363,27 @@ static void modem_cmux_on_fcoff_command(struct modem_cmux *cmux)
361363
modem_cmux_acknowledge_received_frame(cmux);
362364
}
363365

364-
static void modem_cmux_on_cld_command(struct modem_cmux *cmux)
366+
static void modem_cmux_on_cld_command(struct modem_cmux *cmux, struct modem_cmux_command *command)
365367
{
366-
if (cmux->state != MODEM_CMUX_STATE_DISCONNECTING) {
368+
if (command->type.cr) {
369+
modem_cmux_acknowledge_received_frame(cmux);
370+
}
371+
372+
if (cmux->state != MODEM_CMUX_STATE_DISCONNECTING &&
373+
cmux->state != MODEM_CMUX_STATE_CONNECTED) {
367374
LOG_WRN("Unexpected close down");
375+
return;
376+
}
377+
378+
if (cmux->state == MODEM_CMUX_STATE_DISCONNECTING) {
379+
k_work_cancel_delayable(&cmux->disconnect_work);
368380
}
369381

370382
cmux->state = MODEM_CMUX_STATE_DISCONNECTED;
371383
k_mutex_lock(&cmux->transmit_rb_lock, K_FOREVER);
372384
cmux->flow_control_on = false;
373385
k_mutex_unlock(&cmux->transmit_rb_lock);
374-
k_work_cancel_delayable(&cmux->disconnect_work);
386+
375387
modem_cmux_raise_event(cmux, MODEM_CMUX_EVENT_DISCONNECTED);
376388
k_event_clear(&cmux->event, MODEM_CMUX_EVENT_CONNECTED_BIT);
377389
k_event_post(&cmux->event, MODEM_CMUX_EVENT_DISCONNECTED_BIT);
@@ -381,7 +393,6 @@ static void modem_cmux_on_control_frame_ua(struct modem_cmux *cmux)
381393
{
382394
if (cmux->state != MODEM_CMUX_STATE_CONNECTING) {
383395
LOG_DBG("Unexpected UA frame");
384-
385396
return;
386397
}
387398

@@ -414,11 +425,11 @@ static void modem_cmux_on_control_frame_uih(struct modem_cmux *cmux)
414425

415426
switch (command->type.value) {
416427
case MODEM_CMUX_COMMAND_CLD:
417-
modem_cmux_on_cld_command(cmux);
428+
modem_cmux_on_cld_command(cmux, command);
418429
break;
419430

420431
case MODEM_CMUX_COMMAND_MSC:
421-
modem_cmux_on_msc_command(cmux);
432+
modem_cmux_on_msc_command(cmux, command);
422433
break;
423434

424435
case MODEM_CMUX_COMMAND_FCON:
@@ -435,6 +446,40 @@ static void modem_cmux_on_control_frame_uih(struct modem_cmux *cmux)
435446
}
436447
}
437448

449+
static void modem_cmux_connect_response_transmit(struct modem_cmux *cmux)
450+
{
451+
struct modem_cmux_frame frame = {
452+
.dlci_address = cmux->frame.dlci_address,
453+
.cr = cmux->frame.cr,
454+
.pf = cmux->frame.pf,
455+
.type = MODEM_CMUX_FRAME_TYPE_UA,
456+
.data = NULL,
457+
.data_len = 0,
458+
};
459+
460+
LOG_DBG("SABM/DISC request state send ack");
461+
modem_cmux_transmit_cmd_frame(cmux, &frame);
462+
}
463+
464+
static void modem_cmux_on_control_frame_sabm(struct modem_cmux *cmux)
465+
{
466+
modem_cmux_connect_response_transmit(cmux);
467+
468+
if ((cmux->state == MODEM_CMUX_STATE_CONNECTED) ||
469+
(cmux->state == MODEM_CMUX_STATE_DISCONNECTING)) {
470+
LOG_DBG("Connect request not accepted");
471+
return;
472+
}
473+
474+
cmux->state = MODEM_CMUX_STATE_CONNECTED;
475+
k_mutex_lock(&cmux->transmit_rb_lock, K_FOREVER);
476+
cmux->flow_control_on = true;
477+
k_mutex_unlock(&cmux->transmit_rb_lock);
478+
modem_cmux_raise_event(cmux, MODEM_CMUX_EVENT_CONNECTED);
479+
k_event_clear(&cmux->event, MODEM_CMUX_EVENT_DISCONNECTED_BIT);
480+
k_event_post(&cmux->event, MODEM_CMUX_EVENT_CONNECTED_BIT);
481+
}
482+
438483
static void modem_cmux_on_control_frame(struct modem_cmux *cmux)
439484
{
440485
modem_cmux_log_received_frame(&cmux->frame);
@@ -448,6 +493,10 @@ static void modem_cmux_on_control_frame(struct modem_cmux *cmux)
448493
modem_cmux_on_control_frame_uih(cmux);
449494
break;
450495

496+
case MODEM_CMUX_FRAME_TYPE_SABM:
497+
modem_cmux_on_control_frame_sabm(cmux);
498+
break;
499+
451500
default:
452501
LOG_WRN("Unknown %s frame type", "control");
453502
break;
@@ -509,6 +558,39 @@ static void modem_cmux_on_dlci_frame_uih(struct modem_cmux_dlci *dlci)
509558
modem_pipe_notify_receive_ready(&dlci->pipe);
510559
}
511560

561+
static void modem_cmux_on_dlci_frame_sabm(struct modem_cmux_dlci *dlci)
562+
{
563+
struct modem_cmux *cmux = dlci->cmux;
564+
565+
modem_cmux_connect_response_transmit(cmux);
566+
567+
if (dlci->state == MODEM_CMUX_DLCI_STATE_OPEN) {
568+
LOG_DBG("Unexpected SABM frame");
569+
return;
570+
}
571+
572+
dlci->state = MODEM_CMUX_DLCI_STATE_OPEN;
573+
modem_pipe_notify_opened(&dlci->pipe);
574+
k_mutex_lock(&dlci->receive_rb_lock, K_FOREVER);
575+
ring_buf_reset(&dlci->receive_rb);
576+
k_mutex_unlock(&dlci->receive_rb_lock);
577+
}
578+
579+
static void modem_cmux_on_dlci_frame_disc(struct modem_cmux_dlci *dlci)
580+
{
581+
struct modem_cmux *cmux = dlci->cmux;
582+
583+
modem_cmux_connect_response_transmit(cmux);
584+
585+
if (dlci->state != MODEM_CMUX_DLCI_STATE_OPEN) {
586+
LOG_DBG("Unexpected Disc frame");
587+
return;
588+
}
589+
590+
dlci->state = MODEM_CMUX_DLCI_STATE_CLOSED;
591+
modem_pipe_notify_closed(&dlci->pipe);
592+
}
593+
512594
static void modem_cmux_on_dlci_frame(struct modem_cmux *cmux)
513595
{
514596
struct modem_cmux_dlci *dlci;
@@ -532,6 +614,14 @@ static void modem_cmux_on_dlci_frame(struct modem_cmux *cmux)
532614
modem_cmux_on_dlci_frame_uih(dlci);
533615
break;
534616

617+
case MODEM_CMUX_FRAME_TYPE_SABM:
618+
modem_cmux_on_dlci_frame_sabm(dlci);
619+
break;
620+
621+
case MODEM_CMUX_FRAME_TYPE_DISC:
622+
modem_cmux_on_dlci_frame_disc(dlci);
623+
break;
624+
535625
default:
536626
LOG_WRN("Unknown %s frame type", "DLCI");
537627
break;
@@ -996,6 +1086,7 @@ void modem_cmux_init(struct modem_cmux *cmux, const struct modem_cmux_config *co
9961086
k_work_init_delayable(&cmux->connect_work, modem_cmux_connect_handler);
9971087
k_work_init_delayable(&cmux->disconnect_work, modem_cmux_disconnect_handler);
9981088
k_event_init(&cmux->event);
1089+
k_event_clear(&cmux->event, MODEM_CMUX_EVENT_CONNECTED_BIT);
9991090
k_event_post(&cmux->event, MODEM_CMUX_EVENT_DISCONNECTED_BIT);
10001091
}
10011092

@@ -1071,7 +1162,6 @@ int modem_cmux_disconnect(struct modem_cmux *cmux)
10711162
if (ret < 0) {
10721163
return ret;
10731164
}
1074-
10751165
if (k_event_wait(&cmux->event, MODEM_CMUX_EVENT_DISCONNECTED_BIT, false,
10761166
MODEM_CMUX_T2_TIMEOUT) == 0) {
10771167
return -EAGAIN;

0 commit comments

Comments
 (0)