Wed Oct 28 11:50:55 2009

Asterisk developer's documentation


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: 207287 $")
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      /*!< 2200 hz for "0" */
00067 #define CALLERID_MARK   1200.0      /*!< 1200 hz for "1" */
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, int 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, int 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 /*! \brief Initialize stuff for inverse FFT */
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;           /* 1200 baud */   
00133       /* Set up for 1200 / 8000 freq *32 to allow ints */
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;           /* PLL REset */
00139       /* cid->fskd.hdlc = 0; */        /* Async */
00140       cid->fskd.nbit = 8;              /* 8 bits */
00141       cid->fskd.instop = 1;         /* 1 stop bit */
00142       /* cid->fskd.paridad = 0; */     /* No parity */
00143       cid->fskd.bw = 1;                /* Filter 800 Hz */
00144       if (cid_signalling == 2) {       /* v23 signalling */
00145          cid->fskd.f_mark_idx  = 4; /* 1300 Hz */
00146          cid->fskd.f_space_idx = 5; /* 2100 Hz */
00147       } else {                         /* Bell 202 signalling as default */
00148          cid->fskd.f_mark_idx  = 2; /* 1200 Hz */
00149          cid->fskd.f_space_idx = 3; /* 2200 Hz */
00150       }
00151       /* cid->fskd.pcola = 0; */       /* No clue */
00152       /* cid->fskd.cont = 0.0; */      /* Digital PLL reset */
00153       /* cid->fskd.x0 = 0.0; */
00154       /* cid->fskd.state = 0; */
00155       cid->flags = CID_UNKNOWN_NAME | CID_UNKNOWN_NUMBER;
00156       /* cid->pos = 0; */
00157 
00158       fskmodem_init(&cid->fskd);
00159 #else
00160       cid->fskd.spb = 7.0;             /* 1200 baud */
00161       /* cid->fskd.hdlc = 0; */        /* Async */
00162       cid->fskd.nbit = 8;              /* 8 bits */
00163       cid->fskd.nstop = 1.0;           /* 1 stop bit */
00164       /* cid->fskd.paridad = 0; */     /* No parity */
00165       cid->fskd.bw = 1;                /* Filter 800 Hz */
00166       if (cid_signalling == 2) {       /* v23 signalling */
00167          cid->fskd.f_mark_idx =  4; /* 1300 Hz */
00168          cid->fskd.f_space_idx = 5; /* 2100 Hz */
00169       } else {                         /* Bell 202 signalling as default */
00170          cid->fskd.f_mark_idx =  2; /* 1200 Hz */
00171          cid->fskd.f_space_idx = 3; /* 2200 Hz */
00172       }
00173       /* cid->fskd.pcola = 0; */       /* No clue */
00174       /* cid->fskd.cont = 0.0; */      /* Digital PLL reset */
00175       /* cid->fskd.x0 = 0.0; */
00176       /* cid->fskd.state = 0; */
00177       cid->flags = CID_UNKNOWN_NAME | CID_UNKNOWN_NUMBER;
00178       /* cid->pos = 0; */
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    /* "Clear" the number-buffer. */
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    /* Detect protocol and special types */
00213    if (cidstring[0] == 'B') {
00214       /* Handle special codes */
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       /* .DK special code */
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       /* "Standard" callerid */
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       /* It begins with a digit, so we parse it as a number and hope
00242        * for the best */
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, int 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, int 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          /* crc checksum calculation */
00343          if (cid->sawflag > 1)
00344             cid->crc = calc_crc(cid->crc, (unsigned char) b2);
00345 
00346          /* Ignore invalid bytes */
00347          if (b > 0xff)
00348             continue;
00349 
00350          /* skip DLE if needed */
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          /* caller id retrieval */
00361          switch (cid->sawflag) {
00362          case 0: /* DLE */
00363             if (b == 0x10) {
00364                cid->sawflag = 1;
00365                cid->skipflag = 0;
00366                cid->crc = 0;
00367             }
00368             break;
00369          case 1: /* SOH */
00370             if (b == 0x01) 
00371                cid->sawflag = 2;
00372             break ;
00373          case 2: /* HEADER */
00374             if (b == 0x07) 
00375                cid->sawflag = 3;
00376             break;
00377          case 3: /* STX */
00378             if (b == 0x02) 
00379                cid->sawflag = 4;
00380             break;
00381          case 4: /* SERVICE TYPE */
00382             if (b == 0x40) 
00383                cid->sawflag = 5;
00384             break;
00385          case 5: /* Frame Length */
00386             cid->sawflag = 6;
00387             break;   
00388          case 6: /* NUMBER TYPE */
00389             cid->sawflag = 7;
00390             cid->pos = 0;
00391             cid->rawdata[cid->pos++] = b;
00392             break;
00393          case 7:  /* NUMBER LENGTH */
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:  /* Retrieve message */
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:  /* ETX */
00411             cid->sawflag = 10;
00412             break;
00413          case 10: /* CRC Checksum 1 */
00414             cid->sawflag = 11;
00415             break;
00416          case 11: /* CRC Checksum 2 */
00417             cid->sawflag = 12;
00418             if (cid->crc != 0) {
00419                ast_log(LOG_WARNING, "crc checksum error\n") ;
00420                return -1;
00421             } 
00422             /* extract caller id data */
00423             for (x = 0; x < cid->pos;) {
00424                switch (cid->rawdata[x++]) {
00425                case 0x02: /* caller id  number */
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: /* additional information */
00434                   /* length */
00435                   x++; 
00436                   /* number type */
00437                   switch (cid->rawdata[x]) { 
00438                   case 0x00: /* unknown */
00439                   case 0x01: /* international number */
00440                   case 0x02: /* domestic number */
00441                   case 0x03: /* network */
00442                   case 0x04: /* local call */
00443                   case 0x06: /* short dial number */
00444                   case 0x07: /* reserved */
00445                   default:   /* reserved */
00446                      ast_debug(2, "cid info:#1=%X\n", cid->rawdata[x]);
00447                      break ;
00448                   }
00449                   x++; 
00450                   /* numbering plan octed 4 */
00451                   x++; 
00452                   /* numbering plan octed 5 */
00453                   switch (cid->rawdata[x]) { 
00454                   case 0x00: /* unknown */
00455                   case 0x01: /* recommendation E.164 ISDN */
00456                   case 0x03: /* recommendation X.121 */
00457                   case 0x04: /* telex dial plan */
00458                   case 0x08: /* domestic dial plan */
00459                   case 0x09: /* private dial plan */
00460                   case 0x05: /* reserved */
00461                   default:   /* reserved */
00462                      ast_debug(2, "cid info:#2=%X\n", cid->rawdata[x]);
00463                      break ;
00464                   }
00465                   x++; 
00466                   break ;
00467                case 0x04: /* no callerid reason */
00468                   /* length */
00469                   x++; 
00470                   /* no callerid reason code */
00471                   switch (cid->rawdata[x]) {
00472                   case 'P': /* caller id denied by user */
00473                   case 'O': /* service not available */
00474                   case 'C': /* pay phone */
00475                   case 'S': /* service congested */
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: /* dialed number */
00483                   /* length */
00484                   res = cid->rawdata[x++];
00485                   /* dialed number */
00486                   x += res;
00487                   break ;
00488                case 0x22: /* dialed number additional information */
00489                   /* length */
00490                   x++;
00491                   /* number type */
00492                   switch (cid->rawdata[x]) {
00493                   case 0x00: /* unknown */
00494                   case 0x01: /* international number */
00495                   case 0x02: /* domestic number */
00496                   case 0x03: /* network */
00497                   case 0x04: /* local call */
00498                   case 0x06: /* short dial number */
00499                   case 0x07: /* reserved */
00500                   default:   /* reserved */
00501                      if (option_debug > 1)
00502                         ast_log(LOG_NOTICE, "did info:#1=%X\n", cid->rawdata[x]);
00503                      break ;
00504                   }
00505                   x++;
00506                   /* numbering plan octed 4 */
00507                   x++;
00508                   /* numbering plan octed 5 */
00509                   switch (cid->rawdata[x]) {
00510                   case 0x00: /* unknown */
00511                   case 0x01: /* recommendation E.164 ISDN */
00512                   case 0x03: /* recommendation X.121 */
00513                   case 0x04: /* telex dial plan */
00514                   case 0x08: /* domestic dial plan */
00515                   case 0x09: /* private dial plan */
00516                   case 0x05: /* reserved */
00517                   default:   /* reserved */
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, int 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          /* Ignore invalid bytes */
00572          if (b > 0xff)
00573             continue;
00574          switch (cid->sawflag) {
00575          case 0: /* Look for flag */
00576             if (b == 'U')
00577                cid->sawflag = 2;
00578             break;
00579          case 2: /* Get lead-in */
00580             if ((b == 0x04) || (b == 0x80) || (b == 0x06) || (b == 0x82)) {
00581                cid->type = b;
00582                cid->sawflag = 3;
00583                cid->cksum = b;
00584             }
00585             break;
00586          case 3:  /* Get length */
00587             /* Not a lead in.  We're ready  */
00588             cid->sawflag = 4;
00589             cid->len = b;
00590             cid->pos = 0;
00591             cid->cksum += b;
00592             break;
00593          case 4: /* Retrieve message */
00594             if (cid->pos >= 128) {
00595                ast_log(LOG_WARNING, "Caller ID too long???\n");
00596                return -1;
00597             }
00598             cid->rawdata[cid->pos++] = b;
00599             cid->len--;
00600             cid->cksum += b;
00601             if (!cid->len) {
00602                cid->rawdata[cid->pos] = '\0';
00603                cid->sawflag = 5;
00604             }
00605             break;
00606          case 5: /* Check checksum */
00607             if (b != (256 - (cid->cksum & 0xff))) {
00608                ast_log(LOG_NOTICE, "Caller*ID failed checksum\n");
00609                /* Try again */
00610                cid->sawflag = 0;
00611                break;
00612             }
00613       
00614             cid->number[0] = '\0';
00615             cid->name[0] = '\0';
00616             /* Update flags */
00617             cid->flags = 0;
00618             /* If we get this far we're fine.  */
00619             if ((cid->type == 0x80) || (cid->type == 0x82)) {
00620                /* MDMF */
00621                /* Go through each element and process */
00622                for (x = 0; x < cid->pos;) {
00623                   switch (cid->rawdata[x++]) {
00624                   case 1:
00625                      /* Date */
00626                      break;
00627                   case 2: /* Number */
00628                   case 3: /* Number (for Zebble) */
00629                   case 4: /* Number */
00630                      res = cid->rawdata[x];
00631                      if (res > 32) {
00632                         ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]);
00633                         res = 32; 
00634                      }
00635                      if (ast_strlen_zero(cid->number)) {
00636                         memcpy(cid->number, cid->rawdata + x + 1, res);
00637                         /* Null terminate */
00638                         cid->number[res] = '\0';
00639                      }
00640                      break;
00641                   case 6: /* Stentor Call Qualifier (ie. Long Distance call) */
00642                      break;
00643                   case 7: /* Name */
00644                   case 8: /* Name */
00645                      res = cid->rawdata[x];
00646                      if (res > 32) {
00647                         ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]);
00648                         res = 32; 
00649                      }
00650                      memcpy(cid->name, cid->rawdata + x + 1, res);
00651                      cid->name[res] = '\0';
00652                      break;
00653                   case 11: /* Message Waiting */
00654                      res = cid->rawdata[x + 1];
00655                      if (res)
00656                         cid->flags |= CID_MSGWAITING;
00657                      else
00658                         cid->flags |= CID_NOMSGWAITING;
00659                      break;
00660                   case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting  */
00661                   case 19: /* UK: Network message system status (Number of messages waiting) */
00662                   case 22: /* Something French */
00663                      break;
00664                   default:
00665                      ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x - 1]);
00666                   }
00667                   res = cid->rawdata[x];
00668                   if (0 > res){  /* Negative offset in the CID Spill */
00669                      ast_log(LOG_NOTICE, "IE %d has bad field length of %d at offset %d\n", cid->rawdata[x-1], cid->rawdata[x], x);
00670                      /* Try again */
00671                      cid->sawflag = 0;
00672                      break;   /* Exit the loop */
00673                   }
00674                   x += cid->rawdata[x];
00675                   x++;
00676                }
00677             } else if (cid->type == 0x6) {
00678                /* VMWI SDMF */
00679                if (cid->rawdata[2] == 0x42) {
00680                   cid->flags |= CID_MSGWAITING;
00681                } else if (cid->rawdata[2] == 0x6f) {
00682                   cid->flags |= CID_NOMSGWAITING;
00683                }
00684             } else {
00685                /* SDMF */
00686                ast_copy_string(cid->number, cid->rawdata + 8, sizeof(cid->number));
00687             }
00688             if (!strcmp(cid->number, "P")) {
00689                strcpy(cid->number, "");
00690                cid->flags |= CID_PRIVATE_NUMBER;
00691             } else if (!strcmp(cid->number, "O") || ast_strlen_zero(cid->number)) {
00692                strcpy(cid->number, "");
00693                cid->flags |= CID_UNKNOWN_NUMBER;
00694             }
00695             if (!strcmp(cid->name, "P")) {
00696                strcpy(cid->name, "");
00697                cid->flags |= CID_PRIVATE_NAME;
00698             } else if (!strcmp(cid->name, "O") || ast_strlen_zero(cid->name)) {
00699                strcpy(cid->name, "");
00700                cid->flags |= CID_UNKNOWN_NAME;
00701             }
00702             return 1;
00703             break;
00704          default:
00705             ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag);
00706          }
00707       }
00708    }
00709    if (mylen) {
00710       memcpy(cid->oldstuff, buf, mylen * 2);
00711       cid->oldlen = mylen * 2;
00712    } else
00713       cid->oldlen = 0;
00714 
00715    return 0;
00716 }
00717 
00718 void callerid_free(struct callerid_state *cid)
00719 {
00720    ast_free(cid);
00721 }
00722 
00723 static int callerid_genmsg(char *msg, int size, const char *number, const char *name, int flags)
00724 {
00725    struct timeval now = ast_tvnow();
00726    struct ast_tm tm;
00727    char *ptr;
00728    int res;
00729    int i, x;
00730 
00731    /* Get the time */
00732    ast_localtime(&now, &tm, NULL);
00733    
00734    ptr = msg;
00735    
00736    /* Format time and message header */
00737    res = snprintf(ptr, size, "\001\010%02d%02d%02d%02d", tm.tm_mon + 1,
00738             tm.tm_mday, tm.tm_hour, tm.tm_min);
00739    size -= res;
00740    ptr += res;
00741    if (ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) {
00742       /* Indicate number not known */
00743       res = snprintf(ptr, size, "\004\001O");
00744       size -= res;
00745       ptr += res;
00746    } else if (flags & CID_PRIVATE_NUMBER) {
00747       /* Indicate number is private */
00748       res = snprintf(ptr, size, "\004\001P");
00749       size -= res;
00750       ptr += res;
00751    } else {
00752       /* Send up to 16 digits of number MAX */
00753       i = strlen(number);
00754       if (i > 16)
00755          i = 16;
00756       res = snprintf(ptr, size, "\002%c", i);
00757       size -= res;
00758       ptr += res;
00759       for (x = 0; x < i; x++)
00760          ptr[x] = number[x];
00761       ptr[i] = '\0';
00762       ptr += i;
00763       size -= i;
00764    }
00765 
00766    if (ast_strlen_zero(name) || (flags & CID_UNKNOWN_NAME)) {
00767       /* Indicate name not known */
00768       res = snprintf(ptr, size, "\010\001O");
00769       size -= res;
00770       ptr += res;
00771    } else if (flags & CID_PRIVATE_NAME) {
00772       /* Indicate name is private */
00773       res = snprintf(ptr, size, "\010\001P");
00774       size -= res;
00775       ptr += res;
00776    } else {
00777       /* Send up to 16 digits of name MAX */
00778       i = strlen(name);
00779       if (i > 16)
00780          i = 16;
00781       res = snprintf(ptr, size, "\007%c", i);
00782       size -= res;
00783       ptr += res;
00784       for (x = 0; x < i; x++)
00785          ptr[x] = name[x];
00786       ptr[i] = '\0';
00787       ptr += i;
00788       size -= i;
00789    }
00790    return (ptr - msg);
00791    
00792 }
00793 
00794 int vmwi_generate(unsigned char *buf, int active, int type, int codec,
00795               const char* name, const char* number, int flags)
00796 {
00797    char msg[256];
00798    int len = 0;
00799    int sum;
00800    int x;
00801    int bytes = 0;
00802    float cr = 1.0;
00803    float ci = 0.0;
00804    float scont = 0.0;
00805    
00806    if (type == CID_MWI_TYPE_MDMF_FULL) {
00807       /* MDMF Message waiting with date, number, name and MWI parameter */
00808       msg[0] = 0x82;
00809 
00810       /* put date, number info at the right place */
00811       len = callerid_genmsg(msg+2, sizeof(msg)-2, number, name, flags); 
00812       
00813       /* length of MDMF CLI plus Message Waiting Structure */
00814       msg[1] = len+3;
00815       
00816       /* Go to the position to write to */
00817       len = len+2;
00818       
00819       /* "Message Waiting Parameter" */
00820       msg[len++] = 0x0b;
00821       /* Length of IE is one */
00822       msg[len++] = 1;
00823       /* Active or not */
00824       if (active)
00825          msg[len++] = 0xff;
00826       else
00827          msg[len++] = 0x00;
00828       
00829    } else if (type == CID_MWI_TYPE_MDMF) {
00830       /* MDMF Message waiting only */
00831       /* same as above except that the we only put MWI parameter */
00832       msg[len++] = 0x82;
00833       /* Length is 3 */
00834       msg[len++] = 3;
00835       /* IE is "Message Waiting Parameter" */
00836       msg[len++] = 0x0b;
00837       /* Length of IE is one */
00838       msg[len++] = 1;
00839       /* Active or not */
00840       if (active)
00841          msg[len++] = 0xff;
00842       else
00843          msg[len++] = 0x00;
00844    } else {
00845       /* SDMF Message waiting */
00846       msg[len++] = 0x6;
00847       /* Length is 3 */
00848       msg[len++] = 3;
00849       if (active) {
00850          msg[len++] = 0x42;
00851          msg[len++] = 0x42;
00852          msg[len++] = 0x42;
00853       } else {
00854          msg[len++] = 0x6f;
00855          msg[len++] = 0x6f;
00856          msg[len++] = 0x6f;
00857       }
00858    }
00859    sum = 0;
00860    for (x = 0; x < len; x++)
00861       sum += msg[x];
00862    sum = (256 - (sum & 255));
00863    msg[len++] = sum;
00864    /* Wait a half a second */
00865    for (x = 0; x < 4000; x++)
00866       PUT_BYTE(0x7f);
00867    /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
00868    for (x = 0; x < 30; x++)
00869       PUT_CLID(0x55);
00870    /* Send 170ms of callerid marks */
00871    for (x = 0; x < 170; x++)
00872       PUT_CLID_MARKMS;
00873    for (x = 0; x < len; x++) {
00874       PUT_CLID(msg[x]);
00875    }
00876    /* Send 50 more ms of marks */
00877    for (x = 0; x < 50; x++)
00878       PUT_CLID_MARKMS;
00879    return bytes;
00880 }
00881 
00882 int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, int codec)
00883 {
00884    int bytes = 0;
00885    int x, sum;
00886    int len;
00887 
00888    /* Initial carriers (real/imaginary) */
00889    float cr = 1.0;
00890    float ci = 0.0;
00891    float scont = 0.0;
00892    char msg[256];
00893    len = callerid_genmsg(msg, sizeof(msg), number, name, flags);
00894    if (!callwaiting) {
00895       /* Wait a half a second */
00896       for (x = 0; x < 4000; x++)
00897          PUT_BYTE(0x7f);
00898       /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
00899       for (x = 0; x < 30; x++)
00900          PUT_CLID(0x55);
00901    }
00902    /* Send 150ms of callerid marks */
00903    for (x = 0; x < 150; x++)
00904       PUT_CLID_MARKMS;
00905    /* Send 0x80 indicating MDMF format */
00906    PUT_CLID(0x80);
00907    /* Put length of whole message */
00908    PUT_CLID(len);
00909    sum = 0x80 + strlen(msg);
00910    /* Put each character of message and update checksum */
00911    for (x = 0; x < len; x++) {
00912       PUT_CLID(msg[x]);
00913       sum += msg[x];
00914    }
00915    /* Send 2's compliment of sum */
00916    PUT_CLID(256 - (sum & 255));
00917 
00918    /* Send 50 more ms of marks */
00919    for (x = 0; x < 50; x++)
00920       PUT_CLID_MARKMS;
00921    
00922    return bytes;
00923 }
00924 
00925 /*! \brief Clean up phone string
00926  * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
00927  * Basically, remove anything that could be invalid in a pattern.
00928  */
00929 void ast_shrink_phone_number(char *n)
00930 {
00931    int x, y = 0;
00932    int bracketed = 0;
00933 
00934    for (x = 0; n[x]; x++) {
00935       switch (n[x]) {
00936       case '[':
00937          bracketed++;
00938          n[y++] = n[x];
00939          break;
00940       case ']':
00941          bracketed--;
00942          n[y++] = n[x];
00943          break;
00944       case '-':
00945          if (bracketed)
00946             n[y++] = n[x];
00947          break;
00948       case '.':
00949          if (!n[x+1])
00950             n[y++] = n[x];
00951          break;
00952       default:
00953          /* ignore parenthesis and whitespace */
00954          if (!strchr("( )", n[x]))
00955             n[y++] = n[x];
00956       }
00957    }
00958    n[y] = '\0';
00959 }
00960 
00961 /*! \brief Checks if phone number consists of valid characters 
00962    \param exten   String that needs to be checked
00963    \param valid   Valid characters in string
00964    \return 1 if valid string, 0 if string contains invalid characters
00965 */
00966 static int ast_is_valid_string(const char *exten, const char *valid)
00967 {
00968    int x;
00969 
00970    if (ast_strlen_zero(exten))
00971       return 0;
00972    for (x = 0; exten[x]; x++)
00973       if (!strchr(valid, exten[x]))
00974          return 0;
00975    return 1;
00976 }
00977 
00978 /*! \brief checks if string consists only of digits and * \# and + 
00979    \return 1 if string is valid AST phone number
00980    \return 0 if not
00981 */
00982 int ast_isphonenumber(const char *n)
00983 {
00984    return ast_is_valid_string(n, "0123456789*#+");
00985 }
00986 
00987 /*! \brief checks if string consists only of digits and ( ) - * \# and + 
00988    Pre-qualifies the string for ast_shrink_phone_number()
00989    \return 1 if string is valid AST shrinkable phone number
00990    \return 0 if not
00991 */
00992 int ast_is_shrinkable_phonenumber(const char *exten)
00993 {
00994    return ast_is_valid_string(exten, "0123456789*#+()-.");
00995 }
00996 
00997 /*!
00998  * \brief Destructively parse instr for caller id information 
00999  * \return always returns 0, as the code always returns something.
01000  * \note XXX 'name' is not parsed consistently e.g. we have
01001  * input                   location        name
01002  * " foo bar " <123>       123             ' foo bar ' (with spaces around)
01003  * " foo bar "             NULL            'foo bar' (without spaces around)
01004  * The parsing of leading and trailing space/quotes should be more consistent.
01005  */
01006 int ast_callerid_parse(char *instr, char **name, char **location)
01007 {
01008    char *ns, *ne, *ls, *le;
01009 
01010    /* Try "name" <location> format or name <location> format */
01011    if ((ls = strrchr(instr, '<')) && (le = strrchr(ls, '>'))) {
01012       *ls = *le = '\0'; /* location found, trim off the brackets */
01013       *location = ls + 1;  /* and this is the result */
01014       if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
01015          *ns = *ne = '\0'; /* trim off the quotes */
01016          *name = ns + 1;      /* and this is the name */
01017       } else if (ns) {
01018          /* An opening quote was found but no closing quote was. The closing
01019           * quote may actually be after the end of the bracketed number
01020           */
01021          if (strchr(le + 1, '\"')) {
01022             *ns = '\0';
01023             *name = ns + 1;
01024             ast_trim_blanks(*name);
01025          }
01026       } else { /* no quotes, trim off leading and trailing spaces */
01027          *name = ast_skip_blanks(instr);
01028          ast_trim_blanks(*name);
01029       }
01030    } else { /* no valid brackets */
01031       char tmp[256];
01032 
01033       ast_copy_string(tmp, instr, sizeof(tmp));
01034       ast_shrink_phone_number(tmp);
01035       if (ast_isphonenumber(tmp)) { /* Assume it's just a location */
01036          *name = NULL;
01037          strcpy(instr, tmp); /* safe, because tmp will always be the same size or smaller than instr */
01038          *location = instr;
01039       } else { /* Assume it's just a name. */
01040          *location = NULL;
01041          if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
01042             *ns = *ne = '\0'; /* trim off the quotes */
01043             *name = ns + 1;      /* and this is the name */
01044          } else { /* no quotes, trim off leading and trailing spaces */
01045             *name = ast_skip_blanks(instr);
01046             ast_trim_blanks(*name);
01047          }
01048       }
01049    }
01050    return 0;
01051 }
01052 
01053 static int __ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int callwaiting, int codec)
01054 {
01055    if (ast_strlen_zero(name))
01056       name = NULL;
01057    if (ast_strlen_zero(number))
01058       number = NULL;
01059    return callerid_generate(buf, number, name, 0, callwaiting, codec);
01060 }
01061 
01062 int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int codec)
01063 {
01064    return __ast_callerid_generate(buf, name, number, 0, codec);
01065 }
01066 
01067 int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, int codec)
01068 {
01069    return __ast_callerid_generate(buf, name, number, 1, codec);
01070 }
01071 
01072 char *ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
01073 {
01074    if (!unknown)
01075       unknown = "<unknown>";
01076    if (name && num)
01077       snprintf(buf, bufsiz, "\"%s\" <%s>", name, num);
01078    else if (name) 
01079       ast_copy_string(buf, name, bufsiz);
01080    else if (num)
01081       ast_copy_string(buf, num, bufsiz);
01082    else
01083       ast_copy_string(buf, unknown, bufsiz);
01084    return buf;
01085 }
01086 
01087 int ast_callerid_split(const char *buf, char *name, int namelen, char *num, int numlen)
01088 {
01089    char *tmp;
01090    char *l = NULL, *n = NULL;
01091 
01092    tmp = ast_strdupa(buf);
01093    ast_callerid_parse(tmp, &n, &l);
01094    if (n)
01095       ast_copy_string(name, n, namelen);
01096    else
01097       name[0] = '\0';
01098    if (l) {
01099       ast_shrink_phone_number(l);
01100       ast_copy_string(num, l, numlen);
01101    } else
01102       num[0] = '\0';
01103    return 0;
01104 }
01105 
01106 /*! \brief Translation table for Caller ID Presentation settings */
01107 static struct {
01108    int val;
01109    const char *name;
01110    const char *description;
01111 } pres_types[] = {
01112    {  AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened", "Presentation Allowed, Not Screened"},
01113    {  AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", "Presentation Allowed, Passed Screen"},
01114    {  AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", "Presentation Allowed, Failed Screen"},
01115    {  AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed", "Presentation Allowed, Network Number"},
01116    {  AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "prohib_not_screened", "Presentation Prohibited, Not Screened"},
01117    {  AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", "Presentation Prohibited, Passed Screen"},
01118    {  AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", "Presentation Prohibited, Failed Screen"},
01119    {  AST_PRES_PROHIB_NETWORK_NUMBER, "prohib", "Presentation Prohibited, Network Number"},
01120    {  AST_PRES_NUMBER_NOT_AVAILABLE, "unavailable", "Number Unavailable"},
01121 };
01122 
01123 /*! \brief Convert caller ID text code to value 
01124    used in config file parsing
01125    \param data text string
01126    \return value AST_PRES_ from callerid.h 
01127 */
01128 int ast_parse_caller_presentation(const char *data)
01129 {
01130    int i;
01131    if (!data) {
01132       return -1;
01133    }
01134 
01135    for (i = 0; i < ARRAY_LEN(pres_types); i++) {
01136       if (!strcasecmp(pres_types[i].name, data))
01137          return pres_types[i].val;
01138    }
01139 
01140    return -1;
01141 }
01142 
01143 /*! \brief Convert caller ID pres value to explanatory string 
01144    \param data value (see callerid.h AST_PRES_ ) 
01145    \return string for human presentation
01146 */
01147 const char *ast_describe_caller_presentation(int data)
01148 {
01149    int i;
01150 
01151    for (i = 0; i < ARRAY_LEN(pres_types); i++) {
01152       if (pres_types[i].val == data)
01153          return pres_types[i].description;
01154    }
01155 
01156    return "unknown";
01157 }
01158 
01159 /*! \brief Convert caller ID pres value to text code
01160    \param data text string
01161    \return string for config file
01162 */
01163 const char *ast_named_caller_presentation(int data)
01164 {
01165    int i;
01166 
01167    for (i = 0; i < ARRAY_LEN(pres_types); i++) {
01168       if (pres_types[i].val == data)
01169          return pres_types[i].name;
01170    }
01171 
01172    return "unknown";
01173 }

Generated on Wed Oct 28 11:50:55 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6