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
|
||||
|
||||
PKG_NAME:= tom_modem
|
||||
PKG_RELEASE:=beta-1
|
||||
PKG_VERSION:=0.9.1
|
||||
PKG_RELEASE:=beta-2
|
||||
PKG_VERSION:=0.9.2
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
@ -13,6 +13,12 @@ define Package/$(PKG_NAME)
|
||||
TITLE:=Fujr Modem Communite Tool
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/config
|
||||
config PACKAGE_$(PKG_NAME)_EARLY_RETURN
|
||||
bool "Early return"
|
||||
default y
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/description
|
||||
Modem Communite Tool for 5G modem (By Fujr)
|
||||
endef
|
||||
@ -23,6 +29,9 @@ define Build/Prepare
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
ifdef CONFIG_PACKAGE_$(PKG_NAME)_EARLY_RETURN
|
||||
TARGET_CFLAGS+=-DEARLY_RETURN
|
||||
else
|
||||
$(MAKE) -C $(PKG_BUILD_DIR) \
|
||||
$(TARGET_CONFIGURE_OPTS) CFLAGS="$(TARGET_CFLAGS)"
|
||||
endef
|
||||
|
@ -1,8 +1,8 @@
|
||||
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)
|
||||
|
||||
@ -19,6 +19,8 @@ clean:
|
||||
.PHONY:clean
|
||||
clean:
|
||||
rm -rf *.o *.*~ *~ *.swap $(all)
|
||||
rm -rf $(TARGET)
|
||||
rm -rf extlib/*.o
|
||||
depend:
|
||||
$(CC) $(CFLAGS) -MM $(SRCS) > .depend
|
||||
|
||||
|
@ -1,27 +1,8 @@
|
||||
#include "modem_types.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
|
||||
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)
|
||||
{
|
||||
@ -34,8 +15,8 @@ int parse_user_input(int argc, char *argv[], PROFILE_T *profile)
|
||||
option = match_option(argv[opt]);
|
||||
if (option == -1)
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
usage(argv[0]);
|
||||
return INVALID_PARAM;
|
||||
}
|
||||
opt++;
|
||||
switch (option)
|
||||
@ -43,72 +24,72 @@ int parse_user_input(int argc, char *argv[], PROFILE_T *profile)
|
||||
case AT_CMD:
|
||||
if (!has_more_argv())
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
usage(argv[0]);
|
||||
return INVALID_PARAM;
|
||||
}
|
||||
profile->at_cmd = argv[opt++];
|
||||
break;
|
||||
case TTY_DEV:
|
||||
if (!has_more_argv())
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
usage(argv[0]);
|
||||
return INVALID_PARAM;
|
||||
}
|
||||
profile->tty_dev = argv[opt++];
|
||||
break;
|
||||
case BAUD_RATE:
|
||||
if (!has_more_argv())
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
usage(argv[0]);
|
||||
return INVALID_PARAM;
|
||||
}
|
||||
profile->baud_rate = atoi(argv[opt++]);
|
||||
break;
|
||||
case DATA_BITS:
|
||||
if (!has_more_argv())
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
usage(argv[0]);
|
||||
return INVALID_PARAM;
|
||||
}
|
||||
profile->data_bits = atoi(argv[opt++]);
|
||||
break;
|
||||
case PARITY:
|
||||
if (!has_more_argv())
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
usage(argv[0]);
|
||||
return INVALID_PARAM;
|
||||
}
|
||||
profile->parity = argv[opt++];
|
||||
break;
|
||||
case STOP_BITS:
|
||||
if (!has_more_argv())
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
usage(argv[0]);
|
||||
return INVALID_PARAM;
|
||||
}
|
||||
profile->stop_bits = atoi(argv[opt++]);
|
||||
break;
|
||||
case FLOW_CONTROL:
|
||||
if (!has_more_argv())
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
usage(argv[0]);
|
||||
return INVALID_PARAM;
|
||||
}
|
||||
profile->flow_control = argv[opt++];
|
||||
break;
|
||||
case TIMEOUT:
|
||||
if (!has_more_argv())
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
usage(argv[0]);
|
||||
return INVALID_PARAM;
|
||||
}
|
||||
profile->timeout = atoi(argv[opt++]);
|
||||
break;
|
||||
case OPERATION:
|
||||
if (!has_more_argv())
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
usage(argv[0]);
|
||||
return INVALID_PARAM;
|
||||
}
|
||||
profile->op = match_operation(argv[opt++]);
|
||||
break;
|
||||
@ -118,16 +99,16 @@ int parse_user_input(int argc, char *argv[], PROFILE_T *profile)
|
||||
case SMS_PDU:
|
||||
if (!has_more_argv())
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
usage(argv[0]);
|
||||
return INVALID_PARAM;
|
||||
}
|
||||
profile->sms_pdu = argv[opt++];
|
||||
break;
|
||||
case SMS_INDEX:
|
||||
if (!has_more_argv())
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
usage(argv[0]);
|
||||
return INVALID_PARAM;
|
||||
}
|
||||
profile->sms_index = atoi(argv[opt++]);
|
||||
break;
|
||||
@ -153,53 +134,57 @@ int parse_user_input(int argc, char *argv[], PROFILE_T *profile)
|
||||
{
|
||||
profile->op = AT_OP;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int run_op(PROFILE_T *profile)
|
||||
int run_op(PROFILE_T *profile,FDS_T *fds)
|
||||
{
|
||||
switch (profile->op)
|
||||
{
|
||||
case AT_OP:
|
||||
at(profile);
|
||||
break;
|
||||
return at(profile,fds);
|
||||
case SMS_READ_OP:
|
||||
sms_read(profile);
|
||||
break;
|
||||
return sms_read(profile,fds);
|
||||
case SMS_SEND_OP:
|
||||
sms_send(profile);
|
||||
break;
|
||||
return sms_send(profile,fds);
|
||||
case SMS_DELETE_OP:
|
||||
sms_delete(profile);
|
||||
break;
|
||||
return sms_delete(profile,fds);
|
||||
default:
|
||||
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 ret;
|
||||
// init
|
||||
self_name = argv[0];
|
||||
PROFILE_T *profile = &s_profile;
|
||||
FDS_T *fds = &s_fds;
|
||||
parse_user_input(argc, argv, profile);
|
||||
dump_profile();
|
||||
signal(SIGALRM, _timeout);
|
||||
|
||||
// try open tty devices
|
||||
if (open_tty_device(profile))
|
||||
if (tty_open_device(profile,fds))
|
||||
{
|
||||
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);
|
||||
return -1;
|
||||
kill(getpid(), SIGINT);
|
||||
}
|
||||
|
||||
dbg_msg("Exit");
|
||||
return 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
#ifndef _MAIN_H_
|
||||
#define _MAIN_H_
|
||||
#include "modem_types.h"
|
||||
#include "main.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
@ -11,23 +9,24 @@
|
||||
#include <signal.h>
|
||||
#include <sys/select.h>
|
||||
#include <errno.h>
|
||||
#include "operations.h"
|
||||
#include "ttydevice.h"
|
||||
#include "modem_types.h"
|
||||
#include "utils.h"
|
||||
|
||||
#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 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();
|
||||
|
||||
@ -35,8 +34,8 @@ extern int match_option(char *option_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
|
||||
|
@ -1,7 +1,9 @@
|
||||
|
||||
#ifndef _MODEM_TYPES_H_
|
||||
#define _MODEM_TYPES_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
//options
|
||||
#define AT_CMD_S 'c'
|
||||
#define TTY_DEV_S 'd'
|
||||
@ -80,12 +82,20 @@ typedef struct _PROFILE {
|
||||
int sms_index;
|
||||
} PROFILE_T;
|
||||
|
||||
|
||||
typedef struct _FDS {
|
||||
int tty_fd;
|
||||
struct termios old_termios;
|
||||
FILE *fdi;
|
||||
FILE *fdo;
|
||||
} FDS_T;
|
||||
|
||||
typedef struct _SMS {
|
||||
int sms_index;
|
||||
int sms_lenght;
|
||||
int ref_number;
|
||||
int segment_number;
|
||||
int timestamp;
|
||||
time_t timestamp;
|
||||
int total_segments;
|
||||
int type;
|
||||
char *sender;
|
||||
@ -93,6 +103,15 @@ typedef struct _SMS {
|
||||
char *sms_pdu;
|
||||
} SMS_T;
|
||||
|
||||
enum ERROR_CODES {
|
||||
COMM_ERROR = -1,
|
||||
SUCCESS = 0,
|
||||
KEYWORD_NOT_MATCH,
|
||||
TIMEOUT_WAITING_NEWLINE,
|
||||
INVALID_PARAM,
|
||||
UNKNOWN_ERROR,
|
||||
};
|
||||
|
||||
enum SMS_CHARSET {
|
||||
SMS_CHARSET_7BIT,
|
||||
SMS_CHARSET_UCS2
|
||||
@ -121,5 +140,5 @@ enum OPERATIONS {
|
||||
SMS_DELETE_OP
|
||||
};
|
||||
|
||||
|
||||
char *self_name; // program name
|
||||
#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 "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)
|
||||
{
|
||||
char short_option;
|
||||
@ -100,7 +226,6 @@ int match_option(char *option_name)
|
||||
// if start with '--' then it is a long option
|
||||
return -1;
|
||||
}
|
||||
|
||||
int match_operation(char *operation_name)
|
||||
{
|
||||
|
||||
@ -120,7 +245,7 @@ int match_operation(char *operation_name)
|
||||
case SMS_DELETE_OP_S:
|
||||
return SMS_DELETE_OP;
|
||||
default:
|
||||
return -1;
|
||||
return INVALID_PARAM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -144,174 +269,12 @@ int match_operation(char *operation_name)
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
return INVALID_PARAM;
|
||||
}
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
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)
|
||||
void escape_json(char *input, char *output)
|
||||
{
|
||||
char *p = input;
|
||||
char *q = output;
|
||||
@ -365,10 +328,9 @@ static void escape_json(char *input, char *output)
|
||||
}
|
||||
*q = '\0';
|
||||
}
|
||||
|
||||
int usage()
|
||||
int usage(char* name)
|
||||
{
|
||||
err_msg("Usage: %s [options]", self_name);
|
||||
err_msg("Usage: %s [options]", name);
|
||||
err_msg("Options:");
|
||||
err_msg(" -c, --at_cmd <AT command> AT command");
|
||||
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(" -i, --sms_index <sms index> SMS index");
|
||||
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 # normal at mode", self_name);
|
||||
err_msg(" %s -d /dev/mhi_DUN -o r # read sms", 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", name);
|
||||
err_msg(" %s -d /dev/mhi_DUN -o r # read sms", name);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void dump_profile()
|
||||
{
|
||||
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 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)
|
||||
{
|
||||
|
||||
@ -738,10 +373,10 @@ int display_sms_in_json(SMS_T **sms,int num)
|
||||
char escaped_text[SMS_TEXT_SIZE];
|
||||
escape_json(sms[i]->sms_text, escaped_text);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -752,35 +387,7 @@ int display_sms_in_json(SMS_T **sms,int num)
|
||||
}
|
||||
offset += sprintf(msg_json + offset, "]}");
|
||||
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
|
||||
#define _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>
|
||||
#include "modem_types.h"
|
||||
#include "main.h"
|
||||
#include "extlib/pdu.h"
|
||||
#include "time.h"
|
||||
|
||||
extern PROFILE_T s_profile;
|
||||
extern FILE *fdi; // file descriptor for input
|
||||
extern FILE *fdo; // file descriptor for output
|
||||
extern int tty_fd; // file descriptor for tty device
|
||||
extern struct termios oldtio; // old tty setting
|
||||
|
||||
|
||||
extern FDS_T s_fds;
|
||||
|
||||
#define dbg_msg(fmt, args...) do { \
|
||||
if (s_profile.debug) { \
|
||||
@ -51,9 +54,17 @@ int match_option(char *option_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
|
||||
|
@ -1,5 +1,19 @@
|
||||
# 工具介绍
|
||||
|
||||
## 更新介绍
|
||||
|
||||
### 0.9.2
|
||||
|
||||
#### 特性变更
|
||||
|
||||
- 在AT通信中,优化了响应处理逻辑:在接收到初始响应后的特定时间内如果没有进一步的响应,则认为通信已结束。这种机制特别适用于那些可能无法正确返回终止符号的命令。(需要注意的是,当ATE功能启用时,命令回显会立即被读取,这可能导致对于执行时间较长的命令提前返回结果。)
|
||||
- 在操作执行时,若是模组通讯异常(无返回、护法读写等),会在run_ops函数中返回-1,然后直接发送kill -9 命令(避免close时大量的花销),正常返回则返回0,若是与模组通讯无关的故障(如解析异常)应当返回>0的错误代码
|
||||
|
||||
#### 优化
|
||||
|
||||
- 更新了超时处理机制,不再依赖alarm信号,而是通过设置阻塞的读写操作,并结合vmin和vtime参数实现超时控制。
|
||||
- 实现了组件间的一定程度解耦,提高了系统的灵活性和可维护性。
|
||||
|
||||
## 概述
|
||||
|
||||
这个工具是一个 AT 命令行界面,用于与调制解调器进行通信。它支持多种操作,包括发送和读取短信、设置波特率和数据位等。
|
||||
|
Loading…
x
Reference in New Issue
Block a user