Minor formatting change to test a mantis change ...
[asterisk-bristuff.git] / main / callerid.c
blob4dd290e5a1c6b643547ada5dfc1bc5a6f2acde3c
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 <math.h>
32 #include <ctype.h>
34 #include "asterisk/ulaw.h"
35 #include "asterisk/alaw.h"
36 #include "asterisk/frame.h"
37 #include "asterisk/channel.h"
38 #include "asterisk/callerid.h"
39 #include "asterisk/fskmodem.h"
40 #include "asterisk/utils.h"
42 struct callerid_state {
43 fsk_data fskd;
44 char rawdata[256];
45 short oldstuff[160];
46 int oldlen;
47 int pos;
48 int type;
49 int cksum;
50 char name[64];
51 char number[64];
52 int flags;
53 int sawflag;
54 int len;
56 int skipflag;
57 unsigned short crc;
61 float cid_dr[4], cid_di[4];
62 float clidsb = 8000.0 / 1200.0;
63 float sasdr, sasdi;
64 float casdr1, casdi1, casdr2, casdi2;
66 #define CALLERID_SPACE 2200.0 /*!< 2200 hz for "0" */
67 #define CALLERID_MARK 1200.0 /*!< 1200 hz for "1" */
68 #define SAS_FREQ 440.0
69 #define CAS_FREQ1 2130.0
70 #define CAS_FREQ2 2750.0
72 #define AST_CALLERID_UNKNOWN "<unknown>"
74 static inline void gen_tones(unsigned char *buf, int len, int codec, float ddr1, float ddi1, float ddr2, float ddi2, float *cr1, float *ci1, float *cr2, float *ci2)
76 int x;
77 float t;
78 for (x = 0; x < len; x++) {
79 t = *cr1 * ddr1 - *ci1 * ddi1;
80 *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
81 *cr1 = t;
82 t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
83 *cr1 *= t;
84 *ci1 *= t;
86 t = *cr2 * ddr2 - *ci2 * ddi2;
87 *ci2 = *cr2 * ddi2 + *ci2 * ddr2;
88 *cr2 = t;
89 t = 2.0 - (*cr2 * *cr2 + *ci2 * *ci2);
90 *cr2 *= t;
91 *ci2 *= t;
92 buf[x] = AST_LIN2X((*cr1 + *cr2) * 2048.0);
96 static inline void gen_tone(unsigned char *buf, int len, int codec, float ddr1, float ddi1, float *cr1, float *ci1)
98 int x;
99 float t;
100 for (x = 0; x < len; x++) {
101 t = *cr1 * ddr1 - *ci1 * ddi1;
102 *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
103 *cr1 = t;
104 t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
105 *cr1 *= t;
106 *ci1 *= t;
107 buf[x] = AST_LIN2X(*cr1 * 8192.0);
111 /*! \brief Initialize stuff for inverse FFT */
112 void callerid_init(void)
114 cid_dr[0] = cos(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
115 cid_di[0] = sin(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
116 cid_dr[1] = cos(CALLERID_MARK * 2.0 * M_PI / 8000.0);
117 cid_di[1] = sin(CALLERID_MARK * 2.0 * M_PI / 8000.0);
118 sasdr = cos(SAS_FREQ * 2.0 * M_PI / 8000.0);
119 sasdi = sin(SAS_FREQ * 2.0 * M_PI / 8000.0);
120 casdr1 = cos(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
121 casdi1 = sin(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
122 casdr2 = cos(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
123 casdi2 = sin(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
126 struct callerid_state *callerid_new(int cid_signalling)
128 struct callerid_state *cid;
130 if ((cid = ast_calloc(1, sizeof(*cid)))) {
131 cid->fskd.ispb = 7; /* 1200 baud */
132 /* Set up for 1200 / 8000 freq *32 to allow ints */
133 cid->fskd.pllispb = (int)(8000 * 32 / 1200);
134 cid->fskd.pllids = cid->fskd.pllispb/32;
135 cid->fskd.pllispb2 = cid->fskd.pllispb/2;
137 cid->fskd.icont = 0; /* PLL REset */
138 /* cid->fskd.hdlc = 0; */ /* Async */
139 cid->fskd.nbit = 8; /* 8 bits */
140 cid->fskd.instop = 1; /* 1 stop bit */
141 /* cid->fskd.paridad = 0; */ /* No parity */
142 cid->fskd.bw = 1; /* Filter 800 Hz */
143 if (cid_signalling == 2) { /* v23 signalling */
144 cid->fskd.f_mark_idx = 4; /* 1300 Hz */
145 cid->fskd.f_space_idx = 5; /* 2100 Hz */
146 } else { /* Bell 202 signalling as default */
147 cid->fskd.f_mark_idx = 2; /* 1200 Hz */
148 cid->fskd.f_space_idx = 3; /* 2200 Hz */
150 /* cid->fskd.pcola = 0; */ /* No clue */
151 /* cid->fskd.cont = 0.0; */ /* Digital PLL reset */
152 /* cid->fskd.x0 = 0.0; */
153 /* cid->fskd.state = 0; */
154 cid->flags = CID_UNKNOWN_NAME | CID_UNKNOWN_NUMBER;
155 /* cid->pos = 0; */
157 fskmodem_init(&cid->fskd);
160 return cid;
163 void callerid_get(struct callerid_state *cid, char **name, char **number, int *flags)
165 *flags = cid->flags;
166 if (cid->flags & (CID_UNKNOWN_NAME | CID_PRIVATE_NAME))
167 *name = NULL;
168 else
169 *name = cid->name;
170 if (cid->flags & (CID_UNKNOWN_NUMBER | CID_PRIVATE_NUMBER))
171 *number = NULL;
172 else
173 *number = cid->number;
176 void callerid_get_dtmf(char *cidstring, char *number, int *flags)
178 int i;
179 int code;
181 /* "Clear" the number-buffer. */
182 number[0] = 0;
184 if (strlen(cidstring) < 2) {
185 ast_debug(1, "No cid detected\n");
186 *flags = CID_UNKNOWN_NUMBER;
187 return;
190 /* Detect protocol and special types */
191 if (cidstring[0] == 'B') {
192 /* Handle special codes */
193 code = atoi(&cidstring[1]);
194 if (code == 0)
195 *flags = CID_UNKNOWN_NUMBER;
196 else if (code == 10)
197 *flags = CID_PRIVATE_NUMBER;
198 else
199 ast_debug(1, "Unknown DTMF code %d\n", code);
200 } else if (cidstring[0] == 'D' && cidstring[2] == '#') {
201 /* .DK special code */
202 if (cidstring[1] == '1')
203 *flags = CID_PRIVATE_NUMBER;
204 if (cidstring[1] == '2' || cidstring[1] == '3')
205 *flags = CID_UNKNOWN_NUMBER;
206 } else if (cidstring[0] == 'D' || cidstring[0] == 'A') {
207 /* "Standard" callerid */
208 for (i = 1; i < strlen(cidstring); i++) {
209 if (cidstring[i] == 'C' || cidstring[i] == '#')
210 break;
211 if (isdigit(cidstring[i]))
212 number[i-1] = cidstring[i];
213 else
214 ast_debug(1, "Unknown CID digit '%c'\n",
215 cidstring[i]);
217 number[i-1] = 0;
218 } else if (isdigit(cidstring[0])) {
219 /* It begins with a digit, so we parse it as a number and hope
220 * for the best */
221 ast_log(LOG_WARNING, "Couldn't detect start-character. CID "
222 "parsing might be unreliable\n");
223 for (i = 0; i < strlen(cidstring); i++) {
224 if (isdigit(cidstring[i]))
225 number[i] = cidstring[i];
226 else
227 break;
229 number[i] = 0;
230 } else {
231 ast_debug(1, "Unknown CID protocol, start digit '%c'\n", cidstring[0]);
232 *flags = CID_UNKNOWN_NUMBER;
236 int ast_gen_cas(unsigned char *outbuf, int sendsas, int len, int codec)
238 int pos = 0;
239 int saslen = 2400;
240 float cr1 = 1.0;
241 float ci1 = 0.0;
242 float cr2 = 1.0;
243 float ci2 = 0.0;
245 if (sendsas) {
246 if (len < saslen)
247 return -1;
248 gen_tone(outbuf, saslen, codec, sasdr, sasdi, &cr1, &ci1);
249 len -= saslen;
250 pos += saslen;
251 cr2 = cr1;
252 ci2 = ci1;
254 gen_tones(outbuf + pos, len, codec, casdr1, casdi1, casdr2, casdi2, &cr1, &ci1, &cr2, &ci2);
255 return 0;
258 static unsigned short calc_crc(unsigned short crc, unsigned char data)
260 unsigned int i, j, org, dst;
261 org = data;
262 dst = 0;
264 for (i = 0; i < CHAR_BIT; i++) {
265 org <<= 1;
266 dst >>= 1;
267 if (org & 0x100)
268 dst |= 0x80;
270 data = (unsigned char) dst;
271 crc ^= (unsigned int) data << (16 - CHAR_BIT);
272 for (j = 0; j < CHAR_BIT; j++) {
273 if (crc & 0x8000U)
274 crc = (crc << 1) ^ 0x1021U ;
275 else
276 crc <<= 1 ;
278 return crc;
281 int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int len, int codec)
283 int mylen = len;
284 int olen;
285 int b = 'X';
286 int b2;
287 int res;
288 int x;
289 short *buf;
291 buf = alloca(2 * len + cid->oldlen);
293 memcpy(buf, cid->oldstuff, cid->oldlen);
294 mylen += cid->oldlen / 2;
296 for (x = 0; x < len; x++)
297 buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
299 while (mylen >= 160) {
300 b = b2 = 0;
301 olen = mylen;
302 res = fsk_serial(&cid->fskd, buf, &mylen, &b);
304 if (mylen < 0) {
305 ast_log(LOG_ERROR, "No start bit found in fsk data.\n");
306 return -1;
309 buf += (olen - mylen);
311 if (res < 0) {
312 ast_log(LOG_NOTICE, "fsk_serial failed\n");
313 return -1;
316 if (res == 1) {
317 b2 = b;
318 b &= 0x7f;
320 /* crc checksum calculation */
321 if (cid->sawflag > 1)
322 cid->crc = calc_crc(cid->crc, (unsigned char) b2);
324 /* Ignore invalid bytes */
325 if (b > 0xff)
326 continue;
328 /* skip DLE if needed */
329 if (cid->sawflag > 0) {
330 if (cid->sawflag != 5 && cid->skipflag == 0 && b == 0x10) {
331 cid->skipflag = 1 ;
332 continue ;
335 if (cid->skipflag == 1)
336 cid->skipflag = 0 ;
338 /* caller id retrieval */
339 switch (cid->sawflag) {
340 case 0: /* DLE */
341 if (b == 0x10) {
342 cid->sawflag = 1;
343 cid->skipflag = 0;
344 cid->crc = 0;
346 break;
347 case 1: /* SOH */
348 if (b == 0x01)
349 cid->sawflag = 2;
350 break ;
351 case 2: /* HEADER */
352 if (b == 0x07)
353 cid->sawflag = 3;
354 break;
355 case 3: /* STX */
356 if (b == 0x02)
357 cid->sawflag = 4;
358 break;
359 case 4: /* SERVICE TYPE */
360 if (b == 0x40)
361 cid->sawflag = 5;
362 break;
363 case 5: /* Frame Length */
364 cid->sawflag = 6;
365 break;
366 case 6: /* NUMBER TYPE */
367 cid->sawflag = 7;
368 cid->pos = 0;
369 cid->rawdata[cid->pos++] = b;
370 break;
371 case 7: /* NUMBER LENGTH */
372 cid->sawflag = 8;
373 cid->len = b;
374 if ((cid->len+2) >= sizeof(cid->rawdata)) {
375 ast_log(LOG_WARNING, "too long caller id string\n") ;
376 return -1;
378 cid->rawdata[cid->pos++] = b;
379 break;
380 case 8: /* Retrieve message */
381 cid->rawdata[cid->pos++] = b;
382 cid->len--;
383 if (cid->len<=0) {
384 cid->rawdata[cid->pos] = '\0';
385 cid->sawflag = 9;
387 break;
388 case 9: /* ETX */
389 cid->sawflag = 10;
390 break;
391 case 10: /* CRC Checksum 1 */
392 cid->sawflag = 11;
393 break;
394 case 11: /* CRC Checksum 2 */
395 cid->sawflag = 12;
396 if (cid->crc != 0) {
397 ast_log(LOG_WARNING, "crc checksum error\n") ;
398 return -1;
400 /* extract caller id data */
401 for (x = 0; x < cid->pos;) {
402 switch (cid->rawdata[x++]) {
403 case 0x02: /* caller id number */
404 cid->number[0] = '\0';
405 cid->name[0] = '\0';
406 cid->flags = 0;
407 res = cid->rawdata[x++];
408 ast_copy_string(cid->number, &cid->rawdata[x], res+1);
409 x += res;
410 break;
411 case 0x21: /* additional information */
412 /* length */
413 x++;
414 /* number type */
415 switch (cid->rawdata[x]) {
416 case 0x00: /* unknown */
417 case 0x01: /* international number */
418 case 0x02: /* domestic number */
419 case 0x03: /* network */
420 case 0x04: /* local call */
421 case 0x06: /* short dial number */
422 case 0x07: /* reserved */
423 default: /* reserved */
424 ast_debug(2, "cid info:#1=%X\n", cid->rawdata[x]);
425 break ;
427 x++;
428 /* numbering plan octed 4 */
429 x++;
430 /* numbering plan octed 5 */
431 switch (cid->rawdata[x]) {
432 case 0x00: /* unknown */
433 case 0x01: /* recommendation E.164 ISDN */
434 case 0x03: /* recommendation X.121 */
435 case 0x04: /* telex dial plan */
436 case 0x08: /* domestic dial plan */
437 case 0x09: /* private dial plan */
438 case 0x05: /* reserved */
439 default: /* reserved */
440 ast_debug(2, "cid info:#2=%X\n", cid->rawdata[x]);
441 break ;
443 x++;
444 break ;
445 case 0x04: /* no callerid reason */
446 /* length */
447 x++;
448 /* no callerid reason code */
449 switch (cid->rawdata[x]) {
450 case 'P': /* caller id denied by user */
451 case 'O': /* service not available */
452 case 'C': /* pay phone */
453 case 'S': /* service congested */
454 cid->flags |= CID_UNKNOWN_NUMBER;
455 ast_debug(2, "no cid reason:%c\n", cid->rawdata[x]);
456 break ;
458 x++;
459 break ;
460 case 0x09: /* dialed number */
461 /* length */
462 res = cid->rawdata[x++];
463 /* dialed number */
464 x += res;
465 break ;
466 case 0x22: /* dialed number additional information */
467 /* length */
468 x++;
469 /* number type */
470 switch (cid->rawdata[x]) {
471 case 0x00: /* unknown */
472 case 0x01: /* international number */
473 case 0x02: /* domestic number */
474 case 0x03: /* network */
475 case 0x04: /* local call */
476 case 0x06: /* short dial number */
477 case 0x07: /* reserved */
478 default: /* reserved */
479 if (option_debug > 1)
480 ast_log(LOG_NOTICE, "did info:#1=%X\n", cid->rawdata[x]);
481 break ;
483 x++;
484 /* numbering plan octed 4 */
485 x++;
486 /* numbering plan octed 5 */
487 switch (cid->rawdata[x]) {
488 case 0x00: /* unknown */
489 case 0x01: /* recommendation E.164 ISDN */
490 case 0x03: /* recommendation X.121 */
491 case 0x04: /* telex dial plan */
492 case 0x08: /* domestic dial plan */
493 case 0x09: /* private dial plan */
494 case 0x05: /* reserved */
495 default: /* reserved */
496 ast_debug(2, "did info:#2=%X\n", cid->rawdata[x]);
497 break ;
499 x++;
500 break ;
503 return 1;
504 break;
505 default:
506 ast_log(LOG_ERROR, "invalid value in sawflag %d\n", cid->sawflag);
510 if (mylen) {
511 memcpy(cid->oldstuff, buf, mylen * 2);
512 cid->oldlen = mylen * 2;
513 } else
514 cid->oldlen = 0;
516 return 0;
520 int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int codec)
522 int mylen = len;
523 int olen;
524 int b = 'X';
525 int res;
526 int x;
527 short *buf;
529 buf = alloca(2 * len + cid->oldlen);
531 memcpy(buf, cid->oldstuff, cid->oldlen);
532 mylen += cid->oldlen/2;
534 for (x = 0; x < len; x++)
535 buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
536 while (mylen >= 160) {
537 olen = mylen;
538 res = fsk_serial(&cid->fskd, buf, &mylen, &b);
539 if (mylen < 0) {
540 ast_log(LOG_ERROR, "No start bit found in fsk data.\n");
541 return -1;
543 buf += (olen - mylen);
544 if (res < 0) {
545 ast_log(LOG_NOTICE, "fsk_serial failed\n");
546 return -1;
548 if (res == 1) {
549 /* Ignore invalid bytes */
550 if (b > 0xff)
551 continue;
552 switch (cid->sawflag) {
553 case 0: /* Look for flag */
554 if (b == 'U')
555 cid->sawflag = 2;
556 break;
557 case 2: /* Get lead-in */
558 if ((b == 0x04) || (b == 0x80) || (b == 0x06) || (b == 0x82)) {
559 cid->type = b;
560 cid->sawflag = 3;
561 cid->cksum = b;
563 break;
564 case 3: /* Get length */
565 /* Not a lead in. We're ready */
566 cid->sawflag = 4;
567 cid->len = b;
568 cid->pos = 0;
569 cid->cksum += b;
570 break;
571 case 4: /* Retrieve message */
572 if (cid->pos >= 128) {
573 ast_log(LOG_WARNING, "Caller ID too long???\n");
574 return -1;
576 cid->rawdata[cid->pos++] = b;
577 cid->len--;
578 cid->cksum += b;
579 if (!cid->len) {
580 cid->rawdata[cid->pos] = '\0';
581 cid->sawflag = 5;
583 break;
584 case 5: /* Check checksum */
585 if (b != (256 - (cid->cksum & 0xff))) {
586 ast_log(LOG_NOTICE, "Caller*ID failed checksum\n");
587 /* Try again */
588 cid->sawflag = 0;
589 break;
592 cid->number[0] = '\0';
593 cid->name[0] = '\0';
594 /* Update flags */
595 cid->flags = 0;
596 /* If we get this far we're fine. */
597 if ((cid->type == 0x80) || (cid->type == 0x82)) {
598 /* MDMF */
599 /* Go through each element and process */
600 for (x = 0; x < cid->pos;) {
601 switch (cid->rawdata[x++]) {
602 case 1:
603 /* Date */
604 break;
605 case 2: /* Number */
606 case 3: /* Number (for Zebble) */
607 case 4: /* Number */
608 res = cid->rawdata[x];
609 if (res > 32) {
610 ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]);
611 res = 32;
613 if (ast_strlen_zero(cid->number)) {
614 memcpy(cid->number, cid->rawdata + x + 1, res);
615 /* Null terminate */
616 cid->number[res] = '\0';
618 break;
619 case 6: /* Stentor Call Qualifier (ie. Long Distance call) */
620 break;
621 case 7: /* Name */
622 case 8: /* Name */
623 res = cid->rawdata[x];
624 if (res > 32) {
625 ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]);
626 res = 32;
628 memcpy(cid->name, cid->rawdata + x + 1, res);
629 cid->name[res] = '\0';
630 break;
631 case 11: /* Message Waiting */
632 res = cid->rawdata[x + 1];
633 if (res)
634 cid->flags |= CID_MSGWAITING;
635 else
636 cid->flags |= CID_NOMSGWAITING;
637 break;
638 case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting */
639 case 19: /* UK: Network message system status (Number of messages waiting) */
640 case 22: /* Something French */
641 break;
642 default:
643 ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x - 1]);
645 res = cid->rawdata[x];
646 if (0 > res){ /* Negative offset in the CID Spill */
647 ast_log(LOG_NOTICE, "IE %d has bad field length of %d at offset %d\n", cid->rawdata[x-1], cid->rawdata[x], x);
648 /* Try again */
649 cid->sawflag = 0;
650 break; /* Exit the loop */
652 x += cid->rawdata[x];
653 x++;
655 } else if (cid->type == 0x6) {
656 /* VMWI SDMF */
657 if (cid->rawdata[2] == 0x42) {
658 cid->flags |= CID_MSGWAITING;
659 } else if (cid->rawdata[2] == 0x6f) {
660 cid->flags |= CID_NOMSGWAITING;
662 } else {
663 /* SDMF */
664 ast_copy_string(cid->number, cid->rawdata + 8, sizeof(cid->number));
666 if (!strcmp(cid->number, "P")) {
667 strcpy(cid->number, "");
668 cid->flags |= CID_PRIVATE_NUMBER;
669 } else if (!strcmp(cid->number, "O") || ast_strlen_zero(cid->number)) {
670 strcpy(cid->number, "");
671 cid->flags |= CID_UNKNOWN_NUMBER;
673 if (!strcmp(cid->name, "P")) {
674 strcpy(cid->name, "");
675 cid->flags |= CID_PRIVATE_NAME;
676 } else if (!strcmp(cid->name, "O") || ast_strlen_zero(cid->name)) {
677 strcpy(cid->name, "");
678 cid->flags |= CID_UNKNOWN_NAME;
680 return 1;
681 break;
682 default:
683 ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag);
687 if (mylen) {
688 memcpy(cid->oldstuff, buf, mylen * 2);
689 cid->oldlen = mylen * 2;
690 } else
691 cid->oldlen = 0;
693 return 0;
696 void callerid_free(struct callerid_state *cid)
698 ast_free(cid);
701 static int callerid_genmsg(char *msg, int size, const char *number, const char *name, int flags)
703 struct timeval tv = ast_tvnow();
704 struct ast_tm tm;
705 char *ptr;
706 int res;
707 int i, x;
709 /* Get the time */
710 ast_localtime(&tv, &tm, NULL);
712 ptr = msg;
714 /* Format time and message header */
715 res = snprintf(ptr, size, "\001\010%02d%02d%02d%02d", tm.tm_mon + 1,
716 tm.tm_mday, tm.tm_hour, tm.tm_min);
717 size -= res;
718 ptr += res;
719 if (ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) {
720 /* Indicate number not known */
721 res = snprintf(ptr, size, "\004\001O");
722 size -= res;
723 ptr += res;
724 } else if (flags & CID_PRIVATE_NUMBER) {
725 /* Indicate number is private */
726 res = snprintf(ptr, size, "\004\001P");
727 size -= res;
728 ptr += res;
729 } else {
730 /* Send up to 16 digits of number MAX */
731 i = strlen(number);
732 if (i > 16)
733 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)
758 i = 16;
759 res = snprintf(ptr, size, "\007%c", i);
760 size -= res;
761 ptr += res;
762 for (x = 0; x < i; x++)
763 ptr[x] = name[x];
764 ptr[i] = '\0';
765 ptr += i;
766 size -= i;
768 return (ptr - msg);
772 int vmwi_generate(unsigned char *buf, int active, int mdmf, int codec)
774 unsigned char msg[256];
775 int len = 0;
776 int sum;
777 int x;
778 int bytes = 0;
779 float cr = 1.0;
780 float ci = 0.0;
781 float scont = 0.0;
783 if (mdmf) {
784 /* MDMF Message waiting */
785 msg[len++] = 0x82;
786 /* Length is 3 */
787 msg[len++] = 3;
788 /* IE is "Message Waiting Parameter" */
789 msg[len++] = 0xb;
790 /* Length of IE is one */
791 msg[len++] = 1;
792 /* Active or not */
793 if (active)
794 msg[len++] = 0xff;
795 else
796 msg[len++] = 0x00;
797 } else {
798 /* SDMF Message waiting */
799 msg[len++] = 0x6;
800 /* Length is 3 */
801 msg[len++] = 3;
802 if (active) {
803 msg[len++] = 0x42;
804 msg[len++] = 0x42;
805 msg[len++] = 0x42;
806 } else {
807 msg[len++] = 0x6f;
808 msg[len++] = 0x6f;
809 msg[len++] = 0x6f;
812 sum = 0;
813 for (x = 0; x < len; x++)
814 sum += msg[x];
815 sum = (256 - (sum & 255));
816 msg[len++] = sum;
817 /* Wait a half a second */
818 for (x = 0; x < 4000; x++)
819 PUT_BYTE(0x7f);
820 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
821 for (x = 0; x < 30; x++)
822 PUT_CLID(0x55);
823 /* Send 170ms of callerid marks */
824 for (x = 0; x < 170; x++)
825 PUT_CLID_MARKMS;
826 for (x = 0; x < len; x++) {
827 PUT_CLID(msg[x]);
829 /* Send 50 more ms of marks */
830 for (x = 0; x < 50; x++)
831 PUT_CLID_MARKMS;
832 return bytes;
835 int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, int codec)
837 int bytes = 0;
838 int x, sum;
839 int len;
841 /* Initial carriers (real/imaginary) */
842 float cr = 1.0;
843 float ci = 0.0;
844 float scont = 0.0;
845 char msg[256];
846 len = callerid_genmsg(msg, sizeof(msg), number, name, flags);
847 if (!callwaiting) {
848 /* Wait a half a second */
849 for (x = 0; x < 4000; x++)
850 PUT_BYTE(0x7f);
851 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
852 for (x = 0; x < 30; x++)
853 PUT_CLID(0x55);
855 /* Send 150ms of callerid marks */
856 for (x = 0; x < 150; x++)
857 PUT_CLID_MARKMS;
858 /* Send 0x80 indicating MDMF format */
859 PUT_CLID(0x80);
860 /* Put length of whole message */
861 PUT_CLID(len);
862 sum = 0x80 + strlen(msg);
863 /* Put each character of message and update checksum */
864 for (x = 0; x < len; x++) {
865 PUT_CLID(msg[x]);
866 sum += msg[x];
868 /* Send 2's compliment of sum */
869 PUT_CLID(256 - (sum & 255));
871 /* Send 50 more ms of marks */
872 for (x = 0; x < 50; x++)
873 PUT_CLID_MARKMS;
875 return bytes;
878 /*! \brief Clean up phone string
879 * remove '(', ' ', ')', non-trailing '.', and '-' not in square brackets.
880 * Basically, remove anything that could be invalid in a pattern.
882 void ast_shrink_phone_number(char *n)
884 int x, y = 0;
885 int bracketed = 0;
887 for (x = 0; n[x]; x++) {
888 switch (n[x]) {
889 case '[':
890 bracketed++;
891 n[y++] = n[x];
892 break;
893 case ']':
894 bracketed--;
895 n[y++] = n[x];
896 break;
897 case '-':
898 if (bracketed)
899 n[y++] = n[x];
900 break;
901 case '.':
902 if (!n[x+1])
903 n[y++] = n[x];
904 break;
905 default:
906 /* ignore parenthesis and whitespace */
907 if (!strchr("( )", n[x]))
908 n[y++] = n[x];
911 n[y] = '\0';
914 /*! \brief Checks if phone number consists of valid characters
915 \param exten String that needs to be checked
916 \param valid Valid characters in string
917 \return 1 if valid string, 0 if string contains invalid characters
919 static int ast_is_valid_string(const char *exten, const char *valid)
921 int x;
923 if (ast_strlen_zero(exten))
924 return 0;
925 for (x = 0; exten[x]; x++)
926 if (!strchr(valid, exten[x]))
927 return 0;
928 return 1;
931 /*! \brief checks if string consists only of digits and * \# and +
932 \return 1 if string is valid AST phone number
933 \return 0 if not
935 int ast_isphonenumber(const char *n)
937 return ast_is_valid_string(n, "0123456789*#+");
940 /*! \brief checks if string consists only of digits and ( ) - * \# and +
941 Pre-qualifies the string for ast_shrink_phone_number()
942 \return 1 if string is valid AST shrinkable phone number
943 \return 0 if not
945 int ast_is_shrinkable_phonenumber(const char *exten)
947 return ast_is_valid_string(exten, "0123456789*#+()-.");
950 /*! \brief parse string for caller id information
951 \return always returns 0, as the code always returns something.
952 XXX note that 'name' is not parsed consistently e.g. we have
954 input location name
955 " foo bar " <123> 123 ' foo bar ' (with spaces around)
956 " foo bar " NULL 'foo bar' (without spaces around)
957 " foo bar <123>" 123 '" foo bar'
958 The parsing of leading and trailing space/quotes should be more consistent.
960 int ast_callerid_parse(char *instr, char **name, char **location)
962 char *ns, *ne, *ls, *le;
964 /* Try "name" <location> format or name <location> format */
965 if ((ls = strchr(instr, '<')) && (le = strchr(ls, '>'))) {
966 *ls = *le = '\0'; /* location found, trim off the brackets */
967 *location = ls + 1; /* and this is the result */
968 if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
969 *ns = *ne = '\0'; /* trim off the quotes */
970 *name = ns + 1; /* and this is the name */
971 } else { /* no quotes, trim off leading and trailing spaces */
972 *name = ast_skip_blanks(instr);
973 ast_trim_blanks(*name);
975 } else { /* no valid brackets */
976 char tmp[256];
978 ast_copy_string(tmp, instr, sizeof(tmp));
979 ast_shrink_phone_number(tmp);
980 if (ast_isphonenumber(tmp)) { /* Assume it's just a location */
981 *name = NULL;
982 strcpy(instr, tmp); /* safe, because tmp will always be the same size or smaller than instr */
983 *location = instr;
984 } else { /* Assume it's just a name. */
985 *location = NULL;
986 if ((ns = strchr(instr, '"')) && (ne = strchr(ns + 1, '"'))) {
987 *ns = *ne = '\0'; /* trim off the quotes */
988 *name = ns + 1; /* and this is the name */
989 } else { /* no quotes, trim off leading and trailing spaces */
990 *name = ast_skip_blanks(instr);
991 ast_trim_blanks(*name);
995 return 0;
998 static int __ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int callwaiting, int codec)
1000 if (ast_strlen_zero(name))
1001 name = NULL;
1002 if (ast_strlen_zero(number))
1003 number = NULL;
1004 return callerid_generate(buf, number, name, 0, callwaiting, codec);
1007 int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int codec)
1009 return __ast_callerid_generate(buf, name, number, 0, codec);
1012 int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, int codec)
1014 return __ast_callerid_generate(buf, name, number, 1, codec);
1017 char *ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
1019 if (!unknown)
1020 unknown = "<unknown>";
1021 if (name && num)
1022 snprintf(buf, bufsiz, "\"%s\" <%s>", name, num);
1023 else if (name)
1024 ast_copy_string(buf, name, bufsiz);
1025 else if (num)
1026 ast_copy_string(buf, num, bufsiz);
1027 else
1028 ast_copy_string(buf, unknown, bufsiz);
1029 return buf;
1032 int ast_callerid_split(const char *buf, char *name, int namelen, char *num, int numlen)
1034 char *tmp;
1035 char *l = NULL, *n = NULL;
1037 tmp = ast_strdupa(buf);
1038 ast_callerid_parse(tmp, &n, &l);
1039 if (n)
1040 ast_copy_string(name, n, namelen);
1041 else
1042 name[0] = '\0';
1043 if (l) {
1044 ast_shrink_phone_number(l);
1045 ast_copy_string(num, l, numlen);
1046 } else
1047 num[0] = '\0';
1048 return 0;
1051 /*! \brief Translation table for Caller ID Presentation settings */
1052 static struct {
1053 int val;
1054 const char *name;
1055 const char *description;
1056 } pres_types[] = {
1057 { AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened", "Presentation Allowed, Not Screened"},
1058 { AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", "Presentation Allowed, Passed Screen"},
1059 { AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", "Presentation Allowed, Failed Screen"},
1060 { AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed", "Presentation Allowed, Network Number"},
1061 { AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "prohib_not_screened", "Presentation Prohibited, Not Screened"},
1062 { AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", "Presentation Prohibited, Passed Screen"},
1063 { AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", "Presentation Prohibited, Failed Screen"},
1064 { AST_PRES_PROHIB_NETWORK_NUMBER, "prohib", "Presentation Prohibited, Network Number"},
1065 { AST_PRES_NUMBER_NOT_AVAILABLE, "unavailable", "Number Unavailable"},
1068 /*! \brief Convert caller ID text code to value
1069 used in config file parsing
1070 \param data text string
1071 \return value AST_PRES_ from callerid.h
1073 int ast_parse_caller_presentation(const char *data)
1075 int i;
1077 for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
1078 if (!strcasecmp(pres_types[i].name, data))
1079 return pres_types[i].val;
1082 return -1;
1085 /*! \brief Convert caller ID pres value to explanatory string
1086 \param data value (see callerid.h AST_PRES_ )
1087 \return string for human presentation
1089 const char *ast_describe_caller_presentation(int data)
1091 int i;
1093 for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
1094 if (pres_types[i].val == data)
1095 return pres_types[i].description;
1098 return "unknown";
1101 /*! \brief Convert caller ID pres value to text code
1102 \param data text string
1103 \return string for config file
1105 const char *ast_named_caller_presentation(int data)
1107 int i;
1109 for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
1110 if (pres_types[i].val == data)
1111 return pres_types[i].name;
1114 return "unknown";