fix some bug

This commit is contained in:
fujr 2024-11-06 15:33:23 +08:00
parent b0a2131a10
commit 6e8abbf34c
17 changed files with 693 additions and 651 deletions

View File

@ -2,8 +2,8 @@ include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:= tom_modem PKG_NAME:= tom_modem
PKG_RELEASE:=beta-1 PKG_RELEASE:=beta-2
PKG_VERSION:=0.9.1 PKG_VERSION:=0.9.2
include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/package.mk
@ -13,6 +13,12 @@ define Package/$(PKG_NAME)
TITLE:=Fujr Modem Communite Tool TITLE:=Fujr Modem Communite Tool
endef endef
define Package/$(PKG_NAME)/config
config PACKAGE_$(PKG_NAME)_EARLY_RETURN
bool "Early return"
default y
endef
define Package/$(PKG_NAME)/description define Package/$(PKG_NAME)/description
Modem Communite Tool for 5G modem (By Fujr) Modem Communite Tool for 5G modem (By Fujr)
endef endef
@ -23,6 +29,9 @@ define Build/Prepare
endef endef
define Build/Compile define Build/Compile
ifdef CONFIG_PACKAGE_$(PKG_NAME)_EARLY_RETURN
TARGET_CFLAGS+=-DEARLY_RETURN
else
$(MAKE) -C $(PKG_BUILD_DIR) \ $(MAKE) -C $(PKG_BUILD_DIR) \
$(TARGET_CONFIGURE_OPTS) CFLAGS="$(TARGET_CFLAGS)" $(TARGET_CONFIGURE_OPTS) CFLAGS="$(TARGET_CFLAGS)"
endef endef

View File

@ -1,8 +1,8 @@
TARGET = tom_modem TARGET = tom_modem
CFLAGS = -Wall -Ipdu_lib CFLAGS ?= -Wall -Iextlib
SRCS = main.c utils.c pdu_lib/pdu.c pdu_lib/ucs2_to_utf8.c SRCS = main.c utils.c extlib/pdu.c extlib/ucs2_to_utf8.c
OBJS = $(SRCS:.c=.o) OBJS = $(SRCS:.c=.o)
@ -19,6 +19,8 @@ clean:
.PHONY:clean .PHONY:clean
clean: clean:
rm -rf *.o *.*~ *~ *.swap $(all) rm -rf *.o *.*~ *~ *.swap $(all)
rm -rf $(TARGET)
rm -rf extlib/*.o
depend: depend:
$(CC) $(CFLAGS) -MM $(SRCS) > .depend $(CC) $(CFLAGS) -MM $(SRCS) > .depend

View File

@ -1,27 +1,8 @@
#include "modem_types.h"
#include "main.h" #include "main.h"
#include "utils.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <termios.h>
#include <signal.h>
#include <sys/select.h>
#include <errno.h>
FILE *fdi; // file descriptor for input
FILE *fdo; // file descriptor for output
int tty_fd; // file descriptor for tty device
FDS_T s_fds;
PROFILE_T s_profile; // global profile PROFILE_T s_profile; // global profile
char *self_name; // program name
void _timeout(int signo)
{
err_msg("Exit with Signal %d", signo);
kill(getpid(), SIGINT);
}
int parse_user_input(int argc, char *argv[], PROFILE_T *profile) int parse_user_input(int argc, char *argv[], PROFILE_T *profile)
{ {
@ -34,8 +15,8 @@ int parse_user_input(int argc, char *argv[], PROFILE_T *profile)
option = match_option(argv[opt]); option = match_option(argv[opt]);
if (option == -1) if (option == -1)
{ {
usage(); usage(argv[0]);
return -1; return INVALID_PARAM;
} }
opt++; opt++;
switch (option) switch (option)
@ -43,72 +24,72 @@ int parse_user_input(int argc, char *argv[], PROFILE_T *profile)
case AT_CMD: case AT_CMD:
if (!has_more_argv()) if (!has_more_argv())
{ {
usage(); usage(argv[0]);
return -1; return INVALID_PARAM;
} }
profile->at_cmd = argv[opt++]; profile->at_cmd = argv[opt++];
break; break;
case TTY_DEV: case TTY_DEV:
if (!has_more_argv()) if (!has_more_argv())
{ {
usage(); usage(argv[0]);
return -1; return INVALID_PARAM;
} }
profile->tty_dev = argv[opt++]; profile->tty_dev = argv[opt++];
break; break;
case BAUD_RATE: case BAUD_RATE:
if (!has_more_argv()) if (!has_more_argv())
{ {
usage(); usage(argv[0]);
return -1; return INVALID_PARAM;
} }
profile->baud_rate = atoi(argv[opt++]); profile->baud_rate = atoi(argv[opt++]);
break; break;
case DATA_BITS: case DATA_BITS:
if (!has_more_argv()) if (!has_more_argv())
{ {
usage(); usage(argv[0]);
return -1; return INVALID_PARAM;
} }
profile->data_bits = atoi(argv[opt++]); profile->data_bits = atoi(argv[opt++]);
break; break;
case PARITY: case PARITY:
if (!has_more_argv()) if (!has_more_argv())
{ {
usage(); usage(argv[0]);
return -1; return INVALID_PARAM;
} }
profile->parity = argv[opt++]; profile->parity = argv[opt++];
break; break;
case STOP_BITS: case STOP_BITS:
if (!has_more_argv()) if (!has_more_argv())
{ {
usage(); usage(argv[0]);
return -1; return INVALID_PARAM;
} }
profile->stop_bits = atoi(argv[opt++]); profile->stop_bits = atoi(argv[opt++]);
break; break;
case FLOW_CONTROL: case FLOW_CONTROL:
if (!has_more_argv()) if (!has_more_argv())
{ {
usage(); usage(argv[0]);
return -1; return INVALID_PARAM;
} }
profile->flow_control = argv[opt++]; profile->flow_control = argv[opt++];
break; break;
case TIMEOUT: case TIMEOUT:
if (!has_more_argv()) if (!has_more_argv())
{ {
usage(); usage(argv[0]);
return -1; return INVALID_PARAM;
} }
profile->timeout = atoi(argv[opt++]); profile->timeout = atoi(argv[opt++]);
break; break;
case OPERATION: case OPERATION:
if (!has_more_argv()) if (!has_more_argv())
{ {
usage(); usage(argv[0]);
return -1; return INVALID_PARAM;
} }
profile->op = match_operation(argv[opt++]); profile->op = match_operation(argv[opt++]);
break; break;
@ -118,16 +99,16 @@ int parse_user_input(int argc, char *argv[], PROFILE_T *profile)
case SMS_PDU: case SMS_PDU:
if (!has_more_argv()) if (!has_more_argv())
{ {
usage(); usage(argv[0]);
return -1; return INVALID_PARAM;
} }
profile->sms_pdu = argv[opt++]; profile->sms_pdu = argv[opt++];
break; break;
case SMS_INDEX: case SMS_INDEX:
if (!has_more_argv()) if (!has_more_argv())
{ {
usage(); usage(argv[0]);
return -1; return INVALID_PARAM;
} }
profile->sms_index = atoi(argv[opt++]); profile->sms_index = atoi(argv[opt++]);
break; break;
@ -153,53 +134,57 @@ int parse_user_input(int argc, char *argv[], PROFILE_T *profile)
{ {
profile->op = AT_OP; profile->op = AT_OP;
} }
return SUCCESS;
} }
int run_op(PROFILE_T *profile,FDS_T *fds)
int run_op(PROFILE_T *profile)
{ {
switch (profile->op) switch (profile->op)
{ {
case AT_OP: case AT_OP:
at(profile); return at(profile,fds);
break;
case SMS_READ_OP: case SMS_READ_OP:
sms_read(profile); return sms_read(profile,fds);
break;
case SMS_SEND_OP: case SMS_SEND_OP:
sms_send(profile); return sms_send(profile,fds);
break;
case SMS_DELETE_OP: case SMS_DELETE_OP:
sms_delete(profile); return sms_delete(profile,fds);
break;
default: default:
err_msg("Invalid operation"); err_msg("Invalid operation");
break;
} }
return UNKNOWN_ERROR;
}
static void clean_up()
{
if (tcsetattr(s_fds.tty_fd, TCSANOW, &s_fds.old_termios) != 0)
{
err_msg("Error restoring old tty attributes");
return;
}
dbg_msg("Clean up success");
tcflush(s_fds.tty_fd, TCIOFLUSH);
if (s_fds.tty_fd >= 0)
close(s_fds.tty_fd);
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int ret;
// init
self_name = argv[0];
PROFILE_T *profile = &s_profile; PROFILE_T *profile = &s_profile;
FDS_T *fds = &s_fds;
parse_user_input(argc, argv, profile); parse_user_input(argc, argv, profile);
dump_profile(); dump_profile();
signal(SIGALRM, _timeout);
// try open tty devices // try open tty devices
if (open_tty_device(profile)) if (tty_open_device(profile,fds))
{ {
err_msg("Failed to open tty device"); err_msg("Failed to open tty device");
return -1; return COMM_ERROR;
} }
if (run_op(profile)) atexit(clean_up);
if (run_op(profile,fds))
{ {
err_msg("Failed to run operation %d", profile->op); err_msg("Failed to run operation %d", profile->op);
return -1; kill(getpid(), SIGINT);
} }
dbg_msg("Exit"); dbg_msg("Exit");
return 0; return SUCCESS;
} }

View File

@ -1,7 +1,5 @@
#ifndef _MAIN_H_ #ifndef _MAIN_H_
#define _MAIN_H_ #define _MAIN_H_
#include "modem_types.h"
#include "main.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
@ -11,23 +9,24 @@
#include <signal.h> #include <signal.h>
#include <sys/select.h> #include <sys/select.h>
#include <errno.h> #include <errno.h>
#include "operations.h"
#include "ttydevice.h"
#include "modem_types.h"
#include "utils.h"
#define DEFAULT_TIMEOUT 3 #define DEFAULT_TIMEOUT 3
// //
extern FILE *fdi; // file descriptor for input
extern FILE *fdo; // file descriptor for output
extern int tty_fd; // file descriptor for tty device
extern PROFILE_T s_profile; // global profile extern PROFILE_T s_profile; // global profile
extern char *self_name; // program name
extern struct termios oldtio; // old tty setting
extern int at(PROFILE_T *profile);
extern int sms_read(PROFILE_T *profile); extern int at(PROFILE_T *profile,FDS_T *fds);
extern int sms_send(PROFILE_T *profile); extern int sms_read(PROFILE_T *profile,FDS_T *fds);
extern int sms_delete(PROFILE_T *profile); extern int sms_send(PROFILE_T *profile,FDS_T *fds);
extern int sms_delete(PROFILE_T *profile,FDS_T *fds);
extern void dump_profile(); extern void dump_profile();
@ -35,8 +34,8 @@ extern int match_option(char *option_name);
extern int match_operation(char *operation_name); extern int match_operation(char *operation_name);
extern int open_tty_device(PROFILE_T *profile); extern int open_tty_device(PROFILE_T *profile,FDS_T *fds);
extern int usage(); extern int usage(char* name);
#endif #endif

View File

@ -1,7 +1,9 @@
#ifndef _MODEM_TYPES_H_ #ifndef _MODEM_TYPES_H_
#define _MODEM_TYPES_H_ #define _MODEM_TYPES_H_
#include <stdio.h>
#include <termios.h>
#include <time.h>
//options //options
#define AT_CMD_S 'c' #define AT_CMD_S 'c'
#define TTY_DEV_S 'd' #define TTY_DEV_S 'd'
@ -80,12 +82,20 @@ typedef struct _PROFILE {
int sms_index; int sms_index;
} PROFILE_T; } PROFILE_T;
typedef struct _FDS {
int tty_fd;
struct termios old_termios;
FILE *fdi;
FILE *fdo;
} FDS_T;
typedef struct _SMS { typedef struct _SMS {
int sms_index; int sms_index;
int sms_lenght; int sms_lenght;
int ref_number; int ref_number;
int segment_number; int segment_number;
int timestamp; time_t timestamp;
int total_segments; int total_segments;
int type; int type;
char *sender; char *sender;
@ -93,6 +103,15 @@ typedef struct _SMS {
char *sms_pdu; char *sms_pdu;
} SMS_T; } SMS_T;
enum ERROR_CODES {
COMM_ERROR = -1,
SUCCESS = 0,
KEYWORD_NOT_MATCH,
TIMEOUT_WAITING_NEWLINE,
INVALID_PARAM,
UNKNOWN_ERROR,
};
enum SMS_CHARSET { enum SMS_CHARSET {
SMS_CHARSET_7BIT, SMS_CHARSET_7BIT,
SMS_CHARSET_UCS2 SMS_CHARSET_UCS2
@ -121,5 +140,5 @@ enum OPERATIONS {
SMS_DELETE_OP SMS_DELETE_OP
}; };
char *self_name; // program name
#endif #endif

View File

@ -0,0 +1,191 @@
#include "operations.h"
int at(PROFILE_T *profile,FDS_T *fds)
{
int w_ret,r_ret;
char output[COMMON_BUF_SIZE] = {0};
if (profile->at_cmd == NULL)
{
err_msg("AT command is empty");
return INVALID_PARAM;
}
w_ret = tty_write(fds->fdo, profile->at_cmd);
if (w_ret)
{
return w_ret;
}
r_ret = tty_read(fds->fdi, output, COMMON_BUF_SIZE,profile->timeout);
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);
return SUCCESS;
}
int sms_delete(PROFILE_T *profile,FDS_T *fds)
{
int w_ret,r_ret;
if (profile->sms_index < 0)
{
err_msg("SMS index is empty");
return INVALID_PARAM;
}
char *delete_sms_cmd;
delete_sms_cmd = (char *)malloc(32);
snprintf(delete_sms_cmd, 32, DELETE_SMS, profile->sms_index);
w_ret = tty_write(fds->fdo, delete_sms_cmd);
if (w_ret)
{
return w_ret;
}
r_ret = tty_read_keyword(fds->fdi, NULL, COMMON_BUF_SIZE, "OK",profile->timeout);
if (r_ret)
{
dbg_msg("Error deleting SMS, error code: %d", r_ret);
if (r_ret == COMM_ERROR)
return COMM_ERROR;
}
return SUCCESS;
}
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};
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);
if (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);
if (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");
destroy_sms(sms);
}
}
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]);
// }
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)
{
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;
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);
if (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");
send_sms_cmd = (char *)malloc(32);
write_pdu_cmd = (char *)malloc(256);
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("Write PDU command: %s", write_pdu_cmd);
w_ret = tty_write(fds->fdo, send_sms_cmd);
if (w_ret)
{
return w_ret;
}
r_ret = tty_read_keyword(fds->fdi, NULL, COMMON_BUF_SIZE, ">",profile->timeout);
if (r_ret)
{
dbg_msg("Error sending SMS STEP 1, error code: %d", r_ret);
if (r_ret == COMM_ERROR)
return COMM_ERROR;
}
usleep(10000);
w_ret = tty_write(fds->fdo, write_pdu_cmd);
if (w_ret)
{
return w_ret;
}
r_ret = tty_read_keyword(fds->fdi, NULL, COMMON_BUF_SIZE, "+CMGS:",profile->timeout);
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);
return 0;
}

View File

@ -0,0 +1,10 @@
#ifndef OPERATION_H
#define OPERATION_H
#include "modem_types.h"
#include "ttydevice.h"
#include "utils.h"
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_write(FILE *fdo, char *input);
#endif

View File

@ -1,21 +0,0 @@
ALL: pdu_decoder
#CROSS_COMPILE=mips-openwrt-linux-
#CC = $(CROSS_COMPILE)gcc
#CFLAGS = -O2
pdu.o:
$(CC) $(CFLAGS) -c pdu.c
pdu_decoder.o:
$(CC) $(CFLAGS) -c pdu_decoder.c
ucs2_to_utf8:
$(CC) $(CFLAGS) -c ucs2_to_utf8.c
pdu_decoder: pdu.o pdu_decoder.o ucs2_to_utf8
$(CC) $(CFLAGS) ucs2_to_utf8.o pdu.o pdu_decoder.o -o pdu_decoder
clean:
rm -f *.o pdu_decoder
test: clean ALL
echo "0891683108501405F8240BA10156686616F60008414090912385235C6D4191CF6C4752A860015BC67801FF1A00350030003900360036FF0C4EB2FF0C8BB05F9762BD59566BCF592990FD8981676554E6FF0C611F89C9597D76848BDD63A883507ED960A87684670B53CBFF019884795D60A84E2D5956FF01"|./pdu_decoder
echo "0891683108501405F8640BA10156686616F6000841400100957423830608048A3002026B21767B5F556D4191CF6C475373900100356D4191CF5E01FF0853EF63620035004D6D4191CFFF09FF0C731B623394FE63A5FF1A0068007400740070003A002F002F007300680061006B0065002E00730064002E006300680069006E0061006D006F00620069006C0065002E0063006F006D30025C714E1C79FB52A8"|./pdu_decoder

View File

@ -0,0 +1,210 @@
#include "ttydevice.h"
static int tty_set_device(PROFILE_T *profile, FDS_T *fds)
{
int baud_rate, data_bits;
struct termios tty;
baud_rate = profile->baud_rate;
data_bits = profile->data_bits;
if (tcgetattr(fds->tty_fd, &tty) != 0)
{
err_msg("Error getting tty attributes");
return COMM_ERROR;
}
memmove(&fds->old_termios, &tty, sizeof(struct termios));
cfmakeraw(&tty);
tty.c_cflag |= CLOCAL; // 忽略调制解调器控制线,允许本地连接
tty.c_cflag |= CREAD; // 使能接收
// clear flow control ,stop bits parity
tty.c_cflag &= ~CRTSCTS;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~PARENB;
tty.c_oflag &= ~OPOST;
tty.c_cc[VMIN] = 0;
tty.c_cc[VTIME] = 1;
// set data bits 5,6,7,8
tty.c_cflag &= ~CSIZE; // 清除数据位设置
switch (data_bits)
{
case 5:
tty.c_cflag |= CS5;
break;
case 6:
tty.c_cflag |= CS6;
break;
case 7:
tty.c_cflag |= CS7;
break;
case 8:
tty.c_cflag |= CS8;
break;
default:
tty.c_cflag |= CS8;
break;
}
// set baud rate
switch (baud_rate)
{
case 4800:
cfsetspeed(&tty, B4800);
break;
case 9600:
cfsetspeed(&tty, B9600);
break;
case 19200:
cfsetspeed(&tty, B19200);
break;
case 38400:
cfsetspeed(&tty, B38400);
break;
case 57600:
cfsetspeed(&tty, B57600);
break;
case 115200:
cfsetspeed(&tty, B115200);
break;
default:
cfsetspeed(&tty, B115200);
break;
}
if (tcsetattr(fds->tty_fd, TCSANOW, &tty) != 0)
{
err_msg("Error setting tty attributes");
return COMM_ERROR;
}
return SUCCESS;
}
int tty_open_device(PROFILE_T *profile,FDS_T *fds)
{
fds->tty_fd = open(profile->tty_dev, O_RDWR | O_NOCTTY);
if (fds->tty_fd < 0)
{
err_msg("Error opening tty device: %s", profile->tty_dev);
return COMM_ERROR;
}
if (tty_set_device(profile,fds) != 0)
{
err_msg("Error setting tty device");
return COMM_ERROR;
}
tcflush(fds->tty_fd, TCIOFLUSH);
if (fds->tty_fd >= 0)
close(fds->tty_fd);
else
return COMM_ERROR;
fds->tty_fd = open(profile->tty_dev, O_RDWR | O_NOCTTY | O_NONBLOCK);
fds->fdi = fdopen(fds->tty_fd, "r");
fds->fdo = fdopen(fds->tty_fd, "w");
if (fds->fdi == NULL || fds->fdo == NULL)
{
err_msg("Error opening file descriptor");
return COMM_ERROR;
}
if (setvbuf(fds->fdo , NULL, _IOFBF, 0))
{
err_msg("Error setting buffer for fdi");
return COMM_ERROR;
}
if (setvbuf(fds->fdi , NULL, _IOLBF, 0))
{
err_msg("Error setting buffer for fdi");
return COMM_ERROR;
}
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_keyword(FILE *fdi, char *output, int len, char *key_word, int soft_timeout)
{
char tmp[LINE_BUF] = {0};
int msg_len = 0;
int read_flag = 0;
time_t start_time = time(NULL);
int exitcode = TIMEOUT_WAITING_NEWLINE;
while (difftime(time(NULL), start_time) < soft_timeout)
{
if (fgets(tmp, LINE_BUF, fdi))
{
read_flag = 1;
dbg_msg("%s", tmp);
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;
}
}
#ifdef EARLY_RETURN
else
{
if (read_flag > 500){
dbg_msg("early return");
exitcode = TIMEOUT_WAITING_NEWLINE;
break;
}
if (read_flag){
read_flag++;
}
}
#endif
usleep(1000);
}
if (read_flag == 0)
{
exitcode = COMM_ERROR;
}
return exitcode;
}
int tty_write(FILE *fdo, char *input)
{
int cmd_len, ret;
char *cmd_line;
cmd_len = strlen(input) + 3;
cmd_line = (char *)malloc(cmd_len);
if (cmd_line == NULL)
{
err_msg("Error allocating memory");
return COMM_ERROR;
}
snprintf(cmd_line, cmd_len, "%s\r\n", input);
ret = fputs(cmd_line, fdo);
free(cmd_line);
fflush(fdo);
usleep(100);
if (ret < 0)
{
err_msg("Error writing to tty %d" , ret);
return COMM_ERROR;
}
return SUCCESS;
}

View File

@ -0,0 +1,6 @@
#ifndef TTYDEVICE_H
#define TTYDEVICE_H
#include "modem_types.h"
#include "utils.h"
int tty_open_device(PROFILE_T *profile,FDS_T *fds);
#endif

View File

@ -1,7 +1,133 @@
#include "utils.h" #include "utils.h"
#include "pdu_lib/pdu.h"
struct termios oldtio;
static int char_to_hex(char c)
{
// convert char to hex
int is_digit, is_lower, is_upper;
is_digit = c - '0';
is_lower = c - 'a' + 10;
is_upper = c - 'A' + 10;
if (is_digit >= 0 && is_digit <= 9)
{
return is_digit;
}
else if (is_lower >= 10 && is_lower <= 15)
{
return is_lower;
}
else if (is_upper >= 10 && is_upper <= 15)
{
return is_upper;
}
else
{
return -1;
}
}
int decode_pdu(SMS_T *sms)
{
char sms_text[SMS_TEXT_SIZE] = {0};
int tp_dcs;
int skip_bytes;
int pdu_str_len;
unsigned char hex_pdu[SMS_PDU_HEX_SIZE] = {0};
pdu_str_len = strlen(sms->sms_pdu);
for (int i = 0; i < pdu_str_len; i += 2)
{
hex_pdu[i / 2] = char_to_hex(sms->sms_pdu[i]) << 4;
hex_pdu[i / 2] |= char_to_hex(sms->sms_pdu[i + 1]);
}
int sms_len = pdu_decode(hex_pdu, pdu_str_len/2,
&sms->timestamp,
sms->sender, PHONE_NUMBER_SIZE,
sms_text, SMS_TEXT_SIZE,
&tp_dcs,
&sms->ref_number,
&sms->total_segments,
&sms->segment_number,
&skip_bytes);
if (sms_len <= 0)
{
err_msg("Error decoding pdu");
return sms_len;
}
sms->sms_lenght = sms_len;
switch ((tp_dcs / 4) % 4)
{
case 0:
{
// GSM 7 bit
sms->type = SMS_CHARSET_7BIT;
int i;
i = skip_bytes;
if (skip_bytes > 0)
i = (skip_bytes * 8 + 6) / 7;
for (; i < strlen(sms_text); i++)
{
sprintf(sms->sms_text + i, "%c", sms_text[i]);
}
i++;
sprintf(sms->sms_text + i, "%c", '\0');
break;
}
case 2:
{
// UCS2
sms->type = SMS_CHARSET_UCS2;
int offset = 0;
for (int i = skip_bytes; i < SMS_TEXT_SIZE; i += 2)
{
int ucs2_char = 0x000000FF & sms_text[i + 1];
ucs2_char |= (0x0000FF00 & (sms_text[i] << 8));
unsigned char utf8_char[5];
int len = ucs2_to_utf8(ucs2_char, utf8_char);
int j;
for (j = 0; j < len; j++)
{
sprintf(sms->sms_text + offset, "%c", utf8_char[j]);
if (utf8_char[j] != '\0')
{
offset++;
}
}
}
offset++;
sprintf(sms->sms_text + offset, "%c", '\0');
break;
}
default:
break;
}
return sms_len;
}
int destroy_sms(SMS_T *sms)
{
if (sms->sms_pdu != NULL)
{
free(sms->sms_pdu);
}
if (sms->sender != NULL)
{
free(sms->sender);
}
if (sms->sms_text != NULL)
{
free(sms->sms_text);
}
free(sms);
return SUCCESS;
}
int dump_sms(SMS_T *sms)
{
dbg_msg("SMS Index: %d", sms->sms_index);
dbg_msg("SMS Text: %s", sms->sms_text);
dbg_msg("SMS Sender: %s", sms->sender);
dbg_msg("SMS Timestamp: %ld", sms->timestamp);
dbg_msg("SMS Segment: %d/%d", sms->segment_number, sms->total_segments);
return SUCCESS;
}
int match_option(char *option_name) int match_option(char *option_name)
{ {
char short_option; char short_option;
@ -100,7 +226,6 @@ int match_option(char *option_name)
// if start with '--' then it is a long option // if start with '--' then it is a long option
return -1; return -1;
} }
int match_operation(char *operation_name) int match_operation(char *operation_name)
{ {
@ -120,7 +245,7 @@ int match_operation(char *operation_name)
case SMS_DELETE_OP_S: case SMS_DELETE_OP_S:
return SMS_DELETE_OP; return SMS_DELETE_OP;
default: default:
return -1; return INVALID_PARAM;
break; break;
} }
} }
@ -144,174 +269,12 @@ int match_operation(char *operation_name)
} }
else else
{ {
return -1; return INVALID_PARAM;
} }
} }
return SUCCESS;
} }
void escape_json(char *input, char *output)
int open_tty_device(PROFILE_T *profile)
{
tty_fd = open(profile->tty_dev, O_RDWR | O_NOCTTY);
if (tty_fd < 0)
{
err_msg("Error opening tty device: %s", profile->tty_dev);
return -1;
}
if (set_tty_device(profile) != 0)
{
err_msg("Error setting tty device");
return -1;
}
tcflush(tty_fd, TCIOFLUSH);
atexit(clean_up);
if (tty_fd >= 0)
close(tty_fd);
tty_fd = open(profile->tty_dev, O_RDWR | O_NOCTTY);
fdi = fdopen(tty_fd, "r");
fdo = fdopen(tty_fd, "w");
if (fdi == NULL || fdo == NULL)
{
err_msg("Error opening file descriptor");
return -1;
}
if (setvbuf(fdo, NULL, _IOFBF, 0))
{
err_msg("Error setting buffer for fdi");
return -1;
}
if (setvbuf(fdi, NULL, _IOLBF, 0))
{
err_msg("Error setting buffer for fdi");
return -1;
}
return 0;
}
static int set_tty_device(PROFILE_T *profile)
{
int baud_rate, data_bits, stop_bits;
char *flow_control;
struct termios tty;
baud_rate = profile->baud_rate;
data_bits = profile->data_bits;
stop_bits = profile->stop_bits;
flow_control = profile->flow_control;
if (tcgetattr(tty_fd, &tty) != 0)
{
err_msg("Error getting tty attributes");
return -1;
}
memmove(&oldtio, &tty, sizeof(struct termios));
cfmakeraw(&tty);
tty.c_cflag |= CLOCAL; // 忽略调制解调器控制线,允许本地连接
tty.c_cflag |= CREAD; // 使能接收
// clear flow control ,stop bits parity
tty.c_cflag &= ~CRTSCTS;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~PARENB;
tty.c_oflag &= ~OPOST;
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
// set data bits 5,6,7,8
tty.c_cflag &= ~CSIZE; // 清除数据位设置
switch (data_bits)
{
case 5:
tty.c_cflag |= CS5;
break;
case 6:
tty.c_cflag |= CS6;
break;
case 7:
tty.c_cflag |= CS7;
break;
case 8:
tty.c_cflag |= CS8;
break;
default:
tty.c_cflag |= CS8;
break;
}
// set baud rate
switch (baud_rate)
{
case 4800:
cfsetspeed(&tty, B4800);
break;
case 9600:
cfsetspeed(&tty, B9600);
break;
case 19200:
cfsetspeed(&tty, B19200);
break;
case 38400:
cfsetspeed(&tty, B38400);
break;
case 57600:
cfsetspeed(&tty, B57600);
break;
case 115200:
cfsetspeed(&tty, B115200);
break;
default:
cfsetspeed(&tty, B115200);
break;
}
if (tcsetattr(tty_fd, TCSANOW, &tty) != 0)
{
err_msg("Error setting tty attributes");
return -1;
}
return 0;
}
int char_to_hex(char c)
{
// convert char to hex
int is_digit, is_lower, is_upper;
is_digit = c - '0';
is_lower = c - 'a' + 10;
is_upper = c - 'A' + 10;
if (is_digit >= 0 && is_digit <= 9)
{
return is_digit;
}
else if (is_lower >= 10 && is_lower <= 15)
{
return is_lower;
}
else if (is_upper >= 10 && is_upper <= 15)
{
return is_upper;
}
else
{
return -1;
}
}
static void clean_up()
{
if (tcsetattr(tty_fd, TCSANOW, &oldtio) != 0)
{
err_msg("Error restoring old tty attributes");
return;
}
dbg_msg("Clean up success");
tcflush(tty_fd, TCIOFLUSH);
// if (tty_fd >= 0)
// close(tty_fd);
}
static void escape_json(char *input, char *output)
{ {
char *p = input; char *p = input;
char *q = output; char *q = output;
@ -365,10 +328,9 @@ static void escape_json(char *input, char *output)
} }
*q = '\0'; *q = '\0';
} }
int usage(char* name)
int usage()
{ {
err_msg("Usage: %s [options]", self_name); err_msg("Usage: %s [options]", name);
err_msg("Options:"); err_msg("Options:");
err_msg(" -c, --at_cmd <AT command> AT command"); err_msg(" -c, --at_cmd <AT command> AT command");
err_msg(" -d, --tty_dev <TTY device> TTY device **REQUIRED**"); err_msg(" -d, --tty_dev <TTY device> TTY device **REQUIRED**");
@ -380,12 +342,11 @@ int usage()
err_msg(" -p, --sms_pdu <sms pdu> SMS PDU"); err_msg(" -p, --sms_pdu <sms pdu> SMS PDU");
err_msg(" -i, --sms_index <sms index> SMS index"); err_msg(" -i, --sms_index <sms index> SMS index");
err_msg("Example:"); err_msg("Example:");
err_msg(" %s -c ATI -d /dev/ttyUSB2 -b 115200 -B 8 -o at #advance at mode set bautrate and data bit", self_name); err_msg(" %s -c ATI -d /dev/ttyUSB2 -b 115200 -B 8 -o at #advance at mode set bautrate and data bit", name);
err_msg(" %s -c ATI -d /dev/ttyUSB2 # normal at mode", self_name); err_msg(" %s -c ATI -d /dev/ttyUSB2 # normal at mode", name);
err_msg(" %s -d /dev/mhi_DUN -o r # read sms", self_name); err_msg(" %s -d /dev/mhi_DUN -o r # read sms", name);
exit(-1); exit(-1);
} }
void dump_profile() void dump_profile()
{ {
dbg_msg("AT command: %s", s_profile.at_cmd); dbg_msg("AT command: %s", s_profile.at_cmd);
@ -401,332 +362,6 @@ void dump_profile()
dbg_msg("SMS PDU: %s", s_profile.sms_pdu); dbg_msg("SMS PDU: %s", s_profile.sms_pdu);
dbg_msg("SMS index: %d", s_profile.sms_index); dbg_msg("SMS index: %d", s_profile.sms_index);
} }
int tty_read(FILE *fdi, char *output, int len, int timeout)
{
return tty_read_keyword(fdi, output, len, timeout, NULL);
}
int tty_read_keyword(FILE *fdi, char *output, int len, int timeout, char *key_word)
{
int ret, fd;
fd_set rfds;
struct timeval tv;
char tmp[LINE_BUF] = {0};
int msg_len = 0;
int key_word_len = 0;
fd = fileno(fdi);
tv.tv_sec = 0;
tv.tv_usec = timeout;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
if (key_word != NULL)
{
key_word_len = strlen(key_word);
}
while (1)
{
ret = select(fd + 1, &rfds, NULL, NULL, &tv);
if (ret == -1)
{
if (errno == EINTR)
{
err_msg("Interrupted by signal");
return -1;
}
err_msg("Error in select");
return -1;
}
else
{
fgets(tmp, LINE_BUF, fdi);
if (output != NULL)
msg_len += snprintf(output + msg_len, len - msg_len, "%s", tmp);
dbg_msg("%s", tmp);
}
if (key_word != NULL){
if (strncmp(tmp, key_word, key_word_len) == 0)
{
dbg_msg("Received end sign: %s", tmp);
return 0;
}
}
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){
dbg_msg("Received end sign: %s", tmp);
if (key_word == NULL){
return 0;
}
break;
}
}
return -1;
}
int tty_write(FILE *fdo, char *input)
{
int cmd_len, ret;
char *cmd_line;
cmd_len = strlen(input) + 3;
cmd_line = (char *)malloc(cmd_len);
if (cmd_line == NULL)
{
err_msg("Error allocating memory");
return -1;
}
snprintf(cmd_line, cmd_len, "%s\r\n", input);
ret = fputs(cmd_line, fdo);
free(cmd_line);
fflush(fdo);
usleep(100);
if (ret < 0)
{
err_msg("Error writing to tty %d" , ret);
return -1;
}
return 0;
}
int at(PROFILE_T *profile)
{
char output[COMMON_BUF_SIZE] = {0};
if (profile->at_cmd == NULL)
{
err_msg("AT command is empty");
return -1;
}
alarm(profile->timeout);
if (tty_write(fdo, profile->at_cmd))
{
err_msg("Error writing to tty");
return -1;
}
if (tty_read(fdi, output, COMMON_BUF_SIZE, 100))
{
err_msg("Error reading from tty");
return -1;
}
user_msg("%s", output);
return 0;
}
int sms_read(PROFILE_T *profile)
{
SMS_T *sms_list[SMS_LIST_SIZE];
SMS_T *sms;
char sms_pdu[SMS_BUF_SIZE] = {0};
tty_write(fdo, SET_PDU_FORMAT);
alarm(profile->timeout);
if (tty_read_keyword(fdi, NULL, COMMON_BUF_SIZE, 100, "OK"))
{
err_msg("Error setting PDU format");
return -1;
}
dbg_msg("Set PDU format success");
tty_write(fdo, READ_ALL_SMS);
alarm(profile->timeout);
if (tty_read_keyword(fdi, sms_pdu, SMS_BUF_SIZE, 100, "OK"))
{
err_msg("Error reading SMS");
return -1;
}
alarm(0);
//遍历 sms_pdu 的每一行
char *line = strtok(sms_pdu, "\n");
int sms_count = 0;
while (line != NULL)
{
if (strncmp(line, "+CMGL:", 6) == 0)
{
//解析 line +CMGL: 2,1,,102 获取短信索引
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(sms);
if (sms_len > 0)
{
sms_list[sms_count] = sms;
sms_count++;
}
else
{
destroy_sms(sms);
}
}
line = strtok(NULL, "\n");
}
// for (int i = 1; i <= sms_count; i++)
// {
// dump_sms(sms_list[i]);
// //destroy_sms(sms_list[i]);
// }
display_sms_in_json(sms_list,sms_count);
dbg_msg("Read SMS success");
dbg_msg("%s", sms_pdu);
return 0;
}
int sms_send(PROFILE_T *profile)
{
if (profile->sms_pdu == NULL)
{
err_msg("SMS PDU is empty");
return -1;
}
int pdu_len = strlen(profile->sms_pdu);
int pdu_expected_len = (pdu_len) / 2 - 1;
char *send_sms_cmd;
char *write_pdu_cmd;
tty_write(fdo, SET_PDU_FORMAT);
alarm(profile->timeout);
if (tty_read_keyword(fdi, NULL, COMMON_BUF_SIZE, 100, "OK"))
{
err_msg("Error setting PDU format");
return -1;
}
dbg_msg("Set PDU format success");
send_sms_cmd = (char *)malloc(32);
write_pdu_cmd = (char *)malloc(256);
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("Write PDU command: %s", write_pdu_cmd);
free(send_sms_cmd);
free(write_pdu_cmd);
alarm(0);
tty_write(fdo, send_sms_cmd);
usleep(10000);
tty_write(fdo, write_pdu_cmd);
alarm(profile->timeout);
if (tty_read_keyword(fdi, NULL, COMMON_BUF_SIZE, 100, "+CMGS:"))
{
err_msg("Error sending SMS STEP 2");
return -1;
}
return 0;
}
int sms_delete(PROFILE_T *profile)
{
if (profile->sms_index < 0)
{
err_msg("SMS index is empty");
return -1;
}
char *delete_sms_cmd;
delete_sms_cmd = (char *)malloc(32);
snprintf(delete_sms_cmd, 32, DELETE_SMS, profile->sms_index);
tty_write(fdo, delete_sms_cmd);
alarm(profile->timeout);
if (tty_read_keyword(fdi, NULL, COMMON_BUF_SIZE, 100, "OK"))
{
err_msg("Error deleting SMS");
return -1;
}
return 0;
}
int decode(SMS_T *sms)
{
char sms_text[SMS_TEXT_SIZE] = {0};
int tp_dcs;
int skip_bytes;
int pdu_str_len;
time_t sms_time;
unsigned char hex_pdu[SMS_PDU_HEX_SIZE] = {0};
pdu_str_len = strlen(sms->sms_pdu);
for (int i = 0; i < pdu_str_len; i += 2)
{
hex_pdu[i / 2] = char_to_hex(sms->sms_pdu[i]) << 4;
hex_pdu[i / 2] |= char_to_hex(sms->sms_pdu[i + 1]);
}
int sms_len = pdu_decode(hex_pdu, pdu_str_len/2,
&sms->timestamp,
sms->sender, PHONE_NUMBER_SIZE,
sms_text, SMS_TEXT_SIZE,
&tp_dcs,
&sms->ref_number,
&sms->total_segments,
&sms->segment_number,
&skip_bytes);
if (sms_len <= 0)
{
err_msg("Error decoding pdu");
return sms_len;
}
sms->sms_lenght = sms_len;
switch ((tp_dcs / 4) % 4)
{
case 0:
{
// GSM 7 bit
sms->type = SMS_CHARSET_7BIT;
int i;
i = skip_bytes;
if (skip_bytes > 0)
i = (skip_bytes * 8 + 6) / 7;
for (; i < strlen(sms_text); i++)
{
sprintf(sms->sms_text + i, "%c", sms_text[i]);
}
i++;
sprintf(sms->sms_text + i, "%c", '\0');
break;
}
case 2:
{
// UCS2
sms->type = SMS_CHARSET_UCS2;
int offset = 0;
for (int i = skip_bytes; i < SMS_TEXT_SIZE; i += 2)
{
int ucs2_char = 0x000000FF & sms_text[i + 1];
ucs2_char |= (0x0000FF00 & (sms_text[i] << 8));
unsigned char utf8_char[5];
int len = ucs2_to_utf8(ucs2_char, utf8_char);
int j;
for (j = 0; j < len; j++)
{
sprintf(sms->sms_text + offset, "%c", utf8_char[j]);
if (utf8_char[j] != '\0')
{
offset++;
}
}
}
offset++;
sprintf(sms->sms_text + offset, "%c", '\0');
break;
}
default:
break;
}
return sms_len;
}
int display_sms_in_json(SMS_T **sms,int num) int display_sms_in_json(SMS_T **sms,int num)
{ {
@ -738,10 +373,10 @@ int display_sms_in_json(SMS_T **sms,int num)
char escaped_text[SMS_TEXT_SIZE]; char escaped_text[SMS_TEXT_SIZE];
escape_json(sms[i]->sms_text, escaped_text); escape_json(sms[i]->sms_text, escaped_text);
if (sms[i]->ref_number) if (sms[i]->ref_number)
offset += sprintf(msg_json + offset, "{\"index\":%d,\"sender\":\"%s\",\"timestamp\":%d,\"content\":\"%s\",\"reference\":%d,\"total\":%d,\"part\":%d},", offset += sprintf(msg_json + offset, "{\"index\":%d,\"sender\":\"%s\",\"timestamp\":%ld,\"content\":\"%s\",\"reference\":%d,\"total\":%d,\"part\":%d},",
sms[i]->sms_index, sms[i]->sender, sms[i]->timestamp, escaped_text, sms[i]->ref_number, sms[i]->total_segments, sms[i]->segment_number); sms[i]->sms_index, sms[i]->sender, sms[i]->timestamp, escaped_text, sms[i]->ref_number, sms[i]->total_segments, sms[i]->segment_number);
else else
offset += sprintf(msg_json + offset, "{\"index\":%d,\"sender\":\"%s\",\"timestamp\":%d,\"content\":\"%s\"},", offset += sprintf(msg_json + offset, "{\"index\":%d,\"sender\":\"%s\",\"timestamp\":%ld,\"content\":\"%s\"},",
sms[i]->sms_index, sms[i]->sender, sms[i]->timestamp, escaped_text); sms[i]->sms_index, sms[i]->sender, sms[i]->timestamp, escaped_text);
} }
@ -752,35 +387,7 @@ int display_sms_in_json(SMS_T **sms,int num)
} }
offset += sprintf(msg_json + offset, "]}"); offset += sprintf(msg_json + offset, "]}");
user_msg("%s\n", msg_json); user_msg("%s\n", msg_json);
return 0; return SUCCESS;
} }
int dump_sms(SMS_T *sms)
{
dbg_msg("SMS Index: %d", sms->sms_index);
dbg_msg("SMS Text: %s", sms->sms_text);
dbg_msg("SMS Sender: %s", sms->sender);
dbg_msg("SMS Timestamp: %d", sms->timestamp);
dbg_msg("SMS Segment: %d/%d", sms->segment_number, sms->total_segments);
return 0;
}
int destroy_sms(SMS_T *sms)
{
if (sms->sms_pdu != NULL)
{
free(sms->sms_pdu);
}
if (sms->sender != NULL)
{
free(sms->sender);
}
if (sms->sms_text != NULL)
{
free(sms->sms_text);
}
free(sms);
return 0;
}

View File

@ -1,17 +1,20 @@
#ifndef _UTILS_H #ifndef _UTILS_H
#define _UTILS_H #define _UTILS_H
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h> #include <stdlib.h>
#include <termios.h>
#include <signal.h>
#include <sys/select.h>
#include <errno.h>
#include "modem_types.h" #include "modem_types.h"
#include "main.h" #include "extlib/pdu.h"
#include "time.h"
extern PROFILE_T s_profile; extern PROFILE_T s_profile;
extern FILE *fdi; // file descriptor for input extern FDS_T s_fds;
extern FILE *fdo; // file descriptor for output
extern int tty_fd; // file descriptor for tty device
extern struct termios oldtio; // old tty setting
#define dbg_msg(fmt, args...) do { \ #define dbg_msg(fmt, args...) do { \
if (s_profile.debug) { \ if (s_profile.debug) { \
@ -51,9 +54,17 @@ int match_option(char *option_name);
int match_operation(char *operation_name); int match_operation(char *operation_name);
int open_tty_device(PROFILE_T *profile);
static int set_tty_device(PROFILE_T *profile); int decode_pdu(SMS_T *sms);
static void clean_up();
int tty_read_keyword(FILE *fdi, char *output, int len, char *key_word, int soft_timeout);
int tty_read(FILE *fdi, char *output, int len, int soft_timeout);
int dump_sms(SMS_T *sms);
int destroy_sms(SMS_T *sms);
int display_sms_in_json(SMS_T **sms,int num);
#endif #endif

View File

@ -1,5 +1,19 @@
# 工具介绍 # 工具介绍
## 更新介绍
### 0.9.2
#### 特性变更
- 在AT通信中优化了响应处理逻辑在接收到初始响应后的特定时间内如果没有进一步的响应则认为通信已结束。这种机制特别适用于那些可能无法正确返回终止符号的命令。需要注意的是当ATE功能启用时命令回显会立即被读取这可能导致对于执行时间较长的命令提前返回结果。
- 在操作执行时若是模组通讯异常无返回、护法读写等会在run_ops函数中返回-1然后直接发送kill -9 命令避免close时大量的花销正常返回则返回0若是与模组通讯无关的故障如解析异常应当返回>0的错误代码
#### 优化
- 更新了超时处理机制不再依赖alarm信号而是通过设置阻塞的读写操作并结合vmin和vtime参数实现超时控制。
- 实现了组件间的一定程度解耦,提高了系统的灵活性和可维护性。
## 概述 ## 概述
这个工具是一个 AT 命令行界面,用于与调制解调器进行通信。它支持多种操作,包括发送和读取短信、设置波特率和数据位等。 这个工具是一个 AT 命令行界面,用于与调制解调器进行通信。它支持多种操作,包括发送和读取短信、设置波特率和数据位等。