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