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