Thu Jul 9 13:40:23 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: 180196 $")
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 tv = 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(&tv, &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 mdmf, int codec)
00795 {
00796    unsigned char msg[256];
00797    int len = 0;
00798    int sum;
00799    int x;
00800    int bytes = 0;
00801    float cr = 1.0;
00802    float ci = 0.0;
00803    float scont = 0.0;
00804 
00805    if (mdmf) {
00806       /* MDMF Message waiting */
00807       msg[len++] = 0x82;
00808       /* Length is 3 */
00809       msg[len++] = 3;
00810       /* IE is "Message Waiting Parameter" */
00811       msg[len++] = 0xb;
00812       /* Length of IE is one */
00813       msg[len++] = 1;
00814       /* Active or not */
00815       if (active)
00816          msg[len++] = 0xff;
00817       else
00818          msg[len++] = 0x00;
00819    } else {
00820       /* SDMF Message waiting */
00821       msg[len++] = 0x6;
00822       /* Length is 3 */
00823       msg[len++] = 3;
00824       if (active) {
00825          msg[len++] = 0x42;
00826          msg[len++] = 0x42;
00827          msg[len++] = 0x42;
00828       } else {
00829          msg[len++] = 0x6f;
00830          msg[len++] = 0x6f;
00831          msg[len++] = 0x6f;
00832       }
00833    }
00834    sum = 0;
00835    for (x = 0; x < len; x++)
00836       sum += msg[x];
00837    sum = (256 - (sum & 255));
00838    msg[len++] = sum;
00839    /* Wait a half a second */
00840    for (x = 0; x < 4000; x++)
00841       PUT_BYTE(0x7f);
00842    /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
00843    for (x = 0; x < 30; x++)
00844       PUT_CLID(0x55);
00845    /* Send 170ms of callerid marks */
00846    for (x = 0; x < 170; x++)
00847       PUT_CLID_MARKMS;
00848    for (x = 0; x < len; x++) {
00849       PUT_CLID(msg[x]);
00850    }
00851    /* Send 50 more ms of marks */
00852    for (x = 0; x < 50; x++)
00853       PUT_CLID_MARKMS;
00854    return bytes;
00855 }
00856 
00857 int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, int codec)
00858 {
00859    int bytes = 0;
00860    int x, sum;
00861    int len;
00862 
00863    /* Initial carriers (real/imaginary) */
00864    float cr = 1.0;
00865    float ci = 0.0;
00866    float scont = 0.0;
00867    char msg[256];
00868    len = callerid_genmsg(msg, sizeof(msg), number, name, flags);
00869    if (!callwaiting) {
00870       /* Wait a half a second */
00871       for (x = 0; x < 4000; x++)
00872          PUT_BYTE(0x7f);
00873       /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
00874       for (x = 0; x < 30; x++)
00875          PUT_CLID(0x55);
00876    }
00877    /* Send 150ms of callerid marks */
00878    for (x = 0; x < 150; x++)
00879       PUT_CLID_MARKMS;
00880    /* Send 0x80 indicating MDMF format */
00881    PUT_CLID(0x80);
00882    /* Put length of whole message */
00883    PUT_CLID(len);
00884    sum = 0x80 + strlen(msg);
00885    /* Put each character of message and update checksum */
00886    for (x = 0; x < len; x++) {
00887       PUT_CLID(msg[x]);
00888       sum += msg[x];
00889    }
00890    /* Send 2's compliment of sum */
00891    PUT_CLID(256 - (sum & 255));
00892 
00893    /* Send 50 more ms of marks */
00894    for (x = 0; x < 50; x++)
00895       PUT_CLID_MARKMS;
00896    
00897    return bytes;
00898 }
00899 
00900 /*! \brief Clean up phone string
00901  * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
00902  * Basically, remove anything that could be invalid in a pattern.
00903  */
00904 void ast_shrink_phone_number(char *n)
00905 {
00906    int x, y = 0;
00907    int bracketed = 0;
00908 
00909    for (x = 0; n[x]; x++) {
00910       switch (n[x]) {
00911       case '[':
00912          bracketed++;
00913          n[y++] = n[x];
00914          break;
00915       case ']':
00916          bracketed--;
00917          n[y++] = n[x];
00918          break;
00919       case '-':
00920          if (bracketed)
00921             n[y++] = n[x];
00922          break;
00923       case '.':
00924          if (!n[x+1])
00925             n[y++] = n[x];
00926          break;
00927       default:
00928          /* ignore parenthesis and whitespace */
00929          if (!strchr("( )", n[x]))
00930             n[y++] = n[x];
00931       }
00932    }
00933    n[y] = '\0';
00934 }
00935 
00936 /*! \brief Checks if phone number consists of valid characters 
00937    \param exten   String that needs to be checked
00938    \param valid   Valid characters in string
00939    \return 1 if valid string, 0 if string contains invalid characters
00940 */
00941 static int ast_is_valid_string(const char *exten, const char *valid)
00942 {
00943    int x;
00944 
00945    if (ast_strlen_zero(exten))
00946       return 0;
00947    for (x = 0; exten[x]; x++)
00948       if (!strchr(valid, exten[x]))
00949          return 0;
00950    return 1;
00951 }
00952 
00953 /*! \brief checks if string consists only of digits and * \# and + 
00954    \return 1 if string is valid AST phone number
00955    \return 0 if not
00956 */
00957 int ast_isphonenumber(const char *n)
00958 {
00959    return ast_is_valid_string(n, "0123456789*#+");
00960 }
00961 
00962 /*! \brief checks if string consists only of digits and ( ) - * \# and + 
00963    Pre-qualifies the string for ast_shrink_phone_number()
00964    \return 1 if string is valid AST shrinkable phone number
00965    \return 0 if not
00966 */
00967 int ast_is_shrinkable_phonenumber(const char *exten)
00968 {
00969    return ast_is_valid_string(exten, "0123456789*#+()-.");
00970 }
00971 
00972 /*! \brief parse string for caller id information 
00973    \return always returns 0, as the code always returns something.
00974   XXX note that 'name' is not parsed consistently e.g. we have
00975 
00976    input       location name
00977    " foo bar " <123> 123      ' foo bar ' (with spaces around)
00978    " foo bar "    NULL     'foo bar' (without spaces around)
00979   The parsing of leading and trailing space/quotes should be more consistent.
00980 */
00981 int ast_callerid_parse(char *instr, char **name, char **location)
00982 {
00983    char *ns, *ne, *ls, *le;
00984 
00985    /* Try "name" <location> format or name <location> format */
00986    if ((ls = strrchr(instr, '<')) && (le = strrchr(ls, '>'))) {
00987       *ls = *le = '\0'; /* location found, trim off the brackets */
00988       *location = ls + 1;  /* and this is the result */
00989       if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
00990          *ns = *ne = '\0'; /* trim off the quotes */
00991          *name = ns + 1;      /* and this is the name */
00992       } else if (ns) {
00993          /* An opening quote was found but no closing quote was. The closing
00994           * quote may actually be after the end of the bracketed number
00995           */
00996          if (strchr(le + 1, '\"')) {
00997             *ns = '\0';
00998             *name = ns + 1;
00999             ast_trim_blanks(*name);
01000          }
01001       } else { /* no quotes, trim off leading and trailing spaces */
01002          *name = ast_skip_blanks(instr);
01003          ast_trim_blanks(*name);
01004       }
01005    } else { /* no valid brackets */
01006       char tmp[256];
01007 
01008       ast_copy_string(tmp, instr, sizeof(tmp));
01009       ast_shrink_phone_number(tmp);
01010       if (ast_isphonenumber(tmp)) { /* Assume it's just a location */
01011          *name = NULL;
01012          strcpy(instr, tmp); /* safe, because tmp will always be the same size or smaller than instr */
01013          *location = instr;
01014       } else { /* Assume it's just a name. */
01015          *location = NULL;
01016          if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
01017             *ns = *ne = '\0'; /* trim off the quotes */
01018             *name = ns + 1;      /* and this is the name */
01019          } else { /* no quotes, trim off leading and trailing spaces */
01020             *name = ast_skip_blanks(instr);
01021             ast_trim_blanks(*name);
01022          }
01023       }
01024    }
01025    return 0;
01026 }
01027 
01028 static int __ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int callwaiting, int codec)
01029 {
01030    if (ast_strlen_zero(name))
01031       name = NULL;
01032    if (ast_strlen_zero(number))
01033       number = NULL;
01034    return callerid_generate(buf, number, name, 0, callwaiting, codec);
01035 }
01036 
01037 int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int codec)
01038 {
01039    return __ast_callerid_generate(buf, name, number, 0, codec);
01040 }
01041 
01042 int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, int codec)
01043 {
01044    return __ast_callerid_generate(buf, name, number, 1, codec);
01045 }
01046 
01047 char *ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
01048 {
01049    if (!unknown)
01050       unknown = "<unknown>";
01051    if (name && num)
01052       snprintf(buf, bufsiz, "\"%s\" <%s>", name, num);
01053    else if (name) 
01054       ast_copy_string(buf, name, bufsiz);
01055    else if (num)
01056       ast_copy_string(buf, num, bufsiz);
01057    else
01058       ast_copy_string(buf, unknown, bufsiz);
01059    return buf;
01060 }
01061 
01062 int ast_callerid_split(const char *buf, char *name, int namelen, char *num, int numlen)
01063 {
01064    char *tmp;
01065    char *l = NULL, *n = NULL;
01066 
01067    tmp = ast_strdupa(buf);
01068    ast_callerid_parse(tmp, &n, &l);
01069    if (n)
01070       ast_copy_string(name, n, namelen);
01071    else
01072       name[0] = '\0';
01073    if (l) {
01074       ast_shrink_phone_number(l);
01075       ast_copy_string(num, l, numlen);
01076    } else
01077       num[0] = '\0';
01078    return 0;
01079 }
01080 
01081 /*! \brief Translation table for Caller ID Presentation settings */
01082 static struct {
01083    int val;
01084    const char *name;
01085    const char *description;
01086 } pres_types[] = {
01087    {  AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened", "Presentation Allowed, Not Screened"},
01088    {  AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", "Presentation Allowed, Passed Screen"},
01089    {  AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", "Presentation Allowed, Failed Screen"},
01090    {  AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed", "Presentation Allowed, Network Number"},
01091    {  AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "prohib_not_screened", "Presentation Prohibited, Not Screened"},
01092    {  AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", "Presentation Prohibited, Passed Screen"},
01093    {  AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", "Presentation Prohibited, Failed Screen"},
01094    {  AST_PRES_PROHIB_NETWORK_NUMBER, "prohib", "Presentation Prohibited, Network Number"},
01095    {  AST_PRES_NUMBER_NOT_AVAILABLE, "unavailable", "Number Unavailable"},
01096 };
01097 
01098 /*! \brief Convert caller ID text code to value 
01099    used in config file parsing
01100    \param data text string
01101    \return value AST_PRES_ from callerid.h 
01102 */
01103 int ast_parse_caller_presentation(const char *data)
01104 {
01105    int i;
01106 
01107    for (i = 0; i < ARRAY_LEN(pres_types); i++) {
01108       if (!strcasecmp(pres_types[i].name, data))
01109          return pres_types[i].val;
01110    }
01111 
01112    return -1;
01113 }
01114 
01115 /*! \brief Convert caller ID pres value to explanatory string 
01116    \param data value (see callerid.h AST_PRES_ ) 
01117    \return string for human presentation
01118 */
01119 const char *ast_describe_caller_presentation(int data)
01120 {
01121    int i;
01122 
01123    for (i = 0; i < ARRAY_LEN(pres_types); i++) {
01124       if (pres_types[i].val == data)
01125          return pres_types[i].description;
01126    }
01127 
01128    return "unknown";
01129 }
01130 
01131 /*! \brief Convert caller ID pres value to text code
01132    \param data text string
01133    \return string for config file
01134 */
01135 const char *ast_named_caller_presentation(int data)
01136 {
01137    int i;
01138 
01139    for (i = 0; i < ARRAY_LEN(pres_types); i++) {
01140       if (pres_types[i].val == data)
01141          return pres_types[i].name;
01142    }
01143 
01144    return "unknown";
01145 }

Generated on Thu Jul 9 13:40:23 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7