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