f78714fbf45ab1b574c52292296b7446b81953d1
[asterisk/asterisk.git] / callerid.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * CallerID Generation support 
5  * 
6  * Copyright (C) 2001, Linux Support Services, Inc.
7  *
8  * Mark Spencer <markster@linux-support.net>
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 <asterisk/ulaw.h>
24 #include <asterisk/callerid.h>
25 #include <asterisk/logger.h>
26 #include <asterisk/fskmodem.h>
27 #include "sas.h"
28 #include "cas.h"
29
30
31 struct callerid_state {
32         fsk_data fskd;
33         char rawdata[256];
34         short oldstuff[160];
35         int oldlen;
36         int pos;
37         int type;
38         int cksum;
39         char name[64];
40         char number[64];
41         int flags;
42         int sawflag;
43         int len;
44 };
45
46 static float dr[4], di[4];
47 static float clidsb = 8000.0 / 1200.0;
48
49 #define CALLERID_SPACE  2200.0          /* 2200 hz for "0" */
50 #define CALLERID_MARK   1200.0          /* 1200 hz for "1" */
51
52 void callerid_init(void)
53 {
54         /* Initialize stuff for inverse FFT */
55         dr[0] = cos(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
56         di[0] = sin(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
57         dr[1] = cos(CALLERID_MARK * 2.0 * M_PI / 8000.0);
58         di[1] = sin(CALLERID_MARK * 2.0 * M_PI / 8000.0);
59 }
60
61 struct callerid_state *callerid_new(void)
62 {
63         struct callerid_state *cid;
64         cid = malloc(sizeof(struct callerid_state));
65         memset(cid, 0, sizeof(*cid));
66         if (cid) {
67                 cid->fskd.spb = 7;              /* 1200 baud */
68                 cid->fskd.hdlc = 0;             /* Async */
69                 cid->fskd.nbit = 8;             /* 8 bits */
70                 cid->fskd.nstop = 1;    /* 1 stop bit */
71                 cid->fskd.paridad = 0;  /* No parity */
72                 cid->fskd.bw=1;                 /* Filter 800 Hz */
73                 cid->fskd.f_mark_idx =  2;      /* 1200 Hz */
74                 cid->fskd.f_space_idx = 3;      /* 2200 Hz */
75                 cid->fskd.pcola = 0;            /* No clue */
76                 cid->fskd.cont = 0;                     /* Digital PLL reset */
77                 cid->fskd.x0 = 0.0;
78                 cid->fskd.state = 0;
79                 memset(cid->name, 0, sizeof(cid->name));
80                 memset(cid->number, 0, sizeof(cid->number));
81                 cid->flags = CID_UNKNOWN_NAME | CID_UNKNOWN_NUMBER;
82                 cid->pos = 0;
83         } else
84                 ast_log(LOG_WARNING, "Out of memory\n");
85         return cid;
86 }
87
88 void callerid_get(struct callerid_state *cid, char **name, char **number, int *flags)
89 {
90         *flags = cid->flags;
91         if (cid->flags & (CID_UNKNOWN_NAME | CID_PRIVATE_NUMBER))
92                 *name = NULL;
93         else
94                 *name = cid->name;
95         if (cid->flags & (CID_UNKNOWN_NUMBER | CID_PRIVATE_NUMBER))
96                 *number = NULL;
97         else
98                 *number = cid->number;
99 }
100
101 int ast_callerid_gen_cas(unsigned char *outbuf, int len)
102 {
103         int pos = 0;
104         int cnt;
105         int saslen=2400;
106         if (len < saslen)
107                 return -1;
108         while(saslen) {
109                 cnt = saslen;
110                 if (cnt > sizeof(sas))
111                         cnt = sizeof(sas);
112                 memcpy(outbuf + pos, sas, cnt);
113                 pos += cnt;
114                 len -= cnt;
115                 saslen -= cnt;
116         }
117         while(len) {
118                 cnt = len;
119                 if (cnt > sizeof(cas))
120                         cnt = sizeof(cas);
121                 memcpy(outbuf + pos, cas, cnt);
122                 pos += cnt;
123                 len -= cnt;
124         }
125         return 0;
126 }
127
128 int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len)
129 {
130         int mylen = len;
131         int olen;
132         int b = 'X';
133         int res;
134         int x;
135         short *buf = malloc(2 * len + cid->oldlen);
136         short *obuf = buf;
137         if (!buf) {
138                 ast_log(LOG_WARNING, "Out of memory\n");
139                 return -1;
140         }
141         memset(buf, 0, 2 * len + cid->oldlen);
142         memcpy(buf, cid->oldstuff, cid->oldlen);
143         mylen += cid->oldlen/2;
144         for (x=0;x<len;x++) 
145                 buf[x+cid->oldlen/2] = ast_mulaw[ubuf[x]];
146         while(mylen >= 80) {
147                 olen = mylen;
148                 res = fsk_serie(&cid->fskd, buf, &mylen, &b);
149                 buf += (olen - mylen);
150                 if (res < 0) {
151                         ast_log(LOG_NOTICE, "fsk_serie failed\n");
152                         return -1;
153                 }
154                 if (res == 1) {
155                         /* Ignore invalid bytes */
156                         if (b > 0xff)
157                                 continue;
158                         switch(cid->sawflag) {
159                         case 0: /* Look for flag */
160                                 if (b == 'U')
161                                         cid->sawflag = 2;
162                                 break;
163                         case 2: /* Get lead-in */
164                                 if ((b == 0x04) || (b == 0x80)) {
165                                         cid->type = b;
166                                         cid->sawflag = 3;
167                                         cid->cksum = b;
168                                 }
169                                 break;
170                         case 3: /* Get length */
171                                 /* Not a lead in.  We're ready  */
172                                 cid->sawflag = 4;
173                                 cid->len = b;
174                                 cid->pos = 0;
175                                 cid->cksum += b;
176                                 break;
177                         case 4: /* Retrieve message */
178                                 if (cid->pos >= 128) {
179                                         ast_log(LOG_WARNING, "Caller ID too long???\n");
180                                         return -1;
181                                 }
182                                 cid->rawdata[cid->pos++] = b;
183                                 cid->len--;
184                                 cid->cksum += b;
185                                 if (!cid->len) {
186                                         cid->rawdata[cid->pos] = '\0';
187                                         cid->sawflag = 5;
188                                 }
189                                 break;
190                         case 5: /* Check checksum */
191                                 if (b != (256 - (cid->cksum & 0xff))) {
192                                         ast_log(LOG_NOTICE, "Caller*ID failed checksum\n");
193                                         /* Try again */
194                                         cid->sawflag = 0;
195                                         break;
196                                 }
197                 
198                                 strcpy(cid->number, "");
199                                 strcpy(cid->name, "");
200                                 /* If we get this far we're fine.  */
201                                 if (cid->type == 0x80) {
202                                         /* MDMF */
203                                         /* Go through each element and process */
204                                         for (x=0;x< cid->pos;) {
205                                                 switch(cid->rawdata[x++]) {
206                                                 case 1:
207                                                         /* Date */
208                                                         break;
209                                                 case 2: /* Number */
210                                                 case 4: /* Number */
211                                                         res = cid->rawdata[x];
212                                                         if (res > 32) {
213                                                                 ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]);
214                                                                 res = 32; 
215                                                         }
216                                                         memcpy(cid->number, cid->rawdata + x + 1, res);
217                                                         /* Null terminate */
218                                                         cid->number[res] = '\0';
219                                                         break;
220                                                 case 7: /* Name */
221                                                 case 8: /* Name */
222                                                         res = cid->rawdata[x];
223                                                         if (res > 32) {
224                                                                 ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]);
225                                                                 res = 32; 
226                                                         }
227                                                         memcpy(cid->name, cid->rawdata + x + 1, res);
228                                                         cid->name[res] = '\0';
229                                                         break;
230                                                 default:
231                                                         ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x-1]);
232                                                 }
233                                                 x += cid->rawdata[x];
234                                                 x++;
235                                         }
236                                 } else {
237                                         /* SDMF */
238                                         strncpy(cid->number, cid->rawdata + 8, sizeof(cid->number));
239                                 }
240                                 /* Update flags */
241                                 cid->flags = 0;
242                                 if (!strcmp(cid->number, "P")) {
243                                         strcpy(cid->number, "");
244                                         cid->flags |= CID_PRIVATE_NUMBER;
245                                 } else if (!strcmp(cid->number, "O") || !strlen(cid->number)) {
246                                         strcpy(cid->number, "");
247                                         cid->flags |= CID_UNKNOWN_NUMBER;
248                                 }
249                                 if (!strcmp(cid->name, "P")) {
250                                         strcpy(cid->name, "");
251                                         cid->flags |= CID_PRIVATE_NAME;
252                                 } else if (!strcmp(cid->name, "O") || !strlen(cid->name)) {
253                                         strcpy(cid->name, "");
254                                         cid->flags |= CID_UNKNOWN_NAME;
255                                 }
256                                 return 1;
257                                 break;
258                         default:
259                                 ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag);
260                         }
261                 }
262         }
263         if (mylen) {
264                 memcpy(cid->oldstuff, buf, mylen * 2);
265                 cid->oldlen = mylen * 2;
266         }
267         free(obuf);
268         return 0;
269 }
270
271 void callerid_free(struct callerid_state *cid)
272 {
273         free(cid);
274 }
275
276 static void callerid_genmsg(char *msg, int size, char *number, char *name, int flags)
277 {
278         time_t t;
279         struct tm *tm;
280         char *ptr;
281         int res;
282         int i,x;
283         /* Get the time */
284         time(&t);
285         tm = localtime(&t);
286         
287         ptr = msg;
288         
289         /* Format time and message header */
290         res = snprintf(ptr, size, "\001\010%02d%02d%02d%02d", tm->tm_mon + 1,
291                                 tm->tm_mday, tm->tm_hour, tm->tm_min);
292         size -= res;
293         ptr += res;
294         if (!number || !strlen(number) || (flags & CID_UNKNOWN_NUMBER)) {
295                 /* Indicate number not known */
296                 res = snprintf(ptr, size, "\004\001O");
297                 size -= res;
298                 ptr += res;
299         } else if (flags & CID_PRIVATE_NUMBER) {
300                 /* Indicate number is private */
301                 res = snprintf(ptr, size, "\004\001P");
302                 size -= res;
303                 ptr += res;
304         } else {
305                 /* Send up to 10 digits of number MAX */
306                 i = strlen(number);
307                 if (i > 10) i = 10;
308                 res = snprintf(ptr, size, "\002%c", i);
309                 size -= res;
310                 ptr += res;
311                 for (x=0;x<i;x++)
312                         ptr[x] = number[x];
313                 ptr[i] = '\0';
314                 ptr += i;
315                 size -= i;
316         }
317
318         if (!name || !strlen(name) || (flags & CID_UNKNOWN_NAME)) {
319                 /* Indicate name not known */
320                 res = snprintf(ptr, size, "\010\001O");
321                 size -= res;
322                 ptr += res;
323         } else if (flags & CID_PRIVATE_NAME) {
324                 /* Indicate name is private */
325                 res = snprintf(ptr, size, "\010\001P");
326                 size -= res;
327                 ptr += res;
328         } else {
329                 /* Send up to 10 digits of number MAX */
330                 i = strlen(name);
331                 if (i > 16) i = 16;
332                 res = snprintf(ptr, size, "\007%c", i);
333                 size -= res;
334                 ptr += res;
335                 for (x=0;x<i;x++)
336                         ptr[x] = name[x];
337                 ptr[i] = '\0';
338                 ptr += i;
339                 size -= i;
340         }
341         
342 }
343
344 static inline float callerid_getcarrier(float *cr, float *ci, int bit)
345 {
346         /* Move along.  There's nothing to see here... */
347         float t;
348         t = *cr * dr[bit] - *ci * di[bit];
349         *ci = *cr * di[bit] + *ci * dr[bit];
350         *cr = t;
351         
352         t = 2.0 - (*cr * *cr + *ci * *ci);
353         *cr *= t;
354         *ci *= t;
355         return *cr;
356 }       
357
358 #define PUT_BYTE(a) do { \
359         *(buf++) = (a); \
360         bytes++; \
361 } while(0)
362
363 #define PUT_AUDIO_SAMPLE(y) do { \
364         int index = (short)(rint(8192.0 * (y))); \
365         *(buf++) = ast_lin2mu[index + 32768]; \
366         bytes++; \
367 } while(0)
368         
369 #define PUT_CLID_MARKMS do { \
370         int x; \
371         for (x=0;x<8;x++) \
372                 PUT_AUDIO_SAMPLE(callerid_getcarrier(&cr, &ci, 1)); \
373 } while(0)
374
375 #define PUT_CLID_BAUD(bit) do { \
376         while(scont < clidsb) { \
377                 PUT_AUDIO_SAMPLE(callerid_getcarrier(&cr, &ci, bit)); \
378                 scont += 1.0; \
379         } \
380         scont -= clidsb; \
381 } while(0)
382
383
384 #define PUT_CLID(byte) do { \
385         int z; \
386         unsigned char b = (byte); \
387         PUT_CLID_BAUD(0);       /* Start bit */ \
388         for (z=0;z<8;z++) { \
389                 PUT_CLID_BAUD(b & 1); \
390                 b >>= 1; \
391         } \
392         PUT_CLID_BAUD(1);       /* Stop bit */ \
393 } while(0);     
394
395 int callerid_generate(unsigned char *buf, char *number, char *name, int flags, int callwaiting)
396 {
397         int bytes=0;
398         int x, sum;
399         /* Initial carriers (real/imaginary) */
400         float cr = 1.0;
401         float ci = 0.0;
402         float scont = 0.0;
403         char msg[256];
404         callerid_genmsg(msg, sizeof(msg), number, name, flags);
405         if (!callwaiting) {
406                 /* Wait a half a second */
407                 for (x=0;x<4000;x++)
408                         PUT_BYTE(0x7f);
409                 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
410                 for (x=0;x<30;x++)
411                         PUT_CLID(0x55);
412         }
413         /* Send 150ms of callerid marks */
414         for (x=0;x<150;x++)
415                 PUT_CLID_MARKMS;
416         /* Send 0x80 indicating MDMF format */
417         PUT_CLID(0x80);
418         /* Put length of whole message */
419         PUT_CLID(strlen(msg));
420         sum = 0x80 + strlen(msg);
421         /* Put each character of message and update checksum */
422         for (x=0;x<strlen(msg); x++) {
423                 PUT_CLID(msg[x]);
424                 sum += msg[x];
425         }
426         /* Send 2's compliment of sum */
427         PUT_CLID(256 - (sum & 255));
428         /* Send 50 more ms of marks */
429         for (x=0;x<50;x++)
430                 PUT_CLID_MARKMS;
431         
432         return bytes;
433 }
434
435 void ast_shrink_phone_number(char *n)
436 {
437         int x,y=0;
438         for (x=0;n[x];x++)
439                 if (!strchr("( )-.", n[x]))
440                         n[y++] = n[x];
441         n[y] = '\0';
442 }
443
444 int ast_isphonenumber(char *n)
445 {
446         int x;
447         if (!n)
448                 return 0;
449         for (x=0;n[x];x++)
450                 if (!strchr("0123456789", n[x]))
451                         return 0;
452         return 1;
453 }
454
455 int ast_callerid_parse(char *instr, char **name, char **location)
456 {
457         char *ns, *ne;
458         char *ls, *le;
459         char tmp[256];
460         /* Try for "name" <location> format or 
461            name <location> format */
462         if ((ls = strchr(instr, '<')) && (le = strchr(ls, '>'))) {
463                 /* Found the location */
464                 *le = '\0';
465                 *ls = '\0';
466                 *location = ls + 1;
467                 if ((ns = strchr(instr, '\"')) && (ne = strchr(ns + 1, '\"'))) {
468                         /* Get name out of quotes */
469                         *ns = '\0';
470                         *ne = '\0';
471                         *name = ns + 1;
472                         return 0;
473                 } else {
474                         /* Just trim off any trailing spaces */
475                         *name = instr;
476                         while(strlen(instr) && (instr[strlen(instr) - 1] < 33))
477                                 instr[strlen(instr) - 1] = '\0';
478                         /* And leading spaces */
479                         while(**name && (**name < 33))
480                                 name++;
481                         return 0;
482                 }
483         } else {
484                 strncpy(tmp, instr, sizeof(tmp));
485                 ast_shrink_phone_number(tmp);
486                 if (!ast_isphonenumber(tmp)) {
487                         /* Assume it's just a location */
488                         *name = NULL;
489                         *location = instr;
490                 } else {
491                         /* Assume it's just a name */
492                         *name = instr;
493                         *location = NULL;
494                 }
495                 return 0;
496         }
497         return -1;
498 }
499
500 static int __ast_callerid_generate(unsigned char *buf, char *callerid, int callwaiting)
501 {
502         char tmp[256];
503         char *n, *l;
504         if (!callerid)
505                 return callerid_generate(buf, NULL, NULL, 0, callwaiting);
506         strncpy(tmp, callerid, sizeof(tmp));
507         if (ast_callerid_parse(tmp, &n, &l)) {
508                 ast_log(LOG_WARNING, "Unable to parse '%s' into CallerID name & number\n", callerid);
509                 return callerid_generate(buf, NULL, NULL, 0, callwaiting);
510         }
511         if (l)
512                 ast_shrink_phone_number(l);
513         if (!ast_isphonenumber(l))
514                 return callerid_generate(buf, NULL, n, 0, callwaiting);
515         return callerid_generate(buf, l, n, 0, callwaiting);
516 }
517
518 int ast_callerid_generate(unsigned char *buf, char *callerid)
519 {
520         return __ast_callerid_generate(buf, callerid, 0);
521 }
522
523 int ast_callerid_callwaiting_generate(unsigned char *buf, char *callerid)
524 {
525         return __ast_callerid_generate(buf, callerid, 1);
526 }