Asterisk - The Open Source Telephony Project GIT-master-7e7a603
callerid.c
Go to the documentation of this file.
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#include <time.h>
33#include <math.h>
34#include <ctype.h>
35
36#include "asterisk/ulaw.h"
37#include "asterisk/alaw.h"
38#include "asterisk/frame.h"
39#include "asterisk/channel.h"
40#include "asterisk/callerid.h"
41#include "asterisk/fskmodem.h"
42#include "asterisk/utils.h"
44
47 char rawdata[256];
48 short oldstuff[160];
49 int oldlen;
50 int pos;
51 int type;
52 int cksum;
53 char name[64];
54 char number[64];
55 int flags;
58 int len;
59
61 unsigned short crc;
62};
63
64
65float cid_dr[4], cid_di[4];
66float clidsb = 8000.0 / 1200.0;
67float sasdr, sasdi;
69
70#define CALLERID_SPACE 2200.0 /*!< 2200 hz for "0" */
71#define CALLERID_MARK 1200.0 /*!< 1200 hz for "1" */
72#define SAS_FREQ 440.0
73#define CAS_FREQ1 2130.0
74#define CAS_FREQ2 2750.0
75
76#define AST_CALLERID_UNKNOWN "<unknown>"
77
78static 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)
79{
80 int x;
81 float t;
82 for (x = 0; x < len; x++) {
83 t = *cr1 * ddr1 - *ci1 * ddi1;
84 *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
85 *cr1 = t;
86 t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
87 *cr1 *= t;
88 *ci1 *= t;
89
90 t = *cr2 * ddr2 - *ci2 * ddi2;
91 *ci2 = *cr2 * ddi2 + *ci2 * ddr2;
92 *cr2 = t;
93 t = 2.0 - (*cr2 * *cr2 + *ci2 * *ci2);
94 *cr2 *= t;
95 *ci2 *= t;
96 buf[x] = AST_LIN2X((*cr1 + *cr2) * 2048.0);
97 }
98}
99
100static inline void gen_tone(unsigned char *buf, int len, struct ast_format *codec, float ddr1, float ddi1, float *cr1, float *ci1)
101{
102 int x;
103 float t;
104 for (x = 0; x < len; x++) {
105 t = *cr1 * ddr1 - *ci1 * ddi1;
106 *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
107 *cr1 = t;
108 t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
109 *cr1 *= t;
110 *ci1 *= t;
111 buf[x] = AST_LIN2X(*cr1 * 8192.0);
112 }
113}
114
115/*! \brief Initialize stuff for inverse FFT */
117{
118 cid_dr[0] = cos(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
119 cid_di[0] = sin(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
120 cid_dr[1] = cos(CALLERID_MARK * 2.0 * M_PI / 8000.0);
121 cid_di[1] = sin(CALLERID_MARK * 2.0 * M_PI / 8000.0);
122 sasdr = cos(SAS_FREQ * 2.0 * M_PI / 8000.0);
123 sasdi = sin(SAS_FREQ * 2.0 * M_PI / 8000.0);
124 casdr1 = cos(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
125 casdi1 = sin(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
126 casdr2 = cos(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
127 casdi2 = sin(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
128}
129
130struct callerid_state *callerid_new(int cid_signalling)
131{
132 struct callerid_state *cid;
133
134 if ((cid = ast_calloc(1, sizeof(*cid)))) {
135#ifdef INTEGER_CALLERID
136 cid->fskd.ispb = 7; /* 1200 baud */
137 /* Set up for 1200 / 8000 freq *32 to allow ints */
138 cid->fskd.pllispb = (int)(8000 * 32 / 1200);
139 cid->fskd.pllids = cid->fskd.pllispb/32;
140 cid->fskd.pllispb2 = cid->fskd.pllispb/2;
141
142 cid->fskd.icont = 0; /* PLL REset */
143 /* cid->fskd.hdlc = 0; */ /* Async */
144 cid->fskd.nbit = 8; /* 8 bits */
145 cid->fskd.instop = 1; /* 1 stop bit */
146 /* cid->fskd.paridad = 0; */ /* No parity */
147 cid->fskd.bw = 1; /* Filter 800 Hz */
148 if (cid_signalling == 2) { /* v23 signalling */
149 cid->fskd.f_mark_idx = 4; /* 1300 Hz */
150 cid->fskd.f_space_idx = 5; /* 2100 Hz */
151 } else { /* Bell 202 signalling as default */
152 cid->fskd.f_mark_idx = 2; /* 1200 Hz */
153 cid->fskd.f_space_idx = 3; /* 2200 Hz */
154 }
155 /* cid->fskd.pcola = 0; */ /* No clue */
156 /* cid->fskd.cont = 0.0; */ /* Digital PLL reset */
157 /* cid->fskd.x0 = 0.0; */
158 /* cid->fskd.state = 0; */
160 /* cid->pos = 0; */
161
162 fskmodem_init(&cid->fskd);
163#else
164 cid->fskd.spb = 7.0; /* 1200 baud */
165 /* cid->fskd.hdlc = 0; */ /* Async */
166 cid->fskd.nbit = 8; /* 8 bits */
167 cid->fskd.nstop = 1.0; /* 1 stop bit */
168 /* cid->fskd.paridad = 0; */ /* No parity */
169 cid->fskd.bw = 1; /* Filter 800 Hz */
170 if (cid_signalling == 2) { /* v23 signalling */
171 cid->fskd.f_mark_idx = 4; /* 1300 Hz */
172 cid->fskd.f_space_idx = 5; /* 2100 Hz */
173 } else { /* Bell 202 signalling as default */
174 cid->fskd.f_mark_idx = 2; /* 1200 Hz */
175 cid->fskd.f_space_idx = 3; /* 2200 Hz */
176 }
177 /* cid->fskd.pcola = 0; */ /* No clue */
178 /* cid->fskd.cont = 0.0; */ /* Digital PLL reset */
179 /* cid->fskd.x0 = 0.0; */
180 /* cid->fskd.state = 0; */
182 /* cid->pos = 0; */
183#endif
184 }
185
186 return cid;
187}
188
189void callerid_get_with_redirecting(struct callerid_state *cid, char **name, char **number, int *flags, int *redirecting)
190{
191 *flags = cid->flags;
192 if (cid->flags & (CID_UNKNOWN_NAME | CID_PRIVATE_NAME)) {
193 *name = NULL;
194 } else {
195 *name = cid->name;
196 }
198 *number = NULL;
199 } else {
200 *number = cid->number;
201 }
202 *redirecting = cid->redirecting;
203}
204
205void callerid_get(struct callerid_state *cid, char **name, char **number, int *flags)
206{
207 int redirecting;
209}
210
211void callerid_get_dtmf(char *cidstring, char *number, int *flags)
212{
213 int i;
214 int code;
215
216 /* "Clear" the number-buffer. */
217 number[0] = 0;
218
219 if (strlen(cidstring) < 2) {
220 ast_debug(1, "No cid detected\n");
222 return;
223 }
224
225 /* Detect protocol and special types */
226 if (cidstring[0] == 'B') {
227 /* Handle special codes */
228 code = atoi(&cidstring[1]);
229 if (code == 0)
231 else if (code == 10)
233 else
234 ast_debug(1, "Unknown DTMF code %d\n", code);
235 } else if (cidstring[0] == 'D' && cidstring[2] == '#') {
236 /* .DK special code */
237 if (cidstring[1] == '1')
239 if (cidstring[1] == '2' || cidstring[1] == '3')
241 } else if (cidstring[0] == 'D' || cidstring[0] == 'A') {
242 /* "Standard" callerid */
243 for (i = 1; i < strlen(cidstring); i++) {
244 if (cidstring[i] == 'C' || cidstring[i] == '#')
245 break;
246 if (isdigit(cidstring[i]))
247 number[i-1] = cidstring[i];
248 else
249 ast_debug(1, "Unknown CID digit '%c'\n",
250 cidstring[i]);
251 }
252 number[i-1] = 0;
253 } else if (isdigit(cidstring[0])) {
254 /* It begins with a digit, so we parse it as a number and hope
255 * for the best */
256 ast_log(LOG_WARNING, "Couldn't detect start-character. CID "
257 "parsing might be unreliable\n");
258 for (i = 0; i < strlen(cidstring); i++) {
259 if (isdigit(cidstring[i]))
260 number[i] = cidstring[i];
261 else
262 break;
263 }
264 number[i] = 0;
265 } else {
266 ast_debug(1, "Unknown CID protocol, start digit '%c'\n", cidstring[0]);
268 }
269}
270
271int ast_gen_cas(unsigned char *outbuf, int sendsas, int len, struct ast_format *codec)
272{
273 int pos = 0;
274 int saslen = 2400;
275 float cr1 = 1.0;
276 float ci1 = 0.0;
277 float cr2 = 1.0;
278 float ci2 = 0.0;
279
280 if (sendsas) {
281 if (len < saslen)
282 return -1;
283 gen_tone(outbuf, saslen, codec, sasdr, sasdi, &cr1, &ci1);
284 len -= saslen;
285 pos += saslen;
286 cr2 = cr1;
287 ci2 = ci1;
288 }
289 gen_tones(outbuf + pos, len, codec, casdr1, casdi1, casdr2, casdi2, &cr1, &ci1, &cr2, &ci2);
290 return 0;
291}
292
293static unsigned short calc_crc(unsigned short crc, unsigned char data)
294{
295 unsigned int i, j, org, dst;
296 org = data;
297 dst = 0;
298
299 for (i = 0; i < CHAR_BIT; i++) {
300 org <<= 1;
301 dst >>= 1;
302 if (org & 0x100)
303 dst |= 0x80;
304 }
305 data = (unsigned char) dst;
306 crc ^= (unsigned int) data << (16 - CHAR_BIT);
307 for (j = 0; j < CHAR_BIT; j++) {
308 if (crc & 0x8000U)
309 crc = (crc << 1) ^ 0x1021U ;
310 else
311 crc <<= 1 ;
312 }
313 return crc;
314}
315
316int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int len, struct ast_format *codec)
317{
318 int mylen = len;
319 int olen;
320 int b = 'X';
321 int b2;
322 int res;
323 int x;
324 short *buf;
325
326 buf = ast_alloca(2 * len + cid->oldlen);
327
328 memcpy(buf, cid->oldstuff, cid->oldlen);
329 mylen += cid->oldlen / 2;
330
331 for (x = 0; x < len; x++)
332 buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
333
334 while (mylen >= 160) {
335 b = b2 = 0;
336 olen = mylen;
337 res = fsk_serial(&cid->fskd, buf, &mylen, &b);
338
339 if (mylen < 0) {
340 ast_log(LOG_ERROR, "No start bit found in fsk data.\n");
341 return -1;
342 }
343
344 buf += (olen - mylen);
345
346 if (res < 0) {
347 ast_log(LOG_NOTICE, "fsk_serial failed\n");
348 return -1;
349 }
350
351 if (res == 1) {
352 b2 = b;
353 b &= 0x7f;
354
355 /* crc checksum calculation */
356 if (cid->sawflag > 1)
357 cid->crc = calc_crc(cid->crc, (unsigned char) b2);
358
359 /* Ignore invalid bytes */
360 if (b > 0xff)
361 continue;
362
363 /* skip DLE if needed */
364 if (cid->sawflag > 0) {
365 if (cid->sawflag != 5 && cid->skipflag == 0 && b == 0x10) {
366 cid->skipflag = 1 ;
367 continue ;
368 }
369 }
370 if (cid->skipflag == 1)
371 cid->skipflag = 0 ;
372
373 /* caller id retrieval */
374 switch (cid->sawflag) {
375 case 0: /* DLE */
376 if (b == 0x10) {
377 cid->sawflag = 1;
378 cid->skipflag = 0;
379 cid->crc = 0;
380 }
381 break;
382 case 1: /* SOH */
383 if (b == 0x01)
384 cid->sawflag = 2;
385 break ;
386 case 2: /* HEADER */
387 if (b == 0x07)
388 cid->sawflag = 3;
389 break;
390 case 3: /* STX */
391 if (b == 0x02)
392 cid->sawflag = 4;
393 break;
394 case 4: /* SERVICE TYPE */
395 if (b == 0x40)
396 cid->sawflag = 5;
397 break;
398 case 5: /* Frame Length */
399 cid->sawflag = 6;
400 break;
401 case 6: /* NUMBER TYPE */
402 cid->sawflag = 7;
403 cid->pos = 0;
404 cid->rawdata[cid->pos++] = b;
405 break;
406 case 7: /* NUMBER LENGTH */
407 cid->sawflag = 8;
408 cid->len = b;
409 if ((cid->len+2) >= sizeof(cid->rawdata)) {
410 ast_log(LOG_WARNING, "too long caller id string\n") ;
411 return -1;
412 }
413 cid->rawdata[cid->pos++] = b;
414 break;
415 case 8: /* Retrieve message */
416 cid->rawdata[cid->pos++] = b;
417 cid->len--;
418 if (cid->len<=0) {
419 cid->rawdata[cid->pos] = '\0';
420 cid->sawflag = 9;
421 }
422 break;
423 case 9: /* ETX */
424 cid->sawflag = 10;
425 break;
426 case 10: /* CRC Checksum 1 */
427 cid->sawflag = 11;
428 break;
429 case 11: /* CRC Checksum 2 */
430 cid->sawflag = 12;
431 if (cid->crc != 0) {
432 ast_log(LOG_WARNING, "crc checksum error\n") ;
433 return -1;
434 }
435 /* extract caller id data */
436 for (x = 0; x < cid->pos;) {
437 switch (cid->rawdata[x++]) {
438 case 0x02: /* caller id number */
439 cid->number[0] = '\0';
440 cid->name[0] = '\0';
441 cid->flags = 0;
442 res = cid->rawdata[x++];
443 ast_copy_string(cid->number, &cid->rawdata[x], res+1);
444 x += res;
445 break;
446 case 0x21: /* additional information */
447 /* length */
448 x++;
449 /* number type */
450 switch (cid->rawdata[x]) {
451 case 0x00: /* unknown */
452 case 0x01: /* international number */
453 case 0x02: /* domestic number */
454 case 0x03: /* network */
455 case 0x04: /* local call */
456 case 0x06: /* short dial number */
457 case 0x07: /* reserved */
458 default: /* reserved */
459 ast_debug(2, "cid info:#1=%X\n", (unsigned)cid->rawdata[x]);
460 break ;
461 }
462 x++;
463 /* numbering plan octed 4 */
464 x++;
465 /* numbering plan octed 5 */
466 switch (cid->rawdata[x]) {
467 case 0x00: /* unknown */
468 case 0x01: /* recommendation E.164 ISDN */
469 case 0x03: /* recommendation X.121 */
470 case 0x04: /* telex dial plan */
471 case 0x08: /* domestic dial plan */
472 case 0x09: /* private dial plan */
473 case 0x05: /* reserved */
474 default: /* reserved */
475 ast_debug(2, "cid info:#2=%X\n", (unsigned)cid->rawdata[x]);
476 break ;
477 }
478 x++;
479 break ;
480 case 0x04: /* no callerid reason */
481 /* length */
482 x++;
483 /* no callerid reason code */
484 switch (cid->rawdata[x]) {
485 case 'P': /* caller id denied by user */
486 case 'O': /* service not available */
487 case 'C': /* pay phone */
488 case 'S': /* service congested */
490 ast_debug(2, "no cid reason:%c\n", cid->rawdata[x]);
491 break ;
492 }
493 x++;
494 break ;
495 case 0x09: /* dialed number */
496 /* length */
497 res = cid->rawdata[x++];
498 /* dialed number */
499 x += res;
500 break ;
501 case 0x22: /* dialed number additional information */
502 /* length */
503 x++;
504 /* number type */
505 switch (cid->rawdata[x]) {
506 case 0x00: /* unknown */
507 case 0x01: /* international number */
508 case 0x02: /* domestic number */
509 case 0x03: /* network */
510 case 0x04: /* local call */
511 case 0x06: /* short dial number */
512 case 0x07: /* reserved */
513 default: /* reserved */
514 if (DEBUG_ATLEAST(2))
515 ast_log(LOG_NOTICE, "did info:#1=%X\n", (unsigned)cid->rawdata[x]);
516 break ;
517 }
518 x++;
519 /* numbering plan octed 4 */
520 x++;
521 /* numbering plan octed 5 */
522 switch (cid->rawdata[x]) {
523 case 0x00: /* unknown */
524 case 0x01: /* recommendation E.164 ISDN */
525 case 0x03: /* recommendation X.121 */
526 case 0x04: /* telex dial plan */
527 case 0x08: /* domestic dial plan */
528 case 0x09: /* private dial plan */
529 case 0x05: /* reserved */
530 default: /* reserved */
531 ast_debug(2, "did info:#2=%X\n", (unsigned)cid->rawdata[x]);
532 break ;
533 }
534 x++;
535 break ;
536 }
537 }
538 return 1;
539 break;
540 default:
541 ast_log(LOG_ERROR, "invalid value in sawflag %d\n", cid->sawflag);
542 }
543 }
544 }
545 if (mylen) {
546 memcpy(cid->oldstuff, buf, mylen * 2);
547 cid->oldlen = mylen * 2;
548 } else
549 cid->oldlen = 0;
550
551 return 0;
552}
553
554static const char *mdmf_param_name(int param)
555{
556 switch (param) {
557 case 0x1: return "Date/Time";
558 case 0x2: return "Caller Number";
559 case 0x3: return "DNIS";
560 case 0x4: return "Reason For Absence of Number";
561 case 0x5: return "Reason For Redirection";
562 case 0x6: return "Call Qualifier";
563 case 0x7: return "Name";
564 case 0x8: return "Reason For Absence of Name";
565 case 0xB: return "Message Waiting";
566 default: return "Unknown";
567 }
568}
569
570int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, struct ast_format *codec)
571{
572 int mylen = len;
573 int olen;
574 int b = 'X';
575 int res;
576 int x;
577 short *buf;
578
579 buf = ast_alloca(2 * len + cid->oldlen);
580
581 memcpy(buf, cid->oldstuff, cid->oldlen);
582 mylen += cid->oldlen/2;
583
584 for (x = 0; x < len; x++)
585 buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
586 while (mylen >= 160) {
587 olen = mylen;
588 res = fsk_serial(&cid->fskd, buf, &mylen, &b);
589 if (mylen < 0) {
590 ast_log(LOG_ERROR, "No start bit found in fsk data.\n");
591 return -1;
592 }
593 buf += (olen - mylen);
594 if (res < 0) {
595 ast_log(LOG_NOTICE, "fsk_serial failed\n");
596 return -1;
597 }
598 if (res == 1) {
599 if (b > 0xff) {
600 if (cid->sawflag != 5) {
601 /* Ignore invalid bytes */
602 continue;
603 }
604 /*
605 * We can tolerate an error on the checksum character since the
606 * checksum character is the last character in the message and
607 * it validates the message.
608 *
609 * Remove character error flags.
610 * Bit 8 : Parity error
611 * Bit 9 : Framing error
612 */
613 b &= 0xff;
614 }
615 switch (cid->sawflag) {
616 case 0: /* Look for flag */
617 if (b == 'U')
618 cid->sawflag = 2;
619 break;
620 case 2: /* Get lead-in */
621 if ((b == 0x04) || (b == 0x80) || (b == 0x06) || (b == 0x82)) {
622 cid->type = b;
623 cid->sawflag = 3;
624 cid->cksum = b;
625 }
626 break;
627 case 3: /* Get length */
628 /* Not a lead in. We're ready */
629 cid->sawflag = 4;
630 cid->len = b;
631 cid->pos = 0;
632 cid->cksum += b;
633 break;
634 case 4: /* Retrieve message */
635 if (cid->pos >= 128) {
636 ast_log(LOG_WARNING, "Caller ID too long???\n");
637 return -1;
638 }
639 cid->rawdata[cid->pos++] = b;
640 cid->len--;
641 cid->cksum += b;
642 if (!cid->len) {
643 cid->rawdata[cid->pos] = '\0';
644 cid->sawflag = 5;
645 }
646 break;
647 case 5: /* Check checksum */
648 if ((b + cid->cksum) & 0xff) {
649 ast_log(LOG_NOTICE, "Caller*ID failed checksum\n");
650 /* Try again */
651 cid->sawflag = 0;
652 break;
653 }
654
655 cid->number[0] = '\0';
656 cid->name[0] = '\0';
657 /* Update flags */
658 cid->flags = 0;
659 cid->redirecting = 0;
660 /* If we get this far we're fine. */
661 if ((cid->type == 0x80) || (cid->type == 0x82)) {
662 /* MDMF */
663 ast_debug(6, "%s Caller*ID spill received\n", cid->type == 0x80 ? "MDMF" : "MDMF Message Waiting");
664 /* Go through each element and process */
665 for (x = 0; x < cid->pos;) {
666 int param = cid->rawdata[x++];
667 ast_debug(7, "Caller*ID parameter %d (%s), length %d\n", param, mdmf_param_name(param), cid->rawdata[x]);
668 switch (param) {
669 case 1:
670 /* Date/Time... in theory we could synchronize our time according to the Caller*ID,
671 * but it would be silly for a telephone switch to do that. */
672 break;
673 /* For MDMF spills, we would expect to get an "O" or a "P"
674 * for paramter 4 (or 8) as opposed to 2 (or 7) to indicate
675 * a blocked or out of area presentation.
676 * However, for SDMF, which doesn't have parameters,
677 * there is no differentiation, which is why the logic below
678 * just checks the number and name field and here, we use the same
679 * parsing logic for both parameters. Technically, it would be wrong
680 * to receive an 'O' or 'P' for parameters 2 or 7 and treat it as
681 * the reason for absence fields, but that is not likely to happen,
682 * and if it did, could possibly be buggy Caller ID generation we would
683 * want to treat the same way, anyways.
684 *
685 * The "Dialable Directory Number" is how the number would be called back.
686 * Asterisk doesn't really have a corresponding thing for this,
687 * so log it if we get it for debugging, but treat the same otherwise.
688 */
689 case 3: /* Dialable Directory Number / Number (for Zebble) */
690 ast_debug(3, "Caller*ID Dialable Directory Number: '%.*s'\n", cid->rawdata[x], cid->rawdata + x + 1);
691 /* Fall through */
692 case 2: /* Number */
693 case 4: /* Reason for Absence of Number. */
694 res = cid->rawdata[x];
695 if (res > 32) {
696 ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]);
697 res = 32;
698 }
699 if (ast_strlen_zero(cid->number)) {
700 memcpy(cid->number, cid->rawdata + x + 1, res);
701 /* Null terminate */
702 cid->number[res] = '\0';
703 }
704 break;
705 case 5: /* Reason for Redirection */
706 res = cid->rawdata[x];
707 if (res != 1) {
708 ast_log(LOG_WARNING, "Redirecting parameter length is %d?\n", res);
709 break;
710 }
711 switch (*(cid->rawdata + x + 1)) {
712 case 0x1:
714 break;
715 case 0x2:
717 break;
718 case 0x3:
720 break;
721 case 0x4:
723 break;
724 case 0x5:
726 break;
727 default:
728 ast_log(LOG_WARNING, "Redirecting reason is %02x?\n", *(cid->rawdata + x + 1));
729 break;
730 }
731 break;
732 case 6: /* Stentor Call Qualifier (ie. Long Distance call) */
733 res = cid->rawdata[x];
734 if (res == 1 && *(cid->rawdata + x + 1) == 'L') {
735 cid->flags |= CID_QUALIFIER;
736 } else if (res >= 1) {
737 ast_debug(2, "Invalid value (len %d) received for Call Qualifier: '%c'\n", res, *(cid->rawdata + x + 1));
738 }
739 break;
740 case 7: /* Name */
741 case 8: /* Reason for Absence of Name */
742 res = cid->rawdata[x];
743 if (res > 32) {
744 ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]);
745 res = 32;
746 }
747 memcpy(cid->name, cid->rawdata + x + 1, res);
748 cid->name[res] = '\0';
749 break;
750 case 11: /* Message Waiting */
751 res = cid->rawdata[x + 1];
752 if (res)
753 cid->flags |= CID_MSGWAITING;
754 else
755 cid->flags |= CID_NOMSGWAITING;
756 break;
757 case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting */
758 case 19: /* UK: Network message system status (Number of messages waiting) */
759 case 22: /* Something French */
760 break;
761 default:
762 ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x - 1]);
763 }
764 res = cid->rawdata[x];
765 if (0 > res){ /* Negative offset in the CID Spill */
766 ast_log(LOG_NOTICE, "IE %d has bad field length of %d at offset %d\n", cid->rawdata[x-1], cid->rawdata[x], x);
767 /* Try again */
768 cid->sawflag = 0;
769 break; /* Exit the loop */
770 }
771 x += cid->rawdata[x];
772 x++;
773 }
774 } else if (cid->type == 0x6) {
775 /* VMWI SDMF */
776 ast_debug(6, "VMWI SDMF Caller*ID spill received\n");
777 if (cid->rawdata[2] == 0x42) {
778 cid->flags |= CID_MSGWAITING;
779 } else if (cid->rawdata[2] == 0x6f) {
780 cid->flags |= CID_NOMSGWAITING;
781 }
782 } else {
783 /* SDMF */
784 ast_debug(6, "SDMF Caller*ID spill received\n");
785 ast_copy_string(cid->number, cid->rawdata + 8, sizeof(cid->number));
786 }
787 if (!strcmp(cid->number, "P")) {
788 ast_debug(6, "Caller*ID number is private\n");
789 strcpy(cid->number, "");
791 } else if (!strcmp(cid->number, "O")) {
792 ast_debug(6, "Caller*ID number is out of area\n");
793 strcpy(cid->number, "");
795 } else if (ast_strlen_zero(cid->number)) {
796 ast_debug(6, "No Caller*ID number provided, and no reason provided for its absence\n");
797 strcpy(cid->number, "");
799 } else {
800 ast_debug(6, "Caller*ID number is '%s'\n", cid->number);
801 }
802 if (!strcmp(cid->name, "P")) {
803 ast_debug(6, "Caller*ID name is private\n");
804 strcpy(cid->name, "");
805 cid->flags |= CID_PRIVATE_NAME;
806 } else if (!strcmp(cid->name, "O")) {
807 ast_debug(6, "Caller*ID name is out of area\n");
808 strcpy(cid->name, "");
809 cid->flags |= CID_UNKNOWN_NAME;
810 } else if (ast_strlen_zero(cid->name)) {
811 ast_debug(6, "No Caller*ID name provided, and no reason provided for its absence\n");
812 strcpy(cid->name, "");
813 cid->flags |= CID_UNKNOWN_NAME;
814 } else {
815 ast_debug(6, "Caller*ID name is '%s'\n", cid->name);
816 }
817 return 1;
818 break;
819 default:
820 ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag);
821 }
822 }
823 }
824 if (mylen) {
825 memcpy(cid->oldstuff, buf, mylen * 2);
826 cid->oldlen = mylen * 2;
827 } else
828 cid->oldlen = 0;
829
830 return 0;
831}
832
834{
835 ast_free(cid);
836}
837
838static int callerid_genmsg(char *msg, int size, const char *number, const char *name, int flags, int format,
839 const char *ddn, int redirecting, const char *tz)
840{
841 struct timeval now = ast_tvnow();
842 struct ast_tm tm;
843 char *ptr;
844 int res;
845 int i, x;
846
847 /* Get the time */
848 ast_localtime(&now, &tm, tz);
849
850 ptr = msg;
851
852 /* Format time and message header */
853 res = snprintf(ptr, size, "\001\010%02d%02d%02d%02d", tm.tm_mon + 1,
854 tm.tm_mday, tm.tm_hour, tm.tm_min);
855 size -= res;
856 ptr += res;
857
858 if (ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) {
859 /* Indicate number not known */
860 res = snprintf(ptr, size, "\004\001O");
861 size -= res;
862 ptr += res;
863 } else if (flags & CID_PRIVATE_NUMBER) {
864 /* Indicate number is private */
865 res = snprintf(ptr, size, "\004\001P");
866 size -= res;
867 ptr += res;
868 } else {
869 /* Send up to 16 digits of number MAX */
870 i = strlen(number);
871 if (i > 16)
872 i = 16;
873 res = snprintf(ptr, size, "\002%c", i);
874 size -= res;
875 ptr += res;
876 for (x = 0; x < i; x++)
877 ptr[x] = number[x];
878 ptr[i] = '\0';
879 ptr += i;
880 size -= i;
881 }
882
883 if (format == CID_TYPE_SDMF) { /* If Simple Data Message Format, we're done. */
884 /* (some older Caller ID units only support SDMF. If they get an MDMF spill, it's useless.) */
885 return (ptr - msg);
886 }
887
888 if (ast_strlen_zero(name) || (flags & CID_UNKNOWN_NAME)) {
889 /* Indicate name not known */
890 res = snprintf(ptr, size, "\010\001O");
891 size -= res;
892 ptr += res;
893 } else if (flags & CID_PRIVATE_NAME) {
894 /* Indicate name is private */
895 res = snprintf(ptr, size, "\010\001P");
896 size -= res;
897 ptr += res;
898 } else {
899 /* Send up to 16 digits of name MAX */
900 i = strlen(name);
901 if (i > 16)
902 i = 16;
903 res = snprintf(ptr, size, "\007%c", i);
904 size -= res;
905 ptr += res;
906 for (x = 0; x < i; x++)
907 ptr[x] = name[x];
908 ptr[i] = '\0';
909 ptr += i;
910 size -= i;
911 }
912
913 /* Call Qualifier */
914 if (flags & CID_QUALIFIER) {
915 res = snprintf(ptr, size, "\006\001L"); /* LDC (Long Distance Call) is the only valid option */
916 size -= res;
917 ptr += res;
918 }
919
920 /* DDN (Dialable Directory Number) - 11 digits MAX, parameter 003 */
921 /* some CPE seem to display the DDN instead of the CLID, if sent */
922
923 /* Redirecting Reason */
924 if (redirecting >= 0) {
925 res = 0;
926 switch (redirecting) {
928 res = snprintf(ptr, size, "\005\001\001");
929 break;
931 res = snprintf(ptr, size, "\005\001\002");
932 break;
934 res = snprintf(ptr, size, "\005\001\003");
935 break;
937 res = snprintf(ptr, size, "\005\001\004");
938 break;
940 res = snprintf(ptr, size, "\005\001\005");
941 break;
942 default:
943 break;
944 }
945 ptr += res;
946 size -= res;
947 }
948
949 return (ptr - msg);
950}
951
952int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, struct ast_format *codec, const char* name, const char* number, int flags)
953{
954 char msg[256];
955 int len = 0;
956 int sum;
957 int x;
958 int bytes = 0;
959 float cr = 1.0;
960 float ci = 0.0;
961 float scont = 0.0;
962
964 /* MDMF Message waiting with date, number, name and MWI parameter */
965 msg[0] = 0x82;
966
967 /* put date, number info at the right place */
968 len = callerid_genmsg(msg+2, sizeof(msg)-2, number, name, flags, CID_TYPE_MDMF, "", -1, NULL);
969
970 /* length of MDMF CLI plus Message Waiting Structure */
971 msg[1] = len+3;
972
973 /* Go to the position to write to */
974 len = len+2;
975
976 /* "Message Waiting Parameter" */
977 msg[len++] = 0x0b;
978 /* Length of IE is one */
979 msg[len++] = 1;
980 /* Active or not */
981 if (active)
982 msg[len++] = 0xff;
983 else
984 msg[len++] = 0x00;
985
986 } else if (type == CID_MWI_TYPE_MDMF) {
987 /* MDMF Message waiting only */
988 /* same as above except that the we only put MWI parameter */
989 msg[len++] = 0x82;
990 /* Length is 3 */
991 msg[len++] = 3;
992 /* IE is "Message Waiting Parameter" */
993 msg[len++] = 0x0b;
994 /* Length of IE is one */
995 msg[len++] = 1;
996 /* Active or not */
997 if (active)
998 msg[len++] = 0xff;
999 else
1000 msg[len++] = 0x00;
1001 } else {
1002 /* SDMF Message waiting */
1003 msg[len++] = 0x6;
1004 /* Length is 3 */
1005 msg[len++] = 3;
1006 if (active) {
1007 msg[len++] = 0x42;
1008 msg[len++] = 0x42;
1009 msg[len++] = 0x42;
1010 } else {
1011 msg[len++] = 0x6f;
1012 msg[len++] = 0x6f;
1013 msg[len++] = 0x6f;
1014 }
1015 }
1016 sum = 0;
1017 for (x = 0; x < len; x++)
1018 sum += msg[x];
1019 sum = (256 - (sum & 255));
1020 msg[len++] = sum;
1021 /* Wait a half a second */
1022 for (x = 0; x < 4000; x++)
1023 PUT_BYTE(0x7f);
1024 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
1025 for (x = 0; x < 30; x++)
1026 PUT_CLID(0x55);
1027 /* Send 170ms of callerid marks */
1028 for (x = 0; x < 170; x++)
1030 for (x = 0; x < len; x++) {
1031 PUT_CLID(msg[x]);
1032 }
1033 /* Send 50 more ms of marks */
1034 for (x = 0; x < 50; x++)
1036 return bytes;
1037}
1038
1039int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, struct ast_format *codec)
1040{
1041 return callerid_full_generate(buf, number, name, NULL, -1, flags, CID_TYPE_MDMF, callwaiting, codec);
1042}
1043
1044int callerid_full_generate(unsigned char *buf, const char *number, const char *name, const char *ddn, int redirecting,
1045 int flags, int format, int callwaiting, struct ast_format *codec)
1046{
1047 /* Default time zone is NULL (system time zone) */
1048 return callerid_full_tz_generate(buf, number, name, ddn, redirecting, flags, format, callwaiting, codec, NULL);
1049}
1050
1051int callerid_full_tz_generate(unsigned char *buf, const char *number, const char *name, const char *ddn, int redirecting,
1052 int flags, int format, int callwaiting, struct ast_format *codec, const char *tz)
1053{
1054 int bytes = 0;
1055 int x, sum;
1056 int len;
1057
1058 /* Initial carriers (real/imaginary) */
1059 float cr = 1.0;
1060 float ci = 0.0;
1061 float scont = 0.0;
1062 char msg[256];
1063 len = callerid_genmsg(msg, sizeof(msg), number, name, flags, format, ddn, redirecting, tz);
1064 if (!callwaiting) {
1065 /* Wait a half a second */
1066 for (x = 0; x < 4000; x++)
1067 PUT_BYTE(0x7f);
1068 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
1069 for (x = 0; x < 30; x++)
1070 PUT_CLID(0x55);
1071 }
1072 /* Send 150ms of callerid marks */
1073 for (x = 0; x < 150; x++)
1075 /* Send 0x80 indicating MDMF format */
1076 PUT_CLID(0x80);
1077 /* Put length of whole message */
1078 PUT_CLID(len);
1079 sum = 0x80 + strlen(msg);
1080 /* Put each character of message and update checksum */
1081 for (x = 0; x < len; x++) {
1082 PUT_CLID(msg[x]);
1083 sum += msg[x];
1084 }
1085 /* Send 2's compliment of sum */
1086 PUT_CLID(256 - (sum & 255));
1087
1088 /* Send 50 more ms of marks */
1089 for (x = 0; x < 50; x++)
1091
1092 return bytes;
1093}
1094
1095/*!
1096 * \brief Clean up phone string
1097 * \details
1098 * Remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
1099 * Basically, remove anything that could be invalid in a pattern.
1100 */
1102{
1103 int x, y = 0;
1104 int bracketed = 0;
1105
1106 for (x = 0; n[x]; x++) {
1107 switch (n[x]) {
1108 case '[':
1109 bracketed++;
1110 n[y++] = n[x];
1111 break;
1112 case ']':
1113 bracketed--;
1114 n[y++] = n[x];
1115 break;
1116 case '-':
1117 if (bracketed)
1118 n[y++] = n[x];
1119 break;
1120 case '.':
1121 if (!n[x+1])
1122 n[y++] = n[x];
1123 break;
1124 default:
1125 /* ignore parenthesis and whitespace */
1126 if (!strchr("( )", n[x]))
1127 n[y++] = n[x];
1128 }
1129 }
1130 n[y] = '\0';
1131}
1132
1133/*!
1134 * \brief Checks if phone number consists of valid characters
1135 * \param exten String that needs to be checked
1136 * \param valid Valid characters in string
1137 * \retval 1 if valid string
1138 * \retval 0 if string contains invalid characters
1139 */
1140static int ast_is_valid_string(const char *exten, const char *valid)
1141{
1142 int x;
1143
1144 if (ast_strlen_zero(exten))
1145 return 0;
1146 for (x = 0; exten[x]; x++)
1147 if (!strchr(valid, exten[x]))
1148 return 0;
1149 return 1;
1150}
1151
1152int ast_isphonenumber(const char *n)
1153{
1154 return ast_is_valid_string(n, "0123456789*#+");
1155}
1156
1157int ast_is_shrinkable_phonenumber(const char *exten)
1158{
1159 return ast_is_valid_string(exten, "0123456789*#+()-.");
1160}
1161
1162int ast_callerid_parse(char *input_str, char **name, char **location)
1163{
1164 char *ls;
1165 char *le;
1166 char *name_start;
1167 char *instr;
1168 int quotes_stripped = 0;
1169
1170 /* Handle surrounding quotes */
1171 input_str = ast_strip(input_str);
1172 instr = ast_strip_quoted(input_str, "\"", "\"");
1173 if (instr != input_str) {
1174 quotes_stripped = 1;
1175 }
1176
1177 /* Try "name" <location> format or name <location> format or with a missing > */
1178 if ((ls = strrchr(instr, '<'))) {
1179 if ((le = strrchr(ls, '>'))) {
1180 *le = '\0'; /* location found, trim off the brackets */
1181 }
1182 *ls = '\0';
1183 *location = ls + 1; /* and this is the result */
1184
1185 name_start = ast_strip_quoted(instr, "\"", "\"");
1186 } else { /* no valid brackets */
1187 char tmp[256];
1188
1189 ast_copy_string(tmp, instr, sizeof(tmp));
1191 if (!quotes_stripped && ast_isphonenumber(tmp)) { /* Assume it's just a location */
1192 name_start = NULL;
1193 strcpy(instr, tmp); /* safe, because tmp will always be the same size or smaller than instr */
1194 *location = instr;
1195 } else { /* Assume it's just a name. */
1196 *location = NULL;
1197 name_start = ast_strip_quoted(instr, "\"", "\"");
1198 }
1199 }
1200
1201 if (name_start) {
1202 ast_unescape_quoted(name_start);
1203 }
1204 *name = name_start;
1205 return 0;
1206}
1207
1208static int __ast_callerid_generate(unsigned char *buf, const char *name, const char *number,
1209 const char *ddn, int redirecting, int pres, int qualifier, int format, int callwaiting, struct ast_format *codec, const char *tz)
1210{
1211 int flags = 0;
1212
1213 ast_debug(1, "Caller ID Type %s: Number: %s, Name: %s, DDN: %s, Redirecting Reason: %s, Pres: %s, Qualifier: %s, Format: %s\n",
1214 callwaiting ? "II" : "I", number, name, ddn, ast_redirecting_reason_describe(redirecting),
1215 ast_named_caller_presentation(pres), qualifier ? "LDC" : "None", format == CID_TYPE_MDMF ? "MDMF" : "SDMF");
1216
1217 if (ast_strlen_zero(name))
1218 name = NULL;
1220 number = NULL;
1221
1222 if (pres & AST_PRES_RESTRICTED) {
1223 flags |= CID_PRIVATE_NUMBER;
1224 flags |= CID_PRIVATE_NAME;
1225 } else if (pres & AST_PRES_UNAVAILABLE) {
1226 flags |= CID_UNKNOWN_NUMBER;
1227 flags |= CID_UNKNOWN_NAME;
1228 }
1229
1230 if (qualifier) {
1231 flags |= CID_QUALIFIER;
1232 }
1233
1234 return callerid_full_tz_generate(buf, number, name, ddn, redirecting, flags, format, callwaiting, codec, tz);
1235}
1236
1237int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec)
1238{
1239 return __ast_callerid_generate(buf, name, number, "", -1, 0, 0, CID_TYPE_MDMF, 0, codec, NULL);
1240}
1241
1242int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec)
1243{
1244 return __ast_callerid_generate(buf, name, number, "", -1, 0, 0, CID_TYPE_MDMF, 1, codec, NULL);
1245}
1246
1247int ast_callerid_full_generate(unsigned char *buf, const char *name, const char *number,
1248 const char *ddn, int redirecting, int pres, int qualifier, int format, struct ast_format *codec)
1249{
1250 return __ast_callerid_generate(buf, name, number, ddn, redirecting, pres, qualifier, format, 0, codec, NULL);
1251}
1252
1253int ast_callerid_callwaiting_full_generate(unsigned char *buf, const char *name, const char *number,
1254 const char *ddn, int redirecting, int pres, int qualifier, struct ast_format *codec)
1255{
1256 /* Type II Caller ID (CWCID) only uses MDMF, so format isn't an argument */
1257 return __ast_callerid_generate(buf, name, number, ddn, redirecting, pres, qualifier, CID_TYPE_MDMF, 1, codec, NULL);
1258}
1259
1260int ast_callerid_full_tz_generate(unsigned char *buf, const char *name, const char *number,
1261 const char *ddn, int redirecting, int pres, int qualifier, int format, struct ast_format *codec, const char *tz)
1262{
1263 return __ast_callerid_generate(buf, name, number, ddn, redirecting, pres, qualifier, format, 0, codec, tz);
1264}
1265
1266int ast_callerid_callwaiting_full_tz_generate(unsigned char *buf, const char *name, const char *number,
1267 const char *ddn, int redirecting, int pres, int qualifier, struct ast_format *codec, const char *tz)
1268{
1269 /* Type II Caller ID (CWCID) only uses MDMF, so format isn't an argument */
1270 return __ast_callerid_generate(buf, name, number, ddn, redirecting, pres, qualifier, CID_TYPE_MDMF, 1, codec, tz);
1271}
1272
1273char *ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
1274{
1275 if (!unknown)
1276 unknown = "<unknown>";
1277 if (name && num) {
1278 char name_buf[128];
1279
1280 ast_escape_quoted(name, name_buf, sizeof(name_buf));
1281 snprintf(buf, bufsiz, "\"%s\" <%s>", name_buf, num);
1282 } else if (name) {
1283 ast_copy_string(buf, name, bufsiz);
1284 } else if (num) {
1285 ast_copy_string(buf, num, bufsiz);
1286 } else {
1287 ast_copy_string(buf, unknown, bufsiz);
1288 }
1289 return buf;
1290}
1291
1292int ast_callerid_split(const char *buf, char *name, int namelen, char *num, int numlen)
1293{
1294 char *tmp;
1295 char *l = NULL, *n = NULL;
1296
1297 tmp = ast_strdupa(buf);
1298 ast_callerid_parse(tmp, &n, &l);
1299 if (n)
1300 ast_copy_string(name, n, namelen);
1301 else
1302 name[0] = '\0';
1303 if (l) {
1305 ast_copy_string(num, l, numlen);
1306 } else
1307 num[0] = '\0';
1308 return 0;
1309}
1310
1313 const char *name;
1314 const char *description;
1315};
1316
1317/*! \brief Translation table for Caller ID Presentation settings */
1318static const struct ast_value_translation pres_types[] = {
1319/* *INDENT-OFF* */
1320 { AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_UNSCREENED, "allowed_not_screened", "Presentation Allowed, Not Screened" },
1321 { AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", "Presentation Allowed, Passed Screen" },
1322 { AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", "Presentation Allowed, Failed Screen" },
1323 { AST_PRES_ALLOWED | AST_PRES_NETWORK_NUMBER, "allowed", "Presentation Allowed, Network Number" },
1324
1325 { AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED, "prohib_not_screened", "Presentation Prohibited, Not Screened" },
1326 { AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", "Presentation Prohibited, Passed Screen" },
1327 { AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", "Presentation Prohibited, Failed Screen" },
1328 { AST_PRES_RESTRICTED | AST_PRES_NETWORK_NUMBER, "prohib", "Presentation Prohibited, Network Number" },
1329
1330 { AST_PRES_UNAVAILABLE | AST_PRES_NETWORK_NUMBER, "unavailable", "Number Unavailable" }, /* Default name to value conversion. */
1331 { AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_UNSCREENED, "unavailable", "Number Unavailable" },
1332 { AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_FAILED_SCREEN, "unavailable", "Number Unavailable" },
1333 { AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_PASSED_SCREEN, "unavailable", "Number Unavailable" },
1334/* *INDENT-ON* */
1335};
1336
1337/*!
1338 * \brief Convert caller ID text code to value (used in config file parsing)
1339 * \param data text string from config file
1340 * \retval value AST_PRES_ from callerid.h
1341 * \retval -1 if not in table
1342 */
1344{
1345 int index;
1346 if (!data) {
1347 return -1;
1348 }
1349
1350 for (index = 0; index < ARRAY_LEN(pres_types); ++index) {
1351 if (!strcasecmp(pres_types[index].name, data)) {
1352 return pres_types[index].value;
1353 }
1354 }
1355
1356 return -1;
1357}
1358
1359/*!
1360 * \brief Convert caller ID pres value to explanatory string
1361 * \param data AST_PRES_ value from callerid.h
1362 * \return string for human presentation
1363 */
1365{
1366 int index;
1367
1368 for (index = 0; index < ARRAY_LEN(pres_types); ++index) {
1369 if (pres_types[index].value == data) {
1370 return pres_types[index].description;
1371 }
1372 }
1373
1374 return "unknown";
1375}
1376
1377/*!
1378 * \brief Convert caller ID pres value to text code
1379 * \param data AST_PRES_ value from callerid.h
1380 * \return string for config file
1381 */
1383{
1384 int index;
1385
1386 for (index = 0; index < ARRAY_LEN(pres_types); ++index) {
1387 if (pres_types[index].value == data) {
1388 return pres_types[index].name;
1389 }
1390 }
1391
1392 return "unknown";
1393}
1394
1395/*! \brief Translation table for redirecting reason settings */
1397/* *INDENT-OFF* */
1398 { AST_REDIRECTING_REASON_UNKNOWN, "unknown", "Unknown" },
1399 { AST_REDIRECTING_REASON_USER_BUSY, "cfb", "Call Forwarding Busy" },
1400 { AST_REDIRECTING_REASON_NO_ANSWER, "cfnr", "Call Forwarding No Reply" },
1401 { AST_REDIRECTING_REASON_UNAVAILABLE, "unavailable", "Callee is Unavailable" },
1402 { AST_REDIRECTING_REASON_UNCONDITIONAL, "cfu", "Call Forwarding Unconditional" },
1403 { AST_REDIRECTING_REASON_TIME_OF_DAY, "time_of_day", "Time of Day" },
1404 { AST_REDIRECTING_REASON_DO_NOT_DISTURB, "dnd", "Do Not Disturb" },
1405 { AST_REDIRECTING_REASON_DEFLECTION, "deflection", "Call Deflection" },
1406 { AST_REDIRECTING_REASON_FOLLOW_ME, "follow_me", "Follow Me" },
1407 { AST_REDIRECTING_REASON_OUT_OF_ORDER, "out_of_order", "Called DTE Out-Of-Order" },
1408 { AST_REDIRECTING_REASON_AWAY, "away", "Callee is Away" },
1409 { AST_REDIRECTING_REASON_CALL_FWD_DTE, "cf_dte", "Call Forwarding By The Called DTE" },
1410 { AST_REDIRECTING_REASON_SEND_TO_VM, "send_to_vm", "Call is being redirected to user's voicemail" },
1411
1412 /* Convenience SIP aliases. Alias descriptions are not used. */
1413 { AST_REDIRECTING_REASON_USER_BUSY, "user-busy" },
1414 { AST_REDIRECTING_REASON_NO_ANSWER, "no-answer" },
1415 { AST_REDIRECTING_REASON_UNCONDITIONAL, "unconditional" },
1416 { AST_REDIRECTING_REASON_TIME_OF_DAY, "time-of-day" },
1417 { AST_REDIRECTING_REASON_DO_NOT_DISTURB, "do-not-disturb" },
1418 { AST_REDIRECTING_REASON_FOLLOW_ME, "follow-me" },
1419 { AST_REDIRECTING_REASON_OUT_OF_ORDER, "out-of-service" },
1420/* *INDENT-ON* */
1421};
1422
1423int ast_redirecting_reason_parse(const char *data)
1424{
1425 int index;
1426
1427 for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
1428 if (!strcasecmp(redirecting_reason_types[index].name, data)) {
1429 return redirecting_reason_types[index].value;
1430 }
1431 }
1432
1433 return -1;
1434}
1435
1437{
1438 int index;
1439
1440 for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
1441 if (redirecting_reason_types[index].value == data) {
1442 return redirecting_reason_types[index].description ?: "Redirecting reason alias-bug";
1443 }
1444 }
1445
1446 return "not-known";
1447}
1448
1450{
1451 int index;
1452
1453 if (!ast_strlen_zero(data->str)) {
1454 /* Use this string if it has been set. Otherwise, use the table. */
1455 return data->str;
1456 }
1457
1458 for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
1459 if (redirecting_reason_types[index].value == data->code) {
1460 return redirecting_reason_types[index].name;
1461 }
1462 }
1463
1464 return "not-known";
1465}
1466
1467/*! \brief Translation table for connected line update source settings */
1469/* *INDENT-OFF* */
1470 { AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN, "unknown", "Unknown" },
1471 { AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, "answer", "Normal Call Answering" },
1472 { AST_CONNECTED_LINE_UPDATE_SOURCE_DIVERSION, "diversion", "Call Diversion (Deprecated, use REDIRECTING)" },
1473 { AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, "transfer_active", "Call Transfer(Active)" },
1474 { AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, "transfer", "Call Transfer(Active)" },/* Old name must come after new name. */
1475 { AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING, "transfer_alerting", "Call Transfer(Alerting)" }
1476/* *INDENT-ON* */
1477};
1478
1480{
1481 int index;
1482
1483 for (index = 0; index < ARRAY_LEN(connected_line_source_types); ++index) {
1484 if (!strcasecmp(connected_line_source_types[index].name, data)) {
1485 return connected_line_source_types[index].value;
1486 }
1487 }
1488
1489 return -1;
1490}
1491
1493{
1494 int index;
1495
1496 for (index = 0; index < ARRAY_LEN(connected_line_source_types); ++index) {
1497 if (connected_line_source_types[index].value == data) {
1499 }
1500 }
1501
1502 return "not-known";
1503}
1504
1506{
1507 int index;
1508
1509 for (index = 0; index < ARRAY_LEN(connected_line_source_types); ++index) {
1510 if (connected_line_source_types[index].value == data) {
1511 return connected_line_source_types[index].name;
1512 }
1513 }
1514
1515 return "not-known";
1516}
1517
1518/*! \brief Translation table for ast_party_name char-set settings */
1520/* *INDENT-OFF* */
1521 { AST_PARTY_CHAR_SET_UNKNOWN, "unknown", "Unknown" },
1522 { AST_PARTY_CHAR_SET_ISO8859_1, "iso8859-1", "ISO8859-1" },
1523 { AST_PARTY_CHAR_SET_WITHDRAWN, "withdrawn", "Withdrawn" },
1524 { AST_PARTY_CHAR_SET_ISO8859_2, "iso8859-2", "ISO8859-2" },
1525 { AST_PARTY_CHAR_SET_ISO8859_3, "iso8859-3", "ISO8859-3" },
1526 { AST_PARTY_CHAR_SET_ISO8859_4, "iso8859-4", "ISO8859-4" },
1527 { AST_PARTY_CHAR_SET_ISO8859_5, "iso8859-5", "ISO8859-5" },
1528 { AST_PARTY_CHAR_SET_ISO8859_7, "iso8859-7", "ISO8859-7" },
1529 { AST_PARTY_CHAR_SET_ISO10646_BMPSTRING, "bmp", "ISO10646 Bmp String" },
1530 { AST_PARTY_CHAR_SET_ISO10646_UTF_8STRING, "utf8", "ISO10646 UTF-8 String" },
1531/* *INDENT-ON* */
1532};
1533
1534int ast_party_name_charset_parse(const char *data)
1535{
1536 int index;
1537
1538 for (index = 0; index < ARRAY_LEN(party_name_charset_tbl); ++index) {
1539 if (!strcasecmp(party_name_charset_tbl[index].name, data)) {
1540 return party_name_charset_tbl[index].value;
1541 }
1542 }
1543
1544 return -1;
1545}
1546
1548{
1549 int index;
1550
1551 for (index = 0; index < ARRAY_LEN(party_name_charset_tbl); ++index) {
1552 if (party_name_charset_tbl[index].value == data) {
1553 return party_name_charset_tbl[index].description;
1554 }
1555 }
1556
1557 return "not-known";
1558}
1559
1560const char *ast_party_name_charset_str(int data)
1561{
1562 int index;
1563
1564 for (index = 0; index < ARRAY_LEN(party_name_charset_tbl); ++index) {
1565 if (party_name_charset_tbl[index].value == data) {
1566 return party_name_charset_tbl[index].name;
1567 }
1568 }
1569
1570 return "not-known";
1571}
A-Law to Signed linear conversion.
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
static int tmp()
Definition: bt_open.c:389
char * ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
Definition: callerid.c:1273
static const struct ast_value_translation connected_line_source_types[]
Translation table for connected line update source settings.
Definition: callerid.c:1468
int ast_callerid_callwaiting_full_generate(unsigned char *buf, const char *name, const char *number, const char *ddn, int redirecting, int pres, int qualifier, struct ast_format *codec)
Generate Caller-ID spill but in a format suitable for Call Waiting(tm)'s Caller*ID(tm)
Definition: callerid.c:1253
int ast_parse_caller_presentation(const char *data)
Convert caller ID text code to value (used in config file parsing)
Definition: callerid.c:1343
const char * ast_connected_line_source_describe(int data)
Convert connected line update source value to explanatory string.
Definition: callerid.c:1492
#define SAS_FREQ
Definition: callerid.c:72
int ast_callerid_parse(char *input_str, char **name, char **location)
Destructively parse inbuf into name and location (or number)
Definition: callerid.c:1162
int ast_callerid_full_generate(unsigned char *buf, const char *name, const char *number, const char *ddn, int redirecting, int pres, int qualifier, int format, struct ast_format *codec)
Generate Caller-ID spill from the "callerid" field of asterisk (in e-mail address like format)
Definition: callerid.c:1247
float casdi1
Definition: callerid.c:68
static int callerid_genmsg(char *msg, int size, const char *number, const char *name, int flags, int format, const char *ddn, int redirecting, const char *tz)
Definition: callerid.c:838
static const struct ast_value_translation party_name_charset_tbl[]
Translation table for ast_party_name char-set settings.
Definition: callerid.c:1519
float cid_dr[4]
Definition: callerid.c:65
int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, struct ast_format *codec, const char *name, const char *number, int flags)
Generate message waiting indicator.
Definition: callerid.c:952
float sasdr
Definition: callerid.c:67
static unsigned short calc_crc(unsigned short crc, unsigned char data)
Definition: callerid.c:293
static const struct ast_value_translation redirecting_reason_types[]
Translation table for redirecting reason settings.
Definition: callerid.c:1396
int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, struct ast_format *codec)
Generates a CallerID FSK stream in ulaw format suitable for transmission.
Definition: callerid.c:1039
void callerid_free(struct callerid_state *cid)
This function frees callerid_state cid.
Definition: callerid.c:833
void callerid_get_with_redirecting(struct callerid_state *cid, char **name, char **number, int *flags, int *redirecting)
Extract info out of callerID state machine. Flags are listed above.
Definition: callerid.c:189
const char * ast_describe_caller_presentation(int data)
Convert caller ID pres value to explanatory string.
Definition: callerid.c:1364
int ast_gen_cas(unsigned char *outbuf, int sendsas, int len, struct ast_format *codec)
Generate a CAS (CPE Alert Signal) tone for 'n' samples.
Definition: callerid.c:271
const char * ast_party_name_charset_describe(int data)
Convert ast_party_name.char_set value to explanatory string.
Definition: callerid.c:1547
static void gen_tone(unsigned char *buf, int len, struct ast_format *codec, float ddr1, float ddi1, float *cr1, float *ci1)
Definition: callerid.c:100
const char * ast_redirecting_reason_name(const struct ast_party_redirecting_reason *data)
Convert redirecting reason value to text code.
Definition: callerid.c:1449
int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int len, struct ast_format *codec)
Read samples into the state machine.
Definition: callerid.c:316
static int __ast_callerid_generate(unsigned char *buf, const char *name, const char *number, const char *ddn, int redirecting, int pres, int qualifier, int format, int callwaiting, struct ast_format *codec, const char *tz)
Definition: callerid.c:1208
#define CAS_FREQ2
Definition: callerid.c:74
void ast_shrink_phone_number(char *n)
Clean up phone string.
Definition: callerid.c:1101
static int ast_is_valid_string(const char *exten, const char *valid)
Checks if phone number consists of valid characters.
Definition: callerid.c:1140
int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec)
Generate Caller-ID spill but in a format suitable for Call Waiting(tm)'s Caller*ID(tm)
Definition: callerid.c:1242
static 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)
Definition: callerid.c:78
const char * ast_party_name_charset_str(int data)
Convert ast_party_name.char_set value to text code.
Definition: callerid.c:1560
#define CAS_FREQ1
Definition: callerid.c:73
struct callerid_state * callerid_new(int cid_signalling)
Create a callerID state machine.
Definition: callerid.c:130
void callerid_init(void)
Initialize stuff for inverse FFT.
Definition: callerid.c:116
#define CALLERID_MARK
Definition: callerid.c:71
static const char * mdmf_param_name(int param)
Definition: callerid.c:554
int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, struct ast_format *codec)
Read samples into the state machine.
Definition: callerid.c:570
int callerid_full_generate(unsigned char *buf, const char *number, const char *name, const char *ddn, int redirecting, int flags, int format, int callwaiting, struct ast_format *codec)
Generates a CallerID FSK stream in ulaw format suitable for transmission.
Definition: callerid.c:1044
int ast_party_name_charset_parse(const char *data)
Convert ast_party_name.char_set text code to value (used in config file parsing)
Definition: callerid.c:1534
void callerid_get_dtmf(char *cidstring, char *number, int *flags)
Get and parse DTMF-based callerid.
Definition: callerid.c:211
int ast_isphonenumber(const char *n)
Check if a string consists only of digits and + #.
Definition: callerid.c:1152
float casdi2
Definition: callerid.c:68
const char * ast_redirecting_reason_describe(int data)
Convert redirecting reason value to explanatory string.
Definition: callerid.c:1436
int ast_redirecting_reason_parse(const char *data)
Convert redirecting reason text code to value (used in config file parsing)
Definition: callerid.c:1423
float casdr2
Definition: callerid.c:68
const char * ast_connected_line_source_name(int data)
Convert connected line update source value to text code.
Definition: callerid.c:1505
const char * ast_named_caller_presentation(int data)
Convert caller ID pres value to text code.
Definition: callerid.c:1382
float casdr1
Definition: callerid.c:68
static const struct ast_value_translation pres_types[]
Translation table for Caller ID Presentation settings.
Definition: callerid.c:1318
int ast_connected_line_source_parse(const char *data)
Convert connected line update source text code to value (used in config file parsing)
Definition: callerid.c:1479
int ast_callerid_full_tz_generate(unsigned char *buf, const char *name, const char *number, const char *ddn, int redirecting, int pres, int qualifier, int format, struct ast_format *codec, const char *tz)
Generate Caller-ID spill from the "callerid" field of asterisk (in e-mail address like format)
Definition: callerid.c:1260
int ast_callerid_split(const char *buf, char *name, int namelen, char *num, int numlen)
Definition: callerid.c:1292
#define CALLERID_SPACE
Definition: callerid.c:70
float cid_di[4]
Definition: callerid.c:65
float sasdi
Definition: callerid.c:67
int callerid_full_tz_generate(unsigned char *buf, const char *number, const char *name, const char *ddn, int redirecting, int flags, int format, int callwaiting, struct ast_format *codec, const char *tz)
Generates a CallerID FSK stream in ulaw format suitable for transmission.
Definition: callerid.c:1051
int ast_is_shrinkable_phonenumber(const char *exten)
Check if a string consists only of digits and + # ( ) - . (meaning it can be cleaned with ast_shrink_...
Definition: callerid.c:1157
float clidsb
Definition: callerid.c:66
int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec)
Generate Caller-ID spill from the "callerid" field of asterisk (in e-mail address like format)
Definition: callerid.c:1237
int ast_callerid_callwaiting_full_tz_generate(unsigned char *buf, const char *name, const char *number, const char *ddn, int redirecting, int pres, int qualifier, struct ast_format *codec, const char *tz)
Generate Caller-ID spill but in a format suitable for Call Waiting(tm)'s Caller*ID(tm)
Definition: callerid.c:1266
void callerid_get(struct callerid_state *cid, char **name, char **number, int *flags)
Extract info out of callerID state machine. Flags are listed above.
Definition: callerid.c:205
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
#define PUT_CLID(byte)
Definition: callerid.h:412
#define CID_TYPE_MDMF
Definition: callerid.h:75
#define CID_UNKNOWN_NUMBER
Definition: callerid.h:55
#define CID_TYPE_SDMF
Definition: callerid.h:73
#define AST_PRES_USER_NUMBER_UNSCREENED
Definition: callerid.h:426
#define AST_PRES_UNAVAILABLE
Definition: callerid.h:434
#define CID_UNKNOWN_NAME
Definition: callerid.h:54
#define PUT_BYTE(a)
Definition: callerid.h:386
#define AST_PRES_USER_NUMBER_PASSED_SCREEN
Definition: callerid.h:427
#define AST_PRES_RESTRICTED
Definition: callerid.h:433
#define AST_PRES_ALLOWED
Definition: callerid.h:432
#define CID_MWI_TYPE_MDMF
Definition: callerid.h:81
@ AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER
Definition: callerid.h:558
@ AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN
Definition: callerid.h:552
@ AST_CONNECTED_LINE_UPDATE_SOURCE_DIVERSION
Definition: callerid.h:556
@ AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING
Definition: callerid.h:560
@ AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER
Definition: callerid.h:554
#define AST_PRES_NETWORK_NUMBER
Definition: callerid.h:429
#define CID_PRIVATE_NAME
Definition: callerid.h:52
#define PUT_CLID_MARKMS
Definition: callerid.h:397
#define CID_NOMSGWAITING
Definition: callerid.h:57
@ AST_REDIRECTING_REASON_AWAY
Definition: callerid.h:509
@ AST_REDIRECTING_REASON_UNKNOWN
Definition: callerid.h:499
@ AST_REDIRECTING_REASON_SEND_TO_VM
Definition: callerid.h:511
@ AST_REDIRECTING_REASON_NO_ANSWER
Definition: callerid.h:501
@ AST_REDIRECTING_REASON_DO_NOT_DISTURB
Definition: callerid.h:505
@ AST_REDIRECTING_REASON_FOLLOW_ME
Definition: callerid.h:507
@ AST_REDIRECTING_REASON_DEFLECTION
Definition: callerid.h:506
@ AST_REDIRECTING_REASON_UNAVAILABLE
Definition: callerid.h:502
@ AST_REDIRECTING_REASON_UNCONDITIONAL
Definition: callerid.h:503
@ AST_REDIRECTING_REASON_CALL_FWD_DTE
Definition: callerid.h:510
@ AST_REDIRECTING_REASON_OUT_OF_ORDER
Definition: callerid.h:508
@ AST_REDIRECTING_REASON_TIME_OF_DAY
Definition: callerid.h:504
@ AST_REDIRECTING_REASON_USER_BUSY
Definition: callerid.h:500
#define CID_PRIVATE_NUMBER
Definition: callerid.h:53
#define CID_MSGWAITING
Definition: callerid.h:56
#define CID_MWI_TYPE_MDMF_FULL
Definition: callerid.h:83
#define AST_PRES_USER_NUMBER_FAILED_SCREEN
Definition: callerid.h:428
#define AST_XLAW(a)
Definition: callerid.h:86
#define CID_QUALIFIER
Definition: callerid.h:58
#define AST_LIN2X(a)
Definition: callerid.h:85
static char * tz
Definition: cdr_pgsql.c:71
unsigned int cos
Definition: chan_iax2.c:356
static const char type[]
Definition: chan_ooh323.c:109
General Asterisk PBX channel definitions.
@ AST_PARTY_CHAR_SET_UNKNOWN
Definition: channel.h:243
@ AST_PARTY_CHAR_SET_ISO8859_4
Definition: channel.h:248
@ AST_PARTY_CHAR_SET_WITHDRAWN
Definition: channel.h:245
@ AST_PARTY_CHAR_SET_ISO8859_5
Definition: channel.h:249
@ AST_PARTY_CHAR_SET_ISO8859_7
Definition: channel.h:250
@ AST_PARTY_CHAR_SET_ISO8859_2
Definition: channel.h:246
@ AST_PARTY_CHAR_SET_ISO8859_1
Definition: channel.h:244
@ AST_PARTY_CHAR_SET_ISO10646_UTF_8STRING
Definition: channel.h:252
@ AST_PARTY_CHAR_SET_ISO10646_BMPSTRING
Definition: channel.h:251
@ AST_PARTY_CHAR_SET_ISO8859_3
Definition: channel.h:247
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
Media Format Cache API.
static const char name[]
Definition: format_mp3.c:68
FSK Modem Support.
int fsk_serial(fsk_data *fskd, short *buffer, int *len, int *outbyte)
Retrieve a serial byte into outbyte. Buffer is a pointer into a series of shorts and len records the ...
int fskmodem_init(fsk_data *fskd)
Definition: fskmodem_int.c:195
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Asterisk internal frame definitions.
#define DEBUG_ATLEAST(level)
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_NOTICE
#define LOG_WARNING
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1739
static char org[80]
Definition: pbx_dundi.c:202
#define NULL
Definition: resample.c:96
#define M_PI
Definition: resample.c:83
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
Definition: utils.c:1818
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
Definition of a media format.
Definition: format.c:43
Redirecting reason information.
Definition: channel.h:501
int code
enum AST_REDIRECTING_REASON value for redirection
Definition: channel.h:510
char * str
a string value for the redirecting reason
Definition: channel.h:507
int tm_mday
Definition: localtime.h:39
int tm_hour
Definition: localtime.h:38
int tm_min
Definition: localtime.h:37
int tm_mon
Definition: localtime.h:40
const char * description
Definition: callerid.c:1314
const char * name
Definition: callerid.c:1313
unsigned short crc
Definition: callerid.c:61
char rawdata[256]
Definition: callerid.c:47
int redirecting
Definition: callerid.c:56
char number[64]
Definition: callerid.c:54
fsk_data fskd
Definition: callerid.c:46
short oldstuff[160]
Definition: callerid.c:48
char name[64]
Definition: callerid.c:53
int f_mark_idx
float nstop
int pllispb2
Definition: fskmodem_int.h:61
int instop
Definition: fskmodem_int.h:46
int pllispb
Definition: fskmodem_int.h:59
int pllids
Definition: fskmodem_int.h:60
int f_space_idx
Number structure.
Definition: app_followme.c:154
int value
Definition: syslog.c:37
static struct ast_codec unknown
static struct test_val b
Time-related functions and macros.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
u-Law to Signed linear conversion
Utility functions.
void ast_unescape_quoted(char *quote_str)
Unescape quotes in a string.
Definition: utils.c:842
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
Definition: utils.c:781
#define ARRAY_LEN(a)
Definition: utils.h:666