add the other two files that should have been on this target... oops
[asterisk-bristuff.git] / callerid.c
blob58891d0fab0aa5bd33f2baac6154af44a4ec65aa
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 <time.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <math.h>
32 #include <ctype.h>
34 #include "asterisk.h"
36 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 {
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 return -1;
562 buf += (olen - mylen);
563 if (res < 0) {
564 ast_log(LOG_NOTICE, "fsk_serie failed\n");
565 return -1;
567 if (res == 1) {
568 /* Ignore invalid bytes */
569 if (b > 0xff)
570 continue;
571 switch(cid->sawflag) {
572 case 0: /* Look for flag */
573 if (b == 'U')
574 cid->sawflag = 2;
575 break;
576 case 2: /* Get lead-in */
577 if ((b == 0x04) || (b == 0x80)) {
578 cid->type = b;
579 cid->sawflag = 3;
580 cid->cksum = b;
582 break;
583 case 3: /* Get length */
584 /* Not a lead in. We're ready */
585 cid->sawflag = 4;
586 cid->len = b;
587 cid->pos = 0;
588 cid->cksum += b;
589 break;
590 case 4: /* Retrieve message */
591 if (cid->pos >= 128) {
592 ast_log(LOG_WARNING, "Caller ID too long???\n");
593 return -1;
595 cid->rawdata[cid->pos++] = b;
596 cid->len--;
597 cid->cksum += b;
598 if (!cid->len) {
599 cid->rawdata[cid->pos] = '\0';
600 cid->sawflag = 5;
602 break;
603 case 5: /* Check checksum */
604 if (b != (256 - (cid->cksum & 0xff))) {
605 ast_log(LOG_NOTICE, "Caller*ID failed checksum\n");
606 /* Try again */
607 cid->sawflag = 0;
608 break;
611 cid->number[0] = '\0';
612 cid->name[0] = '\0';
613 /* If we get this far we're fine. */
614 if (cid->type == 0x80) {
615 /* MDMF */
616 /* Go through each element and process */
617 for (x=0;x< cid->pos;) {
618 switch(cid->rawdata[x++]) {
619 case 1:
620 /* Date */
621 break;
622 case 2: /* Number */
623 case 3: /* Number (for Zebble) */
624 case 4: /* Number */
625 res = cid->rawdata[x];
626 if (res > 32) {
627 ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]);
628 res = 32;
630 if (ast_strlen_zero(cid->number)) {
631 memcpy(cid->number, cid->rawdata + x + 1, res);
632 /* Null terminate */
633 cid->number[res] = '\0';
635 break;
636 case 6: /* Stentor Call Qualifier (ie. Long Distance call) */
637 break;
638 case 7: /* Name */
639 case 8: /* Name */
640 res = cid->rawdata[x];
641 if (res > 32) {
642 ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]);
643 res = 32;
645 memcpy(cid->name, cid->rawdata + x + 1, res);
646 cid->name[res] = '\0';
647 break;
648 case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting */
649 case 19: /* UK: Network message system status (Number of messages waiting) */
650 case 22: /* Something French */
651 break;
652 default:
653 ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x-1]);
655 x += cid->rawdata[x];
656 x++;
658 } else {
659 /* SDMF */
660 ast_copy_string(cid->number, cid->rawdata + 8, sizeof(cid->number));
662 /* Update flags */
663 cid->flags = 0;
664 if (!strcmp(cid->number, "P")) {
665 strcpy(cid->number, "");
666 cid->flags |= CID_PRIVATE_NUMBER;
667 } else if (!strcmp(cid->number, "O") || ast_strlen_zero(cid->number)) {
668 strcpy(cid->number, "");
669 cid->flags |= CID_UNKNOWN_NUMBER;
671 if (!strcmp(cid->name, "P")) {
672 strcpy(cid->name, "");
673 cid->flags |= CID_PRIVATE_NAME;
674 } else if (!strcmp(cid->name, "O") || ast_strlen_zero(cid->name)) {
675 strcpy(cid->name, "");
676 cid->flags |= CID_UNKNOWN_NAME;
678 return 1;
679 break;
680 default:
681 ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag);
685 if (mylen) {
686 memcpy(cid->oldstuff, buf, mylen * 2);
687 cid->oldlen = mylen * 2;
688 } else
689 cid->oldlen = 0;
690 free(obuf);
691 return 0;
694 void callerid_free(struct callerid_state *cid)
696 free(cid);
699 static int callerid_genmsg(char *msg, int size, char *number, char *name, int flags)
701 time_t t;
702 struct tm tm;
703 char *ptr;
704 int res;
705 int i,x;
706 /* Get the time */
707 time(&t);
708 localtime_r(&t,&tm);
710 ptr = msg;
712 /* Format time and message header */
713 res = snprintf(ptr, size, "\001\010%02d%02d%02d%02d", tm.tm_mon + 1,
714 tm.tm_mday, tm.tm_hour, tm.tm_min);
715 size -= res;
716 ptr += res;
717 if (ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) {
718 /* Indicate number not known */
719 res = snprintf(ptr, size, "\004\001O");
720 size -= res;
721 ptr += res;
722 } else if (flags & CID_PRIVATE_NUMBER) {
723 /* Indicate number is private */
724 res = snprintf(ptr, size, "\004\001P");
725 size -= res;
726 ptr += res;
727 } else {
728 /* Send up to 16 digits of number MAX */
729 i = strlen(number);
730 if (i > 16) i = 16;
731 res = snprintf(ptr, size, "\002%c", i);
732 size -= res;
733 ptr += res;
734 for (x = 0; x < i; x++)
735 ptr[x] = number[x];
736 ptr[i] = '\0';
737 ptr += i;
738 size -= i;
741 if (ast_strlen_zero(name) || (flags & CID_UNKNOWN_NAME)) {
742 /* Indicate name not known */
743 res = snprintf(ptr, size, "\010\001O");
744 size -= res;
745 ptr += res;
746 } else if (flags & CID_PRIVATE_NAME) {
747 /* Indicate name is private */
748 res = snprintf(ptr, size, "\010\001P");
749 size -= res;
750 ptr += res;
751 } else {
752 /* Send up to 16 digits of name MAX */
753 i = strlen(name);
754 if (i > 16) i = 16;
755 res = snprintf(ptr, size, "\007%c", i);
756 size -= res;
757 ptr += res;
758 for (x=0;x<i;x++)
759 ptr[x] = name[x];
760 ptr[i] = '\0';
761 ptr += i;
762 size -= i;
764 return (ptr - msg);
768 int vmwi_generate(unsigned char *buf, int active, int mdmf, int codec)
770 unsigned char msg[256];
771 int len=0;
772 int sum;
773 int x;
774 int bytes = 0;
775 float cr = 1.0;
776 float ci = 0.0;
777 float scont = 0.0;
778 if (mdmf) {
779 /* MDMF Message waiting */
780 msg[len++] = 0x82;
781 /* Length is 3 */
782 msg[len++] = 3;
783 /* IE is "Message Waiting Parameter" */
784 msg[len++] = 0xb;
785 /* Length of IE is one */
786 msg[len++] = 1;
787 /* Active or not */
788 if (active)
789 msg[len++] = 0xff;
790 else
791 msg[len++] = 0x00;
792 } else {
793 /* SDMF Message waiting */
794 msg[len++] = 0x6;
795 /* Length is 3 */
796 msg[len++] = 3;
797 if (active) {
798 msg[len++] = 0x42;
799 msg[len++] = 0x42;
800 msg[len++] = 0x42;
801 } else {
802 msg[len++] = 0x6f;
803 msg[len++] = 0x6f;
804 msg[len++] = 0x6f;
807 sum = 0;
808 for (x=0; x<len; x++)
809 sum += msg[x];
810 sum = (256 - (sum & 255));
811 msg[len++] = sum;
812 /* Wait a half a second */
813 for (x=0; x<4000; x++)
814 PUT_BYTE(0x7f);
815 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
816 for (x=0; x<30; x++)
817 PUT_CLID(0x55);
818 /* Send 170ms of callerid marks */
819 for (x=0; x<170; x++)
820 PUT_CLID_MARKMS;
821 for (x=0; x<len; x++) {
822 PUT_CLID(msg[x]);
824 /* Send 50 more ms of marks */
825 for (x=0; x<50; x++)
826 PUT_CLID_MARKMS;
827 return bytes;
830 int callerid_generate(unsigned char *buf, char *number, char *name, int flags, int callwaiting, int codec)
832 int bytes=0;
833 int x, sum;
834 int len;
836 /* Initial carriers (real/imaginary) */
837 float cr = 1.0;
838 float ci = 0.0;
839 float scont = 0.0;
840 char msg[256];
841 len = callerid_genmsg(msg, sizeof(msg), number, name, flags);
842 if (!callwaiting) {
843 /* Wait a half a second */
844 for (x=0; x<4000; x++)
845 PUT_BYTE(0x7f);
846 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
847 for (x=0; x<30; x++)
848 PUT_CLID(0x55);
850 /* Send 150ms of callerid marks */
851 for (x=0; x<150; x++)
852 PUT_CLID_MARKMS;
853 /* Send 0x80 indicating MDMF format */
854 PUT_CLID(0x80);
855 /* Put length of whole message */
856 PUT_CLID(len);
857 sum = 0x80 + strlen(msg);
858 /* Put each character of message and update checksum */
859 for (x=0; x<len; x++) {
860 PUT_CLID(msg[x]);
861 sum += msg[x];
863 /* Send 2's compliment of sum */
864 PUT_CLID(256 - (sum & 255));
866 /* Send 50 more ms of marks */
867 for (x=0; x<50; x++)
868 PUT_CLID_MARKMS;
870 return bytes;
873 /*! \brief Clean up phone string
874 * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
875 * Basically, remove anything that could be invalid in a pattern.
877 void ast_shrink_phone_number(char *n)
879 int x, y=0;
880 int bracketed = 0;
882 for (x=0; n[x]; x++) {
883 switch(n[x]) {
884 case '[':
885 bracketed++;
886 n[y++] = n[x];
887 break;
888 case ']':
889 bracketed--;
890 n[y++] = n[x];
891 break;
892 case '-':
893 if (bracketed)
894 n[y++] = n[x];
895 break;
896 case '.':
897 if (!n[x+1])
898 n[y++] = n[x];
899 break;
900 default:
901 if (!strchr("( )", n[x]))
902 n[y++] = n[x];
905 n[y] = '\0';
908 /*! \brief Checks if phone number consists of valid characters
909 \param exten String that needs to be checked
910 \param valid Valid characters in string
911 \return 1 if valid string, 0 if string contains invalid characters
913 static int ast_is_valid_string(const char *exten, const char *valid)
915 int x;
917 if (ast_strlen_zero(exten))
918 return 0;
919 for (x=0; exten[x]; x++)
920 if (!strchr(valid, exten[x]))
921 return 0;
922 return 1;
925 /*! \brief checks if string consists only of digits and * \# and +
926 \return 1 if string is valid AST phone number
927 \return 0 if not
929 int ast_isphonenumber(const char *n)
931 return ast_is_valid_string(n, "0123456789*#+");
934 /*! \brief checks if string consists only of digits and ( ) - * \# and +
935 Pre-qualifies the string for ast_shrink_phone_number()
936 \return 1 if string is valid AST shrinkable phone number
937 \return 0 if not
939 int ast_is_shrinkable_phonenumber(const char *exten)
941 return ast_is_valid_string(exten, "0123456789*#+()-.");
944 /*! \brief parse string for caller id information
945 \return always returns 0, as the code always returns something.
946 XXX note that 'name' is not parsed consistently e.g. we have
948 input location name
949 " foo bar " <123> 123 ' foo bar ' (with spaces around)
950 " foo bar " NULL 'foo bar' (without spaces around)
951 " foo bar <123>" 123 '" foo bar'
952 The parsing of leading and trailing space/quotes should be more consistent.
954 int ast_callerid_parse(char *instr, char **name, char **location)
956 char *ns, *ne, *ls, *le;
958 /* Try "name" <location> format or name <location> format */
959 if ((ls = strchr(instr, '<')) && (le = strchr(ls, '>'))) {
960 *ls = *le = '\0'; /* location found, trim off the brackets */
961 *location = ls + 1; /* and this is the result */
962 if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
963 *ns = *ne = '\0'; /* trim off the quotes */
964 *name = ns + 1; /* and this is the name */
965 } else { /* no quotes, trim off leading and trailing spaces */
966 *name = ast_skip_blanks(instr);
967 ast_trim_blanks(*name);
969 } else { /* no valid brackets */
970 char tmp[256];
972 ast_copy_string(tmp, instr, sizeof(tmp));
973 ast_shrink_phone_number(tmp);
974 if (ast_isphonenumber(tmp)) { /* Assume it's just a location */
975 *name = NULL;
976 strcpy(instr, tmp); /* safe, because tmp will always be the same size or smaller than instr */
977 *location = instr;
978 } else { /* Assume it's just a name. */
979 *location = NULL;
980 if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
981 *ns = *ne = '\0'; /* trim off the quotes */
982 *name = ns + 1; /* and this is the name */
983 } else { /* no quotes, trim off leading and trailing spaces */
984 *name = ast_skip_blanks(instr);
985 ast_trim_blanks(*name);
989 return 0;
992 static int __ast_callerid_generate(unsigned char *buf, char *name, char *number, int callwaiting, int codec)
994 if (ast_strlen_zero(name))
995 name = NULL;
996 if (ast_strlen_zero(number))
997 number = NULL;
998 return callerid_generate(buf, number, name, 0, callwaiting, codec);
1001 int ast_callerid_generate(unsigned char *buf, char *name, char *number, int codec)
1003 return __ast_callerid_generate(buf, name, number, 0, codec);
1006 int ast_callerid_callwaiting_generate(unsigned char *buf, char *name, char *number, int codec)
1008 return __ast_callerid_generate(buf, name, number, 1, codec);
1011 char *ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
1013 if (!unknown)
1014 unknown = "<unknown>";
1015 if (name && num)
1016 snprintf(buf, bufsiz, "\"%s\" <%s>", name, num);
1017 else if (name)
1018 ast_copy_string(buf, name, bufsiz);
1019 else if (num)
1020 ast_copy_string(buf, num, bufsiz);
1021 else
1022 ast_copy_string(buf, unknown, bufsiz);
1023 return buf;
1026 int ast_callerid_split(const char *buf, char *name, int namelen, char *num, int numlen)
1028 char *tmp;
1029 char *l = NULL, *n = NULL;
1031 tmp = ast_strdupa(buf);
1032 if (!tmp) {
1033 name[0] = '\0';
1034 num[0] = '\0';
1035 return -1;
1037 ast_callerid_parse(tmp, &n, &l);
1038 if (n)
1039 ast_copy_string(name, n, namelen);
1040 else
1041 name[0] = '\0';
1042 if (l) {
1043 ast_shrink_phone_number(l);
1044 ast_copy_string(num, l, numlen);
1045 } else
1046 num[0] = '\0';
1047 return 0;
1050 /*! \brief Translation table for Caller ID Presentation settings */
1051 static struct {
1052 int val;
1053 char *name;
1054 char *description;
1055 } pres_types[] = {
1056 { AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened", "Presentation Allowed, Not Screened"},
1057 { AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", "Presentation Allowed, Passed Screen"},
1058 { AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", "Presentation Allowed, Failed Screen"},
1059 { AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed", "Presentation Allowed, Network Number"},
1060 { AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "prohib_not_screened", "Presentation Prohibited, Not Screened"},
1061 { AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", "Presentation Prohibited, Passed Screen"},
1062 { AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", "Presentation Prohibited, Failed Screen"},
1063 { AST_PRES_PROHIB_NETWORK_NUMBER, "prohib", "Presentation Prohibited, Network Number"},
1064 { AST_PRES_NUMBER_NOT_AVAILABLE, "unavailable", "Number Unavailable"},
1067 /*! \brief Convert caller ID text code to value
1068 used in config file parsing
1069 \param data text string
1070 \return value AST_PRES_ from callerid.h
1072 int ast_parse_caller_presentation(const char *data)
1074 int i;
1076 for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
1077 if (!strcasecmp(pres_types[i].name, data))
1078 return pres_types[i].val;
1081 return -1;
1084 /*! \brief Convert caller ID pres value to explanatory string
1085 \param data value (see callerid.h AST_PRES_ )
1086 \return string for human presentation
1088 const char *ast_describe_caller_presentation(int data)
1090 int i;
1092 for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
1093 if (pres_types[i].val == data)
1094 return pres_types[i].description;
1097 return "unknown";