another round of version tag updates, along with 'show version files' pattern filtering
[asterisk/asterisk.git] / channels / chan_modem_bestdata.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * BestData 56SX-92 Voice Modem Driver (Conexant)
5  * 
6  * Copyright (C) 1999, Mark Spencer and 2001 Jim Dixon
7  *
8  * Mark Spencer <markster@linux-support.net>
9  * Jim Dixon <jim@lambdatel.com>
10  *
11  * This program is free software, distributed under the terms of
12  * the GNU General Public License
13  */
14
15 #include <stdio.h>
16
17 #include <string.h>
18 #include <stdlib.h>
19 #include <errno.h>
20 #include <unistd.h>
21
22 #include "asterisk.h"
23
24 ASTERISK_FILE_VERSION("$Revision$")
25
26 #include "asterisk/lock.h"
27 #include "asterisk/vmodem.h"
28 #include "asterisk/module.h"
29 #include "asterisk/frame.h"
30 #include "asterisk/logger.h"
31 #include "asterisk/options.h"
32
33 #define STATE_COMMAND   0
34 #define STATE_VOICE     1
35 #define STATE_VOICEPLAY 2
36
37 #define VRA "40"                        /* Number of 100ms of non-ring after a ring cadence after which we consider the lien to be answered */
38 #define VRN "25"                        /* Number of 100ms of non-ring with no cadence after which we assume an answer */
39
40 #define RINGT   7000
41
42 static char *breakcmd = "\020!";
43
44 static char *desc = "BestData (Conexant V.90 Chipset) VoiceModem Driver";
45
46 static int usecnt;
47 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
48
49 static char *bestdata_idents[] = {
50         /* Identify BestData Modem */
51         "ACF3_V1.010-V90_P21_FSH",
52         NULL
53 };
54
55 static int bestdata_break(struct ast_modem_pvt *p);
56
57 static int bestdata_startrec(struct ast_modem_pvt *p)
58 {
59         if (p->ministate != STATE_COMMAND) bestdata_break(p);
60         if (ast_modem_send(p, "AT+VRX", 0) ||
61              ast_modem_expect(p, "CONNECT", 5)) {
62                 ast_log(LOG_WARNING, "Unable to start recording\n");
63                 return -1;
64         }
65         p->ministate = STATE_VOICE;
66         return 0;
67 }
68
69 static int bestdata_startplay(struct ast_modem_pvt *p)
70 {
71         if (p->ministate != STATE_COMMAND) bestdata_break(p);
72         if (ast_modem_send(p, "AT+VTX", 0) ||
73              ast_modem_expect(p, "CONNECT", 5)) {
74                 ast_log(LOG_WARNING, "Unable to start recording\n");
75                 return -1;
76         }
77         p->ministate = STATE_VOICEPLAY;
78         return 0;
79 }
80
81 static int bestdata_break(struct ast_modem_pvt *p)
82 {
83         if (ast_modem_send(p, breakcmd, 2)) {
84                 ast_log(LOG_WARNING, "Failed to break\n");
85                 return -1;
86         }
87         p->ministate = STATE_COMMAND;
88         usleep(10000);
89         /* Read any outstanding junk */
90         while(!ast_modem_read_response(p, 1));
91         if (ast_modem_send(p, "AT", 0)) {
92                 /* Modem might be stuck in some weird mode, try to get it out */
93                 ast_modem_send(p, "+++", 3);
94                 if (ast_modem_expect(p, "OK", 10)) {
95                         ast_log(LOG_WARNING, "Modem is not responding\n");
96                         return -1;
97                 }
98                 if (ast_modem_send(p, "AT", 0)) {
99                         ast_log(LOG_WARNING, "Modem is not responding\n");
100                         return -1;
101                 }
102         }
103         if (ast_modem_expect(p, "OK", 5)) {
104                 ast_log(LOG_WARNING, "Modem did not respond properly\n");
105                 return -1;
106         }
107         return 0;
108 }
109
110 static int bestdata_init(struct ast_modem_pvt *p)
111 {
112         if (option_debug)
113                 ast_log(LOG_DEBUG, "bestdata_init()\n");
114         if (bestdata_break(p))
115                 return -1;
116         /* Force into command mode */
117         p->ministate = STATE_COMMAND;
118         if (ast_modem_send(p, "AT+FCLASS=8", 0) ||
119              ast_modem_expect(p, "OK", 5)) {
120                 ast_log(LOG_WARNING, "Unable to set to voice mode\n");
121                 return -1;
122         }
123         if (ast_modem_send(p, "AT+VSM=1,8000,0,0", 0) ||
124              ast_modem_expect(p, "OK", 5)) {
125                 ast_log(LOG_WARNING, "Unable to set to 8000 Hz sampling\n");
126                 return -1;
127         }
128         if (ast_modem_send(p, "AT+VLS=0", 0) ||
129              ast_modem_expect(p, "OK", 5)) {
130                 ast_log(LOG_WARNING, "Unable to set to telco interface\n");
131                 return -1;
132         }
133         if (ast_modem_send(p, "AT+VRA=" VRA, 0) ||
134              ast_modem_expect(p, "OK", 5)) {
135                 ast_log(LOG_WARNING, "Unable to set to 'ringback goes away' timer\n");
136                 return -1;
137         }
138         if (ast_modem_send(p, "AT+VRN=" VRN, 0) ||
139              ast_modem_expect(p, "OK", 5)) {
140                 ast_log(LOG_WARNING, "Unable to set to 'ringback never came timer'\n");
141                 return -1;
142         }
143         if (ast_modem_send(p, "AT+VTD=63", 0) ||
144              ast_modem_expect(p, "OK", 5)) {
145                 ast_log(LOG_WARNING, "Unable to set to tone detection\n");
146                 return -1;
147         }
148         if (ast_modem_send(p, "AT+VCID=1", 0) ||
149              ast_modem_expect(p, "OK", 5)) {
150                 ast_log(LOG_WARNING, "Unable to enable Caller*ID\n");
151                 return -1;
152         }
153         return 0;
154 }
155
156 static struct ast_frame *bestdata_handle_escape(struct ast_modem_pvt *p, char esc)
157 {
158         char name[30]="",nmbr[30]="";
159         time_t  now;
160
161         /* Handle escaped characters -- but sometimes we call it directly as 
162            a quick way to cause known responses */
163         p->fr.frametype = AST_FRAME_NULL;
164         p->fr.subclass = 0;
165         p->fr.data = NULL;
166         p->fr.datalen = 0;
167         p->fr.samples = 0;
168         p->fr.offset = 0;
169         p->fr.mallocd = 0;
170         p->fr.delivery.tv_sec = 0;
171         p->fr.delivery.tv_usec = 0;
172         if (esc)
173                 ast_log(LOG_DEBUG, "Escaped character '%c'\n", esc);
174         
175         switch(esc) {
176         case 'R': /* Pseudo ring */
177                 time(&now);
178                 if (now > (p->lastring + (RINGT / 1000)))
179                    { /* if stale, treat as new */
180                         p->gotclid = 0;
181                    }
182                 if (p->gotclid)
183                    {
184                         p->fr.frametype = AST_FRAME_CONTROL;
185                         p->fr.subclass = AST_CONTROL_RING;
186                    }
187                 p->ringt = RINGT;
188                 time(&p->lastring);
189                 return &p->fr;
190         case 'X': /* Caller-ID Spill */
191                 if (p->gotclid) return &p->fr;
192                 name[0] = nmbr[0] = 0;
193                 for(;;)
194                    {
195                         char res[1000]="";
196
197                         if (ast_modem_read_response(p, 5)) break;
198                         strncpy(res, p->response, sizeof(res)-1);
199                         ast_modem_trim(res);
200                         if (!strncmp(res,"\020.",2)) break;
201                         if (!strncmp(res,"NAME",4)) strncpy(name,res + 7, sizeof(name) - 1);
202                         if (!strncmp(res,"NMBR",4)) strncpy(nmbr,res + 7, sizeof(nmbr) - 1);
203                    }
204                 p->gotclid = 1;
205                 if ((!strcmp(name,"O")) || (!strcmp(name,"P"))) name[0] = 0;
206                 if ((!strcmp(nmbr,"O")) || (!strcmp(nmbr,"P"))) nmbr[0] = 0;
207                 if (name[0])
208                         strncpy(p->cid_name, name, sizeof(p->cid_name) - 1);
209                 if (nmbr[0])
210                         strncpy(p->cid_num, nmbr, sizeof(p->cid_num) - 1);
211                 if (p->owner) {
212                         p->owner->cid.cid_num = strdup(p->cid_num);
213                         p->owner->cid.cid_name = strdup(p->cid_name);
214                 }
215                 return &p->fr;
216         case '@': /* response from "OK" in command mode */
217                 if (p->owner)
218                         ast_setstate(p->owner, AST_STATE_UP);
219                 if (bestdata_startrec(p)) return NULL;
220                 p->fr.frametype = AST_FRAME_CONTROL;
221                 p->fr.subclass = AST_CONTROL_RING;
222                 return &p->fr;
223         case 'b': /* Busy signal */
224                 p->fr.frametype = AST_FRAME_CONTROL;
225                 p->fr.subclass = AST_CONTROL_BUSY;
226                 return &p->fr;
227         case 'o': /* Overrun */
228                 ast_log(LOG_WARNING, "Overflow on modem, flushing buffers\n");
229                 if (ast_modem_send(p, "\0x10E", 2)) 
230                         ast_log(LOG_WARNING, "Unable to flush buffers\n");
231                 return &p->fr;  
232         case '0':  /* All the DTMF characters */
233         case '1':
234         case '2':
235         case '3':
236         case '4':
237         case '5':
238         case '6':
239         case '7':
240         case '8':
241         case '9':
242         case '*':
243         case '#':
244         case 'A':
245         case 'B':
246         case 'C':
247         case 'D':
248                 p->dtmfrx = esc;  /* save this for when its done */
249                 return &p->fr;  
250         case '/': /* Start of DTMF tone shielding */
251                 p->dtmfrx = ' ';
252                 return &p->fr;  
253         case '~': /* DTMF transition to off */
254                 if (p->dtmfrx > ' ')
255                    {
256                         p->fr.frametype = AST_FRAME_DTMF;
257                         p->fr.subclass = p->dtmfrx;
258                    }
259                 p->dtmfrx = 0;
260                 return &p->fr;  
261         case 'u': /* Underrun */
262                 ast_log(LOG_WARNING, "Data underrun\n");
263                 /* Fall Through */
264         case CHAR_ETX: /* End Transmission */
265         case 'd': /* Dialtone */
266         case 'c': /* Calling Tone */
267         case 'e': /* European version */
268         case 'a': /* Answer Tone */
269         case 'f': /* Bell Answer Tone */
270         case 'T': /* Timing mark */
271         case 't': /* Handset off hook */
272         case 'h': /* Handset hungup */
273         case 0: /* Pseudo signal */
274                 /* Ignore */
275                 return &p->fr;  
276         default:
277                 ast_log(LOG_DEBUG, "Unknown Escaped character '%c' (%d)\n", esc, esc);
278         }
279         return &p->fr;
280 }
281
282 static struct ast_frame *bestdata_read(struct ast_modem_pvt *p)
283 {
284         char result[256];
285         short *b;
286         struct ast_frame *f=NULL;
287         int res;
288         int x;
289
290         if (p->ministate == STATE_COMMAND) {
291                 /* Read the first two bytes, first, in case it's a control message */
292                 fread(result, 1, 2, p->f);
293                 if (result[0] == CHAR_DLE) {
294                         return bestdata_handle_escape(p, result[1]);
295                 } else {
296                         if (p->ringt) /* if ring timeout specified */
297                            {
298                                 x = fileno(p->f);
299                                 res = ast_waitfor_n_fd(&x, 1, &p->ringt, NULL);
300                                 if (res < 0) {
301                                         return NULL;
302                                 }
303                            }
304                         if ((result[0] == '\n') || (result[0] == '\r'))
305                                 return bestdata_handle_escape(p, 0);
306                         /* Read the rest of the line */
307                         fgets(result + 2, sizeof(result) - 2, p->f);
308                         ast_modem_trim(result);
309                         if (!strcasecmp(result, "OK")) {
310                                 /* If we're in immediate mode, reply now */
311                                 if (p->mode == MODEM_MODE_IMMEDIATE)
312                                         return bestdata_handle_escape(p, '@');
313                         } else
314                         if (!strcasecmp(result, "BUSY")) {
315                                 /* Same as a busy signal */
316                                 return bestdata_handle_escape(p, 'b');
317                         } else
318                         if (!strcasecmp(result, "RING")) {
319                                 return bestdata_handle_escape(p, 'R');
320                         } else
321                         if (!strcasecmp(result, "NO DIALTONE")) {
322                                 /* There's no dialtone, so the line isn't working */
323                                 ast_log(LOG_WARNING, "Device '%s' lacking dialtone\n", p->dev);
324                                 return NULL;
325                         }
326                         ast_log(LOG_DEBUG, "Modem said '%s'\n", result);
327                         return bestdata_handle_escape(p, 0);
328                 }
329         } else {
330                   /* if playing, start recording instead */
331                 if (p->ministate == STATE_VOICEPLAY)
332                    {
333                         if (bestdata_startrec(p)) return NULL;
334                    }
335                 /* We have to be more efficient in voice mode */
336                 b = (short *)(p->obuf + p->obuflen);
337                 while (p->obuflen/2 < 240) {
338                         /* Read ahead the full amount */
339                         res = fread(result, 1, 240 - p->obuflen/2, p->f);
340                         if (res < 1) {
341                                 /* If there's nothing there, just continue on */
342                                 if (errno == EAGAIN)
343                                         return bestdata_handle_escape(p, 0);
344                                 ast_log(LOG_WARNING, "Read failed: %s\n", strerror(errno));
345                         }
346                         for (x=0;x<res;x++) {
347                                 /* Process all the bytes that we've read */
348                                 if (result[x] == CHAR_DLE) {
349                                         /* We assume there is no more than one signal frame among our
350                                            data.  */
351                                         if (f) ast_log(LOG_WARNING, "Warning: Dropped a signal frame\n");
352                                           /* if not a DLE in the data */
353                                         if (result[++x] != CHAR_DLE)
354                                            {
355                                                 /* If bestdata_handle_escape says NULL, say it now, doesn't matter
356                                                    what else is there, the connection is dead. */
357                                                 f = bestdata_handle_escape(p, result[x]);
358                                                 if (p->dtmfrx) continue;
359                                                 return(f);
360                                            }
361                                 }
362                                 /* Generate a 16-bit signed linear value from our 
363                                    unsigned 8-bit value */
364                                 *(b++) = (((short)result[x]) - 127) * 0xff;
365                                 p->obuflen += 2;
366                         }
367                         if (f) break;
368                 }
369                 /* If we have a control frame, return it now */
370                 if (f) return f;
371                 /* If we get here, we have a complete voice frame */
372                 p->fr.frametype = AST_FRAME_VOICE;
373                 p->fr.subclass = AST_FORMAT_SLINEAR;
374                 p->fr.samples = 240;
375                 p->fr.data = p->obuf;
376                 p->fr.datalen = p->obuflen;
377                 p->fr.mallocd = 0;
378                 p->fr.delivery.tv_sec = 0;
379                 p->fr.delivery.tv_usec = 0;
380                 p->fr.offset = AST_FRIENDLY_OFFSET;
381                 p->fr.src = __FUNCTION__;
382                 if (option_debug)
383                         ast_log(LOG_DEBUG, "bestdata_read(voice frame)\n");
384                 p->obuflen = 0;
385                 return &p->fr;
386         }
387         return NULL;
388 }
389
390 static int bestdata_write(struct ast_modem_pvt *p, struct ast_frame *f)
391 {
392 unsigned char   c,buf[32768]; /* I hope we dont have frames larger then 16K */
393 int     i,j;
394 short   *sp;
395 unsigned long u;
396 #define DLE     16
397
398         if (p->owner && (p->owner->_state == AST_STATE_UP) && 
399                 (p->ministate != STATE_VOICEPLAY) && bestdata_startplay(p)) return -1;
400         sp = (short *) f->data;
401           /* stick DLE's in ahead of anything else */
402         for(i = 0,j = 0; i < f->datalen / 2; i++)
403            {
404                 *sp *= 3;
405                 u = *sp++ + 32768;
406                 c = u >> 8;
407                 if (c == DLE) buf[j++] = DLE;
408                 buf[j++] = c;
409            }
410         do i = fwrite(buf,1,j,p->f);
411         while ((i == -1) && (errno == EWOULDBLOCK));
412         if (i != j)
413            {
414                 ast_log(LOG_WARNING,"modem short write!!\n");
415                 return -1;
416            }
417         fflush(p->f);
418         if (option_debug)
419                 ast_log(LOG_DEBUG, "bestdata_write()\n");
420         return 0;
421 }
422
423 static char *bestdata_identify(struct ast_modem_pvt *p)
424 {
425         char identity[256];
426         char mfr[80];
427         char mdl[80];
428         char rev[80];
429         ast_modem_send(p, "AT+FMM", 0);
430         ast_modem_read_response(p, 5);
431         strncpy(mdl, p->response, sizeof(mdl)-1);
432         ast_modem_trim(mdl);
433         ast_modem_expect(p, "OK", 5);
434         ast_modem_send(p, "AT+FMI", 0);
435         ast_modem_read_response(p, 5);
436         strncpy(mfr, p->response, sizeof(mfr)-1);
437         ast_modem_trim(mfr);
438         ast_modem_expect(p, "OK", 5);
439         ast_modem_send(p, "AT+FMR", 0);
440         ast_modem_read_response(p, 5);
441         strncpy(rev, p->response, sizeof(rev)-1);
442         ast_modem_trim(rev);
443         ast_modem_expect(p, "OK", 5);
444         snprintf(identity, sizeof(identity), "%s Model %s Revision %s", mfr, mdl, rev);
445         return strdup(identity);
446 }
447
448 static void bestdata_incusecnt(void)
449 {
450         ast_mutex_lock(&usecnt_lock);
451         usecnt++;
452         ast_mutex_unlock(&usecnt_lock);
453         ast_update_use_count();
454 }
455
456 static void bestdata_decusecnt(void)
457 {
458         ast_mutex_lock(&usecnt_lock);
459         usecnt++;
460         ast_mutex_unlock(&usecnt_lock);
461         ast_update_use_count();
462 }
463
464 static int bestdata_answer(struct ast_modem_pvt *p)
465 {
466         p->ringt = 0;
467         p->lastring = 0;
468         if (ast_modem_send(p, "AT+VLS=1", 0) ||
469              ast_modem_expect(p, "OK", 10)) {
470                 ast_log(LOG_WARNING, "Unable to answer: %s", p->response);
471                 return -1;
472         }
473         return 0;
474 }
475
476 static int bestdata_dialdigit(struct ast_modem_pvt *p, char digit)
477 {
478         char cmd[80];
479
480         if (p->ministate != STATE_COMMAND) bestdata_break(p);
481         snprintf(cmd, sizeof(cmd), "AT+VTS=%c", digit);
482         if (ast_modem_send(p, cmd, 0) ||
483              ast_modem_expect(p, "OK", 10)) {
484                 ast_log(LOG_WARNING, "Unable to answer: %s", p->response);
485                 return -1;
486         }
487         return 0;
488 }
489
490 static int bestdata_dial(struct ast_modem_pvt *p, char *stuff)
491 {
492         char cmd[800] = "",a[20]="";
493         int i,j;
494
495         if (p->ministate != STATE_COMMAND)
496            {
497                 bestdata_break(p);
498                 strncpy(cmd, "AT+VTS=", sizeof(cmd) - 1);
499                 j = strlen(cmd);
500                 for(i = 0; stuff[i]; i++)
501                    {
502                         switch(stuff[i])
503                            {
504                             case '!' :
505                                 a[0] = stuff[i];
506                                 a[1] = 0;
507                                 break;
508                             case ',':
509                                 strncpy(a, "[,,100]", sizeof(a) - 1);
510                                 break;
511                             default:
512                                 snprintf(a, sizeof(a), "{%c,7}", stuff[i]);
513                            }
514                         if (stuff[i + 1]) strncat(a, ",", sizeof(a) - strlen(a) - 1);
515                         strncpy(cmd + j, a, sizeof(cmd) - j - 1);
516                         j += strlen(a);
517                    }
518            }
519         else
520            {
521                 snprintf(cmd, sizeof(cmd), "ATD%c %s", p->dialtype,stuff);
522            }
523         if (ast_modem_send(p, cmd, 0)) {
524                 ast_log(LOG_WARNING, "Unable to dial\n");
525                 return -1;
526         }
527         return 0;
528 }
529
530 static int bestdata_hangup(struct ast_modem_pvt *p)
531 {
532         if (bestdata_break(p))
533                 return -1;
534         /* Hangup by switching to data, then back to voice */
535         if (ast_modem_send(p, "ATH", 0) ||
536              ast_modem_expect(p, "OK", 8)) {
537                 ast_log(LOG_WARNING, "Unable to set to data mode\n");
538                 return -1;
539         }
540         if (ast_modem_send(p, "AT+FCLASS=8", 0) ||
541              ast_modem_expect(p, "OK", 5)) {
542                 ast_log(LOG_WARNING, "Unable to set to voice mode\n");
543                 return -1;
544         }
545         p->gotclid = 0;
546         p->ringt = 0;
547         p->lastring = 0;
548         p->dtmfrx = 0;
549         return 0;
550 }
551
552 static struct ast_modem_driver bestdata_driver =
553 {
554         "BestData",
555         bestdata_idents,
556         AST_FORMAT_SLINEAR,
557         0,              /* Not full duplex */
558         bestdata_incusecnt,     /* incusecnt */
559         bestdata_decusecnt,     /* decusecnt */
560         bestdata_identify,      /* identify */
561         bestdata_init,  /* init */
562         NULL,   /* setdev */
563         bestdata_read,
564         bestdata_write,
565         bestdata_dial,  /* dial */
566         bestdata_answer,        /* answer */
567         bestdata_hangup,        /* hangup */
568         bestdata_startrec,      /* start record */
569         NULL,   /* stop record */
570         bestdata_startplay,     /* start playback */
571         NULL,   /* stop playback */
572         NULL,   /* set silence supression */
573         bestdata_dialdigit,     /* dialdigit */
574 };
575
576
577
578 int usecount(void)
579 {
580         int res;
581         ast_mutex_lock(&usecnt_lock);
582         res = usecnt;
583         ast_mutex_unlock(&usecnt_lock);
584         return res;
585 }
586
587 int load_module(void)
588 {
589         return ast_register_modem_driver(&bestdata_driver);
590 }
591
592 int unload_module(void)
593 {
594         return ast_unregister_modem_driver(&bestdata_driver);
595 }
596
597 char *description()
598 {
599         return desc;
600 }
601
602 char *key()
603 {
604         return ASTERISK_GPL_KEY;
605 }