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