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