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$")
34 #include "asterisk/ulaw.h"
35 #include "asterisk/alaw.h"
36 #include "asterisk/frame.h"
37 #include "asterisk/channel.h"
38 #include "asterisk/callerid.h"
39 #include "asterisk/fskmodem.h"
40 #include "asterisk/utils.h"
42 struct callerid_state
{
61 float cid_dr
[4], cid_di
[4];
62 float clidsb
= 8000.0 / 1200.0;
64 float casdr1
, casdi1
, casdr2
, casdi2
;
66 #define CALLERID_SPACE 2200.0 /*!< 2200 hz for "0" */
67 #define CALLERID_MARK 1200.0 /*!< 1200 hz for "1" */
68 #define SAS_FREQ 440.0
69 #define CAS_FREQ1 2130.0
70 #define CAS_FREQ2 2750.0
72 #define AST_CALLERID_UNKNOWN "<unknown>"
74 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
)
78 for (x
= 0; x
< len
; x
++) {
79 t
= *cr1
* ddr1
- *ci1
* ddi1
;
80 *ci1
= *cr1
* ddi1
+ *ci1
* ddr1
;
82 t
= 2.0 - (*cr1
* *cr1
+ *ci1
* *ci1
);
86 t
= *cr2
* ddr2
- *ci2
* ddi2
;
87 *ci2
= *cr2
* ddi2
+ *ci2
* ddr2
;
89 t
= 2.0 - (*cr2
* *cr2
+ *ci2
* *ci2
);
92 buf
[x
] = AST_LIN2X((*cr1
+ *cr2
) * 2048.0);
96 static inline void gen_tone(unsigned char *buf
, int len
, int codec
, float ddr1
, float ddi1
, float *cr1
, float *ci1
)
100 for (x
= 0; x
< len
; x
++) {
101 t
= *cr1
* ddr1
- *ci1
* ddi1
;
102 *ci1
= *cr1
* ddi1
+ *ci1
* ddr1
;
104 t
= 2.0 - (*cr1
* *cr1
+ *ci1
* *ci1
);
107 buf
[x
] = AST_LIN2X(*cr1
* 8192.0);
111 /*! \brief Initialize stuff for inverse FFT */
112 void callerid_init(void)
114 cid_dr
[0] = cos(CALLERID_SPACE
* 2.0 * M_PI
/ 8000.0);
115 cid_di
[0] = sin(CALLERID_SPACE
* 2.0 * M_PI
/ 8000.0);
116 cid_dr
[1] = cos(CALLERID_MARK
* 2.0 * M_PI
/ 8000.0);
117 cid_di
[1] = sin(CALLERID_MARK
* 2.0 * M_PI
/ 8000.0);
118 sasdr
= cos(SAS_FREQ
* 2.0 * M_PI
/ 8000.0);
119 sasdi
= sin(SAS_FREQ
* 2.0 * M_PI
/ 8000.0);
120 casdr1
= cos(CAS_FREQ1
* 2.0 * M_PI
/ 8000.0);
121 casdi1
= sin(CAS_FREQ1
* 2.0 * M_PI
/ 8000.0);
122 casdr2
= cos(CAS_FREQ2
* 2.0 * M_PI
/ 8000.0);
123 casdi2
= sin(CAS_FREQ2
* 2.0 * M_PI
/ 8000.0);
126 struct callerid_state
*callerid_new(int cid_signalling
)
128 struct callerid_state
*cid
;
130 if ((cid
= ast_calloc(1, sizeof(*cid
)))) {
131 cid
->fskd
.ispb
= 7; /* 1200 baud */
132 /* Set up for 1200 / 8000 freq *32 to allow ints */
133 cid
->fskd
.pllispb
= (int)(8000 * 32 / 1200);
134 cid
->fskd
.pllids
= cid
->fskd
.pllispb
/32;
135 cid
->fskd
.pllispb2
= cid
->fskd
.pllispb
/2;
137 cid
->fskd
.icont
= 0; /* PLL REset */
138 /* cid->fskd.hdlc = 0; */ /* Async */
139 cid
->fskd
.nbit
= 8; /* 8 bits */
140 cid
->fskd
.instop
= 1; /* 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
;
157 fskmodem_init(&cid
->fskd
);
163 void callerid_get(struct callerid_state
*cid
, char **name
, char **number
, int *flags
)
166 if (cid
->flags
& (CID_UNKNOWN_NAME
| CID_PRIVATE_NAME
))
170 if (cid
->flags
& (CID_UNKNOWN_NUMBER
| CID_PRIVATE_NUMBER
))
173 *number
= cid
->number
;
176 void callerid_get_dtmf(char *cidstring
, char *number
, int *flags
)
181 /* "Clear" the number-buffer. */
184 if (strlen(cidstring
) < 2) {
185 ast_debug(1, "No cid detected\n");
186 *flags
= CID_UNKNOWN_NUMBER
;
190 /* Detect protocol and special types */
191 if (cidstring
[0] == 'B') {
192 /* Handle special codes */
193 code
= atoi(&cidstring
[1]);
195 *flags
= CID_UNKNOWN_NUMBER
;
197 *flags
= CID_PRIVATE_NUMBER
;
199 ast_debug(1, "Unknown DTMF code %d\n", code
);
200 } else if (cidstring
[0] == 'D' && cidstring
[2] == '#') {
201 /* .DK special code */
202 if (cidstring
[1] == '1')
203 *flags
= CID_PRIVATE_NUMBER
;
204 if (cidstring
[1] == '2' || cidstring
[1] == '3')
205 *flags
= CID_UNKNOWN_NUMBER
;
206 } else if (cidstring
[0] == 'D' || cidstring
[0] == 'A') {
207 /* "Standard" callerid */
208 for (i
= 1; i
< strlen(cidstring
); i
++) {
209 if (cidstring
[i
] == 'C' || cidstring
[i
] == '#')
211 if (isdigit(cidstring
[i
]))
212 number
[i
-1] = cidstring
[i
];
214 ast_debug(1, "Unknown CID digit '%c'\n",
218 } else if (isdigit(cidstring
[0])) {
219 /* It begins with a digit, so we parse it as a number and hope
221 ast_log(LOG_WARNING
, "Couldn't detect start-character. CID "
222 "parsing might be unreliable\n");
223 for (i
= 0; i
< strlen(cidstring
); i
++) {
224 if (isdigit(cidstring
[i
]))
225 number
[i
] = cidstring
[i
];
231 ast_debug(1, "Unknown CID protocol, start digit '%c'\n", cidstring
[0]);
232 *flags
= CID_UNKNOWN_NUMBER
;
236 int ast_gen_cas(unsigned char *outbuf
, int sendsas
, int len
, int codec
)
248 gen_tone(outbuf
, saslen
, codec
, sasdr
, sasdi
, &cr1
, &ci1
);
254 gen_tones(outbuf
+ pos
, len
, codec
, casdr1
, casdi1
, casdr2
, casdi2
, &cr1
, &ci1
, &cr2
, &ci2
);
258 static unsigned short calc_crc(unsigned short crc
, unsigned char data
)
260 unsigned int i
, j
, org
, dst
;
264 for (i
= 0; i
< CHAR_BIT
; i
++) {
270 data
= (unsigned char) dst
;
271 crc
^= (unsigned int) data
<< (16 - CHAR_BIT
);
272 for (j
= 0; j
< CHAR_BIT
; j
++) {
274 crc
= (crc
<< 1) ^ 0x1021U
;
281 int callerid_feed_jp(struct callerid_state
*cid
, unsigned char *ubuf
, int len
, int codec
)
291 buf
= alloca(2 * len
+ cid
->oldlen
);
293 memcpy(buf
, cid
->oldstuff
, cid
->oldlen
);
294 mylen
+= cid
->oldlen
/ 2;
296 for (x
= 0; x
< len
; x
++)
297 buf
[x
+cid
->oldlen
/2] = AST_XLAW(ubuf
[x
]);
299 while (mylen
>= 160) {
302 res
= fsk_serial(&cid
->fskd
, buf
, &mylen
, &b
);
305 ast_log(LOG_ERROR
, "No start bit found in fsk data.\n");
309 buf
+= (olen
- mylen
);
312 ast_log(LOG_NOTICE
, "fsk_serial failed\n");
320 /* crc checksum calculation */
321 if (cid
->sawflag
> 1)
322 cid
->crc
= calc_crc(cid
->crc
, (unsigned char) b2
);
324 /* Ignore invalid bytes */
328 /* skip DLE if needed */
329 if (cid
->sawflag
> 0) {
330 if (cid
->sawflag
!= 5 && cid
->skipflag
== 0 && b
== 0x10) {
335 if (cid
->skipflag
== 1)
338 /* caller id retrieval */
339 switch (cid
->sawflag
) {
359 case 4: /* SERVICE TYPE */
363 case 5: /* Frame Length */
366 case 6: /* NUMBER TYPE */
369 cid
->rawdata
[cid
->pos
++] = b
;
371 case 7: /* NUMBER LENGTH */
374 if ((cid
->len
+2) >= sizeof(cid
->rawdata
)) {
375 ast_log(LOG_WARNING
, "too long caller id string\n") ;
378 cid
->rawdata
[cid
->pos
++] = b
;
380 case 8: /* Retrieve message */
381 cid
->rawdata
[cid
->pos
++] = b
;
384 cid
->rawdata
[cid
->pos
] = '\0';
391 case 10: /* CRC Checksum 1 */
394 case 11: /* CRC Checksum 2 */
397 ast_log(LOG_WARNING
, "crc checksum error\n") ;
400 /* extract caller id data */
401 for (x
= 0; x
< cid
->pos
;) {
402 switch (cid
->rawdata
[x
++]) {
403 case 0x02: /* caller id number */
404 cid
->number
[0] = '\0';
407 res
= cid
->rawdata
[x
++];
408 ast_copy_string(cid
->number
, &cid
->rawdata
[x
], res
+1);
411 case 0x21: /* additional information */
415 switch (cid
->rawdata
[x
]) {
416 case 0x00: /* unknown */
417 case 0x01: /* international number */
418 case 0x02: /* domestic number */
419 case 0x03: /* network */
420 case 0x04: /* local call */
421 case 0x06: /* short dial number */
422 case 0x07: /* reserved */
423 default: /* reserved */
424 ast_debug(2, "cid info:#1=%X\n", cid
->rawdata
[x
]);
428 /* numbering plan octed 4 */
430 /* numbering plan octed 5 */
431 switch (cid
->rawdata
[x
]) {
432 case 0x00: /* unknown */
433 case 0x01: /* recommendation E.164 ISDN */
434 case 0x03: /* recommendation X.121 */
435 case 0x04: /* telex dial plan */
436 case 0x08: /* domestic dial plan */
437 case 0x09: /* private dial plan */
438 case 0x05: /* reserved */
439 default: /* reserved */
440 ast_debug(2, "cid info:#2=%X\n", cid
->rawdata
[x
]);
445 case 0x04: /* no callerid reason */
448 /* no callerid reason code */
449 switch (cid
->rawdata
[x
]) {
450 case 'P': /* caller id denied by user */
451 case 'O': /* service not available */
452 case 'C': /* pay phone */
453 case 'S': /* service congested */
454 cid
->flags
|= CID_UNKNOWN_NUMBER
;
455 ast_debug(2, "no cid reason:%c\n", cid
->rawdata
[x
]);
460 case 0x09: /* dialed number */
462 res
= cid
->rawdata
[x
++];
466 case 0x22: /* dialed number additional information */
470 switch (cid
->rawdata
[x
]) {
471 case 0x00: /* unknown */
472 case 0x01: /* international number */
473 case 0x02: /* domestic number */
474 case 0x03: /* network */
475 case 0x04: /* local call */
476 case 0x06: /* short dial number */
477 case 0x07: /* reserved */
478 default: /* reserved */
479 if (option_debug
> 1)
480 ast_log(LOG_NOTICE
, "did info:#1=%X\n", cid
->rawdata
[x
]);
484 /* numbering plan octed 4 */
486 /* numbering plan octed 5 */
487 switch (cid
->rawdata
[x
]) {
488 case 0x00: /* unknown */
489 case 0x01: /* recommendation E.164 ISDN */
490 case 0x03: /* recommendation X.121 */
491 case 0x04: /* telex dial plan */
492 case 0x08: /* domestic dial plan */
493 case 0x09: /* private dial plan */
494 case 0x05: /* reserved */
495 default: /* reserved */
496 ast_debug(2, "did info:#2=%X\n", cid
->rawdata
[x
]);
506 ast_log(LOG_ERROR
, "invalid value in sawflag %d\n", cid
->sawflag
);
511 memcpy(cid
->oldstuff
, buf
, mylen
* 2);
512 cid
->oldlen
= mylen
* 2;
520 int callerid_feed(struct callerid_state
*cid
, unsigned char *ubuf
, int len
, int codec
)
529 buf
= alloca(2 * len
+ cid
->oldlen
);
531 memcpy(buf
, cid
->oldstuff
, cid
->oldlen
);
532 mylen
+= cid
->oldlen
/2;
534 for (x
= 0; x
< len
; x
++)
535 buf
[x
+cid
->oldlen
/2] = AST_XLAW(ubuf
[x
]);
536 while (mylen
>= 160) {
538 res
= fsk_serial(&cid
->fskd
, buf
, &mylen
, &b
);
540 ast_log(LOG_ERROR
, "No start bit found in fsk data.\n");
543 buf
+= (olen
- mylen
);
545 ast_log(LOG_NOTICE
, "fsk_serial failed\n");
549 /* Ignore invalid bytes */
552 switch (cid
->sawflag
) {
553 case 0: /* Look for flag */
557 case 2: /* Get lead-in */
558 if ((b
== 0x04) || (b
== 0x80) || (b
== 0x06) || (b
== 0x82)) {
564 case 3: /* Get length */
565 /* Not a lead in. We're ready */
571 case 4: /* Retrieve message */
572 if (cid
->pos
>= 128) {
573 ast_log(LOG_WARNING
, "Caller ID too long???\n");
576 cid
->rawdata
[cid
->pos
++] = b
;
580 cid
->rawdata
[cid
->pos
] = '\0';
584 case 5: /* Check checksum */
585 if (b
!= (256 - (cid
->cksum
& 0xff))) {
586 ast_log(LOG_NOTICE
, "Caller*ID failed checksum\n");
592 cid
->number
[0] = '\0';
596 /* If we get this far we're fine. */
597 if ((cid
->type
== 0x80) || (cid
->type
== 0x82)) {
599 /* Go through each element and process */
600 for (x
= 0; x
< cid
->pos
;) {
601 switch (cid
->rawdata
[x
++]) {
606 case 3: /* Number (for Zebble) */
608 res
= cid
->rawdata
[x
];
610 ast_log(LOG_NOTICE
, "Truncating long caller ID number from %d bytes to 32\n", cid
->rawdata
[x
]);
613 if (ast_strlen_zero(cid
->number
)) {
614 memcpy(cid
->number
, cid
->rawdata
+ x
+ 1, res
);
616 cid
->number
[res
] = '\0';
619 case 6: /* Stentor Call Qualifier (ie. Long Distance call) */
623 res
= cid
->rawdata
[x
];
625 ast_log(LOG_NOTICE
, "Truncating long caller ID name from %d bytes to 32\n", cid
->rawdata
[x
]);
628 memcpy(cid
->name
, cid
->rawdata
+ x
+ 1, res
);
629 cid
->name
[res
] = '\0';
631 case 11: /* Message Waiting */
632 res
= cid
->rawdata
[x
+ 1];
634 cid
->flags
|= CID_MSGWAITING
;
636 cid
->flags
|= CID_NOMSGWAITING
;
638 case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting */
639 case 19: /* UK: Network message system status (Number of messages waiting) */
640 case 22: /* Something French */
643 ast_log(LOG_NOTICE
, "Unknown IE %d\n", cid
->rawdata
[x
- 1]);
645 res
= cid
->rawdata
[x
];
646 if (0 > res
){ /* Negative offset in the CID Spill */
647 ast_log(LOG_NOTICE
, "IE %d has bad field length of %d at offset %d\n", cid
->rawdata
[x
-1], cid
->rawdata
[x
], x
);
650 break; /* Exit the loop */
652 x
+= cid
->rawdata
[x
];
655 } else if (cid
->type
== 0x6) {
657 if (cid
->rawdata
[2] == 0x42) {
658 cid
->flags
|= CID_MSGWAITING
;
659 } else if (cid
->rawdata
[2] == 0x6f) {
660 cid
->flags
|= CID_NOMSGWAITING
;
664 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
;
683 ast_log(LOG_ERROR
, "Dunno what to do with a digit in sawflag %d\n", cid
->sawflag
);
688 memcpy(cid
->oldstuff
, buf
, mylen
* 2);
689 cid
->oldlen
= mylen
* 2;
696 void callerid_free(struct callerid_state
*cid
)
701 static int callerid_genmsg(char *msg
, int size
, const char *number
, const char *name
, int flags
)
703 struct timeval tv
= ast_tvnow();
710 ast_localtime(&tv
, &tm
, NULL
);
714 /* Format time and message header */
715 res
= snprintf(ptr
, size
, "\001\010%02d%02d%02d%02d", tm
.tm_mon
+ 1,
716 tm
.tm_mday
, tm
.tm_hour
, tm
.tm_min
);
719 if (ast_strlen_zero(number
) || (flags
& CID_UNKNOWN_NUMBER
)) {
720 /* Indicate number not known */
721 res
= snprintf(ptr
, size
, "\004\001O");
724 } else if (flags
& CID_PRIVATE_NUMBER
) {
725 /* Indicate number is private */
726 res
= snprintf(ptr
, size
, "\004\001P");
730 /* 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 */
759 res
= snprintf(ptr
, size
, "\007%c", i
);
762 for (x
= 0; x
< i
; x
++)
772 int vmwi_generate(unsigned char *buf
, int active
, int mdmf
, int codec
)
774 unsigned char msg
[256];
784 /* MDMF Message waiting */
788 /* IE is "Message Waiting Parameter" */
790 /* Length of IE is one */
798 /* SDMF Message waiting */
813 for (x
= 0; x
< len
; x
++)
815 sum
= (256 - (sum
& 255));
817 /* Wait a half a second */
818 for (x
= 0; x
< 4000; x
++)
820 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
821 for (x
= 0; x
< 30; x
++)
823 /* Send 170ms of callerid marks */
824 for (x
= 0; x
< 170; x
++)
826 for (x
= 0; x
< len
; x
++) {
829 /* Send 50 more ms of marks */
830 for (x
= 0; x
< 50; x
++)
835 int callerid_generate(unsigned char *buf
, const char *number
, const char *name
, int flags
, int callwaiting
, int codec
)
841 /* Initial carriers (real/imaginary) */
846 len
= callerid_genmsg(msg
, sizeof(msg
), number
, name
, flags
);
848 /* Wait a half a second */
849 for (x
= 0; x
< 4000; x
++)
851 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
852 for (x
= 0; x
< 30; x
++)
855 /* Send 150ms of callerid marks */
856 for (x
= 0; x
< 150; x
++)
858 /* Send 0x80 indicating MDMF format */
860 /* Put length of whole message */
862 sum
= 0x80 + strlen(msg
);
863 /* Put each character of message and update checksum */
864 for (x
= 0; x
< len
; x
++) {
868 /* Send 2's compliment of sum */
869 PUT_CLID(256 - (sum
& 255));
871 /* Send 50 more ms of marks */
872 for (x
= 0; x
< 50; x
++)
878 /*! \brief Clean up phone string
879 * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
880 * Basically, remove anything that could be invalid in a pattern.
882 void ast_shrink_phone_number(char *n
)
887 for (x
= 0; n
[x
]; x
++) {
906 /* ignore parenthesis and whitespace */
907 if (!strchr("( )", n
[x
]))
914 /*! \brief Checks if phone number consists of valid characters
915 \param exten String that needs to be checked
916 \param valid Valid characters in string
917 \return 1 if valid string, 0 if string contains invalid characters
919 static int ast_is_valid_string(const char *exten
, const char *valid
)
923 if (ast_strlen_zero(exten
))
925 for (x
= 0; exten
[x
]; x
++)
926 if (!strchr(valid
, exten
[x
]))
931 /*! \brief checks if string consists only of digits and * \# and +
932 \return 1 if string is valid AST phone number
935 int ast_isphonenumber(const char *n
)
937 return ast_is_valid_string(n
, "0123456789*#+");
940 /*! \brief checks if string consists only of digits and ( ) - * \# and +
941 Pre-qualifies the string for ast_shrink_phone_number()
942 \return 1 if string is valid AST shrinkable phone number
945 int ast_is_shrinkable_phonenumber(const char *exten
)
947 return ast_is_valid_string(exten
, "0123456789*#+()-.");
950 /*! \brief parse string for caller id information
951 \return always returns 0, as the code always returns something.
952 XXX note that 'name' is not parsed consistently e.g. we have
955 " foo bar " <123> 123 ' foo bar ' (with spaces around)
956 " foo bar " NULL 'foo bar' (without spaces around)
957 " foo bar <123>" 123 '" foo bar'
958 The parsing of leading and trailing space/quotes should be more consistent.
960 int ast_callerid_parse(char *instr
, char **name
, char **location
)
962 char *ns
, *ne
, *ls
, *le
;
964 /* Try "name" <location> format or name <location> format */
965 if ((ls
= strchr(instr
, '<')) && (le
= strchr(ls
, '>'))) {
966 *ls
= *le
= '\0'; /* location found, trim off the brackets */
967 *location
= ls
+ 1; /* and this is the result */
968 if ((ns
= strchr(instr
, '"')) && (ne
= strchr(ns
+ 1, '"'))) {
969 *ns
= *ne
= '\0'; /* trim off the quotes */
970 *name
= ns
+ 1; /* and this is the name */
971 } else { /* no quotes, trim off leading and trailing spaces */
972 *name
= ast_skip_blanks(instr
);
973 ast_trim_blanks(*name
);
975 } else { /* no valid brackets */
978 ast_copy_string(tmp
, instr
, sizeof(tmp
));
979 ast_shrink_phone_number(tmp
);
980 if (ast_isphonenumber(tmp
)) { /* Assume it's just a location */
982 strcpy(instr
, tmp
); /* safe, because tmp will always be the same size or smaller than instr */
984 } else { /* Assume it's just a name. */
986 if ((ns
= strchr(instr
, '"')) && (ne
= strchr(ns
+ 1, '"'))) {
987 *ns
= *ne
= '\0'; /* trim off the quotes */
988 *name
= ns
+ 1; /* and this is the name */
989 } else { /* no quotes, trim off leading and trailing spaces */
990 *name
= ast_skip_blanks(instr
);
991 ast_trim_blanks(*name
);
998 static int __ast_callerid_generate(unsigned char *buf
, const char *name
, const char *number
, int callwaiting
, int codec
)
1000 if (ast_strlen_zero(name
))
1002 if (ast_strlen_zero(number
))
1004 return callerid_generate(buf
, number
, name
, 0, callwaiting
, codec
);
1007 int ast_callerid_generate(unsigned char *buf
, const char *name
, const char *number
, int codec
)
1009 return __ast_callerid_generate(buf
, name
, number
, 0, codec
);
1012 int ast_callerid_callwaiting_generate(unsigned char *buf
, const char *name
, const char *number
, int codec
)
1014 return __ast_callerid_generate(buf
, name
, number
, 1, codec
);
1017 char *ast_callerid_merge(char *buf
, int bufsiz
, const char *name
, const char *num
, const char *unknown
)
1020 unknown
= "<unknown>";
1022 snprintf(buf
, bufsiz
, "\"%s\" <%s>", name
, num
);
1024 ast_copy_string(buf
, name
, bufsiz
);
1026 ast_copy_string(buf
, num
, bufsiz
);
1028 ast_copy_string(buf
, unknown
, bufsiz
);
1032 int ast_callerid_split(const char *buf
, char *name
, int namelen
, char *num
, int numlen
)
1035 char *l
= NULL
, *n
= NULL
;
1037 tmp
= ast_strdupa(buf
);
1038 ast_callerid_parse(tmp
, &n
, &l
);
1040 ast_copy_string(name
, n
, namelen
);
1044 ast_shrink_phone_number(l
);
1045 ast_copy_string(num
, l
, numlen
);
1051 /*! \brief Translation table for Caller ID Presentation settings */
1055 const char *description
;
1057 { AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED
, "allowed_not_screened", "Presentation Allowed, Not Screened"},
1058 { AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN
, "allowed_passed_screen", "Presentation Allowed, Passed Screen"},
1059 { AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN
, "allowed_failed_screen", "Presentation Allowed, Failed Screen"},
1060 { AST_PRES_ALLOWED_NETWORK_NUMBER
, "allowed", "Presentation Allowed, Network Number"},
1061 { AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED
, "prohib_not_screened", "Presentation Prohibited, Not Screened"},
1062 { AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN
, "prohib_passed_screen", "Presentation Prohibited, Passed Screen"},
1063 { AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN
, "prohib_failed_screen", "Presentation Prohibited, Failed Screen"},
1064 { AST_PRES_PROHIB_NETWORK_NUMBER
, "prohib", "Presentation Prohibited, Network Number"},
1065 { AST_PRES_NUMBER_NOT_AVAILABLE
, "unavailable", "Number Unavailable"},
1068 /*! \brief Convert caller ID text code to value
1069 used in config file parsing
1070 \param data text string
1071 \return value AST_PRES_ from callerid.h
1073 int ast_parse_caller_presentation(const char *data
)
1077 for (i
= 0; i
< ((sizeof(pres_types
) / sizeof(pres_types
[0]))); i
++) {
1078 if (!strcasecmp(pres_types
[i
].name
, data
))
1079 return pres_types
[i
].val
;
1085 /*! \brief Convert caller ID pres value to explanatory string
1086 \param data value (see callerid.h AST_PRES_ )
1087 \return string for human presentation
1089 const char *ast_describe_caller_presentation(int data
)
1093 for (i
= 0; i
< ((sizeof(pres_types
) / sizeof(pres_types
[0]))); i
++) {
1094 if (pres_types
[i
].val
== data
)
1095 return pres_types
[i
].description
;
1101 /*! \brief Convert caller ID pres value to text code
1102 \param data text string
1103 \return string for config file
1105 const char *ast_named_caller_presentation(int data
)
1109 for (i
= 0; i
< ((sizeof(pres_types
) / sizeof(pres_types
[0]))); i
++) {
1110 if (pres_types
[i
].val
== data
)
1111 return pres_types
[i
].name
;