Fri Jul 24 00:40:44 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: 180197 $")
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 /*! \brief parse string for caller id information 
00998    \return always returns 0, as the code always returns something.
00999   XXX note that 'name' is not parsed consistently e.g. we have
01000 
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 
01132    for (i = 0; i < ARRAY_LEN(pres_types); i++) {
01133       if (!strcasecmp(pres_types[i].name, data))
01134          return pres_types[i].val;
01135    }
01136 
01137    return -1;
01138 }
01139 
01140 /*! \brief Convert caller ID pres value to explanatory string 
01141    \param data value (see callerid.h AST_PRES_ ) 
01142    \return string for human presentation
01143 */
01144 const char *ast_describe_caller_presentation(int data)
01145 {
01146    int i;
01147 
01148    for (i = 0; i < ARRAY_LEN(pres_types); i++) {
01149       if (pres_types[i].val == data)
01150          return pres_types[i].description;
01151    }
01152 
01153    return "unknown";
01154 }
01155 
01156 /*! \brief Convert caller ID pres value to text code
01157    \param data text string
01158    \return string for config file
01159 */
01160 const char *ast_named_caller_presentation(int data)
01161 {
01162    int i;
01163 
01164    for (i = 0; i < ARRAY_LEN(pres_types); i++) {
01165       if (pres_types[i].val == data)
01166          return pres_types[i].name;
01167    }
01168 
01169    return "unknown";
01170 }

Generated on Fri Jul 24 00:40:44 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7