git migration: Refactor the ASTERISK_FILE_VERSION macro
[asterisk/asterisk.git] / main / callerid.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief CallerID Generation support
22  *
23  * \author Mark Spencer <markster@digium.com>
24  */
25
26 /*** MODULEINFO
27         <support_level>core</support_level>
28  ***/
29
30 #include "asterisk.h"
31
32 ASTERISK_REGISTER_FILE()
33
34 #include <time.h>
35 #include <math.h>
36 #include <ctype.h>
37
38 #include "asterisk/ulaw.h"
39 #include "asterisk/alaw.h"
40 #include "asterisk/frame.h"
41 #include "asterisk/channel.h"
42 #include "asterisk/callerid.h"
43 #include "asterisk/fskmodem.h"
44 #include "asterisk/utils.h"
45 #include "asterisk/format_cache.h"
46
47 struct callerid_state {
48         fsk_data fskd;
49         char rawdata[256];
50         short oldstuff[160];
51         int oldlen;
52         int pos;
53         int type;
54         int cksum;
55         char name[64];
56         char number[64];
57         int flags;
58         int sawflag;
59         int len;
60
61         int skipflag;
62         unsigned short crc;
63 };
64
65
66 float cid_dr[4], cid_di[4];
67 float clidsb = 8000.0 / 1200.0;
68 float sasdr, sasdi;
69 float casdr1, casdi1, casdr2, casdi2;
70
71 #define CALLERID_SPACE  2200.0          /*!< 2200 hz for "0" */
72 #define CALLERID_MARK   1200.0          /*!< 1200 hz for "1" */
73 #define SAS_FREQ                 440.0
74 #define CAS_FREQ1               2130.0
75 #define CAS_FREQ2               2750.0
76
77 #define AST_CALLERID_UNKNOWN    "<unknown>"
78
79 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)
80 {
81         int x;
82         float t;
83         for (x = 0; x < len; x++) {
84                 t = *cr1 * ddr1 - *ci1 * ddi1;
85                 *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
86                 *cr1 = t;
87                 t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
88                 *cr1 *= t;
89                 *ci1 *= t;
90
91                 t = *cr2 * ddr2 - *ci2 * ddi2;
92                 *ci2 = *cr2 * ddi2 + *ci2 * ddr2;
93                 *cr2 = t;
94                 t = 2.0 - (*cr2 * *cr2 + *ci2 * *ci2);
95                 *cr2 *= t;
96                 *ci2 *= t;
97                 buf[x] = AST_LIN2X((*cr1 + *cr2) * 2048.0);
98         }
99 }
100
101 static inline void gen_tone(unsigned char *buf, int len, struct ast_format *codec, float ddr1, float ddi1, float *cr1, float *ci1)
102 {
103         int x;
104         float t;
105         for (x = 0; x < len; x++) {
106                 t = *cr1 * ddr1 - *ci1 * ddi1;
107                 *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
108                 *cr1 = t;
109                 t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
110                 *cr1 *= t;
111                 *ci1 *= t;
112                 buf[x] = AST_LIN2X(*cr1 * 8192.0);
113         }
114 }
115
116 /*! \brief Initialize stuff for inverse FFT */
117 void callerid_init(void)
118 {
119         cid_dr[0] = cos(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
120         cid_di[0] = sin(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
121         cid_dr[1] = cos(CALLERID_MARK * 2.0 * M_PI / 8000.0);
122         cid_di[1] = sin(CALLERID_MARK * 2.0 * M_PI / 8000.0);
123         sasdr = cos(SAS_FREQ * 2.0 * M_PI / 8000.0);
124         sasdi = sin(SAS_FREQ * 2.0 * M_PI / 8000.0);
125         casdr1 = cos(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
126         casdi1 = sin(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
127         casdr2 = cos(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
128         casdi2 = sin(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
129 }
130
131 struct callerid_state *callerid_new(int cid_signalling)
132 {
133         struct callerid_state *cid;
134
135         if ((cid = ast_calloc(1, sizeof(*cid)))) {
136 #ifdef INTEGER_CALLERID
137                 cid->fskd.ispb = 7;             /* 1200 baud */
138                 /* Set up for 1200 / 8000 freq *32 to allow ints */
139                 cid->fskd.pllispb  = (int)(8000 * 32  / 1200);
140                 cid->fskd.pllids   = cid->fskd.pllispb/32;
141                 cid->fskd.pllispb2 = cid->fskd.pllispb/2;
142
143                 cid->fskd.icont = 0;           /* PLL REset */
144                 /* cid->fskd.hdlc = 0; */       /* Async */
145                 cid->fskd.nbit = 8;             /* 8 bits */
146                 cid->fskd.instop = 1;           /* 1 stop bit */
147                 /* cid->fskd.paridad = 0; */    /* No parity */
148                 cid->fskd.bw = 1;               /* Filter 800 Hz */
149                 if (cid_signalling == 2) {      /* v23 signalling */
150                         cid->fskd.f_mark_idx  = 4;      /* 1300 Hz */
151                         cid->fskd.f_space_idx = 5;      /* 2100 Hz */
152                 } else {                        /* Bell 202 signalling as default */
153                         cid->fskd.f_mark_idx  = 2;      /* 1200 Hz */
154                         cid->fskd.f_space_idx = 3;      /* 2200 Hz */
155                 }
156                 /* cid->fskd.pcola = 0; */      /* No clue */
157                 /* cid->fskd.cont = 0.0; */     /* Digital PLL reset */
158                 /* cid->fskd.x0 = 0.0; */
159                 /* cid->fskd.state = 0; */
160                 cid->flags = CID_UNKNOWN_NAME | CID_UNKNOWN_NUMBER;
161                 /* cid->pos = 0; */
162
163                 fskmodem_init(&cid->fskd);
164 #else
165                 cid->fskd.spb = 7.0;            /* 1200 baud */
166                 /* cid->fskd.hdlc = 0; */       /* Async */
167                 cid->fskd.nbit = 8;             /* 8 bits */
168                 cid->fskd.nstop = 1.0;          /* 1 stop bit */
169                 /* cid->fskd.paridad = 0; */    /* No parity */
170                 cid->fskd.bw = 1;               /* Filter 800 Hz */
171                 if (cid_signalling == 2) {      /* v23 signalling */
172                         cid->fskd.f_mark_idx =  4;      /* 1300 Hz */
173                         cid->fskd.f_space_idx = 5;      /* 2100 Hz */
174                 } else {                        /* Bell 202 signalling as default */
175                         cid->fskd.f_mark_idx =  2;      /* 1200 Hz */
176                         cid->fskd.f_space_idx = 3;      /* 2200 Hz */
177                 }
178                 /* cid->fskd.pcola = 0; */      /* No clue */
179                 /* cid->fskd.cont = 0.0; */     /* Digital PLL reset */
180                 /* cid->fskd.x0 = 0.0; */
181                 /* cid->fskd.state = 0; */
182                 cid->flags = CID_UNKNOWN_NAME | CID_UNKNOWN_NUMBER;
183                 /* cid->pos = 0; */
184 #endif
185         }
186
187         return cid;
188 }
189
190 void callerid_get(struct callerid_state *cid, char **name, char **number, int *flags)
191 {
192         *flags = cid->flags;
193         if (cid->flags & (CID_UNKNOWN_NAME | CID_PRIVATE_NAME))
194                 *name = NULL;
195         else
196                 *name = cid->name;
197         if (cid->flags & (CID_UNKNOWN_NUMBER | CID_PRIVATE_NUMBER))
198                 *number = NULL;
199         else
200                 *number = cid->number;
201 }
202
203 void callerid_get_dtmf(char *cidstring, char *number, int *flags)
204 {
205         int i;
206         int code;
207
208         /* "Clear" the number-buffer. */
209         number[0] = 0;
210
211         if (strlen(cidstring) < 2) {
212                 ast_debug(1, "No cid detected\n");
213                 *flags = CID_UNKNOWN_NUMBER;
214                 return;
215         }
216
217         /* Detect protocol and special types */
218         if (cidstring[0] == 'B') {
219                 /* Handle special codes */
220                 code = atoi(&cidstring[1]);
221                 if (code == 0)
222                         *flags = CID_UNKNOWN_NUMBER;
223                 else if (code == 10)
224                         *flags = CID_PRIVATE_NUMBER;
225                 else
226                         ast_debug(1, "Unknown DTMF code %d\n", code);
227         } else if (cidstring[0] == 'D' && cidstring[2] == '#') {
228                 /* .DK special code */
229                 if (cidstring[1] == '1')
230                         *flags = CID_PRIVATE_NUMBER;
231                 if (cidstring[1] == '2' || cidstring[1] == '3')
232                         *flags = CID_UNKNOWN_NUMBER;
233         } else if (cidstring[0] == 'D' || cidstring[0] == 'A') {
234                 /* "Standard" callerid */
235                 for (i = 1; i < strlen(cidstring); i++) {
236                         if (cidstring[i] == 'C' || cidstring[i] == '#')
237                                 break;
238                         if (isdigit(cidstring[i]))
239                                 number[i-1] = cidstring[i];
240                         else
241                                 ast_debug(1, "Unknown CID digit '%c'\n",
242                                         cidstring[i]);
243                 }
244                 number[i-1] = 0;
245         } else if (isdigit(cidstring[0])) {
246                 /* It begins with a digit, so we parse it as a number and hope
247                  * for the best */
248                 ast_log(LOG_WARNING, "Couldn't detect start-character. CID "
249                         "parsing might be unreliable\n");
250                 for (i = 0; i < strlen(cidstring); i++) {
251                         if (isdigit(cidstring[i]))
252                                 number[i] = cidstring[i];
253                         else
254                                 break;
255                 }
256                 number[i] = 0;
257         } else {
258                 ast_debug(1, "Unknown CID protocol, start digit '%c'\n", cidstring[0]);
259                 *flags = CID_UNKNOWN_NUMBER;
260         }
261 }
262
263 int ast_gen_cas(unsigned char *outbuf, int sendsas, int len, struct ast_format *codec)
264 {
265         int pos = 0;
266         int saslen = 2400;
267         float cr1 = 1.0;
268         float ci1 = 0.0;
269         float cr2 = 1.0;
270         float ci2 = 0.0;
271
272         if (sendsas) {
273                 if (len < saslen)
274                         return -1;
275                 gen_tone(outbuf, saslen, codec, sasdr, sasdi, &cr1, &ci1);
276                 len -= saslen;
277                 pos += saslen;
278                 cr2 = cr1;
279                 ci2 = ci1;
280         }
281         gen_tones(outbuf + pos, len, codec, casdr1, casdi1, casdr2, casdi2, &cr1, &ci1, &cr2, &ci2);
282         return 0;
283 }
284
285 static unsigned short calc_crc(unsigned short crc, unsigned char data)
286 {
287         unsigned int i, j, org, dst;
288         org = data;
289         dst = 0;
290
291         for (i = 0; i < CHAR_BIT; i++) {
292                 org <<= 1;
293                 dst >>= 1;
294                 if (org & 0x100)
295                         dst |= 0x80;
296         }
297         data = (unsigned char) dst;
298         crc ^= (unsigned int) data << (16 - CHAR_BIT);
299         for (j = 0; j < CHAR_BIT; j++) {
300                 if (crc & 0x8000U)
301                         crc = (crc << 1) ^ 0x1021U ;
302                 else
303                         crc <<= 1 ;
304         }
305         return crc;
306 }
307
308 int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int len, struct ast_format *codec)
309 {
310         int mylen = len;
311         int olen;
312         int b = 'X';
313         int b2;
314         int res;
315         int x;
316         short *buf;
317
318         buf = ast_alloca(2 * len + cid->oldlen);
319
320         memcpy(buf, cid->oldstuff, cid->oldlen);
321         mylen += cid->oldlen / 2;
322
323         for (x = 0; x < len; x++)
324                 buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
325
326         while (mylen >= 160) {
327                 b = b2 = 0;
328                 olen = mylen;
329                 res = fsk_serial(&cid->fskd, buf, &mylen, &b);
330
331                 if (mylen < 0) {
332                         ast_log(LOG_ERROR, "No start bit found in fsk data.\n");
333                         return -1;
334                 }
335
336                 buf += (olen - mylen);
337
338                 if (res < 0) {
339                         ast_log(LOG_NOTICE, "fsk_serial failed\n");
340                         return -1;
341                 }
342
343                 if (res == 1) {
344                         b2 = b;
345                         b  &= 0x7f;
346
347                         /* crc checksum calculation */
348                         if (cid->sawflag > 1)
349                                 cid->crc = calc_crc(cid->crc, (unsigned char) b2);
350
351                         /* Ignore invalid bytes */
352                         if (b > 0xff)
353                                 continue;
354
355                         /* skip DLE if needed */
356                         if (cid->sawflag > 0) {
357                                 if (cid->sawflag != 5 && cid->skipflag == 0 && b == 0x10) {
358                                         cid->skipflag = 1 ;
359                                         continue ;
360                                 }
361                         }
362                         if (cid->skipflag == 1)
363                                 cid->skipflag = 0 ;
364
365                         /* caller id retrieval */
366                         switch (cid->sawflag) {
367                         case 0: /* DLE */
368                                 if (b == 0x10) {
369                                         cid->sawflag = 1;
370                                         cid->skipflag = 0;
371                                         cid->crc = 0;
372                                 }
373                                 break;
374                         case 1: /* SOH */
375                                 if (b == 0x01)
376                                         cid->sawflag = 2;
377                                 break ;
378                         case 2: /* HEADER */
379                                 if (b == 0x07)
380                                         cid->sawflag = 3;
381                                 break;
382                         case 3: /* STX */
383                                 if (b == 0x02)
384                                         cid->sawflag = 4;
385                                 break;
386                         case 4: /* SERVICE TYPE */
387                                 if (b == 0x40)
388                                         cid->sawflag = 5;
389                                 break;
390                         case 5: /* Frame Length */
391                                 cid->sawflag = 6;
392                                 break;
393                         case 6: /* NUMBER TYPE */
394                                 cid->sawflag = 7;
395                                 cid->pos = 0;
396                                 cid->rawdata[cid->pos++] = b;
397                                 break;
398                         case 7: /* NUMBER LENGTH */
399                                 cid->sawflag = 8;
400                                 cid->len = b;
401                                 if ((cid->len+2) >= sizeof(cid->rawdata)) {
402                                         ast_log(LOG_WARNING, "too long caller id string\n") ;
403                                         return -1;
404                                 }
405                                 cid->rawdata[cid->pos++] = b;
406                                 break;
407                         case 8: /* Retrieve message */
408                                 cid->rawdata[cid->pos++] = b;
409                                 cid->len--;
410                                 if (cid->len<=0) {
411                                         cid->rawdata[cid->pos] = '\0';
412                                         cid->sawflag = 9;
413                                 }
414                                 break;
415                         case 9: /* ETX */
416                                 cid->sawflag = 10;
417                                 break;
418                         case 10: /* CRC Checksum 1 */
419                                 cid->sawflag = 11;
420                                 break;
421                         case 11: /* CRC Checksum 2 */
422                                 cid->sawflag = 12;
423                                 if (cid->crc != 0) {
424                                         ast_log(LOG_WARNING, "crc checksum error\n") ;
425                                         return -1;
426                                 }
427                                 /* extract caller id data */
428                                 for (x = 0; x < cid->pos;) {
429                                         switch (cid->rawdata[x++]) {
430                                         case 0x02: /* caller id  number */
431                                                 cid->number[0] = '\0';
432                                                 cid->name[0] = '\0';
433                                                 cid->flags = 0;
434                                                 res = cid->rawdata[x++];
435                                                 ast_copy_string(cid->number, &cid->rawdata[x], res+1);
436                                                 x += res;
437                                                 break;
438                                         case 0x21: /* additional information */
439                                                 /* length */
440                                                 x++;
441                                                 /* number type */
442                                                 switch (cid->rawdata[x]) {
443                                                 case 0x00: /* unknown */
444                                                 case 0x01: /* international number */
445                                                 case 0x02: /* domestic number */
446                                                 case 0x03: /* network */
447                                                 case 0x04: /* local call */
448                                                 case 0x06: /* short dial number */
449                                                 case 0x07: /* reserved */
450                                                 default:   /* reserved */
451                                                         ast_debug(2, "cid info:#1=%X\n", (unsigned)cid->rawdata[x]);
452                                                         break ;
453                                                 }
454                                                 x++;
455                                                 /* numbering plan octed 4 */
456                                                 x++;
457                                                 /* numbering plan octed 5 */
458                                                 switch (cid->rawdata[x]) {
459                                                 case 0x00: /* unknown */
460                                                 case 0x01: /* recommendation E.164 ISDN */
461                                                 case 0x03: /* recommendation X.121 */
462                                                 case 0x04: /* telex dial plan */
463                                                 case 0x08: /* domestic dial plan */
464                                                 case 0x09: /* private dial plan */
465                                                 case 0x05: /* reserved */
466                                                 default:   /* reserved */
467                                                         ast_debug(2, "cid info:#2=%X\n", (unsigned)cid->rawdata[x]);
468                                                         break ;
469                                                 }
470                                                 x++;
471                                                 break ;
472                                         case 0x04: /* no callerid reason */
473                                                 /* length */
474                                                 x++;
475                                                 /* no callerid reason code */
476                                                 switch (cid->rawdata[x]) {
477                                                 case 'P': /* caller id denied by user */
478                                                 case 'O': /* service not available */
479                                                 case 'C': /* pay phone */
480                                                 case 'S': /* service congested */
481                                                         cid->flags |= CID_UNKNOWN_NUMBER;
482                                                         ast_debug(2, "no cid reason:%c\n", cid->rawdata[x]);
483                                                         break ;
484                                                 }
485                                                 x++;
486                                                 break ;
487                                         case 0x09: /* dialed number */
488                                                 /* length */
489                                                 res = cid->rawdata[x++];
490                                                 /* dialed number */
491                                                 x += res;
492                                                 break ;
493                                         case 0x22: /* dialed number additional information */
494                                                 /* length */
495                                                 x++;
496                                                 /* number type */
497                                                 switch (cid->rawdata[x]) {
498                                                 case 0x00: /* unknown */
499                                                 case 0x01: /* international number */
500                                                 case 0x02: /* domestic number */
501                                                 case 0x03: /* network */
502                                                 case 0x04: /* local call */
503                                                 case 0x06: /* short dial number */
504                                                 case 0x07: /* reserved */
505                                                 default:   /* reserved */
506                                                         if (option_debug > 1)
507                                                                 ast_log(LOG_NOTICE, "did info:#1=%X\n", (unsigned)cid->rawdata[x]);
508                                                         break ;
509                                                 }
510                                                 x++;
511                                                 /* numbering plan octed 4 */
512                                                 x++;
513                                                 /* numbering plan octed 5 */
514                                                 switch (cid->rawdata[x]) {
515                                                 case 0x00: /* unknown */
516                                                 case 0x01: /* recommendation E.164 ISDN */
517                                                 case 0x03: /* recommendation X.121 */
518                                                 case 0x04: /* telex dial plan */
519                                                 case 0x08: /* domestic dial plan */
520                                                 case 0x09: /* private dial plan */
521                                                 case 0x05: /* reserved */
522                                                 default:   /* reserved */
523                                                         ast_debug(2, "did info:#2=%X\n", (unsigned)cid->rawdata[x]);
524                                                         break ;
525                                                 }
526                                                 x++;
527                                                 break ;
528                                         }
529                                 }
530                                 return 1;
531                                 break;
532                         default:
533                                 ast_log(LOG_ERROR, "invalid value in sawflag %d\n", cid->sawflag);
534                         }
535                 }
536         }
537         if (mylen) {
538                 memcpy(cid->oldstuff, buf, mylen * 2);
539                 cid->oldlen = mylen * 2;
540         } else
541                 cid->oldlen = 0;
542
543         return 0;
544 }
545
546
547 int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, struct ast_format *codec)
548 {
549         int mylen = len;
550         int olen;
551         int b = 'X';
552         int res;
553         int x;
554         short *buf;
555
556         buf = ast_alloca(2 * len + cid->oldlen);
557
558         memcpy(buf, cid->oldstuff, cid->oldlen);
559         mylen += cid->oldlen/2;
560
561         for (x = 0; x < len; x++)
562                 buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
563         while (mylen >= 160) {
564                 olen = mylen;
565                 res = fsk_serial(&cid->fskd, buf, &mylen, &b);
566                 if (mylen < 0) {
567                         ast_log(LOG_ERROR, "No start bit found in fsk data.\n");
568                         return -1;
569                 }
570                 buf += (olen - mylen);
571                 if (res < 0) {
572                         ast_log(LOG_NOTICE, "fsk_serial failed\n");
573                         return -1;
574                 }
575                 if (res == 1) {
576                         if (b > 0xff) {
577                                 if (cid->sawflag != 5) {
578                                         /* Ignore invalid bytes */
579                                         continue;
580                                 }
581                                 /*
582                                  * We can tollerate an error on the checksum character since the
583                                  * checksum character is the last character in the message and
584                                  * it validates the message.
585                                  *
586                                  * Remove character error flags.
587                                  * Bit 8 : Parity error
588                                  * Bit 9 : Framing error
589                                  */
590                                 b &= 0xff;
591                         }
592                         switch (cid->sawflag) {
593                         case 0: /* Look for flag */
594                                 if (b == 'U')
595                                         cid->sawflag = 2;
596                                 break;
597                         case 2: /* Get lead-in */
598                                 if ((b == 0x04) || (b == 0x80) || (b == 0x06) || (b == 0x82)) {
599                                         cid->type = b;
600                                         cid->sawflag = 3;
601                                         cid->cksum = b;
602                                 }
603                                 break;
604                         case 3: /* Get length */
605                                 /* Not a lead in.  We're ready  */
606                                 cid->sawflag = 4;
607                                 cid->len = b;
608                                 cid->pos = 0;
609                                 cid->cksum += b;
610                                 break;
611                         case 4: /* Retrieve message */
612                                 if (cid->pos >= 128) {
613                                         ast_log(LOG_WARNING, "Caller ID too long???\n");
614                                         return -1;
615                                 }
616                                 cid->rawdata[cid->pos++] = b;
617                                 cid->len--;
618                                 cid->cksum += b;
619                                 if (!cid->len) {
620                                         cid->rawdata[cid->pos] = '\0';
621                                         cid->sawflag = 5;
622                                 }
623                                 break;
624                         case 5: /* Check checksum */
625                                 if ((b + cid->cksum) & 0xff) {
626                                         ast_log(LOG_NOTICE, "Caller*ID failed checksum\n");
627                                         /* Try again */
628                                         cid->sawflag = 0;
629                                         break;
630                                 }
631
632                                 cid->number[0] = '\0';
633                                 cid->name[0] = '\0';
634                                 /* Update flags */
635                                 cid->flags = 0;
636                                 /* If we get this far we're fine.  */
637                                 if ((cid->type == 0x80) || (cid->type == 0x82)) {
638                                         /* MDMF */
639                                         /* Go through each element and process */
640                                         for (x = 0; x < cid->pos;) {
641                                                 switch (cid->rawdata[x++]) {
642                                                 case 1:
643                                                         /* Date */
644                                                         break;
645                                                 case 2: /* Number */
646                                                 case 3: /* Number (for Zebble) */
647                                                 case 4: /* Number */
648                                                         res = cid->rawdata[x];
649                                                         if (res > 32) {
650                                                                 ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]);
651                                                                 res = 32;
652                                                         }
653                                                         if (ast_strlen_zero(cid->number)) {
654                                                                 memcpy(cid->number, cid->rawdata + x + 1, res);
655                                                                 /* Null terminate */
656                                                                 cid->number[res] = '\0';
657                                                         }
658                                                         break;
659                                                 case 6: /* Stentor Call Qualifier (ie. Long Distance call) */
660                                                         break;
661                                                 case 7: /* Name */
662                                                 case 8: /* Name */
663                                                         res = cid->rawdata[x];
664                                                         if (res > 32) {
665                                                                 ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]);
666                                                                 res = 32;
667                                                         }
668                                                         memcpy(cid->name, cid->rawdata + x + 1, res);
669                                                         cid->name[res] = '\0';
670                                                         break;
671                                                 case 11: /* Message Waiting */
672                                                         res = cid->rawdata[x + 1];
673                                                         if (res)
674                                                                 cid->flags |= CID_MSGWAITING;
675                                                         else
676                                                                 cid->flags |= CID_NOMSGWAITING;
677                                                         break;
678                                                 case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting  */
679                                                 case 19: /* UK: Network message system status (Number of messages waiting) */
680                                                 case 22: /* Something French */
681                                                         break;
682                                                 default:
683                                                         ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x - 1]);
684                                                 }
685                                                 res = cid->rawdata[x];
686                                                 if (0 > res){   /* Negative offset in the CID Spill */
687                                                         ast_log(LOG_NOTICE, "IE %d has bad field length of %d at offset %d\n", cid->rawdata[x-1], cid->rawdata[x], x);
688                                                         /* Try again */
689                                                         cid->sawflag = 0;
690                                                         break;  /* Exit the loop */
691                                                 }
692                                                 x += cid->rawdata[x];
693                                                 x++;
694                                         }
695                                 } else if (cid->type == 0x6) {
696                                         /* VMWI SDMF */
697                                         if (cid->rawdata[2] == 0x42) {
698                                                 cid->flags |= CID_MSGWAITING;
699                                         } else if (cid->rawdata[2] == 0x6f) {
700                                                 cid->flags |= CID_NOMSGWAITING;
701                                         }
702                                 } else {
703                                         /* SDMF */
704                                         ast_copy_string(cid->number, cid->rawdata + 8, sizeof(cid->number));
705                                 }
706                                 if (!strcmp(cid->number, "P")) {
707                                         strcpy(cid->number, "");
708                                         cid->flags |= CID_PRIVATE_NUMBER;
709                                 } else if (!strcmp(cid->number, "O") || ast_strlen_zero(cid->number)) {
710                                         strcpy(cid->number, "");
711                                         cid->flags |= CID_UNKNOWN_NUMBER;
712                                 }
713                                 if (!strcmp(cid->name, "P")) {
714                                         strcpy(cid->name, "");
715                                         cid->flags |= CID_PRIVATE_NAME;
716                                 } else if (!strcmp(cid->name, "O") || ast_strlen_zero(cid->name)) {
717                                         strcpy(cid->name, "");
718                                         cid->flags |= CID_UNKNOWN_NAME;
719                                 }
720                                 return 1;
721                                 break;
722                         default:
723                                 ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag);
724                         }
725                 }
726         }
727         if (mylen) {
728                 memcpy(cid->oldstuff, buf, mylen * 2);
729                 cid->oldlen = mylen * 2;
730         } else
731                 cid->oldlen = 0;
732
733         return 0;
734 }
735
736 void callerid_free(struct callerid_state *cid)
737 {
738         ast_free(cid);
739 }
740
741 static int callerid_genmsg(char *msg, int size, const char *number, const char *name, int flags)
742 {
743         struct timeval now = ast_tvnow();
744         struct ast_tm tm;
745         char *ptr;
746         int res;
747         int i, x;
748
749         /* Get the time */
750         ast_localtime(&now, &tm, NULL);
751
752         ptr = msg;
753
754         /* Format time and message header */
755         res = snprintf(ptr, size, "\001\010%02d%02d%02d%02d", tm.tm_mon + 1,
756                                 tm.tm_mday, tm.tm_hour, tm.tm_min);
757         size -= res;
758         ptr += res;
759         if (ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) {
760                 /* Indicate number not known */
761                 res = snprintf(ptr, size, "\004\001O");
762                 size -= res;
763                 ptr += res;
764         } else if (flags & CID_PRIVATE_NUMBER) {
765                 /* Indicate number is private */
766                 res = snprintf(ptr, size, "\004\001P");
767                 size -= res;
768                 ptr += res;
769         } else {
770                 /* Send up to 16 digits of number MAX */
771                 i = strlen(number);
772                 if (i > 16)
773                         i = 16;
774                 res = snprintf(ptr, size, "\002%c", i);
775                 size -= res;
776                 ptr += res;
777                 for (x = 0; x < i; x++)
778                         ptr[x] = number[x];
779                 ptr[i] = '\0';
780                 ptr += i;
781                 size -= i;
782         }
783
784         if (ast_strlen_zero(name) || (flags & CID_UNKNOWN_NAME)) {
785                 /* Indicate name not known */
786                 res = snprintf(ptr, size, "\010\001O");
787                 size -= res;
788                 ptr += res;
789         } else if (flags & CID_PRIVATE_NAME) {
790                 /* Indicate name is private */
791                 res = snprintf(ptr, size, "\010\001P");
792                 size -= res;
793                 ptr += res;
794         } else {
795                 /* Send up to 16 digits of name MAX */
796                 i = strlen(name);
797                 if (i > 16)
798                         i = 16;
799                 res = snprintf(ptr, size, "\007%c", i);
800                 size -= res;
801                 ptr += res;
802                 for (x = 0; x < i; x++)
803                         ptr[x] = name[x];
804                 ptr[i] = '\0';
805                 ptr += i;
806                 size -= i;
807         }
808         return (ptr - msg);
809
810 }
811
812 int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, struct ast_format *codec,
813                                const char* name, const char* number, int flags)
814 {
815         char msg[256];
816         int len = 0;
817         int sum;
818         int x;
819         int bytes = 0;
820         float cr = 1.0;
821         float ci = 0.0;
822         float scont = 0.0;
823
824         if (type == CID_MWI_TYPE_MDMF_FULL) {
825                 /* MDMF Message waiting with date, number, name and MWI parameter */
826                 msg[0] = 0x82;
827
828                 /* put date, number info at the right place */
829                 len = callerid_genmsg(msg+2, sizeof(msg)-2, number, name, flags);
830
831                 /* length of MDMF CLI plus Message Waiting Structure */
832                 msg[1] = len+3;
833
834                 /* Go to the position to write to */
835                 len = len+2;
836
837                 /* "Message Waiting Parameter" */
838                 msg[len++] = 0x0b;
839                 /* Length of IE is one */
840                 msg[len++] = 1;
841                 /* Active or not */
842                 if (active)
843                         msg[len++] = 0xff;
844                 else
845                         msg[len++] = 0x00;
846
847         } else if (type == CID_MWI_TYPE_MDMF) {
848                 /* MDMF Message waiting only */
849                 /* same as above except that the we only put MWI parameter */
850                 msg[len++] = 0x82;
851                 /* Length is 3 */
852                 msg[len++] = 3;
853                 /* IE is "Message Waiting Parameter" */
854                 msg[len++] = 0x0b;
855                 /* Length of IE is one */
856                 msg[len++] = 1;
857                 /* Active or not */
858                 if (active)
859                         msg[len++] = 0xff;
860                 else
861                         msg[len++] = 0x00;
862         } else {
863                 /* SDMF Message waiting */
864                 msg[len++] = 0x6;
865                 /* Length is 3 */
866                 msg[len++] = 3;
867                 if (active) {
868                         msg[len++] = 0x42;
869                         msg[len++] = 0x42;
870                         msg[len++] = 0x42;
871                 } else {
872                         msg[len++] = 0x6f;
873                         msg[len++] = 0x6f;
874                         msg[len++] = 0x6f;
875                 }
876         }
877         sum = 0;
878         for (x = 0; x < len; x++)
879                 sum += msg[x];
880         sum = (256 - (sum & 255));
881         msg[len++] = sum;
882         /* Wait a half a second */
883         for (x = 0; x < 4000; x++)
884                 PUT_BYTE(0x7f);
885         /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
886         for (x = 0; x < 30; x++)
887                 PUT_CLID(0x55);
888         /* Send 170ms of callerid marks */
889         for (x = 0; x < 170; x++)
890                 PUT_CLID_MARKMS;
891         for (x = 0; x < len; x++) {
892                 PUT_CLID(msg[x]);
893         }
894         /* Send 50 more ms of marks */
895         for (x = 0; x < 50; x++)
896                 PUT_CLID_MARKMS;
897         return bytes;
898 }
899
900 int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, struct ast_format *codec)
901 {
902         int bytes = 0;
903         int x, sum;
904         int len;
905
906         /* Initial carriers (real/imaginary) */
907         float cr = 1.0;
908         float ci = 0.0;
909         float scont = 0.0;
910         char msg[256];
911         len = callerid_genmsg(msg, sizeof(msg), number, name, flags);
912         if (!callwaiting) {
913                 /* Wait a half a second */
914                 for (x = 0; x < 4000; x++)
915                         PUT_BYTE(0x7f);
916                 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
917                 for (x = 0; x < 30; x++)
918                         PUT_CLID(0x55);
919         }
920         /* Send 150ms of callerid marks */
921         for (x = 0; x < 150; x++)
922                 PUT_CLID_MARKMS;
923         /* Send 0x80 indicating MDMF format */
924         PUT_CLID(0x80);
925         /* Put length of whole message */
926         PUT_CLID(len);
927         sum = 0x80 + strlen(msg);
928         /* Put each character of message and update checksum */
929         for (x = 0; x < len; x++) {
930                 PUT_CLID(msg[x]);
931                 sum += msg[x];
932         }
933         /* Send 2's compliment of sum */
934         PUT_CLID(256 - (sum & 255));
935
936         /* Send 50 more ms of marks */
937         for (x = 0; x < 50; x++)
938                 PUT_CLID_MARKMS;
939
940         return bytes;
941 }
942
943 /*!
944  * \brief Clean up phone string
945  * \details
946  * Remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
947  * Basically, remove anything that could be invalid in a pattern.
948  */
949 void ast_shrink_phone_number(char *n)
950 {
951         int x, y = 0;
952         int bracketed = 0;
953
954         for (x = 0; n[x]; x++) {
955                 switch (n[x]) {
956                 case '[':
957                         bracketed++;
958                         n[y++] = n[x];
959                         break;
960                 case ']':
961                         bracketed--;
962                         n[y++] = n[x];
963                         break;
964                 case '-':
965                         if (bracketed)
966                                 n[y++] = n[x];
967                         break;
968                 case '.':
969                         if (!n[x+1])
970                                 n[y++] = n[x];
971                         break;
972                 default:
973                         /* ignore parenthesis and whitespace */
974                         if (!strchr("( )", n[x]))
975                                 n[y++] = n[x];
976                 }
977         }
978         n[y] = '\0';
979 }
980
981 /*!
982  * \brief Checks if phone number consists of valid characters
983  * \param exten String that needs to be checked
984  * \param valid Valid characters in string
985  * \retval 1 if valid string
986  * \retval 0 if string contains invalid characters
987  */
988 static int ast_is_valid_string(const char *exten, const char *valid)
989 {
990         int x;
991
992         if (ast_strlen_zero(exten))
993                 return 0;
994         for (x = 0; exten[x]; x++)
995                 if (!strchr(valid, exten[x]))
996                         return 0;
997         return 1;
998 }
999
1000 int ast_isphonenumber(const char *n)
1001 {
1002         return ast_is_valid_string(n, "0123456789*#+");
1003 }
1004
1005 int ast_is_shrinkable_phonenumber(const char *exten)
1006 {
1007         return ast_is_valid_string(exten, "0123456789*#+()-.");
1008 }
1009
1010 int ast_callerid_parse(char *input_str, char **name, char **location)
1011 {
1012         char *ls;
1013         char *le;
1014         char *name_start;
1015         char *instr;
1016         int quotes_stripped = 0;
1017
1018         /* Handle surrounding quotes */
1019         input_str = ast_strip(input_str);
1020         instr = ast_strip_quoted(input_str, "\"", "\"");
1021         if (instr != input_str) {
1022                 quotes_stripped = 1;
1023         }
1024
1025         /* Try "name" <location> format or name <location> format or with a missing > */
1026         if ((ls = strrchr(instr, '<'))) {
1027                 if ((le = strrchr(ls, '>'))) {
1028                         *le = '\0';     /* location found, trim off the brackets */
1029                 }
1030                 *ls = '\0';
1031                 *location = ls + 1;     /* and this is the result */
1032
1033                 name_start = ast_strip_quoted(instr, "\"", "\"");
1034         } else {        /* no valid brackets */
1035                 char tmp[256];
1036
1037                 ast_copy_string(tmp, instr, sizeof(tmp));
1038                 ast_shrink_phone_number(tmp);
1039                 if (!quotes_stripped && ast_isphonenumber(tmp)) {       /* Assume it's just a location */
1040                         name_start = NULL;
1041                         strcpy(instr, tmp); /* safe, because tmp will always be the same size or smaller than instr */
1042                         *location = instr;
1043                 } else { /* Assume it's just a name. */
1044                         *location = NULL;
1045                         name_start = ast_strip_quoted(instr, "\"", "\"");
1046                 }
1047         }
1048
1049         if (name_start) {
1050                 ast_unescape_quoted(name_start);
1051         }
1052         *name = name_start;
1053         return 0;
1054 }
1055
1056 static int __ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int callwaiting, struct ast_format *codec)
1057 {
1058         if (ast_strlen_zero(name))
1059                 name = NULL;
1060         if (ast_strlen_zero(number))
1061                 number = NULL;
1062         return callerid_generate(buf, number, name, 0, callwaiting, codec);
1063 }
1064
1065 int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec)
1066 {
1067         return __ast_callerid_generate(buf, name, number, 0, codec);
1068 }
1069
1070 int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec)
1071 {
1072         return __ast_callerid_generate(buf, name, number, 1, codec);
1073 }
1074
1075 char *ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
1076 {
1077         if (!unknown)
1078                 unknown = "<unknown>";
1079         if (name && num) {
1080                 char name_buf[128];
1081
1082                 ast_escape_quoted(name, name_buf, sizeof(name_buf));
1083                 snprintf(buf, bufsiz, "\"%s\" <%s>", name_buf, num);
1084         } else if (name) {
1085                 ast_copy_string(buf, name, bufsiz);
1086         } else if (num) {
1087                 ast_copy_string(buf, num, bufsiz);
1088         } else {
1089                 ast_copy_string(buf, unknown, bufsiz);
1090         }
1091         return buf;
1092 }
1093
1094 int ast_callerid_split(const char *buf, char *name, int namelen, char *num, int numlen)
1095 {
1096         char *tmp;
1097         char *l = NULL, *n = NULL;
1098
1099         tmp = ast_strdupa(buf);
1100         ast_callerid_parse(tmp, &n, &l);
1101         if (n)
1102                 ast_copy_string(name, n, namelen);
1103         else
1104                 name[0] = '\0';
1105         if (l) {
1106                 ast_shrink_phone_number(l);
1107                 ast_copy_string(num, l, numlen);
1108         } else
1109                 num[0] = '\0';
1110         return 0;
1111 }
1112
1113 struct ast_value_translation {
1114         int value;
1115         const char *name;
1116         const char *description;
1117 };
1118
1119 /*! \brief Translation table for Caller ID Presentation settings */
1120 static const struct ast_value_translation pres_types[] = {
1121 /* *INDENT-OFF* */
1122         { AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_UNSCREENED,        "allowed_not_screened",  "Presentation Allowed, Not Screened" },
1123         { AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_PASSED_SCREEN,     "allowed_passed_screen", "Presentation Allowed, Passed Screen" },
1124         { AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_FAILED_SCREEN,     "allowed_failed_screen", "Presentation Allowed, Failed Screen" },
1125         { AST_PRES_ALLOWED | AST_PRES_NETWORK_NUMBER,                "allowed",               "Presentation Allowed, Network Number" },
1126
1127         { AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED,     "prohib_not_screened",   "Presentation Prohibited, Not Screened" },
1128         { AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_PASSED_SCREEN,  "prohib_passed_screen",  "Presentation Prohibited, Passed Screen" },
1129         { AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_FAILED_SCREEN,  "prohib_failed_screen",  "Presentation Prohibited, Failed Screen" },
1130         { AST_PRES_RESTRICTED | AST_PRES_NETWORK_NUMBER,             "prohib",                "Presentation Prohibited, Network Number" },
1131
1132         { AST_PRES_UNAVAILABLE | AST_PRES_NETWORK_NUMBER,            "unavailable",           "Number Unavailable" }, /* Default name to value conversion. */
1133         { AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_UNSCREENED,    "unavailable",           "Number Unavailable" },
1134         { AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_FAILED_SCREEN, "unavailable",           "Number Unavailable" },
1135         { AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_PASSED_SCREEN, "unavailable",           "Number Unavailable" },
1136 /* *INDENT-ON* */
1137 };
1138
1139 /*!
1140  * \brief Convert caller ID text code to value (used in config file parsing)
1141  * \param data text string from config file
1142  * \retval value AST_PRES_ from callerid.h
1143  * \retval -1 if not in table
1144  */
1145 int ast_parse_caller_presentation(const char *data)
1146 {
1147         int index;
1148         if (!data) {
1149                 return -1;
1150         }
1151
1152         for (index = 0; index < ARRAY_LEN(pres_types); ++index) {
1153                 if (!strcasecmp(pres_types[index].name, data)) {
1154                         return pres_types[index].value;
1155                 }
1156         }
1157
1158         return -1;
1159 }
1160
1161 /*!
1162  * \brief Convert caller ID pres value to explanatory string
1163  * \param data AST_PRES_ value from callerid.h
1164  * \return string for human presentation
1165  */
1166 const char *ast_describe_caller_presentation(int data)
1167 {
1168         int index;
1169
1170         for (index = 0; index < ARRAY_LEN(pres_types); ++index) {
1171                 if (pres_types[index].value == data) {
1172                         return pres_types[index].description;
1173                 }
1174         }
1175
1176         return "unknown";
1177 }
1178
1179 /*!
1180  * \brief Convert caller ID pres value to text code
1181  * \param data AST_PRES_ value from callerid.h
1182  * \return string for config file
1183  */
1184 const char *ast_named_caller_presentation(int data)
1185 {
1186         int index;
1187
1188         for (index = 0; index < ARRAY_LEN(pres_types); ++index) {
1189                 if (pres_types[index].value == data) {
1190                         return pres_types[index].name;
1191                 }
1192         }
1193
1194         return "unknown";
1195 }
1196
1197 /*! \brief Translation table for redirecting reason settings */
1198 static const struct ast_value_translation redirecting_reason_types[] = {
1199 /* *INDENT-OFF* */
1200         { AST_REDIRECTING_REASON_UNKNOWN,        "unknown",      "Unknown" },
1201         { AST_REDIRECTING_REASON_USER_BUSY,      "cfb",          "Call Forwarding Busy" },
1202         { AST_REDIRECTING_REASON_NO_ANSWER,      "cfnr",         "Call Forwarding No Reply" },
1203         { AST_REDIRECTING_REASON_UNAVAILABLE,    "unavailable",  "Callee is Unavailable" },
1204         { AST_REDIRECTING_REASON_UNCONDITIONAL,  "cfu",          "Call Forwarding Unconditional" },
1205         { AST_REDIRECTING_REASON_TIME_OF_DAY,    "time_of_day",  "Time of Day" },
1206         { AST_REDIRECTING_REASON_DO_NOT_DISTURB, "dnd",          "Do Not Disturb" },
1207         { AST_REDIRECTING_REASON_DEFLECTION,     "deflection",   "Call Deflection" },
1208         { AST_REDIRECTING_REASON_FOLLOW_ME,      "follow_me",    "Follow Me" },
1209         { AST_REDIRECTING_REASON_OUT_OF_ORDER,   "out_of_order", "Called DTE Out-Of-Order" },
1210         { AST_REDIRECTING_REASON_AWAY,           "away",         "Callee is Away" },
1211         { AST_REDIRECTING_REASON_CALL_FWD_DTE,   "cf_dte",       "Call Forwarding By The Called DTE" },
1212         { AST_REDIRECTING_REASON_SEND_TO_VM,     "send_to_vm",   "Call is being redirected to user's voicemail"},
1213 /* *INDENT-ON* */
1214 };
1215
1216 int ast_redirecting_reason_parse(const char *data)
1217 {
1218         int index;
1219
1220         for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
1221                 if (!strcasecmp(redirecting_reason_types[index].name, data)) {
1222                         return redirecting_reason_types[index].value;
1223                 }
1224         }
1225
1226         return -1;
1227 }
1228
1229 const char *ast_redirecting_reason_describe(int data)
1230 {
1231         int index;
1232
1233         for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
1234                 if (redirecting_reason_types[index].value == data) {
1235                         return redirecting_reason_types[index].description;
1236                 }
1237         }
1238
1239         return "not-known";
1240 }
1241
1242 const char *ast_redirecting_reason_name(const struct ast_party_redirecting_reason *data)
1243 {
1244         int index;
1245
1246         if (!ast_strlen_zero(data->str)) {
1247                 /* Use this string if it has been set. Otherwise, use the table. */
1248                 return data->str;
1249         }
1250
1251         for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
1252                 if (redirecting_reason_types[index].value == data->code) {
1253                         return redirecting_reason_types[index].name;
1254                 }
1255         }
1256
1257         return "not-known";
1258 }
1259
1260 /*! \brief Translation table for connected line update source settings */
1261 static const struct ast_value_translation connected_line_source_types[] = {
1262 /* *INDENT-OFF* */
1263         { AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN,           "unknown",           "Unknown" },
1264         { AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER,            "answer",            "Normal Call Answering" },
1265         { AST_CONNECTED_LINE_UPDATE_SOURCE_DIVERSION,         "diversion",         "Call Diversion (Deprecated, use REDIRECTING)" },
1266         { AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER,          "transfer_active",   "Call Transfer(Active)" },
1267         { AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER,          "transfer",          "Call Transfer(Active)" },/* Old name must come after new name. */
1268         { AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING, "transfer_alerting", "Call Transfer(Alerting)" }
1269 /* *INDENT-ON* */
1270 };
1271
1272 int ast_connected_line_source_parse(const char *data)
1273 {
1274         int index;
1275
1276         for (index = 0; index < ARRAY_LEN(connected_line_source_types); ++index) {
1277                 if (!strcasecmp(connected_line_source_types[index].name, data)) {
1278                         return connected_line_source_types[index].value;
1279                 }
1280         }
1281
1282         return -1;
1283 }
1284
1285 const char *ast_connected_line_source_describe(int data)
1286 {
1287         int index;
1288
1289         for (index = 0; index < ARRAY_LEN(connected_line_source_types); ++index) {
1290                 if (connected_line_source_types[index].value == data) {
1291                         return connected_line_source_types[index].description;
1292                 }
1293         }
1294
1295         return "not-known";
1296 }
1297
1298 const char *ast_connected_line_source_name(int data)
1299 {
1300         int index;
1301
1302         for (index = 0; index < ARRAY_LEN(connected_line_source_types); ++index) {
1303                 if (connected_line_source_types[index].value == data) {
1304                         return connected_line_source_types[index].name;
1305                 }
1306         }
1307
1308         return "not-known";
1309 }
1310
1311 /*! \brief Translation table for ast_party_name char-set settings */
1312 static const struct ast_value_translation party_name_charset_tbl[] = {
1313 /* *INDENT-OFF* */
1314         { AST_PARTY_CHAR_SET_UNKNOWN,               "unknown",      "Unknown" },
1315         { AST_PARTY_CHAR_SET_ISO8859_1,             "iso8859-1",    "ISO8859-1" },
1316         { AST_PARTY_CHAR_SET_WITHDRAWN,             "withdrawn",    "Withdrawn" },
1317         { AST_PARTY_CHAR_SET_ISO8859_2,             "iso8859-2",    "ISO8859-2" },
1318         { AST_PARTY_CHAR_SET_ISO8859_3,             "iso8859-3",    "ISO8859-3" },
1319         { AST_PARTY_CHAR_SET_ISO8859_4,             "iso8859-4",    "ISO8859-4" },
1320         { AST_PARTY_CHAR_SET_ISO8859_5,             "iso8859-5",    "ISO8859-5" },
1321         { AST_PARTY_CHAR_SET_ISO8859_7,             "iso8859-7",    "ISO8859-7" },
1322         { AST_PARTY_CHAR_SET_ISO10646_BMPSTRING,    "bmp",          "ISO10646 Bmp String" },
1323         { AST_PARTY_CHAR_SET_ISO10646_UTF_8STRING,  "utf8",         "ISO10646 UTF-8 String" },
1324 /* *INDENT-ON* */
1325 };
1326
1327 int ast_party_name_charset_parse(const char *data)
1328 {
1329         int index;
1330
1331         for (index = 0; index < ARRAY_LEN(party_name_charset_tbl); ++index) {
1332                 if (!strcasecmp(party_name_charset_tbl[index].name, data)) {
1333                         return party_name_charset_tbl[index].value;
1334                 }
1335         }
1336
1337         return -1;
1338 }
1339
1340 const char *ast_party_name_charset_describe(int data)
1341 {
1342         int index;
1343
1344         for (index = 0; index < ARRAY_LEN(party_name_charset_tbl); ++index) {
1345                 if (party_name_charset_tbl[index].value == data) {
1346                         return party_name_charset_tbl[index].description;
1347                 }
1348         }
1349
1350         return "not-known";
1351 }
1352
1353 const char *ast_party_name_charset_str(int data)
1354 {
1355         int index;
1356
1357         for (index = 0; index < ARRAY_LEN(party_name_charset_tbl); ++index) {
1358                 if (party_name_charset_tbl[index].value == data) {
1359                         return party_name_charset_tbl[index].name;
1360                 }
1361         }
1362
1363         return "not-known";
1364 }