Merged revisions 7799-7800 via svnmerge from
[asterisk/asterisk.git] / channels / chan_modem.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief A/Open ITU-56/2 Voice Modem Driver (Rockwell, IS-101, and others)
22  *
23  * \author Mark Spencer <markster@digium.com>
24  * 
25  * \ingroup channel_drivers
26  */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <ctype.h>
31 #include <string.h>
32 #include <sys/time.h>
33 #include <errno.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #include <sys/socket.h>
37 #include <fcntl.h>
38 #include <sys/ioctl.h>
39 #include <sys/termios.h>
40 #include <sys/signal.h>
41
42 #include "asterisk.h"
43
44 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
45
46 #include "asterisk/lock.h"
47 #include "asterisk/channel.h"
48 #include "asterisk/config.h"
49 #include "asterisk/logger.h"
50 #include "asterisk/module.h"
51 #include "asterisk/pbx.h"
52 #include "asterisk/options.h"
53 #include "asterisk/vmodem.h"
54 #include "asterisk/utils.h"
55
56 /* Up to 10 seconds for an echo to arrive */
57 #define ECHO_TIMEOUT 10
58
59 static const char desc[] = "Generic Voice Modem Driver";
60 static const char tdesc[] = "Generic Voice Modem Channel Driver";
61 static const char type[] = "Modem";
62 static const char config[] = "modem.conf";
63 static char dialtype = 'T';
64 static int gmode = MODEM_MODE_IMMEDIATE;
65
66 /* Default modem type */
67 static char mtype[80] = "autodetect";
68 /* Default context for incoming calls */
69 static char context[AST_MAX_EXTENSION]= "default";
70
71 /* Default language */
72 static char language[MAX_LANGUAGE] = "";
73
74 /* Initialization String */
75 static char initstr[AST_MAX_INIT_STR] = "ATE0Q0";
76
77 /* Default MSN */
78 static char msn[AST_MAX_EXTENSION]="";
79
80 /* Default Listen */
81 static char incomingmsn[AST_MAX_EXTENSION]="";
82
83 /* Default DTMF-detection mode (i4l/asterisk) */
84 static int dtmfmode = MODEM_DTMF_AST;
85 /* Default DTMF-generation mode (i4l (outband) / asterisk (inband) */
86 static int dtmfmodegen = MODEM_DTMF_AST;
87
88 struct ast_dsp *dsp = NULL;
89
90 /* Default valid outgoing MSN */
91 static char outgoingmsn[AST_MAX_EXTENSION]="";
92
93 /* Default group */
94 static ast_group_t cur_group = 0;
95
96 static int usecnt =0;
97
98 static int baudrate = 115200;
99
100 static int stripmsd = 0;
101
102 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
103
104 /* Protect the interface list (of ast_modem_pvt's) */
105 AST_MUTEX_DEFINE_STATIC(iflock);
106
107 /* Protect the monitoring thread, so only one process can kill or start it, and not
108    when it's doing something critical. */
109 AST_MUTEX_DEFINE_STATIC(monlock);
110
111 /* This is the thread for the monitor which checks for input on the channels
112    which are not currently in use.  */
113 static pthread_t monitor_thread = AST_PTHREADT_NULL;
114
115 static int restart_monitor(void);
116
117 int dep_warning = 0;
118
119 static struct ast_channel *modem_request(const char *type, int format, void *data, int *cause);
120 static int modem_digit(struct ast_channel *ast, char digit);
121 static int modem_call(struct ast_channel *ast, char *idest, int timeout);
122 static int modem_hangup(struct ast_channel *ast);
123 static int modem_answer(struct ast_channel *ast);
124 static struct ast_frame *modem_read(struct ast_channel *);
125 static int modem_write(struct ast_channel *ast, struct ast_frame *frame);
126 static int modem_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
127
128 static const struct ast_channel_tech modem_tech = {
129         .type = type,
130         .description = tdesc,
131         .capabilities = AST_FORMAT_SLINEAR,
132         .requester = modem_request,
133         .send_digit = modem_digit,
134         .call = modem_call,
135         .hangup = modem_hangup,
136         .answer = modem_answer,
137         .read = modem_read,
138         .write = modem_write,
139         .fixup = modem_fixup,
140 };
141
142 /* The private structures of the Phone Jack channels are linked for
143    selecting outgoing channels */
144    
145 static struct ast_modem_pvt  *iflist = NULL;
146
147 static int modem_digit(struct ast_channel *ast, char digit)
148 {
149         struct ast_modem_pvt *p;
150         p = ast->tech_pvt;
151         if (p->mc->dialdigit)
152                 return p->mc->dialdigit(p, digit);
153         ast_log(LOG_DEBUG, "Channel %s lacks digit dialing\n", ast->name);
154         return -1;
155 }
156
157 static struct ast_modem_driver *drivers = NULL;
158
159 static struct ast_modem_driver *find_capability(char *ident)
160 {
161         struct ast_modem_driver *mc;
162         int x;
163         mc = drivers;
164         while(mc) {
165                 for (x=0;mc->idents[x];x++) {
166                         if (!strcmp(ident, mc->idents[x])) 
167                                 break;
168                 }
169                 if (mc->idents[x])
170                         break;
171                 mc = mc->next;
172         }
173         if (mc) {
174                 if (mc->incusecnt)
175                         mc->incusecnt();
176         }
177         return mc;
178 }
179
180 static struct ast_modem_driver *find_driver(char *drv)
181 {
182         struct ast_modem_driver *mc;
183         mc = drivers;
184         while(mc) {
185                 if (!strcasecmp(mc->name, drv)) 
186                         break;
187                 mc = mc->next;
188         }
189         if (mc) {
190                 if (mc->incusecnt)
191                         mc->incusecnt();
192         }
193         return mc;
194 }
195
196 int ast_register_modem_driver(struct ast_modem_driver *mc)
197 {
198         mc->next = drivers;
199         drivers = mc;
200         return 0;
201 }
202
203 int ast_unregister_modem_driver(struct ast_modem_driver *mc)
204 {
205         struct ast_modem_driver *last = NULL, *cur;
206         cur = drivers;
207         while(cur) {
208                 if (cur == mc) {
209                         if (last)
210                                 last->next = mc->next;
211                         else
212                                 drivers = mc->next;
213                         return 0;
214                 }
215                 cur = cur->next;
216         }
217         return -1;
218 }
219
220 static int modem_call(struct ast_channel *ast, char *idest, int timeout)
221 {
222         struct ast_modem_pvt *p;
223         int ms = timeout;
224         char rdest[80], *where, dstr[100] = "";
225         char *stringp=NULL;
226         strncpy(rdest, idest, sizeof(rdest)-1);
227         stringp=rdest;
228         strsep(&stringp, ":");
229         where = strsep(&stringp, ":");
230         if (!where) {
231                 ast_log(LOG_WARNING, "Destination %s requres a real destination (device:destination)\n", idest);
232                 return -1;
233         }
234         p = ast->tech_pvt;
235         strncpy(dstr, where + p->stripmsd, sizeof(dstr) - 1);
236         /* if not a transfer or just sending tones, must be in correct state */
237         if (strcasecmp(rdest, "transfer") && strcasecmp(rdest,"sendtones")) {
238                 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
239                         ast_log(LOG_WARNING, "modem_call called on %s, neither down nor reserved\n", ast->name);
240                         return -1;
241                 }
242         } 
243         if (!strcasecmp(rdest,"transfer")) /* if a transfer, put in transfer stuff */
244         {
245                 snprintf(dstr, sizeof(dstr), "!,%s", where + p->stripmsd);
246         }
247         if (!strcasecmp(where, "handset")) {
248                 if (p->mc->setdev)
249                         if (p->mc->setdev(p, MODEM_DEV_HANDSET))
250                                 return -1;
251                 /* Should be immediately up */
252                 ast_setstate(ast, AST_STATE_UP);
253         } else {
254                 if (p->mc->setdev)
255                         if (p->mc->setdev(p, MODEM_DEV_TELCO_SPK))
256                                 return -1;
257                 if (p->mc->dial)
258                         p->mc->dial(p, dstr);
259                 ast_setstate(ast, AST_STATE_DIALING);
260                 while((ast->_state != AST_STATE_UP) && (ms > 0)) {
261                         ms = ast_waitfor(ast, ms);
262                         /* Just read packets and watch what happens */
263                         if (ms > 0) {
264                                 if (!modem_read(ast))
265                                         return -1;
266                         }
267                 }
268                 if (ms < 0)     
269                         return -1;
270         }
271         return 0;
272 }
273
274 int ast_modem_send(struct ast_modem_pvt *p, char *cmd, int len)
275 {
276         int i;
277         usleep(5000);
278         if (!len) {
279                 for(i = 0; cmd[i];)
280                    {
281                         if (fwrite(cmd + i,1,1,p->f) != 1)
282                            {
283                                 if (errno == EWOULDBLOCK) continue;
284                                 return -1;
285                            }
286                         i++;
287                    }
288                 tcdrain(fileno(p->f)); 
289                 fprintf(p->f,"\r\n");
290                 return 0;
291         } else {
292                 if (fwrite(cmd, 1, len, p->f) < len)
293                         return -1;
294                 return 0;
295         }
296 }
297
298 int ast_modem_read_response(struct ast_modem_pvt *p, int timeout)
299 {
300         int res = -1,c,i;
301         timeout *= 1000;
302         p->response[0] = 0;
303         c = i = 0;
304         do {
305                 res = ast_waitfor_n_fd(&p->fd, 1, &timeout, NULL);
306                 if (res < 0) {
307                         strncpy(p->response, "(No Response)", sizeof(p->response)-1);
308                         return -1;
309                 }
310                   /* get no more then buffer length */
311                 while(i < sizeof(p->response) - 1)
312                 {
313                         c = fgetc(p->f);  /* get a char */
314                         if (c < 1) /* if error */
315                         {
316                                   /* if nothing in buffer, go back into timeout stuff */
317                                 if (errno == EWOULDBLOCK) break;
318                                 /* return as error */
319                                 strncpy(p->response, "(No Response)", sizeof(p->response)-1);
320                                 return -1;
321                         }
322                           /* save char */
323                         p->response[i++] = c;
324                         p->response[i] = 0;                     
325                           /* if end of input */
326                         if (c == '\n') break;
327                 }
328                 if (c >= 0)  /* if input terminated normally */
329                 {
330                           /* ignore just CR/LF */
331                         if (!strcmp(p->response,"\r\n"))
332                         {
333                                   /* reset input buffer stuff */
334                                 i = 0; 
335                                 p->response[0] = 0;
336                         }
337                         else /* otherwise return with info in buffer */
338                         {
339                                 return 0;
340                         }
341                 }
342         } while(timeout > 0);
343         strncpy(p->response, "(No Response)", sizeof(p->response)-1);
344         return -1;
345 }
346
347 int ast_modem_expect(struct ast_modem_pvt *p, char *result, int timeout)
348 {
349         int res = -1;
350         timeout *= 1000;
351         strncpy(p->response, "(No Response)", sizeof(p->response)-1);
352         do {
353                 res = ast_waitfor_n_fd(&p->fd, 1, &timeout, NULL);
354                 if (res < 0) {
355                         return -1;
356                 }
357                 /* Read a response */
358                 fgets(p->response, sizeof(p->response), p->f);
359 #if     0
360                 fprintf(stderr, "Modem said: %s", p->response);
361 #endif
362                 if (!strncasecmp(p->response, result, strlen(result))) 
363                         return 0;
364         } while(timeout > 0);
365         return -1;
366 }
367
368 void ast_modem_trim(char *s)
369 {
370         int x;
371         x = strlen(s) - 1;
372         while(x >= 0) {
373                 if ((s[x] != '\r') && (s[x] != '\n') && (s[x] != ' '))
374                         break;
375                 s[x] = '\0';
376                 x--;
377         }
378 }
379
380 static int modem_setup(struct ast_modem_pvt *p, int baudrate)
381 {
382
383         /* Make sure there's a modem there and that it's in a reasonable 
384            mode.  Set the baud rate, etc.  */
385         char identity[256];
386         char *ident = NULL;
387         char etx[2] = { 0x10, '!' }; 
388         if (option_debug)
389                 ast_log(LOG_DEBUG, "Setting up modem %s\n", p->dev);
390         if (ast_modem_send(p, etx, 2)) {
391                 ast_log(LOG_WARNING, "Failed to send ETX?\n");
392                 return -1;
393         }
394         if (ast_modem_send(p, "\r\n", 2)) {
395                 ast_log(LOG_WARNING, "Failed to send enter?\n");
396                 return -1;
397         }
398         usleep(10000);
399         /* Read any outstanding stuff */
400         while(!ast_modem_read_response(p, 0));
401         if (ast_modem_send(p, "ATZ", 0)) {
402                 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev);
403                 return -1;
404         }
405         if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) {
406                 ast_log(LOG_WARNING, "Modem reset failed: %s\n", p->response);
407                 return -1;
408         }
409         if (ast_modem_send(p, p->initstr, 0)) {
410                 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev);
411                 return -1;
412         }
413         if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) {
414                 ast_log(LOG_WARNING, "Modem initialization failed: %s\n", p->response);
415                 return -1;
416         }
417         if (ast_modem_send(p, "ATI3", 0)) {
418                 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev);
419                 return -1;
420         }
421         if (ast_modem_read_response(p, ECHO_TIMEOUT)) {
422                 ast_log(LOG_WARNING, "Modem did not provide identification\n");
423                 return -1;
424         }
425         strncpy(identity, p->response, sizeof(identity)-1);
426         ast_modem_trim(identity);
427         if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) {
428                 ast_log(LOG_WARNING, "Modem did not provide identification\n");
429                 return -1;
430         }
431         if (!strcasecmp(mtype, "autodetect")) {
432                 p->mc = find_capability(identity);
433                 if (!p->mc) {
434                         ast_log(LOG_WARNING, "Unable to autodetect modem.  You'll need to specify a driver in modem.conf.  Please report modem identification (%s) and which driver works to markster@linux-support.net.\n", identity); 
435                         return -1;
436                 }
437         } else {
438                 p->mc = find_driver(mtype);
439                 if (!p->mc) {
440                         ast_log(LOG_WARNING, "No driver for modem type '%s'\n", mtype);
441                         return -1;
442                 }
443         }
444         if (p->mc->init) {
445                 if (p->mc->init(p)) {
446                         ast_log(LOG_WARNING, "Modem Initialization Failed on '%s', driver %s.\n", p->dev, p->mc->name);
447                         p->mc->decusecnt();
448                         return -1;
449                 }
450         }                       
451         if (option_verbose > 2) {
452                 ast_verbose(VERBOSE_PREFIX_3 "Configured modem %s with driver %s (%s)\n", p->dev, p->mc->name, p->mc->identify ? (ident = p->mc->identify(p)) : "No identification");
453         }
454         if (ident)
455                 free(ident);
456         return 0;
457 }
458
459 static int modem_hangup(struct ast_channel *ast)
460 {
461         struct ast_modem_pvt *p;
462         if (option_debug)
463                 ast_log(LOG_DEBUG, "modem_hangup(%s)\n", ast->name);
464         p = ast->tech_pvt;
465         /* Hang up */
466         if (p->mc->hangup)
467                 p->mc->hangup(p);
468         /* Re-initialize */
469         if (p->mc->init)
470                 p->mc->init(p);
471         ast_setstate(ast, AST_STATE_DOWN);
472         memset(p->cid_num, 0, sizeof(p->cid_num));
473         memset(p->cid_name, 0, sizeof(p->cid_name));
474         memset(p->dnid, 0, sizeof(p->dnid));
475         ((struct ast_modem_pvt *)(ast->tech_pvt))->owner = NULL;
476         ast_mutex_lock(&usecnt_lock);
477         usecnt--;
478         if (usecnt < 0) 
479                 ast_log(LOG_WARNING, "Usecnt < 0???\n");
480         ast_mutex_unlock(&usecnt_lock);
481         ast_update_use_count();
482         if (option_verbose > 2) 
483                 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
484         ast->tech_pvt = NULL;
485         ast_setstate(ast, AST_STATE_DOWN);
486         restart_monitor();
487         return 0;
488 }
489
490 static int modem_answer(struct ast_channel *ast)
491 {
492         struct ast_modem_pvt *p;
493         int res=0;
494         if (option_debug)
495                 ast_log(LOG_DEBUG, "modem_answer(%s)\n", ast->name);
496         p = ast->tech_pvt;
497         if (p->mc->answer) {
498                 res = p->mc->answer(p);
499         }
500         if (!res) {
501                 ast->rings = 0;
502                 ast_setstate(ast, AST_STATE_UP);
503         }
504         return res;
505 }
506
507 #if     0
508 static char modem_2digit(char c)
509 {
510         if (c == 12)
511                 return '#';
512         else if (c == 11)
513                 return '*';
514         else if ((c < 10) && (c >= 0))
515                 return '0' + c - 1;
516         else
517                 return '?';
518 }
519 #endif
520 static struct ast_frame *modem_read(struct ast_channel *ast)
521 {
522         struct ast_modem_pvt *p = ast->tech_pvt;
523         struct ast_frame *fr=NULL;
524         if (p->mc->read)
525                 fr = p->mc->read(p);
526         return fr;
527 }
528
529 static int modem_write(struct ast_channel *ast, struct ast_frame *frame)
530 {
531         int res=0;
532         long flags;
533         struct ast_modem_pvt *p = ast->tech_pvt;
534
535         /* Modems tend to get upset when they receive data whilst in
536          * command mode. This makes esp. dial commands short lived.
537          *     Pauline Middelink - 2002-09-24 */
538         if (ast->_state != AST_STATE_UP)
539                 return 0;
540
541         /* Temporarily make non-blocking */
542         flags = fcntl(ast->fds[0], F_GETFL);
543         fcntl(ast->fds[0], F_SETFL, flags | O_NONBLOCK);
544
545         if (p->mc->write)
546                 res = p->mc->write(p, frame);
547
548         /* Block again */
549         fcntl(ast->fds[0], F_SETFL, flags);
550         return res;
551 }
552
553 static int modem_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
554 {
555         struct ast_modem_pvt *p = newchan->tech_pvt;
556 ast_log(LOG_WARNING, "fixup called\n");
557         if (p->owner!=oldchan) {
558             ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n",oldchan,p->owner);
559             return -1;
560         }
561         p->owner = newchan;
562         return 0; 
563 }
564
565 struct ast_channel *ast_modem_new(struct ast_modem_pvt *i, int state)
566 {
567         struct ast_channel *tmp;
568         tmp = ast_channel_alloc(1);
569         if (tmp) {
570                 tmp->tech = &modem_tech;
571                 snprintf(tmp->name, sizeof(tmp->name), "Modem[%s]/%s", i->mc->name, i->dev + 5);
572                 tmp->type = type;
573                 tmp->fds[0] = i->fd;
574                 tmp->nativeformats = i->mc->formats;
575                 ast_setstate(tmp, state);
576                 if (state == AST_STATE_RING)
577                         tmp->rings = 1;
578                 tmp->tech_pvt = i;
579                 strncpy(tmp->context, i->context, sizeof(tmp->context)-1);
580
581                 if (!ast_strlen_zero(i->cid_num))
582                         tmp->cid.cid_num = strdup(i->cid_num);
583                 if (!ast_strlen_zero(i->cid_name))
584                         tmp->cid.cid_name = strdup(i->cid_name);
585
586                 if (!ast_strlen_zero(i->language))
587                         strncpy(tmp->language,i->language, sizeof(tmp->language)-1);
588                 if (!ast_strlen_zero(i->dnid))
589                         strncpy(tmp->exten, i->dnid, sizeof(tmp->exten) - 1);
590                 i->owner = tmp;
591                 ast_mutex_lock(&usecnt_lock);
592                 usecnt++;
593                 ast_mutex_unlock(&usecnt_lock);
594                 ast_update_use_count();
595                 if (state != AST_STATE_DOWN) {
596                         if (ast_pbx_start(tmp)) {
597                                 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
598                                 ast_hangup(tmp);
599                                 tmp = NULL;
600                         }
601                 }
602         } else
603                 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
604         return tmp;
605 }
606
607 static void modem_mini_packet(struct ast_modem_pvt *i)
608 {
609         struct ast_frame *fr;
610         fr = i->mc->read(i);
611         if (!fr) return;
612         if (fr->frametype == AST_FRAME_CONTROL) {
613                 if (fr->subclass == AST_CONTROL_RING) {
614                         ast_modem_new(i, AST_STATE_RING);
615                 }
616         }
617 }
618
619 static void *do_monitor(void *data)
620 {
621         fd_set rfds, efds;
622         int n, res;
623         struct ast_modem_pvt *i;
624         /* This thread monitors all the frame relay interfaces which are not yet in use
625            (and thus do not have a separate thread) indefinitely */
626         /* From here on out, we die whenever asked */
627 #if 0
628         if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
629                 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
630                 return NULL;
631         }
632 #endif
633         for(;;) {
634                 /* Don't let anybody kill us right away.  Nobody should lock the interface list
635                    and wait for the monitor list, but the other way around is okay. */
636                 if (ast_mutex_lock(&monlock)) {
637                         ast_log(LOG_ERROR, "Unable to grab monitor lock\n");
638                         return NULL;
639                 }
640                 /* Lock the interface list */
641                 if (ast_mutex_lock(&iflock)) {
642                         ast_log(LOG_ERROR, "Unable to grab interface lock\n");
643                         ast_mutex_unlock(&monlock);
644                         return NULL;
645                 }
646                 /* Build the stuff we're going to select on, that is the socket of every
647                    ast_modem_pvt that does not have an associated owner channel */
648                 n = -1;
649                 FD_ZERO(&rfds);
650                 FD_ZERO(&efds);
651                 i = iflist;
652                 while(i) {
653                         if (FD_ISSET(i->fd, &rfds)) 
654                                 ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);
655                         if (!i->owner) {
656                                 /* This needs to be watched, as it lacks an owner */
657                                 FD_SET(i->fd, &rfds);
658                                 FD_SET(i->fd, &efds);
659                                 if (i->fd > n)
660                                         n = i->fd;
661                         }
662                         
663                         i = i->next;
664                 }
665                 /* Okay, now that we know what to do, release the interface lock */
666                 ast_mutex_unlock(&iflock);
667                 
668                 /* And from now on, we're okay to be killed, so release the monitor lock as well */
669                 ast_mutex_unlock(&monlock);
670 #if 0
671                 ast_log(LOG_DEBUG, "In monitor, n=%d, pid=%d\n", n, getpid());
672 #endif
673                 /* Wait indefinitely for something to happen */
674                 pthread_testcancel();
675                 res = ast_select(n + 1, &rfds, NULL, &efds, NULL);
676                 pthread_testcancel();
677                 /* Okay, select has finished.  Let's see what happened.  */
678                 if (res < 1) {
679                         if ((errno != EINTR) && (errno != EAGAIN))
680                                 ast_log(LOG_WARNING, "select return %d: %s\n", res, strerror(errno));
681                         continue;
682                 }
683                 /* Alright, lock the interface list again, and let's look and see what has
684                    happened */
685                 if (ast_mutex_lock(&iflock)) {
686                         ast_log(LOG_WARNING, "Unable to lock the interface list\n");
687                         continue;
688                 }
689                 i = iflist;
690                 while(i) {
691                         if (FD_ISSET(i->fd, &rfds) || FD_ISSET(i->fd, &efds)) {
692                                 if (i->owner) {
693                                         ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d, %s)...\n", i->fd, i->dev);
694                                         i = i->next;
695                                         continue;
696                                 }
697                                 modem_mini_packet(i);
698                         }
699                         i=i->next;
700                 }
701                 ast_mutex_unlock(&iflock);
702         }
703         /* Never reached */
704         return NULL;
705         
706 }
707
708 static int restart_monitor()
709 {
710         /* If we're supposed to be stopped -- stay stopped */
711         if (monitor_thread == AST_PTHREADT_STOP)
712                 return 0;
713         if (ast_mutex_lock(&monlock)) {
714                 ast_log(LOG_WARNING, "Unable to lock monitor\n");
715                 return -1;
716         }
717         if (monitor_thread == pthread_self()) {
718                 ast_mutex_unlock(&monlock);
719                 ast_log(LOG_WARNING, "Cannot kill myself\n");
720                 return -1;
721         }
722         if (monitor_thread != AST_PTHREADT_NULL) {
723                 pthread_cancel(monitor_thread);
724                 /* Nudge it a little, as it's probably stuck in select */
725                 pthread_kill(monitor_thread, SIGURG);
726                 pthread_join(monitor_thread, NULL);
727         }
728         /* Start a new monitor */
729         if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
730                 ast_mutex_unlock(&monlock);
731                 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
732                 return -1;
733         }
734         ast_mutex_unlock(&monlock);
735         return 0;
736 }
737
738 static void stty(struct ast_modem_pvt *p)
739 {
740         struct termios mode;
741         memset(&mode, 0, sizeof(mode));
742         if (tcgetattr(p->fd, &mode)) {
743                 ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", p->dev, strerror(errno));
744                 return;
745         }
746 #ifndef SOLARIS
747         cfmakeraw(&mode);
748 #else
749         mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
750                         |INLCR|IGNCR|ICRNL|IXON);
751         mode.c_oflag &= ~OPOST;
752         mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
753         mode.c_cflag &= ~(CSIZE|PARENB);
754         mode.c_cflag |= CS8;
755 #endif
756
757         cfsetispeed(&mode, B115200);
758         cfsetospeed(&mode, B115200);
759         if (tcsetattr(p->fd, TCSANOW, &mode)) 
760                 ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", p->dev, strerror(errno));
761         
762 }
763
764 static struct ast_modem_pvt *mkif(char *iface)
765 {
766         /* Make a ast_modem_pvt structure for this interface */
767         struct ast_modem_pvt *tmp;
768 #if 0
769         int flags;      
770 #endif
771         
772         tmp = malloc(sizeof(struct ast_modem_pvt));
773         if (tmp) {
774                 memset(tmp, 0, sizeof(struct ast_modem_pvt));
775                 tmp->fd = open(iface, O_RDWR | O_NONBLOCK);
776                 if (tmp->fd < 0) {
777                         ast_log(LOG_WARNING, "Unable to open '%s'\n", iface);
778                         free(tmp);
779                         return NULL;
780                 }
781                 strncpy(tmp->language, language, sizeof(tmp->language)-1);
782                 strncpy(tmp->msn, msn, sizeof(tmp->msn)-1);
783                 strncpy(tmp->incomingmsn, incomingmsn, sizeof(tmp->incomingmsn)-1);
784                 tmp->dtmfmode = dtmfmode;
785                 tmp->dtmfmodegen = dtmfmodegen;
786                 snprintf(tmp->outgoingmsn, sizeof(tmp->outgoingmsn), ",%s,", outgoingmsn);
787                 strncpy(tmp->dev, iface, sizeof(tmp->dev)-1);
788                 /* Maybe in the future we want to allow variable
789                    serial settings */
790                 stty(tmp);
791                 tmp->f = fdopen(tmp->fd, "w+");
792                 /* Disable buffering */
793                 setvbuf(tmp->f, NULL, _IONBF,0);
794                 if (tmp->f < 0) {
795                         ast_log(LOG_WARNING, "Unable to fdopen '%s'\n", iface);
796                         free(tmp);
797                         return NULL;
798                 }
799                 tmp->owner = NULL;
800                 tmp->ministate = 0;
801                 tmp->stripmsd = stripmsd;
802                 tmp->dialtype = dialtype;
803                 tmp->mode = gmode;
804                 tmp->group = cur_group;
805                 memset(tmp->cid_num, 0, sizeof(tmp->cid_num));
806                 memset(tmp->cid_name, 0, sizeof(tmp->cid_name));
807                 strncpy(tmp->context, context, sizeof(tmp->context)-1);
808                 strncpy(tmp->initstr, initstr, sizeof(tmp->initstr)-1);
809                 tmp->next = NULL;
810                 tmp->obuflen = 0;
811                 
812                 if (modem_setup(tmp, baudrate) < 0) {
813                         ast_log(LOG_WARNING, "Unable to configure modem '%s'\n", iface);
814                         free(tmp);
815                         return NULL;
816                 }
817         }
818         return tmp;
819 }
820
821 static struct ast_channel *modem_request(const char *type, int format, void *data, int *cause)
822 {
823         int oldformat;
824         struct ast_modem_pvt *p;
825         struct ast_channel *tmp = NULL;
826         char dev[80];
827         ast_group_t group = 0;
828         int groupint;
829         char *stringp=NULL;
830         strncpy(dev, (char *)data, sizeof(dev)-1);
831         stringp=dev;
832         strsep(&stringp, ":");
833         oldformat = format;
834
835         if (!dep_warning) {
836                 ast_log(LOG_WARNING, "This channel driver is deprecated.  Please see the UPGRADE.txt file.\n");
837                 dep_warning = 1;
838         }
839
840         if (dev[0]=='g' && isdigit(dev[1])) {
841                 /* Retrieve the group number */
842                 if (sscanf(dev+1, "%u", &groupint) < 1) {
843                         ast_log(LOG_WARNING, "Unable to determine group from [%s]\n", (char *)data);
844                         return NULL;
845                 }
846                 group = 1 << groupint;
847         }
848
849         /* Search for an unowned channel */
850         if (ast_mutex_lock(&iflock)) {
851                 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
852                 return NULL;
853         }
854         p = iflist;
855         while(p) {
856                 if (group) {
857                         /* if it belongs to the proper group, and the format matches
858                          * and it is not in use, we found a candidate! */
859                         if (p->group & group &&
860                             p->mc->formats & format &&
861                             !p->owner) {
862                                 /* XXX Not quite sure that not having an owner is
863                                  * sufficient evidence of beeing a free device XXX */
864                                 tmp = ast_modem_new(p, AST_STATE_DOWN);
865                                 restart_monitor();
866                                 break;
867                         }
868                 } else {
869                         if (!strcmp(dev, p->dev + 5)) {
870                                 if (p->mc->formats & format) {
871                                         if (!p->owner) {
872                                                 tmp = ast_modem_new(p, AST_STATE_DOWN);
873                                                 restart_monitor();
874                                                 break;
875                                         } else
876                                                 ast_log(LOG_WARNING, "Device '%s' is busy\n", p->dev);
877                                 } else 
878                                         ast_log(LOG_WARNING, "Asked for a format %s line on %s\n", ast_getformatname(format), p->dev);
879                                 break;
880                         }
881                 }
882                 p = p->next;
883         }
884         if (!p) 
885                 ast_log(LOG_WARNING, "Requested device '%s' does not exist\n", dev);
886         
887         ast_mutex_unlock(&iflock);
888         return tmp;
889 }
890
891 static ast_group_t get_group(char *s)
892 {
893         char *piece;
894         int start, finish,x;
895         ast_group_t group = 0;
896         char *copy = ast_strdupa(s);
897         char *stringp=NULL;
898         if (!copy) {
899                 ast_log(LOG_ERROR, "Out of memory\n");
900                 return 0;
901         }
902         stringp=copy;
903         piece = strsep(&stringp, ",");
904         while(piece) {
905                 if (sscanf(piece, "%d-%d", &start, &finish) == 2) {
906                         /* Range */
907                 } else if (sscanf(piece, "%d", &start)) {
908                         /* Just one */
909                         finish = start;
910                 } else {
911                         ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'.  Using '0'\n", s,piece);
912                         return 0;
913                 }
914                 piece = strsep(&stringp, ",");
915
916                 for (x=start;x<=finish;x++) {
917                         if ((x > 63) || (x < 0)) {
918                                 ast_log(LOG_WARNING, "Ignoring invalid group %d\n", x);
919                                 break;
920                         }
921                         group |= (1 << x);
922                 }
923         }
924         return group;
925 }
926
927 static int __unload_module(void)
928 {
929         struct ast_modem_pvt *p, *pl;
930         /* First, take us out of the channel loop */
931         ast_channel_unregister(&modem_tech);
932         if (!ast_mutex_lock(&iflock)) {
933                 /* Hangup all interfaces if they have an owner */
934                 p = iflist;
935                 while(p) {
936                         if (p->owner)
937                                 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
938                         p = p->next;
939                 }
940                 iflist = NULL;
941                 ast_mutex_unlock(&iflock);
942         } else {
943                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
944                 return -1;
945         }
946         if (!ast_mutex_lock(&monlock)) {
947                 if (monitor_thread != AST_PTHREADT_NULL && monitor_thread != AST_PTHREADT_STOP) {
948                         pthread_cancel(monitor_thread);
949                         pthread_join(monitor_thread, NULL);
950                 }
951                 monitor_thread = AST_PTHREADT_STOP;
952                 ast_mutex_unlock(&monlock);
953         } else {
954                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
955                 return -1;
956         }
957
958         if (!ast_mutex_lock(&iflock)) {
959                 /* Destroy all the interfaces and free their memory */
960                 p = iflist;
961                 while(p) {
962                         /* Close the socket, assuming it's real */
963                         if (p->fd > -1)
964                                 close(p->fd);
965                         pl = p;
966                         p = p->next;
967                         /* Free associated memory */
968                         free(pl);
969                 }
970                 iflist = NULL;
971                 ast_mutex_unlock(&iflock);
972         } else {
973                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
974                 return -1;
975         }
976                 
977         return 0;
978 }
979
980 int unload_module()
981 {
982         return __unload_module();
983 }
984
985 int load_module()
986 {
987         struct ast_config *cfg;
988         struct ast_variable *v;
989         struct ast_modem_pvt *tmp;
990         char driver[80];
991         cfg = ast_config_load(config);
992
993         /* We *must* have a config file otherwise stop immediately */
994         if (!cfg) {
995                 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
996                 return -1;
997         }
998         if (ast_mutex_lock(&iflock)) {
999                 /* It's a little silly to lock it, but we mind as well just to be sure */
1000                 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
1001                 return -1;
1002         }
1003         v = ast_variable_browse(cfg, "interfaces");
1004         while(v) {
1005                 /* Create the interface list */
1006                 if (!strcasecmp(v->name, "device")) {
1007                                 tmp = mkif(v->value);
1008                                 if (tmp) {
1009                                         tmp->next = iflist;
1010                                         iflist = tmp;
1011                                         
1012                                 } else {
1013                                         ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
1014                                         ast_config_destroy(cfg);
1015                                         ast_mutex_unlock(&iflock);
1016                                         __unload_module();
1017                                         return -1;
1018                                 }
1019                 } else if (!strcasecmp(v->name, "driver")) {
1020                         snprintf(driver, sizeof(driver), "chan_modem_%s.so", v->value);
1021                         if (option_verbose > 1) 
1022                                 ast_verbose(VERBOSE_PREFIX_2 "Loading modem driver %s", driver);
1023                                 
1024                         if (ast_load_resource(driver)) {
1025                                 ast_log(LOG_ERROR, "Failed to load driver %s\n", driver);
1026                                 ast_config_destroy(cfg);
1027                                 ast_mutex_unlock(&iflock);
1028                                 __unload_module();
1029                                 return -1;
1030                         }
1031                 } else if (!strcasecmp(v->name, "mode")) {
1032                         if (!strncasecmp(v->value, "ri", 2)) 
1033                                 gmode = MODEM_MODE_WAIT_RING;
1034                         else if (!strncasecmp(v->value, "im", 2))
1035                                 gmode = MODEM_MODE_IMMEDIATE;
1036                         else if (!strncasecmp(v->value, "an", 2))
1037                                 gmode = MODEM_MODE_WAIT_ANSWER;
1038                         else
1039                                 ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
1040                 } else if (!strcasecmp(v->name, "stripmsd")) {
1041                         stripmsd = atoi(v->value);
1042                 } else if (!strcasecmp(v->name, "type")) {
1043                         strncpy(mtype, v->value, sizeof(mtype)-1);
1044                 } else if (!strcasecmp(v->name, "initstr")) {
1045                         strncpy(initstr, v->value, sizeof(initstr)-1);
1046                 } else if (!strcasecmp(v->name, "dialtype")) {
1047                         dialtype = toupper(v->value[0]);
1048                 } else if (!strcasecmp(v->name, "context")) {
1049                         strncpy(context, v->value, sizeof(context)-1);
1050                 } else if (!strcasecmp(v->name, "msn")) {
1051                         strncpy(msn, v->value, sizeof(msn)-1);
1052                 } else if (!strcasecmp(v->name, "incomingmsn")) {
1053                         strncpy(incomingmsn, v->value, sizeof(incomingmsn)-1);
1054                 } else if (!strcasecmp(v->name, "dtmfmode")) {
1055                         char tmp[80];
1056                         char *alt;
1057                         strncpy(tmp, v->value, sizeof(tmp) - 1);
1058                         alt = strchr(tmp, '/');
1059                         if (!strcasecmp(tmp, "none"))
1060                                 dtmfmode=MODEM_DTMF_NONE;
1061                         else if (!strcasecmp(tmp, "asterisk"))
1062                                 dtmfmode = MODEM_DTMF_AST;
1063                         else if (!strcasecmp(tmp, "i4l"))
1064                                 dtmfmode = MODEM_DTMF_I4L;
1065                         else {
1066                                 ast_log(LOG_WARNING, "Unknown dtmf detection mode '%s', using 'asterisk'\n", v->value);
1067                                 dtmfmode = MODEM_DTMF_AST;
1068                         }
1069                         if (alt) {
1070                                 if (!strcasecmp(alt, "none"))
1071                                         dtmfmodegen=MODEM_DTMF_NONE;
1072                                 else if (!strcasecmp(alt, "asterisk"))
1073                                         dtmfmodegen = MODEM_DTMF_AST;
1074                                 else if (!strcasecmp(alt, "i4l"))
1075                                         dtmfmodegen = MODEM_DTMF_I4L;
1076                                 else if (!strcasecmp(alt, "both"))
1077                                         dtmfmodegen = MODEM_DTMF_I4L | MODEM_DTMF_AST;
1078                                 else {
1079                                         ast_log(LOG_WARNING, "Unknown dtmf generation mode '%s', using 'asterisk'\n", v->value);
1080                                         dtmfmodegen = MODEM_DTMF_AST;
1081                                 }
1082                         } else
1083                                 dtmfmodegen = dtmfmode;
1084                 } else if (!strcasecmp(v->name, "outgoingmsn")) {
1085                         strncpy(outgoingmsn, v->value, sizeof(outgoingmsn)-1);
1086                 } else if (!strcasecmp(v->name, "language")) {
1087                         strncpy(language, v->value, sizeof(language)-1);
1088                 } else if (!strcasecmp(v->name, "group")) {
1089                         cur_group = get_group(v->value);
1090                 }
1091                 v = v->next;
1092         }
1093         ast_mutex_unlock(&iflock);
1094         if (ast_channel_register(&modem_tech)) {
1095                 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
1096                 ast_config_destroy(cfg);
1097                 __unload_module();
1098                 return -1;
1099         }
1100         ast_config_destroy(cfg);
1101         /* And start the monitor for the first time */
1102         restart_monitor();
1103         return 0;
1104 }
1105
1106 int usecount(void)
1107 {
1108         return usecnt;
1109 }
1110
1111 char *description()
1112 {
1113         return (char *) desc;
1114 }
1115
1116 char *key()
1117 {
1118         return ASTERISK_GPL_KEY;
1119 }
1120