Version 0.1.6 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] = "ATE1Q0";
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         struct ast_modem_pvt *p;
165         int ms = timeout;
166         char rdest[80], *where;
167         strncpy(rdest, idest, sizeof(rdest));
168         strtok(rdest, ":");
169         where = strtok(NULL, ":");
170         if (!where) {
171                 ast_log(LOG_WARNING, "Destination %s requres a real destination (device:destination)\n", idest);
172                 return -1;
173         }
174         p = ast->pvt->pvt;
175         if ((ast->state != AST_STATE_DOWN) && (ast->state != AST_STATE_RESERVED)) {
176                 ast_log(LOG_WARNING, "modem_call called on %s, neither down nor reserved\n", ast->name);
177                 return -1;
178         }
179         if (!strcasecmp(where, "handset")) {
180                 if (p->mc->setdev)
181                         if (p->mc->setdev(p, MODEM_DEV_HANDSET))
182                                 return -1;
183                 /* Should be immediately up */
184                 ast->state = AST_STATE_UP;
185         } else {
186                 if (p->mc->setdev)
187                         if (p->mc->setdev(p, MODEM_DEV_TELCO_SPK))
188                                 return -1;
189                 if (p->mc->dial)
190                         p->mc->dial(p, where + p->stripmsd);
191                 ast->state = AST_STATE_DIALING;
192                 while((ast->state != AST_STATE_UP) && (ms > 0)) {
193                         ms = ast_waitfor(ast, ms);
194                         /* Just read packets and watch what happens */
195                         if (ms > 0) {
196                                 if (!modem_read(ast))
197                                         return -1;
198                         }
199                 }
200                 if (ms < 0)     
201                         return -1;
202         }
203         return 0;
204 }
205
206 int ast_modem_send(struct ast_modem_pvt *p, char *cmd, int len)
207 {
208         int res;
209         if (!len) {
210                 fprintf(p->f, "%s\r\n", cmd);
211                 res = ast_modem_expect(p, cmd, ECHO_TIMEOUT);
212                 if (res) {
213                         ast_log(LOG_WARNING, "Unexpected reply %s\n", p->response);
214                         return -1;
215                 }
216                 return 0;
217         } else {
218                 if (fwrite(cmd, 1, len, p->f) < len)
219                         return -1;
220                 return 0;
221         }
222 }
223
224 int ast_modem_read_response(struct ast_modem_pvt *p, int timeout)
225 {
226         int res = -1;
227         timeout *= 1000;
228         strncpy(p->response, "(No Response)", sizeof(p->response));
229         do {
230                 res = ast_waitfor_n_fd(&p->fd, 1, &timeout);
231                 if (res < 0) {
232                         return -1;
233                 }
234                 /* Read a response */
235                 fgets(p->response, sizeof(p->response), p->f);
236                 return 0;
237         } while(timeout > 0);
238         return -1;
239 }
240
241 int ast_modem_expect(struct ast_modem_pvt *p, char *result, int timeout)
242 {
243         int res = -1;
244         timeout *= 1000;
245         strncpy(p->response, "(No Response)", sizeof(p->response));
246         do {
247                 res = ast_waitfor_n_fd(&p->fd, 1, &timeout);
248                 if (res < 0) {
249                         return -1;
250                 }
251                 /* Read a response */
252                 fgets(p->response, sizeof(p->response), p->f);
253 #if 0
254                 fprintf(stderr, "Modem said: %s", p->response);
255 #endif
256                 if (!strncasecmp(p->response, result, strlen(result))) 
257                         return 0;
258         } while(timeout > 0);
259         return -1;
260 }
261
262 void ast_modem_trim(char *s)
263 {
264         int x;
265         x = strlen(s) - 1;
266         while(x >= 0) {
267                 if ((s[x] != '\r') && (s[x] != '\n') && (s[x] != ' '))
268                         break;
269                 s[x] = '\0';
270                 x--;
271         }
272 }
273
274 static int modem_setup(struct ast_modem_pvt *p, int baudrate)
275 {
276         /* Make sure there's a modem there and that it's in a reasonable 
277            mode.  Set the baud rate, etc.  */
278         char identity[256];
279         char *ident = NULL;
280         char etx[2] = { 0x10, 0x03 };
281         if (option_debug)
282                 ast_log(LOG_DEBUG, "Setting up modem %s\n", p->dev);
283         if (ast_modem_send(p, etx, 2)) {
284                 ast_log(LOG_WARNING, "Failed to send ETX?\n");
285                 return -1;
286         }
287         if (ast_modem_send(p, "\r\n", 2)) {
288                 ast_log(LOG_WARNING, "Failed to send enter?\n");
289                 return -1;
290         }
291         /* Read any outstanding stuff */
292         while(!ast_modem_read_response(p, 0));
293         if (ast_modem_send(p, "ATZ", 0)) {
294                 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev);
295                 return -1;
296         }
297         if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) {
298                 ast_log(LOG_WARNING, "Modem reset failed: %s\n", p->response);
299                 return -1;
300         }
301         if (ast_modem_send(p, p->initstr, 0)) {
302                 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev);
303                 return -1;
304         }
305         if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) {
306                 ast_log(LOG_WARNING, "Modem initialization failed: %s\n", p->response);
307                 return -1;
308         }
309         if (ast_modem_send(p, "ATI3", 0)) {
310                 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev);
311                 return -1;
312         }
313         if (ast_modem_read_response(p, ECHO_TIMEOUT)) {
314                 ast_log(LOG_WARNING, "Modem did not provide identification\n");
315                 return -1;
316         }
317         strncpy(identity, p->response, sizeof(identity));
318         ast_modem_trim(identity);
319         if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) {
320                 ast_log(LOG_WARNING, "Modem did not provide identification\n");
321                 return -1;
322         }
323         if (!strcasecmp(mtype, "autodetect")) {
324                 p->mc = find_capability(identity);
325                 if (!p->mc) {
326                         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); 
327                         return -1;
328                 }
329         } else {
330                 p->mc = find_driver(mtype);
331                 if (!p->mc) {
332                         ast_log(LOG_WARNING, "No driver for modem type '%s'\n", mtype);
333                         return -1;
334                 }
335         }
336         if (p->mc->init) {
337                 if (p->mc->init(p)) {
338                         ast_log(LOG_WARNING, "Modem Initialization Failed on '%s', driver %s.\n", p->dev, p->mc->name);
339                         p->mc->decusecnt();
340                         return -1;
341                 }
342         }                       
343         if (option_verbose > 2) {
344                 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");
345         }
346         if (ident)
347                 free(ident);
348         return 0;
349 }
350
351 static int modem_hangup(struct ast_channel *ast)
352 {
353         struct ast_modem_pvt *p;
354         if (option_debug)
355                 ast_log(LOG_DEBUG, "modem_hangup(%s)\n", ast->name);
356         p = ast->pvt->pvt;
357         /* Hang up */
358         if (p->mc->hangup)
359                 p->mc->hangup(p);
360         /* Re-initialize */
361         if (p->mc->init)
362                 p->mc->init(p);
363         ast->state = AST_STATE_DOWN;
364         memset(p->cid, 0, sizeof(p->cid));
365         ((struct ast_modem_pvt *)(ast->pvt->pvt))->owner = NULL;
366         pthread_mutex_lock(&usecnt_lock);
367         usecnt--;
368         if (usecnt < 0) 
369                 ast_log(LOG_WARNING, "Usecnt < 0???\n");
370         pthread_mutex_unlock(&usecnt_lock);
371         ast_update_use_count();
372         if (option_verbose > 2) 
373                 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
374         ast->pvt->pvt = NULL;
375         ast->state = AST_STATE_DOWN;
376         restart_monitor();
377         return 0;
378 }
379
380 static int modem_answer(struct ast_channel *ast)
381 {
382         struct ast_modem_pvt *p;
383         int res=0;
384         if (option_debug)
385                 ast_log(LOG_DEBUG, "modem_answer(%s)\n", ast->name);
386         p = ast->pvt->pvt;
387         if (p->mc->answer) {
388                 res = p->mc->answer(p);
389         }
390         if (!res) {
391                 ast->rings = 0;
392                 ast->state = AST_STATE_UP;
393         }
394         return res;
395 }
396
397 static char modem_2digit(char c)
398 {
399         if (c == 12)
400                 return '#';
401         else if (c == 11)
402                 return '*';
403         else if ((c < 10) && (c >= 0))
404                 return '0' + c - 1;
405         else
406                 return '?';
407 }
408
409 static struct ast_frame *modem_read(struct ast_channel *ast)
410 {
411         struct ast_modem_pvt *p = ast->pvt->pvt;
412         struct ast_frame *fr=NULL;
413         if (p->mc->read)
414                 fr = p->mc->read(p);
415         return fr;
416 }
417
418 static int modem_write(struct ast_channel *ast, struct ast_frame *frame)
419 {
420         int res=0;
421         struct ast_modem_pvt *p = ast->pvt->pvt;
422         if (p->mc->write)
423                 res = p->mc->write(p, frame);
424         return 0;
425 }
426
427 struct ast_channel *ast_modem_new(struct ast_modem_pvt *i, int state)
428 {
429         struct ast_channel *tmp;
430         tmp = ast_channel_alloc();
431         if (tmp) {
432                 snprintf(tmp->name, sizeof(tmp->name), "Modem[%s]/%s", i->mc->name, i->dev + 5);
433                 tmp->type = type;
434                 tmp->fd = i->fd;
435                 tmp->format = i->mc->formats;
436                 tmp->state = state;
437                 if (state == AST_STATE_RING)
438                         tmp->rings = 1;
439                 tmp->pvt->pvt = i;
440                 tmp->pvt->send_digit = modem_digit;
441                 tmp->pvt->call = modem_call;
442                 tmp->pvt->hangup = modem_hangup;
443                 tmp->pvt->answer = modem_answer;
444                 tmp->pvt->read = modem_read;
445                 tmp->pvt->write = modem_write;
446                 strncpy(tmp->context, i->context, sizeof(tmp->context));
447                 if (strlen(i->cid))
448                         tmp->callerid = strdup(i->cid);
449                 if (strlen(i->language))
450                         strncpy(tmp->language,i->language, sizeof(tmp->language));
451                 i->owner = tmp;
452                 pthread_mutex_lock(&usecnt_lock);
453                 usecnt++;
454                 pthread_mutex_unlock(&usecnt_lock);
455                 ast_update_use_count();
456                 if (state != AST_STATE_DOWN) {
457                         if (ast_pbx_start(tmp)) {
458                                 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
459                                 ast_hangup(tmp);
460                                 tmp = NULL;
461                         }
462                 }
463         } else
464                 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
465         return tmp;
466 }
467
468 static void modem_mini_packet(struct ast_modem_pvt *i)
469 {
470         struct ast_frame *fr;
471         fr = i->mc->read(i);
472         if (fr->frametype == AST_FRAME_CONTROL) {
473                 if (fr->subclass == AST_CONTROL_RING) {
474                         ast_modem_new(i, AST_STATE_RING);
475                 }
476         }
477 }
478
479 static void *do_monitor(void *data)
480 {
481         fd_set rfds, efds;
482         int n, res;
483         struct ast_modem_pvt *i;
484         /* This thread monitors all the frame relay interfaces which are not yet in use
485            (and thus do not have a separate thread) indefinitely */
486         /* From here on out, we die whenever asked */
487 #if 0
488         if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
489                 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
490                 return NULL;
491         }
492 #endif
493         for(;;) {
494                 /* Don't let anybody kill us right away.  Nobody should lock the interface list
495                    and wait for the monitor list, but the other way around is okay. */
496                 if (pthread_mutex_lock(&monlock)) {
497                         ast_log(LOG_ERROR, "Unable to grab monitor lock\n");
498                         return NULL;
499                 }
500                 /* Lock the interface list */
501                 if (pthread_mutex_lock(&iflock)) {
502                         ast_log(LOG_ERROR, "Unable to grab interface lock\n");
503                         pthread_mutex_unlock(&monlock);
504                         return NULL;
505                 }
506                 /* Build the stuff we're going to select on, that is the socket of every
507                    ast_modem_pvt that does not have an associated owner channel */
508                 n = -1;
509                 FD_ZERO(&rfds);
510                 FD_ZERO(&efds);
511                 i = iflist;
512                 while(i) {
513                         if (FD_ISSET(i->fd, &rfds)) 
514                                 ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);
515                         if (!i->owner) {
516                                 /* This needs to be watched, as it lacks an owner */
517                                 FD_SET(i->fd, &rfds);
518                                 FD_SET(i->fd, &efds);
519                                 if (i->fd > n)
520                                         n = i->fd;
521                         }
522                         
523                         i = i->next;
524                 }
525                 /* Okay, now that we know what to do, release the interface lock */
526                 pthread_mutex_unlock(&iflock);
527                 
528                 /* And from now on, we're okay to be killed, so release the monitor lock as well */
529                 pthread_mutex_unlock(&monlock);
530 #if 0
531                 ast_log(LOG_DEBUG, "In monitor, n=%d, pid=%d\n", n, getpid());
532 #endif
533                 /* Wait indefinitely for something to happen */
534                 pthread_testcancel();
535                 res = select(n + 1, &rfds, NULL, &efds, NULL);
536                 pthread_testcancel();
537                 /* Okay, select has finished.  Let's see what happened.  */
538                 if (res < 1) {
539                         ast_log(LOG_WARNING, "select return %d: %s\n", res, strerror(errno));
540                         continue;
541                 }
542                 /* Alright, lock the interface list again, and let's look and see what has
543                    happened */
544                 if (pthread_mutex_lock(&iflock)) {
545                         ast_log(LOG_WARNING, "Unable to lock the interface list\n");
546                         continue;
547                 }
548                 i = iflist;
549                 while(i) {
550                         if (FD_ISSET(i->fd, &rfds) || FD_ISSET(i->fd, &efds)) {
551                                 if (i->owner) {
552                                         ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d, %s)...\n", i->fd, i->dev);
553                                         i = i->next;
554                                         continue;
555                                 }
556                                 modem_mini_packet(i);
557                         }
558                         i=i->next;
559                 }
560                 pthread_mutex_unlock(&iflock);
561         }
562         /* Never reached */
563         return NULL;
564         
565 }
566
567 static int restart_monitor()
568 {
569         /* If we're supposed to be stopped -- stay stopped */
570         if (monitor_thread == -2)
571                 return 0;
572         if (pthread_mutex_lock(&monlock)) {
573                 ast_log(LOG_WARNING, "Unable to lock monitor\n");
574                 return -1;
575         }
576         if (monitor_thread == pthread_self()) {
577                 pthread_mutex_unlock(&monlock);
578                 ast_log(LOG_WARNING, "Cannot kill myself\n");
579                 return -1;
580         }
581         if (monitor_thread != -1) {
582                 pthread_cancel(monitor_thread);
583                 /* Nudge it a little, as it's probably stuck in select */
584                 pthread_kill(monitor_thread, SIGURG);
585                 pthread_join(monitor_thread, NULL);
586         }
587         /* Start a new monitor */
588         if (pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
589                 pthread_mutex_unlock(&monlock);
590                 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
591                 return -1;
592         }
593         pthread_mutex_unlock(&monlock);
594         return 0;
595 }
596
597 static void stty(struct ast_modem_pvt *p)
598 {
599         struct termios mode;
600         memset(&mode, 0, sizeof(mode));
601         if (tcgetattr(p->fd, &mode)) {
602                 ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", p->dev, strerror(errno));
603                 return;
604         }
605         cfmakeraw(&mode);
606         cfsetspeed(&mode, B115200);
607         if (tcsetattr(p->fd, TCSANOW, &mode)) 
608                 ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", p->dev, strerror(errno));
609         
610 }
611
612 static struct ast_modem_pvt *mkif(char *iface)
613 {
614         /* Make a ast_modem_pvt structure for this interface */
615         struct ast_modem_pvt *tmp;
616 #if 0
617         int flags;      
618 #endif
619         
620         tmp = malloc(sizeof(struct ast_modem_pvt));
621         memset(tmp, 0, sizeof(struct ast_modem_pvt));
622         if (tmp) {
623                 tmp->fd = open(iface, O_RDWR | O_NONBLOCK);
624                 if (tmp->fd < 0) {
625                         ast_log(LOG_WARNING, "Unable to open '%s'\n", iface);
626                         free(tmp);
627                         return NULL;
628                 }
629                 strncpy(tmp->language, language, sizeof(tmp->language));
630                 strncpy(tmp->msn, msn, sizeof(tmp->msn));
631                 strncpy(tmp->dev, iface, sizeof(tmp->dev));
632                 /* Maybe in the future we want to allow variable
633                    serial settings */
634                 stty(tmp);
635                 tmp->f = fdopen(tmp->fd, "w+");
636                 /* Disable buffering */
637                 setvbuf(tmp->f, NULL, _IONBF,0);
638                 if (tmp->f < 0) {
639                         ast_log(LOG_WARNING, "Unable to fdopen '%s'\n", iface);
640                         free(tmp);
641                         return NULL;
642                 }
643 #if 0
644                 flags = fcntl(tmp->fd, F_GETFL);
645                 fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK);
646 #endif
647                 tmp->owner = NULL;
648                 tmp->ministate = 0;
649                 tmp->stripmsd = stripmsd;
650                 tmp->dialtype = dialtype;
651                 tmp->mode = gmode;
652                 memset(tmp->cid, 0, sizeof(tmp->cid));
653                 strncpy(tmp->context, context, sizeof(tmp->context));
654                 strncpy(tmp->initstr, initstr, sizeof(tmp->initstr));
655                 tmp->next = NULL;
656                 tmp->obuflen = 0;
657                 
658                 if (modem_setup(tmp, baudrate) < 0) {
659                         ast_log(LOG_WARNING, "Unable to configure modem '%s'\n", iface);
660                         free(tmp);
661                         return NULL;
662                 }
663         }
664         return tmp;
665 }
666
667 static struct ast_channel *modem_request(char *type, int format, void *data)
668 {
669         int oldformat;
670         struct ast_modem_pvt *p;
671         struct ast_channel *tmp = NULL;
672         char dev[80];
673         strncpy(dev, (char *)data, sizeof(dev));
674         strtok(dev, ":");
675         oldformat = format;
676         /* Search for an unowned channel */
677         if (pthread_mutex_lock(&iflock)) {
678                 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
679                 return NULL;
680         }
681         p = iflist;
682         while(p) {
683                 if (!strcmp(dev, p->dev + 5)) {
684                         if (p->mc->formats & format) {
685                                 if (!p->owner) {
686                                         tmp = ast_modem_new(p, AST_STATE_DOWN);
687                                         restart_monitor();
688                                         break;
689                                 } else
690                                         ast_log(LOG_WARNING, "Device '%s' is busy\n", p->dev);
691                         } else 
692                                 ast_log(LOG_WARNING, "Asked for a format %d line on %s\n", format, p->dev);
693                         break;
694                 }
695                 p = p->next;
696         }
697         if (!p) 
698                 ast_log(LOG_WARNING, "Requested device '%s' does not exist\n", p->dev);
699         
700         pthread_mutex_unlock(&iflock);
701         return tmp;
702 }
703
704 int load_module()
705 {
706         struct ast_config *cfg;
707         struct ast_variable *v;
708         struct ast_modem_pvt *tmp;
709         char driver[80];
710         cfg = ast_load(config);
711
712         /* We *must* have a config file otherwise stop immediately */
713         if (!cfg) {
714                 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
715                 return -1;
716         }
717         if (pthread_mutex_lock(&iflock)) {
718                 /* It's a little silly to lock it, but we mind as well just to be sure */
719                 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
720                 return -1;
721         }
722         v = ast_variable_browse(cfg, "interfaces");
723         while(v) {
724                 /* Create the interface list */
725                 if (!strcasecmp(v->name, "device")) {
726                                 tmp = mkif(v->value);
727                                 if (tmp) {
728                                         tmp->next = iflist;
729                                         iflist = tmp;
730                                         
731                                 } else {
732                                         ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
733                                         ast_destroy(cfg);
734                                         pthread_mutex_unlock(&iflock);
735                                         unload_module();
736                                         pthread_mutex_unlock(&iflock);
737                                         return -1;
738                                 }
739                 } else if (!strcasecmp(v->name, "driver")) {
740                         snprintf(driver, sizeof(driver), "chan_modem_%s.so", v->value);
741                         if (option_verbose > 1) 
742                                 ast_verbose(VERBOSE_PREFIX_2 "Loading modem driver %s", driver);
743                                 
744                         if (ast_load_resource(driver)) {
745                                 ast_log(LOG_ERROR, "Failed to load driver %s\n", driver);
746                                 ast_destroy(cfg);
747                                 pthread_mutex_unlock(&iflock);
748                                 unload_module();
749                                 return -1;
750                         }
751                 } else if (!strcasecmp(v->name, "mode")) {
752                         if (!strncasecmp(v->value, "ri", 2)) 
753                                 gmode = MODEM_MODE_WAIT_RING;
754                         else if (!strncasecmp(v->value, "im", 2))
755                                 gmode = MODEM_MODE_IMMEDIATE;
756                         else if (!strncasecmp(v->value, "an", 2))
757                                 gmode = MODEM_MODE_WAIT_ANSWER;
758                         else
759                                 ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
760                 } else if (!strcasecmp(v->name, "stripmsd")) {
761                         stripmsd = atoi(v->value);
762                 } else if (!strcasecmp(v->name, "type")) {
763                         strncpy(mtype, v->value, sizeof(mtype));
764                 } else if (!strcasecmp(v->name, "initstr")) {
765                         strncpy(initstr, v->value, sizeof(initstr));
766                 } else if (!strcasecmp(v->name, "dialtype")) {
767                         dialtype = toupper(v->value[0]);
768                 } else if (!strcasecmp(v->name, "context")) {
769                         strncpy(context, v->value, sizeof(context));
770                 } else if (!strcasecmp(v->name, "msn")) {
771                         strncpy(msn, v->value, sizeof(msn));
772                 } else if (!strcasecmp(v->name, "language")) {
773                         strncpy(language, v->value, sizeof(language));
774                 }
775                 v = v->next;
776         }
777         pthread_mutex_unlock(&iflock);
778         if (ast_channel_register(type, tdesc, /* XXX Don't know our types -- maybe we should register more than one XXX */ 
779                                                 AST_FORMAT_SLINEAR, modem_request)) {
780                 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
781                 ast_destroy(cfg);
782                 unload_module();
783                 return -1;
784         }
785         ast_destroy(cfg);
786         /* And start the monitor for the first time */
787         restart_monitor();
788         return 0;
789 }
790
791 int unload_module()
792 {
793         struct ast_modem_pvt *p, *pl;
794         /* First, take us out of the channel loop */
795         ast_channel_unregister(type);
796         if (!pthread_mutex_lock(&iflock)) {
797                 /* Hangup all interfaces if they have an owner */
798                 p = iflist;
799                 while(p) {
800                         if (p->owner)
801                                 ast_softhangup(p->owner);
802                         p = p->next;
803                 }
804                 iflist = NULL;
805                 pthread_mutex_unlock(&iflock);
806         } else {
807                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
808                 return -1;
809         }
810         if (!pthread_mutex_lock(&monlock)) {
811                 if (monitor_thread > -1) {
812                         pthread_cancel(monitor_thread);
813                         pthread_join(monitor_thread, NULL);
814                 }
815                 monitor_thread = -2;
816                 pthread_mutex_unlock(&monlock);
817         } else {
818                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
819                 return -1;
820         }
821
822         if (!pthread_mutex_lock(&iflock)) {
823                 /* Destroy all the interfaces and free their memory */
824                 p = iflist;
825                 while(p) {
826                         /* Close the socket, assuming it's real */
827                         if (p->fd > -1)
828                                 close(p->fd);
829                         pl = p;
830                         p = p->next;
831                         /* Free associated memory */
832                         free(pl);
833                 }
834                 iflist = NULL;
835                 pthread_mutex_unlock(&iflock);
836         } else {
837                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
838                 return -1;
839         }
840                 
841         return 0;
842 }
843
844 int usecount(void)
845 {
846         int res;
847         pthread_mutex_lock(&usecnt_lock);
848         res = usecnt;
849         pthread_mutex_unlock(&usecnt_lock);
850         return res;
851 }
852
853 char *description()
854 {
855         return desc;
856 }
857