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
35 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
37 #include "asterisk/ulaw.h"
38 #include "asterisk/alaw.h"
39 #include "asterisk/frame.h"
40 #include "asterisk/channel.h"
41 #include "asterisk/callerid.h"
42 #include "asterisk/logger.h"
43 #include "asterisk/fskmodem.h"
44 #include "asterisk/utils.h"
46 struct callerid_state {
62 float cid_dr[4], cid_di[4];
63 float clidsb = 8000.0 / 1200.0;
65 float casdr1, casdi1, casdr2, casdi2;
67 #define CALLERID_SPACE 2200.0 /*!< 2200 hz for "0" */
68 #define CALLERID_MARK 1200.0 /*!< 1200 hz for "1" */
69 #define SAS_FREQ 440.0
70 #define CAS_FREQ1 2130.0
71 #define CAS_FREQ2 2750.0
73 #define AST_CALLERID_UNKNOWN "<unknown>"
75 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)
80 t = *cr1 * ddr1 - *ci1 * ddi1;
81 *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
83 t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
87 t = *cr2 * ddr2 - *ci2 * ddi2;
88 *ci2 = *cr2 * ddi2 + *ci2 * ddr2;
90 t = 2.0 - (*cr2 * *cr2 + *ci2 * *ci2);
93 buf[x] = AST_LIN2X((*cr1 + *cr2) * 2048.0);
97 static inline void gen_tone(unsigned char *buf, int len, int codec, float ddr1, float ddi1, float *cr1, float *ci1)
101 for (x=0;x<len;x++) {
102 t = *cr1 * ddr1 - *ci1 * ddi1;
103 *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
105 t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
108 buf[x] = AST_LIN2X(*cr1 * 8192.0);
112 /*! \brief Initialize stuff for inverse FFT */
113 void callerid_init(void)
115 cid_dr[0] = cos(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
116 cid_di[0] = sin(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
117 cid_dr[1] = cos(CALLERID_MARK * 2.0 * M_PI / 8000.0);
118 cid_di[1] = sin(CALLERID_MARK * 2.0 * M_PI / 8000.0);
119 sasdr = cos(SAS_FREQ * 2.0 * M_PI / 8000.0);
120 sasdi = sin(SAS_FREQ * 2.0 * M_PI / 8000.0);
121 casdr1 = cos(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
122 casdi1 = sin(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
123 casdr2 = cos(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
124 casdi2 = sin(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
127 struct callerid_state *callerid_new(int cid_signalling)
129 struct callerid_state *cid;
130 cid = malloc(sizeof(struct callerid_state));
132 memset(cid, 0, sizeof(struct callerid_state));
133 cid->fskd.spb = 7; /* 1200 baud */
134 cid->fskd.hdlc = 0; /* Async */
135 cid->fskd.nbit = 8; /* 8 bits */
136 cid->fskd.nstop = 1; /* 1 stop bit */
137 cid->fskd.paridad = 0; /* No parity */
138 cid->fskd.bw=1; /* Filter 800 Hz */
139 if (cid_signalling == 2) { /* v23 signalling */
140 cid->fskd.f_mark_idx = 4; /* 1300 Hz */
141 cid->fskd.f_space_idx = 5; /* 2100 Hz */
142 } else { /* Bell 202 signalling as default */
143 cid->fskd.f_mark_idx = 2; /* 1200 Hz */
144 cid->fskd.f_space_idx = 3; /* 2200 Hz */
146 cid->fskd.pcola = 0; /* No clue */
147 cid->fskd.cont = 0; /* Digital PLL reset */
150 memset(cid->name, 0, sizeof(cid->name));
151 memset(cid->number, 0, sizeof(cid->number));
152 cid->flags = CID_UNKNOWN_NAME | CID_UNKNOWN_NUMBER;
155 ast_log(LOG_WARNING, "Out of memory\n");
159 void callerid_get(struct callerid_state *cid, char **name, char **number, int *flags)
162 if (cid->flags & (CID_UNKNOWN_NAME | CID_PRIVATE_NUMBER))
166 if (cid->flags & (CID_UNKNOWN_NUMBER | CID_PRIVATE_NUMBER))
169 *number = cid->number;
172 void callerid_get_dtmf(char *cidstring, char *number, int *flags)
177 /* "Clear" the number-buffer. */
180 if (strlen(cidstring) < 2) {
181 ast_log(LOG_DEBUG, "No cid detected\n");
182 *flags = CID_UNKNOWN_NUMBER;
186 /* Detect protocol and special types */
187 if (cidstring[0] == 'B') {
188 /* Handle special codes */
189 code = atoi(&cidstring[1]);
191 *flags = CID_UNKNOWN_NUMBER;
193 *flags = CID_PRIVATE_NUMBER;
195 ast_log(LOG_DEBUG, "Unknown DTMF code %d\n", code);
196 } else if (cidstring[0] == 'D' && cidstring[2] == '#') {
197 /* .DK special code */
198 if (cidstring[1] == '1')
199 *flags = CID_PRIVATE_NUMBER;
200 if (cidstring[1] == '2' || cidstring[1] == '3')
201 *flags = CID_UNKNOWN_NUMBER;
202 } else if (cidstring[0] == 'D' || cidstring[0] == 'A') {
203 /* "Standard" callerid */
204 for (i = 1; i < strlen(cidstring); i++ ) {
205 if (cidstring[i] == 'C' || cidstring[i] == '#')
207 if (isdigit(cidstring[i]))
208 number[i-1] = cidstring[i];
210 ast_log(LOG_DEBUG, "Unknown CID digit '%c'\n",
214 } else if (isdigit(cidstring[0])) {
215 /* It begins with a digit, so we parse it as a number and hope
217 ast_log(LOG_WARNING, "Couldn't detect start-character. CID "
218 "parsing might be unreliable\n");
219 for (i = 0; i < strlen(cidstring); i++) {
220 if (isdigit(cidstring[i]))
221 number[i] = cidstring[i];
227 ast_log(LOG_DEBUG, "Unknown CID protocol, start digit '%c'\n",
229 *flags = CID_UNKNOWN_NUMBER;
233 int ast_gen_cas(unsigned char *outbuf, int sendsas, int len, int codec)
244 gen_tone(outbuf, saslen, codec, sasdr, sasdi, &cr1, &ci1);
250 gen_tones(outbuf + pos, len, codec, casdr1, casdi1, casdr2, casdi2, &cr1, &ci1, &cr2, &ci2);
254 int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int codec)
261 short *buf = malloc(2 * len + cid->oldlen);
264 ast_log(LOG_WARNING, "Out of memory\n");
267 memset(buf, 0, 2 * len + cid->oldlen);
268 memcpy(buf, cid->oldstuff, cid->oldlen);
269 mylen += cid->oldlen/2;
271 buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
272 while(mylen >= 160) {
274 res = fsk_serie(&cid->fskd, buf, &mylen, &b);
276 ast_log(LOG_ERROR, "fsk_serie made mylen < 0 (%d)\n", mylen);
279 buf += (olen - mylen);
281 ast_log(LOG_NOTICE, "fsk_serie failed\n");
285 /* Ignore invalid bytes */
288 switch(cid->sawflag) {
289 case 0: /* Look for flag */
293 case 2: /* Get lead-in */
294 if ((b == 0x04) || (b == 0x80)) {
300 case 3: /* Get length */
301 /* Not a lead in. We're ready */
307 case 4: /* Retrieve message */
308 if (cid->pos >= 128) {
309 ast_log(LOG_WARNING, "Caller ID too long???\n");
312 cid->rawdata[cid->pos++] = b;
316 cid->rawdata[cid->pos] = '\0';
320 case 5: /* Check checksum */
321 if (b != (256 - (cid->cksum & 0xff))) {
322 ast_log(LOG_NOTICE, "Caller*ID failed checksum\n");
328 cid->number[0] = '\0';
330 /* If we get this far we're fine. */
331 if (cid->type == 0x80) {
333 /* Go through each element and process */
334 for (x=0;x< cid->pos;) {
335 switch(cid->rawdata[x++]) {
340 case 3: /* Number (for Zebble) */
342 res = cid->rawdata[x];
344 ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]);
347 if (ast_strlen_zero(cid->number)) {
348 memcpy(cid->number, cid->rawdata + x + 1, res);
350 cid->number[res] = '\0';
353 case 6: /* Stentor Call Qualifier (ie. Long Distance call) */
357 res = cid->rawdata[x];
359 ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]);
362 memcpy(cid->name, cid->rawdata + x + 1, res);
363 cid->name[res] = '\0';
365 case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting */
366 case 19: /* UK: Network message system status (Number of messages waiting) */
367 case 22: /* Something French */
370 ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x-1]);
372 x += cid->rawdata[x];
377 ast_copy_string(cid->number, cid->rawdata + 8, sizeof(cid->number));
381 if (!strcmp(cid->number, "P")) {
382 strcpy(cid->number, "");
383 cid->flags |= CID_PRIVATE_NUMBER;
384 } else if (!strcmp(cid->number, "O") || ast_strlen_zero(cid->number)) {
385 strcpy(cid->number, "");
386 cid->flags |= CID_UNKNOWN_NUMBER;
388 if (!strcmp(cid->name, "P")) {
389 strcpy(cid->name, "");
390 cid->flags |= CID_PRIVATE_NAME;
391 } else if (!strcmp(cid->name, "O") || ast_strlen_zero(cid->name)) {
392 strcpy(cid->name, "");
393 cid->flags |= CID_UNKNOWN_NAME;
398 ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag);
403 memcpy(cid->oldstuff, buf, mylen * 2);
404 cid->oldlen = mylen * 2;
411 void callerid_free(struct callerid_state *cid)
416 static int callerid_genmsg(char *msg, int size, char *number, char *name, int flags)
429 /* Format time and message header */
430 res = snprintf(ptr, size, "\001\010%02d%02d%02d%02d", tm.tm_mon + 1,
431 tm.tm_mday, tm.tm_hour, tm.tm_min);
434 if (ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) {
435 /* Indicate number not known */
436 res = snprintf(ptr, size, "\004\001O");
439 } else if (flags & CID_PRIVATE_NUMBER) {
440 /* Indicate number is private */
441 res = snprintf(ptr, size, "\004\001P");
445 /* Send up to 16 digits of number MAX */
448 res = snprintf(ptr, size, "\002%c", i);
458 if (ast_strlen_zero(name) || (flags & CID_UNKNOWN_NAME)) {
459 /* Indicate name not known */
460 res = snprintf(ptr, size, "\010\001O");
463 } else if (flags & CID_PRIVATE_NAME) {
464 /* Indicate name is private */
465 res = snprintf(ptr, size, "\010\001P");
469 /* Send up to 16 digits of name MAX */
472 res = snprintf(ptr, size, "\007%c", i);
485 int vmwi_generate(unsigned char *buf, int active, int mdmf, int codec)
487 unsigned char msg[256];
496 /* MDMF Message waiting */
500 /* IE is "Message Waiting Parameter" */
502 /* Length of IE is one */
510 /* SDMF Message waiting */
527 sum = (256 - (sum & 255));
529 /* Wait a half a second */
532 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
535 /* Send 170ms of callerid marks */
538 for (x=0;x<len;x++) {
541 /* Send 50 more ms of marks */
547 int callerid_generate(unsigned char *buf, char *number, char *name, int flags, int callwaiting, int codec)
552 /* Initial carriers (real/imaginary) */
557 len = callerid_genmsg(msg, sizeof(msg), number, name, flags);
559 /* Wait a half a second */
562 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
566 /* Send 150ms of callerid marks */
569 /* Send 0x80 indicating MDMF format */
571 /* Put length of whole message */
573 sum = 0x80 + strlen(msg);
574 /* Put each character of message and update checksum */
575 for (x=0;x<len; x++) {
579 /* Send 2's compliment of sum */
580 PUT_CLID(256 - (sum & 255));
582 /* Send 50 more ms of marks */
589 void ast_shrink_phone_number(char *n)
612 if (!strchr("( )", n[x]))
619 /*! \brief checks if string consists only of digits and * \# and +
620 \return 1 if string is valid AST phone number
623 int ast_isphonenumber(char *n)
626 if (ast_strlen_zero(n))
629 if (!strchr("0123456789*#+", n[x]))
634 /*! \brief parse string for caller id information
635 \return returns -1 on failure, otherwise 0
637 int ast_callerid_parse(char *instr, char **name, char **location)
642 /* Try for "name" <location> format or
643 name <location> format */
644 if ((ls = strchr(instr, '<')) && (le = strchr(ls, '>'))) {
645 /* Found the location */
649 if ((ns = strchr(instr, '\"')) && (ne = strchr(ns + 1, '\"'))) {
650 /* Get name out of quotes */
656 /* Just trim off any trailing spaces */
658 while(!ast_strlen_zero(instr) && (instr[strlen(instr) - 1] < 33))
659 instr[strlen(instr) - 1] = '\0';
660 /* And leading spaces */
661 *name = ast_skip_blanks(*name);
665 ast_copy_string(tmp, instr, sizeof(tmp));
666 ast_shrink_phone_number(tmp);
667 if (ast_isphonenumber(tmp)) {
668 /* Assume it's just a location */
672 /* Assume it's just a name. Make sure it's not quoted though */
674 while(*(*name) && ((*(*name) < 33) || (*(*name) == '\"'))) (*name)++;
675 ne = *name + strlen(*name) - 1;
676 while((ne > *name) && ((*ne < 33) || (*ne == '\"'))) { *ne = '\0'; ne--; }
684 static int __ast_callerid_generate(unsigned char *buf, char *name, char *number, int callwaiting, int codec)
686 if (ast_strlen_zero(name))
688 if (ast_strlen_zero(number))
690 return callerid_generate(buf, number, name, 0, callwaiting, codec);
693 int ast_callerid_generate(unsigned char *buf, char *name, char *number, int codec)
695 return __ast_callerid_generate(buf, name, number, 0, codec);
698 int ast_callerid_callwaiting_generate(unsigned char *buf, char *name, char *number, int codec)
700 return __ast_callerid_generate(buf, name, number, 1, codec);
703 char *ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
706 unknown = "<unknown>";
708 snprintf(buf, bufsiz, "\"%s\" <%s>", name, num);
710 ast_copy_string(buf, name, bufsiz);
712 ast_copy_string(buf, num, bufsiz);
714 ast_copy_string(buf, unknown, bufsiz);
718 int ast_callerid_split(const char *buf, char *name, int namelen, char *num, int numlen)
721 char *l = NULL, *n = NULL;
722 tmp = ast_strdupa(buf);
728 ast_callerid_parse(tmp, &n, &l);
730 ast_copy_string(name, n, namelen);
734 ast_shrink_phone_number(l);
735 ast_copy_string(num, l, numlen);
746 { AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened", "Presentation Allowed, Not Screened"},
747 { AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", "Presentation Allowed, Passed Screen"},
748 { AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", "Presentation Allowed, Failed Screen"},
749 { AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed", "Presentation Allowed, Network Number"},
750 { AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "prohib_not_screened", "Presentation Prohibited, Not Screened"},
751 { AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", "Presentation Prohibited, Passed Screen"},
752 { AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", "Presentation Prohibited, Failed Screen"},
753 { AST_PRES_PROHIB_NETWORK_NUMBER, "prohib", "Presentation Prohibited, Network Number"},
754 { AST_PRES_NUMBER_NOT_AVAILABLE, "unavailable", "Number Unavailable"},
757 /*! \brief Convert caller ID text code to value
758 used in config file parsing
759 \param data text string
760 \return value AST_PRES_ from callerid.h
762 int ast_parse_caller_presentation(const char *data)
766 for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
767 if (!strcasecmp(pres_types[i].name, data))
768 return pres_types[i].val;
774 /*! \brief Convert caller ID pres value to explanatory string
775 \param data value (see callerid.h AST_PRES_ )
776 \return string for human presentation
778 const char *ast_describe_caller_presentation(int data)
782 for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
783 if (pres_types[i].val == data)
784 return pres_types[i].description;