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
00033 #include "asterisk.h"
00034
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 278132 $")
00036
00037 #include <time.h>
00038 #include <math.h>
00039
00040 #include "asterisk/ulaw.h"
00041 #include "asterisk/alaw.h"
00042 #include "asterisk/callerid.h"
00043 #include "asterisk/fskmodem.h"
00044 #include "asterisk/channel.h"
00045 #include "asterisk/module.h"
00046 #include "asterisk/config.h"
00047 #include "asterisk/file.h"
00048
00049 #define AST_API_MODULE
00050 #include "asterisk/adsi.h"
00051
00052 #define DEFAULT_ADSI_MAX_RETRIES 3
00053
00054 #define ADSI_MAX_INTRO 20
00055 #define ADSI_MAX_SPEED_DIAL 6
00056
00057 #define ADSI_FLAG_DATAMODE (1 << 8)
00058
00059 static int maxretries = DEFAULT_ADSI_MAX_RETRIES;
00060
00061
00062 #define ADSI_SPEED_DIAL 10
00063
00064 static char intro[ADSI_MAX_INTRO][20];
00065 static int aligns[ADSI_MAX_INTRO];
00066
00067 #define SPEEDDIAL_MAX_LEN 20
00068 static char speeddial[ADSI_MAX_SPEED_DIAL][3][SPEEDDIAL_MAX_LEN];
00069
00070 static int alignment = 0;
00071
00072 static int adsi_generate(unsigned char *buf, int msgtype, unsigned char *msg, int msglen, int msgnum, int last, format_t codec)
00073 {
00074 int sum, x, bytes = 0;
00075
00076 float cr = 1.0, ci = 0.0, scont = 0.0;
00077
00078 if (msglen > 255) {
00079 msglen = 255;
00080 }
00081
00082
00083 if (msgnum == 1) {
00084 for (x = 0; x < 150; x++) {
00085 PUT_CLID_MARKMS;
00086 }
00087 }
00088
00089
00090 PUT_CLID(msgtype);
00091 sum = msgtype;
00092
00093
00094 PUT_CLID(msglen + 1);
00095 sum += msglen + 1;
00096
00097
00098 PUT_CLID(msgnum);
00099 sum += msgnum;
00100
00101
00102 for (x = 0; x < msglen; x++) {
00103 PUT_CLID(msg[x]);
00104 sum += msg[x];
00105 }
00106
00107
00108 PUT_CLID(256-(sum & 0xff));
00109
00110 #if 0
00111 if (last) {
00112
00113 for (x = 0; x < 50; x++) {
00114 PUT_CLID_MARKMS;
00115 }
00116 }
00117 #endif
00118 return bytes;
00119
00120 }
00121
00122 static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int len, int *remain)
00123 {
00124
00125
00126 struct ast_frame *inf, outf;
00127 int amt;
00128
00129
00130 memset(&outf, 0, sizeof(outf));
00131
00132 if (remain && *remain) {
00133 amt = len;
00134
00135
00136 if (amt > *remain) {
00137 amt = *remain;
00138 } else {
00139 *remain = *remain - amt;
00140 }
00141 outf.frametype = AST_FRAME_VOICE;
00142 outf.subclass.codec = AST_FORMAT_ULAW;
00143 outf.data.ptr = buf;
00144 outf.datalen = amt;
00145 outf.samples = amt;
00146 if (ast_write(chan, &outf)) {
00147 ast_log(LOG_WARNING, "Failed to carefully write frame\n");
00148 return -1;
00149 }
00150
00151 buf += amt;
00152 len -= amt;
00153 }
00154
00155 while (len) {
00156 amt = len;
00157
00158
00159 if (ast_waitfor(chan, 1000) < 1) {
00160 return -1;
00161 }
00162
00163 if (!(inf = ast_read(chan))) {
00164 return -1;
00165 }
00166
00167
00168 if (inf->frametype != AST_FRAME_VOICE) {
00169 ast_frfree(inf);
00170 continue;
00171 }
00172
00173 if (inf->subclass.codec != AST_FORMAT_ULAW) {
00174 ast_log(LOG_WARNING, "Channel not in ulaw?\n");
00175 ast_frfree(inf);
00176 return -1;
00177 }
00178
00179 if (amt > inf->datalen) {
00180 amt = inf->datalen;
00181 } else if (remain) {
00182 *remain = inf->datalen - amt;
00183 }
00184 outf.frametype = AST_FRAME_VOICE;
00185 outf.subclass.codec = AST_FORMAT_ULAW;
00186 outf.data.ptr = buf;
00187 outf.datalen = amt;
00188 outf.samples = amt;
00189 if (ast_write(chan, &outf)) {
00190 ast_log(LOG_WARNING, "Failed to carefully write frame\n");
00191 ast_frfree(inf);
00192 return -1;
00193 }
00194
00195 buf += amt;
00196 len -= amt;
00197 ast_frfree(inf);
00198 }
00199 return 0;
00200 }
00201
00202 static int __adsi_transmit_messages(struct ast_channel *chan, unsigned char **msg, int *msglen, int *msgtype)
00203 {
00204
00205 unsigned char buf[24000 * 5];
00206 int pos = 0, res, x, start = 0, retries = 0, waittime, rem = 0, def;
00207 char ack[3];
00208 struct ast_frame *f;
00209
00210 if (chan->adsicpe == AST_ADSI_UNAVAILABLE) {
00211
00212 errno = ENOSYS;
00213 return -1;
00214 }
00215
00216 while (retries < maxretries) {
00217 if (!(chan->adsicpe & ADSI_FLAG_DATAMODE)) {
00218
00219 ast_gen_cas(buf, 0, 680, AST_FORMAT_ULAW);
00220
00221
00222 if (adsi_careful_send(chan, buf, 680, NULL)) {
00223 ast_log(LOG_WARNING, "Unable to send CAS\n");
00224 }
00225
00226
00227 waittime = 500;
00228 for (;;) {
00229 if (((res = ast_waitfor(chan, waittime)) < 1)) {
00230
00231 ast_debug(1, "No ADSI CPE detected (%d)\n", res);
00232 if (!chan->adsicpe) {
00233 chan->adsicpe = AST_ADSI_UNAVAILABLE;
00234 }
00235 errno = ENOSYS;
00236 return -1;
00237 }
00238 waittime = res;
00239 if (!(f = ast_read(chan))) {
00240 ast_debug(1, "Hangup in ADSI\n");
00241 return -1;
00242 }
00243 if (f->frametype == AST_FRAME_DTMF) {
00244 if (f->subclass.integer == 'A') {
00245
00246 if (!chan->adsicpe) {
00247 chan->adsicpe = AST_ADSI_AVAILABLE;
00248 }
00249 break;
00250 } else {
00251 if (f->subclass.integer == 'D') {
00252 ast_debug(1, "Off-hook capable CPE only, not ADSI\n");
00253 } else {
00254 ast_log(LOG_WARNING, "Unknown ADSI response '%c'\n", f->subclass.integer);
00255 }
00256 if (!chan->adsicpe) {
00257 chan->adsicpe = AST_ADSI_UNAVAILABLE;
00258 }
00259 errno = ENOSYS;
00260 ast_frfree(f);
00261 return -1;
00262 }
00263 }
00264 ast_frfree(f);
00265 }
00266
00267 ast_debug(1, "ADSI Compatible CPE Detected\n");
00268 } else {
00269 ast_debug(1, "Already in data mode\n");
00270 }
00271
00272 x = 0;
00273 pos = 0;
00274 #if 1
00275 def= ast_channel_defer_dtmf(chan);
00276 #endif
00277 while ((x < 6) && msg[x]) {
00278 if ((res = adsi_generate(buf + pos, msgtype[x], msg[x], msglen[x], x+1 - start, (x == 5) || !msg[x+1], AST_FORMAT_ULAW)) < 0) {
00279 ast_log(LOG_WARNING, "Failed to generate ADSI message %d on channel %s\n", x + 1, chan->name);
00280 return -1;
00281 }
00282 ast_debug(1, "Message %d, of %d input bytes, %d output bytes\n", x + 1, msglen[x], res);
00283 pos += res;
00284 x++;
00285 }
00286
00287
00288 rem = 0;
00289 res = adsi_careful_send(chan, buf, pos, &rem);
00290 if (!def) {
00291 ast_channel_undefer_dtmf(chan);
00292 }
00293 if (res) {
00294 return -1;
00295 }
00296
00297 ast_debug(1, "Sent total spill of %d bytes\n", pos);
00298
00299 memset(ack, 0, sizeof(ack));
00300
00301 if ((res = ast_readstring(chan, ack, 2, 1000, 1000, "")) < 0) {
00302 return -1;
00303 }
00304 if (ack[0] == 'D') {
00305 ast_debug(1, "Acked up to message %d\n", atoi(ack + 1)); start += atoi(ack + 1);
00306 if (start >= x) {
00307 break;
00308 } else {
00309 retries++;
00310 ast_debug(1, "Retransmitting (%d), from %d\n", retries, start + 1);
00311 }
00312 } else {
00313 retries++;
00314 ast_log(LOG_WARNING, "Unexpected response to ack: %s (retry %d)\n", ack, retries);
00315 }
00316 }
00317 if (retries >= maxretries) {
00318 ast_log(LOG_WARNING, "Maximum ADSI Retries (%d) exceeded\n", maxretries);
00319 errno = ETIMEDOUT;
00320 return -1;
00321 }
00322 return 0;
00323 }
00324
00325 int AST_OPTIONAL_API_NAME(ast_adsi_begin_download)(struct ast_channel *chan, char *service, unsigned char *fdn, unsigned char *sec, int version)
00326 {
00327 int bytes = 0;
00328 unsigned char buf[256];
00329 char ack[2];
00330
00331
00332
00333 bytes += ast_adsi_download_connect(buf + bytes, service, fdn, sec, version);
00334 if (ast_adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DOWNLOAD, 0)) {
00335 return -1;
00336 }
00337 if (ast_readstring(chan, ack, 1, 10000, 10000, "")) {
00338 return -1;
00339 }
00340 if (ack[0] == 'B') {
00341 return 0;
00342 }
00343 ast_debug(1, "Download was denied by CPE\n");
00344 return -1;
00345 }
00346
00347 int AST_OPTIONAL_API_NAME(ast_adsi_end_download)(struct ast_channel *chan)
00348 {
00349 int bytes = 0;
00350 unsigned char buf[256];
00351
00352
00353
00354 bytes += ast_adsi_download_disconnect(buf + bytes);
00355 if (ast_adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DOWNLOAD, 0)) {
00356 return -1;
00357 }
00358 return 0;
00359 }
00360
00361 int AST_OPTIONAL_API_NAME(ast_adsi_transmit_message_full)(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype, int dowait)
00362 {
00363 unsigned char *msgs[5] = { NULL, NULL, NULL, NULL, NULL };
00364 int msglens[5], msgtypes[5], newdatamode = (chan->adsicpe & ADSI_FLAG_DATAMODE), res, x, writeformat = chan->writeformat, readformat = chan->readformat, waitforswitch = 0;
00365
00366 for (x = 0; x < msglen; x += (msg[x+1]+2)) {
00367 if (msg[x] == ADSI_SWITCH_TO_DATA) {
00368 ast_debug(1, "Switch to data is sent!\n");
00369 waitforswitch++;
00370 newdatamode = ADSI_FLAG_DATAMODE;
00371 }
00372
00373 if (msg[x] == ADSI_SWITCH_TO_VOICE) {
00374 ast_debug(1, "Switch to voice is sent!\n");
00375 waitforswitch++;
00376 newdatamode = 0;
00377 }
00378 }
00379 msgs[0] = msg;
00380
00381 msglens[0] = msglen;
00382 msgtypes[0] = msgtype;
00383
00384 if (msglen > 253) {
00385 ast_log(LOG_WARNING, "Can't send ADSI message of %d bytes, too large\n", msglen);
00386 return -1;
00387 }
00388
00389 ast_stopstream(chan);
00390
00391 if (ast_set_write_format(chan, AST_FORMAT_ULAW)) {
00392 ast_log(LOG_WARNING, "Unable to set write format to ULAW\n");
00393 return -1;
00394 }
00395
00396 if (ast_set_read_format(chan, AST_FORMAT_ULAW)) {
00397 ast_log(LOG_WARNING, "Unable to set read format to ULAW\n");
00398 if (writeformat) {
00399 if (ast_set_write_format(chan, writeformat)) {
00400 ast_log(LOG_WARNING, "Unable to restore write format to %d\n", writeformat);
00401 }
00402 }
00403 return -1;
00404 }
00405 res = __adsi_transmit_messages(chan, msgs, msglens, msgtypes);
00406
00407 if (dowait) {
00408 ast_debug(1, "Wait for switch is '%d'\n", waitforswitch);
00409 while (waitforswitch-- && ((res = ast_waitfordigit(chan, 1000)) > 0)) {
00410 res = 0;
00411 ast_debug(1, "Waiting for 'B'...\n");
00412 }
00413 }
00414
00415 if (!res) {
00416 chan->adsicpe = (chan->adsicpe & ~ADSI_FLAG_DATAMODE) | newdatamode;
00417 }
00418
00419 if (writeformat) {
00420 ast_set_write_format(chan, writeformat);
00421 }
00422 if (readformat) {
00423 ast_set_read_format(chan, readformat);
00424 }
00425
00426 if (!res) {
00427 res = ast_safe_sleep(chan, 100 );
00428 }
00429 return res;
00430 }
00431
00432 int AST_OPTIONAL_API_NAME(ast_adsi_transmit_message)(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
00433 {
00434 return ast_adsi_transmit_message_full(chan, msg, msglen, msgtype, 1);
00435 }
00436
00437 static inline int ccopy(unsigned char *dst, const unsigned char *src, int max)
00438 {
00439 int x = 0;
00440
00441 while ((x < max) && src[x] && (src[x] != 0xff)) {
00442 dst[x] = src[x];
00443 x++;
00444 }
00445 return x;
00446 }
00447
00448 int AST_OPTIONAL_API_NAME(ast_adsi_load_soft_key)(unsigned char *buf, int key, const char *llabel, const char *slabel, char *ret, int data)
00449 {
00450 int bytes = 0;
00451
00452
00453 if ((key < 2) || (key > 33)) {
00454 return -1;
00455 }
00456
00457 buf[bytes++] = ADSI_LOAD_SOFTKEY;
00458
00459 bytes++;
00460
00461 buf[bytes++] = key;
00462
00463
00464 bytes += ccopy(buf + bytes, (const unsigned char *)llabel, 18);
00465
00466
00467 buf[bytes++] = 0xff;
00468
00469
00470 bytes += ccopy(buf + bytes, (const unsigned char *)slabel, 7);
00471
00472
00473
00474 if (ret) {
00475
00476 buf[bytes++] = 0xff;
00477 if (data) {
00478 buf[bytes++] = ADSI_SWITCH_TO_DATA2;
00479 }
00480
00481 bytes += ccopy(buf + bytes, (const unsigned char *)ret, 20);
00482
00483 }
00484
00485 buf[1] = bytes - 2;
00486 return bytes;
00487 }
00488
00489 int AST_OPTIONAL_API_NAME(ast_adsi_connect_session)(unsigned char *buf, unsigned char *fdn, int ver)
00490 {
00491 int bytes = 0, x;
00492
00493
00494 buf[bytes++] = ADSI_CONNECT_SESSION;
00495
00496
00497 bytes++;
00498
00499 if (fdn) {
00500 for (x = 0; x < 4; x++) {
00501 buf[bytes++] = fdn[x];
00502 }
00503 if (ver > -1) {
00504 buf[bytes++] = ver & 0xff;
00505 }
00506 }
00507
00508 buf[1] = bytes - 2;
00509 return bytes;
00510
00511 }
00512
00513 int AST_OPTIONAL_API_NAME(ast_adsi_download_connect)(unsigned char *buf, char *service, unsigned char *fdn, unsigned char *sec, int ver)
00514 {
00515 int bytes = 0, x;
00516
00517
00518 buf[bytes++] = ADSI_DOWNLOAD_CONNECT;
00519
00520
00521 bytes++;
00522
00523
00524 bytes+= ccopy(buf + bytes, (unsigned char *)service, 18);
00525
00526
00527 buf[bytes++] = 0xff;
00528
00529 for (x = 0; x < 4; x++) {
00530 buf[bytes++] = fdn[x];
00531 }
00532
00533 for (x = 0; x < 4; x++) {
00534 buf[bytes++] = sec[x];
00535 }
00536
00537 buf[bytes++] = ver & 0xff;
00538
00539 buf[1] = bytes - 2;
00540
00541 return bytes;
00542
00543 }
00544
00545 int AST_OPTIONAL_API_NAME(ast_adsi_disconnect_session)(unsigned char *buf)
00546 {
00547 int bytes = 0;
00548
00549
00550 buf[bytes++] = ADSI_DISC_SESSION;
00551
00552
00553 bytes++;
00554
00555 buf[1] = bytes - 2;
00556 return bytes;
00557
00558 }
00559
00560 int AST_OPTIONAL_API_NAME(ast_adsi_query_cpeid)(unsigned char *buf)
00561 {
00562 int bytes = 0;
00563 buf[bytes++] = ADSI_QUERY_CPEID;
00564
00565 bytes++;
00566 buf[1] = bytes - 2;
00567 return bytes;
00568 }
00569
00570 int AST_OPTIONAL_API_NAME(ast_adsi_query_cpeinfo)(unsigned char *buf)
00571 {
00572 int bytes = 0;
00573 buf[bytes++] = ADSI_QUERY_CONFIG;
00574
00575 bytes++;
00576 buf[1] = bytes - 2;
00577 return bytes;
00578 }
00579
00580 int AST_OPTIONAL_API_NAME(ast_adsi_read_encoded_dtmf)(struct ast_channel *chan, unsigned char *buf, int maxlen)
00581 {
00582 int bytes = 0, res, gotstar = 0, pos = 0;
00583 unsigned char current = 0;
00584
00585 memset(buf, 0, sizeof(buf));
00586
00587 while (bytes <= maxlen) {
00588
00589 if (!(res = ast_waitfordigit(chan, 1000))) {
00590 break;
00591 }
00592 if (res == '*') {
00593 gotstar = 1;
00594 continue;
00595 }
00596
00597 if ((res < '0') || (res > '9')) {
00598 continue;
00599 }
00600 res -= '0';
00601 if (gotstar) {
00602 res += 9;
00603 }
00604 if (pos) {
00605 pos = 0;
00606 buf[bytes++] = (res << 4) | current;
00607 } else {
00608 pos = 1;
00609 current = res;
00610 }
00611 gotstar = 0;
00612 }
00613
00614 return bytes;
00615 }
00616
00617 int AST_OPTIONAL_API_NAME(ast_adsi_get_cpeid)(struct ast_channel *chan, unsigned char *cpeid, int voice)
00618 {
00619 unsigned char buf[256] = "";
00620 int bytes = 0, res;
00621
00622 bytes += ast_adsi_data_mode(buf);
00623 ast_adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
00624
00625 bytes = 0;
00626 bytes += ast_adsi_query_cpeid(buf);
00627 ast_adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
00628
00629
00630 res = ast_adsi_read_encoded_dtmf(chan, cpeid, 4);
00631 if (res != 4) {
00632 ast_log(LOG_WARNING, "Got %d bytes back of encoded DTMF, expecting 4\n", res);
00633 res = 0;
00634 } else {
00635 res = 1;
00636 }
00637
00638 if (voice) {
00639 bytes = 0;
00640 bytes += ast_adsi_voice_mode(buf, 0);
00641 ast_adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
00642
00643 ast_waitfordigit(chan, 1000);
00644 }
00645 return res;
00646 }
00647
00648 int AST_OPTIONAL_API_NAME(ast_adsi_get_cpeinfo)(struct ast_channel *chan, int *width, int *height, int *buttons, int voice)
00649 {
00650 unsigned char buf[256] = "";
00651 int bytes = 0, res;
00652
00653 bytes += ast_adsi_data_mode(buf);
00654 ast_adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
00655
00656 bytes = 0;
00657 bytes += ast_adsi_query_cpeinfo(buf);
00658 ast_adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
00659
00660
00661 if ((res = ast_readstring(chan, (char *) buf, 2, 1000, 500, "")) < 0) {
00662 return res;
00663 }
00664 if (strlen((char *) buf) != 2) {
00665 ast_log(LOG_WARNING, "Got %d bytes of width, expecting 2\n", res);
00666 res = 0;
00667 } else {
00668 res = 1;
00669 }
00670 if (width) {
00671 *width = atoi((char *) buf);
00672 }
00673
00674 memset(buf, 0, sizeof(buf));
00675 if (res) {
00676 if ((res = ast_readstring(chan, (char *) buf, 2, 1000, 500, "")) < 0) {
00677 return res;
00678 }
00679 if (strlen((char *) buf) != 2) {
00680 ast_log(LOG_WARNING, "Got %d bytes of height, expecting 2\n", res);
00681 res = 0;
00682 } else {
00683 res = 1;
00684 }
00685 if (height) {
00686 *height = atoi((char *) buf);
00687 }
00688 }
00689
00690 memset(buf, 0, sizeof(buf));
00691 if (res) {
00692 if ((res = ast_readstring(chan, (char *) buf, 1, 1000, 500, "")) < 0) {
00693 return res;
00694 }
00695 if (strlen((char *) buf) != 1) {
00696 ast_log(LOG_WARNING, "Got %d bytes of buttons, expecting 1\n", res);
00697 res = 0;
00698 } else {
00699 res = 1;
00700 }
00701 if (buttons) {
00702 *buttons = atoi((char *) buf);
00703 }
00704 }
00705 if (voice) {
00706 bytes = 0;
00707 bytes += ast_adsi_voice_mode(buf, 0);
00708 ast_adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
00709
00710 ast_waitfordigit(chan, 1000);
00711 }
00712 return res;
00713 }
00714
00715 int AST_OPTIONAL_API_NAME(ast_adsi_data_mode)(unsigned char *buf)
00716 {
00717 int bytes = 0;
00718
00719
00720 buf[bytes++] = ADSI_SWITCH_TO_DATA;
00721
00722
00723 bytes++;
00724
00725 buf[1] = bytes - 2;
00726 return bytes;
00727
00728 }
00729
00730 int AST_OPTIONAL_API_NAME(ast_adsi_clear_soft_keys)(unsigned char *buf)
00731 {
00732 int bytes = 0;
00733
00734
00735 buf[bytes++] = ADSI_CLEAR_SOFTKEY;
00736
00737
00738 bytes++;
00739
00740 buf[1] = bytes - 2;
00741 return bytes;
00742
00743 }
00744
00745 int AST_OPTIONAL_API_NAME(ast_adsi_clear_screen)(unsigned char *buf)
00746 {
00747 int bytes = 0;
00748
00749
00750 buf[bytes++] = ADSI_CLEAR_SCREEN;
00751
00752
00753 bytes++;
00754
00755 buf[1] = bytes - 2;
00756 return bytes;
00757
00758 }
00759
00760 int AST_OPTIONAL_API_NAME(ast_adsi_voice_mode)(unsigned char *buf, int when)
00761 {
00762 int bytes = 0;
00763
00764
00765 buf[bytes++] = ADSI_SWITCH_TO_VOICE;
00766
00767
00768 bytes++;
00769
00770 buf[bytes++] = when & 0x7f;
00771
00772 buf[1] = bytes - 2;
00773 return bytes;
00774
00775 }
00776
00777 int AST_OPTIONAL_API_NAME(ast_adsi_available)(struct ast_channel *chan)
00778 {
00779 int cpe = chan->adsicpe & 0xff;
00780 if ((cpe == AST_ADSI_AVAILABLE) ||
00781 (cpe == AST_ADSI_UNKNOWN)) {
00782 return 1;
00783 }
00784 return 0;
00785 }
00786
00787 int AST_OPTIONAL_API_NAME(ast_adsi_download_disconnect)(unsigned char *buf)
00788 {
00789 int bytes = 0;
00790
00791
00792 buf[bytes++] = ADSI_DOWNLOAD_DISC;
00793
00794
00795 bytes++;
00796
00797 buf[1] = bytes - 2;
00798 return bytes;
00799
00800 }
00801
00802 int AST_OPTIONAL_API_NAME(ast_adsi_display)(unsigned char *buf, int page, int line, int just, int wrap,
00803 char *col1, char *col2)
00804 {
00805 int bytes = 0;
00806
00807
00808
00809 if (page) {
00810 if (line > 4) return -1;
00811 } else {
00812 if (line > 33) return -1;
00813 }
00814
00815 if (line < 1) {
00816 return -1;
00817 }
00818
00819 buf[bytes++] = ADSI_LOAD_VIRTUAL_DISP;
00820
00821
00822 bytes++;
00823
00824
00825 buf[bytes++] = ((page & 0x1) << 7) | ((wrap & 0x1) << 6) | (line & 0x3f);
00826
00827
00828 buf[bytes++] = (just & 0x3) << 5;
00829
00830
00831 buf[bytes++] = 0xff;
00832
00833
00834 bytes+= ccopy(buf + bytes, (unsigned char *)col1, 20);
00835
00836
00837 buf[bytes++] = 0xff;
00838
00839
00840 bytes += ccopy(buf + bytes, (unsigned char *)col2, 20);
00841
00842
00843 buf[1] = bytes - 2;
00844
00845 return bytes;
00846
00847 }
00848
00849 int AST_OPTIONAL_API_NAME(ast_adsi_input_control)(unsigned char *buf, int page, int line, int display, int format, int just)
00850 {
00851 int bytes = 0;
00852
00853 if (page) {
00854 if (line > 4) return -1;
00855 } else {
00856 if (line > 33) return -1;
00857 }
00858
00859 if (line < 1) {
00860 return -1;
00861 }
00862
00863 buf[bytes++] = ADSI_INPUT_CONTROL;
00864 bytes++;
00865 buf[bytes++] = ((page & 1) << 7) | (line & 0x3f);
00866 buf[bytes++] = ((display & 1) << 7) | ((just & 0x3) << 4) | (format & 0x7);
00867
00868 buf[1] = bytes - 2;
00869 return bytes;
00870 }
00871
00872 int AST_OPTIONAL_API_NAME(ast_adsi_input_format)(unsigned char *buf, int num, int dir, int wrap, char *format1, char *format2)
00873 {
00874 int bytes = 0;
00875
00876 if (ast_strlen_zero((char *) format1)) {
00877 return -1;
00878 }
00879
00880 buf[bytes++] = ADSI_INPUT_FORMAT;
00881 bytes++;
00882 buf[bytes++] = ((dir & 1) << 7) | ((wrap & 1) << 6) | (num & 0x7);
00883 bytes += ccopy(buf + bytes, (unsigned char *) format1, 20);
00884 buf[bytes++] = 0xff;
00885 if (!ast_strlen_zero(format2)) {
00886 bytes += ccopy(buf + bytes, (unsigned char *) format2, 20);
00887 }
00888 buf[1] = bytes - 2;
00889 return bytes;
00890 }
00891
00892 int AST_OPTIONAL_API_NAME(ast_adsi_set_keys)(unsigned char *buf, unsigned char *keys)
00893 {
00894 int bytes = 0, x;
00895
00896
00897 buf[bytes++] = ADSI_INIT_SOFTKEY_LINE;
00898
00899 bytes++;
00900
00901 for (x = 0; x < 6; x++) {
00902 buf[bytes++] = (keys[x] & 0x3f) ? keys[x] : (keys[x] | 0x1);
00903 }
00904 buf[1] = bytes - 2;
00905 return bytes;
00906 }
00907
00908 int AST_OPTIONAL_API_NAME(ast_adsi_set_line)(unsigned char *buf, int page, int line)
00909 {
00910 int bytes = 0;
00911
00912
00913
00914 if (page) {
00915 if (line > 4) return -1;
00916 } else {
00917 if (line > 33) return -1;
00918 }
00919
00920 if (line < 1) {
00921 return -1;
00922 }
00923
00924 buf[bytes++] = ADSI_LINE_CONTROL;
00925
00926
00927 bytes++;
00928
00929
00930 buf[bytes++] = ((page & 0x1) << 7) | (line & 0x3f);
00931
00932 buf[1] = bytes - 2;
00933 return bytes;
00934 }
00935
00936 static int total = 0;
00937 static int speeds = 0;
00938
00939 int AST_OPTIONAL_API_NAME(ast_adsi_channel_restore)(struct ast_channel *chan)
00940 {
00941 unsigned char dsp[256] = "", keyd[6] = "";
00942 int bytes, x;
00943
00944
00945 bytes = 0;
00946 bytes += ast_adsi_set_line(dsp + bytes, ADSI_INFO_PAGE, 1);
00947
00948
00949
00950 if (speeds) {
00951 for (x = 0; x < speeds; x++) {
00952 keyd[x] = ADSI_SPEED_DIAL + x;
00953 }
00954 bytes += ast_adsi_set_keys(dsp + bytes, keyd);
00955 }
00956 ast_adsi_transmit_message_full(chan, dsp, bytes, ADSI_MSG_DISPLAY, 0);
00957 return 0;
00958
00959 }
00960
00961 int AST_OPTIONAL_API_NAME(ast_adsi_print)(struct ast_channel *chan, char **lines, int *alignments, int voice)
00962 {
00963 unsigned char buf[4096];
00964 int bytes = 0, res, x;
00965
00966 for (x = 0; lines[x]; x++) {
00967 bytes += ast_adsi_display(buf + bytes, ADSI_INFO_PAGE, x+1, alignments[x], 0, lines[x], "");
00968 }
00969 bytes += ast_adsi_set_line(buf + bytes, ADSI_INFO_PAGE, 1);
00970 if (voice) {
00971 bytes += ast_adsi_voice_mode(buf + bytes, 0);
00972 }
00973 res = ast_adsi_transmit_message_full(chan, buf, bytes, ADSI_MSG_DISPLAY, 0);
00974 if (voice) {
00975
00976 ast_waitfordigit(chan, 1000);
00977 }
00978 return res;
00979 }
00980
00981 int AST_OPTIONAL_API_NAME(ast_adsi_load_session)(struct ast_channel *chan, unsigned char *app, int ver, int data)
00982 {
00983 unsigned char dsp[256] = "";
00984 int bytes = 0, res;
00985 char resp[2];
00986
00987
00988 bytes += ast_adsi_connect_session(dsp + bytes, app, ver);
00989
00990 if (data) {
00991 bytes += ast_adsi_data_mode(dsp + bytes);
00992 }
00993
00994
00995 if (ast_adsi_transmit_message_full(chan, dsp, bytes, ADSI_MSG_DISPLAY, 0)) {
00996 return -1;
00997 }
00998 if (app) {
00999 if ((res = ast_readstring(chan, resp, 1, 1200, 1200, "")) < 0) {
01000 return -1;
01001 }
01002 if (res) {
01003 ast_debug(1, "No response from CPE about version. Assuming not there.\n");
01004 return 0;
01005 }
01006 if (!strcmp(resp, "B")) {
01007 ast_debug(1, "CPE has script '%s' version %d already loaded\n", app, ver);
01008 return 1;
01009 } else if (!strcmp(resp, "A")) {
01010 ast_debug(1, "CPE hasn't script '%s' version %d already loaded\n", app, ver);
01011 } else {
01012 ast_log(LOG_WARNING, "Unexpected CPE response to script query: %s\n", resp);
01013 }
01014 } else
01015 return 1;
01016 return 0;
01017
01018 }
01019
01020 int AST_OPTIONAL_API_NAME(ast_adsi_unload_session)(struct ast_channel *chan)
01021 {
01022 unsigned char dsp[256] = "";
01023 int bytes = 0;
01024
01025
01026 bytes += ast_adsi_disconnect_session(dsp + bytes);
01027 bytes += ast_adsi_voice_mode(dsp + bytes, 0);
01028
01029
01030 if (ast_adsi_transmit_message_full(chan, dsp, bytes, ADSI_MSG_DISPLAY, 0)) {
01031 return -1;
01032 }
01033
01034 return 0;
01035 }
01036
01037 static int str2align(const char *s)
01038 {
01039 if (!strncasecmp(s, "l", 1)) {
01040 return ADSI_JUST_LEFT;
01041 } else if (!strncasecmp(s, "r", 1)) {
01042 return ADSI_JUST_RIGHT;
01043 } else if (!strncasecmp(s, "i", 1)) {
01044 return ADSI_JUST_IND;
01045 } else {
01046 return ADSI_JUST_CENT;
01047 }
01048 }
01049
01050 static void init_state(void)
01051 {
01052 int x;
01053
01054 for (x = 0; x < ADSI_MAX_INTRO; x++) {
01055 aligns[x] = ADSI_JUST_CENT;
01056 }
01057 ast_copy_string(intro[0], "Welcome to the", sizeof(intro[0]));
01058 ast_copy_string(intro[1], "Asterisk", sizeof(intro[1]));
01059 ast_copy_string(intro[2], "Open Source PBX", sizeof(intro[2]));
01060 total = 3;
01061 speeds = 0;
01062 for (x = 3; x < ADSI_MAX_INTRO; x++) {
01063 intro[x][0] = '\0';
01064 }
01065 memset(speeddial, 0, sizeof(speeddial));
01066 alignment = ADSI_JUST_CENT;
01067 }
01068
01069 static void adsi_load(int reload)
01070 {
01071 int x = 0;
01072 struct ast_config *conf = NULL;
01073 struct ast_variable *v;
01074 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01075 char *name, *sname;
01076 init_state();
01077
01078 conf = ast_config_load("adsi.conf", config_flags);
01079 if (conf == CONFIG_STATUS_FILEMISSING || conf == CONFIG_STATUS_FILEUNCHANGED || conf == CONFIG_STATUS_FILEINVALID) {
01080 return;
01081 }
01082 for (v = ast_variable_browse(conf, "intro"); v; v = v->next) {
01083 if (!strcasecmp(v->name, "alignment")) {
01084 alignment = str2align(v->value);
01085 } else if (!strcasecmp(v->name, "greeting")) {
01086 if (x < ADSI_MAX_INTRO) {
01087 aligns[x] = alignment;
01088 ast_copy_string(intro[x], v->value, sizeof(intro[x]));
01089 x++;
01090 }
01091 } else if (!strcasecmp(v->name, "maxretries")) {
01092 if (atoi(v->value) > 0) {
01093 maxretries = atoi(v->value);
01094 }
01095 }
01096 }
01097 if (x) {
01098 total = x;
01099 }
01100
01101 x = 0;
01102 for (v = ast_variable_browse(conf, "speeddial"); v; v = v->next) {
01103 char buf[3 * SPEEDDIAL_MAX_LEN];
01104 char *stringp = buf;
01105 ast_copy_string(buf, v->value, sizeof(buf));
01106 name = strsep(&stringp, ",");
01107 sname = strsep(&stringp, ",");
01108 if (!sname) {
01109 sname = name;
01110 }
01111 if (x < ADSI_MAX_SPEED_DIAL) {
01112 ast_copy_string(speeddial[x][0], v->name, sizeof(speeddial[x][0]));
01113 ast_copy_string(speeddial[x][1], name, 18);
01114 ast_copy_string(speeddial[x][2], sname, 7);
01115 x++;
01116 }
01117 }
01118 if (x) {
01119 speeds = x;
01120 }
01121 ast_config_destroy(conf);
01122
01123 return;
01124 }
01125
01126 static int reload(void)
01127 {
01128 adsi_load(1);
01129 return 0;
01130 }
01131
01132 static int load_module(void)
01133 {
01134 adsi_load(0);
01135 return AST_MODULE_LOAD_SUCCESS;
01136 }
01137
01138 static int unload_module(void)
01139 {
01140
01141 return -1;
01142 }
01143
01144 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "ADSI Resource",
01145 .load = load_module,
01146 .unload = unload_module,
01147 .reload = reload,
01148 .load_pri = AST_MODPRI_APP_DEPEND,
01149 );