2024-11-06 15:33:23 +08:00

394 lines
10 KiB
C

#include "utils.h"
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;
char *long_option;
// if start with '-' then it is an single character option
if (option_name[0] == '-' && option_name[1] != '-')
{
short_option = option_name[1];
switch (short_option)
{
case AT_CMD_S:
return AT_CMD;
case TTY_DEV_S:
return TTY_DEV;
case BAUD_RATE_S:
return BAUD_RATE;
case DATA_BITS_S:
return DATA_BITS;
case PARITY_S:
return PARITY;
case STOP_BITS_S:
return STOP_BITS;
case FLOW_CONTROL_S:
return FLOW_CONTROL;
case TIMEOUT_S:
return TIMEOUT;
case OPERATION_S:
return OPERATION;
case DEBUG_S:
return DEBUG;
case SMS_PDU_S:
return SMS_PDU;
case SMS_INDEX_S:
return SMS_INDEX;
default:
return -1;
}
}
if (option_name[0] == '-' && option_name[1] == '-')
{
long_option = option_name + 2;
if (strcmp(long_option, AT_CMD_L) == 0)
{
return AT_CMD;
}
else if (strcmp(long_option, TTY_DEV_L) == 0)
{
return TTY_DEV;
}
else if (strcmp(long_option, BAUD_RATE_L) == 0)
{
return BAUD_RATE;
}
else if (strcmp(long_option, DATA_BITS_L) == 0)
{
return DATA_BITS;
}
else if (strcmp(long_option, PARITY_L) == 0)
{
return PARITY;
}
else if (strcmp(long_option, STOP_BITS_L) == 0)
{
return STOP_BITS;
}
else if (strcmp(long_option, FLOW_CONTROL_L) == 0)
{
return FLOW_CONTROL;
}
else if (strcmp(long_option, TIMEOUT_L) == 0)
{
return TIMEOUT;
}
else if (strcmp(long_option, OPERATION_L) == 0)
{
return OPERATION;
}
else if (strcmp(long_option, DEBUG_L) == 0)
{
return DEBUG;
}
else if (strcmp(long_option, SMS_PDU_L) == 0)
{
return SMS_PDU;
}
else if (strcmp(long_option, SMS_INDEX_L) == 0)
{
return SMS_INDEX;
}
else
{
return -1;
}
}
// if start with '--' then it is a long option
return -1;
}
int match_operation(char *operation_name)
{
char short_op;
int opstr_len = strlen(operation_name);
if (opstr_len == 1)
{
short_op = operation_name[0];
switch (short_op)
{
case AT_OP_S:
return AT_OP;
case SMS_READ_OP_S:
return SMS_READ_OP;
case SMS_SEND_OP_S:
return SMS_SEND_OP;
case SMS_DELETE_OP_S:
return SMS_DELETE_OP;
default:
return INVALID_PARAM;
break;
}
}
else if (opstr_len > 1)
{
if (strcmp(operation_name, AT_OP_L) == 0)
{
return AT_OP;
}
else if (strcmp(operation_name, SMS_READ_OP_L) == 0)
{
return SMS_READ_OP;
}
else if (strcmp(operation_name, SMS_SEND_OP_L) == 0)
{
return SMS_SEND_OP;
}
else if (strcmp(operation_name, SMS_DELETE_OP_L) == 0)
{
return SMS_DELETE_OP;
}
else
{
return INVALID_PARAM;
}
}
return SUCCESS;
}
void escape_json(char *input, char *output)
{
char *p = input;
char *q = output;
while (*p)
{
if (*p == '"')
{
*q++ = '\\';
*q++ = '"';
}
else if (*p == '\\')
{
*q++ = '\\';
*q++ = '\\';
}
else if (*p == '/')
{
*q++ = '\\';
*q++ = '/';
}
else if (*p == '\b')
{
*q++ = '\\';
*q++ = 'b';
}
else if (*p == '\f')
{
*q++ = '\\';
*q++ = 'f';
}
else if (*p == '\n')
{
*q++ = '\\';
*q++ = 'n';
}
else if (*p == '\r')
{
*q++ = '\\';
*q++ = 'r';
}
else if (*p == '\t')
{
*q++ = '\\';
*q++ = 't';
}
else
{
*q++ = *p;
}
p++;
}
*q = '\0';
}
int usage(char* 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**");
err_msg(" -b, --baud_rate <baud rate> Baud rate Default: 115200 Supported: 4800,9600,19200,38400,57600,115200");
err_msg(" -B, --data_bits <data bits> Data bits Default: 8 Supported: 5,6,7,8");
err_msg(" -t, --timeout <timeout> Timeout Default: 3");
err_msg(" -o, --operation <operation> Operation(at[a:defualt], sms_read[r], sms_send[s], sms_delete[d])");
err_msg(" -D, --debug Debug mode Default: off");
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", 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);
dbg_msg("TTY device: %s", s_profile.tty_dev);
dbg_msg("Baud rate: %d", s_profile.baud_rate);
dbg_msg("Data bits: %d", s_profile.data_bits);
dbg_msg("Parity: %s", s_profile.parity);
dbg_msg("Stop bits: %d", s_profile.stop_bits);
dbg_msg("Flow control: %s", s_profile.flow_control);
dbg_msg("Timeout: %d", s_profile.timeout);
dbg_msg("Operation: %d", s_profile.op);
dbg_msg("Debug: %d", s_profile.debug);
dbg_msg("SMS PDU: %s", s_profile.sms_pdu);
dbg_msg("SMS index: %d", s_profile.sms_index);
}
int display_sms_in_json(SMS_T **sms,int num)
{
char msg_json[SMS_BUF_SIZE];
int offset;
offset = sprintf(msg_json, "{\"msg\":[");
for (int i = 0; i < num; i++)
{
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\":%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\":%ld,\"content\":\"%s\"},",
sms[i]->sms_index, sms[i]->sender, sms[i]->timestamp, escaped_text);
}
//if not empty msg_json,remove the last ','
if (offset > 10)
{
offset--;
}
offset += sprintf(msg_json + offset, "]}");
user_msg("%s\n", msg_json);
return SUCCESS;
}