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