static const char* parse_cmgr_pdu(char** str, attribute_unused size_t len, char* oa, size_t oa_len, str_encoding_t* oa_enc, char** msg, str_encoding_t* msg_enc) { /* * parse cmgr info in the following PDU format * +CMGR: message_status,[address_text],TPDU_length<CR><LF> * SMSC_number_and_TPDU<CR><LF><CR><LF> * OK<CR><LF> * * sample * +CMGR: 1,,31 * 07911234567890F3040B911234556780F20008012150220040210C041F04400438043204350442<CR><LF><CR><LF> * OK<CR><LF> */ char delimiters[] = ",,\n"; char * marks[STRLEN(delimiters)]; char * end; size_t tpdu_length; if(mark_line(*str, delimiters, marks) == ITEMS_OF(marks)) { tpdu_length = strtol(marks[1] + 1, &end, 10); if(tpdu_length <= 0 || end[0] != '\r') return "Invalid TPDU length in CMGR PDU status line"; *str = marks[2] + 1; return pdu_parse(str, tpdu_length, oa, oa_len, oa_enc, msg, msg_enc); } return "Can't parse +CMGR response"; }
/* array in order of values RECODE_* */ static const coder recoders[STR_ENCODING_UNKNOWN][2] = { [STR_ENCODING_7BIT_HEX_PAD_0] = { hexstr_7bit_to_char_pad_0, char_to_hexstr_7bit_pad_0 }, [STR_ENCODING_8BIT_HEX] = { hexstr_to_8bitchars, chars8bit_to_hexstr }, [STR_ENCODING_UCS2_HEX] = { hexstr_ucs2_to_utf8, utf8_to_hexstr_ucs2 }, [STR_ENCODING_7BIT] = { just_copy, just_copy }, [STR_ENCODING_7BIT_HEX_PAD_1] = { hexstr_7bit_to_char_pad_1, char_to_hexstr_7bit_pad_1 }, [STR_ENCODING_7BIT_HEX_PAD_2] = { hexstr_7bit_to_char_pad_2, char_to_hexstr_7bit_pad_2 }, [STR_ENCODING_7BIT_HEX_PAD_3] = { hexstr_7bit_to_char_pad_3, char_to_hexstr_7bit_pad_3 }, [STR_ENCODING_7BIT_HEX_PAD_4] = { hexstr_7bit_to_char_pad_4, char_to_hexstr_7bit_pad_4 }, [STR_ENCODING_7BIT_HEX_PAD_5] = { hexstr_7bit_to_char_pad_5, char_to_hexstr_7bit_pad_5 }, [STR_ENCODING_7BIT_HEX_PAD_6] = { hexstr_7bit_to_char_pad_6, char_to_hexstr_7bit_pad_6 }, }; #/* */ EXPORT_DEF ssize_t str_recode(recode_direction_t dir, str_encoding_t encoding, const char* in, size_t in_length, char* out, size_t out_size) { unsigned idx = encoding; if((dir == RECODE_DECODE || dir == RECODE_ENCODE) && idx < ITEMS_OF(recoders)) return (recoders[idx][dir])(in, in_length, out, out_size); return -EINVAL; }
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "at_parse.h" /* at_parse_*() */ #include "mutils.h" /* ITEMS_OF() */ int ok = 0; int faults = 0; int test_strcmp(const char *pa, const char *pb) { int retval; if (pa == NULL) pa = ""; if (pb == NULL) pb = ""; retval = strcmp(pa,pb); if (retval != 0) { int x = 0; while (pa[x] == pb[x] && pa[x] != 0) { x++; } printf("String '%s' and '%s' differs at " "offset %d '%c' != '%c'\n", pa, pb, x, pa[x], pb[x]); } return (retval); } #/* */ void test_parse_cnum() { static const struct test_case { const char * input; const char * result; } cases[] = { { "+CNUM: \"*Subscriber Number\",\"+79139131234\",145", "+79139131234" }, { "+CNUM: \"Subscriber Number\",\"\",145", "" }, { "+CNUM: \"Subscriber Number\",,145", "" }, { "+CNUM: \"\",\"+79139131234\",145", "+79139131234" }, { "+CNUM: ,\"\",145", "" }, { "+CNUM: ,,145", "" }, { "+CNUM: \"\",+79139131234\",145", "+79139131234" }, { "+CNUM: \"\",+79139131234,145", "+79139131234" }, }; unsigned idx = 0; char * input; const char * res; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cnum", input); res = at_parse_cnum(input); if(test_strcmp(res, cases[idx].result) == 0) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = \"%s\"\t%s\n", res, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_cops() { static const struct test_case { const char * input; const char * result; } cases[] = { { "+COPS: 0,0,\"TELE2\",0", "TELE2" }, { "+COPS: 0,0,\"TELE2,0", "TELE2" }, { "+COPS: 0,0,TELE2,0", "TELE2" }, }; unsigned idx = 0; char * input; const char * res; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cops", input); res = at_parse_cops(input); if(test_strcmp(res, cases[idx].result) == 0) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = \"%s\"\t%s\n", res, msg); free(input); } fprintf(stderr, "\n"); }
/*! * \brief Enque a answer commands * \param cpvt -- cpvt structure * \return 0 on success */ EXPORT_DEF int at_enque_answer(struct cpvt* cpvt) { at_queue_cmd_t cmds[] = { ATQ_CMD_DECLARE_DYN(CMD_AT_A), ATQ_CMD_DECLARE_ST(CMD_AT_DDSETEX, cmd_ddsetex2), }; int err; int count = ITEMS_OF(cmds); const char * cmd1; if(cpvt->state == CALL_STATE_INCOMING) { /* FIXME: channel number? */ cmd1 = "ATA\r"; } else if(cpvt->state == CALL_STATE_WAITING) { cmds[0].cmd = CMD_AT_CHLD_2x; cmd1 = "AT+CHLD=2%d\r"; /* no need CMD_AT_DDSETEX in this case? */ count--; } else { ast_log (LOG_ERROR, "[%s] Request answer for call idx %d with state '%s'\n", PVT_ID(cpvt->pvt), cpvt->call_idx, call_state2str(cpvt->state)); return -1; } err = at_fill_generic_cmd(&cmds[0], cmd1, cpvt->call_idx); if(err == 0) err = at_queue_insert(cpvt, cmds, count, 1); return err; }
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "at_parse.h" /* at_parse_*() */ #include "mutils.h" /* ITEMS_OF() */ int ok = 0; int faults = 0; int test_strcmp(const char *pa, const char *pb) { int retval; if (pa == NULL) pa = ""; if (pb == NULL) pb = ""; retval = strcmp(pa,pb); if (retval != 0) { int x = 0; while (pa[x] == pb[x] && pa[x] != 0) { x++; } printf("String '%s' and '%s' differs at " "offset %d '%c' != '%c'\n", pa, pb, x, pa[x], pb[x]); } return (retval); } #/* */ void test_parse_cnum() { static const struct test_case { const char * input; const char * result; } cases[] = { { "+CNUM: \"*Subscriber Number\",\"+79139131234\",145", "+79139131234" }, { "+CNUM: \"Subscriber Number\",\"\",145", "" }, { "+CNUM: \"Subscriber Number\",,145", "" }, { "+CNUM: \"\",\"+79139131234\",145", "+79139131234" }, { "+CNUM: ,\"\",145", "" }, { "+CNUM: ,,145", "" }, { "+CNUM: \"\",+79139131234\",145", "+79139131234" }, { "+CNUM: \"\",+79139131234,145", "+79139131234" }, }; unsigned idx = 0; char * input; const char * res; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cnum", input); res = at_parse_cnum(input); if(test_strcmp(res, cases[idx].result) == 0) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = \"%s\"\t%s\n", res, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_cops() { static const struct test_case { const char * input; const char * result; } cases[] = { { "+COPS: 0,0,\"TELE2\",0", "TELE2" }, { "+COPS: 0,0,\"TELE2,0", "TELE2" }, { "+COPS: 0,0,TELE2,0", "TELE2" }, }; unsigned idx = 0; char * input; const char * res; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cops", input); res = at_parse_cops(input); if(test_strcmp(res, cases[idx].result) == 0) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = \"%s\"\t%s\n", res, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_creg() { struct result { int res; int gsm_reg; int gsm_reg_status; char * lac; char * ci; }; static const struct test_case { const char * input; struct result result; } cases[] = { { "+CREG: 2,1,9110,7E6", { 0, 1, 1, "9110", "7E6"} }, { "+CREG: 2,1,XXXX,AAAA", { 0, 1, 1, "XXXX", "AAAA"} }, }; unsigned idx = 0; char * input; struct result result; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_creg", input); result.res = at_parse_creg(input, strlen(input), &result.gsm_reg, &result.gsm_reg_status, &result.lac, &result.ci); if(result.res == cases[idx].result.res && result.gsm_reg == cases[idx].result.gsm_reg && result.gsm_reg_status == cases[idx].result.gsm_reg_status && test_strcmp(result.lac, cases[idx].result.lac) == 0 && test_strcmp(result.ci, cases[idx].result.ci) == 0 ) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = %d (%d,%d,\"%s\",\"%s\")\t%s\n", result.res, result.gsm_reg, result.gsm_reg_status, result.lac, result.ci, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_cmti() { static const struct test_case { const char * input; int result; } cases[] = { { "+CMTI: \"ME\",41", 41 }, { "+CMTI: 0,111", 111 }, { "+CMTI: ", -1 }, }; unsigned idx = 0; char * input; int result; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cmti", input); result = at_parse_cmti(input); if(result == cases[idx].result) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = %d\t%s\n", result, msg); free(input); } fprintf(stderr, "\n"); }
EXPORT_DEF int at_enque_set_ccwa (struct cpvt* cpvt, attribute_unused const char * unused1, attribute_unused const char * unused2, unsigned call_waiting) { static const char cmd_ccwa_get[] = "AT+CCWA=1,2,1\r"; static const char cmd_ccwa_set[] = "AT+CCWA=%d,%d,%d\r"; int err; call_waiting_t value; at_queue_cmd_t cmds[] = { /* 5 seconds timeout */ ATQ_CMD_DECLARE_DYNIT(CMD_AT_CCWA_SET, ATQ_CMD_TIMEOUT_15S, 0), /* Set Call-Waiting On/Off */ ATQ_CMD_DECLARE_STIT(CMD_AT_CCWA_STATUS, cmd_ccwa_get, ATQ_CMD_TIMEOUT_15S, 0), /* Query CCWA Status for Voice Call */ }; at_queue_cmd_t * pcmd = cmds; unsigned count = ITEMS_OF(cmds); if(call_waiting == CALL_WAITING_DISALLOWED || call_waiting == CALL_WAITING_ALLOWED) { value = call_waiting; err = call_waiting == CALL_WAITING_ALLOWED ? 1 : 0; err = at_fill_generic_cmd(&cmds[0], cmd_ccwa_set, err, err, CCWA_CLASS_VOICE); if(err) return err; } else { value = CALL_WAITING_AUTO; pcmd++; count--; } CONF_SHARED(cpvt->pvt, callwaiting) = value; return at_queue_insert(cpvt, pcmd, count, 0); }
EXPORT_DEF char* at_parse_cops (char* str) { /* * parse COPS response in the following format: * +COPS: <mode>[,<format>,<oper>,<?>] * * example * +COPS: 0,0,"TELE2",0 */ char delimiters[] = ":,,,"; char * marks[STRLEN(delimiters)]; /* parse URC only here */ if(mark_line(str, delimiters, marks) == ITEMS_OF(marks)) { marks[2]++; if(marks[2][0] == '"') marks[2]++; if(marks[3][-1] == '"') marks[3]--; marks[3][0] = 0; return marks[2]; } return NULL; }
/*! * \brief Enque ping command * \param pvt -- pvt structure * \return 0 on success */ EXPORT_DEF int at_enque_ping (struct cpvt * cpvt) { static const at_queue_cmd_t cmds[] = { ATQ_CMD_DECLARE_STIT(CMD_AT, cmd_at, ATQ_CMD_TIMEOUT_1S, 0), /* 1 second timeout */ }; return at_queue_insert_const(cpvt, cmds, ITEMS_OF(cmds), 1); }
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "at_parse.h" /* at_parse_*() */ #include "mutils.h" /* ITEMS_OF() */ int ok = 0; int faults = 0; int test_strcmp(const char *pa, const char *pb) { int retval; if (pa == NULL) pa = ""; if (pb == NULL) pb = ""; retval = strcmp(pa,pb); if (retval != 0) { int x = 0; while (pa[x] == pb[x] && pa[x] != 0) { x++; } printf("String '%s' and '%s' differs at " "offset %d '%c' != '%c'\n", pa, pb, x, pa[x], pb[x]); } return (retval); } #/* */ void test_parse_cnum() { static const struct test_case { const char * input; const char * result; } cases[] = { { "+CNUM: \"*Subscriber Number\",\"+79139131234\",145", "+79139131234" }, { "+CNUM: \"Subscriber Number\",\"\",145", "" }, { "+CNUM: \"Subscriber Number\",,145", "" }, { "+CNUM: \"\",\"+79139131234\",145", "+79139131234" }, { "+CNUM: ,\"\",145", "" }, { "+CNUM: ,,145", "" }, { "+CNUM: \"\",+79139131234\",145", "+79139131234" }, { "+CNUM: \"\",+79139131234,145", "+79139131234" }, }; unsigned idx = 0; char * input; const char * res; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cnum", input); res = at_parse_cnum(input); if(test_strcmp(res, cases[idx].result) == 0) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = \"%s\"\t%s\n", res, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_cops() { static const struct test_case { const char * input; const char * result; } cases[] = { { "+COPS: 0,0,\"TELE2\",0", "TELE2" }, { "+COPS: 0,0,\"TELE2,0", "TELE2" }, { "+COPS: 0,0,TELE2,0", "TELE2" }, }; unsigned idx = 0; char * input; const char * res; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cops", input); res = at_parse_cops(input); if(test_strcmp(res, cases[idx].result) == 0) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = \"%s\"\t%s\n", res, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_creg() { struct result { int res; int gsm_reg; int gsm_reg_status; char * lac; char * ci; }; static const struct test_case { const char * input; struct result result; } cases[] = { { "+CREG: 2,1,9110,7E6", { 0, 1, 1, "9110", "7E6"} }, { "+CREG: 2,1,XXXX,AAAA", { 0, 1, 1, "XXXX", "AAAA"} }, }; unsigned idx = 0; char * input; struct result result; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_creg", input); result.res = at_parse_creg(input, strlen(input), &result.gsm_reg, &result.gsm_reg_status, &result.lac, &result.ci); if(result.res == cases[idx].result.res && result.gsm_reg == cases[idx].result.gsm_reg && result.gsm_reg_status == cases[idx].result.gsm_reg_status && test_strcmp(result.lac, cases[idx].result.lac) == 0 && test_strcmp(result.ci, cases[idx].result.ci) == 0 ) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = %d (%d,%d,\"%s\",\"%s\")\t%s\n", result.res, result.gsm_reg, result.gsm_reg_status, result.lac, result.ci, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_cmti() { static const struct test_case { const char * input; int result; } cases[] = { { "+CMTI: \"ME\",41", 41 }, { "+CMTI: 0,111", 111 }, { "+CMTI: ", -1 }, }; unsigned idx = 0; char * input; int result; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cmti", input); result = at_parse_cmti(input); if(result == cases[idx].result) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = %d\t%s\n", result, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_cmgr() { struct result { const char * res; char * str; char * oa; str_encoding_t oa_enc; char * msg; str_encoding_t msg_enc; }; static const struct test_case { const char * input; struct result result; } cases[] = { { "+CMGR: \"REC READ\",\"+79139131234\",,\"10/12/05,22:00:04+12\"\r\n041F04400438043204350442", { NULL, "\"REC READ\",\"+79139131234", "+79139131234", STR_ENCODING_7BIT, "041F04400438043204350442", STR_ENCODING_UNKNOWN } }, { "+CMGR: \"REC READ\",\"002B00370039003500330037003600310032003000350032\",,\"10/12/05,22:00:04+12\"\r\n041F04400438043204350442", { NULL, "\"REC READ\",\"002B00370039003500330037003600310032003000350032", "002B00370039003500330037003600310032003000350032", STR_ENCODING_UNKNOWN, "041F04400438043204350442", STR_ENCODING_UNKNOWN } }, { "+CMGR: 0,,106\r\n07911111111100F3040B911111111111F200000121702214952163B1582C168BC562B1984C2693C96432994C369BCD66B3D96C369BD168341A8D46A3D168B55AAD56ABD56AB59ACD66B3D96C369BCD76BBDD6EB7DBED76BBE170381C0E87C3E170B95C2E97CBE572B91C0C0683C16030180C", { NULL, "B1582C168BC562B1984C2693C96432994C369BCD66B3D96C369BD168341A8D46A3D168B55AAD56ABD56AB59ACD66B3D96C369BCD76BBDD6EB7DBED76BBE170381C0E87C3E170B95C2E97CBE572B91C0C0683C16030180C", "+11111111112", STR_ENCODING_7BIT, "B1582C168BC562B1984C2693C96432994C369BCD66B3D96C369BD168341A8D46A3D168B55AAD56ABD56AB59ACD66B3D96C369BCD76BBDD6EB7DBED76BBE170381C0E87C3E170B95C2E97CBE572B91C0C0683C16030180C", STR_ENCODING_7BIT_HEX_PAD_0 } }, { "+CMGR: 0,,159\r\n07919740430900F3440B912222222220F20008012180004390218C0500030003010031003100310031003100310031003100310031003200320032003200320032003200320032003200330033003300330033003300330033003300330034003400340034003400340034003400340034003500350035003500350035003500350035003500360036003600360036003600360036003600360037003700370037003700370037", { NULL, "0031003100310031003100310031003100310031003200320032003200320032003200320032003200330033003300330033003300330033003300330034003400340034003400340034003400340034003500350035003500350035003500350035003500360036003600360036003600360036003600360037003700370037003700370037", "+22222222022", STR_ENCODING_7BIT, "0031003100310031003100310031003100310031003200320032003200320032003200320032003200330033003300330033003300330033003300330034003400340034003400340034003400340034003500350035003500350035003500350035003500360036003600360036003600360036003600360037003700370037003700370037", STR_ENCODING_UCS2_HEX } }, { "+CMGR: 0,,158\r\n07916407970970F6400A912222222222000041903021825180A0050003000301A9E5391D14060941439015240409414290102404094142901024040941429010240409414290106405594142901564055941429012A40429AD4AABD22A7481AC56101264455A915624C80AB282AC20A1D06A0559415610D20A4282AC2024C80AB282AC202BC80AB282AC2E9012B4042D414A90D2055282942E90D20502819420254809528294", { NULL, "A9E5391D14060941439015240409414290102404094142901024040941429010240409414290106405594142901564055941429012A40429AD4AABD22A7481AC56101264455A915624C80AB282AC20A1D06A0559415610D20A4282AC2024C80AB282AC202BC80AB282AC2E9012B4042D414A90D2055282942E90D20502819420254809528294", "+2222222222", STR_ENCODING_7BIT, "A9E5391D14060941439015240409414290102404094142901024040941429010240409414290106405594142901564055941429012A40429AD4AABD22A7481AC56101264455A915624C80AB282AC20A1D06A0559415610D20A4282AC2024C80AB282AC202BC80AB282AC2E9012B4042D414A90D2055282942E90D20502819420254809528294", STR_ENCODING_7BIT_HEX_PAD_1, } }, { "+CMGR: 0,,55\r\n07912933035011804409D055F3DB5D060000411120712071022A080701030003990202A09976D7E9E5390B640FB3D364103DCD668364B3562CD692C1623417", { NULL, "A09976D7E9E5390B640FB3D364103DCD668364B3562CD692C1623417", "553", STR_ENCODING_7BIT, "A09976D7E9E5390B640FB3D364103DCD668364B3562CD692C1623417", STR_ENCODING_7BIT_HEX_PAD_5, } }, }; unsigned idx = 0; char * input; struct result result; char oa[200]; char buffer_res[256]; char buffer_dec[256]; const char * msg; result.oa = oa; for(; idx < ITEMS_OF(cases); ++idx) { result.str = input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cmgr", input); result.res = at_parse_cmgr(&result.str, strlen(result.str), result.oa, sizeof(oa), &result.oa_enc, &result.msg, &result.msg_enc); if( ((result.res == NULL && result.res == cases[idx].result.res) || test_strcmp(result.res, cases[idx].result.res) == 0) && test_strcmp(result.str, cases[idx].result.str) == 0 && test_strcmp(result.oa, cases[idx].result.oa) == 0 && result.oa_enc == cases[idx].result.oa_enc && test_strcmp(result.msg, cases[idx].result.msg) == 0 && result.msg_enc == cases[idx].result.msg_enc ) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } memset(buffer_res, 0, sizeof(buffer_res)); memset(buffer_dec, 0, sizeof(buffer_dec)); str_recode(RECODE_DECODE, result.msg_enc, result.msg, strlen(result.msg), buffer_res, sizeof(buffer_res)); str_recode(RECODE_DECODE, cases[idx].result.msg_enc, cases[idx].result.msg, strlen(cases[idx].result.msg), buffer_dec, sizeof(buffer_dec)); fprintf(stderr, " = '%s' ('%s','%s',%d,'%s',%d,'%s','%s')\t%s\n", result.res, result.str, result.oa, result.oa_enc, result.msg, result.msg_enc, buffer_res, buffer_dec, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_cusd() { struct result { int res; int type; char * cusd; int dcs; }; static const struct test_case { const char * input; struct result result; } cases[] = { { "+CUSD: 0,\"CF2135487D2E4130572D0682BB1A\",0", { 0, 0, "CF2135487D2E4130572D0682BB1A", 0} }, { "+CUSD: 1,\"CF2135487D2E4130572D0682BB1A\",1", { 0, 1, "CF2135487D2E4130572D0682BB1A", 1} }, { "+CUSD: 5", { 0, 5, "", -1} }, }; unsigned idx = 0; char * input; struct result result; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cusd", input); result.res = at_parse_cusd(input, &result.type, &result.cusd, &result.dcs); if(result.res == cases[idx].result.res && result.type == cases[idx].result.type && result.dcs == cases[idx].result.dcs && test_strcmp(result.cusd, cases[idx].result.cusd) == 0 ) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = %d (%d,\"%s\",%d)\t%s\n", result.res, result.type, result.cusd, result.dcs, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_cpin() { } #/* */ void test_parse_csq() { } #/* */ void test_parse_rssi() { } #/* */ void test_parse_mode() { } #/* */ void test_parse_csca() { } #/* */ void test_parse_clcc() { struct result { int res; unsigned index; unsigned dir; unsigned stat; unsigned mode; unsigned mpty; char * number; unsigned toa; }; static const struct test_case { const char * input; struct result result; } cases[] = { { "+CLCC: 1,1,4,0,0,\"\",145", { 0, 1, 1, 4, 0, 0, "", 145} }, { "+CLCC: 1,1,4,0,0,\"+79139131234\",145", { 0, 1, 1, 4, 0, 0, "+79139131234", 145} }, { "+CLCC: 1,1,4,0,0,\"+7913913ABCA\",145", { 0, 1, 1, 4, 0, 0, "+7913913ABCA", 145} }, { "+CLCC: 1,1,4,0,0,\"+7913913ABCA\"", { -1, 0, 0, 0, 0, 0, "", 0} }, }; unsigned idx = 0; char * input; struct result result; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_clcc", input); result.res = at_parse_clcc(input, &result.index, &result.dir, &result.stat, &result.mode, &result.mpty, &result.number, &result.toa); if(result.res == cases[idx].result.res && result.index == cases[idx].result.index && result.dir == cases[idx].result.dir && result.stat == cases[idx].result.stat && result.mode == cases[idx].result.mode && result.mpty == cases[idx].result.mpty && test_strcmp(result.number, cases[idx].result.number) == 0 && result.toa == cases[idx].result.toa ) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = %d (%d,%d,%d,%d,%d,\"%s\",%d)\t%s\n", result.res, result.index, result.dir, result.stat, result.mode, result.mpty, result.number, result.toa, msg); free(input); } fprintf(stderr, "\n"); }
/*! * \brief Enque an commands for 'Put active calls on hold and activate the waiting or held call.' * \param pvt -- pvt structure * \return 0 on success */ EXPORT_DEF int at_enque_flip_hold (struct cpvt* cpvt) { static const at_queue_cmd_t cmds[] = { ATQ_CMD_DECLARE_ST(CMD_AT_CHLD_2, cmd_chld2), ATQ_CMD_DECLARE_ST(CMD_AT_CLCC, cmd_clcc), }; return at_queue_insert_const(cpvt, cmds, ITEMS_OF(cmds), 1); }
/* * parse CSCA info in the following format: * +CSCA: <SCA>,<TOSCA> * +CSCA: "+79139131234",145 * +CSCA: "",145 */ char delimiters[] = "\"\""; char * marks[STRLEN(delimiters)]; if(mark_line(str, delimiters, marks) == ITEMS_OF(marks)) { *csca = marks[0] + 1; marks[1][0] = 0; return 0; } return -1; } #/* */ EXPORT_DEF int at_parse_clcc(char* str, unsigned * call_idx, unsigned * dir, unsigned * state, unsigned * mode, unsigned * mpty, char ** number, unsigned * toa) { /* * +CLCC:<id1>,<dir>,<stat>,<mode>,<mpty>[,<number>,<type>[,<alpha>[,<priority>]]]\r\n * ... * +CLCC:<id1>,<dir>,<stat>,<mode>,<mpty>[,<number>,<type>[,<alpha>[,<priority>]]]\r\n * examples * +CLCC: 1,1,4,0,0,"",145 * +CLCC: 1,1,4,0,0,"+79139131234",145 * +CLCC: 1,1,4,0,0,"0079139131234",145 * +CLCC: 1,1,4,0,0,"+7913913ABCA",145 */ char delimiters[] = ":,,,,,,"; char * marks[STRLEN(delimiters)]; *call_idx = 0; *dir = 0; *state = 0; *mode = 0; *mpty = 0; *number = ""; *toa = 0; if(mark_line(str, delimiters, marks) == ITEMS_OF(marks)) { if( sscanf(marks[0] + 1, "%u", call_idx) == 1 && sscanf(marks[1] + 1, "%u", dir) == 1 && sscanf(marks[2] + 1, "%u", state) == 1 && sscanf(marks[3] + 1, "%u", mode) == 1 && sscanf(marks[4] + 1, "%u", mpty) == 1 && sscanf(marks[6] + 1, "%u", toa) == 1) { marks[5]++; if(marks[5][0] == '"') marks[5]++; if(marks[6][-1] == '"') marks[6]--; *number = marks[5]; marks[6][0] = 0; return 0; } } return -1; }
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "at_parse.h" /* at_parse_*() */ #include "mutils.h" /* ITEMS_OF() */ int ok = 0; int faults = 0; int test_strcmp(const char *pa, const char *pb) { int retval; if (pa == NULL) pa = ""; if (pb == NULL) pb = ""; retval = strcmp(pa,pb); if (retval != 0) { int x = 0; while (pa[x] == pb[x] && pa[x] != 0) { x++; } printf("String '%s' and '%s' differs at " "offset %d '%c' != '%c'\n", pa, pb, x, pa[x], pb[x]); } return (retval); } #/* */ void test_parse_cnum() { static const struct test_case { const char * input; const char * result; } cases[] = { { "+CNUM: \"*Subscriber Number\",\"+79139131234\",145", "+79139131234" }, { "+CNUM: \"Subscriber Number\",\"\",145", "" }, { "+CNUM: \"Subscriber Number\",,145", "" }, { "+CNUM: \"\",\"+79139131234\",145", "+79139131234" }, { "+CNUM: ,\"\",145", "" }, { "+CNUM: ,,145", "" }, { "+CNUM: \"\",+79139131234\",145", "+79139131234" }, { "+CNUM: \"\",+79139131234,145", "+79139131234" }, }; unsigned idx = 0; char * input; const char * res; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cnum", input); res = at_parse_cnum(input); if(test_strcmp(res, cases[idx].result) == 0) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = \"%s\"\t%s\n", res, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_cops() { static const struct test_case { const char * input; const char * result; } cases[] = { { "+COPS: 0,0,\"TELE2\",0", "TELE2" }, { "+COPS: 0,0,\"TELE2,0", "TELE2" }, { "+COPS: 0,0,TELE2,0", "TELE2" }, }; unsigned idx = 0; char * input; const char * res; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cops", input); res = at_parse_cops(input); if(test_strcmp(res, cases[idx].result) == 0) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = \"%s\"\t%s\n", res, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_creg() { struct result { int res; int gsm_reg; int gsm_reg_status; char * lac; char * ci; }; static const struct test_case { const char * input; struct result result; } cases[] = { { "+CREG: 2,1,9110,7E6", { 0, 1, 1, "9110", "7E6"} }, { "+CREG: 2,1,XXXX,AAAA", { 0, 1, 1, "XXXX", "AAAA"} }, }; unsigned idx = 0; char * input; struct result result; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_creg", input); result.res = at_parse_creg(input, strlen(input), &result.gsm_reg, &result.gsm_reg_status, &result.lac, &result.ci); if(result.res == cases[idx].result.res && result.gsm_reg == cases[idx].result.gsm_reg && result.gsm_reg_status == cases[idx].result.gsm_reg_status && test_strcmp(result.lac, cases[idx].result.lac) == 0 && test_strcmp(result.ci, cases[idx].result.ci) == 0 ) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = %d (%d,%d,\"%s\",\"%s\")\t%s\n", result.res, result.gsm_reg, result.gsm_reg_status, result.lac, result.ci, msg); free(input); } fprintf(stderr, "\n"); }
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "at_parse.h" /* at_parse_*() */ #include "mutils.h" /* ITEMS_OF() */ int ok = 0; int faults = 0; int test_strcmp(const char *pa, const char *pb) { int retval; if (pa == NULL) pa = ""; if (pb == NULL) pb = ""; retval = strcmp(pa,pb); if (retval != 0) { int x = 0; while (pa[x] == pb[x] && pa[x] != 0) { x++; } printf("String '%s' and '%s' differs at " "offset %d '%c' != '%c'\n", pa, pb, x, pa[x], pb[x]); } return (retval); } #/* */ void test_parse_cnum() { static const struct test_case { const char * input; const char * result; } cases[] = { { "+CNUM: \"*Subscriber Number\",\"+79139131234\",145", "+79139131234" }, { "+CNUM: \"Subscriber Number\",\"\",145", "" }, { "+CNUM: \"Subscriber Number\",,145", "" }, { "+CNUM: \"\",\"+79139131234\",145", "+79139131234" }, { "+CNUM: ,\"\",145", "" }, { "+CNUM: ,,145", "" }, { "+CNUM: \"\",+79139131234\",145", "+79139131234" }, { "+CNUM: \"\",+79139131234,145", "+79139131234" }, }; unsigned idx = 0; char * input; const char * res; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cnum", input); res = at_parse_cnum(input); if(test_strcmp(res, cases[idx].result) == 0) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = \"%s\"\t%s\n", res, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_cops() { static const struct test_case { const char * input; const char * result; } cases[] = { { "+COPS: 0,0,\"TELE2\",0", "TELE2" }, { "+COPS: 0,0,\"TELE2,0", "TELE2" }, { "+COPS: 0,0,TELE2,0", "TELE2" }, }; unsigned idx = 0; char * input; const char * res; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cops", input); res = at_parse_cops(input); if(test_strcmp(res, cases[idx].result) == 0) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = \"%s\"\t%s\n", res, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_creg() { struct result { int res; int gsm_reg; int gsm_reg_status; char * lac; char * ci; }; static const struct test_case { const char * input; struct result result; } cases[] = { { "+CREG: 2,1,9110,7E6", { 0, 1, 1, "9110", "7E6"} }, { "+CREG: 2,1,XXXX,AAAA", { 0, 1, 1, "XXXX", "AAAA"} }, }; unsigned idx = 0; char * input; struct result result; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_creg", input); result.res = at_parse_creg(input, strlen(input), &result.gsm_reg, &result.gsm_reg_status, &result.lac, &result.ci); if(result.res == cases[idx].result.res && result.gsm_reg == cases[idx].result.gsm_reg && result.gsm_reg_status == cases[idx].result.gsm_reg_status && test_strcmp(result.lac, cases[idx].result.lac) == 0 && test_strcmp(result.ci, cases[idx].result.ci) == 0 ) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = %d (%d,%d,\"%s\",\"%s\")\t%s\n", result.res, result.gsm_reg, result.gsm_reg_status, result.lac, result.ci, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_cmti() { static const struct test_case { const char * input; int result; } cases[] = { { "+CMTI: \"ME\",41", 41 }, { "+CMTI: 0,111", 111 }, { "+CMTI: ", -1 }, }; unsigned idx = 0; char * input; int result; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cmti", input); result = at_parse_cmti(input); if(result == cases[idx].result) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = %d\t%s\n", result, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_cmgr() { struct result { const char * res; char * str; char * oa; str_encoding_t oa_enc; char * msg; str_encoding_t msg_enc; }; static const struct test_case { const char * input; struct result result; } cases[] = { { "+CMGR: \"REC READ\",\"+79139131234\",,\"10/12/05,22:00:04+12\"\r\n041F04400438043204350442", { NULL, "\"REC READ\",\"+79139131234", "+79139131234", STR_ENCODING_7BIT, "041F04400438043204350442", STR_ENCODING_UNKNOWN } }, { "+CMGR: \"REC READ\",\"002B00370039003500330037003600310032003000350032\",,\"10/12/05,22:00:04+12\"\r\n041F04400438043204350442", { NULL, "\"REC READ\",\"002B00370039003500330037003600310032003000350032", "002B00370039003500330037003600310032003000350032", STR_ENCODING_UNKNOWN, "041F04400438043204350442", STR_ENCODING_UNKNOWN } }, { "+CMGR: 0,,106\r\n07911111111100F3040B911111111111F200000121702214952163B1582C168BC562B1984C2693C96432994C369BCD66B3D96C369BD168341A8D46A3D168B55AAD56ABD56AB59ACD66B3D96C369BCD76BBDD6EB7DBED76BBE170381C0E87C3E170B95C2E97CBE572B91C0C0683C16030180C", { NULL, "B1582C168BC562B1984C2693C96432994C369BCD66B3D96C369BD168341A8D46A3D168B55AAD56ABD56AB59ACD66B3D96C369BCD76BBDD6EB7DBED76BBE170381C0E87C3E170B95C2E97CBE572B91C0C0683C16030180C", "+11111111112", STR_ENCODING_7BIT, "B1582C168BC562B1984C2693C96432994C369BCD66B3D96C369BD168341A8D46A3D168B55AAD56ABD56AB59ACD66B3D96C369BCD76BBDD6EB7DBED76BBE170381C0E87C3E170B95C2E97CBE572B91C0C0683C16030180C", STR_ENCODING_7BIT_HEX_PAD_0 } }, { "+CMGR: 0,,159\r\n07919740430900F3440B912222222220F20008012180004390218C0500030003010031003100310031003100310031003100310031003200320032003200320032003200320032003200330033003300330033003300330033003300330034003400340034003400340034003400340034003500350035003500350035003500350035003500360036003600360036003600360036003600360037003700370037003700370037", { NULL, "0031003100310031003100310031003100310031003200320032003200320032003200320032003200330033003300330033003300330033003300330034003400340034003400340034003400340034003500350035003500350035003500350035003500360036003600360036003600360036003600360037003700370037003700370037", "+22222222022", STR_ENCODING_7BIT, "0031003100310031003100310031003100310031003200320032003200320032003200320032003200330033003300330033003300330033003300330034003400340034003400340034003400340034003500350035003500350035003500350035003500360036003600360036003600360036003600360037003700370037003700370037", STR_ENCODING_UCS2_HEX } }, { "+CMGR: 0,,158\r\n07916407970970F6400A912222222222000041903021825180A0050003000301A9E5391D14060941439015240409414290102404094142901024040941429010240409414290106405594142901564055941429012A40429AD4AABD22A7481AC56101264455A915624C80AB282AC20A1D06A0559415610D20A4282AC2024C80AB282AC202BC80AB282AC2E9012B4042D414A90D2055282942E90D20502819420254809528294", { NULL, "A9E5391D14060941439015240409414290102404094142901024040941429010240409414290106405594142901564055941429012A40429AD4AABD22A7481AC56101264455A915624C80AB282AC20A1D06A0559415610D20A4282AC2024C80AB282AC202BC80AB282AC2E9012B4042D414A90D2055282942E90D20502819420254809528294", "+2222222222", STR_ENCODING_7BIT, "A9E5391D14060941439015240409414290102404094142901024040941429010240409414290106405594142901564055941429012A40429AD4AABD22A7481AC56101264455A915624C80AB282AC20A1D06A0559415610D20A4282AC2024C80AB282AC202BC80AB282AC2E9012B4042D414A90D2055282942E90D20502819420254809528294", STR_ENCODING_7BIT_HEX_PAD_1, } }, { "+CMGR: 0,,55\r\n07912933035011804409D055F3DB5D060000411120712071022A080701030003990202A09976D7E9E5390B640FB3D364103DCD668364B3562CD692C1623417", { NULL, "A09976D7E9E5390B640FB3D364103DCD668364B3562CD692C1623417", "553", STR_ENCODING_7BIT, "A09976D7E9E5390B640FB3D364103DCD668364B3562CD692C1623417", STR_ENCODING_7BIT_HEX_PAD_5, } }, }; unsigned idx = 0; char * input; struct result result; char oa[200]; char buffer_res[256]; char buffer_dec[256]; const char * msg; result.oa = oa; for(; idx < ITEMS_OF(cases); ++idx) { result.str = input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cmgr", input); result.res = at_parse_cmgr(&result.str, strlen(result.str), result.oa, sizeof(oa), &result.oa_enc, &result.msg, &result.msg_enc); if( ((result.res == NULL && result.res == cases[idx].result.res) || test_strcmp(result.res, cases[idx].result.res) == 0) && test_strcmp(result.str, cases[idx].result.str) == 0 && test_strcmp(result.oa, cases[idx].result.oa) == 0 && result.oa_enc == cases[idx].result.oa_enc && test_strcmp(result.msg, cases[idx].result.msg) == 0 && result.msg_enc == cases[idx].result.msg_enc ) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } memset(buffer_res, 0, sizeof(buffer_res)); memset(buffer_dec, 0, sizeof(buffer_dec)); str_recode(RECODE_DECODE, result.msg_enc, result.msg, strlen(result.msg), buffer_res, sizeof(buffer_res)); str_recode(RECODE_DECODE, cases[idx].result.msg_enc, cases[idx].result.msg, strlen(cases[idx].result.msg), buffer_dec, sizeof(buffer_dec)); fprintf(stderr, " = '%s' ('%s','%s',%d,'%s',%d,'%s','%s')\t%s\n", result.res, result.str, result.oa, result.oa_enc, result.msg, result.msg_enc, buffer_res, buffer_dec, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_cusd() { struct result { int res; int type; char * cusd; int dcs; }; static const struct test_case { const char * input; struct result result; } cases[] = { { "+CUSD: 0,\"CF2135487D2E4130572D0682BB1A\",0", { 0, 0, "CF2135487D2E4130572D0682BB1A", 0} }, { "+CUSD: 1,\"CF2135487D2E4130572D0682BB1A\",1", { 0, 1, "CF2135487D2E4130572D0682BB1A", 1} }, { "+CUSD: 5", { 0, 5, "", -1} }, }; unsigned idx = 0; char * input; struct result result; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cusd", input); result.res = at_parse_cusd(input, &result.type, &result.cusd, &result.dcs); if(result.res == cases[idx].result.res && result.type == cases[idx].result.type && result.dcs == cases[idx].result.dcs && test_strcmp(result.cusd, cases[idx].result.cusd) == 0 ) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = %d (%d,\"%s\",%d)\t%s\n", result.res, result.type, result.cusd, result.dcs, msg); free(input); } fprintf(stderr, "\n"); }
/* SMS sending */ EXPORT_DEF int at_enque_pdu(struct cpvt * cpvt, const char * pdu, attribute_unused const char * u1, attribute_unused unsigned u2, attribute_unused int u3, void ** id) { char * ptr = (char *) pdu; char buf[8+25+1]; at_queue_cmd_t at_cmd[] = { { CMD_AT_CMGS, RES_SMS_PROMPT, ATQ_CMD_FLAG_DEFAULT, { ATQ_CMD_TIMEOUT_2S, 0} , NULL, 0 }, { CMD_AT_SMSTEXT, RES_OK, ATQ_CMD_FLAG_DEFAULT, { ATQ_CMD_TIMEOUT_40S, 0} , NULL, 0 } }; size_t length = strlen(pdu); size_t pdulen = length; int scalen = pdu_parse_sca(&ptr, &pdulen); if(scalen < 2 || length % 2 != 0) { return -EINVAL; } at_cmd[1].data = ast_malloc(length + 2); if(!at_cmd[1].data) { return -ENOMEM; } at_cmd[1].length = length + 1; memcpy(at_cmd[1].data, pdu, length); at_cmd[1].data[length] = 0x1A; at_cmd[1].data[length+1] = 0x0; at_cmd[0].length = snprintf(buf, sizeof(buf), "AT+CMGS=%d\r", (int)(pdulen / 2)); at_cmd[0].data = ast_strdup(buf); if(!at_cmd[0].data) { ast_free(at_cmd[1].data); return -ENOMEM; } /* ast_debug (5, "[%s] PDU Head '%s'\n", PVT_ID(pvt), buf); ast_debug (5, "[%s] PDU Body '%s'\n", PVT_ID(pvt), at_cmd[1].data); */ return at_queue_insert_task(cpvt, at_cmd, ITEMS_OF(at_cmd), 0, (struct at_queue_task **)id); }
static const char * parse_cmgr_text(char ** str, size_t len, char * oa, size_t oa_len, str_encoding_t * oa_enc, char ** msg, str_encoding_t * msg_enc) { /* * parse cmgr info in the following TEXT format: * +CMGR: "<msg status>","+123456789",,timestamp<CR><LF> * <message text><CR><LF><CR><LF> * OK<CR><LF> * or * +CMGR: "<msg status>","002B....",,timestamp<CR><LF> * <message text><CR><LF><CR><LF> * OK<CR><LF> */ char delimiters[] = ",,,\n"; char * marks[STRLEN(delimiters)]; size_t length; unsigned count = mark_line(*str, delimiters, marks); if(count == ITEMS_OF(marks)) { /* unquote number */ marks[0]++; if(marks[0][0] == '"') marks[0]++; if(marks[1][-1] == '"') marks[1]--; length = marks[1] - marks[0] + 1; if(oa_len < length) return "Not enought space for store number"; *oa_enc = get_encoding(RECODE_DECODE, marks[0], length - 1); marks[1][0] = 0; memcpy(oa, marks[0], length); *msg = marks[3] + 1; length = len - (*msg - *str); *msg_enc = get_encoding(RECODE_DECODE, *msg, length); return NULL; } else if(count > 0) *str = marks[count - 1]; return "Can't parse +CMGR response text"; }
EXPORT_DEF int at_parse_cpin (char* str, size_t len) { static const struct { const char * value; unsigned length; } resp[] = { { "READY", 5 }, { "SIM PIN", 7 }, { "SIM PUK", 7 }, }; unsigned idx; for(idx = 0; idx < ITEMS_OF(resp); idx++) { if(memmem (str, len, resp[idx].value, resp[idx].length) != NULL) return idx; } return -1; }
/* * parse RSSI info in the following format: * ^MODE:<mode>,<submode> */ return sscanf (str, "^MODE:%d,%d", mode, submode) == 2 ? 0 : -1; } #/* */ EXPORT_DEF int at_parse_csca(char* str, char ** csca) { /* * parse CSCA info in the following format: * +CSCA: <SCA>,<TOSCA> * +CSCA: "+79139131234",145 * +CSCA: "",145 */ char delimiters[] = "\"\""; char * marks[STRLEN(delimiters)]; if(mark_line(str, delimiters, marks) == ITEMS_OF(marks)) { *csca = marks[0] + 1; marks[1][0] = 0; return 0; } return -1; }
/*! * \brief Enque an activate commands 'Put active calls on hold and activate call x.' * \param cpvt -- cpvt structure * \return 0 on success */ EXPORT_DEF int at_enque_activate (struct cpvt* cpvt) { at_queue_cmd_t cmds[] = { ATQ_CMD_DECLARE_DYN(CMD_AT_CHLD_2x), ATQ_CMD_DECLARE_ST(CMD_AT_CLCC, cmd_clcc), }; int err; if (cpvt->state == CALL_STATE_ACTIVE) return 0; if (cpvt->state != CALL_STATE_ONHOLD && cpvt->state != CALL_STATE_WAITING) { ast_log (LOG_ERROR, "[%s] Imposible activate call idx %d from state '%s'\n", PVT_ID(cpvt->pvt), cpvt->call_idx, call_state2str(cpvt->state)); return -1; } err = at_fill_generic_cmd(&cmds[0], "AT+CHLD=2%d\r", cpvt->call_idx); if(err == 0) err = at_queue_insert(cpvt, cmds, ITEMS_OF(cmds), 1); return err; }
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "at_parse.h" /* at_parse_*() */ #include "mutils.h" /* ITEMS_OF() */ int ok = 0; int faults = 0; int test_strcmp(const char *pa, const char *pb) { int retval; if (pa == NULL) pa = ""; if (pb == NULL) pb = ""; retval = strcmp(pa,pb); if (retval != 0) { int x = 0; while (pa[x] == pb[x] && pa[x] != 0) { x++; } printf("String '%s' and '%s' differs at " "offset %d '%c' != '%c'\n", pa, pb, x, pa[x], pb[x]); } return (retval); } #/* */ void test_parse_cnum() { static const struct test_case { const char * input; const char * result; } cases[] = { { "+CNUM: \"*Subscriber Number\",\"+79139131234\",145", "+79139131234" }, { "+CNUM: \"Subscriber Number\",\"\",145", "" }, { "+CNUM: \"Subscriber Number\",,145", "" }, { "+CNUM: \"\",\"+79139131234\",145", "+79139131234" }, { "+CNUM: ,\"\",145", "" }, { "+CNUM: ,,145", "" }, { "+CNUM: \"\",+79139131234\",145", "+79139131234" }, { "+CNUM: \"\",+79139131234,145", "+79139131234" }, }; unsigned idx = 0; char * input; const char * res; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cnum", input); res = at_parse_cnum(input); if(test_strcmp(res, cases[idx].result) == 0) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = \"%s\"\t%s\n", res, msg); free(input); } fprintf(stderr, "\n"); }
EXPORT_DEF const char * dc_dtmf_setting2str(dc_dtmf_setting_t dtmf) { return enum2str(dtmf, dtmf_values, ITEMS_OF(dtmf_values)); }
/*! * \brief Enque commands for reading SMS * \param cpvt -- cpvt structure * \param index -- index of message in store * \param delete -- if non-zero also enque commands for delete message in store after reading * \return 0 on success */ EXPORT_DEF int at_enque_retrive_sms (struct cpvt* cpvt, int index, int delete) { int err; at_queue_cmd_t cmds[] = { ATQ_CMD_DECLARE_DYN2(CMD_AT_CMGR, RES_CMGR), ATQ_CMD_DECLARE_DYN(CMD_AT_CMGD) }; unsigned cmdsno = ITEMS_OF (cmds); err = at_fill_generic_cmd (&cmds[0], "AT+CMGR=%d\r", index); if (err) return err; if (delete) { err = at_fill_generic_cmd (&cmds[1], "AT+CMGD=%d\r\r", index); if(err) { ast_free (cmds[0].data); return err; } } else
EXPORT_DEF int dc_dtmf_str2setting(const char * value) { return str2enum(value, dtmf_values, ITEMS_OF(dtmf_values)); }
/* first set default values */ memset(config, 0, sizeof(*config)); ast_copy_string (config->context, "default", sizeof (config->context)); ast_copy_string (config->exten, "", sizeof (config->exten)); ast_copy_string (config->language, DEFAULT_LANGUAGE, sizeof (config->language)); config->u2diag = -1; config->resetdongle = 1; config->callingpres = -1; config->initstate = DEV_STATE_STARTED; config->callwaiting = CALL_WAITING_AUTO; config->dtmf = DC_DTMF_SETTING_RELAX; config->mindtmfgap = DEFAULT_MINDTMFGAP; config->mindtmfduration = DEFAULT_MINDTMFDURATION; config->mindtmfinterval = DEFAULT_MINDTMFINTERVAL; } #/* */ EXPORT_DEF void dc_sconfig_fill(struct ast_config * cfg, const char * cat, struct dc_sconfig * config) { struct ast_variable * v; /* read config and translate to values */ for (v = ast_variable_browse (cfg, cat); v; v = v->next) { if (!strcasecmp (v->name, "context")) { ast_copy_string (config->context, v->value, sizeof (config->context)); } else if (!strcasecmp (v->name, "exten")) { ast_copy_string (config->exten, v->value, sizeof (config->exten)); } else if (!strcasecmp (v->name, "language")) { ast_copy_string (config->language, v->value, sizeof (config->language));/* set channel language */ } else if (!strcasecmp (v->name, "group")) { config->group = (int) strtol (v->value, (char**) NULL, 10); /* group is set to 0 if invalid */ } else if (!strcasecmp (v->name, "rxgain")) { config->rxgain = (int) strtol (v->value, (char**) NULL, 10); /* rxgain is set to 0 if invalid */ } else if (!strcasecmp (v->name, "txgain")) { config->txgain = (int) strtol (v->value, (char**) NULL, 10); /* txgain is set to 0 if invalid */ } else if (!strcasecmp (v->name, "u2diag")) { errno = 0; config->u2diag = (int) strtol (v->value, (char**) NULL, 10); /* u2diag is set to -1 if invalid */ if (config->u2diag == 0 && errno == EINVAL) { config->u2diag = -1; } } else if (!strcasecmp (v->name, "callingpres")) { config->callingpres = ast_parse_caller_presentation (v->value); if (config->callingpres == -1) { errno = 0; config->callingpres = (int) strtol (v->value, (char**) NULL, 10);/* callingpres is set to -1 if invalid */ if (config->callingpres == 0 && errno == EINVAL) { config->callingpres = -1; } } } else if (!strcasecmp (v->name, "usecallingpres")) { config->usecallingpres = ast_true (v->value); /* usecallingpres is set to 0 if invalid */ } else if (!strcasecmp (v->name, "autodeletesms")) { config->autodeletesms = ast_true (v->value); /* autodeletesms is set to 0 if invalid */ } else if (!strcasecmp (v->name, "resetdongle")) { config->resetdongle = ast_true (v->value); /* resetdongle is set to 0 if invalid */ } else if (!strcasecmp (v->name, "disablesms")) { config->disablesms = ast_true (v->value); /* disablesms is set to 0 if invalid */ } else if (!strcasecmp (v->name, "smsaspdu")) { config->smsaspdu = ast_true (v->value); /* send_sms_as_pdu us set to 0 if invalid */ } else if (!strcasecmp (v->name, "disable")) { config->initstate = ast_true (v->value) ? DEV_STATE_REMOVED : DEV_STATE_STARTED; } else if (!strcasecmp (v->name, "initstate")) { int val = str2enum(v->value, dev_state_strs, ITEMS_OF(dev_state_strs)); if(val == DEV_STATE_STOPPED || val == DEV_STATE_STARTED || val == DEV_STATE_REMOVED) config->initstate = val; else ast_log(LOG_ERROR, "Invalid value for 'initstate': '%s', must be one of 'stop' 'start' 'remove' default is 'start'\n", v->value); } else if (!strcasecmp (v->name, "callwaiting")) { if(strcasecmp(v->value, "auto")) config->callwaiting = ast_true (v->value); } else if (!strcasecmp (v->name, "dtmf")) { int val = dc_dtmf_str2setting(v->value); if(val >= 0) config->dtmf = val; else ast_log(LOG_ERROR, "Invalid value for 'dtmf': '%s', setting default 'relax'\n", v->value); } else if (!strcasecmp (v->name, "mindtmfgap")) { errno = 0; config->mindtmfgap = (int) strtol (v->value, (char**) NULL, 10); if ((config->mindtmfgap == 0 && errno == EINVAL) || config->mindtmfgap < 0) { ast_log(LOG_ERROR, "Invalid value for 'mindtmfgap' '%s', setting default %d\n", v->value, DEFAULT_MINDTMFGAP); config->mindtmfgap = DEFAULT_MINDTMFGAP; } } else if (!strcasecmp (v->name, "mindtmfduration")) { errno = 0; config->mindtmfduration = (int) strtol (v->value, (char**) NULL, 10); if ((config->mindtmfduration == 0 && errno == EINVAL) || config->mindtmfduration < 0) { ast_log(LOG_ERROR, "Invalid value for 'mindtmfgap' '%s', setting default %d\n", v->value, DEFAULT_MINDTMFDURATION); config->mindtmfduration = DEFAULT_MINDTMFDURATION; } } else if (!strcasecmp (v->name, "mindtmfinterval")) { errno = 0; config->mindtmfinterval = (int) strtol (v->value, (char**) NULL, 10); if ((config->mindtmfinterval == 0 && errno == EINVAL) || config->mindtmfinterval < 0) { ast_log(LOG_ERROR, "Invalid value for 'mindtmfinterval' '%s', setting default %d\n", v->value, DEFAULT_MINDTMFINTERVAL); config->mindtmfduration = DEFAULT_MINDTMFINTERVAL; } } } }
EXPORT_DEF int at_enque_sms (struct cpvt* cpvt, const char* destination, const char* msg, unsigned validity_minutes, int report_req, void ** id) { ssize_t res; char buf[1024] = "AT+CMGS=\""; char pdu_buf[2048]; pvt_t* pvt = cpvt->pvt; at_queue_cmd_t at_cmd[] = { { CMD_AT_CMGS, RES_SMS_PROMPT, ATQ_CMD_FLAG_DEFAULT, { ATQ_CMD_TIMEOUT_2S, 0} , NULL, 0 }, { CMD_AT_SMSTEXT, RES_OK, ATQ_CMD_FLAG_DEFAULT, { ATQ_CMD_TIMEOUT_40S, 0} , NULL, 0 } }; if(pvt->use_pdu) { /* set default validity period */ if(validity_minutes <= 0) validity_minutes = 3 * 24 * 60; /* res = pdu_build(pdu_buf, sizeof(pdu_buf), pvt->sms_scenter, destination, msg, validity_minutes, report_req); */ res = pdu_build(pdu_buf, sizeof(pdu_buf), "", destination, msg, validity_minutes, report_req); if(res <= 0) { if(res == -E2BIG) { ast_verb (3, "[%s] SMS Message too long, PDU has limit 140 octets\n", PVT_ID(pvt)); ast_log (LOG_WARNING, "[%s] SMS Message too long, PDU has limit 140 octets\n", PVT_ID(pvt)); } /* TODO: complain on other errors */ return res; } if(res > (int)(sizeof(pdu_buf) - 2)) return -1; return at_enque_pdu(cpvt, pdu_buf, NULL, 0, 0, id); } else { at_cmd[0].length = 9; res = str_recode (RECODE_ENCODE, STR_ENCODING_UCS2_HEX, destination, strlen (destination), buf + at_cmd[0].length, sizeof(buf) - at_cmd[0].length - 3); if(res <= 0) { ast_log (LOG_ERROR, "[%s] Error converting SMS number to UCS-2\n", PVT_ID(pvt)); return -4; } at_cmd[0].length += res; buf[at_cmd[0].length++] = '"'; buf[at_cmd[0].length++] = '\r'; buf[at_cmd[0].length] = '\0'; } at_cmd[0].data = ast_strdup (buf); if(!at_cmd[0].data) return -ENOMEM; res = strlen (msg); // if(!pvt->use_pdu) // { if (pvt->use_ucs2_encoding) { /* NOTE: bg: i test limit of no response is 133, but for +CMS ERROR: ? */ /* message limit in 178 octet of TPDU (w/o SCA) Headers: Type(1)+MR(1)+DA(3..12)+PID(1)+DCS(1)+VP(0,1,7)+UDL(1) = 8..24 (usually 14) */ if(res > 70) { ast_log (LOG_ERROR, "[%s] SMS message too long, 70 symbols max\n", PVT_ID(pvt)); return -4; } res = str_recode (RECODE_ENCODE, STR_ENCODING_UCS2_HEX, msg, res, pdu_buf, sizeof(pdu_buf) - 2); if (res < 0) { ast_free (at_cmd[0].data); ast_log (LOG_ERROR, "[%s] Error converting SMS to UCS-2: '%s'\n", PVT_ID(pvt), msg); return -4; } pdu_buf[res++] = 0x1a; pdu_buf[res] = 0; at_cmd[1].length = res; } else { if(res > 140) { ast_log (LOG_ERROR, "[%s] SMS message too long, 140 symbols max\n", PVT_ID(pvt)); return -4; } at_cmd[1].length = snprintf (pdu_buf, sizeof(pdu_buf), "%.160s\x1a", msg); } // } at_cmd[1].data = ast_strdup(pdu_buf); if(!at_cmd[1].data) { ast_free(at_cmd[0].data); return -ENOMEM; } return at_queue_insert_task(cpvt, at_cmd, ITEMS_OF(at_cmd), 0, (struct at_queue_task **)id); }
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "at_parse.h" /* at_parse_*() */ #include "mutils.h" /* ITEMS_OF() */ int ok = 0; int faults = 0; int test_strcmp(const char *pa, const char *pb) { int retval; if (pa == NULL) pa = ""; if (pb == NULL) pb = ""; retval = strcmp(pa,pb); if (retval != 0) { int x = 0; while (pa[x] == pb[x] && pa[x] != 0) { x++; } printf("String '%s' and '%s' differs at " "offset %d '%c' != '%c'\n", pa, pb, x, pa[x], pb[x]); } return (retval); } #/* */ void test_parse_cnum() { static const struct test_case { const char * input; const char * result; } cases[] = { { "+CNUM: \"*Subscriber Number\",\"+79139131234\",145", "+79139131234" }, { "+CNUM: \"Subscriber Number\",\"\",145", "" }, { "+CNUM: \"Subscriber Number\",,145", "" }, { "+CNUM: \"\",\"+79139131234\",145", "+79139131234" }, { "+CNUM: ,\"\",145", "" }, { "+CNUM: ,,145", "" }, { "+CNUM: \"\",+79139131234\",145", "+79139131234" }, { "+CNUM: \"\",+79139131234,145", "+79139131234" }, }; unsigned idx = 0; char * input; const char * res; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cnum", input); res = at_parse_cnum(input); if(test_strcmp(res, cases[idx].result) == 0) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = \"%s\"\t%s\n", res, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_cops() { static const struct test_case { const char * input; const char * result; } cases[] = { { "+COPS: 0,0,\"TELE2\",0", "TELE2" }, { "+COPS: 0,0,\"TELE2,0", "TELE2" }, { "+COPS: 0,0,TELE2,0", "TELE2" }, }; unsigned idx = 0; char * input; const char * res; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cops", input); res = at_parse_cops(input); if(test_strcmp(res, cases[idx].result) == 0) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = \"%s\"\t%s\n", res, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_creg() { struct result { int res; int gsm_reg; int gsm_reg_status; char * lac; char * ci; }; static const struct test_case { const char * input; struct result result; } cases[] = { { "+CREG: 2,1,9110,7E6", { 0, 1, 1, "9110", "7E6"} }, { "+CREG: 2,1,XXXX,AAAA", { 0, 1, 1, "XXXX", "AAAA"} }, }; unsigned idx = 0; char * input; struct result result; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_creg", input); result.res = at_parse_creg(input, strlen(input), &result.gsm_reg, &result.gsm_reg_status, &result.lac, &result.ci); if(result.res == cases[idx].result.res && result.gsm_reg == cases[idx].result.gsm_reg && result.gsm_reg_status == cases[idx].result.gsm_reg_status && test_strcmp(result.lac, cases[idx].result.lac) == 0 && test_strcmp(result.ci, cases[idx].result.ci) == 0 ) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = %d (%d,%d,\"%s\",\"%s\")\t%s\n", result.res, result.gsm_reg, result.gsm_reg_status, result.lac, result.ci, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_cmti() { static const struct test_case { const char * input; int result; } cases[] = { { "+CMTI: \"ME\",41", 41 }, { "+CMTI: 0,111", 111 }, { "+CMTI: ", -1 }, }; unsigned idx = 0; char * input; int result; const char * msg; for(; idx < ITEMS_OF(cases); ++idx) { input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cmti", input); result = at_parse_cmti(input); if(result == cases[idx].result) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } fprintf(stderr, " = %d\t%s\n", result, msg); free(input); } fprintf(stderr, "\n"); } #/* */ void test_parse_cmgr() { struct result { const char * res; char * str; char * oa; str_encoding_t oa_enc; char * msg; str_encoding_t msg_enc; }; static const struct test_case { const char * input; struct result result; } cases[] = { { "+CMGR: \"REC READ\",\"+79139131234\",,\"10/12/05,22:00:04+12\"\r\n041F04400438043204350442", { NULL, "\"REC READ\",\"+79139131234", "+79139131234", STR_ENCODING_7BIT, "041F04400438043204350442", STR_ENCODING_UNKNOWN } }, { "+CMGR: \"REC READ\",\"002B00370039003500330037003600310032003000350032\",,\"10/12/05,22:00:04+12\"\r\n041F04400438043204350442", { NULL, "\"REC READ\",\"002B00370039003500330037003600310032003000350032", "002B00370039003500330037003600310032003000350032", STR_ENCODING_UNKNOWN, "041F04400438043204350442", STR_ENCODING_UNKNOWN } }, { "+CMGR: 0,,106\r\n07911111111100F3040B911111111111F200000121702214952163B1582C168BC562B1984C2693C96432994C369BCD66B3D96C369BD168341A8D46A3D168B55AAD56ABD56AB59ACD66B3D96C369BCD76BBDD6EB7DBED76BBE170381C0E87C3E170B95C2E97CBE572B91C0C0683C16030180C", { NULL, "B1582C168BC562B1984C2693C96432994C369BCD66B3D96C369BD168341A8D46A3D168B55AAD56ABD56AB59ACD66B3D96C369BCD76BBDD6EB7DBED76BBE170381C0E87C3E170B95C2E97CBE572B91C0C0683C16030180C", "+11111111112", STR_ENCODING_7BIT, "B1582C168BC562B1984C2693C96432994C369BCD66B3D96C369BD168341A8D46A3D168B55AAD56ABD56AB59ACD66B3D96C369BCD76BBDD6EB7DBED76BBE170381C0E87C3E170B95C2E97CBE572B91C0C0683C16030180C", STR_ENCODING_7BIT_HEX_PAD_0 } }, { "+CMGR: 0,,159\r\n07919740430900F3440B912222222220F20008012180004390218C0500030003010031003100310031003100310031003100310031003200320032003200320032003200320032003200330033003300330033003300330033003300330034003400340034003400340034003400340034003500350035003500350035003500350035003500360036003600360036003600360036003600360037003700370037003700370037", { NULL, "0031003100310031003100310031003100310031003200320032003200320032003200320032003200330033003300330033003300330033003300330034003400340034003400340034003400340034003500350035003500350035003500350035003500360036003600360036003600360036003600360037003700370037003700370037", "+22222222022", STR_ENCODING_7BIT, "0031003100310031003100310031003100310031003200320032003200320032003200320032003200330033003300330033003300330033003300330034003400340034003400340034003400340034003500350035003500350035003500350035003500360036003600360036003600360036003600360037003700370037003700370037", STR_ENCODING_UCS2_HEX } }, { "+CMGR: 0,,158\r\n07916407970970F6400A912222222222000041903021825180A0050003000301A9E5391D14060941439015240409414290102404094142901024040941429010240409414290106405594142901564055941429012A40429AD4AABD22A7481AC56101264455A915624C80AB282AC20A1D06A0559415610D20A4282AC2024C80AB282AC202BC80AB282AC2E9012B4042D414A90D2055282942E90D20502819420254809528294", { NULL, "A9E5391D14060941439015240409414290102404094142901024040941429010240409414290106405594142901564055941429012A40429AD4AABD22A7481AC56101264455A915624C80AB282AC20A1D06A0559415610D20A4282AC2024C80AB282AC202BC80AB282AC2E9012B4042D414A90D2055282942E90D20502819420254809528294", "+2222222222", STR_ENCODING_7BIT, "A9E5391D14060941439015240409414290102404094142901024040941429010240409414290106405594142901564055941429012A40429AD4AABD22A7481AC56101264455A915624C80AB282AC20A1D06A0559415610D20A4282AC2024C80AB282AC202BC80AB282AC2E9012B4042D414A90D2055282942E90D20502819420254809528294", STR_ENCODING_7BIT_HEX_PAD_1, } }, { "+CMGR: 0,,55\r\n07912933035011804409D055F3DB5D060000411120712071022A080701030003990202A09976D7E9E5390B640FB3D364103DCD668364B3562CD692C1623417", { NULL, "A09976D7E9E5390B640FB3D364103DCD668364B3562CD692C1623417", "553", STR_ENCODING_7BIT, "A09976D7E9E5390B640FB3D364103DCD668364B3562CD692C1623417", STR_ENCODING_7BIT_HEX_PAD_5, } }, }; unsigned idx = 0; char * input; struct result result; char oa[200]; char buffer_res[256]; char buffer_dec[256]; const char * msg; result.oa = oa; for(; idx < ITEMS_OF(cases); ++idx) { result.str = input = strdup(cases[idx].input); fprintf(stderr, "%s(\"%s\")...", "at_parse_cmgr", input); result.res = at_parse_cmgr(&result.str, strlen(result.str), result.oa, sizeof(oa), &result.oa_enc, &result.msg, &result.msg_enc); if( ((result.res == NULL && result.res == cases[idx].result.res) || test_strcmp(result.res, cases[idx].result.res) == 0) && test_strcmp(result.str, cases[idx].result.str) == 0 && test_strcmp(result.oa, cases[idx].result.oa) == 0 && result.oa_enc == cases[idx].result.oa_enc && test_strcmp(result.msg, cases[idx].result.msg) == 0 && result.msg_enc == cases[idx].result.msg_enc ) { msg = "OK"; ok++; } else { msg = "FAIL"; faults++; } memset(buffer_res, 0, sizeof(buffer_res)); memset(buffer_dec, 0, sizeof(buffer_dec)); str_recode(RECODE_DECODE, result.msg_enc, result.msg, strlen(result.msg), buffer_res, sizeof(buffer_res)); str_recode(RECODE_DECODE, cases[idx].result.msg_enc, cases[idx].result.msg, strlen(cases[idx].result.msg), buffer_dec, sizeof(buffer_dec)); fprintf(stderr, " = '%s' ('%s','%s',%d,'%s',%d,'%s','%s')\t%s\n", result.res, result.str, result.oa, result.oa_enc, result.msg, result.msg_enc, buffer_res, buffer_dec, msg); free(input); } fprintf(stderr, "\n"); }
/*! * \brief Enque initialization commands * \param cpvt -- cpvt structure * \param from_command -- begin initialization from this command in list * \return 0 on success */ EXPORT_DEF int at_enque_initialization(struct cpvt* cpvt, at_cmd_t from_command) { static const char cmd2[] = "ATZ\r"; static const char cmd3[] = "ATE0\r"; static const char cmd5[] = "AT+CGMI\r"; static const char cmd6[] = "AT+CSCA?\r"; static const char cmd7[] = "AT+CGMM\r"; static const char cmd8[] = "AT+CGMR\r"; static const char cmd9[] = "AT+CMEE=0\r"; static const char cmd10[] = "AT+CGSN\r"; static const char cmd11[] = "AT+CIMI\r"; static const char cmd12[] = "AT+CPIN?\r"; static const char cmd13[] = "AT+COPS=0,0\r"; static const char cmd14[] = "AT+CREG=2\r"; static const char cmd15[] = "AT+CREG?\r"; static const char cmd16[] = "AT+CNUM\r"; static const char cmd17[] = "AT^CVOICE?\r"; // static const char cmd18[] = "AT+CLIP=0\r"; static const char cmd19[] = "AT+CSSN=1,1\r"; static const char cmd21[] = "AT+CSCS=\"UCS2\"\r"; static const char cmd22[] = "AT+CPMS=\"ME\",\"ME\",\"ME\"\r"; static const char cmd23[] = "AT+CNMI=2,1,0,0,0\r"; static const char cmd24[] = "AT+CSQ\r"; static const at_queue_cmd_t st_cmds[] = { ATQ_CMD_DECLARE_ST(CMD_AT, cmd_at), ATQ_CMD_DECLARE_ST(CMD_AT_Z, cmd2), /* optional, reload configuration */ ATQ_CMD_DECLARE_ST(CMD_AT_E, cmd3), /* disable echo */ ATQ_CMD_DECLARE_DYN(CMD_AT_U2DIAG), /* optional, Enable or disable some devices */ ATQ_CMD_DECLARE_ST(CMD_AT_CGMI, cmd5), /* Getting manufacturer info */ ATQ_CMD_DECLARE_ST(CMD_AT_CGMM, cmd7), /* Get Product name */ ATQ_CMD_DECLARE_ST(CMD_AT_CGMR, cmd8), /* Get software version */ ATQ_CMD_DECLARE_ST(CMD_AT_CMEE, cmd9), /* set MS Error Report to 'ERROR' only TODO: change to 1 or 2 and add support in response handlers */ ATQ_CMD_DECLARE_ST(CMD_AT_CGSN, cmd10), /* IMEI Read */ ATQ_CMD_DECLARE_ST(CMD_AT_CIMI, cmd11), /* IMSI Read */ ATQ_CMD_DECLARE_ST(CMD_AT_CPIN, cmd12), /* check is password authentication requirement and the remainder validation times */ ATQ_CMD_DECLARE_ST(CMD_AT_COPS_INIT, cmd13), /* Read operator name */ ATQ_CMD_DECLARE_STI(CMD_AT_CREG_INIT,cmd14), /* GSM registration status setting */ ATQ_CMD_DECLARE_ST(CMD_AT_CREG, cmd15), /* GSM registration status */ ATQ_CMD_DECLARE_ST(CMD_AT_CNUM, cmd16), /* Get Subscriber number */ ATQ_CMD_DECLARE_ST(CMD_AT_CVOICE, cmd17), /* read the current voice mode, and return sampling rate、data bit、frame period */ ATQ_CMD_DECLARE_ST(CMD_AT_CSCA, cmd6), /* Get SMS Service center address */ // ATQ_CMD_DECLARE_ST(CMD_AT_CLIP, cmd18), /* disable Calling line identification presentation in unsolicited response +CLIP: <number>,<type>[,<subaddr>,<satype>[,[<alpha>][,<CLI validitity>]] */ ATQ_CMD_DECLARE_ST(CMD_AT_CSSN, cmd19), /* activate Supplementary Service Notification with CSSI and CSSU */ ATQ_CMD_DECLARE_DYN(CMD_AT_CMGF), /* Set Message Format */ ATQ_CMD_DECLARE_STI(CMD_AT_CSCS, cmd21), /* UCS-2 text encoding */ ATQ_CMD_DECLARE_ST(CMD_AT_CPMS, cmd22), /* SMS Storage Selection */ /* pvt->initialized = 1 after successful of CMD_AT_CNMI */ ATQ_CMD_DECLARE_ST(CMD_AT_CNMI, cmd23), /* New SMS Notification Setting +CNMI=[<mode>[,<mt>[,<bm>[,<ds>[,<bfr>]]]]] */ ATQ_CMD_DECLARE_ST(CMD_AT_CSQ, cmd24), /* Query Signal quality */ }; unsigned in, out; int begin = -1; int err; char * ptmp1 = NULL; char * ptmp2 = NULL; pvt_t * pvt = cpvt->pvt; at_queue_cmd_t cmds[ITEMS_OF(st_cmds)]; /* customize list */ for(in = out = 0; in < ITEMS_OF(st_cmds); in++) { if(begin == -1) { if(st_cmds[in].cmd == from_command) begin = in; else continue; } if(st_cmds[in].cmd == CMD_AT_Z && !CONF_SHARED(pvt, resetdongle)) continue; if(st_cmds[in].cmd == CMD_AT_U2DIAG && CONF_SHARED(pvt, u2diag) == -1) continue; memcpy(&cmds[out], &st_cmds[in], sizeof(st_cmds[in])); if(cmds[out].cmd == CMD_AT_U2DIAG) { err = at_fill_generic_cmd(&cmds[out], "AT^U2DIAG=%d\r", CONF_SHARED(pvt, u2diag)); if(err) goto failure; ptmp1 = cmds[out].data; } else if(cmds[out].cmd == CMD_AT_CMGF) { err = at_fill_generic_cmd(&cmds[out], "AT+CMGF=%d\r", CONF_SHARED(pvt, smsaspdu) ? 0 : 1); if(err) goto failure; ptmp2 = cmds[out].data; } if(cmds[out].cmd == from_command) begin = out; out++; } if(out > 0) return at_queue_insert(cpvt, cmds, out, 0); return 0; failure: if(ptmp1) ast_free(ptmp1); if(ptmp2) ast_free(ptmp2); return err; }