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

Generated on Thu Apr 16 06:27:16 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6