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