Skip to content

Commit

Permalink
Revert "Remove R510 FOTA support"
Browse files Browse the repository at this point in the history
This reverts commit a0b92dd.
  • Loading branch information
technobly committed Sep 20, 2021
1 parent a0b92dd commit 6afbd81
Show file tree
Hide file tree
Showing 11 changed files with 1,398 additions and 68 deletions.
4 changes: 4 additions & 0 deletions hal/inc/hal_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,10 @@
#define HAL_PLATFORM_NCP_COUNT (0)
#endif // HAL_PLATFORM_NCP_COUNT

#ifndef HAL_PLATFORM_NCP_FW_UPDATE
#define HAL_PLATFORM_NCP_FW_UPDATE (0)
#endif // HAL_PLATFORM_NCP_FW_UPDATE

#ifndef HAL_PLATFORM_WIFI_COMPAT
#define HAL_PLATFORM_WIFI_COMPAT (0)
#endif // HAL_PLATFORM_WIFI_COMPAT
Expand Down
2 changes: 2 additions & 0 deletions services/inc/diagnostics.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#define DIAG_NAME_NETWORK_CELLULAR_CELL_GLOBAL_IDENTITY_MOBILE_NETWORK_CODE "net:cell:cgi:mnc"
#define DIAG_NAME_NETWORK_CELLULAR_CELL_GLOBAL_IDENTITY_LOCATION_AREA_CODE "net:cell:cgi:lac"
#define DIAG_NAME_NETWORK_CELLULAR_CELL_GLOBAL_IDENTITY_CELL_ID "net:cell:cgi:ci"
#define DIAG_NAME_NETWORK_NCP_FW_UPDATE_STATUS "net:ncpfw:stat"
#define DIAG_NAME_CLOUD_CONNECTION_STATUS "cloud:stat"
#define DIAG_NAME_CLOUD_CONNECTION_ERROR_CODE "cloud:err"
#define DIAG_NAME_CLOUD_DISCONNECTS "cloud:dconn"
Expand Down Expand Up @@ -95,6 +96,7 @@ typedef enum diag_id {
DIAG_ID_NETWORK_CELLULAR_CELL_GLOBAL_IDENTITY_MOBILE_NETWORK_CODE = 41, // net:cell:cgi:mnc
DIAG_ID_NETWORK_CELLULAR_CELL_GLOBAL_IDENTITY_LOCATION_AREA_CODE = 42, // net:cell:cgi:lac
DIAG_ID_NETWORK_CELLULAR_CELL_GLOBAL_IDENTITY_CELL_ID = 43, // net:cell:cgi:ci
DIAG_ID_NETWORK_NCP_FW_UPDATE_STATUS = 50, // net:nfu:stat
DIAG_ID_CLOUD_CONNECTION_STATUS = 10, // cloud:stat
DIAG_ID_CLOUD_CONNECTION_ERROR_CODE = 13, // cloud:err
DIAG_ID_CLOUD_DISCONNECTS = 14, // cloud:dconn
Expand Down
230 changes: 230 additions & 0 deletions services/inc/ncp_fw_update.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
/*
* Copyright (c) 2021 Particle Industries, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include "hal_platform.h"
#include "system_tick_hal.h"
#include "core_hal.h"
#include "system_defs.h"
#include "system_mode.h"
#include "system_network.h"
#include "cellular_hal.h"
#include "platform_ncp.h"
#include "diagnostics.h"
#include "spark_wiring_diagnostics.h"
#include "ncp_fw_update_dynalib.h"

#if HAL_PLATFORM_NCP
#include "at_parser.h"
#include "at_response.h"
#endif // HAL_PLATFORM_NCP

#if HAL_PLATFORM_NCP_FW_UPDATE

struct NcpFwUpdateCallbacks {
uint16_t size;
uint16_t reserved;

// System.updatesEnabled() / system_update.h
int (*system_get_flag)(system_flag_t flag, uint8_t* value, void*);

// system_cloud.h
bool (*spark_cloud_flag_connected)(void);
void (*spark_cloud_flag_connect)(void);
void (*spark_cloud_flag_disconnect)(void);

// system_cloud_internal.h
bool (*publishEvent)(const char* event, const char* data, unsigned flags);

// system_mode.h
System_Mode_TypeDef (*system_mode)(void);
};
PARTICLE_STATIC_ASSERT(NcpFwUpdateCallbacks_size, sizeof(NcpFwUpdateCallbacks) == (sizeof(void*) * 7));

namespace particle {

namespace services {

const system_tick_t NCP_FW_MODEM_POWER_ON_TIMEOUT = 60000;
const system_tick_t NCP_FW_MODEM_INSTALL_START_TIMEOUT = 5 * 60000;
const system_tick_t NCP_FW_MODEM_INSTALL_FINISH_TIMEOUT = 30 * 60000;
const system_tick_t NCP_FW_MODEM_CLOUD_CONNECT_TIMEOUT = 5 * 60000;
const uint32_t NCP_FW_UBLOX_R510_ENG_VERSION = 100000000;
const int NCP_FW_UUFWINSTALL_COMPLETE = 128;

enum NcpFwUpdateState {
FW_UPDATE_IDLE_STATE = 0,
FW_UPDATE_QUALIFY_FLAGS_STATE = 1,
FW_UPDATE_QUALIFY_MODEM_ON_STATE = 2,
FW_UPDATE_QUALIFY_RETRY_STATE = 3,
FW_UPDATE_SETUP_CLOUD_CONNECT_STATE = 4,
FW_UPDATE_SETUP_CLOUD_CONNECTING_STATE = 5,
FW_UPDATE_SETUP_CLOUD_CONNECTED_STATE = 6,
FW_UPDATE_DOWNLOAD_CLOUD_DISCONNECT_STATE = 7,
FW_UPDATE_DOWNLOAD_CELL_DISCONNECTING_STATE = 8,
FW_UPDATE_DOWNLOAD_CELL_CONNECTING_STATE = 9,
FW_UPDATE_DOWNLOAD_HTTPS_SETUP_STATE = 10,
FW_UPDATE_DOWNLOAD_READY_STATE = 11,
FW_UPDATE_INSTALL_CELL_DISCONNECTING_STATE = 12,
FW_UPDATE_INSTALL_CELL_DISCONNECTED_STATE = 13,
FW_UPDATE_INSTALL_STATE_STARTING = 14,
FW_UPDATE_INSTALL_STATE_WAITING = 15,
FW_UPDATE_FINISHED_POWER_OFF_STATE = 16,
FW_UPDATE_FINISHED_POWERING_OFF_STATE = 17,
FW_UPDATE_FINISHED_CLOUD_CONNECTING_STATE = 18,
FW_UPDATE_FINISHED_CLOUD_CONNECTED_STATE = 19,
FW_UPDATE_FINISHED_IDLE_STATE = 20,
};

enum NcpFwUpdateStatus {
FW_UPDATE_IDLE_STATUS = 0,
FW_UPDATE_DOWNLOADING_STATUS = 1,
FW_UPDATE_UPDATING_STATUS = 2,
FW_UPDATE_SUCCESS_STATUS = 3,
FW_UPDATE_NONE_STATUS = -1, // for diagnostics
FW_UPDATE_FAILED_STATUS = -2,
FW_UPDATE_FAILED_DOWNLOAD_RETRY_MAX_STATUS = -3,
FW_UPDATE_FAILED_START_INSTALL_TIMEOUT_STATUS = -4,
FW_UPDATE_FAILED_INSTALL_AT_ERROR_STATUS = -5,
FW_UPDATE_FAILED_SAME_VERSION_STATUS = -6,
FW_UPDATE_FAILED_INSTALL_TIMEOUT_STATUS = -7,
FW_UPDATE_FAILED_POWER_OFF_TIMEOUT_STATUS = -8,
FW_UPDATE_FAILED_CLOUD_CONNECT_TIMEOUT_STATUS = -9,
FW_UPDATE_FAILED_PUBLISH_RESULT_STATUS = -10,
};

struct HTTPSresponse {
int command;
int result;
int status_code;
char md5_sum[40];
int err_class;
int err_code;
};

const int NCP_FW_DATA_HEADER = 0x5259ADE5;
const int NCP_FW_DATA_FOOTER = 0x1337ACE5;
struct NcpFwUpdateData {
uint32_t header; // NCP_FW_DATA_HEADER;
NcpFwUpdateState state; // FW_UPDATE_IDLE_STATE;
NcpFwUpdateStatus status; // FW_UPDATE_IDLE_STATUS;
int firmwareVersion; // 0;
int startingFirmwareVersion; // 0;
int updateVersion; // 0;
uint8_t isUserConfig; // 0;
NcpFwUpdateConfig userConfigData; // 0;
uint32_t footer; // NCP_FW_DATA_FOOTER;
};

/**
* struct NcpFwUpdateConfig {
* const uint32_t start_version;
* const uint32_t end_version;
* const char filename[256];
* const char md5sum[32];
* };
*/
const NcpFwUpdateConfig NCP_FW_UPDATE_CONFIG[] = {
// { 3140001, 103140001, "SARA-R510S-01B-00-ES-0314A0001_SARA-R510S-01B-00-XX-0314ENG0099A0001.upd", "09c1a98d03c761bcbea50355f9b2a50f" },
// { 103140001, 3140001, "SARA-R510S-01B-00-XX-0314ENG0099A0001_SARA-R510S-01B-00-ES-0314A0001.upd", "136caf2883457093c9e41fda3c6a44e3" },
// { 2060001, 99010001, "SARA-R510S-00B-01_FW02.06_A00.01_IP_SARA-R510S-00B-01_FW99.01_A00.01.upd", "ccfdc48c0a45198d6e168b30d0740959" },
// { 99010001, 2060001, "SARA-R510S-00B-01_FW99.01_A00.01_SARA-R510S-00B-01_FW02.06_A00.01_IP.upd", "5fd6c0d3d731c097605895b86f28c2cf" },
};

const size_t NCP_FW_UPDATE_CONFIG_SIZE = sizeof(NCP_FW_UPDATE_CONFIG) / sizeof(NCP_FW_UPDATE_CONFIG[0]);

class NcpFwUpdate {
public:
/**
* Get the singleton instance of this class.
*/
static NcpFwUpdate* instance();

NcpFwUpdate();
~NcpFwUpdate();

int checkUpdate(const NcpFwUpdateConfig* userConfigData);
void init(NcpFwUpdateCallbacks* callbacks);
int process();
int getStatusDiagnostics();

private:

NcpFwUpdateState ncpFwUpdateState_;
NcpFwUpdateStatus ncpFwUpdateStatus_;
NcpFwUpdateStatus ncpFwUpdateStatusDiagnostics_;
int foatReady_;
system_tick_t startInstallTimer_;
system_tick_t atOkCheckTimer_;
int lastRespCode_;
int atResp_;
int atResponsive_;
int startingFirmwareVersion_;
int firmwareVersion_;
int updateVersion_;
bool isUserConfig_;
system_tick_t cooldownTimer_;
system_tick_t cooldownTimeout_;
bool initialized_;

union {
NcpFwUpdateData var;
uint8_t data[sizeof(NcpFwUpdateData)];
} ncpFwUpdateData_;

/**
* Functional callbacks that provide key system services to this NCP FW Update class.
*/
NcpFwUpdateCallbacks* ncpFwUpdateCallbacks_;

static int cbUUHTTPCR_(int type, const char* buf, int len, HTTPSresponse* data);
static int cbUHTTPER_(int type, const char* buf, int len, HTTPSresponse* data);
static int cbULSTFILE_(int type, const char* buf, int len, int* data);
static int cbATI9_(int type, const char* buf, int len, int* val);
static int cbUPSND_(int type, const char* buf, int len, int* data);
static int cbCOPS_(int type, const char* buf, int len, int* data);
static int httpRespCallback_(AtResponseReader* reader, const char* prefix, void* data);
int getAppFirmwareVersion_();
int setupHTTPSProperties_();
void cooldown_(system_tick_t timer);
void updateCooldown_();
bool inCooldown_();
void validateNcpFwUpdateData_();
int firmwareUpdateForVersion_(const int version);
int saveNcpFwUpdateData_();
int recallNcpFwUpdateData_();
int deleteNcpFwUpdateData_();
};

class NcpFwUpdateDiagnostics: public AbstractUnsignedIntegerDiagnosticData {
public:
NcpFwUpdateDiagnostics() :
AbstractUnsignedIntegerDiagnosticData(DIAG_ID_NETWORK_NCP_FW_UPDATE_STATUS, DIAG_NAME_NETWORK_NCP_FW_UPDATE_STATUS) {
}

virtual int get(IntType& val) override {
val = particle::services::NcpFwUpdate::instance()->getStatusDiagnostics();
return 0; // OK
}
};

} // namespace services

} // namespace particle

#endif // #if HAL_PLATFORM_NCP_FW_UPDATE
41 changes: 41 additions & 0 deletions services/inc/ncp_fw_update_dynalib.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2021 Particle Industries, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#ifdef __cplusplus
struct NcpFwUpdateConfig {
int start_version;
int end_version;
char filename[255 + 1];
char md5sum[32 + 1];
};
#else
typedef struct NcpFwUpdateConfig NcpFwUpdateConfig;
#endif

#ifdef __cplusplus
extern "C" {
#endif

#if !defined(PARTICLE_USER_MODULE) || defined(PARTICLE_USE_UNSTABLE_API)
int ncp_fw_udpate_check(const NcpFwUpdateConfig* data, void* reserved);
#endif // !defined(PARTICLE_USER_MODULE) || defined(PARTICLE_USE_UNSTABLE_API)

#ifdef __cplusplus
}
#endif
2 changes: 2 additions & 0 deletions services/inc/services_dynalib.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#ifdef DYNALIB_EXPORT
#include "nanopb_misc.h"
#include <stdint.h>
#include "ncp_fw_update_dynalib.h"
#ifdef PB_WITHOUT_64BIT
#define pb_int64_t int32_t
#define pb_uint64_t uint32_t
Expand Down Expand Up @@ -114,6 +115,7 @@ DYNALIB_FN(BASE_IDX + 0, services, set_system_error_message, void(const char*, .
DYNALIB_FN(BASE_IDX + 1, services, clear_system_error_message, void())
DYNALIB_FN(BASE_IDX + 2, services, get_system_error_message, const char*(int))
DYNALIB_FN(BASE_IDX + 3, services, jsmn_parse, int(jsmn_parser*, const char*, size_t, jsmntok_t*, unsigned int, void*))
DYNALIB_FN(BASE_IDX + 4, services, ncp_fw_udpate_check, int(const NcpFwUpdateConfig*, void*))

DYNALIB_END(services)

Expand Down
3 changes: 2 additions & 1 deletion services/inc/system_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ namespace particle { namespace services {

enum class SystemCacheKey : uint16_t {
WIFI_NCP_FIRMWARE_VERSION = 0x0000,
WIFI_NCP_MAC_ADDRESS = 0x0001
WIFI_NCP_MAC_ADDRESS = 0x0001,
NCP_FW_UPDATE_DATA = 0x0002,
};

class SystemCache {
Expand Down
65 changes: 65 additions & 0 deletions services/inc/system_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,71 @@ typedef enum network_disconnect_reason {
NETWORK_DISCONNECT_REASON_UNKNOWN = 7 ///< Unspecified disconnection reason.
} network_disconnect_reason;

typedef enum system_flag_t {
/**
* When 0, no OTA update is pending.
* When 1, an OTA update is pending, and will start when the SYSTEM_FLAG_OTA_UPDATES_FLAG
* is set.
*/
SYSTEM_FLAG_OTA_UPDATE_PENDING,

/**
* When 0, OTA updates are not started.
* When 1, OTA updates are started. Default.
*/
SYSTEM_FLAG_OTA_UPDATE_ENABLED,

/*
* When 0, no reset is pending.
* When 1, a reset is pending. The system will perform the reset
* when SYSTEM_FLAG_RESET_ENABLED is set to 1.
*/
SYSTEM_FLAG_RESET_PENDING,

/**
* When 0, the system is not able to perform a system reset.
* When 1, thee system will reset the device when a reset is pending.
*/
SYSTEM_FLAG_RESET_ENABLED,

/**
* A persistent flag that when set will cause the system to startup
* in listening mode. The flag is automatically cleared on reboot.
*/
SYSTEM_FLAG_STARTUP_LISTEN_MODE,

/**
* Enable/Disable use of serial1 during setup.
*/
SYSTEM_FLAG_WIFITESTER_OVER_SERIAL1,

/**
* Enable/disable publishing of last reset info to the cloud.
*/
SYSTEM_FLAG_PUBLISH_RESET_INFO,

/**
* When 0, the system doesn't reset network connection on cloud connection errors.
* When 1 (default), the system resets network connection after a number of failed attempts to
* connect to the cloud.
*/
SYSTEM_FLAG_RESET_NETWORK_ON_CLOUD_ERRORS,

/**
* Enable/Disable runtime power management peripheral detection
*/
SYSTEM_FLAG_PM_DETECTION,

/**
* When 0, OTA updates are only applied when SYSTEM_FLAG_OTA_UPDATE_ENABLED is set.
* When 1, OTA updates are applied irrespective of the value of SYSTEM_FLAG_OTA_UPDATE_ENABLED.
*/
SYSTEM_FLAG_OTA_UPDATE_FORCED,

SYSTEM_FLAG_MAX

} system_flag_t;

#ifdef __cplusplus

#include "enumflags.h"
Expand Down
Loading

0 comments on commit 6afbd81

Please sign in to comment.