Skip to content

Commit

Permalink
[hal] cellular add/remove urc handler
Browse files Browse the repository at this point in the history
  • Loading branch information
technobly committed Nov 23, 2021
1 parent 997ca98 commit ae61beb
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 33 deletions.
10 changes: 10 additions & 0 deletions hal/inc/cellular_hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,16 @@ int cellular_update_status(void* reserved);
*/
int cellular_enable_updates(void* reserved);

/**
* Add URC handler
*/
int cellular_add_urc_handler(const char* prefix, hal_cellular_urc_callback_t cb, void* context);

/**
* Remove URC handler
*/
int cellular_remove_urc_handler(const char* prefix);

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 2 additions & 0 deletions hal/inc/cellular_hal_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ typedef int (*_CALLBACKPTR_MDM)(int type, const char* buf, int len, void* param)

typedef void (*_CELLULAR_SMS_CB_MDM)(void* data, int index);

typedef int (*hal_cellular_urc_callback_t)(const char* data, void* context);

#ifdef __cplusplus
// Todo - is storing raw string pointers correct here? These will only be valid
// If they are stored as constants in the application.
Expand Down
66 changes: 66 additions & 0 deletions hal/network/ncp/cellular/cellular_hal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "ifapi.h"

#include "system_network.h" // FIXME: For network_interface_index
#include "spark_wiring_vector.h"

#include "str_util.h"
#include "endian_util.h"
Expand Down Expand Up @@ -108,6 +109,32 @@ hal_net_access_tech_t fromCellularAccessTechnology(CellularAccessTechnology rat)
}
}

struct CellularHalUrcHandler {
const char* prefix;
hal_cellular_urc_callback_t callback;
void* context;
};

Vector<CellularHalUrcHandler> sUrcHandlers;

static int commonUrcHandler(AtResponseReader* reader, const char* prefix, void* data) {
auto handler = static_cast<CellularHalUrcHandler*>(data);

const size_t atResponseSize = 64;
std::unique_ptr<char[]> atResponse(new(std::nothrow) char[atResponseSize]);
CHECK_TRUE(atResponse.get(), SYSTEM_ERROR_NO_MEMORY);

const auto n = reader->readLine(atResponse.get(), atResponseSize - 1);
if (n < 0) {
return n;
}
atResponse[n] = '\0';
handler->callback(atResponse.get(), handler->context);
atResponse.reset();

return SYSTEM_ERROR_NONE;
}

} // unnamed

int cellular_on(void* reserved) {
Expand Down Expand Up @@ -508,6 +535,45 @@ int cellular_command(_CALLBACKPTR_MDM cb, void* param, system_tick_t timeout_ms,
return mdmTypeToResult(mdmType);
}

int cellular_add_urc_handler(const char* prefix, hal_cellular_urc_callback_t cb, void* context) {
const auto mgr = cellularNetworkManager();
CHECK_TRUE(mgr, SYSTEM_ERROR_UNKNOWN);
const auto client = mgr->ncpClient();
CHECK_TRUE(client, SYSTEM_ERROR_UNKNOWN);
const auto parser = client->atParser();

const NcpClientLock lock(client);

sUrcHandlers.append({
.prefix = prefix,
.callback = cb,
.context = context
});
auto& handler = sUrcHandlers.last();

return parser->addUrcHandler(prefix, commonUrcHandler, &handler);
}

int cellular_remove_urc_handler(const char* prefix) {
const auto mgr = cellularNetworkManager();
CHECK_TRUE(mgr, SYSTEM_ERROR_UNKNOWN);
const auto client = mgr->ncpClient();
CHECK_TRUE(client, SYSTEM_ERROR_UNKNOWN);
const auto parser = client->atParser();

const NcpClientLock lock(client);

parser->removeUrcHandler(prefix);
for (int i = 0; i < sUrcHandlers.size(); ++i) {
if (strcmp(sUrcHandlers.at(i).prefix, prefix) == 0) {
sUrcHandlers.removeAt(i);
break;
}
}

return SYSTEM_ERROR_NONE;
}

int cellular_data_usage_set(CellularDataHal* data, void* reserved) {
return SYSTEM_ERROR_NOT_SUPPORTED;
}
Expand Down
76 changes: 44 additions & 32 deletions services/src/ncp_fw_update.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

#include "ncp_fw_update.h"
#include "system_error.h"
// #if HAL_PLATFORM_NCP_FW_UPDATE
#if HAL_PLATFORM_NCP_FW_UPDATE

#include "logging.h"
#define SARA_NCP_FW_UPDATE_LOG_CATEGORY "system.ncp.update"
Expand Down Expand Up @@ -84,10 +84,10 @@ const int NCP_FW_UUFWINSTALL_COMPLETE = 128;
* };
*/
const SaraNcpFwUpdateConfig SARA_NCP_FW_UPDATE_CONFIG[] = {
// { sizeof(SaraNcpFwUpdateConfig), 3140001, 103140001, "SARA-R510S-01B-00-ES-0314A0001_SARA-R510S-01B-00-XX-0314ENG0099A0001.upd", "09c1a98d03c761bcbea50355f9b2a50f" },
// { sizeof(SaraNcpFwUpdateConfig), 103140001, 3140001, "SARA-R510S-01B-00-XX-0314ENG0099A0001_SARA-R510S-01B-00-ES-0314A0001.upd", "136caf2883457093c9e41fda3c6a44e3" },
// { sizeof(SaraNcpFwUpdateConfig), 2060001, 99010001, "SARA-R510S-00B-01_FW02.06_A00.01_IP_SARA-R510S-00B-01_FW99.01_A00.01.upd", "ccfdc48c0a45198d6e168b30d0740959" },
// { sizeof(SaraNcpFwUpdateConfig), 99010001, 2060001, "SARA-R510S-00B-01_FW99.01_A00.01_SARA-R510S-00B-01_FW02.06_A00.01_IP.upd", "5fd6c0d3d731c097605895b86f28c2cf" },
// { sizeof(SaraNcpFwUpdateConfig), 31400010, 31400011, "SARA-R510S-01B-00-ES-0314A0001_SARA-R510S-01B-00-XX-0314ENG0099A0001.upd", "09c1a98d03c761bcbea50355f9b2a50f" },
// { sizeof(SaraNcpFwUpdateConfig), 31400011, 31400010, "SARA-R510S-01B-00-XX-0314ENG0099A0001_SARA-R510S-01B-00-ES-0314A0001.upd", "136caf2883457093c9e41fda3c6a44e3" },
// { sizeof(SaraNcpFwUpdateConfig), 20600010, 990100010, "SARA-R510S-00B-01_FW02.06_A00.01_IP_SARA-R510S-00B-01_FW99.01_A00.01.upd", "ccfdc48c0a45198d6e168b30d0740959" },
// { sizeof(SaraNcpFwUpdateConfig), 990100010, 20600010, "SARA-R510S-00B-01_FW99.01_A00.01_SARA-R510S-00B-01_FW02.06_A00.01_IP.upd", "5fd6c0d3d731c097605895b86f28c2cf" },
};
const size_t SARA_NCP_FW_UPDATE_CONFIG_SIZE = sizeof(SARA_NCP_FW_UPDATE_CONFIG) / sizeof(SARA_NCP_FW_UPDATE_CONFIG[0]);

Expand Down Expand Up @@ -460,17 +460,18 @@ int SaraNcpFwUpdate::process() {
NCPFW_LOG(INFO, "Disconnecting Cellular...");
// network_disconnect() doesn't wait for final OK response from CFUN=0
// wait for DETACH: +CGEV: ME PDN DEACT 1
// FIXME: Note that this uses internals of the NCP client/parser and that a new cellular_hal API
// should be added for this functionality later, as in all the other places we are using
// cellular_commandas opposed to directly calling into ncp client/parser.
// FIXME
#ifndef UNIT_TEST
auto mgr = cellularNetworkManager();
auto client = mgr->ncpClient();
auto parser = client->atParser();
const NcpClientLock lock(client);
parser->addUrcHandler("+CGEV", cgevCallback, this);
#endif // UNIT_TEST
cellular_add_urc_handler("+CGEV", [](const char* data, void* context) -> int {
const auto self = (SaraNcpFwUpdate*)context;
int profile;

int r = ::sscanf(data, "+CGEV: ME PDN DEACT %d", &profile);
// do not CHECK_TRUE as we intend to ignore +CGEV: ME DETACH
if (r >= 1) {
self->cgevDeactProfile_ = profile;
}

return SYSTEM_ERROR_NONE;
}, this);
cgevDeactProfile_ = 0;
startTimer_ = millis();
network_disconnect(0, NETWORK_DISCONNECT_REASON_USER, 0);
Expand Down Expand Up @@ -537,17 +538,25 @@ int SaraNcpFwUpdate::process() {
}
}

// FIXME: Note that this uses internals of the NCP client/parser and that a new cellular_hal API
// should be added for this functionality later, as in all the other places we are using
// cellular_commandas opposed to directly calling into ncp client/parser.
// FIXME
#ifndef UNIT_TEST
auto mgr = cellularNetworkManager();
auto client = mgr->ncpClient();
auto parser = client->atParser();
const NcpClientLock lock(client);
parser->addUrcHandler("+UUHTTPCR", httpRespCallback, this);
#endif // UNIT_TEST
cellular_add_urc_handler("+UUHTTPCR", [](const char* data, void* context) -> int {
const auto self = (SaraNcpFwUpdate*)context;
int a, b, c;
char s[40];

int r = ::sscanf(data, "+UUHTTPCR: %*d,%d,%d,%d,\"%32s\"", &a, &b, &c, s);
CHECK_TRUE(r >= 3, SYSTEM_ERROR_AT_RESPONSE_UNEXPECTED);

self->httpsResp_.valid = false; // make following lines atomic
self->httpsResp_.command = a;
self->httpsResp_.result = b;
self->httpsResp_.status_code = c;
if (r > 3) {
memcpy(self->httpsResp_.md5_sum, &s, sizeof(s));
}
self->httpsResp_.valid = true;

return SYSTEM_ERROR_NONE;
}, this);

NCPFW_LOG(INFO, "Starting download...");
#if SARA_NCP_FW_UPDATE_ENABLE_DOWNLOAD
Expand Down Expand Up @@ -575,6 +584,8 @@ int SaraNcpFwUpdate::process() {
}
}
}

cellular_remove_urc_handler("+UUHTTPCR");
#else // SARA_NCP_FW_UPDATE_ENABLE_DOWNLOAD
// DEBUG
modemFirmwareDownloadComplete = true;
Expand Down Expand Up @@ -606,6 +617,7 @@ int SaraNcpFwUpdate::process() {
{
if (cgevDeactProfile_ == NCP_FW_UBLOX_DEFAULT_CID) { // Default CID detached
NCPFW_LOG(INFO, "Disconnected Cellular.");
cellular_remove_urc_handler("+CGEV");
saraNcpFwUpdateState_ = FW_UPDATE_STATE_INSTALL_STARTING;
cooldown(1000); // allow other disconnect URCs to pass
}
Expand Down Expand Up @@ -1005,10 +1017,10 @@ int sara_ncp_fw_update_config(const SaraNcpFwUpdateConfig* userConfigData, void*
return particle::services::SaraNcpFwUpdate::instance()->setConfig(userConfigData);
}

// #else // #if HAL_PLATFORM_NCP_FW_UPDATE
#else // #if HAL_PLATFORM_NCP_FW_UPDATE

// int sara_ncp_fw_update_config(const SaraNcpFwUpdateConfig* userConfigData, void* reserved) {
// return SYSTEM_ERROR_NONE;
// }
int sara_ncp_fw_update_config(const SaraNcpFwUpdateConfig* userConfigData, void* reserved) {
return SYSTEM_ERROR_NONE;
}

// #endif // #if HAL_PLATFORM_NCP_FW_UPDATE
#endif // #if HAL_PLATFORM_NCP_FW_UPDATE
2 changes: 1 addition & 1 deletion test/unit_tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Building and running tests
Create a build directory:

```bash
rm -rf .build && mkdir .build && cd .build
rm -rf build && mkdir build && cd build
```

Generate build files:
Expand Down
8 changes: 8 additions & 0 deletions test/unit_tests/ncp_fw_update/stubs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,12 @@ int cellular_command(_CALLBACKPTR_MDM cb, void* param, system_tick_t timeout_ms,

int cellular_get_ncp_firmware_version(uint32_t* version, void* reserved) {
return 0;
}

int cellular_add_urc_handler(const char* prefix, hal_cellular_urc_callback_t cb, void* context) {
return 0;
}

int cellular_remove_urc_handler(const char* prefix) {
return 0;
}

0 comments on commit ae61beb

Please sign in to comment.