From 20022805abeb07b6820e0726d2686333745a5d12 Mon Sep 17 00:00:00 2001 From: fujr Date: Sat, 19 Apr 2025 14:00:37 +0800 Subject: [PATCH] tom_modem: add greedy read feature and dynamic at_message mem alloc --- application/tom_modem/Makefile | 2 +- application/tom_modem/src/main.c | 3 + application/tom_modem/src/modem_types.h | 6 +- application/tom_modem/src/operations.c | 198 ++++++++++++++---------- application/tom_modem/src/operations.h | 4 +- application/tom_modem/src/ttydevice.c | 86 +++++----- application/tom_modem/src/utils.c | 10 +- application/tom_modem/src/utils.h | 4 +- 8 files changed, 181 insertions(+), 132 deletions(-) diff --git a/application/tom_modem/Makefile b/application/tom_modem/Makefile index 88ffd50..7ba74ab 100644 --- a/application/tom_modem/Makefile +++ b/application/tom_modem/Makefile @@ -3,7 +3,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:= tom_modem PKG_RELEASE:=1 -PKG_VERSION:=1.0.1 +PKG_VERSION:=1.0.2 include $(INCLUDE_DIR)/package.mk diff --git a/application/tom_modem/src/main.c b/application/tom_modem/src/main.c index 7f19b49..8c076b0 100644 --- a/application/tom_modem/src/main.c +++ b/application/tom_modem/src/main.c @@ -112,6 +112,9 @@ int parse_user_input(int argc, char *argv[], PROFILE_T *profile) } profile->sms_index = atoi(argv[opt++]); break; + case GREEDY_READ: + profile->greedy_read = 1; + break; default: err_msg("Invalid option: %s", argv[opt]); break; diff --git a/application/tom_modem/src/modem_types.h b/application/tom_modem/src/modem_types.h index f07484e..36d2bbd 100644 --- a/application/tom_modem/src/modem_types.h +++ b/application/tom_modem/src/modem_types.h @@ -17,6 +17,7 @@ #define DEBUG_S 'D' #define SMS_PDU_S 'p' #define SMS_INDEX_S 'i' +#define GREEDY_READ_S 'g' #define AT_CMD_L "at_cmd" #define TTY_DEV_L "tty_dev" @@ -30,6 +31,7 @@ #define DEBUG_L "debug" #define SMS_PDU_L "sms_pdu" #define SMS_INDEX_L "sms_index" +#define GREEDY_READ_L "greedy_read" //operations #define AT_OP_S 'a' @@ -85,6 +87,7 @@ typedef struct _PROFILE { int debug; char *sms_pdu; int sms_index; + int greedy_read; } PROFILE_T; @@ -141,7 +144,8 @@ enum OPTIONS { OPERATION, DEBUG, SMS_PDU, - SMS_INDEX + SMS_INDEX, + GREEDY_READ }; enum OPERATIONS { diff --git a/application/tom_modem/src/operations.c b/application/tom_modem/src/operations.c index aa36b35..057af5b 100644 --- a/application/tom_modem/src/operations.c +++ b/application/tom_modem/src/operations.c @@ -3,7 +3,7 @@ int at(PROFILE_T *profile,FDS_T *fds) { int w_ret,r_ret; - char output[COMMON_BUF_SIZE] = {0}; + AT_MESSAGE_T message = {0}; if (profile->at_cmd == NULL) { err_msg("AT command is empty"); @@ -15,23 +15,26 @@ int at(PROFILE_T *profile,FDS_T *fds) return w_ret; } - r_ret = tty_read(fds->fdi, output, COMMON_BUF_SIZE,profile->timeout); + r_ret = tty_read(fds->fdi, &message, profile); if (r_ret) { dbg_msg("Error sending AT command, error code: %d", r_ret); if (r_ret == COMM_ERROR) return r_ret; } - user_msg("%s", output); + if (message.message) + { + user_msg("%s", message.message); + free(message.message); + } return SUCCESS; } int binary_at(PROFILE_T *profile,FDS_T *fds) { int w_ret,r_ret,hex_convert_ret; - int binary_at_cmd_len; char *binary_at_cmd; - char output[COMMON_BUF_SIZE] = {0}; + AT_MESSAGE_T message = {0}; if (profile->at_cmd == NULL) { err_msg("AT command is empty"); @@ -52,18 +55,23 @@ int binary_at(PROFILE_T *profile,FDS_T *fds) } w_ret = tty_write_raw(fds->fdo, binary_at_cmd); + free(binary_at_cmd); if (w_ret) { return w_ret; } - r_ret = tty_read_keyword(fds->fdi, output, COMMON_BUF_SIZE, "OK",profile->timeout); + r_ret = tty_read_keyword(fds->fdi, &message, "OK", profile); if (r_ret) { dbg_msg("Error sending AT command, error code: %d", r_ret); if (r_ret == COMM_ERROR) return r_ret; } - user_msg("%s", output); + if (message.message) + { + user_msg("%s", message.message); + free(message.message); + } return SUCCESS; } @@ -83,7 +91,7 @@ int sms_delete(PROFILE_T *profile,FDS_T *fds) { return w_ret; } - r_ret = tty_read_keyword(fds->fdi, NULL, COMMON_BUF_SIZE, "OK",profile->timeout); + r_ret = tty_read_keyword(fds->fdi, NULL, "OK", profile); if (r_ret) { dbg_msg("Error deleting SMS, error code: %d", r_ret); @@ -97,137 +105,155 @@ int sms_read(PROFILE_T *profile,FDS_T *fds) SMS_T *sms_list[SMS_LIST_SIZE]; SMS_T *sms; int w_ret,r_ret; - char sms_pdu[SMS_BUF_SIZE] = {0}; + AT_MESSAGE_T message = {0}; + w_ret = tty_write(fds->fdo, SET_PDU_FORMAT); if (w_ret) { return w_ret; } - r_ret = tty_read_keyword(fds->fdi, NULL, COMMON_BUF_SIZE, "OK",profile->timeout); + + r_ret = tty_read_keyword(fds->fdi, NULL, "OK", profile); if (r_ret) { - dbg_msg("Error setting PDU format , error code: %d", r_ret); + dbg_msg("Error setting PDU format, error code: %d", r_ret); if (r_ret == COMM_ERROR) + { return r_ret; + } } dbg_msg("Set PDU format success"); + w_ret = tty_write(fds->fdo, READ_ALL_SMS); if (w_ret) { return w_ret; } - r_ret = tty_read_keyword(fds->fdi, sms_pdu, SMS_BUF_SIZE, "OK",profile->timeout); + + r_ret = tty_read_keyword(fds->fdi, &message, "OK", profile); if (r_ret) { - dbg_msg("Error reading SMS , error code: %d", r_ret); + dbg_msg("Error reading SMS, error code: %d", r_ret); if (r_ret == COMM_ERROR) - return r_ret; - } - - - - //遍历 sms_pdu 的每一行 - char *line = strtok(sms_pdu, "\n"); - int sms_count = 0; - while (line != NULL) - { - if (strncmp(line, "+CMGL:", 6) == 0) { - sms = (SMS_T *)malloc(sizeof(SMS_T)); - memset(sms, 0, sizeof(SMS_T)); - char *pdu = strtok(NULL, "\n"); - sms->sms_pdu = (char *)malloc(strlen(pdu)); - sms->sender = (char *)malloc(PHONE_NUMBER_SIZE); - sms->sms_text = (char *)malloc(SMS_TEXT_SIZE); - sms->sms_index = get_sms_index(line); - memcpy(sms->sms_pdu, pdu, strlen(pdu)); - int sms_len = decode_pdu(sms); - if (sms_len > 0) - { - sms_list[sms_count] = sms; - sms_count++; - } - else - { - dbg_msg("Error decoding sms in line: %s", line); - destroy_sms(sms); - } + return r_ret; } - line = strtok(NULL, "\n"); } - - display_sms_in_json(sms_list,sms_count); - // for (int i = 1; i <= sms_count; i++) - // { - // dump_sms(sms_list[i]); - // destroy_sms(sms_list[i]); - // } + if (message.message) + { + char *line = strtok(message.message, "\n"); + int sms_count = 0; + + while (line != NULL) + { + if (strncmp(line, "+CMGL:", 6) == 0) + { + sms = (SMS_T *)malloc(sizeof(SMS_T)); + memset(sms, 0, sizeof(SMS_T)); + char *pdu = strtok(NULL, "\n"); + sms->sms_pdu = (char *)malloc(strlen(pdu)); + sms->sender = (char *)malloc(PHONE_NUMBER_SIZE); + sms->sms_text = (char *)malloc(SMS_TEXT_SIZE); + sms->sms_index = get_sms_index(line); + memcpy(sms->sms_pdu, pdu, strlen(pdu)); + int sms_len = decode_pdu(sms); + if (sms_len > 0) + { + sms_list[sms_count] = sms; + sms_count++; + } + else + { + dbg_msg("Error decoding SMS in line: %s", line); + destroy_sms(sms); + } + } + line = strtok(NULL, "\n"); + } + + display_sms_in_json(sms_list, sms_count); + free(message.message); + } + dbg_msg("Read SMS success"); - dbg_msg("%s", sms_pdu); return SUCCESS; } -int sms_send(PROFILE_T *profile,FDS_T *fds) -{ - int w_ret,r_ret; - if (profile->sms_pdu == NULL) - { +int sms_send(PROFILE_T *profile, FDS_T *fds) { + int w_ret, r_ret; + AT_MESSAGE_T message = {0}; + + if (profile->sms_pdu == NULL) { err_msg("SMS PDU is empty"); return INVALID_PARAM; } int pdu_len = strlen(profile->sms_pdu); int pdu_expected_len = (pdu_len) / 2 - 1; - char *send_sms_cmd; - char *write_pdu_cmd; + char *send_sms_cmd = (char *)malloc(32); + char *write_pdu_cmd = (char *)malloc(256); + w_ret = tty_write(fds->fdo, SET_PDU_FORMAT); - if (w_ret) - { + if (w_ret) { + free(send_sms_cmd); + free(write_pdu_cmd); return w_ret; } - r_ret = tty_read_keyword(fds->fdi, NULL, COMMON_BUF_SIZE, "OK",profile->timeout); - if (r_ret) - { - dbg_msg("Error setting PDU format , error code: %d", r_ret); - if (r_ret == COMM_ERROR) - return r_ret; + + r_ret = tty_read_keyword(fds->fdi, NULL, "OK", profile); + if (r_ret) { + dbg_msg("Error setting PDU format, error code: %d", r_ret); + free(send_sms_cmd); + free(write_pdu_cmd); + if (message.message) free(message.message); + return r_ret; } dbg_msg("Set PDU format success"); - send_sms_cmd = (char *)malloc(32); - write_pdu_cmd = (char *)malloc(256); + if (message.message) free(message.message); + snprintf(send_sms_cmd, 32, SEND_SMS, pdu_expected_len); - dbg_msg("Send SMS command: %s", send_sms_cmd); snprintf(write_pdu_cmd, 256, "%s%c", profile->sms_pdu, 0x1A); + + dbg_msg("Send SMS command: %s", send_sms_cmd); dbg_msg("Write PDU command: %s", write_pdu_cmd); + w_ret = tty_write(fds->fdo, send_sms_cmd); - if (w_ret) - { + if (w_ret) { + free(send_sms_cmd); + free(write_pdu_cmd); return w_ret; } - r_ret = tty_read_keyword(fds->fdi, NULL, COMMON_BUF_SIZE, ">",profile->timeout); - if (r_ret) - { + + r_ret = tty_read_keyword(fds->fdi, NULL, ">", profile); + if (r_ret) { dbg_msg("Error sending SMS STEP 1, error code: %d", r_ret); - if (r_ret == COMM_ERROR) - return COMM_ERROR; + free(send_sms_cmd); + free(write_pdu_cmd); + if (message.message) free(message.message); + return r_ret; } + if (message.message) free(message.message); + usleep(10000); w_ret = tty_write(fds->fdo, write_pdu_cmd); - if (w_ret) - { + if (w_ret) { + free(send_sms_cmd); + free(write_pdu_cmd); return w_ret; } - r_ret = tty_read_keyword(fds->fdi, NULL, COMMON_BUF_SIZE, "+CMGS:",profile->timeout); - if (r_ret) - { + + r_ret = tty_read_keyword(fds->fdi, &message, "+CMGS:", profile); + if (r_ret) { dbg_msg("Error sending SMS STEP 2, error code: %d", r_ret); - if (r_ret == COMM_ERROR) - return COMM_ERROR; + free(send_sms_cmd); + free(write_pdu_cmd); + if (message.message) free(message.message); + return r_ret; } + if (message.message) free(message.message); free(send_sms_cmd); free(write_pdu_cmd); - - return 0; + return SUCCESS; } diff --git a/application/tom_modem/src/operations.h b/application/tom_modem/src/operations.h index b9013b0..157428e 100644 --- a/application/tom_modem/src/operations.h +++ b/application/tom_modem/src/operations.h @@ -5,8 +5,8 @@ #include "utils.h" int str_to_hex(char *str, char *hex); int tty_open_device(PROFILE_T *profile, FDS_T *fds); -int tty_read(FILE *fdi, char *output, int len, int soft_timeout); -int tty_read_keyword(FILE *fdi, char *output, int len, char *key_word, int soft_timeout); +int tty_read(FILE *fdi, AT_MESSAGE_T *message, PROFILE_T *profile); +int tty_read_keyword(FILE *fdi, AT_MESSAGE_T *message, char *key_word, PROFILE_T *profile); int tty_write_raw(FILE *fdo, char *input); int tty_write(FILE *fdo, char *input); #endif diff --git a/application/tom_modem/src/ttydevice.c b/application/tom_modem/src/ttydevice.c index 9d06160..be52739 100644 --- a/application/tom_modem/src/ttydevice.c +++ b/application/tom_modem/src/ttydevice.c @@ -128,76 +128,84 @@ int tty_open_device(PROFILE_T *profile,FDS_T *fds) return SUCCESS; } -int tty_read(FILE *fdi, char *output, int len, int soft_timeout) -{ - return tty_read_keyword(fdi, output, len, NULL, soft_timeout); +int tty_read(FILE *fdi, AT_MESSAGE_T *message, PROFILE_T *profile) { + return tty_read_keyword(fdi, message, NULL, profile); } -int tty_read_keyword(FILE *fdi, char *output, int len, char *key_word, int soft_timeout) -{ +int tty_read_keyword(FILE *fdi, AT_MESSAGE_T *message, char *key_word, PROFILE_T *profile) { char tmp[LINE_BUF] = {0}; - int msg_len = 0; + char *dynamic_buffer = NULL; + int buffer_size = 0; int read_flag = 0; time_t start_time = time(NULL); int exitcode = TIMEOUT_WAITING_NEWLINE; - while (difftime(time(NULL), start_time) < soft_timeout) - { + + while (difftime(time(NULL), start_time) < profile->timeout) { memset(tmp, 0, LINE_BUF); - if (fgets(tmp, LINE_BUF, fdi)) - { + if (fgets(tmp, LINE_BUF, fdi)) { read_flag = 1; dbg_msg("%s", tmp); - if (msg_len + strlen(tmp) >= len) - { - err_msg("Error: output buffer is too small"); - exitcode = BUFFER_OVERFLOW; - break; + if (profile->greedy_read && strlen(tmp) > 0) { + start_time = time(NULL); + } + if (message != NULL) { + int tmp_len = strlen(tmp); + char *new_buffer = realloc(dynamic_buffer, buffer_size + tmp_len + 1); + if (!new_buffer) { + free(dynamic_buffer); + err_msg("Error: memory allocation failed"); + exitcode = BUFFER_OVERFLOW; + break; + } + dynamic_buffer = new_buffer; + memcpy(dynamic_buffer + buffer_size, tmp, tmp_len); + buffer_size += tmp_len; + dynamic_buffer[buffer_size] = '\0'; } - if (output != NULL) - msg_len += snprintf(output + msg_len, len - msg_len, "%s", tmp); if (strncmp(tmp, "OK", 2) == 0 || strncmp(tmp, "ERROR", 5) == 0 || strncmp(tmp, "+CMS ERROR:", 11) == 0 || strncmp(tmp, "+CME ERROR:", 11) == 0 || strncmp(tmp, "NO CARRIER", 10) == 0 || - (key_word != NULL && strncmp(tmp, key_word, strlen(key_word)) == 0)) - { - if (key_word != NULL && strncmp(tmp, key_word, strlen(key_word)) == 0) - { - dbg_msg("keyword found"); - exitcode = SUCCESS; - } - else if (key_word == NULL) - { - exitcode = SUCCESS; - } - else - { - exitcode = KEYWORD_NOT_MATCH; - } - break; + (key_word != NULL && strncmp(tmp, key_word, strlen(key_word)) == 0)) { + if (key_word != NULL && strncmp(tmp, key_word, strlen(key_word)) == 0) { + dbg_msg("keyword found"); + exitcode = SUCCESS; + } else if (key_word == NULL) { + exitcode = SUCCESS; + } else { + exitcode = KEYWORD_NOT_MATCH; } + break; + } } #ifdef EARLY_RETURN - else - { - if (read_flag > 500){ + else { + if (read_flag > 500) { dbg_msg("early return"); exitcode = TIMEOUT_WAITING_NEWLINE; break; } - if (read_flag){ + if (read_flag) { read_flag++; } } #endif usleep(5000); } - if (read_flag == 0) - { + + if (read_flag == 0) { exitcode = COMM_ERROR; } + + if (message != NULL) { + message->message = dynamic_buffer; + message->len = buffer_size; + } else { + free(dynamic_buffer); + } + return exitcode; } diff --git a/application/tom_modem/src/utils.c b/application/tom_modem/src/utils.c index 8428e6e..0e0ae9e 100644 --- a/application/tom_modem/src/utils.c +++ b/application/tom_modem/src/utils.c @@ -204,6 +204,8 @@ int match_option(char *option_name) return SMS_PDU; case SMS_INDEX_S: return SMS_INDEX; + case GREEDY_READ_S: + return GREEDY_READ; default: return -1; } @@ -259,6 +261,10 @@ int match_option(char *option_name) { return SMS_INDEX; } + else if (strcmp(long_option, GREEDY_READ_L) == 0) + { + return GREEDY_READ; + } else { return -1; @@ -389,11 +395,12 @@ int usage(char* name) err_msg(" -d, --tty_dev TTY device **REQUIRED**"); err_msg(" -b, --baud_rate Baud rate Default: 115200 Supported: 4800,9600,19200,38400,57600,115200"); err_msg(" -B, --data_bits Data bits Default: 8 Supported: 5,6,7,8"); - err_msg(" -t, --timeout Timeout Default: 3"); + err_msg(" -t, --timeout Default: 3 Timeout in seconds, if output is more than timeout, it will be ignored unless -g option is set"); err_msg(" -o, --operation Operation(at[a:defualt],binary_at[b], sms_read[r], sms_send[s], sms_delete[d])"); err_msg(" -D, --debug Debug mode Default: off"); err_msg(" -p, --sms_pdu SMS PDU"); err_msg(" -i, --sms_index SMS index"); + err_msg(" -g, --greedy_read Default: off, Greedy read mode, if set, each round it get new data from tty device, it will reset the timeout"); #ifdef USE_SEMAPHORE err_msg(" -C, --cleanup Semaphore cleanup"); #endif @@ -440,6 +447,7 @@ void dump_profile() dbg_msg("Debug: %d", s_profile.debug); dbg_msg("SMS PDU: %s", s_profile.sms_pdu); dbg_msg("SMS index: %d", s_profile.sms_index); + dbg_msg("Greedy read: %d", s_profile.greedy_read); } int display_sms_in_json(SMS_T **sms,int num) { diff --git a/application/tom_modem/src/utils.h b/application/tom_modem/src/utils.h index 6a48cab..38e6bec 100644 --- a/application/tom_modem/src/utils.h +++ b/application/tom_modem/src/utils.h @@ -75,9 +75,9 @@ int match_operation(char *operation_name); int decode_pdu(SMS_T *sms); -int tty_read_keyword(FILE *fdi, char *output, int len, char *key_word, int soft_timeout); +int tty_read(FILE *fdi, AT_MESSAGE_T *message, PROFILE_T *profile); -int tty_read(FILE *fdi, char *output, int len, int soft_timeout); +int tty_read_keyword(FILE *fdi, AT_MESSAGE_T *message, char *key_word, PROFILE_T *profile); int dump_sms(SMS_T *sms);