various cleanups, remove support for CVS checkouts
[asterisk-bristuff.git] / callerid.c
blob98cb7d0815396711150e1144761585e413f741e7
1 /*
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.
19 /*! \file
21 * \brief CallerID Generation support
23 * \author Mark Spencer <markster@digium.com>
26 #include "asterisk.h"
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
30 #include <time.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <math.h>
36 #include <ctype.h>
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 {
49 fsk_data fskd;
50 char rawdata[256];
51 short oldstuff[160];
52 int oldlen;
53 int pos;
54 int type;
55 int cksum;
56 char name[64];
57 char number[64];
58 int flags;
59 int sawflag;
60 int len;
62 int skipflag;
63 unsigned short crc;
67 float cid_dr[4], cid_di[4];
68 float clidsb = 8000.0 / 1200.0;
69 float sasdr, sasdi;
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)
82 int x;
83 float t;
84 for (x=0;x<len;x++) {
85 t = *cr1 * ddr1 - *ci1 * ddi1;
86 *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
87 *cr1 = t;
88 t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
89 *cr1 *= t;
90 *ci1 *= t;
92 t = *cr2 * ddr2 - *ci2 * ddi2;
93 *ci2 = *cr2 * ddi2 + *ci2 * ddr2;
94 *cr2 = t;
95 t = 2.0 - (*cr2 * *cr2 + *ci2 * *ci2);
96 *cr2 *= t;
97 *ci2 *= t;
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)
104 int x;
105 float t;
106 for (x=0;x<len;x++) {
107 t = *cr1 * ddr1 - *ci1 * ddi1;
108 *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
109 *cr1 = t;
110 t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
111 *cr1 *= t;
112 *ci1 *= t;
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;
155 /* cid->pos = 0; */
158 return cid;
161 void callerid_get(struct callerid_state *cid, char **name, char **number, int *flags)
163 *flags = cid->flags;
164 if (cid->flags & (CID_UNKNOWN_NAME | CID_PRIVATE_NUMBER))
165 *name = NULL;
166 else
167 *name = cid->name;
168 if (cid->flags & (CID_UNKNOWN_NUMBER | CID_PRIVATE_NUMBER))
169 *number = NULL;
170 else
171 *number = cid->number;
174 void callerid_get_dtmf(char *cidstring, char *number, int *flags)
176 int i;
177 int code;
179 /* "Clear" the number-buffer. */
180 number[0] = 0;
182 if (strlen(cidstring) < 2) {
183 ast_log(LOG_DEBUG, "No cid detected\n");
184 *flags = CID_UNKNOWN_NUMBER;
185 return;
188 /* Detect protocol and special types */
189 if (cidstring[0] == 'B') {
190 /* Handle special codes */
191 code = atoi(&cidstring[1]);
192 if (code == 0)
193 *flags = CID_UNKNOWN_NUMBER;
194 else if (code == 10)
195 *flags = CID_PRIVATE_NUMBER;
196 else
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] == '#')
208 break;
209 if (isdigit(cidstring[i]))
210 number[i-1] = cidstring[i];
211 else
212 ast_log(LOG_DEBUG, "Unknown CID digit '%c'\n",
213 cidstring[i]);
215 number[i-1] = 0;
216 } else if (isdigit(cidstring[0])) {
217 /* It begins with a digit, so we parse it as a number and hope
218 * for the best */
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];
224 else
225 break;
227 number[i] = 0;
228 } else {
229 ast_log(LOG_DEBUG, "Unknown CID protocol, start digit '%c'\n",
230 cidstring[0]);
231 *flags = CID_UNKNOWN_NUMBER;
235 int ast_gen_cas(unsigned char *outbuf, int sendsas, int len, int codec)
237 int pos = 0;
238 int saslen=2400;
239 float cr1 = 1.0;
240 float ci1 = 0.0;
241 float cr2 = 1.0;
242 float ci2 = 0.0;
243 if (sendsas) {
244 if (len < saslen)
245 return -1;
246 gen_tone(outbuf, saslen, codec, sasdr, sasdi, &cr1, &ci1);
247 len -= saslen;
248 pos += saslen;
249 cr2 = cr1;
250 ci2 = ci1;
252 gen_tones(outbuf + pos, len, codec, casdr1, casdi1, casdr2, casdi2, &cr1, &ci1, &cr2, &ci2);
253 return 0;
256 static unsigned short calc_crc(unsigned short crc, unsigned char data)
258 unsigned int i, j, org, dst;
259 org = data;
260 dst = 0;
262 for (i=0; i < CHAR_BIT; i++) {
263 org <<= 1;
264 dst >>= 1;
265 if (org & 0x100) {
266 dst |= 0x80;
269 data = (unsigned char)dst;
270 crc ^= (unsigned int)data << (16 - CHAR_BIT);
271 for ( j=0; j<CHAR_BIT; j++ ) {
272 if ( crc & 0x8000U )
273 crc = (crc << 1) ^ 0x1021U ;
274 else
275 crc <<= 1 ;
277 return crc;
280 int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int len, int codec)
282 int mylen = len;
283 int olen;
284 int b = 'X';
285 int b2 ;
286 int res;
287 int x;
288 short *buf;
289 short *obuf;
291 if (!(buf = ast_calloc(1, 2 * len + cid->oldlen))) {
292 return -1;
295 obuf = buf;
296 memcpy(buf, cid->oldstuff, cid->oldlen);
297 mylen += cid->oldlen/2;
299 for (x=0;x<len;x++)
300 buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
302 while (mylen >= 160) {
303 b = b2 = 0 ;
304 olen = mylen;
305 res = fsk_serie(&cid->fskd, buf, &mylen, &b);
307 if (mylen < 0) {
308 ast_log(LOG_ERROR, "fsk_serie made mylen < 0 (%d)\n", mylen);
309 return -1;
312 buf += (olen - mylen);
314 if (res < 0) {
315 ast_log(LOG_NOTICE, "fsk_serie failed\n");
316 return -1;
319 if (res == 1) {
321 b2 = b ;
322 b = b & 0x7f ;
324 /* crc checksum calculation */
325 if ( cid->sawflag > 1 ) {
326 cid->crc = calc_crc(cid->crc, (unsigned char)b2);
329 /* Ignore invalid bytes */
330 if (b > 0xff) {
331 continue;
334 /* skip DLE if needed */
335 if ( cid->sawflag > 0 ) {
336 if ( cid->sawflag != 5 && cid->skipflag == 0 && b == 0x10 ) {
337 cid->skipflag = 1 ;
338 continue ;
341 if ( cid->skipflag == 1 ) {
342 cid->skipflag = 0 ;
345 /* caller id retrieval */
346 switch(cid->sawflag) {
347 case 0: /* DLE */
348 if (b == 0x10) {
349 cid->sawflag = 1;
350 cid->skipflag = 0;
351 cid->crc = 0;
353 break;
354 case 1: /* SOH */
355 if (b == 0x01) {
356 cid->sawflag = 2;
358 break ;
359 case 2: /* HEADER */
360 if (b == 0x07) {
361 cid->sawflag = 3;
363 break;
364 case 3: /* STX */
365 if (b == 0x02) {
366 cid->sawflag = 4;
368 break;
369 case 4: /* SERVICE TYPE */
370 if (b == 0x40) {
371 cid->sawflag = 5;
373 break;
374 case 5: /* Frame Length */
375 cid->sawflag = 6;
376 break;
377 case 6: /* NUMBER TYPE */
378 cid->sawflag = 7;
379 cid->pos = 0;
380 cid->rawdata[cid->pos++] = b;
381 break;
382 case 7: /* NUMBER LENGTH */
383 cid->sawflag = 8;
384 cid->len = b;
385 if ( (cid->len+2) >= sizeof( cid->rawdata ) ) {
386 ast_log(LOG_WARNING, "too long caller id string\n" ) ;
387 return -1;
389 cid->rawdata[cid->pos++] = b;
390 break;
391 case 8: /* Retrieve message */
392 cid->rawdata[cid->pos++] = b;
393 cid->len--;
394 if (cid->len<=0) {
395 cid->rawdata[cid->pos] = '\0';
396 cid->sawflag = 9;
398 break;
399 case 9: /* ETX */
400 cid->sawflag = 10;
401 break;
402 case 10: /* CRC Checksum 1 */
403 cid->sawflag = 11;
404 break;
405 case 11: /* CRC Checksum 2 */
406 cid->sawflag = 12;
407 if ( cid->crc != 0 ) {
408 ast_log(LOG_WARNING, "crc checksum error\n" ) ;
409 return -1;
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';
416 cid->name[0] = '\0';
417 cid->flags = 0;
418 res = cid->rawdata[x++];
419 ast_copy_string(cid->number, &cid->rawdata[x], res+1 );
420 x += res;
421 break;
422 case 0x21: /* additional information */
423 /* length */
424 x++;
425 /* number type */
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]);
437 break ;
439 x++;
440 /* numbering plan octed 4 */
441 x++;
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]);
454 break ;
456 x++;
457 break ;
458 case 0x04: /* no callerid reason */
459 /* length */
460 x++;
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]);
470 break ;
472 x++;
473 break ;
474 case 0x09: /* dialed number */
475 /* length */
476 res = cid->rawdata[x++];
477 /* dialed number */
478 x += res;
479 break ;
480 case 0x22: /* dialed number additional information */
481 /* length */
482 x++;
483 /* number type */
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]);
495 break ;
497 x++;
498 /* numbering plan octed 4 */
499 x++;
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]);
512 break ;
514 x++;
515 break ;
518 return 1;
519 break;
520 default:
521 ast_log(LOG_ERROR, "invalid value in sawflag %d\n", cid->sawflag);
525 if (mylen) {
526 memcpy(cid->oldstuff, buf, mylen * 2);
527 cid->oldlen = mylen * 2;
528 } else
529 cid->oldlen = 0;
530 free(obuf);
531 return 0;
535 int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int codec)
537 int mylen = len;
538 int olen;
539 int b = 'X';
540 int res;
541 int x;
542 short *buf;
543 short *obuf;
545 if (!(buf = ast_calloc(1, 2 * len + cid->oldlen))) {
546 return -1;
549 obuf = buf;
550 memcpy(buf, cid->oldstuff, cid->oldlen);
551 mylen += cid->oldlen/2;
553 for (x=0;x<len;x++)
554 buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
555 while(mylen >= 160) {
556 olen = mylen;
557 res = fsk_serie(&cid->fskd, buf, &mylen, &b);
558 if (mylen < 0) {
559 ast_log(LOG_ERROR, "fsk_serie made mylen < 0 (%d)\n", mylen);
560 free(obuf);
561 return -1;
563 buf += (olen - mylen);
564 if (res < 0) {
565 ast_log(LOG_NOTICE, "fsk_serie failed\n");
566 return -1;
568 if (res == 1) {
569 /* Ignore invalid bytes */
570 if (b > 0xff)
571 continue;
572 switch(cid->sawflag) {
573 case 0: /* Look for flag */
574 if (b == 'U')
575 cid->sawflag = 2;
576 break;
577 case 2: /* Get lead-in */
578 if ((b == 0x04) || (b == 0x80)) {
579 cid->type = b;
580 cid->sawflag = 3;
581 cid->cksum = b;
583 break;
584 case 3: /* Get length */
585 /* Not a lead in. We're ready */
586 cid->sawflag = 4;
587 cid->len = b;
588 cid->pos = 0;
589 cid->cksum += b;
590 break;
591 case 4: /* Retrieve message */
592 if (cid->pos >= 128) {
593 ast_log(LOG_WARNING, "Caller ID too long???\n");
594 free(obuf);
595 return -1;
597 cid->rawdata[cid->pos++] = b;
598 cid->len--;
599 cid->cksum += b;
600 if (!cid->len) {
601 cid->rawdata[cid->pos] = '\0';
602 cid->sawflag = 5;
604 break;
605 case 5: /* Check checksum */
606 if (b != (256 - (cid->cksum & 0xff))) {
607 ast_log(LOG_NOTICE, "Caller*ID failed checksum\n");
608 /* Try again */
609 cid->sawflag = 0;
610 break;
613 cid->number[0] = '\0';
614 cid->name[0] = '\0';
615 /* If we get this far we're fine. */
616 if (cid->type == 0x80) {
617 /* MDMF */
618 /* Go through each element and process */
619 for (x=0;x< cid->pos;) {
620 switch(cid->rawdata[x++]) {
621 case 1:
622 /* Date */
623 break;
624 case 2: /* Number */
625 case 3: /* Number (for Zebble) */
626 case 4: /* Number */
627 res = cid->rawdata[x];
628 if (res > 32) {
629 ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]);
630 res = 32;
632 if (ast_strlen_zero(cid->number)) {
633 memcpy(cid->number, cid->rawdata + x + 1, res);
634 /* Null terminate */
635 cid->number[res] = '\0';
637 break;
638 case 6: /* Stentor Call Qualifier (ie. Long Distance call) */
639 break;
640 case 7: /* Name */
641 case 8: /* Name */
642 res = cid->rawdata[x];
643 if (res > 32) {
644 ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]);
645 res = 32;
647 memcpy(cid->name, cid->rawdata + x + 1, res);
648 cid->name[res] = '\0';
649 break;
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 */
653 break;
654 default:
655 ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x-1]);
657 x += cid->rawdata[x];
658 x++;
660 } else {
661 /* SDMF */
662 ast_copy_string(cid->number, cid->rawdata + 8, sizeof(cid->number));
664 /* Update flags */
665 cid->flags = 0;
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;
680 free(obuf);
681 return 1;
682 break;
683 default:
684 ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag);
688 if (mylen) {
689 memcpy(cid->oldstuff, buf, mylen * 2);
690 cid->oldlen = mylen * 2;
691 } else
692 cid->oldlen = 0;
693 free(obuf);
694 return 0;
697 void callerid_free(struct callerid_state *cid)
699 free(cid);
702 static int callerid_genmsg(char *msg, int size, const char *number, const char *name, int flags)
704 time_t t;
705 struct tm tm;
706 char *ptr;
707 int res;
708 int i,x;
709 /* Get the time */
710 time(&t);
711 localtime_r(&t,&tm);
713 ptr = msg;
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);
718 size -= res;
719 ptr += res;
720 if (ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) {
721 /* Indicate number not known */
722 res = snprintf(ptr, size, "\004\001O");
723 size -= res;
724 ptr += res;
725 } else if (flags & CID_PRIVATE_NUMBER) {
726 /* Indicate number is private */
727 res = snprintf(ptr, size, "\004\001P");
728 size -= res;
729 ptr += res;
730 } else {
731 /* Send up to 16 digits of number MAX */
732 i = strlen(number);
733 if (i > 16) i = 16;
734 res = snprintf(ptr, size, "\002%c", i);
735 size -= res;
736 ptr += res;
737 for (x = 0; x < i; x++)
738 ptr[x] = number[x];
739 ptr[i] = '\0';
740 ptr += i;
741 size -= i;
744 if (ast_strlen_zero(name) || (flags & CID_UNKNOWN_NAME)) {
745 /* Indicate name not known */
746 res = snprintf(ptr, size, "\010\001O");
747 size -= res;
748 ptr += res;
749 } else if (flags & CID_PRIVATE_NAME) {
750 /* Indicate name is private */
751 res = snprintf(ptr, size, "\010\001P");
752 size -= res;
753 ptr += res;
754 } else {
755 /* Send up to 16 digits of name MAX */
756 i = strlen(name);
757 if (i > 16) i = 16;
758 res = snprintf(ptr, size, "\007%c", i);
759 size -= res;
760 ptr += res;
761 for (x=0;x<i;x++)
762 ptr[x] = name[x];
763 ptr[i] = '\0';
764 ptr += i;
765 size -= i;
767 return (ptr - msg);
771 int vmwi_generate(unsigned char *buf, int active, int mdmf, int codec)
773 unsigned char msg[256];
774 int len=0;
775 int sum;
776 int x;
777 int bytes = 0;
778 float cr = 1.0;
779 float ci = 0.0;
780 float scont = 0.0;
781 if (mdmf) {
782 /* MDMF Message waiting */
783 msg[len++] = 0x82;
784 /* Length is 3 */
785 msg[len++] = 3;
786 /* IE is "Message Waiting Parameter" */
787 msg[len++] = 0xb;
788 /* Length of IE is one */
789 msg[len++] = 1;
790 /* Active or not */
791 if (active)
792 msg[len++] = 0xff;
793 else
794 msg[len++] = 0x00;
795 } else {
796 /* SDMF Message waiting */
797 msg[len++] = 0x6;
798 /* Length is 3 */
799 msg[len++] = 3;
800 if (active) {
801 msg[len++] = 0x42;
802 msg[len++] = 0x42;
803 msg[len++] = 0x42;
804 } else {
805 msg[len++] = 0x6f;
806 msg[len++] = 0x6f;
807 msg[len++] = 0x6f;
810 sum = 0;
811 for (x=0; x<len; x++)
812 sum += msg[x];
813 sum = (256 - (sum & 255));
814 msg[len++] = sum;
815 /* Wait a half a second */
816 for (x=0; x<4000; x++)
817 PUT_BYTE(0x7f);
818 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
819 for (x=0; x<30; x++)
820 PUT_CLID(0x55);
821 /* Send 170ms of callerid marks */
822 for (x=0; x<170; x++)
823 PUT_CLID_MARKMS;
824 for (x=0; x<len; x++) {
825 PUT_CLID(msg[x]);
827 /* Send 50 more ms of marks */
828 for (x=0; x<50; x++)
829 PUT_CLID_MARKMS;
830 return bytes;
833 int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, int codec)
835 int bytes=0;
836 int x, sum;
837 int len;
839 /* Initial carriers (real/imaginary) */
840 float cr = 1.0;
841 float ci = 0.0;
842 float scont = 0.0;
843 char msg[256];
844 len = callerid_genmsg(msg, sizeof(msg), number, name, flags);
845 if (!callwaiting) {
846 /* Wait a half a second */
847 for (x=0; x<4000; x++)
848 PUT_BYTE(0x7f);
849 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
850 for (x=0; x<30; x++)
851 PUT_CLID(0x55);
853 /* Send 150ms of callerid marks */
854 for (x=0; x<150; x++)
855 PUT_CLID_MARKMS;
856 /* Send 0x80 indicating MDMF format */
857 PUT_CLID(0x80);
858 /* Put length of whole message */
859 PUT_CLID(len);
860 sum = 0x80 + strlen(msg);
861 /* Put each character of message and update checksum */
862 for (x=0; x<len; x++) {
863 PUT_CLID(msg[x]);
864 sum += msg[x];
866 /* Send 2's compliment of sum */
867 PUT_CLID(256 - (sum & 255));
869 /* Send 50 more ms of marks */
870 for (x=0; x<50; x++)
871 PUT_CLID_MARKMS;
873 return bytes;
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)
882 int x, y=0;
883 int bracketed = 0;
885 for (x=0; n[x]; x++) {
886 switch(n[x]) {
887 case '[':
888 bracketed++;
889 n[y++] = n[x];
890 break;
891 case ']':
892 bracketed--;
893 n[y++] = n[x];
894 break;
895 case '-':
896 if (bracketed)
897 n[y++] = n[x];
898 break;
899 case '.':
900 if (!n[x+1])
901 n[y++] = n[x];
902 break;
903 default:
904 if (!strchr("( )", n[x]))
905 n[y++] = n[x];
908 n[y] = '\0';
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)
918 int x;
920 if (ast_strlen_zero(exten))
921 return 0;
922 for (x=0; exten[x]; x++)
923 if (!strchr(valid, exten[x]))
924 return 0;
925 return 1;
928 /*! \brief checks if string consists only of digits and * \# and +
929 \return 1 if string is valid AST phone number
930 \return 0 if not
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
940 \return 0 if not
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
951 input location name
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 */
973 char tmp[256];
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 */
978 *name = NULL;
979 strcpy(instr, tmp); /* safe, because tmp will always be the same size or smaller than instr */
980 *location = instr;
981 } else { /* Assume it's just a name. */
982 *location = NULL;
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);
992 return 0;
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))
998 name = NULL;
999 if (ast_strlen_zero(number))
1000 number = NULL;
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)
1016 if (!unknown)
1017 unknown = "<unknown>";
1018 if (name && num)
1019 snprintf(buf, bufsiz, "\"%s\" <%s>", name, num);
1020 else if (name)
1021 ast_copy_string(buf, name, bufsiz);
1022 else if (num)
1023 ast_copy_string(buf, num, bufsiz);
1024 else
1025 ast_copy_string(buf, unknown, bufsiz);
1026 return buf;
1029 int ast_callerid_split(const char *buf, char *name, int namelen, char *num, int numlen)
1031 char *tmp;
1032 char *l = NULL, *n = NULL;
1034 tmp = ast_strdupa(buf);
1035 ast_callerid_parse(tmp, &n, &l);
1036 if (n)
1037 ast_copy_string(name, n, namelen);
1038 else
1039 name[0] = '\0';
1040 if (l) {
1041 ast_shrink_phone_number(l);
1042 ast_copy_string(num, l, numlen);
1043 } else
1044 num[0] = '\0';
1045 return 0;
1048 /*! \brief Translation table for Caller ID Presentation settings */
1049 static struct {
1050 int val;
1051 char *name;
1052 char *description;
1053 } pres_types[] = {
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)
1072 int i;
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;
1079 return -1;
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)
1088 int i;
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;
1095 return "unknown";