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