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