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