Version 0.1.8 from FTP
[asterisk/asterisk.git] / channels / chan_oss.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Use /dev/dsp as a channel, and the console to command it :).
5  *
6  * The full-duplex "simulation" is pretty weak.  This is generally a 
7  * VERY BADLY WRITTEN DRIVER so please don't use it as a model for
8  * writing a driver.
9  * 
10  * Copyright (C) 1999, Mark Spencer
11  *
12  * Mark Spencer <markster@linux-support.net>
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License
16  */
17
18 #include <asterisk/frame.h>
19 #include <asterisk/logger.h>
20 #include <asterisk/channel.h>
21 #include <asterisk/module.h>
22 #include <asterisk/channel_pvt.h>
23 #include <asterisk/options.h>
24 #include <asterisk/pbx.h>
25 #include <asterisk/config.h>
26 #include <asterisk/cli.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <errno.h>
30 #include <sys/ioctl.h>
31 #include <sys/time.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <linux/soundcard.h>
36 #include "busy.h"
37 #include "ringtone.h"
38 #include "ring10.h"
39 #include "answer.h"
40
41 /* Which device to use */
42 #define DEV_DSP "/dev/dsp"
43
44 /* Lets use 160 sample frames, just like GSM.  */
45 #define FRAME_SIZE 160
46
47 /* When you set the frame size, you have to come up with
48    the right buffer format as well. */
49 /* 5 64-byte frames = one frame */
50 #define BUFFER_FMT ((buffersize * 10) << 16) | (0x0006);
51
52 /* Don't switch between read/write modes faster than every 300 ms */
53 #define MIN_SWITCH_TIME 600
54
55 static struct timeval lasttime;
56
57 static int usecnt;
58 static int needanswer = 0;
59 static int needhangup = 0;
60 static int silencesuppression = 0;
61 static int silencethreshold = 1000;
62
63 static char digits[80] = "";
64 static char text2send[80] = "";
65
66 static pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER;
67
68 static char *type = "Console";
69 static char *desc = "OSS Console Channel Driver";
70 static char *tdesc = "OSS Console Channel Driver";
71 static char *config = "oss.conf";
72
73 static char context[AST_MAX_EXTENSION] = "default";
74 static char language[MAX_LANGUAGE] = "";
75 static char exten[AST_MAX_EXTENSION] = "s";
76
77 /* Command pipe */
78 static int cmd[2];
79
80 int hookstate=0;
81
82 static short silence[FRAME_SIZE] = {0, };
83
84 struct sound {
85         int ind;
86         short *data;
87         int datalen;
88         int samplen;
89         int silencelen;
90         int repeat;
91 };
92
93 static struct sound sounds[] = {
94         { AST_CONTROL_RINGING, ringtone, sizeof(ringtone)/2, 16000, 32000, 1 },
95         { AST_CONTROL_BUSY, busy, sizeof(busy)/2, 4000, 4000, 1 },
96         { AST_CONTROL_CONGESTION, busy, sizeof(busy)/2, 2000, 2000, 1 },
97         { AST_CONTROL_RING, ring10, sizeof(ring10)/2, 16000, 32000, 1 },
98         { AST_CONTROL_ANSWER, answer, sizeof(answer)/2, 2200, 0, 0 },
99 };
100
101 /* Sound command pipe */
102 static int sndcmd[2];
103
104 static struct chan_oss_pvt {
105         /* We only have one OSS structure -- near sighted perhaps, but it
106            keeps this driver as simple as possible -- as it should be. */
107         struct ast_channel *owner;
108         char exten[AST_MAX_EXTENSION];
109         char context[AST_MAX_EXTENSION];
110 } oss;
111
112 static int time_has_passed()
113 {
114         struct timeval tv;
115         int ms;
116         gettimeofday(&tv, NULL);
117         ms = (tv.tv_sec - lasttime.tv_sec) * 1000 +
118                         (tv.tv_usec - lasttime.tv_usec) / 1000;
119         if (ms > MIN_SWITCH_TIME)
120                 return -1;
121         return 0;
122 }
123
124 /* Number of buffers...  Each is FRAMESIZE/8 ms long.  For example
125    with 160 sample frames, and a buffer size of 3, we have a 60ms buffer, 
126    usually plenty. */
127
128 pthread_t sthread;
129
130 #define MAX_BUFFER_SIZE 100
131 static int buffersize = 3;
132
133 static int full_duplex = 0;
134
135 /* Are we reading or writing (simulated full duplex) */
136 static int readmode = 1;
137
138 /* File descriptor for sound device */
139 static int sounddev = -1;
140
141 static int autoanswer = 1;
142  
143 static int calc_loudness(short *frame)
144 {
145         int sum = 0;
146         int x;
147         for (x=0;x<FRAME_SIZE;x++) {
148                 if (frame[x] < 0)
149                         sum -= frame[x];
150                 else
151                         sum += frame[x];
152         }
153         sum = sum/FRAME_SIZE;
154         return sum;
155 }
156
157 static int cursound = -1;
158 static int sampsent = 0;
159 static int silencelen=0;
160 static int offset=0;
161 static int nosound=0;
162
163 static int send_sound(void)
164 {
165         short myframe[FRAME_SIZE];
166         int total = FRAME_SIZE;
167         short *frame = NULL;
168         int amt=0;
169         int res;
170         int myoff;
171         audio_buf_info abi;
172         if (cursound > -1) {
173                 res = ioctl(sounddev, SNDCTL_DSP_GETOSPACE ,&abi);
174                 if (res) {
175                         ast_log(LOG_WARNING, "Unable to read output space\n");
176                         return -1;
177                 }
178                 /* Calculate how many samples we can send, max */
179                 if (total > (abi.fragments * abi.fragsize / 2)) 
180                         total = abi.fragments * abi.fragsize / 2;
181                 res = total;
182                 if (sampsent < sounds[cursound].samplen) {
183                         myoff=0;
184                         while(total) {
185                                 amt = total;
186                                 if (amt > (sounds[cursound].datalen - offset)) 
187                                         amt = sounds[cursound].datalen - offset;
188                                 memcpy(myframe + myoff, sounds[cursound].data + offset, amt * 2);
189                                 total -= amt;
190                                 offset += amt;
191                                 sampsent += amt;
192                                 myoff += amt;
193                                 if (offset >= sounds[cursound].datalen)
194                                         offset = 0;
195                         }
196                         /* Set it up for silence */
197                         if (sampsent >= sounds[cursound].samplen) 
198                                 silencelen = sounds[cursound].silencelen;
199                         frame = myframe;
200                 } else {
201                         if (silencelen > 0) {
202                                 frame = silence;
203                                 silencelen -= res;
204                         } else {
205                                 if (sounds[cursound].repeat) {
206                                         /* Start over */
207                                         sampsent = 0;
208                                         offset = 0;
209                                 } else {
210                                         cursound = -1;
211                                         nosound = 0;
212                                 }
213                         }
214                 }
215                 res = write(sounddev, frame, res * 2);
216                 if (res > 0)
217                         return 0;
218                 return res;
219         }
220         return 0;
221 }
222
223 static void *sound_thread(void *unused)
224 {
225         fd_set rfds;
226         fd_set wfds;
227         int max;
228         int res;
229         for(;;) {
230                 FD_ZERO(&rfds);
231                 FD_ZERO(&wfds);
232                 max = sndcmd[0];
233                 FD_SET(sndcmd[0], &rfds);
234                 if (cursound > -1) {
235                         FD_SET(sounddev, &wfds);
236                         if (sounddev > max)
237                                 max = sounddev;
238                 }
239                 res = select(max + 1, &rfds, &wfds, NULL, NULL);
240                 if (res < 1) {
241                         ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
242                         continue;
243                 }
244                 if (FD_ISSET(sndcmd[0], &rfds)) {
245                         read(sndcmd[0], &cursound, sizeof(cursound));
246                         silencelen = 0;
247                         offset = 0;
248                         sampsent = 0;
249                 }
250                 if (FD_ISSET(sounddev, &wfds))
251                         if (send_sound())
252                                 ast_log(LOG_WARNING, "Failed to write sound\n");
253         }
254         /* Never reached */
255         return NULL;
256 }
257
258 #if 0
259 static int silence_suppress(short *buf)
260 {
261 #define SILBUF 3
262         int loudness;
263         static int silentframes = 0;
264         static char silbuf[FRAME_SIZE * 2 * SILBUF];
265         static int silbufcnt=0;
266         if (!silencesuppression)
267                 return 0;
268         loudness = calc_loudness((short *)(buf));
269         if (option_debug)
270                 ast_log(LOG_DEBUG, "loudness is %d\n", loudness);
271         if (loudness < silencethreshold) {
272                 silentframes++;
273                 silbufcnt++;
274                 /* Keep track of the last few bits of silence so we can play
275                    them as lead-in when the time is right */
276                 if (silbufcnt >= SILBUF) {
277                         /* Make way for more buffer */
278                         memmove(silbuf, silbuf + FRAME_SIZE * 2, FRAME_SIZE * 2 * (SILBUF - 1));
279                         silbufcnt--;
280                 }
281                 memcpy(silbuf + FRAME_SIZE * 2 * silbufcnt, buf, FRAME_SIZE * 2);
282                 if (silentframes > 10) {
283                         /* We've had plenty of silence, so compress it now */
284                         return 1;
285                 }
286         } else {
287                 silentframes=0;
288                 /* Write any buffered silence we have, it may have something
289                    important */
290                 if (silbufcnt) {
291                         write(sounddev, silbuf, silbufcnt * FRAME_SIZE);
292                         silbufcnt = 0;
293                 }
294         }
295         return 0;
296 }
297 #endif
298
299 static int setformat(void)
300 {
301         int fmt, desired, res, fd = sounddev;
302         static int warnedalready = 0;
303         static int warnedalready2 = 0;
304         fmt = AFMT_S16_LE;
305         res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt);
306         if (res < 0) {
307                 ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n");
308                 return -1;
309         }
310         res = ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
311         if (res >= 0) {
312                 if (option_verbose > 1) 
313                         ast_verbose(VERBOSE_PREFIX_2 "Console is full duplex\n");
314                 full_duplex = -1;
315         }
316         fmt = 0;
317         res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt);
318         if (res < 0) {
319                 ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
320                 return -1;
321         }
322         /* 8000 Hz desired */
323         desired = 8000;
324         fmt = desired;
325         res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt);
326         if (res < 0) {
327                 ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
328                 return -1;
329         }
330         if (fmt != desired) {
331                 if (!warnedalready++)
332                         ast_log(LOG_WARNING, "Requested %d Hz, got %d Hz -- sound may be choppy\n", desired, fmt);
333         }
334 #if 1
335         fmt = BUFFER_FMT;
336         res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt);
337         if (res < 0) {
338                 if (!warnedalready2++)
339                         ast_log(LOG_WARNING, "Unable to set fragment size -- sound may be choppy\n");
340         }
341 #endif
342         return 0;
343 }
344
345 static int soundcard_setoutput(int force)
346 {
347         /* Make sure the soundcard is in output mode.  */
348         int fd = sounddev;
349         if (full_duplex || (!readmode && !force))
350                 return 0;
351         readmode = 0;
352         if (force || time_has_passed()) {
353                 ioctl(sounddev, SNDCTL_DSP_RESET);
354                 /* Keep the same fd reserved by closing the sound device and copying stdin at the same
355                    time. */
356                 /* dup2(0, sound); */ 
357                 close(sounddev);
358                 fd = open(DEV_DSP, O_WRONLY |O_NONBLOCK);
359                 if (fd < 0) {
360                         ast_log(LOG_WARNING, "Unable to re-open DSP device: %s\n", strerror(errno));
361                         return -1;
362                 }
363                 /* dup2 will close the original and make fd be sound */
364                 if (dup2(fd, sounddev) < 0) {
365                         ast_log(LOG_WARNING, "dup2() failed: %s\n", strerror(errno));
366                         return -1;
367                 }
368                 if (setformat()) {
369                         return -1;
370                 }
371                 return 0;
372         }
373         return 1;
374 }
375
376 static int soundcard_setinput(int force)
377 {
378         int fd = sounddev;
379         if (full_duplex || (readmode && !force))
380                 return 0;
381         readmode = -1;
382         if (force || time_has_passed()) {
383                 ioctl(sounddev, SNDCTL_DSP_RESET);
384                 close(sounddev);
385                 /* dup2(0, sound); */
386                 fd = open(DEV_DSP, O_RDONLY | O_NONBLOCK);
387                 if (fd < 0) {
388                         ast_log(LOG_WARNING, "Unable to re-open DSP device: %s\n", strerror(errno));
389                         return -1;
390                 }
391                 /* dup2 will close the original and make fd be sound */
392                 if (dup2(fd, sounddev) < 0) {
393                         ast_log(LOG_WARNING, "dup2() failed: %s\n", strerror(errno));
394                         return -1;
395                 }
396                 if (setformat()) {
397                         return -1;
398                 }
399                 return 0;
400         }
401         return 1;
402 }
403
404 static int soundcard_init()
405 {
406         /* Assume it's full duplex for starters */
407         int fd = open(DEV_DSP,  O_RDWR | O_NONBLOCK);
408         if (fd < 0) {
409                 ast_log(LOG_WARNING, "Unable to open %s: %s\n", DEV_DSP, strerror(errno));
410                 return fd;
411         }
412         gettimeofday(&lasttime, NULL);
413         sounddev = fd;
414         setformat();
415         if (!full_duplex) 
416                 soundcard_setinput(1);
417         return sounddev;
418 }
419
420 static int oss_digit(struct ast_channel *c, char digit)
421 {
422         ast_verbose( " << Console Received digit %c >> \n", digit);
423         return 0;
424 }
425
426 static int oss_text(struct ast_channel *c, char *text)
427 {
428         ast_verbose( " << Console Received text %s >> \n", text);
429         return 0;
430 }
431
432 static int oss_call(struct ast_channel *c, char *dest, int timeout)
433 {
434         int res = 3;
435         ast_verbose( " << Call placed to '%s' on console >> \n", dest);
436         if (autoanswer) {
437                 ast_verbose( " << Auto-answered >> \n" );
438                 needanswer = 1;
439         } else {
440                 ast_verbose( " << Type 'answer' to answer, or use 'autoanswer' for future calls >> \n");
441                 write(sndcmd[1], &res, sizeof(res));
442         }
443         return 0;
444 }
445
446 static void answer_sound(void)
447 {
448         int res;
449         nosound = 1;
450         res = 4;
451         write(sndcmd[1], &res, sizeof(res));
452         
453 }
454
455 static int oss_answer(struct ast_channel *c)
456 {
457         ast_verbose( " << Console call has been answered >> \n");
458         answer_sound();
459         c->state = AST_STATE_UP;
460         cursound = -1;
461         return 0;
462 }
463
464 static int oss_hangup(struct ast_channel *c)
465 {
466         int res;
467         cursound = -1;
468         c->pvt->pvt = NULL;
469         oss.owner = NULL;
470         ast_verbose( " << Hangup on console >> \n");
471         ast_pthread_mutex_lock(&usecnt_lock);
472         usecnt--;
473         ast_pthread_mutex_unlock(&usecnt_lock);
474         needhangup = 0;
475         needanswer = 0;
476         if (hookstate) {
477                 res = 2;
478                 write(sndcmd[1], &res, sizeof(res));
479         }
480         return 0;
481 }
482
483 static int soundcard_writeframe(short *data)
484 {       
485         /* Write an exactly FRAME_SIZE sized of frame */
486         static int bufcnt = 0;
487         static short buffer[FRAME_SIZE * MAX_BUFFER_SIZE * 5];
488         struct audio_buf_info info;
489         int res;
490         int fd = sounddev;
491         static int warned=0;
492         if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info)) {
493                 if (!warned)
494                         ast_log(LOG_WARNING, "Error reading output space\n");
495                 bufcnt = buffersize;
496                 warned++;
497         }
498         if ((info.fragments >= buffersize * 5) && (bufcnt == buffersize)) {
499                 /* We've run out of stuff, buffer again */
500                 bufcnt = 0;
501         }
502         if (bufcnt == buffersize) {
503                 /* Write sample immediately */
504                 res = write(fd, ((void *)data), FRAME_SIZE * 2);
505         } else {
506                 /* Copy the data into our buffer */
507                 res = FRAME_SIZE * 2;
508                 memcpy(buffer + (bufcnt * FRAME_SIZE), data, FRAME_SIZE * 2);
509                 bufcnt++;
510                 if (bufcnt == buffersize) {
511                         res = write(fd, ((void *)buffer), FRAME_SIZE * 2 * buffersize);
512                 }
513         }
514         return res;
515 }
516
517
518 static int oss_write(struct ast_channel *chan, struct ast_frame *f)
519 {
520         int res;
521         static char sizbuf[8000];
522         static int sizpos = 0;
523         int len = sizpos;
524         int pos;
525         /* Immediately return if no sound is enabled */
526         if (nosound)
527                 return 0;
528         /* Stop any currently playing sound */
529         cursound = -1;
530         if (!full_duplex && (strlen(digits) || needhangup || needanswer)) {
531                 /* If we're half duplex, we have to switch to read mode
532                    to honor immediate needs if necessary */
533                 res = soundcard_setinput(1);
534                 if (res < 0) {
535                         ast_log(LOG_WARNING, "Unable to set device to input mode\n");
536                         return -1;
537                 }
538                 return 0;
539         }
540         res = soundcard_setoutput(0);
541         if (res < 0) {
542                 ast_log(LOG_WARNING, "Unable to set output device\n");
543                 return -1;
544         } else if (res > 0) {
545                 /* The device is still in read mode, and it's too soon to change it,
546                    so just pretend we wrote it */
547                 return 0;
548         }
549         /* We have to digest the frame in 160-byte portions */
550         if (f->datalen > sizeof(sizbuf) - sizpos) {
551                 ast_log(LOG_WARNING, "Frame too large\n");
552                 return -1;
553         }
554         memcpy(sizbuf + sizpos, f->data, f->datalen);
555         len += f->datalen;
556         pos = 0;
557         while(len - pos > FRAME_SIZE * 2) {
558                 soundcard_writeframe((short *)(sizbuf + pos));
559                 pos += FRAME_SIZE * 2;
560         }
561         if (len - pos) 
562                 memmove(sizbuf, sizbuf + pos, len - pos);
563         sizpos = len - pos;
564         return 0;
565 }
566
567 static struct ast_frame *oss_read(struct ast_channel *chan)
568 {
569         static struct ast_frame f;
570         static char buf[FRAME_SIZE * 2 + AST_FRIENDLY_OFFSET];
571         static int readpos = 0;
572         int res;
573         int b;
574         int nonull=0;
575         
576 #if 0
577         ast_log(LOG_DEBUG, "oss_read()\n");
578 #endif
579         
580         /* Acknowledge any pending cmd */
581         res = read(cmd[0], &b, sizeof(b));
582         if (res > 0)
583                 nonull = 1;
584         
585         f.frametype = AST_FRAME_NULL;
586         f.subclass = 0;
587         f.timelen = 0;
588         f.datalen = 0;
589         f.data = NULL;
590         f.offset = 0;
591         f.src = type;
592         f.mallocd = 0;
593         
594         if (needhangup) {
595                 return NULL;
596         }
597         if (strlen(text2send)) {
598                 f.frametype = AST_FRAME_TEXT;
599                 f.subclass = 0;
600                 f.data = text2send;
601                 f.datalen = strlen(text2send);
602                 strcpy(text2send,"");
603                 return &f;
604         }
605         if (strlen(digits)) {
606                 f.frametype = AST_FRAME_DTMF;
607                 f.subclass = digits[0];
608                 for (res=0;res<strlen(digits);res++)
609                         digits[res] = digits[res + 1];
610                 return &f;
611         }
612         
613         if (needanswer) {
614                 needanswer = 0;
615                 f.frametype = AST_FRAME_CONTROL;
616                 f.subclass = AST_CONTROL_ANSWER;
617                 chan->state = AST_STATE_UP;
618                 return &f;
619         }
620         
621         if (nonull)
622                 return &f;
623                 
624         res = soundcard_setinput(0);
625         if (res < 0) {
626                 ast_log(LOG_WARNING, "Unable to set input mode\n");
627                 return NULL;
628         }
629         if (res > 0) {
630                 /* Theoretically shouldn't happen, but anyway, return a NULL frame */
631                 return &f;
632         }
633         res = read(sounddev, buf + AST_FRIENDLY_OFFSET + readpos, FRAME_SIZE * 2 - readpos);
634         if (res < 0) {
635                 ast_log(LOG_WARNING, "Error reading from sound device: %s\n", strerror(errno));
636                 CRASH;
637                 return NULL;
638         }
639         readpos += res;
640         
641         if (readpos >= FRAME_SIZE * 2) {
642                 /* A real frame */
643                 readpos = 0;
644                 f.frametype = AST_FRAME_VOICE;
645                 f.subclass = AST_FORMAT_SLINEAR;
646                 f.timelen = FRAME_SIZE / 8;
647                 f.datalen = FRAME_SIZE * 2;
648                 f.data = buf + AST_FRIENDLY_OFFSET;
649                 f.offset = AST_FRIENDLY_OFFSET;
650                 f.src = type;
651                 f.mallocd = 0;
652 #if 0
653                 { static int fd = -1;
654                   if (fd < 0)
655                         fd = open("output.raw", O_RDWR | O_TRUNC | O_CREAT);
656                   write(fd, f.data, f.datalen);
657                 }
658 #endif          
659         }
660         return &f;
661 }
662
663 static int oss_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
664 {
665         struct chan_oss_pvt *p = newchan->pvt->pvt;
666         p->owner = newchan;
667         return 0;
668 }
669
670 static int oss_indicate(struct ast_channel *chan, int cond)
671 {
672         int res;
673         switch(cond) {
674         case AST_CONTROL_BUSY:
675                 res = 1;
676                 break;
677         case AST_CONTROL_CONGESTION:
678                 res = 2;
679                 break;
680         case AST_CONTROL_RINGING:
681                 res = 0;
682                 break;
683         default:
684                 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, chan->name);
685                 return -1;
686         }
687         if (res > -1) {
688                 write(sndcmd[1], &res, sizeof(res));
689         }
690         return 0;       
691 }
692
693 static struct ast_channel *oss_new(struct chan_oss_pvt *p, int state)
694 {
695         struct ast_channel *tmp;
696         tmp = ast_channel_alloc();
697         if (tmp) {
698                 snprintf(tmp->name, sizeof(tmp->name), "OSS/%s", DEV_DSP + 5);
699                 tmp->type = type;
700                 tmp->fds[0] = sounddev;
701                 tmp->fds[1] = cmd[0];
702                 tmp->nativeformats = AST_FORMAT_SLINEAR;
703                 tmp->pvt->pvt = p;
704                 tmp->pvt->send_digit = oss_digit;
705                 tmp->pvt->send_text = oss_text;
706                 tmp->pvt->hangup = oss_hangup;
707                 tmp->pvt->answer = oss_answer;
708                 tmp->pvt->read = oss_read;
709                 tmp->pvt->call = oss_call;
710                 tmp->pvt->write = oss_write;
711                 tmp->pvt->indicate = oss_indicate;
712                 tmp->pvt->fixup = oss_fixup;
713                 if (strlen(p->context))
714                         strncpy(tmp->context, p->context, sizeof(tmp->context));
715                 if (strlen(p->exten))
716                         strncpy(tmp->exten, p->exten, sizeof(tmp->exten));
717                 if (strlen(language))
718                         strncpy(tmp->language, language, sizeof(tmp->language));
719                 p->owner = tmp;
720                 tmp->state = state;
721                 ast_pthread_mutex_lock(&usecnt_lock);
722                 usecnt++;
723                 ast_pthread_mutex_unlock(&usecnt_lock);
724                 ast_update_use_count();
725                 if (state != AST_STATE_DOWN) {
726                         if (ast_pbx_start(tmp)) {
727                                 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
728                                 ast_hangup(tmp);
729                                 tmp = NULL;
730                         }
731                 }
732         }
733         return tmp;
734 }
735
736 static struct ast_channel *oss_request(char *type, int format, void *data)
737 {
738         int oldformat = format;
739         struct ast_channel *tmp;
740         format &= AST_FORMAT_SLINEAR;
741         if (!format) {
742                 ast_log(LOG_NOTICE, "Asked to get a channel of format '%d'\n", oldformat);
743                 return NULL;
744         }
745         if (oss.owner) {
746                 ast_log(LOG_NOTICE, "Already have a call on the OSS channel\n");
747                 return NULL;
748         }
749         tmp= oss_new(&oss, AST_STATE_DOWN);
750         if (!tmp) {
751                 ast_log(LOG_WARNING, "Unable to create new OSS channel\n");
752         }
753         return tmp;
754 }
755
756 static int console_autoanswer(int fd, int argc, char *argv[])
757 {
758         if ((argc != 1) && (argc != 2))
759                 return RESULT_SHOWUSAGE;
760         if (argc == 1) {
761                 ast_cli(fd, "Auto answer is %s.\n", autoanswer ? "on" : "off");
762                 return RESULT_SUCCESS;
763         } else {
764                 if (!strcasecmp(argv[1], "on"))
765                         autoanswer = -1;
766                 else if (!strcasecmp(argv[1], "off"))
767                         autoanswer = 0;
768                 else
769                         return RESULT_SHOWUSAGE;
770         }
771         return RESULT_SUCCESS;
772 }
773
774 static char *autoanswer_complete(char *line, char *word, int pos, int state)
775 {
776 #ifndef MIN
777 #define MIN(a,b) ((a) < (b) ? (a) : (b))
778 #endif
779         switch(state) {
780         case 0:
781                 if (strlen(word) && !strncasecmp(word, "on", MIN(strlen(word), 2)))
782                         return strdup("on");
783         case 1:
784                 if (strlen(word) && !strncasecmp(word, "off", MIN(strlen(word), 3)))
785                         return strdup("off");
786         default:
787                 return NULL;
788         }
789         return NULL;
790 }
791
792 static char autoanswer_usage[] =
793 "Usage: autoanswer [on|off]\n"
794 "       Enables or disables autoanswer feature.  If used without\n"
795 "       argument, displays the current on/off status of autoanswer.\n"
796 "       The default value of autoanswer is in 'oss.conf'.\n";
797
798 static int console_answer(int fd, int argc, char *argv[])
799 {
800         if (argc != 1)
801                 return RESULT_SHOWUSAGE;
802         if (!oss.owner) {
803                 ast_cli(fd, "No one is calling us\n");
804                 return RESULT_FAILURE;
805         }
806         hookstate = 1;
807         cursound = -1;
808         needanswer++;
809         answer_sound();
810         return RESULT_SUCCESS;
811 }
812
813 static char sendtext_usage[] =
814 "Usage: send text <message>\n"
815 "       Sends a text message for display on the remote terminal.\n";
816
817 static int console_sendtext(int fd, int argc, char *argv[])
818 {
819         int tmparg = 1;
820         if (argc < 1)
821                 return RESULT_SHOWUSAGE;
822         if (!oss.owner) {
823                 ast_cli(fd, "No one is calling us\n");
824                 return RESULT_FAILURE;
825         }
826         if (strlen(text2send))
827                 ast_cli(fd, "Warning: message already waiting to be sent, overwriting\n");
828         strcpy(text2send, "");
829         while(tmparg <= argc) {
830                 strncat(text2send, argv[tmparg++], sizeof(text2send) - strlen(text2send));
831                 strncat(text2send, " ", sizeof(text2send) - strlen(text2send));
832         }
833         needanswer++;
834         return RESULT_SUCCESS;
835 }
836
837 static char answer_usage[] =
838 "Usage: answer\n"
839 "       Answers an incoming call on the console (OSS) channel.\n";
840
841 static int console_hangup(int fd, int argc, char *argv[])
842 {
843         if (argc != 1)
844                 return RESULT_SHOWUSAGE;
845         cursound = -1;
846         if (!oss.owner && !hookstate) {
847                 ast_cli(fd, "No call to hangup up\n");
848                 return RESULT_FAILURE;
849         }
850         hookstate = 0;
851         if (oss.owner)
852                 needhangup++;
853         return RESULT_SUCCESS;
854 }
855
856 static char hangup_usage[] =
857 "Usage: hangup\n"
858 "       Hangs up any call currently placed on the console.\n";
859
860
861 static int console_dial(int fd, int argc, char *argv[])
862 {
863         char tmp[256], *tmp2;
864         char *mye, *myc;
865         int b = 0;
866         if ((argc != 1) && (argc != 2))
867                 return RESULT_SHOWUSAGE;
868         if (oss.owner) {
869                 if (argc == 2) {
870                         strncat(digits, argv[1], sizeof(digits) - strlen(digits));
871                         /* Wake up the polling thread */
872                         write(cmd[1], &b, sizeof(b));
873                 } else {
874                         ast_cli(fd, "You're already in a call.  You can use this only to dial digits until you hangup\n");
875                         return RESULT_FAILURE;
876                 }
877                 return RESULT_SUCCESS;
878         }
879         mye = exten;
880         myc = context;
881         if (argc == 2) {
882                 strncpy(tmp, argv[1], sizeof(tmp));
883                 strtok(tmp, "@");
884                 tmp2 = strtok(NULL, "@");
885                 if (strlen(tmp))
886                         mye = tmp;
887                 if (tmp2 && strlen(tmp2))
888                         myc = tmp2;
889         }
890         if (ast_exists_extension(NULL, myc, mye, 1)) {
891                 strncpy(oss.exten, mye, sizeof(oss.exten));
892                 strncpy(oss.context, myc, sizeof(oss.context));
893                 hookstate = 1;
894                 oss_new(&oss, AST_STATE_UP);
895         } else
896                 ast_cli(fd, "No such extension '%s' in context '%s'\n", mye, myc);
897         return RESULT_SUCCESS;
898 }
899
900 static char dial_usage[] =
901 "Usage: dial [extension[@context]]\n"
902 "       Dials a given extensison (";
903
904
905 static struct ast_cli_entry myclis[] = {
906         { { "answer", NULL }, console_answer, "Answer an incoming console call", answer_usage },
907         { { "hangup", NULL }, console_hangup, "Hangup a call on the console", hangup_usage },
908         { { "dial", NULL }, console_dial, "Dial an extension on the console", dial_usage },
909         { { "send text", NULL }, console_sendtext, "Send text to the remote device", sendtext_usage },
910         { { "autoanswer", NULL }, console_autoanswer, "Sets/displays autoanswer", autoanswer_usage, autoanswer_complete }
911 };
912
913 int load_module()
914 {
915         int res;
916         int x;
917         int flags;
918         struct ast_config *cfg = ast_load(config);
919         struct ast_variable *v;
920         res = pipe(cmd);
921         res = pipe(sndcmd);
922         if (res) {
923                 ast_log(LOG_ERROR, "Unable to create pipe\n");
924                 return -1;
925         }
926         flags = fcntl(cmd[0], F_GETFL);
927         fcntl(cmd[0], F_SETFL, flags | O_NONBLOCK);
928         flags = fcntl(cmd[1], F_GETFL);
929         fcntl(cmd[1], F_SETFL, flags | O_NONBLOCK);
930         res = soundcard_init();
931         if (res < 0) {
932                 close(cmd[1]);
933                 close(cmd[0]);
934                 if (option_verbose > 1) {
935                         ast_verbose(VERBOSE_PREFIX_2 "No sound card detected -- console channel will be unavailable\n");
936                         ast_verbose(VERBOSE_PREFIX_2 "Turn off OSS support by adding 'noload=chan_oss.so' in /etc/asterisk/modules.conf\n");
937                 }
938                 return 0;
939         }
940         if (!full_duplex)
941                 ast_log(LOG_WARNING, "XXX I don't work right with non-full duplex sound cards XXX\n");
942         res = ast_channel_register(type, tdesc, AST_FORMAT_SLINEAR, oss_request);
943         if (res < 0) {
944                 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", type);
945                 return -1;
946         }
947         for (x=0;x<sizeof(myclis)/sizeof(struct ast_cli_entry); x++)
948                 ast_cli_register(myclis + x);
949         if (cfg) {
950                 v = ast_variable_browse(cfg, "general");
951                 while(v) {
952                         if (!strcasecmp(v->name, "autoanswer"))
953                                 autoanswer = ast_true(v->value);
954                         else if (!strcasecmp(v->name, "silencesuppression"))
955                                 silencesuppression = ast_true(v->value);
956                         else if (!strcasecmp(v->name, "silencethreshold"))
957                                 silencethreshold = atoi(v->value);
958                         else if (!strcasecmp(v->name, "context"))
959                                 strncpy(context, v->value, sizeof(context));
960                         else if (!strcasecmp(v->name, "language"))
961                                 strncpy(language, v->value, sizeof(language));
962                         else if (!strcasecmp(v->name, "extension"))
963                                 strncpy(exten, v->value, sizeof(exten));
964                         v=v->next;
965                 }
966                 ast_destroy(cfg);
967         }
968         pthread_create(&sthread, NULL, sound_thread, NULL);
969         return 0;
970 }
971
972
973
974 int unload_module()
975 {
976         int x;
977         for (x=0;x<sizeof(myclis)/sizeof(struct ast_cli_entry); x++)
978                 ast_cli_unregister(myclis + x);
979         close(sounddev);
980         if (cmd[0] > 0) {
981                 close(cmd[0]);
982                 close(cmd[1]);
983         }
984         if (sndcmd[0] > 0) {
985                 close(sndcmd[0]);
986                 close(sndcmd[1]);
987         }
988         if (oss.owner)
989                 ast_softhangup(oss.owner);
990         if (oss.owner)
991                 return -1;
992         return 0;
993 }
994
995 char *description()
996 {
997         return desc;
998 }
999
1000 int usecount()
1001 {
1002         int res;
1003         ast_pthread_mutex_lock(&usecnt_lock);
1004         res = usecnt;
1005         ast_pthread_mutex_unlock(&usecnt_lock);
1006         return res;
1007 }
1008
1009 char *key()
1010 {
1011         return ASTERISK_GPL_KEY;
1012 }