📄 irdial.c
字号:
/* Copyright (C) 2002-2003 Gerd Rausch, BlauLogic (http://blaulogic.com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Except as contained in this notice, neither the name of BlauLogic nor the name(s) of the author(s) may be used to endorse or promote products derived from this software without specific prior written permission. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR(S) OR BLAULOGIC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/#include <ctype.h>#include <string.h>#include <pgmspace.h>#include <io.h>#if FLASHEND>=0x3FFF#define IRDIAL_WITH_IRCOMM#endif#include <misc.h>#include <irphy.h>#include <irlap.h>#include <irobex.h>#ifdef IRDIAL_WITH_IRCOMM#include <ircomm.h>#endif#include "rules.h"#include "dtmf.h"typedef enum File_Type { FILE_TYPE_UNKNOWN, FILE_TYPE_TEXT_UNKNOWN, FILE_TYPE_TEXT_RULES, FILE_TYPE_TEXT_DIAL, FILE_TYPE_TEXT_OTHER, FILE_TYPE_VCARD} File_Type;typedef enum Text_Parse_State { TEXT_PARSE_STATE_INITIAL, TEXT_PARSE_STATE_WHITESPACE, TEXT_PARSE_STATE_NUMBER, TEXT_PARSE_STATE_DONE} Text_Parse_State;typedef struct Text_Parse_Context { uint8_t state;} Text_Parse_Context;typedef enum VCard_Parse_State { VCARD_PARSE_STATE_INITIAL, VCARD_PARSE_STATE_KEYWORD, VCARD_PARSE_STATE_MATCH, VCARD_PARSE_STATE_NEXT_FIELD, VCARD_PARSE_STATE_NEXT_LINE, VCARD_PARSE_STATE_NUMBER, VCARD_PARSE_STATE_DONE} VCard_Parse_State;typedef enum VCard_Match_Field { VCARD_MATCH_FIELD_TEL, VCARD_MATCH_FIELD_PREF, VCARD_MATCH_FIELD_QUOTED_PRINTABLE,} VCard_Match_Field;typedef struct VCard_Parse_Context { uint8_t state; char escape_char; uint8_t escaped; uint8_t is_tel, is_pref; uint8_t match_field; prog_char *match_p;} VCard_Parse_Context;#ifdef IRDIAL_WITH_IRCOMMtypedef enum IRComm_Parse_State { IRCOMM_PARSE_STATE_INITIAL, IRCOMM_PARSE_STATE_GOT_A, IRCOMM_PARSE_STATE_GOT_AT, IRCOMM_PARSE_STATE_ECHO, IRCOMM_PARSE_STATE_NUMBER, IRCOMM_PARSE_STATE_DONE} IRComm_Parse_State;typedef struct IRComm_Parse_Context { uint8_t state;} IRComm_Parse_Context;#endif /* IRDIAL_WITH_IRCOMM */typedef struct Parse_Context { uint8_t file_type; uint8_t number_len; char number[64]; union { Text_Parse_Context text; VCard_Parse_Context vcard;#ifdef IRDIAL_WITH_IRCOMM IRComm_Parse_Context ircomm;#endif Rules_Parse_Context rules; } u;} Parse_Context;static uint8_t append_digit(Parse_Context *context_p, char a_c){ char c; switch(a_c) { case ' ': case '\t': case '-': case '/': case '.': case ')': return 1; case '(': c='='; break; case '+': case '=': case ',': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '*': case '#': c=a_c; break; default: return 0; } if(context_p->number_len<sizeof(context_p->number)-1) context_p->number[context_p->number_len++]=c; return 1;}static void parse_text(Parse_Context *context_p, uint8_t *data, uint16_t size){ uint16_t i; i=0; while(i<size) { switch(context_p->u.text.state) { case TEXT_PARSE_STATE_INITIAL: if(data[i]=='\r' || data[i]=='\n') context_p->u.text.state=TEXT_PARSE_STATE_WHITESPACE; i++; break; case TEXT_PARSE_STATE_WHITESPACE: if(data[i]!=' ' && data[i]!='\t' && data[i]!='\r' && data[i]!='\n') context_p->u.text.state=TEXT_PARSE_STATE_NUMBER; else i++; break; case TEXT_PARSE_STATE_NUMBER: if(!append_digit(context_p, data[i])) context_p->u.text.state=TEXT_PARSE_STATE_DONE; else i++; break; default: return; } }}static void parse_vcard(Parse_Context *context_p, uint8_t *data, uint16_t size){ uint16_t i; i=0; while(i<size) { switch(context_p->u.vcard.state) { case VCARD_PARSE_STATE_INITIAL: context_p->u.vcard.escape_char='\\'; context_p->u.vcard.escaped=0; context_p->u.vcard.is_tel=0; context_p->u.vcard.is_pref=0; context_p->u.vcard.state=VCARD_PARSE_STATE_KEYWORD; break; case VCARD_PARSE_STATE_KEYWORD: switch(toupper(data[i])) { case 'T': context_p->u.vcard.state=VCARD_PARSE_STATE_MATCH; context_p->u.vcard.match_field=VCARD_MATCH_FIELD_TEL; context_p->u.vcard.match_p=PSTR("EL"); break; case 'P': context_p->u.vcard.state=VCARD_PARSE_STATE_MATCH; context_p->u.vcard.match_field=VCARD_MATCH_FIELD_PREF; context_p->u.vcard.match_p=PSTR("REF"); break; case 'E': context_p->u.vcard.state=VCARD_PARSE_STATE_MATCH; context_p->u.vcard.match_field=VCARD_MATCH_FIELD_QUOTED_PRINTABLE; context_p->u.vcard.match_p=PSTR("NCODING=QUOTED-PRINTABLE"); break; case ';': break; case ':': context_p->u.vcard.state=VCARD_PARSE_STATE_NEXT_LINE; break; case '\n': context_p->u.vcard.state=VCARD_PARSE_STATE_INITIAL; break; default: context_p->u.vcard.state=VCARD_PARSE_STATE_NEXT_FIELD; } i++; break; case VCARD_PARSE_STATE_MATCH: switch(data[i]) { case 0: context_p->u.vcard.state=VCARD_PARSE_STATE_DONE; break; case ';': case ':': if(!PRG_RDB(context_p->u.vcard.match_p)) { switch(context_p->u.vcard.match_field) { case VCARD_MATCH_FIELD_TEL: context_p->u.vcard.is_tel=1; break; case VCARD_MATCH_FIELD_PREF: context_p->u.vcard.is_pref=1; break; case VCARD_MATCH_FIELD_QUOTED_PRINTABLE: context_p->u.vcard.escape_char='='; break; } } context_p->u.vcard.state=VCARD_PARSE_STATE_NEXT_FIELD; break; default: if(toupper(data[i])==PRG_RDB(context_p->u.vcard.match_p)) { context_p->u.vcard.match_p++; i++; } else context_p->u.vcard.state=VCARD_PARSE_STATE_NEXT_FIELD; } break; case VCARD_PARSE_STATE_NEXT_FIELD: switch(data[i]) { case ';': context_p->u.vcard.state=VCARD_PARSE_STATE_KEYWORD; break; case ':': if(context_p->u.vcard.is_tel && (!context_p->number_len || context_p->u.vcard.is_pref)) { context_p->number_len=0; context_p->u.vcard.state=VCARD_PARSE_STATE_NUMBER; } else context_p->u.vcard.state=VCARD_PARSE_STATE_NEXT_LINE; break; case '\n': context_p->u.vcard.state=VCARD_PARSE_STATE_INITIAL; break; } i++; break; case VCARD_PARSE_STATE_NEXT_LINE: if(!context_p->u.vcard.escaped) { if(data[i]==context_p->u.vcard.escape_char) context_p->u.vcard.escaped=1; else if(data[i]=='\n') context_p->u.vcard.state=VCARD_PARSE_STATE_INITIAL; } else if(data[i]!='\r') context_p->u.vcard.escaped=0; i++; break; case VCARD_PARSE_STATE_NUMBER: if(!append_digit(context_p, data[i])) context_p->u.text.state=VCARD_PARSE_STATE_NEXT_LINE; else i++; break; default: return; } }}static uint8_t put_name_cb(char *name, void *user_data){ Parse_Context *context_p=(Parse_Context *)user_data; char *ext; if((ext=strrchr(name, '.'))) { ext++; if(strcasecmp_P(ext, PSTR("txt"))==0) { context_p->file_type=FILE_TYPE_TEXT_UNKNOWN; } else if(strcasecmp_P(ext, PSTR("vcf"))==0) { context_p->file_type=FILE_TYPE_VCARD; context_p->u.vcard.state=VCARD_PARSE_STATE_INITIAL; } else context_p->file_type=FILE_TYPE_UNKNOWN; } else context_p->file_type=FILE_TYPE_UNKNOWN; return 1;}static uint8_t put_data_cb(uint8_t *data, uint16_t size, void *user_data){ Parse_Context *context_p=(Parse_Context *)user_data; if(context_p->file_type==FILE_TYPE_TEXT_UNKNOWN) { if(size>=6 && strncmp_P(data, PSTR("@rules"), 6)==0) { context_p->file_type=FILE_TYPE_TEXT_RULES; context_p->u.rules.state=RULES_PARSE_STATE_INITIAL; } else if(size>=5 && strncmp_P(data, PSTR("@dial"), 5)==0) { context_p->file_type=FILE_TYPE_TEXT_DIAL; context_p->u.text.state=TEXT_PARSE_STATE_INITIAL; } else context_p->file_type=FILE_TYPE_TEXT_OTHER; } switch(context_p->file_type) { case FILE_TYPE_TEXT_RULES: rules_parse(&context_p->u.rules, data, size); break; case FILE_TYPE_TEXT_DIAL: parse_text(context_p, data, size); break; case FILE_TYPE_VCARD: parse_vcard(context_p, data, size); break; } return 1;}#ifdef IRDIAL_WITH_IRCOMMstatic int16_t put_ircomm_cb(uint8_t *data, uint16_t size, uint8_t *resp_buf, uint16_t resp_buf_size, uint8_t *terminate_p, void *user_data){ Parse_Context *context_p=(Parse_Context *)user_data; uint16_t n, i; n=0; i=0; while(i<size) { switch(context_p->u.text.state) { case IRCOMM_PARSE_STATE_INITIAL: if(toupper(data[i])=='A') context_p->u.text.state=IRCOMM_PARSE_STATE_GOT_A; i++; break; case IRCOMM_PARSE_STATE_GOT_A: if(toupper(data[i])=='T') { context_p->u.text.state=IRCOMM_PARSE_STATE_GOT_AT; if(n+2<=resp_buf_size) { resp_buf[n++]='A'; resp_buf[n++]='T'; } } else context_p->u.text.state=IRCOMM_PARSE_STATE_INITIAL; i++; break; case IRCOMM_PARSE_STATE_GOT_AT: if(toupper(data[i])=='D') { context_p->u.text.state=IRCOMM_PARSE_STATE_NUMBER; i++; } else context_p->u.text.state=IRCOMM_PARSE_STATE_ECHO; break; case IRCOMM_PARSE_STATE_ECHO: if(data[i]=='\r' || data[i]=='\n') { context_p->u.text.state=IRCOMM_PARSE_STATE_INITIAL; if(n+6<=resp_buf_size) { memcpy_P(resp_buf+n, PSTR("\r\nOK\r\n"), 6); n+=6; } } else if(n<resp_buf_size) resp_buf[n++]=toupper(data[i]); i++; break; case IRCOMM_PARSE_STATE_NUMBER: if(data[i]!='\r' && data[i]!='\n') { append_digit(context_p, data[i]); i++; } else context_p->u.text.state=IRCOMM_PARSE_STATE_DONE; break; default: *terminate_p=1; return n; } } return n;}#endif /* IRDIAL_WITH_IRCOMM */int main(void){ IrLAP_Context irlap_ctx; Parse_Context parse_ctx; uint8_t success;#ifdef IRDIAL_WITH_IRCOMM IrIAS_Node *ias_nodes[3]; int16_t dlsap_sel;#endif irphy_reset(); irlap_init_context(&irlap_ctx);#ifdef IRDIAL_WITH_IRCOMM ias_nodes[0]=&irobex_ias_node; ias_nodes[1]=&ircomm_ias_node; ias_nodes[2]=0;#endif for(;;) { irphy_wait(-1); parse_ctx.file_type=FILE_TYPE_UNKNOWN; parse_ctx.number_len=0;#ifdef IRDIAL_WITH_IRCOMM if((dlsap_sel=irttp2_accept(&irlap_ctx, IRLMP_HINT1_OBEX | IRLMP_HINT1_COMM, ias_nodes))<0) continue; if(dlsap_sel==IRCOMM_LSAP_SEL_VAL) { parse_ctx.u.ircomm.state=IRCOMM_PARSE_STATE_INITIAL; ircomm2_serve(&irlap_ctx, put_ircomm_cb, &parse_ctx); success=1; } else success=irobex_receive(&irlap_ctx, put_name_cb, put_data_cb, &parse_ctx);#else success=irobex_receive(&irlap_ctx, put_name_cb, put_data_cb, &parse_ctx);#endif if(parse_ctx.file_type==FILE_TYPE_TEXT_RULES) rules_parse_finish(&parse_ctx.u.rules, success); if(!success) continue; parse_ctx.number[parse_ctx.number_len]=0; rules_apply(parse_ctx.number, sizeof(parse_ctx.number)); if(!*parse_ctx.number) continue; /* pull line switch */ sbi(DDRD, DDD3); cbi(PORTD, PD3); sleep_msec(3000); dtmf_dial(parse_ctx.number); sleep_msec(3000); /* release line switch */ sbi(PORTD, PD3); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -