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 #include "asterisk.h"
00031
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 369001 $")
00033
00034 #include <time.h>
00035 #include <math.h>
00036 #include <ctype.h>
00037
00038 #include "asterisk/ulaw.h"
00039 #include "asterisk/alaw.h"
00040 #include "asterisk/frame.h"
00041 #include "asterisk/channel.h"
00042 #include "asterisk/callerid.h"
00043 #include "asterisk/fskmodem.h"
00044 #include "asterisk/utils.h"
00045
00046 struct callerid_state {
00047 fsk_data fskd;
00048 char rawdata[256];
00049 short oldstuff[160];
00050 int oldlen;
00051 int pos;
00052 int type;
00053 int cksum;
00054 char name[64];
00055 char number[64];
00056 int flags;
00057 int sawflag;
00058 int len;
00059
00060 int skipflag;
00061 unsigned short crc;
00062 };
00063
00064
00065 float cid_dr[4], cid_di[4];
00066 float clidsb = 8000.0 / 1200.0;
00067 float sasdr, sasdi;
00068 float casdr1, casdi1, casdr2, casdi2;
00069
00070 #define CALLERID_SPACE 2200.0
00071 #define CALLERID_MARK 1200.0
00072 #define SAS_FREQ 440.0
00073 #define CAS_FREQ1 2130.0
00074 #define CAS_FREQ2 2750.0
00075
00076 #define AST_CALLERID_UNKNOWN "<unknown>"
00077
00078 static inline void gen_tones(unsigned char *buf, int len, format_t codec, float ddr1, float ddi1, float ddr2, float ddi2, float *cr1, float *ci1, float *cr2, float *ci2)
00079 {
00080 int x;
00081 float t;
00082 for (x = 0; x < len; x++) {
00083 t = *cr1 * ddr1 - *ci1 * ddi1;
00084 *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
00085 *cr1 = t;
00086 t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
00087 *cr1 *= t;
00088 *ci1 *= t;
00089
00090 t = *cr2 * ddr2 - *ci2 * ddi2;
00091 *ci2 = *cr2 * ddi2 + *ci2 * ddr2;
00092 *cr2 = t;
00093 t = 2.0 - (*cr2 * *cr2 + *ci2 * *ci2);
00094 *cr2 *= t;
00095 *ci2 *= t;
00096 buf[x] = AST_LIN2X((*cr1 + *cr2) * 2048.0);
00097 }
00098 }
00099
00100 static inline void gen_tone(unsigned char *buf, int len, format_t codec, float ddr1, float ddi1, float *cr1, float *ci1)
00101 {
00102 int x;
00103 float t;
00104 for (x = 0; x < len; x++) {
00105 t = *cr1 * ddr1 - *ci1 * ddi1;
00106 *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
00107 *cr1 = t;
00108 t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
00109 *cr1 *= t;
00110 *ci1 *= t;
00111 buf[x] = AST_LIN2X(*cr1 * 8192.0);
00112 }
00113 }
00114
00115
00116 void callerid_init(void)
00117 {
00118 cid_dr[0] = cos(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
00119 cid_di[0] = sin(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
00120 cid_dr[1] = cos(CALLERID_MARK * 2.0 * M_PI / 8000.0);
00121 cid_di[1] = sin(CALLERID_MARK * 2.0 * M_PI / 8000.0);
00122 sasdr = cos(SAS_FREQ * 2.0 * M_PI / 8000.0);
00123 sasdi = sin(SAS_FREQ * 2.0 * M_PI / 8000.0);
00124 casdr1 = cos(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
00125 casdi1 = sin(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
00126 casdr2 = cos(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
00127 casdi2 = sin(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
00128 }
00129
00130 struct callerid_state *callerid_new(int cid_signalling)
00131 {
00132 struct callerid_state *cid;
00133
00134 if ((cid = ast_calloc(1, sizeof(*cid)))) {
00135 #ifdef INTEGER_CALLERID
00136 cid->fskd.ispb = 7;
00137
00138 cid->fskd.pllispb = (int)(8000 * 32 / 1200);
00139 cid->fskd.pllids = cid->fskd.pllispb/32;
00140 cid->fskd.pllispb2 = cid->fskd.pllispb/2;
00141
00142 cid->fskd.icont = 0;
00143
00144 cid->fskd.nbit = 8;
00145 cid->fskd.instop = 1;
00146
00147 cid->fskd.bw = 1;
00148 if (cid_signalling == 2) {
00149 cid->fskd.f_mark_idx = 4;
00150 cid->fskd.f_space_idx = 5;
00151 } else {
00152 cid->fskd.f_mark_idx = 2;
00153 cid->fskd.f_space_idx = 3;
00154 }
00155
00156
00157
00158
00159 cid->flags = CID_UNKNOWN_NAME | CID_UNKNOWN_NUMBER;
00160
00161
00162 fskmodem_init(&cid->fskd);
00163 #else
00164 cid->fskd.spb = 7.0;
00165
00166 cid->fskd.nbit = 8;
00167 cid->fskd.nstop = 1.0;
00168
00169 cid->fskd.bw = 1;
00170 if (cid_signalling == 2) {
00171 cid->fskd.f_mark_idx = 4;
00172 cid->fskd.f_space_idx = 5;
00173 } else {
00174 cid->fskd.f_mark_idx = 2;
00175 cid->fskd.f_space_idx = 3;
00176 }
00177
00178
00179
00180
00181 cid->flags = CID_UNKNOWN_NAME | CID_UNKNOWN_NUMBER;
00182
00183 #endif
00184 }
00185
00186 return cid;
00187 }
00188
00189 void callerid_get(struct callerid_state *cid, char **name, char **number, int *flags)
00190 {
00191 *flags = cid->flags;
00192 if (cid->flags & (CID_UNKNOWN_NAME | CID_PRIVATE_NAME))
00193 *name = NULL;
00194 else
00195 *name = cid->name;
00196 if (cid->flags & (CID_UNKNOWN_NUMBER | CID_PRIVATE_NUMBER))
00197 *number = NULL;
00198 else
00199 *number = cid->number;
00200 }
00201
00202 void callerid_get_dtmf(char *cidstring, char *number, int *flags)
00203 {
00204 int i;
00205 int code;
00206
00207
00208 number[0] = 0;
00209
00210 if (strlen(cidstring) < 2) {
00211 ast_debug(1, "No cid detected\n");
00212 *flags = CID_UNKNOWN_NUMBER;
00213 return;
00214 }
00215
00216
00217 if (cidstring[0] == 'B') {
00218
00219 code = atoi(&cidstring[1]);
00220 if (code == 0)
00221 *flags = CID_UNKNOWN_NUMBER;
00222 else if (code == 10)
00223 *flags = CID_PRIVATE_NUMBER;
00224 else
00225 ast_debug(1, "Unknown DTMF code %d\n", code);
00226 } else if (cidstring[0] == 'D' && cidstring[2] == '#') {
00227
00228 if (cidstring[1] == '1')
00229 *flags = CID_PRIVATE_NUMBER;
00230 if (cidstring[1] == '2' || cidstring[1] == '3')
00231 *flags = CID_UNKNOWN_NUMBER;
00232 } else if (cidstring[0] == 'D' || cidstring[0] == 'A') {
00233
00234 for (i = 1; i < strlen(cidstring); i++) {
00235 if (cidstring[i] == 'C' || cidstring[i] == '#')
00236 break;
00237 if (isdigit(cidstring[i]))
00238 number[i-1] = cidstring[i];
00239 else
00240 ast_debug(1, "Unknown CID digit '%c'\n",
00241 cidstring[i]);
00242 }
00243 number[i-1] = 0;
00244 } else if (isdigit(cidstring[0])) {
00245
00246
00247 ast_log(LOG_WARNING, "Couldn't detect start-character. CID "
00248 "parsing might be unreliable\n");
00249 for (i = 0; i < strlen(cidstring); i++) {
00250 if (isdigit(cidstring[i]))
00251 number[i] = cidstring[i];
00252 else
00253 break;
00254 }
00255 number[i] = 0;
00256 } else {
00257 ast_debug(1, "Unknown CID protocol, start digit '%c'\n", cidstring[0]);
00258 *flags = CID_UNKNOWN_NUMBER;
00259 }
00260 }
00261
00262 int ast_gen_cas(unsigned char *outbuf, int sendsas, int len, format_t codec)
00263 {
00264 int pos = 0;
00265 int saslen = 2400;
00266 float cr1 = 1.0;
00267 float ci1 = 0.0;
00268 float cr2 = 1.0;
00269 float ci2 = 0.0;
00270
00271 if (sendsas) {
00272 if (len < saslen)
00273 return -1;
00274 gen_tone(outbuf, saslen, codec, sasdr, sasdi, &cr1, &ci1);
00275 len -= saslen;
00276 pos += saslen;
00277 cr2 = cr1;
00278 ci2 = ci1;
00279 }
00280 gen_tones(outbuf + pos, len, codec, casdr1, casdi1, casdr2, casdi2, &cr1, &ci1, &cr2, &ci2);
00281 return 0;
00282 }
00283
00284 static unsigned short calc_crc(unsigned short crc, unsigned char data)
00285 {
00286 unsigned int i, j, org, dst;
00287 org = data;
00288 dst = 0;
00289
00290 for (i = 0; i < CHAR_BIT; i++) {
00291 org <<= 1;
00292 dst >>= 1;
00293 if (org & 0x100)
00294 dst |= 0x80;
00295 }
00296 data = (unsigned char) dst;
00297 crc ^= (unsigned int) data << (16 - CHAR_BIT);
00298 for (j = 0; j < CHAR_BIT; j++) {
00299 if (crc & 0x8000U)
00300 crc = (crc << 1) ^ 0x1021U ;
00301 else
00302 crc <<= 1 ;
00303 }
00304 return crc;
00305 }
00306
00307 int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int len, format_t codec)
00308 {
00309 int mylen = len;
00310 int olen;
00311 int b = 'X';
00312 int b2;
00313 int res;
00314 int x;
00315 short *buf;
00316
00317 buf = alloca(2 * len + cid->oldlen);
00318
00319 memcpy(buf, cid->oldstuff, cid->oldlen);
00320 mylen += cid->oldlen / 2;
00321
00322 for (x = 0; x < len; x++)
00323 buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
00324
00325 while (mylen >= 160) {
00326 b = b2 = 0;
00327 olen = mylen;
00328 res = fsk_serial(&cid->fskd, buf, &mylen, &b);
00329
00330 if (mylen < 0) {
00331 ast_log(LOG_ERROR, "No start bit found in fsk data.\n");
00332 return -1;
00333 }
00334
00335 buf += (olen - mylen);
00336
00337 if (res < 0) {
00338 ast_log(LOG_NOTICE, "fsk_serial failed\n");
00339 return -1;
00340 }
00341
00342 if (res == 1) {
00343 b2 = b;
00344 b &= 0x7f;
00345
00346
00347 if (cid->sawflag > 1)
00348 cid->crc = calc_crc(cid->crc, (unsigned char) b2);
00349
00350
00351 if (b > 0xff)
00352 continue;
00353
00354
00355 if (cid->sawflag > 0) {
00356 if (cid->sawflag != 5 && cid->skipflag == 0 && b == 0x10) {
00357 cid->skipflag = 1 ;
00358 continue ;
00359 }
00360 }
00361 if (cid->skipflag == 1)
00362 cid->skipflag = 0 ;
00363
00364
00365 switch (cid->sawflag) {
00366 case 0:
00367 if (b == 0x10) {
00368 cid->sawflag = 1;
00369 cid->skipflag = 0;
00370 cid->crc = 0;
00371 }
00372 break;
00373 case 1:
00374 if (b == 0x01)
00375 cid->sawflag = 2;
00376 break ;
00377 case 2:
00378 if (b == 0x07)
00379 cid->sawflag = 3;
00380 break;
00381 case 3:
00382 if (b == 0x02)
00383 cid->sawflag = 4;
00384 break;
00385 case 4:
00386 if (b == 0x40)
00387 cid->sawflag = 5;
00388 break;
00389 case 5:
00390 cid->sawflag = 6;
00391 break;
00392 case 6:
00393 cid->sawflag = 7;
00394 cid->pos = 0;
00395 cid->rawdata[cid->pos++] = b;
00396 break;
00397 case 7:
00398 cid->sawflag = 8;
00399 cid->len = b;
00400 if ((cid->len+2) >= sizeof(cid->rawdata)) {
00401 ast_log(LOG_WARNING, "too long caller id string\n") ;
00402 return -1;
00403 }
00404 cid->rawdata[cid->pos++] = b;
00405 break;
00406 case 8:
00407 cid->rawdata[cid->pos++] = b;
00408 cid->len--;
00409 if (cid->len<=0) {
00410 cid->rawdata[cid->pos] = '\0';
00411 cid->sawflag = 9;
00412 }
00413 break;
00414 case 9:
00415 cid->sawflag = 10;
00416 break;
00417 case 10:
00418 cid->sawflag = 11;
00419 break;
00420 case 11:
00421 cid->sawflag = 12;
00422 if (cid->crc != 0) {
00423 ast_log(LOG_WARNING, "crc checksum error\n") ;
00424 return -1;
00425 }
00426
00427 for (x = 0; x < cid->pos;) {
00428 switch (cid->rawdata[x++]) {
00429 case 0x02:
00430 cid->number[0] = '\0';
00431 cid->name[0] = '\0';
00432 cid->flags = 0;
00433 res = cid->rawdata[x++];
00434 ast_copy_string(cid->number, &cid->rawdata[x], res+1);
00435 x += res;
00436 break;
00437 case 0x21:
00438
00439 x++;
00440
00441 switch (cid->rawdata[x]) {
00442 case 0x00:
00443 case 0x01:
00444 case 0x02:
00445 case 0x03:
00446 case 0x04:
00447 case 0x06:
00448 case 0x07:
00449 default:
00450 ast_debug(2, "cid info:#1=%X\n", cid->rawdata[x]);
00451 break ;
00452 }
00453 x++;
00454
00455 x++;
00456
00457 switch (cid->rawdata[x]) {
00458 case 0x00:
00459 case 0x01:
00460 case 0x03:
00461 case 0x04:
00462 case 0x08:
00463 case 0x09:
00464 case 0x05:
00465 default:
00466 ast_debug(2, "cid info:#2=%X\n", cid->rawdata[x]);
00467 break ;
00468 }
00469 x++;
00470 break ;
00471 case 0x04:
00472
00473 x++;
00474
00475 switch (cid->rawdata[x]) {
00476 case 'P':
00477 case 'O':
00478 case 'C':
00479 case 'S':
00480 cid->flags |= CID_UNKNOWN_NUMBER;
00481 ast_debug(2, "no cid reason:%c\n", cid->rawdata[x]);
00482 break ;
00483 }
00484 x++;
00485 break ;
00486 case 0x09:
00487
00488 res = cid->rawdata[x++];
00489
00490 x += res;
00491 break ;
00492 case 0x22:
00493
00494 x++;
00495
00496 switch (cid->rawdata[x]) {
00497 case 0x00:
00498 case 0x01:
00499 case 0x02:
00500 case 0x03:
00501 case 0x04:
00502 case 0x06:
00503 case 0x07:
00504 default:
00505 if (option_debug > 1)
00506 ast_log(LOG_NOTICE, "did info:#1=%X\n", cid->rawdata[x]);
00507 break ;
00508 }
00509 x++;
00510
00511 x++;
00512
00513 switch (cid->rawdata[x]) {
00514 case 0x00:
00515 case 0x01:
00516 case 0x03:
00517 case 0x04:
00518 case 0x08:
00519 case 0x09:
00520 case 0x05:
00521 default:
00522 ast_debug(2, "did info:#2=%X\n", cid->rawdata[x]);
00523 break ;
00524 }
00525 x++;
00526 break ;
00527 }
00528 }
00529 return 1;
00530 break;
00531 default:
00532 ast_log(LOG_ERROR, "invalid value in sawflag %d\n", cid->sawflag);
00533 }
00534 }
00535 }
00536 if (mylen) {
00537 memcpy(cid->oldstuff, buf, mylen * 2);
00538 cid->oldlen = mylen * 2;
00539 } else
00540 cid->oldlen = 0;
00541
00542 return 0;
00543 }
00544
00545
00546 int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, format_t codec)
00547 {
00548 int mylen = len;
00549 int olen;
00550 int b = 'X';
00551 int res;
00552 int x;
00553 short *buf;
00554
00555 buf = alloca(2 * len + cid->oldlen);
00556
00557 memcpy(buf, cid->oldstuff, cid->oldlen);
00558 mylen += cid->oldlen/2;
00559
00560 for (x = 0; x < len; x++)
00561 buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
00562 while (mylen >= 160) {
00563 olen = mylen;
00564 res = fsk_serial(&cid->fskd, buf, &mylen, &b);
00565 if (mylen < 0) {
00566 ast_log(LOG_ERROR, "No start bit found in fsk data.\n");
00567 return -1;
00568 }
00569 buf += (olen - mylen);
00570 if (res < 0) {
00571 ast_log(LOG_NOTICE, "fsk_serial failed\n");
00572 return -1;
00573 }
00574 if (res == 1) {
00575 if (b > 0xff) {
00576 if (cid->sawflag != 5) {
00577
00578 continue;
00579 }
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 b &= 0xff;
00590 }
00591 switch (cid->sawflag) {
00592 case 0:
00593 if (b == 'U')
00594 cid->sawflag = 2;
00595 break;
00596 case 2:
00597 if ((b == 0x04) || (b == 0x80) || (b == 0x06) || (b == 0x82)) {
00598 cid->type = b;
00599 cid->sawflag = 3;
00600 cid->cksum = b;
00601 }
00602 break;
00603 case 3:
00604
00605 cid->sawflag = 4;
00606 cid->len = b;
00607 cid->pos = 0;
00608 cid->cksum += b;
00609 break;
00610 case 4:
00611 if (cid->pos >= 128) {
00612 ast_log(LOG_WARNING, "Caller ID too long???\n");
00613 return -1;
00614 }
00615 cid->rawdata[cid->pos++] = b;
00616 cid->len--;
00617 cid->cksum += b;
00618 if (!cid->len) {
00619 cid->rawdata[cid->pos] = '\0';
00620 cid->sawflag = 5;
00621 }
00622 break;
00623 case 5:
00624 if (b != (256 - (cid->cksum & 0xff))) {
00625 ast_log(LOG_NOTICE, "Caller*ID failed checksum\n");
00626
00627 cid->sawflag = 0;
00628 break;
00629 }
00630
00631 cid->number[0] = '\0';
00632 cid->name[0] = '\0';
00633
00634 cid->flags = 0;
00635
00636 if ((cid->type == 0x80) || (cid->type == 0x82)) {
00637
00638
00639 for (x = 0; x < cid->pos;) {
00640 switch (cid->rawdata[x++]) {
00641 case 1:
00642
00643 break;
00644 case 2:
00645 case 3:
00646 case 4:
00647 res = cid->rawdata[x];
00648 if (res > 32) {
00649 ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]);
00650 res = 32;
00651 }
00652 if (ast_strlen_zero(cid->number)) {
00653 memcpy(cid->number, cid->rawdata + x + 1, res);
00654
00655 cid->number[res] = '\0';
00656 }
00657 break;
00658 case 6:
00659 break;
00660 case 7:
00661 case 8:
00662 res = cid->rawdata[x];
00663 if (res > 32) {
00664 ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]);
00665 res = 32;
00666 }
00667 memcpy(cid->name, cid->rawdata + x + 1, res);
00668 cid->name[res] = '\0';
00669 break;
00670 case 11:
00671 res = cid->rawdata[x + 1];
00672 if (res)
00673 cid->flags |= CID_MSGWAITING;
00674 else
00675 cid->flags |= CID_NOMSGWAITING;
00676 break;
00677 case 17:
00678 case 19:
00679 case 22:
00680 break;
00681 default:
00682 ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x - 1]);
00683 }
00684 res = cid->rawdata[x];
00685 if (0 > res){
00686 ast_log(LOG_NOTICE, "IE %d has bad field length of %d at offset %d\n", cid->rawdata[x-1], cid->rawdata[x], x);
00687
00688 cid->sawflag = 0;
00689 break;
00690 }
00691 x += cid->rawdata[x];
00692 x++;
00693 }
00694 } else if (cid->type == 0x6) {
00695
00696 if (cid->rawdata[2] == 0x42) {
00697 cid->flags |= CID_MSGWAITING;
00698 } else if (cid->rawdata[2] == 0x6f) {
00699 cid->flags |= CID_NOMSGWAITING;
00700 }
00701 } else {
00702
00703 ast_copy_string(cid->number, cid->rawdata + 8, sizeof(cid->number));
00704 }
00705 if (!strcmp(cid->number, "P")) {
00706 strcpy(cid->number, "");
00707 cid->flags |= CID_PRIVATE_NUMBER;
00708 } else if (!strcmp(cid->number, "O") || ast_strlen_zero(cid->number)) {
00709 strcpy(cid->number, "");
00710 cid->flags |= CID_UNKNOWN_NUMBER;
00711 }
00712 if (!strcmp(cid->name, "P")) {
00713 strcpy(cid->name, "");
00714 cid->flags |= CID_PRIVATE_NAME;
00715 } else if (!strcmp(cid->name, "O") || ast_strlen_zero(cid->name)) {
00716 strcpy(cid->name, "");
00717 cid->flags |= CID_UNKNOWN_NAME;
00718 }
00719 return 1;
00720 break;
00721 default:
00722 ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag);
00723 }
00724 }
00725 }
00726 if (mylen) {
00727 memcpy(cid->oldstuff, buf, mylen * 2);
00728 cid->oldlen = mylen * 2;
00729 } else
00730 cid->oldlen = 0;
00731
00732 return 0;
00733 }
00734
00735 void callerid_free(struct callerid_state *cid)
00736 {
00737 ast_free(cid);
00738 }
00739
00740 static int callerid_genmsg(char *msg, int size, const char *number, const char *name, int flags)
00741 {
00742 struct timeval now = ast_tvnow();
00743 struct ast_tm tm;
00744 char *ptr;
00745 int res;
00746 int i, x;
00747
00748
00749 ast_localtime(&now, &tm, NULL);
00750
00751 ptr = msg;
00752
00753
00754 res = snprintf(ptr, size, "\001\010%02d%02d%02d%02d", tm.tm_mon + 1,
00755 tm.tm_mday, tm.tm_hour, tm.tm_min);
00756 size -= res;
00757 ptr += res;
00758 if (ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) {
00759
00760 res = snprintf(ptr, size, "\004\001O");
00761 size -= res;
00762 ptr += res;
00763 } else if (flags & CID_PRIVATE_NUMBER) {
00764
00765 res = snprintf(ptr, size, "\004\001P");
00766 size -= res;
00767 ptr += res;
00768 } else {
00769
00770 i = strlen(number);
00771 if (i > 16)
00772 i = 16;
00773 res = snprintf(ptr, size, "\002%c", i);
00774 size -= res;
00775 ptr += res;
00776 for (x = 0; x < i; x++)
00777 ptr[x] = number[x];
00778 ptr[i] = '\0';
00779 ptr += i;
00780 size -= i;
00781 }
00782
00783 if (ast_strlen_zero(name) || (flags & CID_UNKNOWN_NAME)) {
00784
00785 res = snprintf(ptr, size, "\010\001O");
00786 size -= res;
00787 ptr += res;
00788 } else if (flags & CID_PRIVATE_NAME) {
00789
00790 res = snprintf(ptr, size, "\010\001P");
00791 size -= res;
00792 ptr += res;
00793 } else {
00794
00795 i = strlen(name);
00796 if (i > 16)
00797 i = 16;
00798 res = snprintf(ptr, size, "\007%c", i);
00799 size -= res;
00800 ptr += res;
00801 for (x = 0; x < i; x++)
00802 ptr[x] = name[x];
00803 ptr[i] = '\0';
00804 ptr += i;
00805 size -= i;
00806 }
00807 return (ptr - msg);
00808
00809 }
00810
00811 int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, format_t codec,
00812 const char* name, const char* number, int flags)
00813 {
00814 char msg[256];
00815 int len = 0;
00816 int sum;
00817 int x;
00818 int bytes = 0;
00819 float cr = 1.0;
00820 float ci = 0.0;
00821 float scont = 0.0;
00822
00823 if (type == CID_MWI_TYPE_MDMF_FULL) {
00824
00825 msg[0] = 0x82;
00826
00827
00828 len = callerid_genmsg(msg+2, sizeof(msg)-2, number, name, flags);
00829
00830
00831 msg[1] = len+3;
00832
00833
00834 len = len+2;
00835
00836
00837 msg[len++] = 0x0b;
00838
00839 msg[len++] = 1;
00840
00841 if (active)
00842 msg[len++] = 0xff;
00843 else
00844 msg[len++] = 0x00;
00845
00846 } else if (type == CID_MWI_TYPE_MDMF) {
00847
00848
00849 msg[len++] = 0x82;
00850
00851 msg[len++] = 3;
00852
00853 msg[len++] = 0x0b;
00854
00855 msg[len++] = 1;
00856
00857 if (active)
00858 msg[len++] = 0xff;
00859 else
00860 msg[len++] = 0x00;
00861 } else {
00862
00863 msg[len++] = 0x6;
00864
00865 msg[len++] = 3;
00866 if (active) {
00867 msg[len++] = 0x42;
00868 msg[len++] = 0x42;
00869 msg[len++] = 0x42;
00870 } else {
00871 msg[len++] = 0x6f;
00872 msg[len++] = 0x6f;
00873 msg[len++] = 0x6f;
00874 }
00875 }
00876 sum = 0;
00877 for (x = 0; x < len; x++)
00878 sum += msg[x];
00879 sum = (256 - (sum & 255));
00880 msg[len++] = sum;
00881
00882 for (x = 0; x < 4000; x++)
00883 PUT_BYTE(0x7f);
00884
00885 for (x = 0; x < 30; x++)
00886 PUT_CLID(0x55);
00887
00888 for (x = 0; x < 170; x++)
00889 PUT_CLID_MARKMS;
00890 for (x = 0; x < len; x++) {
00891 PUT_CLID(msg[x]);
00892 }
00893
00894 for (x = 0; x < 50; x++)
00895 PUT_CLID_MARKMS;
00896 return bytes;
00897 }
00898
00899 int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, format_t codec)
00900 {
00901 int bytes = 0;
00902 int x, sum;
00903 int len;
00904
00905
00906 float cr = 1.0;
00907 float ci = 0.0;
00908 float scont = 0.0;
00909 char msg[256];
00910 len = callerid_genmsg(msg, sizeof(msg), number, name, flags);
00911 if (!callwaiting) {
00912
00913 for (x = 0; x < 4000; x++)
00914 PUT_BYTE(0x7f);
00915
00916 for (x = 0; x < 30; x++)
00917 PUT_CLID(0x55);
00918 }
00919
00920 for (x = 0; x < 150; x++)
00921 PUT_CLID_MARKMS;
00922
00923 PUT_CLID(0x80);
00924
00925 PUT_CLID(len);
00926 sum = 0x80 + strlen(msg);
00927
00928 for (x = 0; x < len; x++) {
00929 PUT_CLID(msg[x]);
00930 sum += msg[x];
00931 }
00932
00933 PUT_CLID(256 - (sum & 255));
00934
00935
00936 for (x = 0; x < 50; x++)
00937 PUT_CLID_MARKMS;
00938
00939 return bytes;
00940 }
00941
00942
00943
00944
00945
00946
00947
00948 void ast_shrink_phone_number(char *n)
00949 {
00950 int x, y = 0;
00951 int bracketed = 0;
00952
00953 for (x = 0; n[x]; x++) {
00954 switch (n[x]) {
00955 case '[':
00956 bracketed++;
00957 n[y++] = n[x];
00958 break;
00959 case ']':
00960 bracketed--;
00961 n[y++] = n[x];
00962 break;
00963 case '-':
00964 if (bracketed)
00965 n[y++] = n[x];
00966 break;
00967 case '.':
00968 if (!n[x+1])
00969 n[y++] = n[x];
00970 break;
00971 default:
00972
00973 if (!strchr("( )", n[x]))
00974 n[y++] = n[x];
00975 }
00976 }
00977 n[y] = '\0';
00978 }
00979
00980
00981
00982
00983
00984
00985
00986
00987 static int ast_is_valid_string(const char *exten, const char *valid)
00988 {
00989 int x;
00990
00991 if (ast_strlen_zero(exten))
00992 return 0;
00993 for (x = 0; exten[x]; x++)
00994 if (!strchr(valid, exten[x]))
00995 return 0;
00996 return 1;
00997 }
00998
00999 int ast_isphonenumber(const char *n)
01000 {
01001 return ast_is_valid_string(n, "0123456789*#+");
01002 }
01003
01004 int ast_is_shrinkable_phonenumber(const char *exten)
01005 {
01006 return ast_is_valid_string(exten, "0123456789*#+()-.");
01007 }
01008
01009 int ast_callerid_parse(char *instr, char **name, char **location)
01010 {
01011 char *ns, *ne, *ls, *le;
01012
01013
01014 if ((ls = strrchr(instr, '<')) && (le = strrchr(ls, '>'))) {
01015 *ls = *le = '\0';
01016 *location = ls + 1;
01017 if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
01018 *ns = *ne = '\0';
01019 *name = ns + 1;
01020 } else if (ns) {
01021
01022
01023
01024 if (strchr(le + 1, '\"')) {
01025 *ns = '\0';
01026 *name = ns + 1;
01027 ast_trim_blanks(*name);
01028 } else {
01029 *name = NULL;
01030 }
01031 } else {
01032 *name = ast_skip_blanks(instr);
01033 ast_trim_blanks(*name);
01034 }
01035 } else {
01036 char tmp[256];
01037
01038 ast_copy_string(tmp, instr, sizeof(tmp));
01039 ast_shrink_phone_number(tmp);
01040 if (ast_isphonenumber(tmp)) {
01041 *name = NULL;
01042 strcpy(instr, tmp);
01043 *location = instr;
01044 } else {
01045 *location = NULL;
01046 if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
01047 *ns = *ne = '\0';
01048 *name = ns + 1;
01049 } else {
01050 *name = ast_skip_blanks(instr);
01051 ast_trim_blanks(*name);
01052 }
01053 }
01054 }
01055 return 0;
01056 }
01057
01058 static int __ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int callwaiting, format_t codec)
01059 {
01060 if (ast_strlen_zero(name))
01061 name = NULL;
01062 if (ast_strlen_zero(number))
01063 number = NULL;
01064 return callerid_generate(buf, number, name, 0, callwaiting, codec);
01065 }
01066
01067 int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, format_t codec)
01068 {
01069 return __ast_callerid_generate(buf, name, number, 0, codec);
01070 }
01071
01072 int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, format_t codec)
01073 {
01074 return __ast_callerid_generate(buf, name, number, 1, codec);
01075 }
01076
01077 char *ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
01078 {
01079 if (!unknown)
01080 unknown = "<unknown>";
01081 if (name && num)
01082 snprintf(buf, bufsiz, "\"%s\" <%s>", name, num);
01083 else if (name)
01084 ast_copy_string(buf, name, bufsiz);
01085 else if (num)
01086 ast_copy_string(buf, num, bufsiz);
01087 else
01088 ast_copy_string(buf, unknown, bufsiz);
01089 return buf;
01090 }
01091
01092 int ast_callerid_split(const char *buf, char *name, int namelen, char *num, int numlen)
01093 {
01094 char *tmp;
01095 char *l = NULL, *n = NULL;
01096
01097 tmp = ast_strdupa(buf);
01098 ast_callerid_parse(tmp, &n, &l);
01099 if (n)
01100 ast_copy_string(name, n, namelen);
01101 else
01102 name[0] = '\0';
01103 if (l) {
01104 ast_shrink_phone_number(l);
01105 ast_copy_string(num, l, numlen);
01106 } else
01107 num[0] = '\0';
01108 return 0;
01109 }
01110
01111 struct ast_value_translation {
01112 int value;
01113 const char *name;
01114 const char *description;
01115 };
01116
01117
01118 static const struct ast_value_translation pres_types[] = {
01119
01120 { AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_UNSCREENED, "allowed_not_screened", "Presentation Allowed, Not Screened" },
01121 { AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", "Presentation Allowed, Passed Screen" },
01122 { AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", "Presentation Allowed, Failed Screen" },
01123 { AST_PRES_ALLOWED | AST_PRES_NETWORK_NUMBER, "allowed", "Presentation Allowed, Network Number" },
01124
01125 { AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED, "prohib_not_screened", "Presentation Prohibited, Not Screened" },
01126 { AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", "Presentation Prohibited, Passed Screen" },
01127 { AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", "Presentation Prohibited, Failed Screen" },
01128 { AST_PRES_RESTRICTED | AST_PRES_NETWORK_NUMBER, "prohib", "Presentation Prohibited, Network Number" },
01129
01130 { AST_PRES_UNAVAILABLE | AST_PRES_NETWORK_NUMBER, "unavailable", "Number Unavailable" },
01131 { AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_UNSCREENED, "unavailable", "Number Unavailable" },
01132 { AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_FAILED_SCREEN, "unavailable", "Number Unavailable" },
01133 { AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_PASSED_SCREEN, "unavailable", "Number Unavailable" },
01134
01135 };
01136
01137
01138
01139
01140
01141
01142
01143 int ast_parse_caller_presentation(const char *data)
01144 {
01145 int index;
01146 if (!data) {
01147 return -1;
01148 }
01149
01150 for (index = 0; index < ARRAY_LEN(pres_types); ++index) {
01151 if (!strcasecmp(pres_types[index].name, data)) {
01152 return pres_types[index].value;
01153 }
01154 }
01155
01156 return -1;
01157 }
01158
01159
01160
01161
01162
01163
01164 const char *ast_describe_caller_presentation(int data)
01165 {
01166 int index;
01167
01168 for (index = 0; index < ARRAY_LEN(pres_types); ++index) {
01169 if (pres_types[index].value == data) {
01170 return pres_types[index].description;
01171 }
01172 }
01173
01174 return "unknown";
01175 }
01176
01177
01178
01179
01180
01181
01182 const char *ast_named_caller_presentation(int data)
01183 {
01184 int index;
01185
01186 for (index = 0; index < ARRAY_LEN(pres_types); ++index) {
01187 if (pres_types[index].value == data) {
01188 return pres_types[index].name;
01189 }
01190 }
01191
01192 return "unknown";
01193 }
01194
01195
01196 static const struct ast_value_translation redirecting_reason_types[] = {
01197
01198 { AST_REDIRECTING_REASON_UNKNOWN, "unknown", "Unknown" },
01199 { AST_REDIRECTING_REASON_USER_BUSY, "cfb", "Call Forwarding Busy" },
01200 { AST_REDIRECTING_REASON_NO_ANSWER, "cfnr", "Call Forwarding No Reply" },
01201 { AST_REDIRECTING_REASON_UNAVAILABLE, "unavailable", "Callee is Unavailable" },
01202 { AST_REDIRECTING_REASON_UNCONDITIONAL, "cfu", "Call Forwarding Unconditional" },
01203 { AST_REDIRECTING_REASON_TIME_OF_DAY, "time_of_day", "Time of Day" },
01204 { AST_REDIRECTING_REASON_DO_NOT_DISTURB, "dnd", "Do Not Disturb" },
01205 { AST_REDIRECTING_REASON_DEFLECTION, "deflection", "Call Deflection" },
01206 { AST_REDIRECTING_REASON_FOLLOW_ME, "follow_me", "Follow Me" },
01207 { AST_REDIRECTING_REASON_OUT_OF_ORDER, "out_of_order", "Called DTE Out-Of-Order" },
01208 { AST_REDIRECTING_REASON_AWAY, "away", "Callee is Away" },
01209 { AST_REDIRECTING_REASON_CALL_FWD_DTE, "cf_dte", "Call Forwarding By The Called DTE" },
01210
01211 };
01212
01213 int ast_redirecting_reason_parse(const char *data)
01214 {
01215 int index;
01216
01217 for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
01218 if (!strcasecmp(redirecting_reason_types[index].name, data)) {
01219 return redirecting_reason_types[index].value;
01220 }
01221 }
01222
01223 return -1;
01224 }
01225
01226 const char *ast_redirecting_reason_describe(int data)
01227 {
01228 int index;
01229
01230 for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
01231 if (redirecting_reason_types[index].value == data) {
01232 return redirecting_reason_types[index].description;
01233 }
01234 }
01235
01236 return "not-known";
01237 }
01238
01239 const char *ast_redirecting_reason_name(int data)
01240 {
01241 int index;
01242
01243 for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
01244 if (redirecting_reason_types[index].value == data) {
01245 return redirecting_reason_types[index].name;
01246 }
01247 }
01248
01249 return "not-known";
01250 }
01251
01252
01253 static const struct ast_value_translation connected_line_source_types[] = {
01254
01255 { AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN, "unknown", "Unknown" },
01256 { AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, "answer", "Normal Call Answering" },
01257 { AST_CONNECTED_LINE_UPDATE_SOURCE_DIVERSION, "diversion", "Call Diversion (Deprecated, use REDIRECTING)" },
01258 { AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, "transfer_active", "Call Transfer(Active)" },
01259 { AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, "transfer", "Call Transfer(Active)" },
01260 { AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING, "transfer_alerting", "Call Transfer(Alerting)" }
01261
01262 };
01263
01264 int ast_connected_line_source_parse(const char *data)
01265 {
01266 int index;
01267
01268 for (index = 0; index < ARRAY_LEN(connected_line_source_types); ++index) {
01269 if (!strcasecmp(connected_line_source_types[index].name, data)) {
01270 return connected_line_source_types[index].value;
01271 }
01272 }
01273
01274 return -1;
01275 }
01276
01277 const char *ast_connected_line_source_describe(int data)
01278 {
01279 int index;
01280
01281 for (index = 0; index < ARRAY_LEN(connected_line_source_types); ++index) {
01282 if (connected_line_source_types[index].value == data) {
01283 return connected_line_source_types[index].description;
01284 }
01285 }
01286
01287 return "not-known";
01288 }
01289
01290 const char *ast_connected_line_source_name(int data)
01291 {
01292 int index;
01293
01294 for (index = 0; index < ARRAY_LEN(connected_line_source_types); ++index) {
01295 if (connected_line_source_types[index].value == data) {
01296 return connected_line_source_types[index].name;
01297 }
01298 }
01299
01300 return "not-known";
01301 }
01302
01303
01304 static const struct ast_value_translation party_name_charset_tbl[] = {
01305
01306 { AST_PARTY_CHAR_SET_UNKNOWN, "unknown", "Unknown" },
01307 { AST_PARTY_CHAR_SET_ISO8859_1, "iso8859-1", "ISO8859-1" },
01308 { AST_PARTY_CHAR_SET_WITHDRAWN, "withdrawn", "Withdrawn" },
01309 { AST_PARTY_CHAR_SET_ISO8859_2, "iso8859-2", "ISO8859-2" },
01310 { AST_PARTY_CHAR_SET_ISO8859_3, "iso8859-3", "ISO8859-3" },
01311 { AST_PARTY_CHAR_SET_ISO8859_4, "iso8859-4", "ISO8859-4" },
01312 { AST_PARTY_CHAR_SET_ISO8859_5, "iso8859-5", "ISO8859-5" },
01313 { AST_PARTY_CHAR_SET_ISO8859_7, "iso8859-7", "ISO8859-7" },
01314 { AST_PARTY_CHAR_SET_ISO10646_BMPSTRING, "bmp", "ISO10646 Bmp String" },
01315 { AST_PARTY_CHAR_SET_ISO10646_UTF_8STRING, "utf8", "ISO10646 UTF-8 String" },
01316
01317 };
01318
01319 int ast_party_name_charset_parse(const char *data)
01320 {
01321 int index;
01322
01323 for (index = 0; index < ARRAY_LEN(party_name_charset_tbl); ++index) {
01324 if (!strcasecmp(party_name_charset_tbl[index].name, data)) {
01325 return party_name_charset_tbl[index].value;
01326 }
01327 }
01328
01329 return -1;
01330 }
01331
01332 const char *ast_party_name_charset_describe(int data)
01333 {
01334 int index;
01335
01336 for (index = 0; index < ARRAY_LEN(party_name_charset_tbl); ++index) {
01337 if (party_name_charset_tbl[index].value == data) {
01338 return party_name_charset_tbl[index].description;
01339 }
01340 }
01341
01342 return "not-known";
01343 }
01344
01345 const char *ast_party_name_charset_str(int data)
01346 {
01347 int index;
01348
01349 for (index = 0; index < ARRAY_LEN(party_name_charset_tbl); ++index) {
01350 if (party_name_charset_tbl[index].value == data) {
01351 return party_name_charset_tbl[index].name;
01352 }
01353 }
01354
01355 return "not-known";
01356 }