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