00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "asterisk.h"
00033
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 53780 $")
00035
00036 #include <sys/types.h>
00037 #include <netinet/in.h>
00038 #include <stdlib.h>
00039 #include <unistd.h>
00040 #include <string.h>
00041 #include <stdlib.h>
00042 #include <ctype.h>
00043 #include <stdio.h>
00044 #include <errno.h>
00045
00046 #include "asterisk/file.h"
00047 #include "asterisk/logger.h"
00048 #include "asterisk/channel.h"
00049 #include "asterisk/pbx.h"
00050 #include "asterisk/module.h"
00051 #include "asterisk/adsi.h"
00052 #include "asterisk/options.h"
00053 #include "asterisk/utils.h"
00054 #include "asterisk/lock.h"
00055
00056 static char *app = "ADSIProg";
00057
00058 static char *synopsis = "Load Asterisk ADSI Scripts into phone";
00059
00060
00061
00062 static char *descrip =
00063 " ADSIProg(script): This application programs an ADSI Phone with the given\n"
00064 "script. If nothing is specified, the default script (asterisk.adsi) is used.\n";
00065
00066 struct adsi_event {
00067 int id;
00068 char *name;
00069 };
00070
00071 static struct adsi_event events[] = {
00072 { 1, "CALLERID" },
00073 { 2, "VMWI" },
00074 { 3, "NEARANSWER" },
00075 { 4, "FARANSWER" },
00076 { 5, "ENDOFRING" },
00077 { 6, "IDLE" },
00078 { 7, "OFFHOOK" },
00079 { 8, "CIDCW" },
00080 { 9, "BUSY" },
00081 { 10, "FARRING" },
00082 { 11, "DIALTONE" },
00083 { 12, "RECALL" },
00084 { 13, "MESSAGE" },
00085 { 14, "REORDER" },
00086 { 15, "DISTINCTIVERING" },
00087 { 16, "RING" },
00088 { 17, "REMINDERRING" },
00089 { 18, "SPECIALRING" },
00090 { 19, "CODEDRING" },
00091 { 20, "TIMER" },
00092 { 21, "INUSE" },
00093 { 22, "EVENT22" },
00094 { 23, "EVENT23" },
00095 { 24, "CPEID" },
00096 };
00097
00098 static struct adsi_event justify[] = {
00099 { 0, "CENTER" },
00100 { 1, "RIGHT" },
00101 { 2, "LEFT" },
00102 { 3, "INDENT" },
00103 };
00104
00105 #define STATE_NORMAL 0
00106 #define STATE_INKEY 1
00107 #define STATE_INSUB 2
00108 #define STATE_INIF 3
00109
00110 #define MAX_RET_CODE 20
00111 #define MAX_SUB_LEN 255
00112 #define MAX_MAIN_LEN 1600
00113
00114 #define ARG_STRING (1 << 0)
00115 #define ARG_NUMBER (1 << 1)
00116
00117 struct adsi_soft_key {
00118 char vname[40];
00119 int retstrlen;
00120 int initlen;
00121 int id;
00122 int defined;
00123 char retstr[80];
00124 };
00125
00126 struct adsi_subscript {
00127 char vname[40];
00128 int id;
00129 int defined;
00130 int datalen;
00131 int inscount;
00132 int ifinscount;
00133 char *ifdata;
00134 char data[2048];
00135 };
00136
00137 struct adsi_state {
00138 char vname[40];
00139 int id;
00140 };
00141
00142 struct adsi_flag {
00143 char vname[40];
00144 int id;
00145 };
00146
00147 struct adsi_display {
00148 char vname[40];
00149 int id;
00150 char data[70];
00151 int datalen;
00152 };
00153
00154 struct adsi_script {
00155 int state;
00156 int numkeys;
00157 int numsubs;
00158 int numstates;
00159 int numdisplays;
00160 int numflags;
00161 struct adsi_soft_key *key;
00162 struct adsi_subscript *sub;
00163
00164 struct adsi_display displays[63];
00165
00166 struct adsi_state states[256];
00167
00168 struct adsi_soft_key keys[62];
00169
00170 struct adsi_subscript subs[128];
00171
00172 struct adsi_flag flags[7];
00173
00174
00175 unsigned char sec[5];
00176 char desc[19];
00177 unsigned char fdn[5];
00178 int ver;
00179 };
00180
00181
00182 static int process_token(void *out, char *src, int maxlen, int argtype)
00183 {
00184 if ((strlen(src) > 1) && src[0] == '\"') {
00185
00186 if (!(argtype & ARG_STRING))
00187 return -1;
00188 src++;
00189
00190 if (maxlen > strlen(src) - 1)
00191 maxlen = strlen(src) - 1;
00192 memcpy(out, src, maxlen);
00193 ((char *)out)[maxlen] = '\0';
00194 } else if (!ast_strlen_zero(src) && (src[0] == '\\')) {
00195 if (!(argtype & ARG_NUMBER))
00196 return -1;
00197
00198 if (sscanf(src, "%o", (int *)out) != 1)
00199 return -1;
00200 if (argtype & ARG_STRING) {
00201
00202 *((unsigned int *)out) = htonl(*((unsigned int *)out));
00203 }
00204 } else if ((strlen(src) > 2) && (src[0] == '0') && (tolower(src[1]) == 'x')) {
00205 if (!(argtype & ARG_NUMBER))
00206 return -1;
00207
00208 if (sscanf(src + 2, "%x", (unsigned int *)out) != 1)
00209 return -1;
00210 if (argtype & ARG_STRING) {
00211
00212 *((unsigned int *)out) = htonl(*((unsigned int *)out));
00213 }
00214 } else if ((!ast_strlen_zero(src) && isdigit(src[0]))) {
00215 if (!(argtype & ARG_NUMBER))
00216 return -1;
00217
00218 if (sscanf(src, "%d", (int *)out) != 1)
00219 return -1;
00220 if (argtype & ARG_STRING) {
00221
00222 *((unsigned int *)out) = htonl(*((unsigned int *)out));
00223 }
00224 } else
00225 return -1;
00226 return 0;
00227 }
00228
00229 static char *get_token(char **buf, char *script, int lineno)
00230 {
00231 char *tmp = *buf;
00232 char *keyword;
00233 int quoted = 0;
00234
00235 while(*tmp && (*tmp < 33))
00236 tmp++;
00237 if (!*tmp)
00238 return NULL;
00239 keyword = tmp;
00240 while(*tmp && ((*tmp > 32) || quoted)) {
00241 if (*tmp == '\"') {
00242 quoted = !quoted;
00243 }
00244 tmp++;
00245 }
00246 if (quoted) {
00247 ast_log(LOG_WARNING, "Mismatched quotes at line %d of %s\n", lineno, script);
00248 return NULL;
00249 }
00250 *tmp = '\0';
00251 tmp++;
00252 while(*tmp && (*tmp < 33))
00253 tmp++;
00254
00255 *buf = tmp;
00256 return keyword;
00257 }
00258
00259 static char *validdtmf = "123456789*0#ABCD";
00260
00261 static int send_dtmf(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
00262 {
00263 char dtmfstr[80];
00264 char *a;
00265 int bytes=0;
00266 a = get_token(&args, script, lineno);
00267 if (!a) {
00268 ast_log(LOG_WARNING, "Expecting something to send for SENDDTMF at line %d of %s\n", lineno, script);
00269 return 0;
00270 }
00271 if (process_token(dtmfstr, a, sizeof(dtmfstr) - 1, ARG_STRING)) {
00272 ast_log(LOG_WARNING, "Invalid token for SENDDTMF at line %d of %s\n", lineno, script);
00273 return 0;
00274 }
00275 a = dtmfstr;
00276 while(*a) {
00277 if (strchr(validdtmf, *a)) {
00278 *buf = *a;
00279 buf++;
00280 bytes++;
00281 } else
00282 ast_log(LOG_WARNING, "'%c' is not a valid DTMF tone at line %d of %s\n", *a, lineno, script);
00283 a++;
00284 }
00285 return bytes;
00286 }
00287
00288 static int goto_line(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
00289 {
00290 char *page;
00291 char *gline;
00292 int line;
00293 unsigned char cmd;
00294 page = get_token(&args, script, lineno);
00295 gline = get_token(&args, script, lineno);
00296 if (!page || !gline) {
00297 ast_log(LOG_WARNING, "Expecting page and line number for GOTOLINE at line %d of %s\n", lineno, script);
00298 return 0;
00299 }
00300 if (!strcasecmp(page, "INFO")) {
00301 cmd = 0;
00302 } else if (!strcasecmp(page, "COMM")) {
00303 cmd = 0x80;
00304 } else {
00305 ast_log(LOG_WARNING, "Expecting either 'INFO' or 'COMM' page, got got '%s' at line %d of %s\n", page, lineno, script);
00306 return 0;
00307 }
00308 if (process_token(&line, gline, sizeof(line), ARG_NUMBER)) {
00309 ast_log(LOG_WARNING, "Invalid line number '%s' at line %d of %s\n", gline, lineno, script);
00310 return 0;
00311 }
00312 cmd |= line;
00313 buf[0] = 0x8b;
00314 buf[1] = cmd;
00315 return 2;
00316 }
00317
00318 static int goto_line_rel(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
00319 {
00320 char *dir;
00321 char *gline;
00322 int line;
00323 unsigned char cmd;
00324 dir = get_token(&args, script, lineno);
00325 gline = get_token(&args, script, lineno);
00326 if (!dir || !gline) {
00327 ast_log(LOG_WARNING, "Expecting direction and number of lines for GOTOLINEREL at line %d of %s\n", lineno, script);
00328 return 0;
00329 }
00330 if (!strcasecmp(dir, "UP")) {
00331 cmd = 0;
00332 } else if (!strcasecmp(dir, "DOWN")) {
00333 cmd = 0x20;
00334 } else {
00335 ast_log(LOG_WARNING, "Expecting either 'UP' or 'DOWN' direction, got '%s' at line %d of %s\n", dir, lineno, script);
00336 return 0;
00337 }
00338 if (process_token(&line, gline, sizeof(line), ARG_NUMBER)) {
00339 ast_log(LOG_WARNING, "Invalid line number '%s' at line %d of %s\n", gline, lineno, script);
00340 return 0;
00341 }
00342 cmd |= line;
00343 buf[0] = 0x8c;
00344 buf[1] = cmd;
00345 return 2;
00346 }
00347
00348 static int send_delay(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
00349 {
00350 char *gtime;
00351 int ms;
00352 gtime = get_token(&args, script, lineno);
00353 if (!gtime) {
00354 ast_log(LOG_WARNING, "Expecting number of milliseconds to wait at line %d of %s\n", lineno, script);
00355 return 0;
00356 }
00357 if (process_token(&ms, gtime, sizeof(ms), ARG_NUMBER)) {
00358 ast_log(LOG_WARNING, "Invalid delay milliseconds '%s' at line %d of %s\n", gtime, lineno, script);
00359 return 0;
00360 }
00361 buf[0] = 0x90;
00362 if (id == 11)
00363 buf[1] = ms / 100;
00364 else
00365 buf[1] = ms / 10;
00366 return 2;
00367 }
00368
00369 static int set_state(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
00370 {
00371 char *gstate;
00372 int state;
00373 gstate = get_token(&args, script, lineno);
00374 if (!gstate) {
00375 ast_log(LOG_WARNING, "Expecting state number at line %d of %s\n", lineno, script);
00376 return 0;
00377 }
00378 if (process_token(&state, gstate, sizeof(state), ARG_NUMBER)) {
00379 ast_log(LOG_WARNING, "Invalid state number '%s' at line %d of %s\n", gstate, lineno, script);
00380 return 0;
00381 }
00382 buf[0] = id;
00383 buf[1] = state;
00384 return 2;
00385 }
00386
00387 static int cleartimer(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
00388 {
00389 char *tok;
00390 tok = get_token(&args, script, lineno);
00391 if (tok)
00392 ast_log(LOG_WARNING, "Clearing timer requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
00393
00394 buf[0] = id;
00395
00396 if (id == 7)
00397 buf[1] = 0x10;
00398 else
00399 buf[1] = 0x00;
00400 return 2;
00401 }
00402
00403 static struct adsi_flag *getflagbyname(struct adsi_script *state, char *name, char *script, int lineno, int create)
00404 {
00405 int x;
00406 for (x=0;x<state->numflags;x++)
00407 if (!strcasecmp(state->flags[x].vname, name))
00408 return &state->flags[x];
00409
00410 if (!create)
00411 return NULL;
00412 if (state->numflags > 6) {
00413 ast_log(LOG_WARNING, "No more flag space at line %d of %s\n", lineno, script);
00414 return NULL;
00415 }
00416 ast_copy_string(state->flags[state->numflags].vname, name, sizeof(state->flags[state->numflags].vname));
00417 state->flags[state->numflags].id = state->numflags + 1;
00418 state->numflags++;
00419 return &state->flags[state->numflags-1];
00420 }
00421
00422 static int setflag(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
00423 {
00424 char *tok;
00425 char sname[80];
00426 struct adsi_flag *flag;
00427 tok = get_token(&args, script, lineno);
00428 if (!tok) {
00429 ast_log(LOG_WARNING, "Setting flag requires a flag number at line %d of %s\n", lineno, script);
00430 return 0;
00431 }
00432 if (process_token(sname, tok, sizeof(sname) - 1, ARG_STRING)) {
00433 ast_log(LOG_WARNING, "Invalid flag '%s' at line %d of %s\n", tok, lineno, script);
00434 return 0;
00435 }
00436 flag = getflagbyname(state, sname, script, lineno, 0);
00437 if (!flag) {
00438 ast_log(LOG_WARNING, "Flag '%s' is undeclared at line %d of %s\n", sname, lineno, script);
00439 return 0;
00440 }
00441 buf[0] = id;
00442 buf[1] = ((flag->id & 0x7) << 4) | 1;
00443 return 2;
00444 }
00445
00446 static int clearflag(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
00447 {
00448 char *tok;
00449 struct adsi_flag *flag;
00450 char sname[80];
00451 tok = get_token(&args, script, lineno);
00452 if (!tok) {
00453 ast_log(LOG_WARNING, "Clearing flag requires a flag number at line %d of %s\n", lineno, script);
00454 return 0;
00455 }
00456 if (process_token(sname, tok, sizeof(sname) - 1, ARG_STRING)) {
00457 ast_log(LOG_WARNING, "Invalid flag '%s' at line %d of %s\n", tok, lineno, script);
00458 return 0;
00459 }
00460 flag = getflagbyname(state, sname, script, lineno, 0);
00461 if (!flag) {
00462 ast_log(LOG_WARNING, "Flag '%s' is undeclared at line %d of %s\n", sname, lineno, script);
00463 return 0;
00464 }
00465 buf[0] = id;
00466 buf[1] = ((flag->id & 0x7) << 4);
00467 return 2;
00468 }
00469
00470 static int starttimer(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
00471 {
00472 char *tok;
00473 int secs;
00474 tok = get_token(&args, script, lineno);
00475 if (!tok) {
00476 ast_log(LOG_WARNING, "Missing number of seconds at line %d of %s\n", lineno, script);
00477 return 0;
00478 }
00479 if (process_token(&secs, tok, sizeof(secs), ARG_NUMBER)) {
00480 ast_log(LOG_WARNING, "Invalid number of seconds '%s' at line %d of %s\n", tok, lineno, script);
00481 return 0;
00482 }
00483 buf[0] = id;
00484 buf[1] = 0x1;
00485 buf[2] = secs;
00486 return 3;
00487 }
00488
00489 static int geteventbyname(char *name)
00490 {
00491 int x;
00492 for (x=0;x<sizeof(events) / sizeof(events[0]); x++) {
00493 if (!strcasecmp(events[x].name, name))
00494 return events[x].id;
00495 }
00496 return 0;
00497 }
00498
00499 static int getjustifybyname(char *name)
00500 {
00501 int x;
00502 for (x=0;x<sizeof(justify) / sizeof(justify[0]); x++) {
00503 if (!strcasecmp(justify[x].name, name))
00504 return justify[x].id;
00505 }
00506 return -1;
00507 }
00508
00509 static struct adsi_soft_key *getkeybyname(struct adsi_script *state, char *name, char *script, int lineno)
00510 {
00511 int x;
00512 for (x=0;x<state->numkeys;x++)
00513 if (!strcasecmp(state->keys[x].vname, name))
00514 return &state->keys[x];
00515 if (state->numkeys > 61) {
00516 ast_log(LOG_WARNING, "No more key space at line %d of %s\n", lineno, script);
00517 return NULL;
00518 }
00519 ast_copy_string(state->keys[state->numkeys].vname, name, sizeof(state->keys[state->numkeys].vname));
00520 state->keys[state->numkeys].id = state->numkeys + 2;
00521 state->numkeys++;
00522 return &state->keys[state->numkeys-1];
00523 }
00524
00525 static struct adsi_subscript *getsubbyname(struct adsi_script *state, char *name, char *script, int lineno)
00526 {
00527 int x;
00528 for (x=0;x<state->numsubs;x++)
00529 if (!strcasecmp(state->subs[x].vname, name))
00530 return &state->subs[x];
00531 if (state->numsubs > 127) {
00532 ast_log(LOG_WARNING, "No more subscript space at line %d of %s\n", lineno, script);
00533 return NULL;
00534 }
00535 ast_copy_string(state->subs[state->numsubs].vname, name, sizeof(state->subs[state->numsubs].vname));
00536 state->subs[state->numsubs].id = state->numsubs;
00537 state->numsubs++;
00538 return &state->subs[state->numsubs-1];
00539 }
00540
00541 static struct adsi_state *getstatebyname(struct adsi_script *state, char *name, char *script, int lineno, int create)
00542 {
00543 int x;
00544 for (x=0;x<state->numstates;x++)
00545 if (!strcasecmp(state->states[x].vname, name))
00546 return &state->states[x];
00547
00548 if (!create)
00549 return NULL;
00550 if (state->numstates > 253) {
00551 ast_log(LOG_WARNING, "No more state space at line %d of %s\n", lineno, script);
00552 return NULL;
00553 }
00554 ast_copy_string(state->states[state->numstates].vname, name, sizeof(state->states[state->numstates].vname));
00555 state->states[state->numstates].id = state->numstates + 1;
00556 state->numstates++;
00557 return &state->states[state->numstates-1];
00558 }
00559
00560 static struct adsi_display *getdisplaybyname(struct adsi_script *state, char *name, char *script, int lineno, int create)
00561 {
00562 int x;
00563 for (x=0;x<state->numdisplays;x++)
00564 if (!strcasecmp(state->displays[x].vname, name))
00565 return &state->displays[x];
00566
00567 if (!create)
00568 return NULL;
00569 if (state->numdisplays > 61) {
00570 ast_log(LOG_WARNING, "No more display space at line %d of %s\n", lineno, script);
00571 return NULL;
00572 }
00573 ast_copy_string(state->displays[state->numdisplays].vname, name, sizeof(state->displays[state->numdisplays].vname));
00574 state->displays[state->numdisplays].id = state->numdisplays + 1;
00575 state->numdisplays++;
00576 return &state->displays[state->numdisplays-1];
00577 }
00578
00579 static int showkeys(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
00580 {
00581 char *tok;
00582 char newkey[80];
00583 int bytes;
00584 unsigned char keyid[6];
00585 int x;
00586 int flagid=0;
00587 struct adsi_soft_key *key;
00588 struct adsi_flag *flag;
00589
00590 for (x=0;x<7;x++) {
00591
00592 tok = get_token(&args, script, lineno);
00593 if (!tok)
00594 break;
00595 if (!strcasecmp(tok, "UNLESS")) {
00596
00597 tok = get_token(&args, script, lineno);
00598 if (!tok) {
00599 ast_log(LOG_WARNING, "Missing argument for UNLESS clause at line %d of %s\n", lineno, script);
00600 } else if (process_token(newkey, tok, sizeof(newkey) - 1, ARG_STRING)) {
00601 ast_log(LOG_WARNING, "Invalid flag name '%s' at line %d of %s\n", tok, lineno, script);
00602 } else if (!(flag = getflagbyname(state, newkey, script, lineno, 0))) {
00603 ast_log(LOG_WARNING, "Flag '%s' is undeclared at line %d of %s\n", newkey, lineno, script);
00604 } else
00605 flagid = flag->id;
00606 if ((tok = get_token(&args, script, lineno)))
00607 ast_log(LOG_WARNING, "Extra arguments after UNLESS clause: '%s' at line %d of %s\n", tok, lineno, script);
00608 break;
00609 }
00610 if (x > 5) {
00611 ast_log(LOG_WARNING, "Only 6 keys can be defined, ignoring '%s' at line %d of %s\n", tok, lineno, script);
00612 break;
00613 }
00614 if (process_token(newkey, tok, sizeof(newkey) - 1, ARG_STRING)) {
00615 ast_log(LOG_WARNING, "Invalid token for key name: %s\n", tok);
00616 continue;
00617 }
00618
00619 key = getkeybyname(state, newkey, script, lineno);
00620 if (!key)
00621 break;
00622 keyid[x] = key->id;
00623 }
00624 buf[0] = id;
00625 buf[1] = (flagid & 0x7) << 3 | (x & 0x7);
00626 for (bytes=0;bytes<x;bytes++) {
00627 buf[bytes + 2] = keyid[bytes];
00628 }
00629 return 2 + x;
00630 }
00631
00632 static int showdisplay(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
00633 {
00634 char *tok;
00635 char dispname[80];
00636 int line=0;
00637 int flag=0;
00638 int cmd = 3;
00639 struct adsi_display *disp;
00640
00641
00642 tok = get_token(&args, script, lineno);
00643 if (!tok || process_token(dispname, tok, sizeof(dispname) - 1, ARG_STRING)) {
00644 ast_log(LOG_WARNING, "Invalid display name: %s at line %d of %s\n", tok ? tok : "<nothing>", lineno, script);
00645 return 0;
00646 }
00647 disp = getdisplaybyname(state, dispname, script, lineno, 0);
00648 if (!disp) {
00649 ast_log(LOG_WARNING, "Display '%s' is undefined at line %d of %s\n", dispname, lineno, script);
00650 return 0;
00651 }
00652
00653 tok = get_token(&args, script, lineno);
00654 if (!tok || strcasecmp(tok, "AT")) {
00655 ast_log(LOG_WARNING, "Missing token 'AT' at line %d of %s\n", lineno, script);
00656 return 0;
00657 }
00658
00659 tok = get_token(&args, script, lineno);
00660 if (!tok || process_token(&line, tok, sizeof(line), ARG_NUMBER)) {
00661 ast_log(LOG_WARNING, "Invalid line: '%s' at line %d of %s\n", tok ? tok : "<nothing>", lineno, script);
00662 return 0;
00663 }
00664 tok = get_token(&args, script, lineno);
00665 if (tok && !strcasecmp(tok, "NOUPDATE")) {
00666 cmd = 1;
00667 tok = get_token(&args, script, lineno);
00668 }
00669 if (tok && !strcasecmp(tok, "UNLESS")) {
00670
00671 tok = get_token(&args, script, lineno);
00672 if (!tok) {
00673 ast_log(LOG_WARNING, "Missing argument for UNLESS clause at line %d of %s\n", lineno, script);
00674 } else if (process_token(&flag, tok, sizeof(flag), ARG_NUMBER)) {
00675 ast_log(LOG_WARNING, "Invalid flag number '%s' at line %d of %s\n", tok, lineno, script);
00676 }
00677 if ((tok = get_token(&args, script, lineno)))
00678 ast_log(LOG_WARNING, "Extra arguments after UNLESS clause: '%s' at line %d of %s\n", tok, lineno, script);
00679 }
00680
00681 buf[0] = id;
00682 buf[1] = (cmd << 6) | (disp->id & 0x3f);
00683 buf[2] = ((line & 0x1f) << 3) | (flag & 0x7);
00684 return 3;
00685 }
00686
00687 static int cleardisplay(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
00688 {
00689 char *tok;
00690 tok = get_token(&args, script, lineno);
00691 if (tok)
00692 ast_log(LOG_WARNING, "Clearing display requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
00693
00694 buf[0] = id;
00695 buf[1] = 0x00;
00696 return 2;
00697 }
00698
00699 static int digitdirect(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
00700 {
00701 char *tok;
00702 tok = get_token(&args, script, lineno);
00703 if (tok)
00704 ast_log(LOG_WARNING, "Digitdirect requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
00705
00706 buf[0] = id;
00707 buf[1] = 0x7;
00708 return 2;
00709 }
00710
00711 static int clearcbone(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
00712 {
00713 char *tok;
00714 tok = get_token(&args, script, lineno);
00715 if (tok)
00716 ast_log(LOG_WARNING, "CLEARCB1 requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
00717
00718 buf[0] = id;
00719 buf[1] = 0;
00720 return 2;
00721 }
00722
00723 static int digitcollect(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
00724 {
00725 char *tok;
00726 tok = get_token(&args, script, lineno);
00727 if (tok)
00728 ast_log(LOG_WARNING, "Digitcollect requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
00729
00730 buf[0] = id;
00731 buf[1] = 0xf;
00732 return 2;
00733 }
00734
00735 static int subscript(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
00736 {
00737 char *tok;
00738 char subscript[80];
00739 struct adsi_subscript *sub;
00740 tok = get_token(&args, script, lineno);
00741 if (!tok) {
00742 ast_log(LOG_WARNING, "Missing subscript to call at line %d of %s\n", lineno, script);
00743 return 0;
00744 }
00745 if (process_token(subscript, tok, sizeof(subscript) - 1, ARG_STRING)) {
00746 ast_log(LOG_WARNING, "Invalid number of seconds '%s' at line %d of %s\n", tok, lineno, script);
00747 return 0;
00748 }
00749 sub = getsubbyname(state, subscript, script, lineno);
00750 if (!sub)
00751 return 0;
00752 buf[0] = 0x9d;
00753 buf[1] = sub->id;
00754 return 2;
00755 }
00756
00757 static int onevent(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
00758 {
00759 char *tok;
00760 char subscript[80];
00761 char sname[80];
00762 int sawin=0;
00763 int event;
00764 int snums[8];
00765 int scnt = 0;
00766 int x;
00767 struct adsi_subscript *sub;
00768 tok = get_token(&args, script, lineno);
00769 if (!tok) {
00770 ast_log(LOG_WARNING, "Missing event for 'ONEVENT' at line %d of %s\n", lineno, script);
00771 return 0;
00772 }
00773 event = geteventbyname(tok);
00774 if (event < 1) {
00775 ast_log(LOG_WARNING, "'%s' is not a valid event name, at line %d of %s\n", args, lineno, script);
00776 return 0;
00777 }
00778 tok = get_token(&args, script, lineno);
00779 while ((!sawin && !strcasecmp(tok, "IN")) ||
00780 (sawin && !strcasecmp(tok, "OR"))) {
00781 sawin = 1;
00782 if (scnt > 7) {
00783 ast_log(LOG_WARNING, "No more than 8 states may be specified for inclusion at line %d of %s\n", lineno, script);
00784 return 0;
00785 }
00786
00787 tok = get_token(&args, script, lineno);
00788 if (process_token(sname, tok, sizeof(sname), ARG_STRING)) {
00789 ast_log(LOG_WARNING, "'%s' is not a valid state name at line %d of %s\n", tok, lineno, script);
00790 return 0;
00791 }
00792 if ((snums[scnt] = getstatebyname(state, sname, script, lineno, 0) < 0)) {
00793 ast_log(LOG_WARNING, "State '%s' not declared at line %d of %s\n", sname, lineno, script);
00794 return 0;
00795 }
00796 scnt++;
00797 tok = get_token(&args, script, lineno);
00798 if (!tok)
00799 break;
00800 }
00801 if (!tok || strcasecmp(tok, "GOTO")) {
00802 if (!tok)
00803 tok = "<nothing>";
00804 if (sawin)
00805 ast_log(LOG_WARNING, "Got '%s' while looking for 'GOTO' or 'OR' at line %d of %s\n", tok, lineno, script);
00806 else
00807 ast_log(LOG_WARNING, "Got '%s' while looking for 'GOTO' or 'IN' at line %d of %s\n", tok, lineno, script);
00808 }
00809 tok = get_token(&args, script, lineno);
00810 if (!tok) {
00811 ast_log(LOG_WARNING, "Missing subscript to call at line %d of %s\n", lineno, script);
00812 return 0;
00813 }
00814 if (process_token(subscript, tok, sizeof(subscript) - 1, ARG_STRING)) {
00815 ast_log(LOG_WARNING, "Invalid subscript '%s' at line %d of %s\n", tok, lineno, script);
00816 return 0;
00817 }
00818 sub = getsubbyname(state, subscript, script, lineno);
00819 if (!sub)
00820 return 0;
00821 buf[0] = 8;
00822 buf[1] = event;
00823 buf[2] = sub->id | 0x80;
00824 for (x=0;x<scnt;x++)
00825 buf[3 + x] = snums[x];
00826 return 3 + scnt;
00827 }
00828
00829 struct adsi_key_cmd {
00830 char *name;
00831 int id;
00832 int (*add_args)(char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno);
00833 };
00834
00835 static struct adsi_key_cmd kcmds[] = {
00836 { "SENDDTMF", 0, send_dtmf },
00837
00838 { "ONHOOK", 0x81 },
00839 { "OFFHOOK", 0x82 },
00840 { "FLASH", 0x83 },
00841 { "WAITDIALTONE", 0x84 },
00842
00843 { "BLANK", 0x86 },
00844 { "SENDCHARS", 0x87 },
00845 { "CLEARCHARS", 0x88 },
00846 { "BACKSPACE", 0x89 },
00847
00848 { "GOTOLINE", 0x8b, goto_line },
00849 { "GOTOLINEREL", 0x8c, goto_line_rel },
00850 { "PAGEUP", 0x8d },
00851 { "PAGEDOWN", 0x8e },
00852
00853 { "DELAY", 0x90, send_delay },
00854 { "DIALPULSEONE", 0x91 },
00855 { "DATAMODE", 0x92 },
00856 { "VOICEMODE", 0x93 },
00857
00858
00859 { "CLEARCB1", 0x95, clearcbone },
00860 { "DIGITCOLLECT", 0x96, digitcollect },
00861 { "DIGITDIRECT", 0x96, digitdirect },
00862 { "CLEAR", 0x97 },
00863 { "SHOWDISPLAY", 0x98, showdisplay },
00864 { "CLEARDISPLAY", 0x98, cleardisplay },
00865 { "SHOWKEYS", 0x99, showkeys },
00866 { "SETSTATE", 0x9a, set_state },
00867 { "TIMERSTART", 0x9b, starttimer },
00868 { "TIMERCLEAR", 0x9b, cleartimer },
00869 { "SETFLAG", 0x9c, setflag },
00870 { "CLEARFLAG", 0x9c, clearflag },
00871 { "GOTO", 0x9d, subscript },
00872 { "EVENT22", 0x9e },
00873 { "EVENT23", 0x9f },
00874 { "EXIT", 0xa0 },
00875 };
00876
00877 static struct adsi_key_cmd opcmds[] = {
00878
00879
00880 { "SHOWKEYS", 2, showkeys },
00881
00882 { "SHOWDISPLAY", 3, showdisplay },
00883 { "CLEARDISPLAY", 3, cleardisplay },
00884 { "CLEAR", 5 },
00885 { "SETSTATE", 6, set_state },
00886 { "TIMERSTART", 7, starttimer },
00887 { "TIMERCLEAR", 7, cleartimer },
00888 { "ONEVENT", 8, onevent },
00889
00890 { "SETFLAG", 10, setflag },
00891 { "CLEARFLAG", 10, clearflag },
00892 { "DELAY", 11, send_delay },
00893 { "EXIT", 12 },
00894 };
00895
00896
00897 static int process_returncode(struct adsi_soft_key *key, char *code, char *args, struct adsi_script *state, char *script, int lineno)
00898 {
00899 int x;
00900 char *unused;
00901 int res;
00902 for (x=0;x<sizeof(kcmds) / sizeof(kcmds[0]);x++) {
00903 if ((kcmds[x].id > -1) && !strcasecmp(kcmds[x].name, code)) {
00904 if (kcmds[x].add_args) {
00905 res = kcmds[x].add_args(key->retstr + key->retstrlen,
00906 code, kcmds[x].id, args, state, script, lineno);
00907 if ((key->retstrlen + res - key->initlen) <= MAX_RET_CODE)
00908 key->retstrlen += res;
00909 else
00910 ast_log(LOG_WARNING, "No space for '%s' code in key '%s' at line %d of %s\n", kcmds[x].name, key->vname, lineno, script);
00911 } else {
00912 if ((unused = get_token(&args, script, lineno)))
00913 ast_log(LOG_WARNING, "'%s' takes no arguments at line %d of %s (token is '%s')\n", kcmds[x].name, lineno, script, unused);