2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
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.
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.
21 * \brief CallerID Generation support
23 * \author Mark Spencer <markster@digium.com>
28 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
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/logger.h"
44 #include "asterisk/fskmodem.h"
45 #include "asterisk/options.h"
46 #include "asterisk/utils.h"
48 struct callerid_state
{
67 float cid_dr
[4], cid_di
[4];
68 float clidsb
= 8000.0 / 1200.0;
70 float casdr1
, casdi1
, casdr2
, casdi2
;
72 #define CALLERID_SPACE 2200.0 /*!< 2200 hz for "0" */
73 #define CALLERID_MARK 1200.0 /*!< 1200 hz for "1" */
74 #define SAS_FREQ 440.0
75 #define CAS_FREQ1 2130.0
76 #define CAS_FREQ2 2750.0
78 #define AST_CALLERID_UNKNOWN "<unknown>"
80 static inline void gen_tones(unsigned char *buf
, int len
, int codec
, float ddr1
, float ddi1
, float ddr2
, float ddi2
, float *cr1
, float *ci1
, float *cr2
, float *ci2
)
85 t
= *cr1
* ddr1
- *ci1
* ddi1
;
86 *ci1
= *cr1
* ddi1
+ *ci1
* ddr1
;
88 t
= 2.0 - (*cr1
* *cr1
+ *ci1
* *ci1
);
92 t
= *cr2
* ddr2
- *ci2
* ddi2
;
93 *ci2
= *cr2
* ddi2
+ *ci2
* ddr2
;
95 t
= 2.0 - (*cr2
* *cr2
+ *ci2
* *ci2
);
98 buf
[x
] = AST_LIN2X((*cr1
+ *cr2
) * 2048.0);
102 static inline void gen_tone(unsigned char *buf
, int len
, int codec
, float ddr1
, float ddi1
, float *cr1
, float *ci1
)
106 for (x
=0;x
<len
;x
++) {
107 t
= *cr1
* ddr1
- *ci1
* ddi1
;
108 *ci1
= *cr1
* ddi1
+ *ci1
* ddr1
;
110 t
= 2.0 - (*cr1
* *cr1
+ *ci1
* *ci1
);
113 buf
[x
] = AST_LIN2X(*cr1
* 8192.0);
117 /*! \brief Initialize stuff for inverse FFT */
118 void callerid_init(void)
120 cid_dr
[0] = cos(CALLERID_SPACE
* 2.0 * M_PI
/ 8000.0);
121 cid_di
[0] = sin(CALLERID_SPACE
* 2.0 * M_PI
/ 8000.0);
122 cid_dr
[1] = cos(CALLERID_MARK
* 2.0 * M_PI
/ 8000.0);
123 cid_di
[1] = sin(CALLERID_MARK
* 2.0 * M_PI
/ 8000.0);
124 sasdr
= cos(SAS_FREQ
* 2.0 * M_PI
/ 8000.0);
125 sasdi
= sin(SAS_FREQ
* 2.0 * M_PI
/ 8000.0);
126 casdr1
= cos(CAS_FREQ1
* 2.0 * M_PI
/ 8000.0);
127 casdi1
= sin(CAS_FREQ1
* 2.0 * M_PI
/ 8000.0);
128 casdr2
= cos(CAS_FREQ2
* 2.0 * M_PI
/ 8000.0);
129 casdi2
= sin(CAS_FREQ2
* 2.0 * M_PI
/ 8000.0);
132 struct callerid_state
*callerid_new(int cid_signalling
)
134 struct callerid_state
*cid
;
136 if ((cid
= ast_calloc(1, sizeof(*cid
)))) {
137 cid
->fskd
.spb
= 7.0; /* 1200 baud */
138 /* cid->fskd.hdlc = 0; */ /* Async */
139 cid
->fskd
.nbit
= 8; /* 8 bits */
140 cid
->fskd
.nstop
= 1.0; /* 1 stop bit */
141 /* cid->fskd.paridad = 0; */ /* No parity */
142 cid
->fskd
.bw
= 1; /* Filter 800 Hz */
143 if (cid_signalling
== 2) { /* v23 signalling */
144 cid
->fskd
.f_mark_idx
= 4; /* 1300 Hz */
145 cid
->fskd
.f_space_idx
= 5; /* 2100 Hz */
146 } else { /* Bell 202 signalling as default */
147 cid
->fskd
.f_mark_idx
= 2; /* 1200 Hz */
148 cid
->fskd
.f_space_idx
= 3; /* 2200 Hz */
150 /* cid->fskd.pcola = 0; */ /* No clue */
151 /* cid->fskd.cont = 0.0; */ /* Digital PLL reset */
152 /* cid->fskd.x0 = 0.0; */
153 /* cid->fskd.state = 0; */
154 cid
->flags
= CID_UNKNOWN_NAME
| CID_UNKNOWN_NUMBER
;
161 void callerid_get(struct callerid_state
*cid
, char **name
, char **number
, int *flags
)
164 if (cid
->flags
& (CID_UNKNOWN_NAME
| CID_PRIVATE_NUMBER
))
168 if (cid
->flags
& (CID_UNKNOWN_NUMBER
| CID_PRIVATE_NUMBER
))
171 *number
= cid
->number
;
174 void callerid_get_dtmf(char *cidstring
, char *number
, int *flags
)
179 /* "Clear" the number-buffer. */
182 if (strlen(cidstring
) < 2) {
183 ast_log(LOG_DEBUG
, "No cid detected\n");
184 *flags
= CID_UNKNOWN_NUMBER
;
188 /* Detect protocol and special types */
189 if (cidstring
[0] == 'B') {
190 /* Handle special codes */
191 code
= atoi(&cidstring
[1]);
193 *flags
= CID_UNKNOWN_NUMBER
;
195 *flags
= CID_PRIVATE_NUMBER
;
197 ast_log(LOG_DEBUG
, "Unknown DTMF code %d\n", code
);
198 } else if (cidstring
[0] == 'D' && cidstring
[2] == '#') {
199 /* .DK special code */
200 if (cidstring
[1] == '1')
201 *flags
= CID_PRIVATE_NUMBER
;
202 if (cidstring
[1] == '2' || cidstring
[1] == '3')
203 *flags
= CID_UNKNOWN_NUMBER
;
204 } else if (cidstring
[0] == 'D' || cidstring
[0] == 'A') {
205 /* "Standard" callerid */
206 for (i
= 1; i
< strlen(cidstring
); i
++ ) {
207 if (cidstring
[i
] == 'C' || cidstring
[i
] == '#')
209 if (isdigit(cidstring
[i
]))
210 number
[i
-1] = cidstring
[i
];
212 ast_log(LOG_DEBUG
, "Unknown CID digit '%c'\n",
216 } else if (isdigit(cidstring
[0])) {
217 /* It begins with a digit, so we parse it as a number and hope
219 ast_log(LOG_WARNING
, "Couldn't detect start-character. CID "
220 "parsing might be unreliable\n");
221 for (i
= 0; i
< strlen(cidstring
); i
++) {
222 if (isdigit(cidstring
[i
]))
223 number
[i
] = cidstring
[i
];
229 ast_log(LOG_DEBUG
, "Unknown CID protocol, start digit '%c'\n",
231 *flags
= CID_UNKNOWN_NUMBER
;
235 int ast_gen_cas(unsigned char *outbuf
, int sendsas
, int len
, int codec
)
246 gen_tone(outbuf
, saslen
, codec
, sasdr
, sasdi
, &cr1
, &ci1
);
252 gen_tones(outbuf
+ pos
, len
, codec
, casdr1
, casdi1
, casdr2
, casdi2
, &cr1
, &ci1
, &cr2
, &ci2
);
256 static unsigned short calc_crc(unsigned short crc
, unsigned char data
)
258 unsigned int i
, j
, org
, dst
;
262 for (i
=0; i
< CHAR_BIT
; i
++) {
269 data
= (unsigned char)dst
;
270 crc
^= (unsigned int)data
<< (16 - CHAR_BIT
);
271 for ( j
=0; j
<CHAR_BIT
; j
++ ) {
273 crc
= (crc
<< 1) ^ 0x1021U
;
280 int callerid_feed_jp(struct callerid_state
*cid
, unsigned char *ubuf
, int len
, int codec
)
291 if (!(buf
= ast_calloc(1, 2 * len
+ cid
->oldlen
))) {
296 memcpy(buf
, cid
->oldstuff
, cid
->oldlen
);
297 mylen
+= cid
->oldlen
/2;
300 buf
[x
+cid
->oldlen
/2] = AST_XLAW(ubuf
[x
]);
302 while (mylen
>= 160) {
305 res
= fsk_serie(&cid
->fskd
, buf
, &mylen
, &b
);
308 ast_log(LOG_ERROR
, "fsk_serie made mylen < 0 (%d)\n", mylen
);
312 buf
+= (olen
- mylen
);
315 ast_log(LOG_NOTICE
, "fsk_serie failed\n");
324 /* crc checksum calculation */
325 if ( cid
->sawflag
> 1 ) {
326 cid
->crc
= calc_crc(cid
->crc
, (unsigned char)b2
);
329 /* Ignore invalid bytes */
334 /* skip DLE if needed */
335 if ( cid
->sawflag
> 0 ) {
336 if ( cid
->sawflag
!= 5 && cid
->skipflag
== 0 && b
== 0x10 ) {
341 if ( cid
->skipflag
== 1 ) {
345 /* caller id retrieval */
346 switch(cid
->sawflag
) {
369 case 4: /* SERVICE TYPE */
374 case 5: /* Frame Length */
377 case 6: /* NUMBER TYPE */
380 cid
->rawdata
[cid
->pos
++] = b
;
382 case 7: /* NUMBER LENGTH */
385 if ( (cid
->len
+2) >= sizeof( cid
->rawdata
) ) {
386 ast_log(LOG_WARNING
, "too long caller id string\n" ) ;
389 cid
->rawdata
[cid
->pos
++] = b
;
391 case 8: /* Retrieve message */
392 cid
->rawdata
[cid
->pos
++] = b
;
395 cid
->rawdata
[cid
->pos
] = '\0';
402 case 10: /* CRC Checksum 1 */
405 case 11: /* CRC Checksum 2 */
407 if ( cid
->crc
!= 0 ) {
408 ast_log(LOG_WARNING
, "crc checksum error\n" ) ;
411 /* extract caller id data */
412 for (x
=0; x
<cid
->pos
; ) {
413 switch (cid
->rawdata
[x
++]) {
414 case 0x02: /* caller id number */
415 cid
->number
[0] = '\0';
418 res
= cid
->rawdata
[x
++];
419 ast_copy_string(cid
->number
, &cid
->rawdata
[x
], res
+1 );
422 case 0x21: /* additional information */
426 switch (cid
->rawdata
[x
]) {
427 case 0x00: /* unknown */
428 case 0x01: /* international number */
429 case 0x02: /* domestic number */
430 case 0x03: /* network */
431 case 0x04: /* local call */
432 case 0x06: /* short dial number */
433 case 0x07: /* reserved */
434 default: /* reserved */
435 if (option_debug
> 1)
436 ast_log(LOG_DEBUG
, "cid info:#1=%X\n", cid
->rawdata
[x
]);
440 /* numbering plan octed 4 */
442 /* numbering plan octed 5 */
443 switch (cid
->rawdata
[x
]) {
444 case 0x00: /* unknown */
445 case 0x01: /* recommendation E.164 ISDN */
446 case 0x03: /* recommendation X.121 */
447 case 0x04: /* telex dial plan */
448 case 0x08: /* domestic dial plan */
449 case 0x09: /* private dial plan */
450 case 0x05: /* reserved */
451 default: /* reserved */
452 if (option_debug
> 1)
453 ast_log(LOG_DEBUG
, "cid info:#2=%X\n", cid
->rawdata
[x
]);
458 case 0x04: /* no callerid reason */
461 /* no callerid reason code */
462 switch (cid
->rawdata
[x
]) {
463 case 'P': /* caller id denied by user */
464 case 'O': /* service not available */
465 case 'C': /* pay phone */
466 case 'S': /* service congested */
467 cid
->flags
|= CID_UNKNOWN_NUMBER
;
468 if (option_debug
> 1)
469 ast_log(LOG_DEBUG
, "no cid reason:%c\n",cid
->rawdata
[x
]);
474 case 0x09: /* dialed number */
476 res
= cid
->rawdata
[x
++];
480 case 0x22: /* dialed number additional information */
484 switch (cid
->rawdata
[x
]) {
485 case 0x00: /* unknown */
486 case 0x01: /* international number */
487 case 0x02: /* domestic number */
488 case 0x03: /* network */
489 case 0x04: /* local call */
490 case 0x06: /* short dial number */
491 case 0x07: /* reserved */
492 default: /* reserved */
493 if (option_debug
> 1)
494 ast_log(LOG_NOTICE
, "did info:#1=%X\n", cid
->rawdata
[x
]);
498 /* numbering plan octed 4 */
500 /* numbering plan octed 5 */
501 switch (cid
->rawdata
[x
]) {
502 case 0x00: /* unknown */
503 case 0x01: /* recommendation E.164 ISDN */
504 case 0x03: /* recommendation X.121 */
505 case 0x04: /* telex dial plan */
506 case 0x08: /* domestic dial plan */
507 case 0x09: /* private dial plan */
508 case 0x05: /* reserved */
509 default: /* reserved */
510 if (option_debug
> 1)
511 ast_log(LOG_DEBUG
, "did info:#2=%X\n", cid
->rawdata
[x
]);
521 ast_log(LOG_ERROR
, "invalid value in sawflag %d\n", cid
->sawflag
);
526 memcpy(cid
->oldstuff
, buf
, mylen
* 2);
527 cid
->oldlen
= mylen
* 2;
535 int callerid_feed(struct callerid_state
*cid
, unsigned char *ubuf
, int len
, int codec
)
545 if (!(buf
= ast_calloc(1, 2 * len
+ cid
->oldlen
))) {
550 memcpy(buf
, cid
->oldstuff
, cid
->oldlen
);
551 mylen
+= cid
->oldlen
/2;
554 buf
[x
+cid
->oldlen
/2] = AST_XLAW(ubuf
[x
]);
555 while(mylen
>= 160) {
557 res
= fsk_serie(&cid
->fskd
, buf
, &mylen
, &b
);
559 ast_log(LOG_ERROR
, "fsk_serie made mylen < 0 (%d)\n", mylen
);
563 buf
+= (olen
- mylen
);
565 ast_log(LOG_NOTICE
, "fsk_serie failed\n");
569 /* Ignore invalid bytes */
572 switch(cid
->sawflag
) {
573 case 0: /* Look for flag */
577 case 2: /* Get lead-in */
578 if ((b
== 0x04) || (b
== 0x80)) {
584 case 3: /* Get length */
585 /* Not a lead in. We're ready */
591 case 4: /* Retrieve message */
592 if (cid
->pos
>= 128) {
593 ast_log(LOG_WARNING
, "Caller ID too long???\n");
597 cid
->rawdata
[cid
->pos
++] = b
;
601 cid
->rawdata
[cid
->pos
] = '\0';
605 case 5: /* Check checksum */
606 if (b
!= (256 - (cid
->cksum
& 0xff))) {
607 ast_log(LOG_NOTICE
, "Caller*ID failed checksum\n");
613 cid
->number
[0] = '\0';
615 /* If we get this far we're fine. */
616 if (cid
->type
== 0x80) {
618 /* Go through each element and process */
619 for (x
=0;x
< cid
->pos
;) {
620 switch(cid
->rawdata
[x
++]) {
625 case 3: /* Number (for Zebble) */
627 res
= cid
->rawdata
[x
];
629 ast_log(LOG_NOTICE
, "Truncating long caller ID number from %d bytes to 32\n", cid
->rawdata
[x
]);
632 if (ast_strlen_zero(cid
->number
)) {
633 memcpy(cid
->number
, cid
->rawdata
+ x
+ 1, res
);
635 cid
->number
[res
] = '\0';
638 case 6: /* Stentor Call Qualifier (ie. Long Distance call) */
642 res
= cid
->rawdata
[x
];
644 ast_log(LOG_NOTICE
, "Truncating long caller ID name from %d bytes to 32\n", cid
->rawdata
[x
]);
647 memcpy(cid
->name
, cid
->rawdata
+ x
+ 1, res
);
648 cid
->name
[res
] = '\0';
650 case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting */
651 case 19: /* UK: Network message system status (Number of messages waiting) */
652 case 22: /* Something French */
655 ast_log(LOG_NOTICE
, "Unknown IE %d\n", cid
->rawdata
[x
-1]);
657 x
+= cid
->rawdata
[x
];
662 ast_copy_string(cid
->number
, cid
->rawdata
+ 8, sizeof(cid
->number
));
666 if (!strcmp(cid
->number
, "P")) {
667 strcpy(cid
->number
, "");
668 cid
->flags
|= CID_PRIVATE_NUMBER
;
669 } else if (!strcmp(cid
->number
, "O") || ast_strlen_zero(cid
->number
)) {
670 strcpy(cid
->number
, "");
671 cid
->flags
|= CID_UNKNOWN_NUMBER
;
673 if (!strcmp(cid
->name
, "P")) {
674 strcpy(cid
->name
, "");
675 cid
->flags
|= CID_PRIVATE_NAME
;
676 } else if (!strcmp(cid
->name
, "O") || ast_strlen_zero(cid
->name
)) {
677 strcpy(cid
->name
, "");
678 cid
->flags
|= CID_UNKNOWN_NAME
;
684 ast_log(LOG_ERROR
, "Dunno what to do with a digit in sawflag %d\n", cid
->sawflag
);
689 memcpy(cid
->oldstuff
, buf
, mylen
* 2);
690 cid
->oldlen
= mylen
* 2;
697 void callerid_free(struct callerid_state
*cid
)
702 static int callerid_genmsg(char *msg
, int size
, const char *number
, const char *name
, int flags
)
715 /* Format time and message header */
716 res
= snprintf(ptr
, size
, "\001\010%02d%02d%02d%02d", tm
.tm_mon
+ 1,
717 tm
.tm_mday
, tm
.tm_hour
, tm
.tm_min
);
720 if (ast_strlen_zero(number
) || (flags
& CID_UNKNOWN_NUMBER
)) {
721 /* Indicate number not known */
722 res
= snprintf(ptr
, size
, "\004\001O");
725 } else if (flags
& CID_PRIVATE_NUMBER
) {
726 /* Indicate number is private */
727 res
= snprintf(ptr
, size
, "\004\001P");
731 /* Send up to 16 digits of number MAX */
734 res
= snprintf(ptr
, size
, "\002%c", i
);
737 for (x
= 0; x
< i
; x
++)
744 if (ast_strlen_zero(name
) || (flags
& CID_UNKNOWN_NAME
)) {
745 /* Indicate name not known */
746 res
= snprintf(ptr
, size
, "\010\001O");
749 } else if (flags
& CID_PRIVATE_NAME
) {
750 /* Indicate name is private */
751 res
= snprintf(ptr
, size
, "\010\001P");
755 /* Send up to 16 digits of name MAX */
758 res
= snprintf(ptr
, size
, "\007%c", i
);
771 int vmwi_generate(unsigned char *buf
, int active
, int mdmf
, int codec
)
773 unsigned char msg
[256];
782 /* MDMF Message waiting */
786 /* IE is "Message Waiting Parameter" */
788 /* Length of IE is one */
796 /* SDMF Message waiting */
811 for (x
=0; x
<len
; x
++)
813 sum
= (256 - (sum
& 255));
815 /* Wait a half a second */
816 for (x
=0; x
<4000; x
++)
818 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
821 /* Send 170ms of callerid marks */
822 for (x
=0; x
<170; x
++)
824 for (x
=0; x
<len
; x
++) {
827 /* Send 50 more ms of marks */
833 int callerid_generate(unsigned char *buf
, const char *number
, const char *name
, int flags
, int callwaiting
, int codec
)
839 /* Initial carriers (real/imaginary) */
844 len
= callerid_genmsg(msg
, sizeof(msg
), number
, name
, flags
);
846 /* Wait a half a second */
847 for (x
=0; x
<4000; x
++)
849 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
853 /* Send 150ms of callerid marks */
854 for (x
=0; x
<150; x
++)
856 /* Send 0x80 indicating MDMF format */
858 /* Put length of whole message */
860 sum
= 0x80 + strlen(msg
);
861 /* Put each character of message and update checksum */
862 for (x
=0; x
<len
; x
++) {
866 /* Send 2's compliment of sum */
867 PUT_CLID(256 - (sum
& 255));
869 /* Send 50 more ms of marks */
876 /*! \brief Clean up phone string
877 * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
878 * Basically, remove anything that could be invalid in a pattern.
880 void ast_shrink_phone_number(char *n
)
885 for (x
=0; n
[x
]; x
++) {
904 if (!strchr("( )", n
[x
]))
911 /*! \brief Checks if phone number consists of valid characters
912 \param exten String that needs to be checked
913 \param valid Valid characters in string
914 \return 1 if valid string, 0 if string contains invalid characters
916 static int ast_is_valid_string(const char *exten
, const char *valid
)
920 if (ast_strlen_zero(exten
))
922 for (x
=0; exten
[x
]; x
++)
923 if (!strchr(valid
, exten
[x
]))
928 /*! \brief checks if string consists only of digits and * \# and +
929 \return 1 if string is valid AST phone number
932 int ast_isphonenumber(const char *n
)
934 return ast_is_valid_string(n
, "0123456789*#+");
937 /*! \brief checks if string consists only of digits and ( ) - * \# and +
938 Pre-qualifies the string for ast_shrink_phone_number()
939 \return 1 if string is valid AST shrinkable phone number
942 int ast_is_shrinkable_phonenumber(const char *exten
)
944 return ast_is_valid_string(exten
, "0123456789*#+()-.");
947 /*! \brief parse string for caller id information
948 \return always returns 0, as the code always returns something.
949 XXX note that 'name' is not parsed consistently e.g. we have
952 " foo bar " <123> 123 ' foo bar ' (with spaces around)
953 " foo bar " NULL 'foo bar' (without spaces around)
954 " foo bar <123>" 123 '" foo bar'
955 The parsing of leading and trailing space/quotes should be more consistent.
957 int ast_callerid_parse(char *instr
, char **name
, char **location
)
959 char *ns
, *ne
, *ls
, *le
;
961 /* Try "name" <location> format or name <location> format */
962 if ((ls
= strchr(instr
, '<')) && (le
= strchr(ls
, '>'))) {
963 *ls
= *le
= '\0'; /* location found, trim off the brackets */
964 *location
= ls
+ 1; /* and this is the result */
965 if ((ns
= strchr(instr
, '"')) && (ne
= strchr(ns
+ 1, '"'))) {
966 *ns
= *ne
= '\0'; /* trim off the quotes */
967 *name
= ns
+ 1; /* and this is the name */
968 } else { /* no quotes, trim off leading and trailing spaces */
969 *name
= ast_skip_blanks(instr
);
970 ast_trim_blanks(*name
);
972 } else { /* no valid brackets */
975 ast_copy_string(tmp
, instr
, sizeof(tmp
));
976 ast_shrink_phone_number(tmp
);
977 if (ast_isphonenumber(tmp
)) { /* Assume it's just a location */
979 strcpy(instr
, tmp
); /* safe, because tmp will always be the same size or smaller than instr */
981 } else { /* Assume it's just a name. */
983 if ((ns
= strchr(instr
, '"')) && (ne
= strchr(ns
+ 1, '"'))) {
984 *ns
= *ne
= '\0'; /* trim off the quotes */
985 *name
= ns
+ 1; /* and this is the name */
986 } else { /* no quotes, trim off leading and trailing spaces */
987 *name
= ast_skip_blanks(instr
);
988 ast_trim_blanks(*name
);
995 static int __ast_callerid_generate(unsigned char *buf
, const char *name
, const char *number
, int callwaiting
, int codec
)
997 if (ast_strlen_zero(name
))
999 if (ast_strlen_zero(number
))
1001 return callerid_generate(buf
, number
, name
, 0, callwaiting
, codec
);
1004 int ast_callerid_generate(unsigned char *buf
, const char *name
, const char *number
, int codec
)
1006 return __ast_callerid_generate(buf
, name
, number
, 0, codec
);
1009 int ast_callerid_callwaiting_generate(unsigned char *buf
, const char *name
, const char *number
, int codec
)
1011 return __ast_callerid_generate(buf
, name
, number
, 1, codec
);
1014 char *ast_callerid_merge(char *buf
, int bufsiz
, const char *name
, const char *num
, const char *unknown
)
1017 unknown
= "<unknown>";
1019 snprintf(buf
, bufsiz
, "\"%s\" <%s>", name
, num
);
1021 ast_copy_string(buf
, name
, bufsiz
);
1023 ast_copy_string(buf
, num
, bufsiz
);
1025 ast_copy_string(buf
, unknown
, bufsiz
);
1029 int ast_callerid_split(const char *buf
, char *name
, int namelen
, char *num
, int numlen
)
1032 char *l
= NULL
, *n
= NULL
;
1034 tmp
= ast_strdupa(buf
);
1035 ast_callerid_parse(tmp
, &n
, &l
);
1037 ast_copy_string(name
, n
, namelen
);
1041 ast_shrink_phone_number(l
);
1042 ast_copy_string(num
, l
, numlen
);
1048 /*! \brief Translation table for Caller ID Presentation settings */
1054 { AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED
, "allowed_not_screened", "Presentation Allowed, Not Screened"},
1055 { AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN
, "allowed_passed_screen", "Presentation Allowed, Passed Screen"},
1056 { AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN
, "allowed_failed_screen", "Presentation Allowed, Failed Screen"},
1057 { AST_PRES_ALLOWED_NETWORK_NUMBER
, "allowed", "Presentation Allowed, Network Number"},
1058 { AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED
, "prohib_not_screened", "Presentation Prohibited, Not Screened"},
1059 { AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN
, "prohib_passed_screen", "Presentation Prohibited, Passed Screen"},
1060 { AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN
, "prohib_failed_screen", "Presentation Prohibited, Failed Screen"},
1061 { AST_PRES_PROHIB_NETWORK_NUMBER
, "prohib", "Presentation Prohibited, Network Number"},
1062 { AST_PRES_NUMBER_NOT_AVAILABLE
, "unavailable", "Number Unavailable"},
1065 /*! \brief Convert caller ID text code to value
1066 used in config file parsing
1067 \param data text string
1068 \return value AST_PRES_ from callerid.h
1070 int ast_parse_caller_presentation(const char *data
)
1074 for (i
= 0; i
< ((sizeof(pres_types
) / sizeof(pres_types
[0]))); i
++) {
1075 if (!strcasecmp(pres_types
[i
].name
, data
))
1076 return pres_types
[i
].val
;
1082 /*! \brief Convert caller ID pres value to explanatory string
1083 \param data value (see callerid.h AST_PRES_ )
1084 \return string for human presentation
1086 const char *ast_describe_caller_presentation(int data
)
1090 for (i
= 0; i
< ((sizeof(pres_types
) / sizeof(pres_types
[0]))); i
++) {
1091 if (pres_types
[i
].val
== data
)
1092 return pres_types
[i
].description
;