| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdint.h> |
| #include <unistd.h> |
| #include <time.h> |
| #include <errno.h> |
| #include <pthread.h> |
| #include "ql_fota_api.h" |
| #include "fota_info.h" |
| #include "ql_fota.h" |
| //#include "ql_fota_log.h" |
| #include "ql_absys_api.h" |
| //#include "test_utils.h" |
| |
| |
| typedef void (*item_handler_f)(void); |
| typedef int (*init_handler_f)(void); |
| typedef int (*deinit_handler_f)(void); |
| |
| |
| #define T_ARRAY_SIZE(items) (sizeof(items)/sizeof(items[0])) |
| |
| typedef struct |
| { |
| const char *name; |
| item_handler_f handle; |
| } t_item_t; |
| |
| typedef struct |
| { |
| const char *name; |
| int item_len; |
| t_item_t *item_list; |
| } t_module_t; |
| |
| typedef struct |
| { |
| const char *name; |
| init_handler_f init_handle; |
| deinit_handler_f deinit_handle; |
| } t_init_t; |
| |
| int t_get_int(int *val); |
| int t_get_hex(uint32_t *val); |
| int t_get_char(int *val); |
| int t_get_string(char *str_buf, int str_len); |
| int t_get_int_list(int *dat_buf, int *dat_len); |
| int t_get_float_list(float *dat_buf, int *dat_len); |
| /*-----------------------------------------------------------------------------------------------*/ |
| /** |
| @brief Read a int value from stdin |
| @param[out] val, Return read data |
| @return |
| 0 - successful |
| 1 - read an enter |
| -1 - invalid input |
| */ |
| /*-----------------------------------------------------------------------------------------------*/ |
| int t_get_int(int *val) |
| { |
| int dat; |
| char *ptr_end = NULL; |
| char buf[256] = {0}; |
| |
| if(NULL == fgets(buf, sizeof(buf)-1, stdin)) |
| { |
| return -1; |
| } |
| |
| if(0 == buf[0]) |
| { |
| return -1; |
| } |
| |
| if(buf[0] == '\n') |
| { |
| return 1; |
| } |
| |
| dat = strtol(buf, &ptr_end, 10); |
| if(ptr_end!=NULL && ptr_end[0]!='\n') |
| { |
| return -1; |
| } |
| |
| if(val) |
| { |
| val[0] = dat; |
| } |
| |
| return 0; |
| } |
| |
| /*-----------------------------------------------------------------------------------------------*/ |
| /** |
| @brief Read a uint32 value from stdin |
| @param[out] val, Return read data |
| @return |
| 0 - successful |
| 1 - read an enter |
| -1 - invalid input |
| */ |
| /*-----------------------------------------------------------------------------------------------*/ |
| int t_get_hex(uint32_t *val) |
| { |
| int dat; |
| char *ptr_end = NULL; |
| char buf[256] = {0}; |
| |
| if(fgets(buf, sizeof(buf)-1, stdin) == NULL) |
| { |
| return -1; |
| } |
| |
| if(0 == buf[0]) |
| { |
| return -1; |
| } |
| |
| if(buf[0] == '\n') |
| { |
| return 1; |
| } |
| |
| dat = strtol(buf, &ptr_end, 16); |
| if(ptr_end!=NULL && ptr_end[0]!='\n') |
| { |
| return -1; |
| } |
| |
| if(val) |
| { |
| val[0] = dat; |
| } |
| |
| return 0; |
| } |
| |
| /*-----------------------------------------------------------------------------------------------*/ |
| /** |
| @brief Read a char value from stdin |
| @param[out] val, Return read data |
| @return |
| 0 - successful |
| 1 - read an enter |
| -1 - invalid input |
| */ |
| /*-----------------------------------------------------------------------------------------------*/ |
| int t_get_char(int *val) |
| { |
| char buf[256] = {0}; |
| |
| if(fgets(buf, sizeof(buf)-1, stdin) == NULL) |
| { |
| return -1; |
| } |
| |
| if(0 == buf[0]) |
| { |
| return -1; |
| } |
| |
| if(buf[0] == '\n') |
| { |
| return 1; |
| } |
| |
| if(buf[1]!='\n') |
| { |
| return -1; |
| } |
| |
| if(val) |
| { |
| val[0] = buf[0]; |
| } |
| |
| return 0; |
| } |
| |
| /*-----------------------------------------------------------------------------------------------*/ |
| /** |
| @brief Read a string value from stdin |
| @param[out] val, Return read data |
| @return |
| 0 - successful |
| 1 - read an enter |
| -1 - invalid input |
| */ |
| /*-----------------------------------------------------------------------------------------------*/ |
| int t_get_string(char *str_buf, int str_len) |
| { |
| char *ptr; |
| char buf[256] = {0}; |
| |
| if(fgets(buf, sizeof(buf)-1, stdin) == NULL) |
| { |
| return -1; |
| } |
| |
| if(0 == buf[0]) |
| { |
| return -1; |
| } |
| |
| if(buf[0] == '\n') |
| { |
| return 1; |
| } |
| |
| ptr = strchr(buf, '\n'); |
| if(ptr) |
| { |
| ptr[0] = 0; |
| } |
| |
| strncpy(str_buf, buf, str_len-1); |
| |
| return 0; |
| } |
| |
| /*-----------------------------------------------------------------------------------------------*/ |
| /** |
| @brief Read a list of int values from stdin |
| @param[out] val, Return read datas |
| @param[out&in] val, Input buffer length, output the number of read |
| @return |
| 0 - successful |
| 1 - read an enter |
| -1 - invalid input |
| */ |
| /*-----------------------------------------------------------------------------------------------*/ |
| int t_get_int_list(int *dat_buf, int *dat_len) |
| { |
| int idx = 0; |
| int len; |
| int dat; |
| char *ptr, *ptr_save; |
| char *ptr_end; |
| char buf[256] = {0}; |
| |
| if(!dat_buf || !dat_len) |
| { |
| return -1; |
| } |
| |
| len = dat_len[0]; |
| |
| if(fgets(buf, sizeof(buf)-1, stdin) == NULL) |
| { |
| return -1; |
| } |
| |
| if(0 == buf[0]) |
| { |
| return -1; |
| } |
| |
| if(buf[0] == '\n') |
| { |
| return 1; |
| } |
| |
| for(ptr=strtok_r(buf, ",.: \t\r\n", &ptr_save); |
| ptr!=NULL; |
| ptr=strtok_r(NULL, ",.: \t\r\n", &ptr_save)) |
| { |
| dat = strtol(ptr, &ptr_end, 10); |
| if(ptr_end!=NULL && ptr_end[0]!=0) |
| { |
| return -1; |
| } |
| if(idx >= len) |
| { |
| return 0; |
| } |
| |
| dat_buf[idx] = dat; |
| idx++; |
| } |
| |
| dat_len[0] = idx; |
| return 0; |
| } |
| |
| /*-----------------------------------------------------------------------------------------------*/ |
| /** |
| @brief Read a list of float values from stdin |
| @param[out] val, Return read datas |
| @param[out&in] val, Input buffer length, output the number of read |
| @return |
| 0 - successful |
| 1 - read an enter |
| -1 - invalid input |
| */ |
| /*-----------------------------------------------------------------------------------------------*/ |
| int t_get_float_list(float *dat_buf, int *dat_len) |
| { |
| int idx = 0; |
| int len; |
| float dat; |
| char *ptr, *ptr_save; |
| char *ptr_end; |
| char buf[256] = {0}; |
| |
| if(!dat_buf || !dat_len) |
| { |
| return -1; |
| } |
| |
| len = dat_len[0]; |
| |
| if(fgets(buf, sizeof(buf)-1, stdin) == NULL) |
| { |
| return -1; |
| } |
| |
| if(0 == buf[0]) |
| { |
| return -1; |
| } |
| |
| if(buf[0] == '\n') |
| { |
| return 1; |
| } |
| |
| for(ptr=strtok_r(buf, ",: \t\r\n", &ptr_save); |
| ptr!=NULL; |
| ptr=strtok_r(NULL, ",: \t\r\n", &ptr_save)) |
| { |
| dat = strtof(ptr, &ptr_end); |
| if(ptr_end!=NULL && ptr_end[0]!=0) |
| { |
| return -1; |
| } |
| if(idx >= len) |
| { |
| return 0; |
| } |
| |
| dat_buf[idx] = dat; |
| idx++; |
| } |
| |
| dat_len[0] = idx; |
| return 0; |
| } |
| #if 0 |
| #define DEBUG_INFO |
| #ifdef DEBUG_INFO |
| #define LOG_DBG(fmt, ...) printf("[DBG][%s_%d][%ld] "fmt"\n", __FUNCTION__, __LINE__, time(NULL), ##__VA_ARGS__) |
| #else |
| #define LOG_DBG(fmt, ...) |
| #endif |
| #define LOG_ERR(fmt, ...) printf("[DBG][%s_%d][%ld] "fmt"\n", __FUNCTION__, __LINE__, time(NULL), ##__VA_ARGS__) |
| #endif |
| |
| #define ITEM_NUM (sizeof(g_items)/sizeof(g_items[0])) |
| |
| void test_ota_api_start(void); |
| void test_get_fota_upgrade_info(void); |
| void test_ql_absys_switch(void); |
| void test_ql_absys_get_cur_active_part(void); |
| void test_ql_absys_sync(void); |
| void test_ql_absys_getstatus(void); |
| void test_ql_fota_fw_write_by_url(void); |
| |
| t_item_t g_items[] = { |
| {"API : ql_abfota_start_update", test_ota_api_start}, |
| {"API : ql_abfota_get_update_status", test_get_fota_upgrade_info}, |
| {"API : ql_absys_switch", test_ql_absys_switch}, |
| {"API : ql_absys_sync", test_ql_absys_sync}, |
| {"API : ql_absys_get_cur_active_part", test_ql_absys_get_cur_active_part}, |
| {"API : ql_absys_getstatus", test_ql_absys_getstatus} |
| }; |
| |
| void dump_items(void) |
| { |
| int i; |
| |
| printf("\n"); |
| |
| for(i=0; i<ITEM_NUM; i++) |
| { |
| printf("%d\t%s\n", i, g_items[i].name); |
| } |
| printf("-1\texit\n"); |
| } |
| |
| int main(int argc, const char **argv) |
| { |
| int ret = -1; |
| int idx = 0; |
| |
| printf("Quectel OTA API test sample, version : v0.0.1\n"); |
| |
| dump_items(); |
| |
| while(1) { |
| printf("Please enter your choice: "); |
| ret = t_get_int(&idx); |
| printf("\n"); |
| if(ret < 0) { |
| printf("Invalid input\n"); |
| continue; |
| } else if(ret == 1) { |
| dump_items(); |
| continue; |
| } |
| |
| if(idx == -1) { |
| break; |
| } |
| |
| if(idx<0 || idx>=ITEM_NUM) { |
| printf("Not support idx: %d\n", idx); |
| continue; |
| } |
| |
| g_items[idx].handle(); |
| } |
| return 0; |
| } |
| |
| void test_ota_api_start(void) |
| { |
| char package_file[128] = {0}; |
| int ret = -1; |
| |
| printf("please input the fota fbf package file dir: \n"); |
| printf("eg: /user_data/\n"); |
| //fota包同时已经放入该路径下 |
| memset(package_file, 0x0, sizeof(package_file)); |
| scanf("%s", package_file); |
| fflush(stdin); |
| ret = t_get_string((char*)package_file, sizeof(package_file)); |
| if (ret < 0 || package_file[0] == 0) { |
| printf("Invalid package file\n"); |
| return; |
| } |
| |
| ret = ql_abfota_start_update((char*)package_file); |
| |
| if (ret != 0) { |
| printf("run ql_abfota_start_update failed, api return: %d\n", ret); |
| return; |
| } |
| |
| printf("Update in-active partition SUCCEED\n"); |
| return; |
| } |
| |
| void test_ql_absys_getstatus(void) |
| { |
| int status = 0; |
| // char stat_buf[16] = {0}; |
| sysstatus_t sys_state; |
| status = ql_absys_getstatus(&sys_state); |
| if (status < 0) { |
| printf("failed to get absys status!!!\n"); |
| return; |
| } |
| |
| if (sys_state.is_damaged == 0) |
| { |
| printf("absys partition status : succeed\n"); |
| } |
| else |
| { |
| printf("absys partition status : damaged\n"); |
| printf("absys partition damaged position : %s\n", sys_state.damaged_partname); |
| printf("absys needsync!!!\n"); |
| } |
| return; |
| } |
| |
| |
| void test_get_fota_upgrade_info(void) |
| { |
| int ret = -1; |
| char stat_buf[16] = {0}; |
| update_info_t update_info; |
| ret = ql_abfota_get_update_status(&update_info); |
| if ( ret != 0) { |
| printf("run ql_abfota_start_update failed, api return: %d\n", ret); |
| return; |
| } |
| |
| memset(stat_buf, 0, sizeof(stat_buf)); |
| |
| switch (update_info.ota_state) { |
| case SUCCEED: |
| strncpy(stat_buf, "SUCCEED", strlen("SUCCEED")+1); |
| break; |
| case UPDATE: |
| strncpy(stat_buf, "UPDATE", strlen("UPDATE")+1); |
| break; |
| case BACKUP: |
| strncpy(stat_buf, "BACKUP", strlen("BACKUP")+1); |
| break; |
| case FAILED: |
| strncpy(stat_buf, "FAILED", strlen("FAILED")+1); |
| break; |
| case WRITEDONE: |
| strncpy(stat_buf, "WRITEDONE", strlen("WRITEDONE")+1); |
| break; |
| case NEEDSYNC: |
| strncpy(stat_buf, "NEEDSYNC", strlen("NEEDSYNC")+1); |
| break; |
| case UNKNOWN_STATUS: |
| default: |
| strncpy(stat_buf, "UNKNOWN_STATUS", strlen("UNKNOWN_STATUS")+1); |
| break; |
| } |
| |
| printf("Current fota progress: %d\n", update_info.percentage); |
| printf("Current fota state: %s\n", stat_buf); |
| printf("Current fota exit code: %d\n", update_info.exit_code); |
| |
| return; |
| } |
| |
| void test_ql_absys_switch(void) |
| { |
| int ret = -1; |
| ret = ql_absys_switch(); |
| if (ret != 0) { |
| printf("run ql_absys_switch failed, api return: %d\n", ret); |
| return; |
| } |
| |
| printf("It is okay to swith AB part to run\n"); |
| sleep(1); |
| |
| system("reboot"); |
| return; |
| } |
| |
| |
| void test_ql_absys_sync(void) |
| { |
| int ret = -1; |
| |
| ret = ql_absys_sync(); |
| if (ret != 0) { |
| printf("run ql_absys_sync failed, api return: %d\n", ret); |
| return; |
| } |
| |
| printf("do AB sync succeed\n"); |
| return; |
| } |
| |
| |
| void test_ql_absys_get_cur_active_part(void) |
| { |
| int ret = -1; |
| absystem_t cur_system; |
| |
| ret = ql_absys_get_cur_active_part(&cur_system); |
| if (ret != 0) { |
| printf("run ql_absys_get_cur_active_part failed, api return: %d\n", ret); |
| return; |
| } |
| |
| printf("Current active part is %c\n", (cur_system ? 'B': 'A')); |
| return; |
| } |