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