Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion drivers/modem/modem_cellular.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ enum modem_cellular_event {
MODEM_CELLULAR_EVENT_SCRIPT_SUCCESS,
MODEM_CELLULAR_EVENT_SCRIPT_FAILED,
MODEM_CELLULAR_EVENT_CMUX_CONNECTED,
MODEM_CELLULAR_EVENT_CMUX_DISCONNECTED,
MODEM_CELLULAR_EVENT_DLCI1_OPENED,
MODEM_CELLULAR_EVENT_DLCI2_OPENED,
MODEM_CELLULAR_EVENT_TIMEOUT,
Expand Down Expand Up @@ -261,6 +262,8 @@ static const char *modem_cellular_event_str(enum modem_cellular_event event)
return "script failed";
case MODEM_CELLULAR_EVENT_CMUX_CONNECTED:
return "cmux connected";
case MODEM_CELLULAR_EVENT_CMUX_DISCONNECTED:
return "cmux disconnected";
case MODEM_CELLULAR_EVENT_DLCI1_OPENED:
return "dlci1 opened";
case MODEM_CELLULAR_EVENT_DLCI2_OPENED:
Expand Down Expand Up @@ -1454,6 +1457,7 @@ static int modem_cellular_on_dormant_state_leave(struct modem_cellular_data *dat

static int modem_cellular_on_init_power_off_state_enter(struct modem_cellular_data *data)
{
modem_cmux_disconnect_async(&data->cmux);
modem_cellular_start_timer(data, K_MSEC(2000));
return 0;
}
Expand All @@ -1465,6 +1469,9 @@ static void modem_cellular_init_power_off_event_handler(struct modem_cellular_da
(const struct modem_cellular_config *)data->dev->config;

switch (evt) {
case MODEM_CELLULAR_EVENT_CMUX_DISCONNECTED:
modem_cellular_stop_timer(data);
__fallthrough;
case MODEM_CELLULAR_EVENT_TIMEOUT:
/* Shutdown script can only be used if cmd_pipe is available, i.e. we are not in
* some intermediary state without a pipe for commands available
Expand Down Expand Up @@ -1864,7 +1871,9 @@ static void modem_cellular_cmux_handler(struct modem_cmux *cmux, enum modem_cmux
case MODEM_CMUX_EVENT_CONNECTED:
modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_CMUX_CONNECTED);
break;

case MODEM_CMUX_EVENT_DISCONNECTED:
modem_cellular_delegate_event(data, MODEM_CELLULAR_EVENT_CMUX_DISCONNECTED);
break;
default:
break;
}
Expand Down
47 changes: 35 additions & 12 deletions subsys/modem/modem_cmux.c
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,17 @@ static void modem_cmux_on_fcoff_command(struct modem_cmux *cmux)
modem_cmux_acknowledge_received_frame(cmux);
}

static void disconnect(struct modem_cmux *cmux)
{
LOG_DBG("CMUX disconnected");
k_work_cancel_delayable(&cmux->disconnect_work);
set_state(cmux, MODEM_CMUX_STATE_DISCONNECTED);
k_mutex_lock(&cmux->transmit_rb_lock, K_FOREVER);
cmux->flow_control_on = false;
k_mutex_unlock(&cmux->transmit_rb_lock);
modem_cmux_raise_event(cmux, MODEM_CMUX_EVENT_DISCONNECTED);
}

static void modem_cmux_on_cld_command(struct modem_cmux *cmux, struct modem_cmux_command *command)
{
if (command->type.cr) {
Expand All @@ -464,16 +475,11 @@ static void modem_cmux_on_cld_command(struct modem_cmux *cmux, struct modem_cmux
}

if (cmux->state == MODEM_CMUX_STATE_DISCONNECTING) {
k_work_cancel_delayable(&cmux->disconnect_work);
disconnect(cmux);
} else {
set_state(cmux, MODEM_CMUX_STATE_DISCONNECTING);
k_work_schedule(&cmux->disconnect_work, MODEM_CMUX_T1_TIMEOUT);
}

LOG_DBG("CMUX disconnected");
set_state(cmux, MODEM_CMUX_STATE_DISCONNECTED);
k_mutex_lock(&cmux->transmit_rb_lock, K_FOREVER);
cmux->flow_control_on = false;
k_mutex_unlock(&cmux->transmit_rb_lock);

modem_cmux_raise_event(cmux, MODEM_CMUX_EVENT_DISCONNECTED);
}

static void modem_cmux_on_control_frame_ua(struct modem_cmux *cmux)
Expand Down Expand Up @@ -545,6 +551,19 @@ static void modem_cmux_on_control_frame_uih(struct modem_cmux *cmux)

modem_cmux_log_received_command(command);

if (!command->type.cr) {
LOG_DBG("Received response command");
switch (command->type.value) {
case MODEM_CMUX_COMMAND_CLD:
modem_cmux_on_cld_command(cmux, command);
break;
default:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reviewers: In case you are wondering why switch-case with only one case, see the PR #97362 there is PSC command handler coming.
This is just split into its own PR.

/* Responses to other commands are ignored */
break;
}
return;
}

switch (command->type.value) {
case MODEM_CMUX_COMMAND_CLD:
modem_cmux_on_cld_command(cmux, command);
Expand Down Expand Up @@ -631,8 +650,7 @@ static void modem_cmux_on_control_frame(struct modem_cmux *cmux)
modem_cmux_log_received_frame(&cmux->frame);

if (is_connected(cmux) && cmux->frame.cr == cmux->initiator) {
LOG_DBG("Received a response frame, dropping");
return;
LOG_DBG("Received a response frame");
}

switch (cmux->frame.type) {
Expand Down Expand Up @@ -1138,7 +1156,12 @@ static void modem_cmux_disconnect_handler(struct k_work *item)
struct modem_cmux_command *command;
uint8_t data[2];

set_state(cmux, MODEM_CMUX_STATE_DISCONNECTING);
if (cmux->state == MODEM_CMUX_STATE_DISCONNECTING) {
disconnect(cmux);
} else {
set_state(cmux, MODEM_CMUX_STATE_DISCONNECTING);
k_work_schedule(&cmux->disconnect_work, MODEM_CMUX_T1_TIMEOUT);
}

command = modem_cmux_command_wrap(data);
command->type.ea = 1;
Expand Down
8 changes: 6 additions & 2 deletions tests/subsys/modem/modem_cmux_pair/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -507,9 +507,10 @@ ZTEST(modem_cmux_pair, test_modem_cmux_disconnect_connect)
modem_backend_mock_reset(&bus_mock_dte);
zassert_true(modem_cmux_disconnect_async(&cmux_dte) == 0, "Failed to disconnect CMUX");

k_msleep(100);
events = k_event_wait_all(&cmux_event_dte, (EVENT_CMUX_DISCONNECTED), false, K_MSEC(660));
zassert_true((events & EVENT_CMUX_DISCONNECTED), "Failed to disconnect CMUX");

events = k_event_wait_all(&cmux_event_dte, (EVENT_CMUX_DISCONNECTED), false, K_MSEC(100));
events = k_event_wait_all(&cmux_event_dce, (EVENT_CMUX_DISCONNECTED), false, K_MSEC(660));
zassert_true((events & EVENT_CMUX_DISCONNECTED), "Failed to disconnect CMUX");

/* Reconnect CMUX */
Expand Down Expand Up @@ -554,6 +555,9 @@ ZTEST(modem_cmux_pair, test_modem_cmux_disconnect_connect_sync)
zassert_true(modem_cmux_disconnect(&cmux_dte) == 0, "Failed to disconnect CMUX");
zassert_true(modem_cmux_disconnect(&cmux_dte) == -EALREADY,
"Should already be disconnected");

events = k_event_wait_all(&cmux_event_dce, (EVENT_CMUX_DISCONNECTED), false, K_MSEC(660));
zassert_true((events & EVENT_CMUX_DISCONNECTED), "Failed to disconnect CMUX");
zassert_true(modem_cmux_disconnect(&cmux_dce) == -EALREADY,
"Should already be disconnected");

Expand Down