![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
callerid.c
Go to the documentation of this file.
00001 /* 00002 * Asterisk -- An open source telephony toolkit. 00003 * 00004 * Copyright (C) 1999 - 2005, Digium, Inc. 00005 * 00006 * Mark Spencer <markster@digium.com> 00007 * 00008 * See http://www.asterisk.org for more information about 00009 * the Asterisk project. Please do not directly contact 00010 * any of the maintainers of this project for assistance; 00011 * the project provides a web site, mailing lists and IRC 00012 * channels for your use. 00013 * 00014 * This program is free software, distributed under the terms of 00015 * the GNU General Public License Version 2. See the LICENSE file 00016 * at the top of the source tree. 00017 */ 00018 00019 /*! \file 00020 * 00021 * \brief CallerID Generation support 00022 * 00023 * \author Mark Spencer <markster@digium.com> 00024 */ 00025 00026 #include "asterisk.h" 00027 00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 51701 $") 00029 00030 #include <time.h> 00031 #include <string.h> 00032 #include <stdio.h> 00033 #include <stdlib.h> 00034 #include <unistd.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/logger.h" 00044 #include "asterisk/fskmodem.h" 00045 #include "asterisk/options.h" 00046 #include "asterisk/utils.h" 00047 00048 struct callerid_state { 00049 fsk_data fskd; 00050 char rawdata[256]; 00051 short oldstuff[160]; 00052 int oldlen; 00053 int pos; 00054 int type; 00055 int cksum; 00056 char name[64]; 00057 char number[64]; 00058 int flags; 00059 int sawflag; 00060 int len; 00061 00062 int skipflag; 00063 unsigned short crc; 00064 }; 00065 00066 00067 float cid_dr[4], cid_di[4]; 00068 float clidsb = 8000.0 / 1200.0; 00069 float sasdr, sasdi; 00070 float casdr1, casdi1, casdr2, casdi2; 00071 00072 #define CALLERID_SPACE 2200.0 /*!< 2200 hz for "0" */ 00073 #define CALLERID_MARK 1200.0 /*!< 1200 hz for "1" */ 00074 #define SAS_FREQ 440.0 00075 #define CAS_FREQ1 2130.0 00076 #define CAS_FREQ2 2750.0 00077 00078 #define AST_CALLERID_UNKNOWN "<unknown>" 00079 00080 static inline void gen_tones(unsigned char *buf, int len, int codec, float ddr1, float ddi1, float ddr2, float ddi2, float *cr1, float *ci1, float *cr2, float *ci2) 00081 { 00082 int x; 00083 float t; 00084 for (x = 0; x < len; x++) { 00085 t = *cr1 * ddr1 - *ci1 * ddi1; 00086 *ci1 = *cr1 * ddi1 + *ci1 * ddr1; 00087 *cr1 = t; 00088 t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1); 00089 *cr1 *= t; 00090 *ci1 *= t; 00091 00092 t = *cr2 * ddr2 - *ci2 * ddi2; 00093 *ci2 = *cr2 * ddi2 + *ci2 * ddr2; 00094 *cr2 = t; 00095 t = 2.0 - (*cr2 * *cr2 + *ci2 * *ci2); 00096 *cr2 *= t; 00097 *ci2 *= t; 00098 buf[x] = AST_LIN2X((*cr1 + *cr2) * 2048.0); 00099 } 00100 } 00101 00102 static inline void gen_tone(unsigned char *buf, int len, int codec, float ddr1, float ddi1, float *cr1, float *ci1) 00103 { 00104 int x; 00105 float t; 00106 for (x = 0; x < len; x++) { 00107 t = *cr1 * ddr1 - *ci1 * ddi1; 00108 *ci1 = *cr1 * ddi1 + *ci1 * ddr1; 00109 *cr1 = t; 00110 t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1); 00111 *cr1 *= t; 00112 *ci1 *= t; 00113 buf[x] = AST_LIN2X(*cr1 * 8192.0); 00114 } 00115 } 00116 00117 /*! \brief Initialize stuff for inverse FFT */ 00118 void callerid_init(void) 00119 { 00120 cid_dr[0] = cos(CALLERID_SPACE * 2.0 * M_PI / 8000.0); 00121 cid_di[0] = sin(CALLERID_SPACE * 2.0 * M_PI / 8000.0); 00122 cid_dr[1] = cos(CALLERID_MARK * 2.0 * M_PI / 8000.0); 00123 cid_di[1] = sin(CALLERID_MARK * 2.0 * M_PI / 8000.0); 00124 sasdr = cos(SAS_FREQ * 2.0 * M_PI / 8000.0); 00125 sasdi = sin(SAS_FREQ * 2.0 * M_PI / 8000.0); 00126 casdr1 = cos(CAS_FREQ1 * 2.0 * M_PI / 8000.0); 00127 casdi1 = sin(CAS_FREQ1 * 2.0 * M_PI / 8000.0); 00128 casdr2 = cos(CAS_FREQ2 * 2.0 * M_PI / 8000.0); 00129 casdi2 = sin(CAS_FREQ2 * 2.0 * M_PI / 8000.0); 00130 } 00131 00132 struct callerid_state *callerid_new(int cid_signalling) 00133 { 00134 struct callerid_state *cid; 00135 00136 if ((cid = ast_calloc(1, sizeof(*cid)))) { 00137 cid->fskd.spb = 7.0; /* 1200 baud */ 00138 /* cid->fskd.hdlc = 0; */ /* Async */ 00139 cid->fskd.nbit = 8; /* 8 bits */ 00140 cid->fskd.nstop = 1.0; /* 1 stop bit */ 00141 /* cid->fskd.paridad = 0; */ /* No parity */ 00142 cid->fskd.bw = 1; /* Filter 800 Hz */ 00143 if (cid_signalling == 2) { /* v23 signalling */ 00144 cid->fskd.f_mark_idx = 4; /* 1300 Hz */ 00145 cid->fskd.f_space_idx = 5; /* 2100 Hz */ 00146 } else { /* Bell 202 signalling as default */ 00147 cid->fskd.f_mark_idx = 2; /* 1200 Hz */ 00148 cid->fskd.f_space_idx = 3; /* 2200 Hz */ 00149 } 00150 /* cid->fskd.pcola = 0; */ /* No clue */ 00151 /* cid->fskd.cont = 0.0; */ /* Digital PLL reset */ 00152 /* cid->fskd.x0 = 0.0; */ 00153 /* cid->fskd.state = 0; */ 00154 cid->flags = CID_UNKNOWN_NAME | CID_UNKNOWN_NUMBER; 00155 /* cid->pos = 0; */ 00156 } 00157 00158 return cid; 00159 } 00160 00161 void callerid_get(struct callerid_state *cid, char **name, char **number, int *flags) 00162 { 00163 *flags = cid->flags; 00164 if (cid->flags & (CID_UNKNOWN_NAME | CID_PRIVATE_NAME)) 00165 *name = NULL; 00166 else 00167 *name = cid->name; 00168 if (cid->flags & (CID_UNKNOWN_NUMBER | CID_PRIVATE_NUMBER)) 00169 *number = NULL; 00170 else 00171 *number = cid->number; 00172 } 00173 00174 void callerid_get_dtmf(char *cidstring, char *number, int *flags) 00175 { 00176 int i; 00177 int code; 00178 00179 /* "Clear" the number-buffer. */ 00180 number[0] = 0; 00181 00182 if (strlen(cidstring) < 2) { 00183 ast_log(LOG_DEBUG, "No cid detected\n"); 00184 *flags = CID_UNKNOWN_NUMBER; 00185 return; 00186 } 00187 00188 /* Detect protocol and special types */ 00189 if (cidstring[0] == 'B') { 00190 /* Handle special codes */ 00191 code = atoi(&cidstring[1]); 00192 if (code == 0) 00193 *flags = CID_UNKNOWN_NUMBER; 00194 else if (code == 10) 00195 *flags = CID_PRIVATE_NUMBER; 00196 else 00197 ast_log(LOG_DEBUG, "Unknown DTMF code %d\n", code); 00198 } else if (cidstring[0] == 'D' && cidstring[2] == '#') { 00199 /* .DK special code */ 00200 if (cidstring[1] == '1') 00201 *flags = CID_PRIVATE_NUMBER; 00202 if (cidstring[1] == '2' || cidstring[1] == '3') 00203 *flags = CID_UNKNOWN_NUMBER; 00204 } else if (cidstring[0] == 'D' || cidstring[0] == 'A') { 00205 /* "Standard" callerid */ 00206 for (i = 1; i < strlen(cidstring); i++) { 00207 if (cidstring[i] == 'C' || cidstring[i] == '#') 00208 break; 00209 if (isdigit(cidstring[i])) 00210 number[i-1] = cidstring[i]; 00211 else 00212 ast_log(LOG_DEBUG, "Unknown CID digit '%c'\n", 00213 cidstring[i]); 00214 } 00215 number[i-1] = 0; 00216 } else if (isdigit(cidstring[0])) { 00217 /* It begins with a digit, so we parse it as a number and hope 00218 * for the best */ 00219 ast_log(LOG_WARNING, "Couldn't detect start-character. CID " 00220 "parsing might be unreliable\n"); 00221 for (i = 0; i < strlen(cidstring); i++) { 00222 if (isdigit(cidstring[i])) 00223 number[i] = cidstring[i]; 00224 else 00225 break; 00226 } 00227 number[i] = 0; 00228 } else { 00229 if (option_debug) 00230 ast_log(LOG_DEBUG, "Unknown CID protocol, start digit '%c'\n", cidstring[0]); 00231 *flags = CID_UNKNOWN_NUMBER; 00232 } 00233 } 00234 00235 int ast_gen_cas(unsigned char *outbuf, int sendsas, int len, int codec) 00236 { 00237 int pos = 0; 00238 int saslen = 2400; 00239 float cr1 = 1.0; 00240 float ci1 = 0.0; 00241 float cr2 = 1.0; 00242 float ci2 = 0.0; 00243 00244 if (sendsas) { 00245 if (len < saslen) 00246 return -1; 00247 gen_tone(outbuf, saslen, codec, sasdr, sasdi, &cr1, &ci1); 00248 len -= saslen; 00249 pos += saslen; 00250 cr2 = cr1; 00251 ci2 = ci1; 00252 } 00253 gen_tones(outbuf + pos, len, codec, casdr1, casdi1, casdr2, casdi2, &cr1, &ci1, &cr2, &ci2); 00254 return 0; 00255 } 00256 00257 static unsigned short calc_crc(unsigned short crc, unsigned char data) 00258 { 00259 unsigned int i, j, org, dst; 00260 org = data; 00261 dst = 0; 00262 00263 for (i = 0; i < CHAR_BIT; i++) { 00264 org <<= 1; 00265 dst >>= 1; 00266 if (org & 0x100) 00267 dst |= 0x80; 00268 } 00269 data = (unsigned char) dst; 00270 crc ^= (unsigned int) data << (16 - CHAR_BIT); 00271 for (j = 0; j < CHAR_BIT; j++) { 00272 if (crc & 0x8000U) 00273 crc = (crc << 1) ^ 0x1021U ; 00274 else 00275 crc <<= 1 ; 00276 } 00277 return crc; 00278 } 00279 00280 int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int len, int codec) 00281 { 00282 int mylen = len; 00283 int olen; 00284 int b = 'X'; 00285 int b2; 00286 int res; 00287 int x; 00288 short *buf; 00289 00290 buf = alloca(2 * len + cid->oldlen); 00291 00292 memcpy(buf, cid->oldstuff, cid->oldlen); 00293 mylen += cid->oldlen / 2; 00294 00295 for (x = 0; x < len; x++) 00296 buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]); 00297 00298 while (mylen >= 160) { 00299 b = b2 = 0; 00300 olen = mylen; 00301 res = fsk_serial(&cid->fskd, buf, &mylen, &b); 00302 00303 if (mylen < 0) { 00304 ast_log(LOG_ERROR, "fsk_serial made mylen < 0 (%d)\n", mylen); 00305 return -1; 00306 } 00307 00308 buf += (olen - mylen); 00309 00310 if (res < 0) { 00311 ast_log(LOG_NOTICE, "fsk_serial failed\n"); 00312 return -1; 00313 } 00314 00315 if (res == 1) { 00316 b2 = b; 00317 b &= 0x7f; 00318 00319 /* crc checksum calculation */ 00320 if (cid->sawflag > 1) 00321 cid->crc = calc_crc(cid->crc, (unsigned char) b2); 00322 00323 /* Ignore invalid bytes */ 00324 if (b > 0xff) 00325 continue; 00326 00327 /* skip DLE if needed */ 00328 if (cid->sawflag > 0) { 00329 if (cid->sawflag != 5 && cid->skipflag == 0 && b == 0x10) { 00330 cid->skipflag = 1 ; 00331 continue ; 00332 } 00333 } 00334 if (cid->skipflag == 1) 00335 cid->skipflag = 0 ; 00336 00337 /* caller id retrieval */ 00338 switch (cid->sawflag) { 00339 case 0: /* DLE */ 00340 if (b == 0x10) { 00341 cid->sawflag = 1; 00342 cid->skipflag = 0; 00343 cid->crc = 0; 00344 } 00345 break; 00346 case 1: /* SOH */ 00347 if (b == 0x01) 00348 cid->sawflag = 2; 00349 break ; 00350 case 2: /* HEADER */ 00351 if (b == 0x07) 00352 cid->sawflag = 3; 00353 break; 00354 case 3: /* STX */ 00355 if (b == 0x02) 00356 cid->sawflag = 4; 00357 break; 00358 case 4: /* SERVICE TYPE */ 00359 if (b == 0x40) 00360 cid->sawflag = 5; 00361 break; 00362 case 5: /* Frame Length */ 00363 cid->sawflag = 6; 00364 break; 00365 case 6: /* NUMBER TYPE */ 00366 cid->sawflag = 7; 00367 cid->pos = 0; 00368 cid->rawdata[cid->pos++] = b; 00369 break; 00370 case 7: /* NUMBER LENGTH */ 00371 cid->sawflag = 8; 00372 cid->len = b; 00373 if ((cid->len+2) >= sizeof(cid->rawdata)) { 00374 ast_log(LOG_WARNING, "too long caller id string\n") ; 00375 return -1; 00376 } 00377 cid->rawdata[cid->pos++] = b; 00378 break; 00379 case 8: /* Retrieve message */ 00380 cid->rawdata[cid->pos++] = b; 00381 cid->len--; 00382 if (cid->len<=0) { 00383 cid->rawdata[cid->pos] = '\0'; 00384 cid->sawflag = 9; 00385 } 00386 break; 00387 case 9: /* ETX */ 00388 cid->sawflag = 10; 00389 break; 00390 case 10: /* CRC Checksum 1 */ 00391 cid->sawflag = 11; 00392 break; 00393 case 11: /* CRC Checksum 2 */ 00394 cid->sawflag = 12; 00395 if (cid->crc != 0) { 00396 ast_log(LOG_WARNING, "crc checksum error\n") ; 00397 return -1; 00398 } 00399 /* extract caller id data */ 00400 for (x = 0; x < cid->pos;) { 00401 switch (cid->rawdata[x++]) { 00402 case 0x02: /* caller id number */ 00403 cid->number[0] = '\0'; 00404 cid->name[0] = '\0'; 00405 cid->flags = 0; 00406 res = cid->rawdata[x++]; 00407 ast_copy_string(cid->number, &cid->rawdata[x], res+1); 00408 x += res; 00409 break; 00410 case 0x21: /* additional information */ 00411 /* length */ 00412 x++; 00413 /* number type */ 00414 switch (cid->rawdata[x]) { 00415 case 0x00: /* unknown */ 00416 case 0x01: /* international number */ 00417 case 0x02: /* domestic number */ 00418 case 0x03: /* network */ 00419 case 0x04: /* local call */ 00420 case 0x06: /* short dial number */ 00421 case 0x07: /* reserved */ 00422 default: /* reserved */ 00423 if (option_debug > 1) 00424 ast_log(LOG_DEBUG, "cid info:#1=%X\n", cid->rawdata[x]); 00425 break ; 00426 } 00427 x++; 00428 /* numbering plan octed 4 */ 00429 x++; 00430 /* numbering plan octed 5 */ 00431 switch (cid->rawdata[x]) { 00432 case 0x00: /* unknown */ 00433 case 0x01: /* recommendation E.164 ISDN */ 00434 case 0x03: /* recommendation X.121 */ 00435 case 0x04: /* telex dial plan */ 00436 case 0x08: /* domestic dial plan */ 00437 case 0x09: /* private dial plan */ 00438 case 0x05: /* reserved */ 00439 default: /* reserved */ 00440 if (option_debug > 1) 00441 ast_log(LOG_DEBUG, "cid info:#2=%X\n", cid->rawdata[x]); 00442 break ; 00443 } 00444 x++; 00445 break ; 00446 case 0x04: /* no callerid reason */ 00447 /* length */ 00448 x++; 00449 /* no callerid reason code */ 00450 switch (cid->rawdata[x]) { 00451 case 'P': /* caller id denied by user */ 00452 case 'O': /* service not available */ 00453 case 'C': /* pay phone */ 00454 case 'S': /* service congested */ 00455 cid->flags |= CID_UNKNOWN_NUMBER; 00456 if (option_debug > 1) 00457 ast_log(LOG_DEBUG, "no cid reason:%c\n",cid->rawdata[x]); 00458 break ; 00459 } 00460 x++; 00461 break ; 00462 case 0x09: /* dialed number */ 00463 /* length */ 00464 res = cid->rawdata[x++]; 00465 /* dialed number */ 00466 x += res; 00467 break ; 00468 case 0x22: /* dialed number additional information */ 00469 /* length */ 00470 x++; 00471 /* number type */ 00472 switch (cid->rawdata[x]) { 00473 case 0x00: /* unknown */ 00474 case 0x01: /* international number */ 00475 case 0x02: /* domestic number */ 00476 case 0x03: /* network */ 00477 case 0x04: /* local call */ 00478 case 0x06: /* short dial number */ 00479 case 0x07: /* reserved */ 00480 default: /* reserved */ 00481 if (option_debug > 1) 00482 ast_log(LOG_NOTICE, "did info:#1=%X\n", cid->rawdata[x]); 00483 break ; 00484 } 00485 x++; 00486 /* numbering plan octed 4 */ 00487 x++; 00488 /* numbering plan octed 5 */ 00489 switch (cid->rawdata[x]) { 00490 case 0x00: /* unknown */ 00491 case 0x01: /* recommendation E.164 ISDN */ 00492 case 0x03: /* recommendation X.121 */ 00493 case 0x04: /* telex dial plan */ 00494 case 0x08: /* domestic dial plan */ 00495 case 0x09: /* private dial plan */ 00496 case 0x05: /* reserved */ 00497 default: /* reserved */ 00498 if (option_debug > 1) 00499 ast_log(LOG_DEBUG, "did info:#2=%X\n", cid->rawdata[x]); 00500 break ; 00501 } 00502 x++; 00503 break ; 00504 } 00505 } 00506 return 1; 00507 break; 00508 default: 00509 ast_log(LOG_ERROR, "invalid value in sawflag %d\n", cid->sawflag); 00510 } 00511 } 00512 } 00513 if (mylen) { 00514 memcpy(cid->oldstuff, buf, mylen * 2); 00515 cid->oldlen = mylen * 2; 00516 } else 00517 cid->oldlen = 0; 00518 00519 return 0; 00520 } 00521 00522 00523 int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int codec) 00524 { 00525 int mylen = len; 00526 int olen; 00527 int b = 'X'; 00528 int res; 00529 int x; 00530 short *buf; 00531 00532 buf = alloca(2 * len + cid->oldlen); 00533 00534 memcpy(buf, cid->oldstuff, cid->oldlen); 00535 mylen += cid->oldlen/2; 00536 00537 for (x = 0; x < len; x++) 00538 buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]); 00539 while (mylen >= 160) { 00540 olen = mylen; 00541 res = fsk_serial(&cid->fskd, buf, &mylen, &b); 00542 if (mylen < 0) { 00543 ast_log(LOG_ERROR, "fsk_serial made mylen < 0 (%d)\n", mylen); 00544 return -1; 00545 } 00546 buf += (olen - mylen); 00547 if (res < 0) { 00548 ast_log(LOG_NOTICE, "fsk_serial failed\n"); 00549 return -1; 00550 } 00551 if (res == 1) { 00552 /* Ignore invalid bytes */ 00553 if (b > 0xff) 00554 continue; 00555 switch (cid->sawflag) { 00556 case 0: /* Look for flag */ 00557 if (b == 'U') 00558 cid->sawflag = 2; 00559 break; 00560 case 2: /* Get lead-in */ 00561 if ((b == 0x04) || (b == 0x80)) { 00562 cid->type = b; 00563 cid->sawflag = 3; 00564 cid->cksum = b; 00565 } 00566 break; 00567 case 3: /* Get length */ 00568 /* Not a lead in. We're ready */ 00569 cid->sawflag = 4; 00570 cid->len = b; 00571 cid->pos = 0; 00572 cid->cksum += b; 00573 break; 00574 case 4: /* Retrieve message */ 00575 if (cid->pos >= 128) { 00576 ast_log(LOG_WARNING, "Caller ID too long???\n"); 00577 return -1; 00578 } 00579 cid->rawdata[cid->pos++] = b; 00580 cid->len--; 00581 cid->cksum += b; 00582 if (!cid->len) { 00583 cid->rawdata[cid->pos] = '\0'; 00584 cid->sawflag = 5; 00585 } 00586 break; 00587 case 5: /* Check checksum */ 00588 if (b != (256 - (cid->cksum & 0xff))) { 00589 ast_log(LOG_NOTICE, "Caller*ID failed checksum\n"); 00590 /* Try again */ 00591 cid->sawflag = 0; 00592 break; 00593 } 00594 00595 cid->number[0] = '\0'; 00596 cid->name[0] = '\0'; 00597 /* If we get this far we're fine. */ 00598 if (cid->type == 0x80) { 00599 /* MDMF */ 00600 /* Go through each element and process */ 00601 for (x = 0; x < cid->pos;) { 00602 switch (cid->rawdata[x++]) { 00603 case 1: 00604 /* Date */ 00605 break; 00606 case 2: /* Number */ 00607 case 3: /* Number (for Zebble) */ 00608 case 4: /* Number */ 00609 res = cid->rawdata[x]; 00610 if (res > 32) { 00611 ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]); 00612 res = 32; 00613 } 00614 if (ast_strlen_zero(cid->number)) { 00615 memcpy(cid->number, cid->rawdata + x + 1, res); 00616 /* Null terminate */ 00617 cid->number[res] = '\0'; 00618 } 00619 break; 00620 case 6: /* Stentor Call Qualifier (ie. Long Distance call) */ 00621 break; 00622 case 7: /* Name */ 00623 case 8: /* Name */ 00624 res = cid->rawdata[x]; 00625 if (res > 32) { 00626 ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]); 00627 res = 32; 00628 } 00629 memcpy(cid->name, cid->rawdata + x + 1, res); 00630 cid->name[res] = '\0'; 00631 break; 00632 case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting */ 00633 case 19: /* UK: Network message system status (Number of messages waiting) */ 00634 case 22: /* Something French */ 00635 break; 00636 default: 00637 ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x - 1]); 00638 } 00639 x += cid->rawdata[x]; 00640 x++; 00641 } 00642 } else { 00643 /* SDMF */ 00644 ast_copy_string(cid->number, cid->rawdata + 8, sizeof(cid->number)); 00645 } 00646 /* Update flags */ 00647 cid->flags = 0; 00648 if (!strcmp(cid->number, "P")) { 00649 strcpy(cid->number, ""); 00650 cid->flags |= CID_PRIVATE_NUMBER; 00651 } else if (!strcmp(cid->number, "O") || ast_strlen_zero(cid->number)) { 00652 strcpy(cid->number, ""); 00653 cid->flags |= CID_UNKNOWN_NUMBER; 00654 } 00655 if (!strcmp(cid->name, "P")) { 00656 strcpy(cid->name, ""); 00657 cid->flags |= CID_PRIVATE_NAME; 00658 } else if (!strcmp(cid->name, "O") || ast_strlen_zero(cid->name)) { 00659 strcpy(cid->name, ""); 00660 cid->flags |= CID_UNKNOWN_NAME; 00661 } 00662 return 1; 00663 break; 00664 default: 00665 ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag); 00666 } 00667 } 00668 } 00669 if (mylen) { 00670 memcpy(cid->oldstuff, buf, mylen * 2); 00671 cid->oldlen = mylen * 2; 00672 } else 00673 cid->oldlen = 0; 00674 00675 return 0; 00676 } 00677 00678 void callerid_free(struct callerid_state *cid) 00679 { 00680 free(cid); 00681 } 00682 00683 static int callerid_genmsg(char *msg, int size, const char *number, const char *name, int flags) 00684 { 00685 time_t t; 00686 struct tm tm; 00687 char *ptr; 00688 int res; 00689 int i, x; 00690 00691 /* Get the time */ 00692 time(&t); 00693 localtime_r(&t,&tm); 00694 00695 ptr = msg; 00696 00697 /* Format time and message header */ 00698 res = snprintf(ptr, size, "\001\010%02d%02d%02d%02d", tm.tm_mon + 1, 00699 tm.tm_mday, tm.tm_hour, tm.tm_min); 00700 size -= res; 00701 ptr += res; 00702 if (ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) { 00703 /* Indicate number not known */ 00704 res = snprintf(ptr, size, "\004\001O"); 00705 size -= res; 00706 ptr += res; 00707 } else if (flags & CID_PRIVATE_NUMBER) { 00708 /* Indicate number is private */ 00709 res = snprintf(ptr, size, "\004\001P"); 00710 size -= res; 00711 ptr += res; 00712 } else { 00713 /* Send up to 16 digits of number MAX */ 00714 i = strlen(number); 00715 if (i > 16) 00716 i = 16; 00717 res = snprintf(ptr, size, "\002%c", i); 00718 size -= res; 00719 ptr += res; 00720 for (x = 0; x < i; x++) 00721 ptr[x] = number[x]; 00722 ptr[i] = '\0'; 00723 ptr += i; 00724 size -= i; 00725 } 00726 00727 if (ast_strlen_zero(name) || (flags & CID_UNKNOWN_NAME)) { 00728 /* Indicate name not known */ 00729 res = snprintf(ptr, size, "\010\001O"); 00730 size -= res; 00731 ptr += res; 00732 } else if (flags & CID_PRIVATE_NAME) { 00733 /* Indicate name is private */ 00734 res = snprintf(ptr, size, "\010\001P"); 00735 size -= res; 00736 ptr += res; 00737 } else { 00738 /* Send up to 16 digits of name MAX */ 00739 i = strlen(name); 00740 if (i > 16) 00741 i = 16; 00742 res = snprintf(ptr, size, "\007%c", i); 00743 size -= res; 00744 ptr += res; 00745 for (x = 0; x < i; x++) 00746 ptr[x] = name[x]; 00747 ptr[i] = '\0'; 00748 ptr += i; 00749 size -= i; 00750 } 00751 return (ptr - msg); 00752 00753 } 00754 00755 int vmwi_generate(unsigned char *buf, int active, int mdmf, int codec) 00756 { 00757 unsigned char msg[256]; 00758 int len=0; 00759 int sum; 00760 int x; 00761 int bytes = 0; 00762 float cr = 1.0; 00763 float ci = 0.0; 00764 float scont = 0.0; 00765 00766 if (mdmf) { 00767 /* MDMF Message waiting */ 00768 msg[len++] = 0x82; 00769 /* Length is 3 */ 00770 msg[len++] = 3; 00771 /* IE is "Message Waiting Parameter" */ 00772 msg[len++] = 0xb; 00773 /* Length of IE is one */ 00774 msg[len++] = 1; 00775 /* Active or not */ 00776 if (active) 00777 msg[len++] = 0xff; 00778 else 00779 msg[len++] = 0x00; 00780 } else { 00781 /* SDMF Message waiting */ 00782 msg[len++] = 0x6; 00783 /* Length is 3 */ 00784 msg[len++] = 3; 00785 if (active) { 00786 msg[len++] = 0x42; 00787 msg[len++] = 0x42; 00788 msg[len++] = 0x42; 00789 } else { 00790 msg[len++] = 0x6f; 00791 msg[len++] = 0x6f; 00792 msg[len++] = 0x6f; 00793 } 00794 } 00795 sum = 0; 00796 for (x = 0; x < len; x++) 00797 sum += msg[x]; 00798 sum = (256 - (sum & 255)); 00799 msg[len++] = sum; 00800 /* Wait a half a second */ 00801 for (x = 0; x < 4000; x++) 00802 PUT_BYTE(0x7f); 00803 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */ 00804 for (x = 0; x < 30; x++) 00805 PUT_CLID(0x55); 00806 /* Send 170ms of callerid marks */ 00807 for (x = 0; x < 170; x++) 00808 PUT_CLID_MARKMS; 00809 for (x = 0; x < len; x++) { 00810 PUT_CLID(msg[x]); 00811 } 00812 /* Send 50 more ms of marks */ 00813 for (x = 0; x < 50; x++) 00814 PUT_CLID_MARKMS; 00815 return bytes; 00816 } 00817 00818 int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, int codec) 00819 { 00820 int bytes=0; 00821 int x, sum; 00822 int len; 00823 00824 /* Initial carriers (real/imaginary) */ 00825 float cr = 1.0; 00826 float ci = 0.0; 00827 float scont = 0.0; 00828 char msg[256]; 00829 len = callerid_genmsg(msg, sizeof(msg), number, name, flags); 00830 if (!callwaiting) { 00831 /* Wait a half a second */ 00832 for (x = 0; x < 4000; x++) 00833 PUT_BYTE(0x7f); 00834 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */ 00835 for (x = 0; x < 30; x++) 00836 PUT_CLID(0x55); 00837 } 00838 /* Send 150ms of callerid marks */ 00839 for (x = 0; x < 150; x++) 00840 PUT_CLID_MARKMS; 00841 /* Send 0x80 indicating MDMF format */ 00842 PUT_CLID(0x80); 00843 /* Put length of whole message */ 00844 PUT_CLID(len); 00845 sum = 0x80 + strlen(msg); 00846 /* Put each character of message and update checksum */ 00847 for (x = 0; x < len; x++) { 00848 PUT_CLID(msg[x]); 00849 sum += msg[x]; 00850 } 00851 /* Send 2's compliment of sum */ 00852 PUT_CLID(256 - (sum & 255)); 00853 00854 /* Send 50 more ms of marks */ 00855 for (x = 0; x < 50; x++) 00856 PUT_CLID_MARKMS; 00857 00858 return bytes; 00859 } 00860 00861 /*! \brief Clean up phone string 00862 * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets. 00863 * Basically, remove anything that could be invalid in a pattern. 00864 */ 00865 void ast_shrink_phone_number(char *n) 00866 { 00867 int x, y=0; 00868 int bracketed = 0; 00869 00870 for (x = 0; n[x]; x++) { 00871 switch (n[x]) { 00872 case '[': 00873 bracketed++; 00874 n[y++] = n[x]; 00875 break; 00876 case ']': 00877 bracketed--; 00878 n[y++] = n[x]; 00879 break; 00880 case '-': 00881 if (bracketed) 00882 n[y++] = n[x]; 00883 break; 00884 case '.': 00885 if (!n[x+1]) 00886 n[y++] = n[x]; 00887 break; 00888 default: 00889 if (!strchr("()", n[x])) 00890 n[y++] = n[x]; 00891 } 00892 } 00893 n[y] = '\0'; 00894 } 00895 00896 /*! \brief Checks if phone number consists of valid characters 00897 \param exten String that needs to be checked 00898 \param valid Valid characters in string 00899 \return 1 if valid string, 0 if string contains invalid characters 00900 */ 00901 static int ast_is_valid_string(const char *exten, const char *valid) 00902 { 00903 int x; 00904 00905 if (ast_strlen_zero(exten)) 00906 return 0; 00907 for (x = 0; exten[x]; x++) 00908 if (!strchr(valid, exten[x])) 00909 return 0; 00910 return 1; 00911 } 00912 00913 /*! \brief checks if string consists only of digits and * \# and + 00914 \return 1 if string is valid AST phone number 00915 \return 0 if not 00916 */ 00917 int ast_isphonenumber(const char *n) 00918 { 00919 return ast_is_valid_string(n, "0123456789*#+"); 00920 } 00921 00922 /*! \brief checks if string consists only of digits and ( ) - * \# and + 00923 Pre-qualifies the string for ast_shrink_phone_number() 00924 \return 1 if string is valid AST shrinkable phone number 00925 \return 0 if not 00926 */ 00927 int ast_is_shrinkable_phonenumber(const char *exten) 00928 { 00929 return ast_is_valid_string(exten, "0123456789*#+()-."); 00930 } 00931 00932 /*! \brief parse string for caller id information 00933 \return always returns 0, as the code always returns something. 00934 XXX note that 'name' is not parsed consistently e.g. we have 00935 00936 input location name 00937 " foo bar " <123> 123 ' foo bar ' (with spaces around) 00938 " foo bar " NULL 'foo bar' (without spaces around) 00939 " foo bar <123>" 123 '" foo bar' 00940 The parsing of leading and trailing space/quotes should be more consistent. 00941 */ 00942 int ast_callerid_parse(char *instr, char **name, char **location) 00943 { 00944 char *ns, *ne, *ls, *le; 00945 00946 /* Try "name" <location> format or name <location> format */ 00947 if ((ls = strchr(instr, '<')) && (le = strchr(ls, '>'))) { 00948 *ls = *le = '\0'; /* location found, trim off the brackets */ 00949 *location = ls + 1; /* and this is the result */ 00950 if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) { 00951 *ns = *ne = '\0'; /* trim off the quotes */ 00952 *name = ns + 1; /* and this is the name */ 00953 } else { /* no quotes, trim off leading and trailing spaces */ 00954 *name = ast_skip_blanks(instr); 00955 ast_trim_blanks(*name); 00956 } 00957 } else { /* no valid brackets */ 00958 char tmp[256]; 00959 00960 ast_copy_string(tmp, instr, sizeof(tmp)); 00961 ast_shrink_phone_number(tmp); 00962 if (ast_isphonenumber(tmp)) { /* Assume it's just a location */ 00963 *name = NULL; 00964 strcpy(instr, tmp); /* safe, because tmp will always be the same size or smaller than instr */ 00965 *location = instr; 00966 } else { /* Assume it's just a name. */ 00967 *location = NULL; 00968 if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) { 00969 *ns = *ne = '\0'; /* trim off the quotes */ 00970 *name = ns + 1; /* and this is the name */ 00971 } else { /* no quotes, trim off leading and trailing spaces */ 00972 *name = ast_skip_blanks(instr); 00973 ast_trim_blanks(*name); 00974 } 00975 } 00976 } 00977 return 0; 00978 } 00979 00980 static int __ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int callwaiting, int codec) 00981 { 00982 if (ast_strlen_zero(name)) 00983 name = NULL; 00984 if (ast_strlen_zero(number)) 00985 number = NULL; 00986 return callerid_generate(buf, number, name, 0, callwaiting, codec); 00987 } 00988 00989 int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int codec) 00990 { 00991 return __ast_callerid_generate(buf, name, number, 0, codec); 00992 } 00993 00994 int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, int codec) 00995 { 00996 return __ast_callerid_generate(buf, name, number, 1, codec); 00997 } 00998 00999 char *ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown) 01000 { 01001 if (!unknown) 01002 unknown = "<unknown>"; 01003 if (name && num) 01004 snprintf(buf, bufsiz, "\"%s\" <%s>", name, num); 01005 else if (name) 01006 ast_copy_string(buf, name, bufsiz); 01007 else if (num) 01008 ast_copy_string(buf, num, bufsiz); 01009 else 01010 ast_copy_string(buf, unknown, bufsiz); 01011 return buf; 01012 } 01013 01014 int ast_callerid_split(const char *buf, char *name, int namelen, char *num, int numlen) 01015 { 01016 char *tmp; 01017 char *l = NULL, *n = NULL; 01018 01019 tmp = ast_strdupa(buf); 01020 ast_callerid_parse(tmp, &n, &l); 01021 if (n) 01022 ast_copy_string(name, n, namelen); 01023 else 01024 name[0] = '\0'; 01025 if (l) { 01026 ast_shrink_phone_number(l); 01027 ast_copy_string(num, l, numlen); 01028 } else 01029 num[0] = '\0'; 01030 return 0; 01031 } 01032 01033 /*! \brief Translation table for Caller ID Presentation settings */ 01034 static struct { 01035 int val; 01036 const char *name; 01037 const char *description; 01038 } pres_types[] = { 01039 { AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened", "Presentation Allowed, Not Screened"}, 01040 { AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", "Presentation Allowed, Passed Screen"}, 01041 { AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", "Presentation Allowed, Failed Screen"}, 01042 { AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed", "Presentation Allowed, Network Number"}, 01043 { AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "prohib_not_screened", "Presentation Prohibited, Not Screened"}, 01044 { AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", "Presentation Prohibited, Passed Screen"}, 01045 { AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", "Presentation Prohibited, Failed Screen"}, 01046 { AST_PRES_PROHIB_NETWORK_NUMBER, "prohib", "Presentation Prohibited, Network Number"}, 01047 { AST_PRES_NUMBER_NOT_AVAILABLE, "unavailable", "Number Unavailable"}, 01048 }; 01049 01050 /*! \brief Convert caller ID text code to value 01051 used in config file parsing 01052 \param data text string 01053 \return value AST_PRES_ from callerid.h 01054 */ 01055 int ast_parse_caller_presentation(const char *data) 01056 { 01057 int i; 01058 01059 for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) { 01060 if (!strcasecmp(pres_types[i].name, data)) 01061 return pres_types[i].val; 01062 } 01063 01064 return -1; 01065 } 01066 01067 /*! \brief Convert caller ID pres value to explanatory string 01068 \param data value (see callerid.h AST_PRES_ ) 01069 \return string for human presentation 01070 */ 01071 const char *ast_describe_caller_presentation(int data) 01072 { 01073 int i; 01074 01075 for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) { 01076 if (pres_types[i].val == data) 01077 return pres_types[i].description; 01078 } 01079 01080 return "unknown"; 01081 } 01082 01083 /*! \brief Convert caller ID pres value to text code 01084 \param data text string 01085 \return string for config file 01086 */ 01087 const char *ast_named_caller_presentation(int data) 01088 { 01089 int i; 01090 01091 for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) { 01092 if (pres_types[i].val == data) 01093 return pres_types[i].name; 01094 } 01095 01096 return "unknown"; 01097 }