diff --git a/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp b/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp index b530021fb6..5d3ffa4eb5 100644 --- a/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp +++ b/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp @@ -29,8 +29,11 @@ using namespace mbed; using namespace events; +uint8_t urc_callback_count; + void urc_callback() { + urc_callback_count++; } void urc2_callback() @@ -44,6 +47,7 @@ protected: void SetUp() { + urc_callback_count = 0; } void TearDown() @@ -954,16 +958,19 @@ TEST_F(TestATHandler, test_ATHandler_resp_start) filehandle_stub_table_pos = 0; at.resp_start(); - char table7[] = "urc: info\r\nresponseOK\r\n\0"; + char table7[] = "urc: info\r\nresponse\r\nOK\r\n\0"; at.flush(); at.clear_error(); filehandle_stub_table = table7; filehandle_stub_table_pos = 0; - at.set_urc_handler("urc: ", NULL); + mbed::Callback cb1(&urc_callback); + at.set_urc_handler("urc: ", cb1); at.resp_start(); // recv_buff: "responseOK\r\n\0" at.resp_stop(); // consumes to OKCRLF -> OK EXPECT_TRUE(at.get_last_error() == NSAPI_ERROR_OK); + EXPECT_TRUE(urc_callback_count == 1); + urc_callback_count = 0; char table8[] = "urc: info\r\nresponse\0"; at.flush(); @@ -1060,9 +1067,22 @@ TEST_F(TestATHandler, test_ATHandler_resp_stop) filehandle_stub_table = table3; filehandle_stub_table_pos = 0; at.resp_start(); - at.resp_stop(); + // Set stop tag for response to CRLF -> resp stop should stop on first CRLF + char table6[] = "line1\r\nline2\r\nOK\r\n"; + filehandle_stub_table = table6; + filehandle_stub_table_pos = 0; + + at.flush(); + at.clear_error(); + filehandle_stub_table_pos = 0; + + at.resp_start(); + at.set_stop_tag("\r\n"); + at.resp_stop(); + EXPECT_TRUE(at.get_last_error() == NSAPI_ERROR_OK); + char table7[] = "ssssss\0"; filehandle_stub_table = table7; filehandle_stub_table_pos = 0; @@ -1072,6 +1092,38 @@ TEST_F(TestATHandler, test_ATHandler_resp_stop) filehandle_stub_table_pos = 0; at.resp_start("ss", false); at.resp_stop(); + + // prefix + URC line + some other line + URC line + URC line + OKCRLF + char table4[] = "line1\r\nline2abcd\r\nline3abcd\r\nline4\r\n\r\nline3\r\nline3\r\nOK\r\n"; + filehandle_stub_table = table4; + filehandle_stub_table_pos = 0; + + at.flush(); + at.clear_error(); + filehandle_stub_table_pos = 0; + mbed::Callback cb1(&urc_callback); + at.set_urc_handler("line3", cb1); + + at.resp_start("line2"); + at.resp_stop(); + EXPECT_TRUE(urc_callback_count == 3); + urc_callback_count = 0; + + // URC line + prefix + URC line + some other line + URC line + URC line + some other line + OKCRLF + char table5[] = "line1\r\nline3\r\nline2abcd\r\nline3abcd\r\nline4\r\n\r\nline3\r\nline3\r\nline4\r\nOK\r\n"; + filehandle_stub_table = table5; + filehandle_stub_table_pos = 0; + + at.flush(); + at.clear_error(); + filehandle_stub_table_pos = 0; + mbed::Callback cb2(&urc_callback); + at.set_urc_handler("line3", cb2); + + at.resp_start("line2"); + at.resp_stop(); + EXPECT_TRUE(urc_callback_count == 4); + urc_callback_count = 0; } TEST_F(TestATHandler, test_ATHandler_info_resp) diff --git a/features/cellular/framework/AT/ATHandler.cpp b/features/cellular/framework/AT/ATHandler.cpp index e7d366ca38..e82bc699b2 100644 --- a/features/cellular/framework/AT/ATHandler.cpp +++ b/features/cellular/framework/AT/ATHandler.cpp @@ -1058,21 +1058,52 @@ bool ATHandler::consume_to_stop_tag() void ATHandler::resp_stop() { - // Do not return on error so that we can consume whatever there is in the buffer + if (_is_fh_usable) { + // Do not return on error so that we can consume whatever there is in the buffer - if (_current_scope == ElemType) { - information_response_element_stop(); - set_scope(InfoType); + if (_current_scope == ElemType) { + information_response_element_stop(); + set_scope(InfoType); + } + + if (_current_scope == InfoType) { + information_response_stop(); + } + + // Go for response stop_tag + if (_stop_tag && !_stop_tag->found && !_error_found) { + // Check for URC for every new line + while (!get_last_error()) { + + if (match(_stop_tag->tag, _stop_tag->len)) { + break; + } + + if (match_urc()) { + continue; + } + + // If no URC nor stop_tag found, look for CRLF and consume everything up to and including CRLF + if (mem_str(_recv_buff, _recv_len, CRLF, CRLF_LENGTH)) { + consume_to_tag(CRLF, true); + // If stop tag is CRLF we have to stop reading/consuming the buffer + if (!strncmp(CRLF, _stop_tag->tag, _stop_tag->len)) { + break; + } + // If no URC nor CRLF nor stop_tag -> fill buffer + } else { + if (!fill_buffer()) { + // if we don't get any match and no data within timeout, set an error to indicate need for recovery + set_error(NSAPI_ERROR_DEVICE_ERROR); + } + } + } + } + } else { + _last_err = NSAPI_ERROR_BUSY; } - if (_current_scope == InfoType) { - information_response_stop(); - } - - // Go for response stop_tag - if (consume_to_stop_tag()) { - set_scope(NotSet); - } + set_scope(NotSet); // Restore stop tag to OK set_tag(&_resp_stop, OK); diff --git a/features/cellular/framework/AT/ATHandler.h b/features/cellular/framework/AT/ATHandler.h index efd436f967..83ed9d1fa0 100644 --- a/features/cellular/framework/AT/ATHandler.h +++ b/features/cellular/framework/AT/ATHandler.h @@ -381,6 +381,10 @@ public: /** Ends all scopes starting from current scope. * Consumes everything until the scope's stop tag is found, then * goes to next scope until response scope is ending. + * URC match is checked during response scope ending, + * for every new line / CRLF. + * + * * Possible sequence: * element scope -> information response scope -> response scope */