Mon Aug 31 12:30:02 2015

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

Generated on 31 Aug 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1