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