Version 0.1.9 from FTP
[asterisk/asterisk.git] / channels / chan_modem.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * A/Open ITU-56/2 Voice Modem Driver (Rockwell, IS-101, and others)
5  * 
6  * Copyright (C) 1999, Mark Spencer
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
14 #include <stdio.h>
15 #include <pthread.h>
16 #include <string.h>
17 #include <asterisk/channel.h>
18 #include <asterisk/channel_pvt.h>
19 #include <asterisk/config.h>
20 #include <asterisk/logger.h>
21 #include <asterisk/module.h>
22 #include <asterisk/pbx.h>
23 #include <asterisk/options.h>
24 #include <asterisk/vmodem.h>
25 #include <sys/socket.h>
26 #include <sys/time.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <arpa/inet.h>
31 #include <fcntl.h>
32 #include <sys/ioctl.h>
33 #include <sys/termios.h>
34 #include <sys/signal.h>
35 #include <ctype.h>
36
37 /* Up to 10 seconds for an echo to arrive */
38 #define ECHO_TIMEOUT 10
39
40 static char *desc = "Generic Voice Modem Driver";
41 static char *tdesc = "Generic Voice Modem Channel Driver";
42 static char *type = "Modem";
43 static char *config = "modem.conf";
44 static char dialtype = 'T';
45 static int gmode = MODEM_MODE_IMMEDIATE;
46
47 /* Default modem type */
48 static char mtype[80] = "autodetect";
49 /* Default context for incoming calls */
50 static char context[AST_MAX_EXTENSION]= "default";
51
52 /* Default language */
53 static char language[MAX_LANGUAGE] = "";
54
55 /* Initialization String */
56 static char initstr[AST_MAX_INIT_STR] = "ATE0Q0";
57
58 /* Default MSN */
59 static char msn[AST_MAX_EXTENSION]="";
60
61 static int usecnt =0;
62
63 static int baudrate = 115200;
64
65 static int stripmsd = 0;
66
67 static pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER;
68
69 /* Protect the interface list (of ast_modem_pvt's) */
70 static pthread_mutex_t iflock = PTHREAD_MUTEX_INITIALIZER;
71
72 /* Protect the monitoring thread, so only one process can kill or start it, and not
73    when it's doing something critical. */
74 static pthread_mutex_t monlock = PTHREAD_MUTEX_INITIALIZER;
75
76 /* This is the thread for the monitor which checks for input on the channels
77    which are not currently in use.  */
78 static pthread_t monitor_thread = -1;
79
80 static int restart_monitor(void);
81
82 /* The private structures of the Phone Jack channels are linked for
83    selecting outgoing channels */
84    
85 static struct ast_modem_pvt  *iflist = NULL;
86
87 static int modem_digit(struct ast_channel *ast, char digit)
88 {
89         struct ast_modem_pvt *p;
90         p = ast->pvt->pvt;
91         if (p->mc->dialdigit)
92                 return p->mc->dialdigit(p, digit);
93         else ast_log(LOG_DEBUG, "Channel %s lacks digit dialing\n");
94         return 0;
95 }
96
97 static struct ast_modem_driver *drivers = NULL;
98
99 static struct ast_frame *modem_read(struct ast_channel *);
100
101 static struct ast_modem_driver *find_capability(char *ident)
102 {
103         struct ast_modem_driver *mc;
104         int x;
105         mc = drivers;
106         while(mc) {
107                 for (x=0;mc->idents[x];x++) {
108                         if (!strcmp(ident, mc->idents[x])) 
109                                 break;
110                 }
111                 if (mc->idents[x])
112                         break;
113                 mc = mc->next;
114         }
115         if (mc) {
116                 if (mc->incusecnt)
117                         mc->incusecnt();
118         }
119         return mc;
120 }
121
122 static struct ast_modem_driver *find_driver(char *drv)
123 {
124         struct ast_modem_driver *mc;
125         mc = drivers;
126         while(mc) {
127                 if (!strcasecmp(mc->name, drv)) 
128                         break;
129                 mc = mc->next;
130         }
131         if (mc) {
132                 if (mc->incusecnt)
133                         mc->incusecnt();
134         }
135         return mc;
136 }
137
138 int ast_register_modem_driver(struct ast_modem_driver *mc)
139 {
140         mc->next = drivers;
141         drivers = mc;
142         return 0;
143 }
144
145 int ast_unregister_modem_driver(struct ast_modem_driver *mc)
146 {
147         struct ast_modem_driver *last = NULL, *cur;
148         cur = drivers;
149         while(cur) {
150                 if (cur == mc) {
151                         if (last)
152                                 last->next = mc->next;
153                         else
154                                 drivers = mc->next;
155                         return 0;
156                 }
157                 cur = cur->next;
158         }
159         return -1;
160 }
161
162 static int modem_call(struct ast_channel *ast, char *idest, int timeout)
163 {
164         static int modem_hangup(struct ast_channel *ast);
165         struct ast_modem_pvt *p;
166         int ms = timeout;
167         char rdest[80], *where, dstr[100];
168         strncpy(rdest, idest, sizeof(rdest));
169         strtok(rdest, ":");
170         where = strtok(NULL, ":");
171         if (!where) {
172                 ast_log(LOG_WARNING, "Destination %s requres a real destination (device:destination)\n", idest);
173                 return -1;
174         }
175         p = ast->pvt->pvt;
176         strcpy(dstr,where + p->stripmsd);
177         /* if not a transfer or just sending tones, must be in correct state */
178         if (strcasecmp(rdest, "transfer") && strcasecmp(rdest,"sendtones")) {
179                 if ((ast->state != AST_STATE_DOWN) && (ast->state != AST_STATE_RESERVED)) {
180                         ast_log(LOG_WARNING, "modem_call called on %s, neither down nor reserved\n", ast->name);
181                         return -1;
182                 }
183         } 
184         if (!strcasecmp(rdest,"transfer")) /* if a transfer, put in transfer stuff */
185         {
186                 sprintf(dstr,"!,%s",where + p->stripmsd);
187         }
188         if (!strcasecmp(where, "handset")) {
189                 if (p->mc->setdev)
190                         if (p->mc->setdev(p, MODEM_DEV_HANDSET))
191                                 return -1;
192                 /* Should be immediately up */
193                 ast->state = AST_STATE_UP;
194         } else {
195                 if (p->mc->setdev)
196                         if (p->mc->setdev(p, MODEM_DEV_TELCO_SPK))
197                                 return -1;
198                 if (p->mc->dial)
199                         p->mc->dial(p, dstr);
200                 ast->state = AST_STATE_DIALING;
201                 while((ast->state != AST_STATE_UP) && (ms > 0)) {
202                         ms = ast_waitfor(ast, ms);
203                         /* Just read packets and watch what happens */
204                         if (ms > 0) {
205                                 if (!modem_read(ast))
206                                         return -1;
207                         }
208                 }
209                 if (ms < 0)     
210                         return -1;
211         }
212         return 0;
213 }
214
215 int ast_modem_send(struct ast_modem_pvt *p, char *cmd, int len)
216 {
217         int i;
218         usleep(5000);
219         if (!len) {
220                 for(i = 0; cmd[i];)
221                    {
222                         if (fwrite(cmd + i,1,1,p->f) != 1)
223                            {
224                                 if (errno == EWOULDBLOCK) continue;
225                                 return -1;
226                            }
227                         i++;
228                    }
229                 tcdrain(fileno(p->f)); 
230                 fprintf(p->f,"\r\n");
231                 return 0;
232         } else {
233                 if (fwrite(cmd, 1, len, p->f) < len)
234                         return -1;
235                 return 0;
236         }
237 }
238
239 int ast_modem_read_response(struct ast_modem_pvt *p, int timeout)
240 {
241         int res = -1,c,i;
242         timeout *= 1000;
243         p->response[0] = 0;
244         c = i = 0;
245         do {
246                 res = ast_waitfor_n_fd(&p->fd, 1, &timeout, NULL);
247                 if (res < 0) {
248                         strncpy(p->response, "(No Response)", sizeof(p->response));
249                         return -1;
250                 }
251                   /* get no more then buffer length */
252                 while(i < sizeof(p->response) - 1)
253                 {
254                         c = fgetc(p->f);  /* get a char */
255                         if (c < 1) /* if error */
256                         {
257                                   /* if nothing in buffer, go back into timeout stuff */
258                                 if (errno == EWOULDBLOCK) break;
259                                 /* return as error */
260                                 strncpy(p->response, "(No Response)", sizeof(p->response));
261                                 return -1;
262                         }
263                           /* save char */
264                         p->response[i++] = c;
265                         p->response[i] = 0;                     
266                           /* if end of input */
267                         if (c == '\n') break;
268                 }
269                 if (c >= 0)  /* if input terminated normally */
270                 {
271                           /* ignore just CR/LF */
272                         if (!strcmp(p->response,"\r\n"))
273                         {
274                                   /* reset input buffer stuff */
275                                 i = 0; 
276                                 p->response[0] = 0;
277                         }
278                         else /* otherwise return with info in buffer */
279                         {
280                                 return 0;
281                         }
282                 }
283         } while(timeout > 0);
284         strncpy(p->response, "(No Response)", sizeof(p->response));
285         return -1;
286 }
287
288 int ast_modem_expect(struct ast_modem_pvt *p, char *result, int timeout)
289 {
290         int res = -1;
291         timeout *= 1000;
292         strncpy(p->response, "(No Response)", sizeof(p->response));
293         do {
294                 res = ast_waitfor_n_fd(&p->fd, 1, &timeout, NULL);
295                 if (res < 0) {
296                         return -1;
297                 }
298                 /* Read a response */
299                 fgets(p->response, sizeof(p->response), p->f);
300 #if     0
301                 fprintf(stderr, "Modem said: %s", p->response);
302 #endif
303                 if (!strncasecmp(p->response, result, strlen(result))) 
304                         return 0;
305         } while(timeout > 0);
306         return -1;
307 }
308
309 void ast_modem_trim(char *s)
310 {
311         int x;
312         x = strlen(s) - 1;
313         while(x >= 0) {
314                 if ((s[x] != '\r') && (s[x] != '\n') && (s[x] != ' '))
315                         break;
316                 s[x] = '\0';
317                 x--;
318         }
319 }
320
321 static int modem_setup(struct ast_modem_pvt *p, int baudrate)
322 {
323
324         /* Make sure there's a modem there and that it's in a reasonable 
325            mode.  Set the baud rate, etc.  */
326         char identity[256];
327         char *ident = NULL;
328         char etx[2] = { 0x10, '!' }; 
329         if (option_debug)
330                 ast_log(LOG_DEBUG, "Setting up modem %s\n", p->dev);
331         if (ast_modem_send(p, etx, 2)) {
332                 ast_log(LOG_WARNING, "Failed to send ETX?\n");
333                 return -1;
334         }
335         if (ast_modem_send(p, "\r\n", 2)) {
336                 ast_log(LOG_WARNING, "Failed to send enter?\n");
337                 return -1;
338         }
339         usleep(10000);
340         /* Read any outstanding stuff */
341         while(!ast_modem_read_response(p, 0));
342         if (ast_modem_send(p, "ATZ", 0)) {
343                 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev);
344                 return -1;
345         }
346         if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) {
347                 ast_log(LOG_WARNING, "Modem reset failed: %s\n", p->response);
348                 return -1;
349         }
350         if (ast_modem_send(p, p->initstr, 0)) {
351                 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev);
352                 return -1;
353         }
354         if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) {
355                 ast_log(LOG_WARNING, "Modem initialization failed: %s\n", p->response);
356                 return -1;
357         }
358         if (ast_modem_send(p, "ATI3", 0)) {
359                 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev);
360                 return -1;
361         }
362         if (ast_modem_read_response(p, ECHO_TIMEOUT)) {
363                 ast_log(LOG_WARNING, "Modem did not provide identification\n");
364                 return -1;
365         }
366         strncpy(identity, p->response, sizeof(identity));
367         ast_modem_trim(identity);
368         if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) {
369                 ast_log(LOG_WARNING, "Modem did not provide identification\n");
370                 return -1;
371         }
372         if (!strcasecmp(mtype, "autodetect")) {
373                 p->mc = find_capability(identity);
374                 if (!p->mc) {
375                         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); 
376                         return -1;
377                 }
378         } else {
379                 p->mc = find_driver(mtype);
380                 if (!p->mc) {
381                         ast_log(LOG_WARNING, "No driver for modem type '%s'\n", mtype);
382                         return -1;
383                 }
384         }
385         if (p->mc->init) {
386                 if (p->mc->init(p)) {
387                         ast_log(LOG_WARNING, "Modem Initialization Failed on '%s', driver %s.\n", p->dev, p->mc->name);
388                         p->mc->decusecnt();
389                         return -1;
390                 }
391         }                       
392         if (option_verbose > 2) {
393                 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");
394         }
395         if (ident)
396                 free(ident);
397         return 0;
398 }
399
400 static int modem_hangup(struct ast_channel *ast)
401 {
402         struct ast_modem_pvt *p;
403         if (option_debug)
404                 ast_log(LOG_DEBUG, "modem_hangup(%s)\n", ast->name);
405         p = ast->pvt->pvt;
406         /* Hang up */
407         if (p->mc->hangup)
408                 p->mc->hangup(p);
409         /* Re-initialize */
410         if (p->mc->init)
411                 p->mc->init(p);
412         ast->state = AST_STATE_DOWN;
413         memset(p->cid, 0, sizeof(p->cid));
414         ((struct ast_modem_pvt *)(ast->pvt->pvt))->owner = NULL;
415         ast_pthread_mutex_lock(&usecnt_lock);
416         usecnt--;
417         if (usecnt < 0) 
418                 ast_log(LOG_WARNING, "Usecnt < 0???\n");
419         ast_pthread_mutex_unlock(&usecnt_lock);
420         ast_update_use_count();
421         if (option_verbose > 2) 
422                 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
423         ast->pvt->pvt = NULL;
424         ast->state = AST_STATE_DOWN;
425         restart_monitor();
426         return 0;
427 }
428
429 static int modem_answer(struct ast_channel *ast)
430 {
431         struct ast_modem_pvt *p;
432         int res=0;
433         if (option_debug)
434                 ast_log(LOG_DEBUG, "modem_answer(%s)\n", ast->name);
435         p = ast->pvt->pvt;
436         if (p->mc->answer) {
437                 res = p->mc->answer(p);
438         }
439         if (!res) {
440                 ast->rings = 0;
441                 ast->state = AST_STATE_UP;
442         }
443         return res;
444 }
445
446 #if     0
447 static char modem_2digit(char c)
448 {
449         if (c == 12)
450                 return '#';
451         else if (c == 11)
452                 return '*';
453         else if ((c < 10) && (c >= 0))
454                 return '0' + c - 1;
455         else
456                 return '?';
457 }
458 #endif
459 static struct ast_frame *modem_read(struct ast_channel *ast)
460 {
461         struct ast_modem_pvt *p = ast->pvt->pvt;
462         struct ast_frame *fr=NULL;
463         if (p->mc->read)
464                 fr = p->mc->read(p);
465         return fr;
466 }
467
468 static int modem_write(struct ast_channel *ast, struct ast_frame *frame)
469 {
470         int res=0;
471         struct ast_modem_pvt *p = ast->pvt->pvt;
472         if (p->mc->write)
473                 res = p->mc->write(p, frame);
474         return 0;
475 }
476
477 struct ast_channel *ast_modem_new(struct ast_modem_pvt *i, int state)
478 {
479         struct ast_channel *tmp;
480         tmp = ast_channel_alloc();
481         if (tmp) {
482                 snprintf(tmp->name, sizeof(tmp->name), "Modem[%s]/%s", i->mc->name, i->dev + 5);
483                 tmp->type = type;
484                 tmp->fds[0] = i->fd;
485                 tmp->nativeformats = i->mc->formats;
486                 tmp->state = state;
487                 if (state == AST_STATE_RING)
488                         tmp->rings = 1;
489                 tmp->pvt->pvt = i;
490                 tmp->pvt->send_digit = modem_digit;
491                 tmp->pvt->call = modem_call;
492                 tmp->pvt->hangup = modem_hangup;
493                 tmp->pvt->answer = modem_answer;
494                 tmp->pvt->read = modem_read;
495                 tmp->pvt->write = modem_write;
496                 strncpy(tmp->context, i->context, sizeof(tmp->context));
497                 if (strlen(i->cid))
498                         tmp->callerid = strdup(i->cid);
499                 if (strlen(i->language))
500                         strncpy(tmp->language,i->language, sizeof(tmp->language));
501                 i->owner = tmp;
502                 ast_pthread_mutex_lock(&usecnt_lock);
503                 usecnt++;
504                 ast_pthread_mutex_unlock(&usecnt_lock);
505                 ast_update_use_count();
506                 if (state != AST_STATE_DOWN) {
507                         if (ast_pbx_start(tmp)) {
508                                 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
509                                 ast_hangup(tmp);
510                                 tmp = NULL;
511                         }
512                 }
513         } else
514                 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
515         return tmp;
516 }
517
518 static void modem_mini_packet(struct ast_modem_pvt *i)
519 {
520         struct ast_frame *fr;
521         fr = i->mc->read(i);
522         if (!fr) return;
523         if (fr->frametype == AST_FRAME_CONTROL) {
524                 if (fr->subclass == AST_CONTROL_RING) {
525                         ast_modem_new(i, AST_STATE_RING);
526                 }
527         }
528 }
529
530 static void *do_monitor(void *data)
531 {
532         fd_set rfds, efds;
533         int n, res;
534         struct ast_modem_pvt *i;
535         /* This thread monitors all the frame relay interfaces which are not yet in use
536            (and thus do not have a separate thread) indefinitely */
537         /* From here on out, we die whenever asked */
538 #if 0
539         if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
540                 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
541                 return NULL;
542         }
543 #endif
544         for(;;) {
545                 /* Don't let anybody kill us right away.  Nobody should lock the interface list
546                    and wait for the monitor list, but the other way around is okay. */
547                 if (ast_pthread_mutex_lock(&monlock)) {
548                         ast_log(LOG_ERROR, "Unable to grab monitor lock\n");
549                         return NULL;
550                 }
551                 /* Lock the interface list */
552                 if (ast_pthread_mutex_lock(&iflock)) {
553                         ast_log(LOG_ERROR, "Unable to grab interface lock\n");
554                         ast_pthread_mutex_unlock(&monlock);
555                         return NULL;
556                 }
557                 /* Build the stuff we're going to select on, that is the socket of every
558                    ast_modem_pvt that does not have an associated owner channel */
559                 n = -1;
560                 FD_ZERO(&rfds);
561                 FD_ZERO(&efds);
562                 i = iflist;
563                 while(i) {
564                         if (FD_ISSET(i->fd, &rfds)) 
565                                 ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);
566                         if (!i->owner) {
567                                 /* This needs to be watched, as it lacks an owner */
568                                 FD_SET(i->fd, &rfds);
569                                 FD_SET(i->fd, &efds);
570                                 if (i->fd > n)
571                                         n = i->fd;
572                         }
573                         
574                         i = i->next;
575                 }
576                 /* Okay, now that we know what to do, release the interface lock */
577                 ast_pthread_mutex_unlock(&iflock);
578                 
579                 /* And from now on, we're okay to be killed, so release the monitor lock as well */
580                 ast_pthread_mutex_unlock(&monlock);
581 #if 0
582                 ast_log(LOG_DEBUG, "In monitor, n=%d, pid=%d\n", n, getpid());
583 #endif
584                 /* Wait indefinitely for something to happen */
585                 pthread_testcancel();
586                 res = select(n + 1, &rfds, NULL, &efds, NULL);
587                 pthread_testcancel();
588                 /* Okay, select has finished.  Let's see what happened.  */
589                 if (res < 1) {
590                         ast_log(LOG_WARNING, "select return %d: %s\n", res, strerror(errno));
591                         continue;
592                 }
593                 /* Alright, lock the interface list again, and let's look and see what has
594                    happened */
595                 if (ast_pthread_mutex_lock(&iflock)) {
596                         ast_log(LOG_WARNING, "Unable to lock the interface list\n");
597                         continue;
598                 }
599                 i = iflist;
600                 while(i) {
601                         if (FD_ISSET(i->fd, &rfds) || FD_ISSET(i->fd, &efds)) {
602                                 if (i->owner) {
603                                         ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d, %s)...\n", i->fd, i->dev);
604                                         i = i->next;
605                                         continue;
606                                 }
607                                 modem_mini_packet(i);
608                         }
609                         i=i->next;
610                 }
611                 ast_pthread_mutex_unlock(&iflock);
612         }
613         /* Never reached */
614         return NULL;
615         
616 }
617
618 static int restart_monitor()
619 {
620         /* If we're supposed to be stopped -- stay stopped */
621         if (monitor_thread == -2)
622                 return 0;
623         if (ast_pthread_mutex_lock(&monlock)) {
624                 ast_log(LOG_WARNING, "Unable to lock monitor\n");
625                 return -1;
626         }
627         if (monitor_thread == pthread_self()) {
628                 ast_pthread_mutex_unlock(&monlock);
629                 ast_log(LOG_WARNING, "Cannot kill myself\n");
630                 return -1;
631         }
632         if (monitor_thread != -1) {
633                 pthread_cancel(monitor_thread);
634                 /* Nudge it a little, as it's probably stuck in select */
635                 pthread_kill(monitor_thread, SIGURG);
636                 pthread_join(monitor_thread, NULL);
637         }
638         /* Start a new monitor */
639         if (pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
640                 ast_pthread_mutex_unlock(&monlock);
641                 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
642                 return -1;
643         }
644         ast_pthread_mutex_unlock(&monlock);
645         return 0;
646 }
647
648 static void stty(struct ast_modem_pvt *p)
649 {
650         struct termios mode;
651         memset(&mode, 0, sizeof(mode));
652         if (tcgetattr(p->fd, &mode)) {
653                 ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", p->dev, strerror(errno));
654                 return;
655         }
656         cfmakeraw(&mode);
657         cfsetspeed(&mode, B115200);
658         if (tcsetattr(p->fd, TCSANOW, &mode)) 
659                 ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", p->dev, strerror(errno));
660         
661 }
662
663 static struct ast_modem_pvt *mkif(char *iface)
664 {
665         /* Make a ast_modem_pvt structure for this interface */
666         struct ast_modem_pvt *tmp;
667 #if 0
668         int flags;      
669 #endif
670         
671         tmp = malloc(sizeof(struct ast_modem_pvt));
672         memset(tmp, 0, sizeof(struct ast_modem_pvt));
673         if (tmp) {
674                 tmp->fd = open(iface, O_RDWR | O_NONBLOCK);
675                 if (tmp->fd < 0) {
676                         ast_log(LOG_WARNING, "Unable to open '%s'\n", iface);
677                         free(tmp);
678                         return NULL;
679                 }
680                 strncpy(tmp->language, language, sizeof(tmp->language));
681                 strncpy(tmp->msn, msn, sizeof(tmp->msn));
682                 strncpy(tmp->dev, iface, sizeof(tmp->dev));
683                 /* Maybe in the future we want to allow variable
684                    serial settings */
685                 stty(tmp);
686                 tmp->f = fdopen(tmp->fd, "w+");
687                 /* Disable buffering */
688                 setvbuf(tmp->f, NULL, _IONBF,0);
689                 if (tmp->f < 0) {
690                         ast_log(LOG_WARNING, "Unable to fdopen '%s'\n", iface);
691                         free(tmp);
692                         return NULL;
693                 }
694 #if 0
695                 flags = fcntl(tmp->fd, F_GETFL);
696                 fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK);
697 #endif
698                 tmp->owner = NULL;
699                 tmp->ministate = 0;
700                 tmp->stripmsd = stripmsd;
701                 tmp->dialtype = dialtype;
702                 tmp->mode = gmode;
703                 memset(tmp->cid, 0, sizeof(tmp->cid));
704                 strncpy(tmp->context, context, sizeof(tmp->context));
705                 strncpy(tmp->initstr, initstr, sizeof(tmp->initstr));
706                 tmp->next = NULL;
707                 tmp->obuflen = 0;
708                 
709                 if (modem_setup(tmp, baudrate) < 0) {
710                         ast_log(LOG_WARNING, "Unable to configure modem '%s'\n", iface);
711                         free(tmp);
712                         return NULL;
713                 }
714         }
715         return tmp;
716 }
717
718 static struct ast_channel *modem_request(char *type, int format, void *data)
719 {
720         int oldformat;
721         struct ast_modem_pvt *p;
722         struct ast_channel *tmp = NULL;
723         char dev[80];
724         strncpy(dev, (char *)data, sizeof(dev));
725         strtok(dev, ":");
726         oldformat = format;
727         /* Search for an unowned channel */
728         if (ast_pthread_mutex_lock(&iflock)) {
729                 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
730                 return NULL;
731         }
732         p = iflist;
733         while(p) {
734                 if (!strcmp(dev, p->dev + 5)) {
735                         if (p->mc->formats & format) {
736                                 if (!p->owner) {
737                                         tmp = ast_modem_new(p, AST_STATE_DOWN);
738                                         restart_monitor();
739                                         break;
740                                 } else
741                                         ast_log(LOG_WARNING, "Device '%s' is busy\n", p->dev);
742                         } else 
743                                 ast_log(LOG_WARNING, "Asked for a format %d line on %s\n", format, p->dev);
744                         break;
745                 }
746                 p = p->next;
747         }
748         if (!p) 
749                 ast_log(LOG_WARNING, "Requested device '%s' does not exist\n", p->dev);
750         
751         ast_pthread_mutex_unlock(&iflock);
752         return tmp;
753 }
754
755 int load_module()
756 {
757         struct ast_config *cfg;
758         struct ast_variable *v;
759         struct ast_modem_pvt *tmp;
760         char driver[80];
761         cfg = ast_load(config);
762
763         /* We *must* have a config file otherwise stop immediately */
764         if (!cfg) {
765                 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
766                 return -1;
767         }
768         if (ast_pthread_mutex_lock(&iflock)) {
769                 /* It's a little silly to lock it, but we mind as well just to be sure */
770                 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
771                 return -1;
772         }
773         v = ast_variable_browse(cfg, "interfaces");
774         while(v) {
775                 /* Create the interface list */
776                 if (!strcasecmp(v->name, "device")) {
777                                 tmp = mkif(v->value);
778                                 if (tmp) {
779                                         tmp->next = iflist;
780                                         iflist = tmp;
781                                         
782                                 } else {
783                                         ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
784                                         ast_destroy(cfg);
785                                         ast_pthread_mutex_unlock(&iflock);
786                                         unload_module();
787                                         ast_pthread_mutex_unlock(&iflock);
788                                         return -1;
789                                 }
790                 } else if (!strcasecmp(v->name, "driver")) {
791                         snprintf(driver, sizeof(driver), "chan_modem_%s.so", v->value);
792                         if (option_verbose > 1) 
793                                 ast_verbose(VERBOSE_PREFIX_2 "Loading modem driver %s", driver);
794                                 
795                         if (ast_load_resource(driver)) {
796                                 ast_log(LOG_ERROR, "Failed to load driver %s\n", driver);
797                                 ast_destroy(cfg);
798                                 ast_pthread_mutex_unlock(&iflock);
799                                 unload_module();
800                                 return -1;
801                         }
802                 } else if (!strcasecmp(v->name, "mode")) {
803                         if (!strncasecmp(v->value, "ri", 2)) 
804                                 gmode = MODEM_MODE_WAIT_RING;
805                         else if (!strncasecmp(v->value, "im", 2))
806                                 gmode = MODEM_MODE_IMMEDIATE;
807                         else if (!strncasecmp(v->value, "an", 2))
808                                 gmode = MODEM_MODE_WAIT_ANSWER;
809                         else
810                                 ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
811                 } else if (!strcasecmp(v->name, "stripmsd")) {
812                         stripmsd = atoi(v->value);
813                 } else if (!strcasecmp(v->name, "type")) {
814                         strncpy(mtype, v->value, sizeof(mtype));
815                 } else if (!strcasecmp(v->name, "initstr")) {
816                         strncpy(initstr, v->value, sizeof(initstr));
817                 } else if (!strcasecmp(v->name, "dialtype")) {
818                         dialtype = toupper(v->value[0]);
819                 } else if (!strcasecmp(v->name, "context")) {
820                         strncpy(context, v->value, sizeof(context));
821                 } else if (!strcasecmp(v->name, "msn")) {
822                         strncpy(msn, v->value, sizeof(msn));
823                 } else if (!strcasecmp(v->name, "language")) {
824                         strncpy(language, v->value, sizeof(language));
825                 }
826                 v = v->next;
827         }
828         ast_pthread_mutex_unlock(&iflock);
829         if (ast_channel_register(type, tdesc, /* XXX Don't know our types -- maybe we should register more than one XXX */ 
830                                                 AST_FORMAT_SLINEAR, modem_request)) {
831                 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
832                 ast_destroy(cfg);
833                 unload_module();
834                 return -1;
835         }
836         ast_destroy(cfg);
837         /* And start the monitor for the first time */
838         restart_monitor();
839         return 0;
840 }
841
842 int unload_module()
843 {
844         struct ast_modem_pvt *p, *pl;
845         /* First, take us out of the channel loop */
846         ast_channel_unregister(type);
847         if (!ast_pthread_mutex_lock(&iflock)) {
848                 /* Hangup all interfaces if they have an owner */
849                 p = iflist;
850                 while(p) {
851                         if (p->owner)
852                                 ast_softhangup(p->owner);
853                         p = p->next;
854                 }
855                 iflist = NULL;
856                 ast_pthread_mutex_unlock(&iflock);
857         } else {
858                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
859                 return -1;
860         }
861         if (!ast_pthread_mutex_lock(&monlock)) {
862                 if (monitor_thread > -1) {
863                         pthread_cancel(monitor_thread);
864                         pthread_join(monitor_thread, NULL);
865                 }
866                 monitor_thread = -2;
867                 ast_pthread_mutex_unlock(&monlock);
868         } else {
869                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
870                 return -1;
871         }
872
873         if (!ast_pthread_mutex_lock(&iflock)) {
874                 /* Destroy all the interfaces and free their memory */
875                 p = iflist;
876                 while(p) {
877                         /* Close the socket, assuming it's real */
878                         if (p->fd > -1)
879                                 close(p->fd);
880                         pl = p;
881                         p = p->next;
882                         /* Free associated memory */
883                         free(pl);
884                 }
885                 iflist = NULL;
886                 ast_pthread_mutex_unlock(&iflock);
887         } else {
888                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
889                 return -1;
890         }
891                 
892         return 0;
893 }
894
895 int usecount(void)
896 {
897         int res;
898         ast_pthread_mutex_lock(&usecnt_lock);
899         res = usecnt;
900         ast_pthread_mutex_unlock(&usecnt_lock);
901         return res;
902 }
903
904 char *description()
905 {
906         return desc;
907 }
908
909 char *key()
910 {
911         return ASTERISK_GPL_KEY;
912 }
913