Stop ignoring .lastclean
[asterisk-bristuff.git] / main / callerid.c
blob860deae0ece30ed71eb2be9925e96c2bfc343fa6
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_NAME))
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, "No start bit found in fsk data.\n");
309 free(obuf);
310 return -1;
313 buf += (olen - mylen);
315 if (res < 0) {
316 ast_log(LOG_NOTICE, "fsk_serie failed\n");
317 free(obuf);
318 return -1;
321 if (res == 1) {
323 b2 = b ;
324 b = b & 0x7f ;
326 /* crc checksum calculation */
327 if ( cid->sawflag > 1 ) {
328 cid->crc = calc_crc(cid->crc, (unsigned char)b2);
331 /* Ignore invalid bytes */
332 if (b > 0xff) {
333 continue;
336 /* skip DLE if needed */
337 if ( cid->sawflag > 0 ) {
338 if ( cid->sawflag != 5 && cid->skipflag == 0 && b == 0x10 ) {
339 cid->skipflag = 1 ;
340 continue ;
343 if ( cid->skipflag == 1 ) {
344 cid->skipflag = 0 ;
347 /* caller id retrieval */
348 switch(cid->sawflag) {
349 case 0: /* DLE */
350 if (b == 0x10) {
351 cid->sawflag = 1;
352 cid->skipflag = 0;
353 cid->crc = 0;
355 break;
356 case 1: /* SOH */
357 if (b == 0x01) {
358 cid->sawflag = 2;
360 break ;
361 case 2: /* HEADER */
362 if (b == 0x07) {
363 cid->sawflag = 3;
365 break;
366 case 3: /* STX */
367 if (b == 0x02) {
368 cid->sawflag = 4;
370 break;
371 case 4: /* SERVICE TYPE */
372 if (b == 0x40) {
373 cid->sawflag = 5;
375 break;
376 case 5: /* Frame Length */
377 cid->sawflag = 6;
378 break;
379 case 6: /* NUMBER TYPE */
380 cid->sawflag = 7;
381 cid->pos = 0;
382 cid->rawdata[cid->pos++] = b;
383 break;
384 case 7: /* NUMBER LENGTH */
385 cid->sawflag = 8;
386 cid->len = b;
387 if ( (cid->len+2) >= sizeof( cid->rawdata ) ) {
388 ast_log(LOG_WARNING, "too long caller id string\n" ) ;
389 free(obuf);
390 return -1;
392 cid->rawdata[cid->pos++] = b;
393 break;
394 case 8: /* Retrieve message */
395 cid->rawdata[cid->pos++] = b;
396 cid->len--;
397 if (cid->len<=0) {
398 cid->rawdata[cid->pos] = '\0';
399 cid->sawflag = 9;
401 break;
402 case 9: /* ETX */
403 cid->sawflag = 10;
404 break;
405 case 10: /* CRC Checksum 1 */
406 cid->sawflag = 11;
407 break;
408 case 11: /* CRC Checksum 2 */
409 cid->sawflag = 12;
410 if ( cid->crc != 0 ) {
411 ast_log(LOG_WARNING, "crc checksum error\n" ) ;
412 free(obuf);
413 return -1;
415 /* extract caller id data */
416 for (x=0; x<cid->pos; ) {
417 switch (cid->rawdata[x++]) {
418 case 0x02: /* caller id number */
419 cid->number[0] = '\0';
420 cid->name[0] = '\0';
421 cid->flags = 0;
422 res = cid->rawdata[x++];
423 ast_copy_string(cid->number, &cid->rawdata[x], res+1 );
424 x += res;
425 break;
426 case 0x21: /* additional information */
427 /* length */
428 x++;
429 /* number type */
430 switch (cid->rawdata[x]) {
431 case 0x00: /* unknown */
432 case 0x01: /* international number */
433 case 0x02: /* domestic number */
434 case 0x03: /* network */
435 case 0x04: /* local call */
436 case 0x06: /* short dial number */
437 case 0x07: /* reserved */
438 default: /* reserved */
439 if (option_debug > 1)
440 ast_log(LOG_DEBUG, "cid info:#1=%X\n", cid->rawdata[x]);
441 break ;
443 x++;
444 /* numbering plan octed 4 */
445 x++;
446 /* numbering plan octed 5 */
447 switch (cid->rawdata[x]) {
448 case 0x00: /* unknown */
449 case 0x01: /* recommendation E.164 ISDN */
450 case 0x03: /* recommendation X.121 */
451 case 0x04: /* telex dial plan */
452 case 0x08: /* domestic dial plan */
453 case 0x09: /* private dial plan */
454 case 0x05: /* reserved */
455 default: /* reserved */
456 if (option_debug > 1)
457 ast_log(LOG_DEBUG, "cid info:#2=%X\n", cid->rawdata[x]);
458 break ;
460 x++;
461 break ;
462 case 0x04: /* no callerid reason */
463 /* length */
464 x++;
465 /* no callerid reason code */
466 switch (cid->rawdata[x]) {
467 case 'P': /* caller id denied by user */
468 case 'O': /* service not available */
469 case 'C': /* pay phone */
470 case 'S': /* service congested */
471 cid->flags |= CID_UNKNOWN_NUMBER;
472 if (option_debug > 1)
473 ast_log(LOG_DEBUG, "no cid reason:%c\n",cid->rawdata[x]);
474 break ;
476 x++;
477 break ;
478 case 0x09: /* dialed number */
479 /* length */
480 res = cid->rawdata[x++];
481 /* dialed number */
482 x += res;
483 break ;
484 case 0x22: /* dialed number additional information */
485 /* length */
486 x++;
487 /* number type */
488 switch (cid->rawdata[x]) {
489 case 0x00: /* unknown */
490 case 0x01: /* international number */
491 case 0x02: /* domestic number */
492 case 0x03: /* network */
493 case 0x04: /* local call */
494 case 0x06: /* short dial number */
495 case 0x07: /* reserved */
496 default: /* reserved */
497 if (option_debug > 1)
498 ast_log(LOG_NOTICE, "did info:#1=%X\n", cid->rawdata[x]);
499 break ;
501 x++;
502 /* numbering plan octed 4 */
503 x++;
504 /* numbering plan octed 5 */
505 switch (cid->rawdata[x]) {
506 case 0x00: /* unknown */
507 case 0x01: /* recommendation E.164 ISDN */
508 case 0x03: /* recommendation X.121 */
509 case 0x04: /* telex dial plan */
510 case 0x08: /* domestic dial plan */
511 case 0x09: /* private dial plan */
512 case 0x05: /* reserved */
513 default: /* reserved */
514 if (option_debug > 1)
515 ast_log(LOG_DEBUG, "did info:#2=%X\n", cid->rawdata[x]);
516 break ;
518 x++;
519 break ;
522 free(obuf);
523 return 1;
524 break;
525 default:
526 ast_log(LOG_ERROR, "invalid value in sawflag %d\n", cid->sawflag);
530 if (mylen) {
531 memcpy(cid->oldstuff, buf, mylen * 2);
532 cid->oldlen = mylen * 2;
533 } else
534 cid->oldlen = 0;
535 free(obuf);
536 return 0;
540 int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int codec)
542 int mylen = len;
543 int olen;
544 int b = 'X';
545 int res;
546 int x;
547 short *buf;
548 short *obuf;
550 if (!(buf = ast_calloc(1, 2 * len + cid->oldlen))) {
551 return -1;
554 obuf = buf;
555 memcpy(buf, cid->oldstuff, cid->oldlen);
556 mylen += cid->oldlen/2;
558 for (x=0;x<len;x++)
559 buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
560 while(mylen >= 160) {
561 olen = mylen;
562 res = fsk_serie(&cid->fskd, buf, &mylen, &b);
563 if (mylen < 0) {
564 ast_log(LOG_ERROR, "No start bit found in fsk data.\n");
565 free(obuf);
566 return -1;
568 buf += (olen - mylen);
569 if (res < 0) {
570 ast_log(LOG_NOTICE, "fsk_serie failed\n");
571 free(obuf);
572 return -1;
574 if (res == 1) {
575 /* Ignore invalid bytes */
576 if (b > 0xff)
577 continue;
578 switch(cid->sawflag) {
579 case 0: /* Look for flag */
580 if (b == 'U')
581 cid->sawflag = 2;
582 break;
583 case 2: /* Get lead-in */
584 if ((b == 0x04) || (b == 0x80)) {
585 cid->type = b;
586 cid->sawflag = 3;
587 cid->cksum = b;
589 break;
590 case 3: /* Get length */
591 /* Not a lead in. We're ready */
592 cid->sawflag = 4;
593 cid->len = b;
594 cid->pos = 0;
595 cid->cksum += b;
596 break;
597 case 4: /* Retrieve message */
598 if (cid->pos >= 128) {
599 ast_log(LOG_WARNING, "Caller ID too long???\n");
600 free(obuf);
601 return -1;
603 cid->rawdata[cid->pos++] = b;
604 cid->len--;
605 cid->cksum += b;
606 if (!cid->len) {
607 cid->rawdata[cid->pos] = '\0';
608 cid->sawflag = 5;
610 break;
611 case 5: /* Check checksum */
612 if (b != (256 - (cid->cksum & 0xff))) {
613 ast_log(LOG_NOTICE, "Caller*ID failed checksum\n");
614 /* Try again */
615 cid->sawflag = 0;
616 break;
619 cid->number[0] = '\0';
620 cid->name[0] = '\0';
621 /* If we get this far we're fine. */
622 if (cid->type == 0x80) {
623 /* MDMF */
624 /* Go through each element and process */
625 for (x=0;x< cid->pos;) {
626 switch(cid->rawdata[x++]) {
627 case 1:
628 /* Date */
629 break;
630 case 2: /* Number */
631 case 3: /* Number (for Zebble) */
632 case 4: /* Number */
633 res = cid->rawdata[x];
634 if (res > 32) {
635 ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]);
636 res = 32;
638 if (ast_strlen_zero(cid->number)) {
639 memcpy(cid->number, cid->rawdata + x + 1, res);
640 /* Null terminate */
641 cid->number[res] = '\0';
643 break;
644 case 6: /* Stentor Call Qualifier (ie. Long Distance call) */
645 break;
646 case 7: /* Name */
647 case 8: /* Name */
648 res = cid->rawdata[x];
649 if (res > 32) {
650 ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]);
651 res = 32;
653 memcpy(cid->name, cid->rawdata + x + 1, res);
654 cid->name[res] = '\0';
655 break;
656 case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting */
657 case 19: /* UK: Network message system status (Number of messages waiting) */
658 case 22: /* Something French */
659 break;
660 default:
661 ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x-1]);
663 res = cid->rawdata[x];
664 if (0 > res){ /* Negative offset in the CID Spill */
665 ast_log(LOG_NOTICE, "IE %d has bad field length of %d at offset %d\n", cid->rawdata[x-1], cid->rawdata[x], x);
666 /* Try again */
667 cid->sawflag = 0;
668 break; /* Exit the loop */
670 x += cid->rawdata[x];
671 x++;
673 } else {
674 /* SDMF */
675 ast_copy_string(cid->number, cid->rawdata + 8, sizeof(cid->number));
677 /* Update flags */
678 cid->flags = 0;
679 if (!strcmp(cid->number, "P")) {
680 strcpy(cid->number, "");
681 cid->flags |= CID_PRIVATE_NUMBER;
682 } else if (!strcmp(cid->number, "O") || ast_strlen_zero(cid->number)) {
683 strcpy(cid->number, "");
684 cid->flags |= CID_UNKNOWN_NUMBER;
686 if (!strcmp(cid->name, "P")) {
687 strcpy(cid->name, "");
688 cid->flags |= CID_PRIVATE_NAME;
689 } else if (!strcmp(cid->name, "O") || ast_strlen_zero(cid->name)) {
690 strcpy(cid->name, "");
691 cid->flags |= CID_UNKNOWN_NAME;
693 free(obuf);
694 return 1;
695 break;
696 default:
697 ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag);
701 if (mylen) {
702 memcpy(cid->oldstuff, buf, mylen * 2);
703 cid->oldlen = mylen * 2;
704 } else
705 cid->oldlen = 0;
706 free(obuf);
707 return 0;
710 void callerid_free(struct callerid_state *cid)
712 free(cid);
715 static int callerid_genmsg(char *msg, int size, const char *number, const char *name, int flags)
717 time_t t;
718 struct tm tm;
719 char *ptr;
720 int res;
721 int i,x;
722 /* Get the time */
723 time(&t);
724 ast_localtime(&t, &tm, NULL);
726 ptr = msg;
728 /* Format time and message header */
729 res = snprintf(ptr, size, "\001\010%02d%02d%02d%02d", tm.tm_mon + 1,
730 tm.tm_mday, tm.tm_hour, tm.tm_min);
731 size -= res;
732 ptr += res;
733 if (ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) {
734 /* Indicate number not known */
735 res = snprintf(ptr, size, "\004\001O");
736 size -= res;
737 ptr += res;
738 } else if (flags & CID_PRIVATE_NUMBER) {
739 /* Indicate number is private */
740 res = snprintf(ptr, size, "\004\001P");
741 size -= res;
742 ptr += res;
743 } else {
744 /* Send up to 16 digits of number MAX */
745 i = strlen(number);
746 if (i > 16) i = 16;
747 res = snprintf(ptr, size, "\002%c", i);
748 size -= res;
749 ptr += res;
750 for (x = 0; x < i; x++)
751 ptr[x] = number[x];
752 ptr[i] = '\0';
753 ptr += i;
754 size -= i;
757 if (ast_strlen_zero(name) || (flags & CID_UNKNOWN_NAME)) {
758 /* Indicate name not known */
759 res = snprintf(ptr, size, "\010\001O");
760 size -= res;
761 ptr += res;
762 } else if (flags & CID_PRIVATE_NAME) {
763 /* Indicate name is private */
764 res = snprintf(ptr, size, "\010\001P");
765 size -= res;
766 ptr += res;
767 } else {
768 /* Send up to 16 digits of name MAX */
769 i = strlen(name);
770 if (i > 16) i = 16;
771 res = snprintf(ptr, size, "\007%c", i);
772 size -= res;
773 ptr += res;
774 for (x=0;x<i;x++)
775 ptr[x] = name[x];
776 ptr[i] = '\0';
777 ptr += i;
778 size -= i;
780 return (ptr - msg);
784 int vmwi_generate(unsigned char *buf, int active, int mdmf, int codec)
786 unsigned char msg[256];
787 int len=0;
788 int sum;
789 int x;
790 int bytes = 0;
791 float cr = 1.0;
792 float ci = 0.0;
793 float scont = 0.0;
794 if (mdmf) {
795 /* MDMF Message waiting */
796 msg[len++] = 0x82;
797 /* Length is 3 */
798 msg[len++] = 3;
799 /* IE is "Message Waiting Parameter" */
800 msg[len++] = 0xb;
801 /* Length of IE is one */
802 msg[len++] = 1;
803 /* Active or not */
804 if (active)
805 msg[len++] = 0xff;
806 else
807 msg[len++] = 0x00;
808 } else {
809 /* SDMF Message waiting */
810 msg[len++] = 0x6;
811 /* Length is 3 */
812 msg[len++] = 3;
813 if (active) {
814 msg[len++] = 0x42;
815 msg[len++] = 0x42;
816 msg[len++] = 0x42;
817 } else {
818 msg[len++] = 0x6f;
819 msg[len++] = 0x6f;
820 msg[len++] = 0x6f;
823 sum = 0;
824 for (x=0; x<len; x++)
825 sum += msg[x];
826 sum = (256 - (sum & 255));
827 msg[len++] = sum;
828 /* Wait a half a second */
829 for (x=0; x<4000; x++)
830 PUT_BYTE(0x7f);
831 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
832 for (x=0; x<30; x++)
833 PUT_CLID(0x55);
834 /* Send 170ms of callerid marks */
835 for (x=0; x<170; x++)
836 PUT_CLID_MARKMS;
837 for (x=0; x<len; x++) {
838 PUT_CLID(msg[x]);
840 /* Send 50 more ms of marks */
841 for (x=0; x<50; x++)
842 PUT_CLID_MARKMS;
843 return bytes;
846 int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, int codec)
848 int bytes=0;
849 int x, sum;
850 int len;
852 /* Initial carriers (real/imaginary) */
853 float cr = 1.0;
854 float ci = 0.0;
855 float scont = 0.0;
856 char msg[256];
857 len = callerid_genmsg(msg, sizeof(msg), number, name, flags);
858 if (!callwaiting) {
859 /* Wait a half a second */
860 for (x=0; x<4000; x++)
861 PUT_BYTE(0x7f);
862 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
863 for (x=0; x<30; x++)
864 PUT_CLID(0x55);
866 /* Send 150ms of callerid marks */
867 for (x=0; x<150; x++)
868 PUT_CLID_MARKMS;
869 /* Send 0x80 indicating MDMF format */
870 PUT_CLID(0x80);
871 /* Put length of whole message */
872 PUT_CLID(len);
873 sum = 0x80 + strlen(msg);
874 /* Put each character of message and update checksum */
875 for (x=0; x<len; x++) {
876 PUT_CLID(msg[x]);
877 sum += msg[x];
879 /* Send 2's compliment of sum */
880 PUT_CLID(256 - (sum & 255));
882 /* Send 50 more ms of marks */
883 for (x=0; x<50; x++)
884 PUT_CLID_MARKMS;
886 return bytes;
889 /*! \brief Clean up phone string
890 * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
891 * Basically, remove anything that could be invalid in a pattern.
893 void ast_shrink_phone_number(char *n)
895 int x, y=0;
896 int bracketed = 0;
898 for (x=0; n[x]; x++) {
899 switch(n[x]) {
900 case '[':
901 bracketed++;
902 n[y++] = n[x];
903 break;
904 case ']':
905 bracketed--;
906 n[y++] = n[x];
907 break;
908 case '-':
909 if (bracketed)
910 n[y++] = n[x];
911 break;
912 case '.':
913 if (!n[x+1])
914 n[y++] = n[x];
915 break;
916 default:
917 if (!strchr("( )", n[x]))
918 n[y++] = n[x];
921 n[y] = '\0';
924 /*! \brief Checks if phone number consists of valid characters
925 \param exten String that needs to be checked
926 \param valid Valid characters in string
927 \return 1 if valid string, 0 if string contains invalid characters
929 static int ast_is_valid_string(const char *exten, const char *valid)
931 int x;
933 if (ast_strlen_zero(exten))
934 return 0;
935 for (x=0; exten[x]; x++)
936 if (!strchr(valid, exten[x]))
937 return 0;
938 return 1;
941 /*! \brief checks if string consists only of digits and * \# and +
942 \return 1 if string is valid AST phone number
943 \return 0 if not
945 int ast_isphonenumber(const char *n)
947 return ast_is_valid_string(n, "0123456789*#+");
950 /*! \brief checks if string consists only of digits and ( ) - * \# and +
951 Pre-qualifies the string for ast_shrink_phone_number()
952 \return 1 if string is valid AST shrinkable phone number
953 \return 0 if not
955 int ast_is_shrinkable_phonenumber(const char *exten)
957 return ast_is_valid_string(exten, "0123456789*#+()-.");
961 * \brief Destructively parse instr for caller id information
962 * \return always returns 0, as the code always returns something.
963 * \note XXX 'name' is not parsed consistently e.g. we have
964 * input location name
965 * " foo bar " <123> 123 ' foo bar ' (with spaces around)
966 * " foo bar " NULL 'foo bar' (without spaces around)
967 * " foo bar <123>" 123 '" foo bar'
968 * The parsing of leading and trailing space/quotes should be more consistent.
970 int ast_callerid_parse(char *instr, char **name, char **location)
972 char *ns, *ne, *ls, *le;
974 /* Try "name" <location> format or name <location> format */
975 if ((ls = strchr(instr, '<')) && (le = strchr(ls, '>'))) {
976 *ls = *le = '\0'; /* location found, trim off the brackets */
977 *location = ls + 1; /* and this is the result */
978 if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
979 *ns = *ne = '\0'; /* trim off the quotes */
980 *name = ns + 1; /* and this is the name */
981 } else { /* no quotes, trim off leading and trailing spaces */
982 *name = ast_skip_blanks(instr);
983 ast_trim_blanks(*name);
985 } else { /* no valid brackets */
986 char tmp[256];
988 ast_copy_string(tmp, instr, sizeof(tmp));
989 ast_shrink_phone_number(tmp);
990 if (ast_isphonenumber(tmp)) { /* Assume it's just a location */
991 *name = NULL;
992 strcpy(instr, tmp); /* safe, because tmp will always be the same size or smaller than instr */
993 *location = instr;
994 } else { /* Assume it's just a name. */
995 *location = NULL;
996 if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
997 *ns = *ne = '\0'; /* trim off the quotes */
998 *name = ns + 1; /* and this is the name */
999 } else { /* no quotes, trim off leading and trailing spaces */
1000 *name = ast_skip_blanks(instr);
1001 ast_trim_blanks(*name);
1005 return 0;
1008 static int __ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int callwaiting, int codec)
1010 if (ast_strlen_zero(name))
1011 name = NULL;
1012 if (ast_strlen_zero(number))
1013 number = NULL;
1014 return callerid_generate(buf, number, name, 0, callwaiting, codec);
1017 int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int codec)
1019 return __ast_callerid_generate(buf, name, number, 0, codec);
1022 int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, int codec)
1024 return __ast_callerid_generate(buf, name, number, 1, codec);
1027 char *ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
1029 if (!unknown)
1030 unknown = "<unknown>";
1031 if (name && num)
1032 snprintf(buf, bufsiz, "\"%s\" <%s>", name, num);
1033 else if (name)
1034 ast_copy_string(buf, name, bufsiz);
1035 else if (num)
1036 ast_copy_string(buf, num, bufsiz);
1037 else
1038 ast_copy_string(buf, unknown, bufsiz);
1039 return buf;
1042 int ast_callerid_split(const char *buf, char *name, int namelen, char *num, int numlen)
1044 char *tmp;
1045 char *l = NULL, *n = NULL;
1047 tmp = ast_strdupa(buf);
1048 ast_callerid_parse(tmp, &n, &l);
1049 if (n)
1050 ast_copy_string(name, n, namelen);
1051 else
1052 name[0] = '\0';
1053 if (l) {
1054 ast_shrink_phone_number(l);
1055 ast_copy_string(num, l, numlen);
1056 } else
1057 num[0] = '\0';
1058 return 0;
1061 /*! \brief Translation table for Caller ID Presentation settings */
1062 static struct {
1063 int val;
1064 char *name;
1065 char *description;
1066 } pres_types[] = {
1067 { AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened", "Presentation Allowed, Not Screened"},
1068 { AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", "Presentation Allowed, Passed Screen"},
1069 { AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", "Presentation Allowed, Failed Screen"},
1070 { AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed", "Presentation Allowed, Network Number"},
1071 { AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "prohib_not_screened", "Presentation Prohibited, Not Screened"},
1072 { AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", "Presentation Prohibited, Passed Screen"},
1073 { AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", "Presentation Prohibited, Failed Screen"},
1074 { AST_PRES_PROHIB_NETWORK_NUMBER, "prohib", "Presentation Prohibited, Network Number"},
1075 { AST_PRES_NUMBER_NOT_AVAILABLE, "unavailable", "Number Unavailable"},
1078 /*! \brief Convert caller ID text code to value
1079 used in config file parsing
1080 \param data text string
1081 \return value AST_PRES_ from callerid.h
1083 int ast_parse_caller_presentation(const char *data)
1085 int i;
1087 for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
1088 if (!strcasecmp(pres_types[i].name, data))
1089 return pres_types[i].val;
1092 return -1;
1095 /*! \brief Convert caller ID pres value to explanatory string
1096 \param data value (see callerid.h AST_PRES_ )
1097 \return string for human presentation
1099 const char *ast_describe_caller_presentation(int data)
1101 int i;
1103 for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
1104 if (pres_types[i].val == data)
1105 return pres_types[i].description;
1108 return "unknown";