modem: pipe: Reinvoke receive ready on attach
This PR makes the modem_pipe instances track if they have data ready to receive, and invoke the RECEIVE_READY event every time they are attached if the backend implementing the pipe has notified that receive is ready. This mechanism ensures that modules attaching to a pipe get the async RECEIVE_READY event immediately after attaching to a pipe if there is data ready, instead of having to poll the pipe, or worse, wait until newer data becomes available. The addition revealed a timing issue in the cmux test suite. Specifically the CMUX instance now immediately receives the response to a command which the CMUX instance has not sent yet, causing it to drop the response. The CMUX test suite now uses the transaction mechanism of the mock_pipe to wait for the command before sending the response. Signed-off-by: Bjarki Arge Andreasen <bjarkix123@gmail.com>
This commit is contained in:
parent
8cb9d76553
commit
40b9f51ee5
|
@ -53,6 +53,7 @@ struct modem_pipe {
|
|||
enum modem_pipe_state state;
|
||||
struct k_mutex lock;
|
||||
struct k_condvar condvar;
|
||||
bool receive_ready_pending;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,6 +20,7 @@ void modem_pipe_init(struct modem_pipe *pipe, void *data, struct modem_pipe_api
|
|||
pipe->callback = NULL;
|
||||
pipe->user_data = NULL;
|
||||
pipe->state = MODEM_PIPE_STATE_CLOSED;
|
||||
pipe->receive_ready_pending = false;
|
||||
|
||||
k_mutex_init(&pipe->lock);
|
||||
k_condvar_init(&pipe->condvar);
|
||||
|
@ -63,6 +64,11 @@ void modem_pipe_attach(struct modem_pipe *pipe, modem_pipe_api_callback callback
|
|||
k_mutex_lock(&pipe->lock, K_FOREVER);
|
||||
pipe->callback = callback;
|
||||
pipe->user_data = user_data;
|
||||
|
||||
if (pipe->receive_ready_pending && (pipe->callback != NULL)) {
|
||||
pipe->callback(pipe, MODEM_PIPE_EVENT_RECEIVE_READY, pipe->user_data);
|
||||
}
|
||||
|
||||
k_mutex_unlock(&pipe->lock);
|
||||
}
|
||||
|
||||
|
@ -94,6 +100,7 @@ int modem_pipe_receive(struct modem_pipe *pipe, uint8_t *buf, size_t size)
|
|||
}
|
||||
|
||||
ret = pipe->api->receive(pipe->data, buf, size);
|
||||
pipe->receive_ready_pending = false;
|
||||
k_mutex_unlock(&pipe->lock);
|
||||
return ret;
|
||||
}
|
||||
|
@ -155,6 +162,7 @@ void modem_pipe_notify_closed(struct modem_pipe *pipe)
|
|||
{
|
||||
k_mutex_lock(&pipe->lock, K_FOREVER);
|
||||
pipe->state = MODEM_PIPE_STATE_CLOSED;
|
||||
pipe->receive_ready_pending = false;
|
||||
|
||||
if (pipe->callback != NULL) {
|
||||
pipe->callback(pipe, MODEM_PIPE_EVENT_CLOSED, pipe->user_data);
|
||||
|
@ -168,6 +176,8 @@ void modem_pipe_notify_receive_ready(struct modem_pipe *pipe)
|
|||
{
|
||||
k_mutex_lock(&pipe->lock, K_FOREVER);
|
||||
|
||||
pipe->receive_ready_pending = true;
|
||||
|
||||
if (pipe->callback != NULL) {
|
||||
pipe->callback(pipe, MODEM_PIPE_EVENT_RECEIVE_READY, pipe->user_data);
|
||||
}
|
||||
|
|
|
@ -265,32 +265,26 @@ static void *test_modem_cmux_setup(void)
|
|||
};
|
||||
|
||||
bus_mock_pipe = modem_backend_mock_init(&bus_mock, &bus_mock_config);
|
||||
__ASSERT_NO_MSG(modem_pipe_open_async(bus_mock_pipe) == 0);
|
||||
__ASSERT_NO_MSG(modem_pipe_open(bus_mock_pipe) == 0);
|
||||
|
||||
/* Connect CMUX */
|
||||
__ASSERT_NO_MSG(modem_cmux_attach(&cmux, bus_mock_pipe) == 0);
|
||||
modem_backend_mock_prime(&bus_mock, &transaction_control_sabm);
|
||||
__ASSERT_NO_MSG(modem_cmux_connect_async(&cmux) == 0);
|
||||
modem_backend_mock_put(&bus_mock, cmux_frame_control_sabm_ack,
|
||||
sizeof(cmux_frame_control_sabm_ack));
|
||||
|
||||
events = k_event_wait(&cmux_event, EVENT_CMUX_CONNECTED, false, K_MSEC(100));
|
||||
__ASSERT_NO_MSG(events == EVENT_CMUX_CONNECTED);
|
||||
|
||||
/* Open DLCI channels */
|
||||
modem_pipe_attach(dlci1_pipe, test_modem_dlci1_pipe_callback, NULL);
|
||||
modem_pipe_attach(dlci2_pipe, test_modem_dlci2_pipe_callback, NULL);
|
||||
modem_backend_mock_prime(&bus_mock, &transaction_dlci1_sabm);
|
||||
__ASSERT_NO_MSG(modem_pipe_open_async(dlci1_pipe) == 0);
|
||||
__ASSERT_NO_MSG(modem_pipe_open_async(dlci2_pipe) == 0);
|
||||
modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_sabm_ack,
|
||||
sizeof(cmux_frame_dlci1_sabm_ack));
|
||||
|
||||
modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_sabm_ack,
|
||||
sizeof(cmux_frame_dlci2_sabm_ack));
|
||||
|
||||
events = k_event_wait_all(&cmux_event, (EVENT_CMUX_DLCI1_OPEN | EVENT_CMUX_DLCI2_OPEN),
|
||||
false, K_MSEC(100));
|
||||
|
||||
events = k_event_wait(&cmux_event, EVENT_CMUX_DLCI1_OPEN, false, K_MSEC(100));
|
||||
__ASSERT_NO_MSG((events & EVENT_CMUX_DLCI1_OPEN));
|
||||
|
||||
modem_pipe_attach(dlci2_pipe, test_modem_dlci2_pipe_callback, NULL);
|
||||
modem_backend_mock_prime(&bus_mock, &transaction_dlci2_sabm);
|
||||
__ASSERT_NO_MSG(modem_pipe_open_async(dlci2_pipe) == 0);
|
||||
events = k_event_wait(&cmux_event, EVENT_CMUX_DLCI2_OPEN, false, K_MSEC(100));
|
||||
__ASSERT_NO_MSG((events & EVENT_CMUX_DLCI2_OPEN));
|
||||
|
||||
return NULL;
|
||||
|
|
Loading…
Reference in a new issue