Add Q.SIG option to zapata.conf
[asterisk/asterisk.git] / callerid.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * CallerID Generation support 
5  * 
6  * Copyright (C) 2001 - 2005, Digium, Inc.
7  *
8  * Mark Spencer <markster@digium.com>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License.
12  *
13  * Includes code and algorithms from the Zapata library.
14  *
15  */
16
17 #include <time.h>
18 #include <string.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <math.h>
23 #include <ctype.h>
24
25 #include "asterisk/ulaw.h"
26 #include "asterisk/alaw.h"
27 #include "asterisk/frame.h"
28 #include "asterisk/channel.h"
29 #include "asterisk/callerid.h"
30 #include "asterisk/logger.h"
31 #include "asterisk/fskmodem.h"
32 #include "asterisk/utils.h"
33
34 struct callerid_state {
35         fsk_data fskd;
36         char rawdata[256];
37         short oldstuff[160];
38         int oldlen;
39         int pos;
40         int type;
41         int cksum;
42         char name[64];
43         char number[64];
44         int flags;
45         int sawflag;
46         int len;
47 };
48
49
50 float cid_dr[4], cid_di[4];
51 float clidsb = 8000.0 / 1200.0;
52 float sasdr, sasdi;
53 float casdr1, casdi1, casdr2, casdi2;
54
55 #define CALLERID_SPACE  2200.0          /* 2200 hz for "0" */
56 #define CALLERID_MARK   1200.0          /* 1200 hz for "1" */
57 #define SAS_FREQ                 440.0
58 #define CAS_FREQ1               2130.0
59 #define CAS_FREQ2               2750.0
60
61 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)
62 {
63         int x;
64         float t;
65         for (x=0;x<len;x++) {
66                 t = *cr1 * ddr1 - *ci1 * ddi1;
67                 *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
68                 *cr1 = t;
69                 t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
70                 *cr1 *= t;
71                 *ci1 *= t;      
72
73                 t = *cr2 * ddr2 - *ci2 * ddi2;
74                 *ci2 = *cr2 * ddi2 + *ci2 * ddr2;
75                 *cr2 = t;
76                 t = 2.0 - (*cr2 * *cr2 + *ci2 * *ci2);
77                 *cr2 *= t;
78                 *ci2 *= t;      
79                 buf[x] = AST_LIN2X((*cr1 + *cr2) * 2048.0);
80         }
81 }
82
83 static inline void gen_tone(unsigned char *buf, int len, int codec, float ddr1, float ddi1, float *cr1, float *ci1)
84 {
85         int x;
86         float t;
87         for (x=0;x<len;x++) {
88                 t = *cr1 * ddr1 - *ci1 * ddi1;
89                 *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
90                 *cr1 = t;
91                 t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
92                 *cr1 *= t;
93                 *ci1 *= t;      
94                 buf[x] = AST_LIN2X(*cr1 * 8192.0);
95         }
96 }
97
98 void callerid_init(void)
99 {
100         /* Initialize stuff for inverse FFT */
101         cid_dr[0] = cos(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
102         cid_di[0] = sin(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
103         cid_dr[1] = cos(CALLERID_MARK * 2.0 * M_PI / 8000.0);
104         cid_di[1] = sin(CALLERID_MARK * 2.0 * M_PI / 8000.0);
105         sasdr = cos(SAS_FREQ * 2.0 * M_PI / 8000.0);
106         sasdi = sin(SAS_FREQ * 2.0 * M_PI / 8000.0);
107         casdr1 = cos(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
108         casdi1 = sin(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
109         casdr2 = cos(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
110         casdi2 = sin(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
111 }
112
113 struct callerid_state *callerid_new(int cid_signalling)
114 {
115         struct callerid_state *cid;
116         cid = malloc(sizeof(struct callerid_state));
117         if (cid) {
118                 memset(cid, 0, sizeof(struct callerid_state));
119                 cid->fskd.spb = 7;              /* 1200 baud */
120                 cid->fskd.hdlc = 0;             /* Async */
121                 cid->fskd.nbit = 8;             /* 8 bits */
122                 cid->fskd.nstop = 1;    /* 1 stop bit */
123                 cid->fskd.paridad = 0;  /* No parity */
124                 cid->fskd.bw=1;                 /* Filter 800 Hz */
125                 if (cid_signalling == 2) { /* v23 signalling */
126                         cid->fskd.f_mark_idx =  4;      /* 1300 Hz */
127                         cid->fskd.f_space_idx = 5;      /* 2100 Hz */
128                 } else { /* Bell 202 signalling as default */ 
129                         cid->fskd.f_mark_idx =  2;      /* 1200 Hz */
130                         cid->fskd.f_space_idx = 3;      /* 2200 Hz */
131                 }
132                 cid->fskd.pcola = 0;            /* No clue */
133                 cid->fskd.cont = 0;                     /* Digital PLL reset */
134                 cid->fskd.x0 = 0.0;
135                 cid->fskd.state = 0;
136                 memset(cid->name, 0, sizeof(cid->name));
137                 memset(cid->number, 0, sizeof(cid->number));
138                 cid->flags = CID_UNKNOWN_NAME | CID_UNKNOWN_NUMBER;
139                 cid->pos = 0;
140         } else
141                 ast_log(LOG_WARNING, "Out of memory\n");
142         return cid;
143 }
144
145 void callerid_get(struct callerid_state *cid, char **name, char **number, int *flags)
146 {
147         *flags = cid->flags;
148         if (cid->flags & (CID_UNKNOWN_NAME | CID_PRIVATE_NUMBER))
149                 *name = NULL;
150         else
151                 *name = cid->name;
152         if (cid->flags & (CID_UNKNOWN_NUMBER | CID_PRIVATE_NUMBER))
153                 *number = NULL;
154         else
155                 *number = cid->number;
156 }
157
158 void callerid_get_dtmf(char *cidstring, char *number, int *flags)
159 {
160         int i;
161         int code;
162
163         /* "Clear" the number-buffer. */
164         number[0] = 0;
165
166         if (strlen(cidstring) < 2) {
167                 ast_log(LOG_DEBUG, "No cid detected\n");
168                 *flags = CID_UNKNOWN_NUMBER;
169                 return;
170         }
171         
172         /* Detect protocol and special types */
173         if (cidstring[0] == 'B') {
174                 /* Handle special codes */
175                 code = atoi(&cidstring[1]);
176                 if (code == 0)
177                         *flags = CID_UNKNOWN_NUMBER;
178                 else if (code == 10) 
179                         *flags = CID_PRIVATE_NUMBER;
180                 else
181                         ast_log(LOG_DEBUG, "Unknown DTMF code %d\n", code);
182         } else if (cidstring[0] == 'D' && cidstring[2] == '#') {
183                 /* .DK special code */
184                 if (cidstring[1] == '1')
185                         *flags = CID_PRIVATE_NUMBER;
186                 if (cidstring[1] == '2' || cidstring[1] == '3')
187                         *flags = CID_UNKNOWN_NUMBER;
188         } else if (cidstring[0] == 'D' || cidstring[0] == 'A') {
189                 /* "Standard" callerid */
190                 for (i = 1; i < strlen(cidstring); i++ ) {
191                         if (cidstring[i] == 'C' || cidstring[i] == '#')
192                                 break;
193                         if (isdigit(cidstring[i]))
194                                 number[i-1] = cidstring[i];
195                         else
196                                 ast_log(LOG_DEBUG, "Unknown CID digit '%c'\n",
197                                         cidstring[i]);
198                 }
199                 number[i-1] = 0;
200         } else if (isdigit(cidstring[0])) {
201                 /* It begins with a digit, so we parse it as a number and hope
202                  * for the best */
203                 ast_log(LOG_WARNING, "Couldn't detect start-character. CID "
204                         "parsing might be unreliable\n");
205                 for (i = 0; i < strlen(cidstring); i++) {
206                         if (isdigit(cidstring[i]))
207                                 number[i] = cidstring[i];
208                         else
209                                 break;
210                 }
211                 number[i] = 0;
212         } else {
213                 ast_log(LOG_DEBUG, "Unknown CID protocol, start digit '%c'\n", 
214                         cidstring[0]);
215                 *flags = CID_UNKNOWN_NUMBER;
216         }
217 }
218
219 int ast_gen_cas(unsigned char *outbuf, int sendsas, int len, int codec)
220 {
221         int pos = 0;
222         int saslen=2400;
223         float cr1 = 1.0;
224         float ci1 = 0.0;
225         float cr2 = 1.0;
226         float ci2 = 0.0;
227         if (sendsas) {
228                 if (len < saslen)
229                         return -1;
230                 gen_tone(outbuf, saslen, codec, sasdr, sasdi, &cr1, &ci1);
231                 len -= saslen;
232                 pos += saslen;
233                 cr2 = cr1;
234                 ci2 = ci1;
235         }
236         gen_tones(outbuf + pos, len, codec, casdr1, casdi1, casdr2, casdi2, &cr1, &ci1, &cr2, &ci2);
237         return 0;
238 }
239
240 int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int codec)
241 {
242         int mylen = len;
243         int olen;
244         int b = 'X';
245         int res;
246         int x;
247         short *buf = malloc(2 * len + cid->oldlen);
248         short *obuf = buf;
249         if (!buf) {
250                 ast_log(LOG_WARNING, "Out of memory\n");
251                 return -1;
252         }
253         memset(buf, 0, 2 * len + cid->oldlen);
254         memcpy(buf, cid->oldstuff, cid->oldlen);
255         mylen += cid->oldlen/2;
256         for (x=0;x<len;x++) 
257                 buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
258         while(mylen >= 160) {
259                 olen = mylen;
260                 res = fsk_serie(&cid->fskd, buf, &mylen, &b);
261                 if (mylen < 0) {
262                         ast_log(LOG_ERROR, "fsk_serie made mylen < 0 (%d)\n", mylen);
263                         return -1;
264                 }
265                 buf += (olen - mylen);
266                 if (res < 0) {
267                         ast_log(LOG_NOTICE, "fsk_serie failed\n");
268                         return -1;
269                 }
270                 if (res == 1) {
271                         /* Ignore invalid bytes */
272                         if (b > 0xff)
273                                 continue;
274                         switch(cid->sawflag) {
275                         case 0: /* Look for flag */
276                                 if (b == 'U')
277                                         cid->sawflag = 2;
278                                 break;
279                         case 2: /* Get lead-in */
280                                 if ((b == 0x04) || (b == 0x80)) {
281                                         cid->type = b;
282                                         cid->sawflag = 3;
283                                         cid->cksum = b;
284                                 }
285                                 break;
286                         case 3: /* Get length */
287                                 /* Not a lead in.  We're ready  */
288                                 cid->sawflag = 4;
289                                 cid->len = b;
290                                 cid->pos = 0;
291                                 cid->cksum += b;
292                                 break;
293                         case 4: /* Retrieve message */
294                                 if (cid->pos >= 128) {
295                                         ast_log(LOG_WARNING, "Caller ID too long???\n");
296                                         return -1;
297                                 }
298                                 cid->rawdata[cid->pos++] = b;
299                                 cid->len--;
300                                 cid->cksum += b;
301                                 if (!cid->len) {
302                                         cid->rawdata[cid->pos] = '\0';
303                                         cid->sawflag = 5;
304                                 }
305                                 break;
306                         case 5: /* Check checksum */
307                                 if (b != (256 - (cid->cksum & 0xff))) {
308                                         ast_log(LOG_NOTICE, "Caller*ID failed checksum\n");
309                                         /* Try again */
310                                         cid->sawflag = 0;
311                                         break;
312                                 }
313                 
314                                 cid->number[0] = '\0';
315                                 cid->name[0] = '\0';
316                                 /* If we get this far we're fine.  */
317                                 if (cid->type == 0x80) {
318                                         /* MDMF */
319                                         /* Go through each element and process */
320                                         for (x=0;x< cid->pos;) {
321                                                 switch(cid->rawdata[x++]) {
322                                                 case 1:
323                                                         /* Date */
324                                                         break;
325                                                 case 2: /* Number */
326                                                 case 3: /* Number (for Zebble) */
327                                                 case 4: /* Number */
328                                                         res = cid->rawdata[x];
329                                                         if (res > 32) {
330                                                                 ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]);
331                                                                 res = 32; 
332                                                         }
333                                                         if (ast_strlen_zero(cid->number)) {
334                                                                 memcpy(cid->number, cid->rawdata + x + 1, res);
335                                                                 /* Null terminate */
336                                                                 cid->number[res] = '\0';
337                                                         }
338                                                         break;
339                                                 case 6: /* Stentor Call Qualifier (ie. Long Distance call) */
340                                                         break;
341                                                 case 7: /* Name */
342                                                 case 8: /* Name */
343                                                         res = cid->rawdata[x];
344                                                         if (res > 32) {
345                                                                 ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]);
346                                                                 res = 32; 
347                                                         }
348                                                         memcpy(cid->name, cid->rawdata + x + 1, res);
349                                                         cid->name[res] = '\0';
350                                                         break;
351                                                 case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting  */
352                                                 case 19: /* UK: Network message system status (Number of messages waiting) */
353                                                 case 22: /* Something French */
354                                                         break;
355                                                 default:
356                                                         ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x-1]);
357                                                 }
358                                                 x += cid->rawdata[x];
359                                                 x++;
360                                         }
361                                 } else {
362                                         /* SDMF */
363                                         strncpy(cid->number, cid->rawdata + 8, sizeof(cid->number)-1);
364                                 }
365                                 /* Update flags */
366                                 cid->flags = 0;
367                                 if (!strcmp(cid->number, "P")) {
368                                         strcpy(cid->number, "");
369                                         cid->flags |= CID_PRIVATE_NUMBER;
370                                 } else if (!strcmp(cid->number, "O") || ast_strlen_zero(cid->number)) {
371                                         strcpy(cid->number, "");
372                                         cid->flags |= CID_UNKNOWN_NUMBER;
373                                 }
374                                 if (!strcmp(cid->name, "P")) {
375                                         strcpy(cid->name, "");
376                                         cid->flags |= CID_PRIVATE_NAME;
377                                 } else if (!strcmp(cid->name, "O") || ast_strlen_zero(cid->name)) {
378                                         strcpy(cid->name, "");
379                                         cid->flags |= CID_UNKNOWN_NAME;
380                                 }
381                                 return 1;
382                                 break;
383                         default:
384                                 ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag);
385                         }
386                 }
387         }
388         if (mylen) {
389                 memcpy(cid->oldstuff, buf, mylen * 2);
390                 cid->oldlen = mylen * 2;
391         } else
392                 cid->oldlen = 0;
393         free(obuf);
394         return 0;
395 }
396
397 void callerid_free(struct callerid_state *cid)
398 {
399         free(cid);
400 }
401
402 static int callerid_genmsg(char *msg, int size, char *number, char *name, int flags)
403 {
404         time_t t;
405         struct tm tm;
406         char *ptr;
407         int res;
408         int i,x;
409         /* Get the time */
410         time(&t);
411         localtime_r(&t,&tm);
412         
413         ptr = msg;
414         
415         /* Format time and message header */
416         res = snprintf(ptr, size, "\001\010%02d%02d%02d%02d", tm.tm_mon + 1,
417                                 tm.tm_mday, tm.tm_hour, tm.tm_min);
418         size -= res;
419         ptr += res;
420         if (!number || ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) {
421                 /* Indicate number not known */
422                 res = snprintf(ptr, size, "\004\001O");
423                 size -= res;
424                 ptr += res;
425         } else if (flags & CID_PRIVATE_NUMBER) {
426                 /* Indicate number is private */
427                 res = snprintf(ptr, size, "\004\001P");
428                 size -= res;
429                 ptr += res;
430         } else {
431                 /* Send up to 16 digits of number MAX */
432                 i = strlen(number);
433                 if (i > 16) i = 16;
434                 res = snprintf(ptr, size, "\002%c", i);
435                 size -= res;
436                 ptr += res;
437                 for (x=0;x<i;x++)
438                         ptr[x] = number[x];
439                 ptr[i] = '\0';
440                 ptr += i;
441                 size -= i;
442         }
443
444         if (!name || ast_strlen_zero(name) || (flags & CID_UNKNOWN_NAME)) {
445                 /* Indicate name not known */
446                 res = snprintf(ptr, size, "\010\001O");
447                 size -= res;
448                 ptr += res;
449         } else if (flags & CID_PRIVATE_NAME) {
450                 /* Indicate name is private */
451                 res = snprintf(ptr, size, "\010\001P");
452                 size -= res;
453                 ptr += res;
454         } else {
455                 /* Send up to 16 digits of name MAX */
456                 i = strlen(name);
457                 if (i > 16) i = 16;
458                 res = snprintf(ptr, size, "\007%c", i);
459                 size -= res;
460                 ptr += res;
461                 for (x=0;x<i;x++)
462                         ptr[x] = name[x];
463                 ptr[i] = '\0';
464                 ptr += i;
465                 size -= i;
466         }
467         return (ptr - msg);
468         
469 }
470
471 int vmwi_generate(unsigned char *buf, int active, int mdmf, int codec)
472 {
473         unsigned char msg[256];
474         int len=0;
475         int sum;
476         int x;
477         int bytes = 0;
478         float cr = 1.0;
479         float ci = 0.0;
480         float scont = 0.0;
481         if (mdmf) {
482                 /* MDMF Message waiting */
483                 msg[len++] = 0x82;
484                 /* Length is 3 */
485                 msg[len++] = 3;
486                 /* IE is "Message Waiting Parameter" */
487                 msg[len++] = 0xb;
488                 /* Length of IE is one */
489                 msg[len++] = 1;
490                 /* Active or not */
491                 if (active)
492                         msg[len++] = 0xff;
493                 else
494                         msg[len++] = 0x00;
495         } else {
496                 /* SDMF Message waiting */
497                 msg[len++] = 0x6;
498                 /* Length is 3 */
499                 msg[len++] = 3;
500                 if (active) {
501                         msg[len++] = 0x42;
502                         msg[len++] = 0x42;
503                         msg[len++] = 0x42;
504                 } else {
505                         msg[len++] = 0x6f;
506                         msg[len++] = 0x6f;
507                         msg[len++] = 0x6f;
508                 }
509         }
510         sum = 0;
511         for (x=0;x<len;x++)
512                 sum += msg[x];
513         sum = (256 - (sum & 255));
514         msg[len++] = sum;
515         /* Wait a half a second */
516         for (x=0;x<4000;x++)
517                 PUT_BYTE(0x7f);
518         /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
519         for (x=0;x<30;x++)
520                 PUT_CLID(0x55);
521         /* Send 170ms of callerid marks */
522         for (x=0;x<170;x++)
523                 PUT_CLID_MARKMS;
524         for (x=0;x<len;x++) {
525                 PUT_CLID(msg[x]);
526         }
527         /* Send 50 more ms of marks */
528         for (x=0;x<50;x++)
529                 PUT_CLID_MARKMS;
530         return bytes;
531 }
532
533 int callerid_generate(unsigned char *buf, char *number, char *name, int flags, int callwaiting, int codec)
534 {
535         int bytes=0;
536         int x, sum;
537         int len;
538         /* Initial carriers (real/imaginary) */
539         float cr = 1.0;
540         float ci = 0.0;
541         float scont = 0.0;
542         unsigned char msg[256];
543         len = callerid_genmsg(msg, sizeof(msg), number, name, flags);
544         if (!callwaiting) {
545                 /* Wait a half a second */
546                 for (x=0;x<4000;x++)
547                         PUT_BYTE(0x7f);
548                 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
549                 for (x=0;x<30;x++)
550                         PUT_CLID(0x55);
551         }
552         /* Send 150ms of callerid marks */
553         for (x=0;x<150;x++)
554                 PUT_CLID_MARKMS;
555         /* Send 0x80 indicating MDMF format */
556         PUT_CLID(0x80);
557         /* Put length of whole message */
558         PUT_CLID(len);
559         sum = 0x80 + strlen(msg);
560         /* Put each character of message and update checksum */
561         for (x=0;x<len; x++) {
562                 PUT_CLID(msg[x]);
563                 sum += msg[x];
564         }
565         /* Send 2's compliment of sum */
566         PUT_CLID(256 - (sum & 255));
567
568         /* Send 50 more ms of marks */
569         for (x=0;x<50;x++)
570                 PUT_CLID_MARKMS;
571         
572         return bytes;
573 }
574
575 void ast_shrink_phone_number(char *n)
576 {
577         int x,y=0;
578         int bracketed=0;
579         for (x=0;n[x];x++) {
580                 switch(n[x]) {
581                 case '[':
582                         bracketed++;
583                         n[y++] = n[x];
584                         break;
585                 case ']':
586                         bracketed--;
587                         n[y++] = n[x];
588                         break;
589                 case '-':
590                         if (bracketed)
591                                 n[y++] = n[x];
592                         break;
593                 case '.':
594                         if (!n[x+1])
595                                 n[y++] = n[x];
596                         break;
597                 default:
598                         if (!strchr("( )", n[x]))
599                                 n[y++] = n[x];
600                 }
601         }
602         n[y] = '\0';
603 }
604
605 int ast_isphonenumber(char *n)
606 {
607         int x;
608         if (!n || ast_strlen_zero(n))
609                 return 0;
610         for (x=0;n[x];x++)
611                 if (!strchr("0123456789*#+", n[x]))
612                         return 0;
613         return 1;
614 }
615
616 int ast_callerid_parse(char *instr, char **name, char **location)
617 {
618         char *ns, *ne;
619         char *ls, *le;
620         char tmp[256];
621         /* Try for "name" <location> format or 
622            name <location> format */
623         if ((ls = strchr(instr, '<')) && (le = strchr(ls, '>'))) {
624                 /* Found the location */
625                 *le = '\0';
626                 *ls = '\0';
627                 *location = ls + 1;
628                 if ((ns = strchr(instr, '\"')) && (ne = strchr(ns + 1, '\"'))) {
629                         /* Get name out of quotes */
630                         *ns = '\0';
631                         *ne = '\0';
632                         *name = ns + 1;
633                         return 0;
634                 } else {
635                         /* Just trim off any trailing spaces */
636                         *name = instr;
637                         while(!ast_strlen_zero(instr) && (instr[strlen(instr) - 1] < 33))
638                                 instr[strlen(instr) - 1] = '\0';
639                         /* And leading spaces */
640                         while(**name && (**name < 33))
641                                 (*name)++;
642                         return 0;
643                 }
644         } else {
645                 strncpy(tmp, instr, sizeof(tmp)-1);
646                 ast_shrink_phone_number(tmp);
647                 if (ast_isphonenumber(tmp)) {
648                         /* Assume it's just a location */
649                         *name = NULL;
650                         *location = instr;
651                 } else {
652                         /* Assume it's just a name.  Make sure it's not quoted though */
653                         *name = instr;
654                         while(*(*name) && ((*(*name) < 33) || (*(*name) == '\"'))) (*name)++;
655                         ne = *name + strlen(*name) - 1;
656                         while((ne > *name) && ((*ne < 33) || (*ne == '\"'))) { *ne = '\0'; ne--; }
657                         *location = NULL;
658                 }
659                 return 0;
660         }
661         return -1;
662 }
663
664 static int __ast_callerid_generate(unsigned char *buf, char *name, char *number, int callwaiting, int codec)
665 {
666         if (name && ast_strlen_zero(name))
667                 name = NULL;
668         if (number && ast_strlen_zero(number))
669                 number = NULL;
670         return callerid_generate(buf, number, name, 0, callwaiting, codec);
671 }
672
673 int ast_callerid_generate(unsigned char *buf, char *name, char *number, int codec)
674 {
675         return __ast_callerid_generate(buf, name, number, 0, codec);
676 }
677
678 int ast_callerid_callwaiting_generate(unsigned char *buf, char *name, char *number, int codec)
679 {
680         return __ast_callerid_generate(buf, name, number, 1, codec);
681 }
682
683 char *ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
684 {
685         if (!unknown)
686                 unknown = "<unknown>";
687         if (name && num)
688                 snprintf(buf, bufsiz, "\"%s\" <%s>", name, num);
689         else if (name) 
690                 strncpy(buf, name, bufsiz - 1);
691         else if (num)
692                 strncpy(buf, num, bufsiz - 1);
693         else
694                 strncpy(buf, unknown, bufsiz - 1);
695         return buf;
696 }
697 int ast_callerid_split(const char *buf, char *name, int namelen, char *num, int numlen)
698 {
699         char *tmp;
700         char *l = NULL, *n = NULL;
701         tmp = ast_strdupa(buf);
702         if (!tmp) {
703                 name[0] = '\0';
704                 num[0] = '\0';
705                 return -1;
706         }
707         ast_callerid_parse(tmp, &n, &l);
708         if (n)
709                 strncpy(name, n, namelen - 1);
710         else
711                 name[0] = '\0';
712         if (l) {
713                 ast_shrink_phone_number(l);
714                 strncpy(num, l, numlen - 1);
715         } else
716                 num[0] = '\0';
717         return 0;
718 }
719
720 static struct {
721         int val;
722         char *name;
723         char *description;
724 } pres_types[] = {
725         {  AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened", "Presentation Allowed, Not Screened"},
726         {  AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", "Presentation Allowed, Passed Screen"},
727         {  AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", "Presentation Allowed, Failed Screen"},
728         {  AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed", "Presentation Allowed, Network Number"},
729         {  AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "prohib_not_screened", "Presentation Prohibited, Not Screened"},
730         {  AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", "Presentation Prohibited, Passed Screen"},
731         {  AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", "Presentation Prohibited, Failed Screen"},
732         {  AST_PRES_PROHIB_NETWORK_NUMBER, "prohib", "Presentation Prohibited, Network Number"},
733         {  AST_PRES_NUMBER_NOT_AVAILABLE, "unavailable", "Number Unavailable"},
734 };
735
736 int ast_parse_caller_presentation(const char *data)
737 {
738         int i;
739
740         for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
741                 if (!strcasecmp(pres_types[i].name, data))
742                         return pres_types[i].val;
743         }
744
745         return -1;
746 }
747
748 const char *ast_describe_caller_presentation(int data)
749 {
750         int i;
751
752         for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
753                 if (pres_types[i].val == data)
754                         return pres_types[i].description;
755         }
756
757         return "unknown";
758 }