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