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_NAME
))
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
);
313 buf
+= (olen
- mylen
);
316 ast_log(LOG_NOTICE
, "fsk_serie failed\n");
326 /* crc checksum calculation */
327 if ( cid
->sawflag
> 1 ) {
328 cid
->crc
= calc_crc(cid
->crc
, (unsigned char)b2
);
331 /* Ignore invalid bytes */
336 /* skip DLE if needed */
337 if ( cid
->sawflag
> 0 ) {
338 if ( cid
->sawflag
!= 5 && cid
->skipflag
== 0 && b
== 0x10 ) {
343 if ( cid
->skipflag
== 1 ) {
347 /* caller id retrieval */
348 switch(cid
->sawflag
) {
371 case 4: /* SERVICE TYPE */
376 case 5: /* Frame Length */
379 case 6: /* NUMBER TYPE */
382 cid
->rawdata
[cid
->pos
++] = b
;
384 case 7: /* NUMBER LENGTH */
387 if ( (cid
->len
+2) >= sizeof( cid
->rawdata
) ) {
388 ast_log(LOG_WARNING
, "too long caller id string\n" ) ;
392 cid
->rawdata
[cid
->pos
++] = b
;
394 case 8: /* Retrieve message */
395 cid
->rawdata
[cid
->pos
++] = b
;
398 cid
->rawdata
[cid
->pos
] = '\0';
405 case 10: /* CRC Checksum 1 */
408 case 11: /* CRC Checksum 2 */
410 if ( cid
->crc
!= 0 ) {
411 ast_log(LOG_WARNING
, "crc checksum error\n" ) ;
415 /* extract caller id data */
416 for (x
=0; x
<cid
->pos
; ) {
417 switch (cid
->rawdata
[x
++]) {
418 case 0x02: /* caller id number */
419 cid
->number
[0] = '\0';
422 res
= cid
->rawdata
[x
++];
423 ast_copy_string(cid
->number
, &cid
->rawdata
[x
], res
+1 );
426 case 0x21: /* additional information */
430 switch (cid
->rawdata
[x
]) {
431 case 0x00: /* unknown */
432 case 0x01: /* international number */
433 case 0x02: /* domestic number */
434 case 0x03: /* network */
435 case 0x04: /* local call */
436 case 0x06: /* short dial number */
437 case 0x07: /* reserved */
438 default: /* reserved */
439 if (option_debug
> 1)
440 ast_log(LOG_DEBUG
, "cid info:#1=%X\n", cid
->rawdata
[x
]);
444 /* numbering plan octed 4 */
446 /* numbering plan octed 5 */
447 switch (cid
->rawdata
[x
]) {
448 case 0x00: /* unknown */
449 case 0x01: /* recommendation E.164 ISDN */
450 case 0x03: /* recommendation X.121 */
451 case 0x04: /* telex dial plan */
452 case 0x08: /* domestic dial plan */
453 case 0x09: /* private dial plan */
454 case 0x05: /* reserved */
455 default: /* reserved */
456 if (option_debug
> 1)
457 ast_log(LOG_DEBUG
, "cid info:#2=%X\n", cid
->rawdata
[x
]);
462 case 0x04: /* no callerid reason */
465 /* no callerid reason code */
466 switch (cid
->rawdata
[x
]) {
467 case 'P': /* caller id denied by user */
468 case 'O': /* service not available */
469 case 'C': /* pay phone */
470 case 'S': /* service congested */
471 cid
->flags
|= CID_UNKNOWN_NUMBER
;
472 if (option_debug
> 1)
473 ast_log(LOG_DEBUG
, "no cid reason:%c\n",cid
->rawdata
[x
]);
478 case 0x09: /* dialed number */
480 res
= cid
->rawdata
[x
++];
484 case 0x22: /* dialed number additional information */
488 switch (cid
->rawdata
[x
]) {
489 case 0x00: /* unknown */
490 case 0x01: /* international number */
491 case 0x02: /* domestic number */
492 case 0x03: /* network */
493 case 0x04: /* local call */
494 case 0x06: /* short dial number */
495 case 0x07: /* reserved */
496 default: /* reserved */
497 if (option_debug
> 1)
498 ast_log(LOG_NOTICE
, "did info:#1=%X\n", cid
->rawdata
[x
]);
502 /* numbering plan octed 4 */
504 /* numbering plan octed 5 */
505 switch (cid
->rawdata
[x
]) {
506 case 0x00: /* unknown */
507 case 0x01: /* recommendation E.164 ISDN */
508 case 0x03: /* recommendation X.121 */
509 case 0x04: /* telex dial plan */
510 case 0x08: /* domestic dial plan */
511 case 0x09: /* private dial plan */
512 case 0x05: /* reserved */
513 default: /* reserved */
514 if (option_debug
> 1)
515 ast_log(LOG_DEBUG
, "did info:#2=%X\n", cid
->rawdata
[x
]);
526 ast_log(LOG_ERROR
, "invalid value in sawflag %d\n", cid
->sawflag
);
531 memcpy(cid
->oldstuff
, buf
, mylen
* 2);
532 cid
->oldlen
= mylen
* 2;
540 int callerid_feed(struct callerid_state
*cid
, unsigned char *ubuf
, int len
, int codec
)
550 if (!(buf
= ast_calloc(1, 2 * len
+ cid
->oldlen
))) {
555 memcpy(buf
, cid
->oldstuff
, cid
->oldlen
);
556 mylen
+= cid
->oldlen
/2;
559 buf
[x
+cid
->oldlen
/2] = AST_XLAW(ubuf
[x
]);
560 while(mylen
>= 160) {
562 res
= fsk_serie(&cid
->fskd
, buf
, &mylen
, &b
);
564 ast_log(LOG_ERROR
, "fsk_serie made mylen < 0 (%d)\n", mylen
);
568 buf
+= (olen
- mylen
);
570 ast_log(LOG_NOTICE
, "fsk_serie failed\n");
575 /* Ignore invalid bytes */
578 switch(cid
->sawflag
) {
579 case 0: /* Look for flag */
583 case 2: /* Get lead-in */
584 if ((b
== 0x04) || (b
== 0x80)) {
590 case 3: /* Get length */
591 /* Not a lead in. We're ready */
597 case 4: /* Retrieve message */
598 if (cid
->pos
>= 128) {
599 ast_log(LOG_WARNING
, "Caller ID too long???\n");
603 cid
->rawdata
[cid
->pos
++] = b
;
607 cid
->rawdata
[cid
->pos
] = '\0';
611 case 5: /* Check checksum */
612 if (b
!= (256 - (cid
->cksum
& 0xff))) {
613 ast_log(LOG_NOTICE
, "Caller*ID failed checksum\n");
619 cid
->number
[0] = '\0';
621 /* If we get this far we're fine. */
622 if (cid
->type
== 0x80) {
624 /* Go through each element and process */
625 for (x
=0;x
< cid
->pos
;) {
626 switch(cid
->rawdata
[x
++]) {
631 case 3: /* Number (for Zebble) */
633 res
= cid
->rawdata
[x
];
635 ast_log(LOG_NOTICE
, "Truncating long caller ID number from %d bytes to 32\n", cid
->rawdata
[x
]);
638 if (ast_strlen_zero(cid
->number
)) {
639 memcpy(cid
->number
, cid
->rawdata
+ x
+ 1, res
);
641 cid
->number
[res
] = '\0';
644 case 6: /* Stentor Call Qualifier (ie. Long Distance call) */
648 res
= cid
->rawdata
[x
];
650 ast_log(LOG_NOTICE
, "Truncating long caller ID name from %d bytes to 32\n", cid
->rawdata
[x
]);
653 memcpy(cid
->name
, cid
->rawdata
+ x
+ 1, res
);
654 cid
->name
[res
] = '\0';
656 case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting */
657 case 19: /* UK: Network message system status (Number of messages waiting) */
658 case 22: /* Something French */
661 ast_log(LOG_NOTICE
, "Unknown IE %d\n", cid
->rawdata
[x
-1]);
663 res
= cid
->rawdata
[x
];
664 if (0 > res
){ /* Negative offset in the CID Spill */
665 ast_log(LOG_NOTICE
, "IE %d has bad field length of %d at offset %d\n", cid
->rawdata
[x
-1], cid
->rawdata
[x
], x
);
668 break; /* Exit the loop */
670 x
+= cid
->rawdata
[x
];
675 ast_copy_string(cid
->number
, cid
->rawdata
+ 8, sizeof(cid
->number
));
679 if (!strcmp(cid
->number
, "P")) {
680 strcpy(cid
->number
, "");
681 cid
->flags
|= CID_PRIVATE_NUMBER
;
682 } else if (!strcmp(cid
->number
, "O") || ast_strlen_zero(cid
->number
)) {
683 strcpy(cid
->number
, "");
684 cid
->flags
|= CID_UNKNOWN_NUMBER
;
686 if (!strcmp(cid
->name
, "P")) {
687 strcpy(cid
->name
, "");
688 cid
->flags
|= CID_PRIVATE_NAME
;
689 } else if (!strcmp(cid
->name
, "O") || ast_strlen_zero(cid
->name
)) {
690 strcpy(cid
->name
, "");
691 cid
->flags
|= CID_UNKNOWN_NAME
;
697 ast_log(LOG_ERROR
, "Dunno what to do with a digit in sawflag %d\n", cid
->sawflag
);
702 memcpy(cid
->oldstuff
, buf
, mylen
* 2);
703 cid
->oldlen
= mylen
* 2;
710 void callerid_free(struct callerid_state
*cid
)
715 static int callerid_genmsg(char *msg
, int size
, const char *number
, const char *name
, int flags
)
724 ast_localtime(&t
, &tm
, NULL
);
728 /* Format time and message header */
729 res
= snprintf(ptr
, size
, "\001\010%02d%02d%02d%02d", tm
.tm_mon
+ 1,
730 tm
.tm_mday
, tm
.tm_hour
, tm
.tm_min
);
733 if (ast_strlen_zero(number
) || (flags
& CID_UNKNOWN_NUMBER
)) {
734 /* Indicate number not known */
735 res
= snprintf(ptr
, size
, "\004\001O");
738 } else if (flags
& CID_PRIVATE_NUMBER
) {
739 /* Indicate number is private */
740 res
= snprintf(ptr
, size
, "\004\001P");
744 /* Send up to 16 digits of number MAX */
747 res
= snprintf(ptr
, size
, "\002%c", i
);
750 for (x
= 0; x
< i
; x
++)
757 if (ast_strlen_zero(name
) || (flags
& CID_UNKNOWN_NAME
)) {
758 /* Indicate name not known */
759 res
= snprintf(ptr
, size
, "\010\001O");
762 } else if (flags
& CID_PRIVATE_NAME
) {
763 /* Indicate name is private */
764 res
= snprintf(ptr
, size
, "\010\001P");
768 /* Send up to 16 digits of name MAX */
771 res
= snprintf(ptr
, size
, "\007%c", i
);
784 int vmwi_generate(unsigned char *buf
, int active
, int mdmf
, int codec
)
786 unsigned char msg
[256];
795 /* MDMF Message waiting */
799 /* IE is "Message Waiting Parameter" */
801 /* Length of IE is one */
809 /* SDMF Message waiting */
824 for (x
=0; x
<len
; x
++)
826 sum
= (256 - (sum
& 255));
828 /* Wait a half a second */
829 for (x
=0; x
<4000; x
++)
831 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
834 /* Send 170ms of callerid marks */
835 for (x
=0; x
<170; x
++)
837 for (x
=0; x
<len
; x
++) {
840 /* Send 50 more ms of marks */
846 int callerid_generate(unsigned char *buf
, const char *number
, const char *name
, int flags
, int callwaiting
, int codec
)
852 /* Initial carriers (real/imaginary) */
857 len
= callerid_genmsg(msg
, sizeof(msg
), number
, name
, flags
);
859 /* Wait a half a second */
860 for (x
=0; x
<4000; x
++)
862 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
866 /* Send 150ms of callerid marks */
867 for (x
=0; x
<150; x
++)
869 /* Send 0x80 indicating MDMF format */
871 /* Put length of whole message */
873 sum
= 0x80 + strlen(msg
);
874 /* Put each character of message and update checksum */
875 for (x
=0; x
<len
; x
++) {
879 /* Send 2's compliment of sum */
880 PUT_CLID(256 - (sum
& 255));
882 /* Send 50 more ms of marks */
889 /*! \brief Clean up phone string
890 * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
891 * Basically, remove anything that could be invalid in a pattern.
893 void ast_shrink_phone_number(char *n
)
898 for (x
=0; n
[x
]; x
++) {
917 if (!strchr("( )", n
[x
]))
924 /*! \brief Checks if phone number consists of valid characters
925 \param exten String that needs to be checked
926 \param valid Valid characters in string
927 \return 1 if valid string, 0 if string contains invalid characters
929 static int ast_is_valid_string(const char *exten
, const char *valid
)
933 if (ast_strlen_zero(exten
))
935 for (x
=0; exten
[x
]; x
++)
936 if (!strchr(valid
, exten
[x
]))
941 /*! \brief checks if string consists only of digits and * \# and +
942 \return 1 if string is valid AST phone number
945 int ast_isphonenumber(const char *n
)
947 return ast_is_valid_string(n
, "0123456789*#+");
950 /*! \brief checks if string consists only of digits and ( ) - * \# and +
951 Pre-qualifies the string for ast_shrink_phone_number()
952 \return 1 if string is valid AST shrinkable phone number
955 int ast_is_shrinkable_phonenumber(const char *exten
)
957 return ast_is_valid_string(exten
, "0123456789*#+()-.");
960 /*! \brief parse string for caller id information
961 \return always returns 0, as the code always returns something.
962 XXX note that 'name' is not parsed consistently e.g. we have
965 " foo bar " <123> 123 ' foo bar ' (with spaces around)
966 " foo bar " NULL 'foo bar' (without spaces around)
967 " foo bar <123>" 123 '" foo bar'
968 The parsing of leading and trailing space/quotes should be more consistent.
970 int ast_callerid_parse(char *instr
, char **name
, char **location
)
972 char *ns
, *ne
, *ls
, *le
;
974 /* Try "name" <location> format or name <location> format */
975 if ((ls
= strchr(instr
, '<')) && (le
= strchr(ls
, '>'))) {
976 *ls
= *le
= '\0'; /* location found, trim off the brackets */
977 *location
= ls
+ 1; /* and this is the result */
978 if ((ns
= strchr(instr
, '"')) && (ne
= strchr(ns
+ 1, '"'))) {
979 *ns
= *ne
= '\0'; /* trim off the quotes */
980 *name
= ns
+ 1; /* and this is the name */
981 } else { /* no quotes, trim off leading and trailing spaces */
982 *name
= ast_skip_blanks(instr
);
983 ast_trim_blanks(*name
);
985 } else { /* no valid brackets */
988 ast_copy_string(tmp
, instr
, sizeof(tmp
));
989 ast_shrink_phone_number(tmp
);
990 if (ast_isphonenumber(tmp
)) { /* Assume it's just a location */
992 strcpy(instr
, tmp
); /* safe, because tmp will always be the same size or smaller than instr */
994 } else { /* Assume it's just a name. */
996 if ((ns
= strchr(instr
, '"')) && (ne
= strchr(ns
+ 1, '"'))) {
997 *ns
= *ne
= '\0'; /* trim off the quotes */
998 *name
= ns
+ 1; /* and this is the name */
999 } else { /* no quotes, trim off leading and trailing spaces */
1000 *name
= ast_skip_blanks(instr
);
1001 ast_trim_blanks(*name
);
1008 static int __ast_callerid_generate(unsigned char *buf
, const char *name
, const char *number
, int callwaiting
, int codec
)
1010 if (ast_strlen_zero(name
))
1012 if (ast_strlen_zero(number
))
1014 return callerid_generate(buf
, number
, name
, 0, callwaiting
, codec
);
1017 int ast_callerid_generate(unsigned char *buf
, const char *name
, const char *number
, int codec
)
1019 return __ast_callerid_generate(buf
, name
, number
, 0, codec
);
1022 int ast_callerid_callwaiting_generate(unsigned char *buf
, const char *name
, const char *number
, int codec
)
1024 return __ast_callerid_generate(buf
, name
, number
, 1, codec
);
1027 char *ast_callerid_merge(char *buf
, int bufsiz
, const char *name
, const char *num
, const char *unknown
)
1030 unknown
= "<unknown>";
1032 snprintf(buf
, bufsiz
, "\"%s\" <%s>", name
, num
);
1034 ast_copy_string(buf
, name
, bufsiz
);
1036 ast_copy_string(buf
, num
, bufsiz
);
1038 ast_copy_string(buf
, unknown
, bufsiz
);
1042 int ast_callerid_split(const char *buf
, char *name
, int namelen
, char *num
, int numlen
)
1045 char *l
= NULL
, *n
= NULL
;
1047 tmp
= ast_strdupa(buf
);
1048 ast_callerid_parse(tmp
, &n
, &l
);
1050 ast_copy_string(name
, n
, namelen
);
1054 ast_shrink_phone_number(l
);
1055 ast_copy_string(num
, l
, numlen
);
1061 /*! \brief Translation table for Caller ID Presentation settings */
1067 { AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED
, "allowed_not_screened", "Presentation Allowed, Not Screened"},
1068 { AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN
, "allowed_passed_screen", "Presentation Allowed, Passed Screen"},
1069 { AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN
, "allowed_failed_screen", "Presentation Allowed, Failed Screen"},
1070 { AST_PRES_ALLOWED_NETWORK_NUMBER
, "allowed", "Presentation Allowed, Network Number"},
1071 { AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED
, "prohib_not_screened", "Presentation Prohibited, Not Screened"},
1072 { AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN
, "prohib_passed_screen", "Presentation Prohibited, Passed Screen"},
1073 { AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN
, "prohib_failed_screen", "Presentation Prohibited, Failed Screen"},
1074 { AST_PRES_PROHIB_NETWORK_NUMBER
, "prohib", "Presentation Prohibited, Network Number"},
1075 { AST_PRES_NUMBER_NOT_AVAILABLE
, "unavailable", "Number Unavailable"},
1078 /*! \brief Convert caller ID text code to value
1079 used in config file parsing
1080 \param data text string
1081 \return value AST_PRES_ from callerid.h
1083 int ast_parse_caller_presentation(const char *data
)
1087 for (i
= 0; i
< ((sizeof(pres_types
) / sizeof(pres_types
[0]))); i
++) {
1088 if (!strcasecmp(pres_types
[i
].name
, data
))
1089 return pres_types
[i
].val
;
1095 /*! \brief Convert caller ID pres value to explanatory string
1096 \param data value (see callerid.h AST_PRES_ )
1097 \return string for human presentation
1099 const char *ast_describe_caller_presentation(int data
)
1103 for (i
= 0; i
< ((sizeof(pres_types
) / sizeof(pres_types
[0]))); i
++) {
1104 if (pres_types
[i
].val
== data
)
1105 return pres_types
[i
].description
;