Version 0.1.3 from FTP
[asterisk/asterisk.git] / channels / chan_vofr.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Implementation of Voice over Frame Relay, Adtran Style
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 <sys/socket.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <arpa/inet.h>
29 #include <linux/if_packet.h>
30 #include <linux/if_ether.h>
31 #ifndef OLD_SANGOMA_API
32 #include <linux/if_wanpipe.h>
33 #include <linux/wanpipe.h>
34 #endif
35 #include <sys/signal.h>
36 #include "adtranvofr.h"
37
38 /* #define VOFRDUMPER */
39
40 #define G723_MAX_BUF 2048
41
42 #define FR_API_MESS 16
43
44 static char *desc = "Adtran Voice over Frame Relay";
45 static char *type = "AdtranVoFR";
46 static char *tdesc = "Voice over Frame Relay/Adtran style";
47 static char *config = "adtranvofr.conf";
48
49 static char context[AST_MAX_EXTENSION] = "default";
50
51 static char language[MAX_LANGUAGE] = "";
52
53 static int usecnt =0;
54 static pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER;
55
56 /* Protect the interface list (of vofr_pvt's) */
57 static pthread_mutex_t iflock = PTHREAD_MUTEX_INITIALIZER;
58
59 /* Protect the monitoring thread, so only one process can kill or start it, and not
60    when it's doing something critical. */
61 static pthread_mutex_t monlock = PTHREAD_MUTEX_INITIALIZER;
62
63 /* This is the thread for the monitor which checks for input on the channels
64    which are not currently in use.  */
65 static pthread_t monitor_thread = 0;
66
67 static int restart_monitor(void);
68
69 /* The private structures of the Adtran VoFR channels are linked for
70    selecting outgoing channels */
71    
72 static struct vofr_pvt {
73         int s;                                                  /* Raw socket for this DLCI */
74 #ifdef OLD_SANGOMA_API
75         struct sockaddr_pkt sa;                 /* Sockaddr needed for sending, also has iface name */
76 #else
77         struct wan_sockaddr_ll sa;              /* Wanpipe sockaddr */
78 #endif
79         struct ast_channel *owner;              /* Channel we belong to, possibly NULL */
80         int outgoing;                                   /* Does this channel support outgoing calls? */
81         struct vofr_pvt *next;                  /* Next channel in list */
82         struct vofr_hdr *hdr;                           /* VOFR header version of buf */
83         struct vofr_hdr *ohdr;
84         u_int8_t dlcih;                                 /* High two bits of DLCI */
85         u_int8_t dlcil;                                 /* Bottom two bits of DLCI */
86         u_int8_t cid;                                   /* Call ID */
87         char buf[G723_MAX_BUF];                                 /* Static buffer for reading frames */
88         char obuf[G723_MAX_BUF];                                /* Output buffer */
89         char context[AST_MAX_EXTENSION];
90         char language[MAX_LANGUAGE];
91         int ringgothangup;                              /* Have we received exactly one hangup after a ring */
92 } *iflist = NULL;
93
94 #ifdef VOFRDUMPER
95
96 /* Some useful debugging routines */
97
98 static char *set(int val)
99 {
100         return (val ? "Set  " : "Unset");
101 }
102
103 static char *controlstr(int control)
104 {
105         switch(control) {
106         case VOFR_CONTROL_ADTRAN:
107                 return "Adtran Proprietary";
108         case VOFR_CONTROL_VOICE:
109                 return "Voice";
110         case VOFR_CONTROL_RFC1490:
111                 return "RFC 1490";
112         }
113         return "Unknown";
114 }
115
116 static char *dtypestr(int control)
117 {
118         switch(control) {
119         case VOFR_TYPE_SIGNAL:
120                 return "Signal Frame";
121         case VOFR_TYPE_VOICE:
122                 return "Voice Frame";
123         case VOFR_TYPE_ANSWER:
124                 return "Answer Tone";
125         case VOFR_TYPE_FAX:     
126                 return "FAX";
127         case VOFR_TYPE_DTMF:
128                 return "DTMF Digit";
129         }
130         return "Unknown";
131 }
132
133 static char *vflagsstr(int flags)
134 {
135         static char buf[80];
136         buf[0] = '\0';
137         if (!flags)
138                 return "(None)";
139         if (flags & VOFR_ROUTE_LOCAL)
140                 strcat(buf, "Local ");
141         if (flags & VOFR_ROUTE_VOICE)
142                 strcat(buf, "Voice ");
143         if (flags & VOFR_ROUTE_DTE)
144                 strcat(buf, "DTE ");
145         else if (flags & VOFR_ROUTE_DTE1)
146                 strcat(buf, "DTE1 ");
147         else if (flags & VOFR_ROUTE_DTE2)       
148                 strcat(buf, "DTE2 ");
149         return buf;
150 }
151
152 static char *remidstr(int remid)
153 {
154         switch(remid) {
155         case VOFR_CARD_TYPE_UNSPEC:
156                 return "Unspecified";
157         case VOFR_CARD_TYPE_FXS:
158                 return "FXS";
159         case VOFR_CARD_TYPE_FXO:
160                 return "FXO";
161         case VOFR_CARD_TYPE_ENM:        
162                 return "E&M";
163         case VOFR_CARD_TYPE_VCOM:       
164                 return "Atlas/VCOM";
165         }
166         return "Unknown";
167 }
168
169 static char *modulationstr(int modulation)
170 {
171         switch(modulation) {
172         case VOFR_MODULATION_SINGLE:
173                 return "Single Frequency";
174         case VOFR_MODULATION_V21:
175                 return "V.21";
176         case VOFR_MODULATION_V27ter_2:
177                 return "V.27 (2400bps)";
178         case VOFR_MODULATION_V27ter_4:
179                 return "V.27 (4800bps)";
180         case VOFR_MODULATION_V29_7:
181                 return "V.29 (7200bps)";
182         case VOFR_MODULATION_V29_9:
183                 return "V.29 (9600bps)";
184         case VOFR_MODULATION_V33_12:
185                 return "V.33 (12000bps)";
186         case VOFR_MODULATION_V33_14:
187                 return "V.33 (14400BPS)";
188         }
189         return "Unknown";
190 }
191
192 static char *signalstr(int signal)
193 {
194         switch(signal) {
195         case VOFR_SIGNAL_ON_HOOK:
196                 return "On Hook";
197         case VOFR_SIGNAL_OFF_HOOK:
198                 return "Off Hook";
199         case VOFR_SIGNAL_RING:
200                 return "Ring";
201         case VOFR_SIGNAL_SWITCHED_DIAL:
202                 return "Switched Dial";
203         case VOFR_SIGNAL_BUSY:
204                 return "Busy";
205         case VOFR_SIGNAL_TRUNK_BUSY:
206                 return "Trunk Busy";
207         }
208         return "Unknown";
209 }
210
211 static char *vofr_digitstr(int val)
212 {
213         static char num[5];
214         if (val < 10) {
215                 snprintf(num, sizeof(num), "%d", val);
216                 return num;
217         }
218         switch(val) {
219         case 10:
220                 return "*";
221         case 11:
222                 return "#";
223         }
224         return "Unknown";
225 }
226
227
228 static void vofr_dump_packet(struct vofr_hdr *vh, int len)
229 {
230         printf("VoFR Packet Dump\n");
231         printf("================\n");
232         printf("EI: %s ", set(vh->control & VOFR_MASK_EI));
233         printf("LI: %s\n", set(vh->control & VOFR_MASK_LI));
234         printf("Control: %s (0x%02x)\n", 
235                 controlstr(vh->control & VOFR_MASK_CONTROL), vh->control & VOFR_MASK_CONTROL);
236         printf("Data Type: %s (0x%02x)\n", dtypestr(vh->dtype), vh->dtype);
237         if (vh->dtype == VOFR_TYPE_SIGNAL) {
238                 printf(" \\--Signal: %s (0x%02x)\n", signalstr(vh->data[0]), vh->data[0]);
239         }
240         if (vh->dtype == VOFR_TYPE_DTMF) {
241                 printf(" \\--Digit: %s (0x%02x)\n", vofr_digitstr(vh->data[0]), vh->data[0]);
242         }
243         printf("Connect Tag: 0x%02x\n", vh->ctag);
244         printf("Voice Rt Flags: %s\n", vflagsstr(vh->vflags));
245         printf("DLCI X-Ref: %d\n", (vh->dlcih << 8) | (vh->dlcil));
246         printf("Channel ID: %d\n", vh->cid);
247         printf("Remote ID: %s (0x%02x)\n", remidstr(vh->remid), vh->remid);
248         printf("Modulation: %s (0x%02x)\n", modulationstr(vh->mod), vh->mod);
249         printf("\n");
250         fflush(stdout);
251 }
252
253 #endif
254
255 static int vofr_xmit(struct vofr_pvt *p, char *data, int len)
256 {
257         int res;
258 #ifdef OLD_SANGOMA_API
259     res=sendto(p->s, data, len, 0, (struct sockaddr *)&p->sa, sizeof(struct sockaddr_pkt));
260 #else
261     res=sendto(p->s, data, len, 0, (struct sockaddr *)&p->sa, sizeof(struct wan_sockaddr_ll));
262 #endif
263         if (res != len) {
264                 ast_log(LOG_WARNING, "vofr_xmit returned %d\n", res);
265         }
266         return res;
267 }
268
269 static int vofr_digit(struct ast_channel *ast, char digit)
270 {
271         /*
272          * T H I S   I S   T O T A L L Y   U N D O C U M E N T E D
273          *     A N D   D O E S   N O T   S O U N D   R I G H T
274          *   XXX Figure out how to really send a decent digit XXX
275          */
276         struct vofr_pvt *p;
277         struct vofr_hdr *vh;
278         p = ast->pvt->pvt;
279         vh = p->ohdr;
280         vh->control = VOFR_CONTROL_VOICE;
281         vh->dtype = VOFR_TYPE_DTMF;
282         vh->vflags = VOFR_ROUTE_NONE;
283         vh->dlcih = p->dlcih;
284         vh->dlcil = p->dlcil;
285         vh->cid = p->cid;
286         vh->remid = VOFR_CARD_TYPE_ASTERISK;
287         vh->mod = VOFR_MODULATION_SINGLE;
288         if ((digit >= '0') && (digit <= '9'))
289                 vh->data[0] = digit - '0';
290         else if (digit == '*')
291                 vh->data[0] = 10;
292         else if (digit == '#')
293                 vh->data[0] = 11;
294         else {
295                 ast_log(LOG_WARNING, "%s: tried to dial a non digit '%c'\n", ast->name, digit);
296                 return -1;
297         }
298         vh->data[1] = 0x14;
299         vh->data[2] = 0x1f;
300         vh->data[3] = 0x70;
301                 /* We sorta start the digit */
302         vofr_xmit(p, p->obuf, VOFR_HDR_SIZE + 4 + FR_API_MESS);
303         usleep(30000);
304                 /* And terminate with an empty voice frame */
305         vh->control = VOFR_CONTROL_VOICE;
306         vh->dtype = VOFR_TYPE_VOICE;
307         vh->vflags = VOFR_ROUTE_NONE;
308         vh->dlcih = p->dlcih;
309         vh->dlcil = p->dlcil;
310         vh->cid = p->cid;
311         vh->remid = VOFR_CARD_TYPE_ASTERISK;
312         vh->mod = VOFR_MODULATION_SINGLE;
313         vofr_xmit(p, p->obuf, VOFR_HDR_SIZE + FR_API_MESS);
314         return 0;
315 }
316
317 static int vofr_xmit_signal(struct vofr_pvt *p, int signal, int pad)
318 {
319         /* Prepare and transmit outgoing buffer with given signal and
320            pad the end with *pad* bytes of data presumed to already
321            be in the buffer (like DTMF tones, etc) */
322         struct vofr_hdr *vh = p->ohdr;
323         int res;
324     vh->control = VOFR_CONTROL_VOICE;
325     vh->dtype = VOFR_TYPE_SIGNAL;
326     vh->vflags = VOFR_ROUTE_NONE;
327     vh->dlcih = p->dlcih;
328     vh->dlcil = p->dlcil;
329     vh->cid = p->cid;
330     vh->remid = VOFR_CARD_TYPE_ASTERISK;
331     vh->mod = VOFR_MODULATION_SINGLE;
332     vh->data[0] = signal;
333         if (FR_API_MESS)
334                 memset(p->obuf, 0, FR_API_MESS);
335         res = vofr_xmit(p, p->obuf,  VOFR_HDR_SIZE + pad + 1 + FR_API_MESS);
336         return res;
337
338 }
339
340 static int vofr_call(struct ast_channel *ast, char *dest, int timeout)
341 {
342         int res;
343         int otimeout;
344         struct ast_frame *f;
345         struct vofr_pvt *p;
346         p = ast->pvt->pvt;
347         if ((ast->state != AST_STATE_DOWN) && (ast->state != AST_STATE_RESERVED)) {
348                 ast_log(LOG_WARNING, "vofr_call called on %s, neither down nor reserved\n", ast->name);
349                 return -1;
350         }
351         /* Take the system off hook */
352         vofr_xmit_signal(p, VOFR_SIGNAL_OFFHOOK, 0);
353         /* Wait for an acknowledgement */
354         otimeout = 1000;
355         while(otimeout) {
356                 otimeout = ast_waitfor(ast, 1000);
357                 if (otimeout < 1) {
358                         ast_log(LOG_WARNING, "Unable to take line off hook\n");
359                         /* Musta gotten hung up, or no ack on off hook */
360                         return -1;      
361                 }
362                 f = ast_read(ast);
363                 if (!f)
364                         return -1;
365                 if ((f->frametype == AST_FRAME_CONTROL) &&
366                     (f->subclass == AST_CONTROL_OFFHOOK)) 
367                         /* Off hook */
368                                 break;
369         }
370         if (!otimeout) {
371                 ast_log(LOG_WARNING, "Unable to take line off hook\n");
372                 return -1;
373         }
374         /* Send the digits */
375         while(*dest) {
376                 ast->state = AST_STATE_DIALING;
377                 vofr_digit(ast, *dest);
378                 /* Wait .1 seconds before dialing next digit */
379                 usleep(100000);
380                 dest++;
381         }
382         if (timeout) {
383                 /* Wait for the ack that it's ringing */
384                 otimeout = 1000;
385                 while(otimeout) {
386                         otimeout = ast_waitfor(ast, 1000);
387                         if (otimeout < 1) {
388                                 ast_log(LOG_WARNING, "No acknowledgement for ringing\n");
389                                 /* Musta gotten hung up, or no ack on off hook */
390                                 return -1;      
391                         }
392                         f = ast_read(ast);
393                         if (!f) 
394                                 return -1;
395                         
396                         if (f->frametype == AST_FRAME_CONTROL) {
397                             if (f->subclass == AST_CONTROL_RINGING) {
398                                         ast->state = AST_STATE_RINGING;
399                                         /* We're ringing -- good enough */
400                                         break;
401                                 }
402                                 if (f->subclass == AST_CONTROL_BUSY)
403                                 /* It's busy */
404                                         return -1;
405                         }
406                         ast_frfree(f);
407                 }               
408         }
409         otimeout = timeout;
410         while(timeout) {
411                 /* Wait for an answer, up to timeout... */
412                 res = ast_waitfor(ast, timeout);
413                 if (res < 0)
414                         /* Musta gotten hung up */
415                         return -1;
416                 else
417                         timeout = res;
418                 if (res) {
419                         /* Ooh, read what's there. */
420                         f = ast_read(ast);
421                         if (!f)
422                                 return -1;
423                         if ((f->frametype == AST_FRAME_CONTROL) && 
424                             (f->subclass == AST_CONTROL_ANSWER)) 
425                                 /* Got an answer -- return the # of ms it took */
426                                 return otimeout - res;
427                                 
428                 }
429         }
430         return 0;
431 }
432
433 static int send_hangup(struct vofr_pvt *p)
434 {
435         /* Just send the hangup sequence */
436         return vofr_xmit_signal(p, 0x80, 0);
437 }
438
439 static int vofr_hangup(struct ast_channel *ast)
440 {
441         int res;
442         if (option_debug)
443                 ast_log(LOG_DEBUG, "vofr_hangup(%s)\n", ast->name);
444         if (!ast->pvt->pvt) {
445                 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
446                 return 0;
447         }
448         res = send_hangup(ast->pvt->pvt);
449         if (res < 0) {
450                 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
451                 return -1;
452         }
453         ast->state = AST_STATE_DOWN;
454         ((struct vofr_pvt *)(ast->pvt->pvt))->owner = NULL;
455         ((struct vofr_pvt *)(ast->pvt->pvt))->ringgothangup = 0;
456         pthread_mutex_lock(&usecnt_lock);
457         usecnt--;
458         if (usecnt < 0) 
459                 ast_log(LOG_WARNING, "Usecnt < 0???\n");
460         pthread_mutex_unlock(&usecnt_lock);
461         ast_update_use_count();
462         if (option_verbose > 2) 
463                 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
464         ast->pvt->pvt = NULL;
465         ast->state = AST_STATE_DOWN;
466         restart_monitor();
467         return 0;
468 }
469
470 static int vofr_answer(struct ast_channel *ast)
471 {
472         int res;
473         int cnt = 1000;
474         char buf[2048];
475         struct vofr_hdr *vh;
476         ast->rings = 0;
477         if (option_debug)
478                 ast_log(LOG_DEBUG, "vofr_answer(%s)\n", ast->name);
479         res = vofr_xmit_signal(ast->pvt->pvt, VOFR_SIGNAL_OFFHOOK, 0);
480         if (res < 0)
481                 ast_log(LOG_WARNING, "Unable to anaswer line %s\n", ast->name);
482         ast->state = AST_STATE_UP;
483         while(cnt > 0) {
484                 cnt = ast_waitfor(ast, cnt);
485                 if (cnt > 0) {
486                         res = read(ast->fd, buf, sizeof(buf));
487 #ifdef VOFRDUMPER
488                                 vofr_dump_packet((void *)(buf +FR_API_MESS), res - FR_API_MESS);
489 #endif
490                         res -= FR_API_MESS;
491                         if (res < 0)
492                                 ast_log(LOG_WARNING, "Warning:  read failed (%s) on %s\n", strerror(errno), ast->name);
493                         else {
494                                 /* We're looking for an answer */
495                                 vh = (struct vofr_hdr *)(buf + FR_API_MESS);
496                                 switch(vh->dtype) {
497                                 case VOFR_TYPE_SIGNAL:
498                                         switch(vh->data[0]) {
499                                         case VOFR_SIGNAL_UNKNOWN:
500                                                 switch(vh->data[1]) {
501                                                 case 0x1:
502                                                         if (option_debug) 
503                                                                 ast_log(LOG_DEBUG, "Answered '%s'\n", ast->name);
504                                                         else if (option_verbose > 2) 
505                                                                 ast_verbose( VERBOSE_PREFIX_3 "Answered '%s'\n", ast->name);
506                                                         ast->state = AST_STATE_UP;
507                                                         return 0;
508                                                         break;
509                                                 default:
510                                                         ast_log(LOG_WARNING, "Unexpected 'unknown' frame type %d\n", vh->data[1]);
511                                                 }
512                                                 break;
513                                         case VOFR_SIGNAL_ON_HOOK:
514                                                 /* Ignore onhooks.  */
515                                                 break;
516                                         default:
517                                                 ast_log(LOG_WARNING, "Unexpected signal type %d\n", vh->data[0]);
518                                         }
519                                         break;
520                                 default:
521                                         ast_log(LOG_WARNING, "Unexpected data type %d\n", vh->dtype);
522                                 }
523                         }
524                 }
525         }
526         ast_log(LOG_WARNING, "Did not get acknowledged answer\n");
527         return -1;
528 }
529
530 static char vofr_2digit(char c)
531 {
532         if (c == 11)
533                 return '#';
534         else if (c == 10)
535                 return '*';
536         else if ((c < 10) && (c >= 0))
537                 return '0' + c;
538         else
539                 return '?';
540 }
541
542 static struct ast_frame  *vofr_read(struct ast_channel *ast)
543 {
544         int res;
545         char tone;
546         int timeout,x;
547         struct vofr_pvt *p = ast->pvt->pvt;
548         short *swapping;
549         struct ast_frame *fr = (struct ast_frame *)(p->buf);
550         struct vofr_hdr *vh = (struct vofr_hdr *)(p->buf + sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET - sizeof(struct vofr_hdr));
551         /* Read into the right place in the buffer, in case we send this
552            as a voice frame. */
553         CHECK_BLOCKING(ast);
554         res = read(p->s, ((char *)vh)  - FR_API_MESS, 
555                                 G723_MAX_BUF - AST_FRIENDLY_OFFSET - sizeof(struct ast_frame) + sizeof(struct vofr_hdr) + FR_API_MESS);
556 #ifdef VOFRDUMPER
557         vofr_dump_packet((void *)(vh), res);
558 #endif
559         ast->blocking = 0;
560         res -= FR_API_MESS;             
561         if (res < sizeof(struct vofr_hdr *)) {
562                 ast_log(LOG_WARNING, "Nonsense frame on %s\n", ast->name);
563                 return NULL;
564         }
565
566         /* Some nice norms */
567         fr->datalen = 0;
568         fr->timelen = 0;
569         fr->data =  NULL;
570         fr->src = type;
571         fr->offset = 0;
572         fr->mallocd=0;
573         
574         /* Now, what we do depends on what we read */
575         switch(vh->dtype) {
576         case VOFR_TYPE_SIGNAL:
577                 switch(vh->data[0]) {
578                 case VOFR_SIGNAL_ON_HOOK:
579                         /* Hang up this line */
580                         if ((ast->state == AST_STATE_UP) || (p->ringgothangup)) {
581                                 return NULL;
582                         } else {
583                                 fr->frametype = AST_FRAME_NULL;
584                                 fr->subclass = 0;
585                                 p->ringgothangup=1;
586                         }
587                         break;
588                 case VOFR_SIGNAL_RING:
589                         ast->rings++;
590                         p->ringgothangup = 0;
591                         break;
592                 case VOFR_SIGNAL_UNKNOWN:
593                         switch(vh->data[1]) {
594                         case 0x1:
595                                 /* This is a little tricky, because it depends
596                                    on the context of what state we're in */
597                                 switch(ast->state) {
598                                 case AST_STATE_RINGING:
599                                         fr->frametype = AST_FRAME_CONTROL;
600                                         fr->subclass = AST_CONTROL_ANSWER;
601                                         ast->state = AST_STATE_UP;
602                                         break;
603                                 case AST_STATE_DOWN:
604                                 case AST_STATE_UP:
605                                         fr->frametype = AST_FRAME_NULL;
606                                         fr->subclass = 0;
607                                         break;
608                                 }
609                                 break;
610                         case 0x2:
611                                 /* Remote acknowledged off hook */
612                                 fr->frametype = AST_FRAME_CONTROL;
613                                 fr->subclass = AST_CONTROL_OFFHOOK;
614                                 ast->state = AST_STATE_OFFHOOK;
615                                 break;
616                         case 0x3:
617                                 /* Busy signal */
618                                 fr->frametype = AST_FRAME_CONTROL;
619                                 fr->subclass = AST_CONTROL_BUSY;
620                                 ast->state = AST_STATE_BUSY;
621                                 break;
622                         case 0x5:
623                                 /* Ringing -- acknowledged */
624                                 fr->frametype = AST_FRAME_CONTROL;
625                                 fr->subclass = AST_CONTROL_RINGING;
626                                 ast->state = AST_STATE_RINGING;
627                                 break;
628                         case 0x6:
629                                 /* Hang up detected.  Return NULL */
630                                 return NULL;
631                         default:
632                                 ast_log(LOG_WARNING, "Don't know what to do with 'unknown' signal '%d'\n", vh->data[1]);
633                                 fr->frametype = AST_FRAME_NULL;
634                                 fr->subclass = 0;
635                         }
636                         return fr;
637                         break;
638                 default:
639                         ast_log(LOG_WARNING, "Don't know what to do with signal '%d'\n", vh->data[0]);
640                 }
641                 break;
642         case VOFR_TYPE_DTMF:
643                 /* If it's a DTMF tone, then we want to wait until we don't get any more dtmf tones or
644                    the DTMF tone changes.  
645                        XXX Note: We will drop at least one frame here though XXX */
646                 
647                 tone = vofr_2digit(vh->data[0]);
648                 timeout = 50;
649                 do {
650                         if ((timeout = ast_waitfor(ast, timeout)) < 1)
651                                 break;
652                         CHECK_BLOCKING(ast);
653                         res = read(p->s, ((char *)vh)  - FR_API_MESS, 
654                                         G723_MAX_BUF - AST_FRIENDLY_OFFSET - sizeof(struct ast_frame) + sizeof(struct vofr_hdr) + FR_API_MESS);
655                         ast->blocking = 0;
656                         res -= FR_API_MESS;             
657                         if (res < sizeof(struct vofr_hdr *)) {
658                                 ast_log(LOG_WARNING, "Nonsense frame on %s\n", ast->name);
659                                 return NULL;
660                         }
661                         if (vh->dtype == VOFR_TYPE_DTMF) {
662                                 /* Reset the timeout */
663                                 timeout = 50;
664                                 if ((tone != vofr_2digit(vh->data[0])) )
665                                         /* Or not...  Something else now.. Just send our first frame */
666                                         break;
667                         }
668                         
669                 } while (timeout);
670                 fr->frametype = AST_FRAME_DTMF;
671                 fr->subclass = tone;
672                 fr->datalen = 0;
673                 fr->data = NULL;
674                 fr->offset = 0;
675                 return fr;
676         case VOFR_TYPE_VOICE:
677                 /* XXX Bug in the Adtran: Sometimes we don't know when calls are picked up, so if we
678                        get voice frames, go ahead and consider it answered even though it probably has
679                            not been answered XXX */
680                 if ((ast->state == AST_STATE_RINGING) || (ast->state == AST_STATE_DIALING))  {
681                         ast_log(LOG_DEBUG, "Adtran bug! (state = %d)\n", ast->state);
682                         fr->frametype = AST_FRAME_CONTROL;
683                         fr->subclass = AST_CONTROL_ANSWER;
684                         ast->state = AST_STATE_UP;
685                         return fr;
686                 } else if (ast->state !=  AST_STATE_UP) {
687                         ast_log(LOG_WARNING, "Voice in weird state %d\n", ast->state);
688                 }
689                 fr->frametype = AST_FRAME_VOICE;
690                 fr->subclass = AST_FORMAT_G723_1;
691                 fr->datalen = res - sizeof(struct vofr_hdr);
692                 fr->data = ((char *)vh) + sizeof(struct vofr_hdr);
693                 fr->src = type;
694                 /* XXX Byte swapping is a bug XXX */
695                 swapping = fr->data;
696                 for (x=0;x<fr->datalen/2;x++)
697                         swapping[x] = ntohs(swapping[x]);
698                 fr->offset = AST_FRIENDLY_OFFSET;
699                 /* Thirty ms of sound per frame */
700                 fr->timelen = 30;
701                 return fr;
702         default:
703                 ast_log(LOG_WARNING, "Don't know what to do with data type %d frames\n", vh->dtype);
704         }
705         /* If we don't know what it is, send a NULL frame */
706         fr->frametype = AST_FRAME_NULL;
707         fr->subclass = 0;
708         return fr;
709 }
710
711 static int vofr_write(struct ast_channel *ast, struct ast_frame *frame)
712 {
713         struct vofr_hdr *vh;
714         struct vofr_pvt *p = ast->pvt->pvt;
715         short *swapping;
716     int x;
717         char *start;
718         int res;
719         /* Write a frame of (presumably voice) data */
720         if (frame->frametype != AST_FRAME_VOICE) {
721                 ast_log(LOG_WARNING, "Don't know what to do with  frame type '%d'\n", frame->frametype);
722                 return -1;
723         }
724         if (frame->subclass != AST_FORMAT_G723_1) {
725                 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
726                 return -1;
727         }
728         /* If we get here, we have a voice frame of G.723.1 data.  First check to be
729            sure we have enough headroom for the vofr header.  If there isn't enough
730            headroom, we're lazy and just error out rather than copying it into the
731            output buffer, because applications should always leave AST_FRIENDLY_OFFSET
732            bytes just for this reason. */
733         if (frame->offset < sizeof(struct vofr_hdr) + FR_API_MESS) {
734                 ast_log(LOG_WARNING, "Frame source '%s' didn't provide a friendly enough offset\n", (frame->src ? frame->src : "**Unknown**"));
735                 return -1;
736         }
737         /* XXX Byte swapping is a bug XXX */
738         swapping = frame->data;
739         for (x=0;x<frame->datalen/2;x++)
740                 swapping[x] = ntohs(swapping[x]);
741         vh = (struct vofr_hdr *)(frame->data - sizeof(struct vofr_hdr));
742         /* Some versions of the API have some header mess that needs to be
743            zero'd out and acounted for..  */
744         start = ((void *)vh) - FR_API_MESS;
745         if (start)
746                 memset(start, 0, FR_API_MESS);
747         /* Now we fill in the vofr header */
748         vh->control = VOFR_CONTROL_VOICE;
749         vh->dtype = VOFR_TYPE_VOICE;
750         vh->vflags = VOFR_ROUTE_NONE;
751         vh->dlcih = p->dlcih;
752         vh->dlcil = p->dlcil;
753         vh->cid = p->cid;
754         vh->remid = VOFR_CARD_TYPE_ASTERISK;
755         vh->mod = VOFR_MODULATION_SINGLE;
756         res = vofr_xmit(p, start, 
757                                 VOFR_HDR_SIZE + frame->datalen + FR_API_MESS);
758         res -= FR_API_MESS;
759         /* XXX Byte swapping is a bug, but get it back to the right format XXX */
760         swapping = frame->data;
761         for (x=0;x<frame->datalen/2;x++)
762                 swapping[x] = htons(swapping[x]);
763         if (res != VOFR_HDR_SIZE + frame->datalen) {
764                 ast_log(LOG_WARNING, "Unable to write frame correctly\n");
765                 return -1;
766         }
767         return 0;
768 }
769
770 static struct ast_channel *vofr_new(struct vofr_pvt *i, int state)
771 {
772         struct ast_channel *tmp;
773         tmp = ast_channel_alloc();
774         if (tmp) {
775 #ifdef OLD_SANGOMA_API
776                 snprintf(tmp->name, sizeof(tmp->name), "AdtranVoFR/%s", i->sa.spkt_device);
777 #else
778                 snprintf(tmp->name, sizeof(tmp->name), "AdtranVoFR/%s", i->sa.sll_device);
779 #endif
780                 tmp->type = type;
781                 tmp->fd = i->s;
782                 /* Adtran VoFR supports only G723.1 format data.  G711 (ulaw) would be nice too */
783                 tmp->format = AST_FORMAT_G723_1;
784                 tmp->state = state;
785                 if (state == AST_STATE_RING)
786                         tmp->rings = 1;
787                 tmp->pvt->pvt = i;
788                 tmp->pvt->send_digit = vofr_digit;
789                 tmp->pvt->call = vofr_call;
790                 tmp->pvt->hangup = vofr_hangup;
791                 tmp->pvt->answer = vofr_answer;
792                 tmp->pvt->read = vofr_read;
793                 tmp->pvt->write = vofr_write;
794                 if (strlen(i->language))
795                         strncpy(tmp->language, i->language, sizeof(tmp->language));
796                 i->owner = tmp;
797                 pthread_mutex_lock(&usecnt_lock);
798                 usecnt++;
799                 pthread_mutex_unlock(&usecnt_lock);
800                 ast_update_use_count();
801                 strncpy(tmp->context, i->context, sizeof(tmp->context));
802                 if (state != AST_STATE_DOWN) {
803                         if (ast_pbx_start(tmp)) {
804                                 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
805                                 ast_hangup(tmp);
806                                 tmp = NULL;
807                         }
808                 }
809         } else
810                 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
811         return tmp;
812 }
813
814 static int vofr_mini_packet(struct vofr_pvt *i, struct vofr_hdr *pkt, int len)
815 {
816         /* Here, we're looking for rings or off hooks -- signals that
817            something is about to happen and we need to start the 
818            PBX thread */
819         switch(pkt->dtype) {
820         case VOFR_TYPE_SIGNAL:
821                 switch(pkt->data[0]) {
822                 case VOFR_SIGNAL_RING:
823                         /* If we get a RING, we definitely want to start a new thread */
824                         if (!i->owner) {
825                                 i->ringgothangup = 0;
826                                 vofr_new(i, AST_STATE_RING);
827                         } else
828                                 ast_log(LOG_WARNING, "Got a ring, but there's an owner?\n");
829                         break;
830                 case VOFR_SIGNAL_OFF_HOOK:
831                         /* Network termination, go off hook */
832 #if 0
833                         ast_log(LOG_DEBUG, "Off hook\n");
834 #endif
835                         vofr_xmit_signal(i, 0x10, 2);
836                         if (!i->owner)
837                                 vofr_new(i, AST_STATE_UP);
838                         else
839                                 ast_log(LOG_WARNING, "Got an offhook, but there's an owner?\n");
840                         break;
841                 case VOFR_SIGNAL_ON_HOOK:
842                         break;
843                 case VOFR_SIGNAL_UNKNOWN:
844                         switch(pkt->data[1]) {
845                         case 0x1:
846                                 /* ignore */
847                                 break;
848                         case 0x6:
849                                 /* A remote hangup request */
850                                 if (option_debug)
851                                         ast_log(LOG_DEBUG, "Sending hangup reply\n");
852                                 send_hangup(i);
853                                 break;
854                         default:
855                                 ast_log(LOG_WARNING, "Unexected 'unknown' signal '%d'\n", pkt->data[1]);
856                         }
857                         break;
858                 default:
859                         ast_log(LOG_DEBUG, "Unknown signal type '%d'\n", pkt->data[0]);
860                 }                       
861                 break;
862         case VOFR_TYPE_VOICE:
863                 break;
864         default:
865                 ast_log(LOG_DEBUG, "Unknown packet type '%d'\n", pkt->dtype);
866         }
867         return 0;
868 }
869
870 static void *do_monitor(void *data)
871 {
872         fd_set rfds;
873         int n, res;
874         struct vofr_pvt *i;
875         /* This thread monitors all the frame relay interfaces which are not yet in use
876            (and thus do not have a separate thread) indefinitely */
877         /* From here on out, we die whenever asked */
878 #if 0
879         if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
880                 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
881                 return NULL;
882         }
883 #endif
884         for(;;) {
885                 /* Don't let anybody kill us right away.  Nobody should lock the interface list
886                    and wait for the monitor list, but the other way around is okay. */
887                 if (pthread_mutex_lock(&monlock)) {
888                         ast_log(LOG_ERROR, "Unable to grab monitor lock\n");
889                         return NULL;
890                 }
891                 /* Lock the interface list */
892                 if (pthread_mutex_lock(&iflock)) {
893                         ast_log(LOG_ERROR, "Unable to grab interface lock\n");
894                         pthread_mutex_unlock(&monlock);
895                         return NULL;
896                 }
897                 /* Build the stuff we're going to select on, that is the socket of every
898                    vofr_pvt that does not have an associated owner channel */
899                 n = -1;
900                 FD_ZERO(&rfds);
901                 i = iflist;
902                 while(i) {
903                         if (FD_ISSET(i->s, &rfds)) 
904 #ifdef OLD_SANGOMA_API
905                                 ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->s, i->sa.spkt_device);
906 #else
907                                 ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->s, i->sa.sll_device);
908 #endif
909                         if (!i->owner) {
910                                 /* This needs to be watched, as it lacks an owner */
911                                 FD_SET(i->s, &rfds);
912                                 if (i->s > n)
913                                         n = i->s;
914                         }
915                         i = i->next;
916                 }
917                 /* Okay, now that we know what to do, release the interface lock */
918                 pthread_mutex_unlock(&iflock);
919                 
920                 /* And from now on, we're okay to be killed, so release the monitor lock as well */
921                 pthread_mutex_unlock(&monlock);
922                 pthread_testcancel();
923                 /* Wait indefinitely for something to happen */
924                 res = select(n + 1, &rfds, NULL, NULL, NULL);
925                 pthread_testcancel();
926                 /* Okay, select has finished.  Let's see what happened.  */
927                 if (res < 0) {
928                         if ((errno != EAGAIN) && (errno != EINTR))
929                                 ast_log(LOG_WARNING, "select return %d: %s\n", res, strerror(errno));
930                         continue;
931                 }
932                 /* Alright, lock the interface list again, and let's look and see what has
933                    happened */
934                 if (pthread_mutex_lock(&iflock)) {
935                         ast_log(LOG_WARNING, "Unable to lock the interface list\n");
936                         continue;
937                 }
938                 i = iflist;
939                 while(i) {
940                         if (FD_ISSET(i->s, &rfds)) {
941                                 if (i->owner) {
942 #ifdef OLD_SANGOMA_API
943                                         ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d, %s)...\n", i->s, i->sa.spkt_device);
944 #else
945                                         ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d, %s)...\n", i->s, i->sa.sll_device);
946 #endif
947                                         continue;
948                                 }
949                                 res = read(i->s, i->buf, sizeof(i->buf));
950                                 res -= FR_API_MESS;
951 #ifdef VOFRDUMPER
952                                 vofr_dump_packet(i->hdr, res);
953 #endif
954                                 vofr_mini_packet(i, i->hdr, res);
955                         }
956                         i=i->next;
957                 }
958                 pthread_mutex_unlock(&iflock);
959         }
960         /* Never reached */
961         return NULL;
962         
963 }
964
965 static int restart_monitor(void)
966 {
967         /* If we're supposed to be stopped -- stay stopped */
968         if (monitor_thread == -2)
969                 return 0;
970         if (pthread_mutex_lock(&monlock)) {
971                 ast_log(LOG_WARNING, "Unable to lock monitor\n");
972                 return -1;
973         }
974         if (monitor_thread == pthread_self()) {
975                 pthread_mutex_unlock(&monlock);
976                 ast_log(LOG_WARNING, "Cannot kill myself\n");
977                 return -1;
978         }
979         if (monitor_thread) {
980 #if 0
981                 pthread_cancel(monitor_thread);
982 #endif
983                 pthread_kill(monitor_thread, SIGURG);
984 #if 0
985                 pthread_join(monitor_thread, NULL);
986 #endif
987         }
988         if (!monitor_thread)
989         /* Start a new monitor */
990         if (pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
991                 pthread_mutex_unlock(&monlock);
992                 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
993                 return -1;
994         }
995         pthread_mutex_unlock(&monlock);
996         return 0;
997 }
998
999 static struct vofr_pvt *mkif(char *type, char *iface)
1000 {
1001         /* Make a vofr_pvt structure for this interface */
1002         struct vofr_pvt *tmp;
1003         int sndbuf = 4096;
1004         
1005         tmp = malloc(sizeof(struct vofr_pvt));
1006         if (tmp) {
1007
1008                 /* Allocate a packet socket */
1009 #ifdef OLD_SANGOMA_API
1010                 tmp->s = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL));
1011 #else
1012                 /* Why the HELL does Sangoma change their API every damn time
1013                    they make a new driver release?!?!?!  Leave it the hell
1014                    alone this time.  */
1015                 tmp->s = socket(AF_WANPIPE, SOCK_RAW, 0);
1016 #endif          
1017
1018                 if (tmp->s < 0) {
1019                         ast_log(LOG_ERROR, "Unable to create socket: %s\n", strerror(errno));
1020                         free(tmp);
1021                         return NULL;
1022                 }
1023
1024 #ifdef OLD_SANGOMA_API
1025                 /* Prepare sockaddr for binding */
1026                 memset(&tmp->sa, 0, sizeof(tmp->sa));
1027                 strncpy(tmp->sa.spkt_device, iface, sizeof(tmp->sa.spkt_device));
1028                 tmp->sa.spkt_protocol = htons(0x16);
1029                 tmp->sa.spkt_family = AF_PACKET;
1030                 if (bind(tmp->s, (struct sockaddr *)&tmp->sa, sizeof(struct sockaddr))) {
1031 #else
1032                 /* Prepare sockaddr for binding */
1033                 memset(&tmp->sa, 0, sizeof(tmp->sa));
1034                 tmp->sa.sll_family = AF_WANPIPE;
1035                 tmp->sa.sll_protocol = htons(ETH_P_IP);
1036                 strncpy(tmp->sa.sll_device, iface, sizeof(tmp->sa.sll_device));
1037                 strncpy(tmp->sa.sll_card, "wanpipe1", sizeof(tmp->sa.sll_card));
1038                 tmp->sa.sll_ifindex = 0;
1039                 if (bind(tmp->s, (struct sockaddr *)&tmp->sa, sizeof(struct wan_sockaddr_ll))) {
1040 #endif          
1041                 /* Bind socket to specific interface */
1042 #ifdef OLD_SANGOMA_API
1043                         ast_log(LOG_ERROR, "Unable to bind to '%s': %s\n", tmp->sa.spkt_device, 
1044 #else
1045                         ast_log(LOG_ERROR, "Unable to bind to '%s': %s\n", tmp->sa.sll_device, 
1046 #endif
1047                                                                                 strerror(errno));
1048                         free(tmp);
1049                         return NULL;
1050                 }
1051                 
1052                 /* Set magic send buffer size */
1053                 if (setsockopt(tmp->s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf))) {
1054                         ast_log(LOG_ERROR, "Unable to set send buffer size to %d: %s\n", sndbuf, strerror(errno));
1055                         free(tmp);
1056                         return NULL;
1057                 }
1058                 tmp->owner =  NULL;
1059                 tmp->hdr = (struct vofr_hdr *)(tmp->buf + FR_API_MESS);
1060                 tmp->ohdr = (struct vofr_hdr *)(tmp->obuf + FR_API_MESS);
1061                 tmp->dlcil = 0;
1062                 tmp->dlcih = 0;
1063                 tmp->cid = 1;
1064                 tmp->ringgothangup = 0;
1065                 strncpy(tmp->language, language, sizeof(tmp->language));
1066                 strncpy(tmp->context, context, sizeof(tmp->context));
1067                 /* User terminations are game for outgoing connections */
1068                 if (!strcasecmp(type, "user")) 
1069                         tmp->outgoing = 1;
1070                 else
1071                         tmp->outgoing = 0;
1072                 tmp->next = NULL;
1073                 /* Hang it up to be sure it's good */
1074                 send_hangup(tmp);
1075                 
1076         }
1077         return tmp;
1078 }
1079
1080 static struct ast_channel *vofr_request(char *type, int format, void *data)
1081 {
1082         int oldformat;
1083         struct vofr_pvt *p;
1084         struct ast_channel *tmp = NULL;
1085         /* We can only support G.723.1 formatted frames, but we should never
1086            be asked to support anything else anyway, since we've published
1087            our capabilities when we registered. */
1088         oldformat = format;
1089         format &= AST_FORMAT_G723_1;
1090         if (!format) {
1091                 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
1092                 return NULL;
1093         }
1094         /* Search for an unowned channel */
1095         if (pthread_mutex_lock(&iflock)) {
1096                 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
1097                 return NULL;
1098         }
1099         p = iflist;
1100         while(p) {
1101                 if (!p->owner) {
1102                         tmp = vofr_new(p, AST_STATE_DOWN);
1103                         break;
1104                 }
1105                 p = p->next;
1106         }
1107         pthread_mutex_unlock(&iflock);
1108         restart_monitor();
1109         return tmp;
1110 }
1111
1112 int load_module()
1113 {
1114         struct ast_config *cfg;
1115         struct ast_variable *v;
1116         struct vofr_pvt *tmp;
1117         cfg = ast_load(config);
1118
1119         /* We *must* have a config file otherwise stop immediately */
1120         if (!cfg) {
1121                 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
1122                 return -1;
1123         }
1124         if (pthread_mutex_lock(&iflock)) {
1125                 /* It's a little silly to lock it, but we mind as well just to be sure */
1126                 ast_log(LOG_ERROR, "Unable to lock interface list???\n");
1127                 return -1;
1128         }
1129         v = ast_variable_browse(cfg, "interfaces");
1130         while(v) {
1131                 /* Create the interface list */
1132                 if (!strcasecmp(v->name, "user") ||
1133                         !strcasecmp(v->name, "network")) {
1134                                 tmp = mkif(v->name, v->value);
1135                                 if (tmp) {
1136                                         tmp->next = iflist;
1137                                         iflist = tmp;
1138                                 } else {
1139                                         ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
1140                                         ast_destroy(cfg);
1141                                         pthread_mutex_unlock(&iflock);
1142                                         unload_module();
1143                                         return -1;
1144                                 }
1145                 } else if (!strcasecmp(v->name, "context")) {
1146                         strncpy(context, v->value, sizeof(context));
1147                 } else if (!strcasecmp(v->name, "language")) {
1148                         strncpy(language, v->value, sizeof(language));
1149                 }
1150                 v = v->next;
1151         }
1152         pthread_mutex_unlock(&iflock);
1153         /* Make sure we can register our AdtranVoFR channel type */
1154         if (ast_channel_register(type, tdesc, AST_FORMAT_G723_1, vofr_request)) {
1155                 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
1156                 ast_destroy(cfg);
1157                 unload_module();
1158                 return -1;
1159         }
1160         ast_destroy(cfg);
1161         /* And start the monitor for the first time */
1162         restart_monitor();
1163         return 0;
1164 }
1165
1166 int unload_module()
1167 {
1168         struct vofr_pvt *p, *pl;
1169         /* First, take us out of the channel loop */
1170         ast_channel_unregister(type);
1171         if (!pthread_mutex_lock(&iflock)) {
1172                 /* Hangup all interfaces if they have an owner */
1173                 p = iflist;
1174                 while(p) {
1175                         if (p->owner)
1176                                 ast_softhangup(p->owner);
1177                         p = p->next;
1178                 }
1179                 iflist = NULL;
1180                 pthread_mutex_unlock(&iflock);
1181         } else {
1182                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1183                 return -1;
1184         }
1185         if (!pthread_mutex_lock(&monlock)) {
1186                 if (monitor_thread) {
1187                         pthread_cancel(monitor_thread);
1188                         pthread_kill(monitor_thread, SIGURG);
1189                         pthread_join(monitor_thread, NULL);
1190                 }
1191                 monitor_thread = -2;
1192                 pthread_mutex_unlock(&monlock);
1193         } else {
1194                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1195                 return -1;
1196         }
1197
1198         if (!pthread_mutex_lock(&iflock)) {
1199                 /* Destroy all the interfaces and free their memory */
1200                 p = iflist;
1201                 while(p) {
1202                         /* Close the socket, assuming it's real */
1203                         if (p->s > -1)
1204                                 close(p->s);
1205                         pl = p;
1206                         p = p->next;
1207                         /* Free associated memory */
1208                         free(pl);
1209                 }
1210                 iflist = NULL;
1211                 pthread_mutex_unlock(&iflock);
1212         } else {
1213                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1214                 return -1;
1215         }
1216                 
1217         return 0;
1218 }
1219
1220 int usecount()
1221 {
1222         int res;
1223         pthread_mutex_lock(&usecnt_lock);
1224         res = usecnt;
1225         pthread_mutex_unlock(&usecnt_lock);
1226         return res;
1227 }
1228
1229 char *description()
1230 {
1231         return desc;
1232 }
1233