@@ -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
348350static 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+
438483static 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+
512594static 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