Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:51 2009

## Asterisk developer's documentation

# chan_oss.c

Go to the documentation of this file.

    00001 /*
    00002  * Asterisk -- An open source telephony toolkit.
    00003  *
    00004  * Copyright (C) 1999 - 2005, Digium, Inc.
    00005  *
    00006  * Mark Spencer <markster@digium.com>
    00007  *
    00008  * FreeBSD changes and multiple device support by Luigi Rizzo, 2005.05.25
    00009  * note-this code best seen with ts=8 (8-spaces tabs) in the editor
    00010  *
    00011  * See http://www.asterisk.org for more information about
    00012  * the Asterisk project. Please do not directly contact
    00013  * any of the maintainers of this project for assistance;
    00014  * the project provides a web site, mailing lists and IRC
    00015  * channels for your use.
    00016  *
    00017  * This program is free software, distributed under the terms of
    00018  * the GNU General Public License Version 2. See the LICENSE file
    00019  * at the top of the source tree.
    00020  */
    00021
    00022 /*! \file
    00023  *
    00024  * \brief Channel driver for OSS sound cards
    00025  *
    00026  * \par See also
    00027  * \arg \ref Config_oss
    00028  *
    00029  * \ingroup channel_drivers
    00030  */
    00031
    00032 #include <stdio.h>
    00033 #include <ctype.h>   /* for isalnum */
    00034 #include <string.h>
    00035 #include <unistd.h>
    00036 #include <sys/ioctl.h>
    00037 #include <fcntl.h>
    00038 #include <sys/time.h>
    00039 #include <stdlib.h>
    00040 #include <errno.h>
    00041
    00042
    00043 #ifdef __linux
    00044 #include <linux/soundcard.h>
    00045 #elif defined(__FreeBSD__)
    00046 #include <sys/soundcard.h>
    00047 #else
    00048 #include <soundcard.h>
    00049 #endif
    00050
    00051 #include "asterisk.h"
    00052
    00053 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 36998 $")
    00054
    00055 #include "asterisk/lock.h"
    00056 #include "asterisk/frame.h"
    00057 #include "asterisk/logger.h"
    00058 #include "asterisk/channel.h"
    00059 #include "asterisk/module.h"
    00060 #include "asterisk/options.h"
    00061 #include "asterisk/pbx.h"
    00062 #include "asterisk/config.h"
    00063
    00064 #include "asterisk/cli.h"
    00065 #include "asterisk/utils.h"
    00066 #include "asterisk/causes.h"
    00067 #include "asterisk/endian.h"
    00068
    00069 /* ringtones we use */
    00070 #include "busy.h"
    00071 #include "ringtone.h"
    00072 #include "ring10.h"
    00073 #include "answer.h"
    00074
    00075 /*
    00076  * Basic mode of operation:
    00077  *
    00078  * we have one keyboard (which receives commands from the keyboard)
    00079  * and multiple headset's connected to audio cards.
    00080  * Cards/Headsets are named as the sections of oss.conf.
    00081  * The section called [general] contains the default parameters.
    00082  *
    00083  * At any time, the keyboard is attached to one card, and you
    00084  * can switch among them using the command 'console foo'
    00085  * where 'foo' is the name of the card you want.
    00086  *
    00087  * oss.conf parameters are
    00088
    00089 [general]
    00090 ; general config options, default values are shown
    00091 ; all but debug can go also in the device-specific sections.
    00092 ; debug=0x0    ; misc debug flags, default is 0
    00093
    00094 [card1]
    00095 ; autoanswer = no ; no autoanswer on call
    00096 ; autohangup = yes   ; hangup when other party closes
    00097 ; extension=s     ; default extension to call
    00098 ; context=default ; default context
    00099 ; language=""     ; default language
    00100 ; overridecontext=yes   ; the whole dial string is considered an extension.
    00101          ; if no, the last @ will start the context
    00102
    00103 ; device=/dev/dsp ; device to open
    00104 ; mixer="-f /dev/mixer0 pcm 80 ; mixer command to run on start
    00105 ; queuesize=10    ; frames in device driver
    00106 ; frags=8      ; argument to SETFRAGMENT
    00107
    00108 .. and so on for the other cards.
    00109
    00110  */
    00111
    00112 /*
    00113  * Helper macros to parse config arguments. They will go in a common
    00114  * header file if their usage is globally accepted. In the meantime,
    00115  * we define them here. Typical usage is as below.
    00116  * Remember to open a block right before M_START (as it declares
    00117  * some variables) and use the M_* macros WITHOUT A SEMICOLON:
    00118  *
    00119  * {
    00120  *    M_START(v->name, v->value)
    00121  *
    00122  *    M_BOOL("dothis", x->flag1)
    00123  *    M_STR("name", x->somestring)
    00124  *    M_F("bar", some_c_code)
    00125  *    M_END(some_final_statement)
    00126  *    ... other code in the block
    00127  * }
    00128  *
    00129  * XXX NOTE these macros should NOT be replicated in other parts of asterisk.
    00130  * Likely we will come up with a better way of doing config file parsing.
    00131  */
    00132 #define M_START(var, val) \
    00133         char *__s = var; char *__val = val;
    00134 #define M_END(x)   x;
    00135 #define M_F(tag, f)        if (!strcasecmp((__s), tag)) { f; } else
    00136 #define M_BOOL(tag, dst)   M_F(tag, (dst) = ast_true(__val) )
    00137 #define M_UINT(tag, dst)   M_F(tag, (dst) = strtoul(__val, NULL, 0) )
    00138 #define M_STR(tag, dst)    M_F(tag, ast_copy_string(dst, __val, sizeof(dst)))
    00139
    00140 /*
    00141  * The following parameters are used in the driver:
    00142  *
    00143  *  FRAME_SIZE the size of an audio frame, in samples.
    00144  *    160 is used almost universally, so you should not change it.
    00145  *
    00146  *  FRAGS   the argument for the SETFRAGMENT ioctl.
    00147  *    Overridden by the 'frags' parameter in oss.conf
    00148  *
    00149  *    Bits 0-7 are the base-2 log of the device's block size,
    00150  *    bits 16-31 are the number of blocks in the driver's queue.
    00151  *    There are a lot of differences in the way this parameter
    00152  *    is supported by different drivers, so you may need to
    00153  *    experiment a bit with the value.
    00154  *    A good default for linux is 30 blocks of 64 bytes, which
    00155  *    results in 6 frames of 320 bytes (160 samples).
    00156  *    FreeBSD works decently with blocks of 256 or 512 bytes,
    00157  *    leaving the number unspecified.
    00158  *    Note that this only refers to the device buffer size,
    00159  *    this module will then try to keep the lenght of audio
    00160  *    buffered within small constraints.
    00161  *
    00162  *  QUEUE_SIZE The max number of blocks actually allowed in the device
    00163  *    driver's buffer, irrespective of the available number.
    00164  *    Overridden by the 'queuesize' parameter in oss.conf
    00165  *
    00166  *    Should be >=2, and at most as large as the hw queue above
    00167  *    (otherwise it will never be full).
    00168  */
    00169
    00170 #define FRAME_SIZE   160
    00171 #define  QUEUE_SIZE  10
    00172
    00173 #if defined(__FreeBSD__)
    00174 #define  FRAGS 0x8
    00175 #else
    00176 #define  FRAGS ( ( (6 * 5) << 16 ) | 0x6 )
    00177 #endif
    00178
    00179 /*
    00180  * XXX text message sizes are probably 256 chars, but i am
    00181  * not sure if there is a suitable definition anywhere.
    00182  */
    00183 #define TEXT_SIZE 256
    00184
    00185 #if 0
    00186 #define  TRYOPEN  1  /* try to open on startup */
    00187 #endif
    00188 #define  O_CLOSE  0x444 /* special 'close' mode for device */
    00189 /* Which device to use */
    00190 #if defined( __OpenBSD__ ) || defined( __NetBSD__ )
    00191 #define DEV_DSP "/dev/audio"
    00192 #else
    00193 #define DEV_DSP "/dev/dsp"
    00194 #endif
    00195
    00196 #ifndef MIN
    00197 #define MIN(a,b) ((a) < (b) ? (a) : (b))
    00198 #endif
    00199 #ifndef MAX
    00200 #define MAX(a,b) ((a) > (b) ? (a) : (b))
    00201 #endif
    00202
    00203
    00204 static int usecnt;
    00205 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
    00206
    00207 static char *config = "oss.conf";   /* default config file */
    00208
    00209 static int oss_debug;
    00210
    00211 /*
    00212  * Each sound is made of 'datalen' samples of sound, repeated as needed to
    00213  * generate 'samplen' samples of data, then followed by 'silencelen' samples
    00214  * of silence. The loop is repeated if 'repeat' is set.
    00215  */
    00216 struct sound {
    00217    int ind;
    00218    char *desc;
    00219    short *data;
    00220    int datalen;
    00221    int samplen;
    00222    int silencelen;
    00223    int repeat;
    00224 };
    00225
    00226 static struct sound sounds[] = {
    00227    { AST_CONTROL_RINGING, "RINGING", ringtone, sizeof(ringtone)/2, 16000, 32000, 1 },
    00228    { AST_CONTROL_BUSY, "BUSY", busy, sizeof(busy)/2, 4000, 4000, 1 },
    00229    { AST_CONTROL_CONGESTION, "CONGESTION", busy, sizeof(busy)/2, 2000, 2000, 1 },
    00230    { AST_CONTROL_RING, "RING10", ring10, sizeof(ring10)/2, 16000, 32000, 1 },
    00231    { AST_CONTROL_ANSWER, "ANSWER", answer, sizeof(answer)/2, 2200, 0, 0 },
    00232    { -1, NULL, 0, 0, 0, 0 },  /* end marker */
    00233 };
    00234
    00235
    00236 /*
    00237  * descriptor for one of our channels.
    00238  * There is one used for 'default' values (from the [general] entry in
    00239  * the configuration file), and then one instance for each device
    00240  * (the default is cloned from [general], others are only created
    00241  * if the relevant section exists).
    00242  */
    00243 struct chan_oss_pvt {
    00244    struct chan_oss_pvt *next;
    00245
    00246    char *type; /* XXX maybe take the one from oss_tech */
    00247    char *name;
    00248    /*
    00249     * cursound indicates which in struct sound we play. -1 means nothing,
    00250     * any other value is a valid sound, in which case sampsent indicates
    00251     * the next sample to send in [0..samplen + silencelen]
    00252     * nosound is set to disable the audio data from the channel
    00253     * (so we can play the tones etc.).
    00254     */
    00255    int sndcmd[2]; /* Sound command pipe */
    00256    int cursound;  /* index of sound to send */
    00257    int sampsent;  /* # of sound samples sent */
    00258    int nosound;   /* set to block audio from the PBX */
    00259
    00260    int total_blocks; /* total blocks in the output device */
    00261    int sounddev;
    00262    enum { M_UNSET, M_FULL, M_READ, M_WRITE } duplex;
    00263    int autoanswer;
    00264    int autohangup;
    00265    int hookstate;
    00266    char *mixer_cmd;     /* initial command to issue to the mixer */
    00267    unsigned int   queuesize;  /* max fragments in queue */
    00268    unsigned int   frags;      /* parameter for SETFRAGMENT */
    00269
    00270    int warned;    /* various flags used for warnings */
    00271 #define WARN_used_blocks   1
    00272 #define WARN_speed      2
    00273 #define WARN_frag    4
    00274    int w_errors;  /* overfull in the write path */
    00275    struct timeval lastopen;
    00276
    00277    int overridecontext;
    00278    int mute;
    00279    char device[64];  /* device to open */
    00280
    00281    pthread_t sthread;
    00282
    00283    struct ast_channel *owner;
    00284    char ext[AST_MAX_EXTENSION];
    00285    char ctx[AST_MAX_CONTEXT];
    00286    char language[MAX_LANGUAGE];
    00287
    00288    /* buffers used in oss_write */
    00289    char oss_write_buf[FRAME_SIZE*2];
    00290    int oss_write_dst;
    00291    /* buffers used in oss_read - AST_FRIENDLY_OFFSET space for headers
    00292     * plus enough room for a full frame
    00293     */
    00294    char oss_read_buf[FRAME_SIZE * 2 + AST_FRIENDLY_OFFSET];
    00295    int readpos; /* read position above */
    00296    struct ast_frame read_f;   /* returned by oss_read */
    00297 };
    00298
    00299 static struct chan_oss_pvt oss_default = {
    00300    .type = "Console",
    00301    .cursound = -1,
    00302    .sounddev = -1,
    00303    .duplex = M_UNSET, /* XXX check this */
    00304    .autoanswer = 1,
    00305    .autohangup = 1,
    00306    .queuesize = QUEUE_SIZE,
    00307    .frags = FRAGS,
    00308    .ext = "s",
    00309    .ctx = "default",
    00310    .readpos = AST_FRIENDLY_OFFSET,  /* start here on reads */
    00311    .lastopen = { 0, 0 },
    00312 };
    00313
    00314 static char *oss_active;    /* the active device */
    00315
    00316 static int setformat(struct chan_oss_pvt *o, int mode);
    00317
    00318 static struct ast_channel *oss_request(const char *type, int format, void *data
    00319 , int *cause);
    00320 static int oss_digit(struct ast_channel *c, char digit);
    00321 static int oss_text(struct ast_channel *c, const char *text);
    00322 static int oss_hangup(struct ast_channel *c);
    00323 static int oss_answer(struct ast_channel *c);
    00324 static struct ast_frame *oss_read(struct ast_channel *chan);
    00325 static int oss_call(struct ast_channel *c, char *dest, int timeout);
    00326 static int oss_write(struct ast_channel *chan, struct ast_frame *f);
    00327 static int oss_indicate(struct ast_channel *chan, int cond);
    00328 static int oss_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
    00329
    00330 static const struct ast_channel_tech oss_tech = {
    00331    .type =        "Console",
    00332    .description = "OSS Console Channel Driver",
    00333    .capabilities =   AST_FORMAT_SLINEAR,
    00334    .requester =   oss_request,
    00335    .send_digit =  oss_digit,
    00336    .send_text =   oss_text,
    00337    .hangup =      oss_hangup,
    00338    .answer =      oss_answer,
    00339    .read =        oss_read,
    00340    .call =        oss_call,
    00341    .write =    oss_write,
    00342    .indicate =    oss_indicate,
    00343    .fixup =    oss_fixup,
    00344 };
    00345
    00346 /*
    00347  * returns a pointer to the descriptor with the given name
    00348  */
    00349 static struct chan_oss_pvt *find_desc(char *dev)
    00350 {
    00351    struct chan_oss_pvt *o;
    00352
    00353    for (o = oss_default.next; o && strcmp(o->name, dev) != 0; o = o->next)
    00354       ;
    00355    if (o == NULL)
    00356       ast_log(LOG_WARNING, "could not find <%s>\n", dev);
    00357    return o;
    00358 }
    00359
    00360 /*
    00361  * split a string in extension-context, returns pointers to malloc'ed
    00362  * strings.
    00363  * If we do not have 'overridecontext' then the last @ is considered as
    00364  * a context separator, and the context is overridden.
    00365  * This is usually not very necessary as you can play with the dialplan,
    00366  * and it is nice not to need it because you have '@' in SIP addresses.
    00367  * Return value is the buffer address.
    00368  */
    00369 static char *ast_ext_ctx(const char *src, char **ext, char **ctx)
    00370 {
    00371    struct chan_oss_pvt *o = find_desc(oss_active);
    00372
    00373    if (ext == NULL || ctx == NULL)
    00374       return NULL;   /* error */
    00375    *ext = *ctx = NULL;
    00376    if (src && *src != '\0')
    00377       *ext = strdup(src);
    00378    if (*ext == NULL)
    00379       return NULL;
    00380    if (!o->overridecontext) {
    00381       /* parse from the right */
    00382       *ctx = strrchr(*ext, '@');
    00383       if (*ctx)
    00384          *(*ctx)++ = '\0';
    00385    }
    00386    return *ext;
    00387 }
    00388
    00389 /*
    00390  * Returns the number of blocks used in the audio output channel
    00391  */
    00392 static int used_blocks(struct chan_oss_pvt *o)
    00393 {
    00394    struct audio_buf_info info;
    00395
    00396    if (ioctl(o->sounddev, SNDCTL_DSP_GETOSPACE, &info)) {
    00397       if (! (o->warned & WARN_used_blocks)) {
    00398          ast_log(LOG_WARNING, "Error reading output space\n");
    00399          o->warned |= WARN_used_blocks;
    00400       }
    00401       return 1;
    00402    }
    00403    if (o->total_blocks == 0) {
    00404       if (0) /* debugging */
    00405          ast_log(LOG_WARNING, "fragtotal %d size %d avail %d\n",
    00406              info.fragstotal,
    00407              info.fragsize,
    00408              info.fragments);
    00409       o->total_blocks = info.fragments;
    00410    }
    00411    return o->total_blocks - info.fragments;
    00412 }
    00413
    00414 /* Write an exactly FRAME_SIZE sized frame */
    00415 static int soundcard_writeframe(struct chan_oss_pvt *o, short *data)
    00416 {
    00417    int res;
    00418
    00419    if (o->sounddev < 0)
    00420       setformat(o, O_RDWR);
    00421    if (o->sounddev < 0)
    00422       return 0;   /* not fatal */
    00423    /*
    00424     * Nothing complex to manage the audio device queue.
    00425     * If the buffer is full just drop the extra, otherwise write.
    00426     * XXX in some cases it might be useful to write anyways after
    00427     * a number of failures, to restart the output chain.
    00428     */
    00429    res = used_blocks(o);
    00430    if (res > o->queuesize) {  /* no room to write a block */
    00431       if (o->w_errors++ == 0 && (oss_debug & 0x4))
    00432          ast_log(LOG_WARNING, "write: used %d blocks (%d)\n",
    00433              res, o->w_errors);
    00434       return 0;
    00435    }
    00436    o->w_errors = 0;
    00437    return write(o->sounddev, ((void *)data), FRAME_SIZE * 2);
    00438 }
    00439
    00440 /*
    00441  * Handler for 'sound writable' events from the sound thread.
    00442  * Builds a frame from the high level description of the sounds,
    00443  * and passes it to the audio device.
    00444  * The actual sound is made of 1 or more sequences of sound samples
    00445  * (s->datalen, repeated to make s->samplen samples) followed by
    00446  * s->silencelen samples of silence. The position in the sequence is stored
    00447  * in o->sampsent, which goes between 0 .. s->samplen+s->silencelen.
    00448  * In case we fail to write a frame, don't update o->sampsent.
    00449  */
    00450 static void send_sound(struct chan_oss_pvt *o)
    00451 {
    00452    short myframe[FRAME_SIZE];
    00453    int ofs, l, start;
    00454    int l_sampsent = o->sampsent;
    00455    struct sound *s;
    00456
    00457    if (o->cursound < 0) /* no sound to send */
    00458       return;
    00459    s = &sounds[o->cursound];
    00460    for (ofs = 0; ofs < FRAME_SIZE; ofs += l) {
    00461       l = s->samplen - l_sampsent;  /* # of available samples */
    00462       if (l > 0) {
    00463          start = l_sampsent % s->datalen; /* source offset */
    00464          if (l > FRAME_SIZE - ofs)  /* don't overflow the frame */
    00465             l = FRAME_SIZE - ofs;
    00466          if (l > s->datalen - start)   /* don't overflow the source */
    00467             l = s->datalen - start;
    00468          bcopy(s->data + start, myframe + ofs, l*2);
    00469          if (0)
    00470             ast_log(LOG_WARNING, "send_sound sound %d/%d of %d into %d\n",
    00471                 l_sampsent, l, s->samplen, ofs);
    00472          l_sampsent += l;
    00473       } else { /* end of samples, maybe some silence */
    00474          static const short silence[FRAME_SIZE] = {0, };
    00475
    00476          l += s->silencelen;
    00477          if (l > 0) {
    00478             if (l > FRAME_SIZE - ofs)
    00479                l = FRAME_SIZE - ofs;
    00480             bcopy(silence, myframe + ofs, l*2);
    00481             l_sampsent += l;
    00482          } else { /* silence is over, restart sound if loop */
    00483             if (s->repeat == 0) {   /* last block */
    00484                o->cursound = -1;
    00485                o->nosound = 0;   /* allow audio data */
    00486                if (ofs < FRAME_SIZE)   /* pad with silence */
    00487                   bcopy(silence, myframe + ofs, (FRAME_SIZE - ofs)*2);
    00488             }
    00489             l_sampsent = 0;
    00490          }
    00491       }
    00492    }
    00493    l = soundcard_writeframe(o, myframe);
    00494    if (l > 0)
    00495       o->sampsent = l_sampsent;  /* update status */
    00496 }
    00497
    00498 static void *sound_thread(void *arg)
    00499 {
    00500    char ign[4096];
    00501    struct chan_oss_pvt *o = (struct chan_oss_pvt *)arg;
    00502
    00503    /*
    00504     * Just in case, kick the driver by trying to read from it.
    00505     * Ignore errors - this read is almost guaranteed to fail.
    00506     */
    00507    read(o->sounddev, ign, sizeof(ign));
    00508    for (;;) {
    00509       fd_set rfds, wfds;
    00510       int maxfd, res;
    00511
    00512       FD_ZERO(&rfds);
    00513       FD_ZERO(&wfds);
    00514       FD_SET(o->sndcmd[0], &rfds);
    00515       maxfd = o->sndcmd[0];   /* pipe from the main process */
    00516       if (o->cursound > -1 && o->sounddev < 0)
    00517          setformat(o, O_RDWR);   /* need the channel, try to reopen */
    00518       else if (o->cursound == -1 && o->owner == NULL)
    00519          setformat(o, O_CLOSE);  /* can close */
    00520       if (o->sounddev > -1) {
    00521          if (!o->owner) { /* no one owns the audio, so we must drain it */
    00522             FD_SET(o->sounddev, &rfds);
    00523             maxfd = MAX(o->sounddev, maxfd);
    00524          }
    00525          if (o->cursound > -1) {
    00526             FD_SET(o->sounddev, &wfds);
    00527             maxfd = MAX(o->sounddev, maxfd);
    00528          }
    00529       }
    00530       /* ast_select emulates linux behaviour in terms of timeout handling */
    00531       res = ast_select(maxfd + 1, &rfds, &wfds, NULL, NULL);
    00532       if (res < 1) {
    00533          ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
    00534          sleep(1);
    00535          continue;
    00536       }
    00537       if (FD_ISSET(o->sndcmd[0], &rfds)) {
    00538          /* read which sound to play from the pipe */
    00539          int i, what = -1;
    00540
    00541          read(o->sndcmd[0], &what, sizeof(what));
    00542          for (i = 0; sounds[i].ind != -1; i++) {
    00543             if (sounds[i].ind == what) {
    00544                o->cursound = i;
    00545                o->sampsent = 0;
    00546                o->nosound = 1; /* block audio from pbx */
    00547                break;
    00548             }
    00549          }
    00550          if (sounds[i].ind == -1)
    00551             ast_log(LOG_WARNING, "invalid sound index: %d\n", what);
    00552       }
    00553       if (o->sounddev > -1) {
    00554          if (FD_ISSET(o->sounddev, &rfds)) /* read and ignore errors */
    00555             read(o->sounddev, ign, sizeof(ign));
    00556          if (FD_ISSET(o->sounddev, &wfds))
    00557             send_sound(o);
    00558       }
    00559    }
    00560    return NULL; /* Never reached */
    00561 }
    00562
    00563 /*
    00564  * reset and close the device if opened,
    00565  * then open and initialize it in the desired mode,
    00566  * trigger reads and writes so we can start using it.
    00567  */
    00568 static int setformat(struct chan_oss_pvt *o, int mode)
    00569 {
    00570    int fmt, desired, res, fd;
    00571
    00572    if (o->sounddev >= 0) {
    00573       ioctl(o->sounddev, SNDCTL_DSP_RESET, 0);
    00574       close(o->sounddev);
    00575       o->duplex = M_UNSET;
    00576       o->sounddev = -1;
    00577    }
    00578    if (mode == O_CLOSE) /* we are done */
    00579       return 0;
    00580    if (ast_tvdiff_ms(ast_tvnow(), o->lastopen) < 1000)
    00581       return -1;  /* don't open too often */
    00582    o->lastopen = ast_tvnow();
    00583    fd = o->sounddev = open(o->device, mode |O_NONBLOCK);
    00584    if (fd < 0) {
    00585       ast_log(LOG_WARNING, "Unable to re-open DSP device %s: %s\n",
    00586           o->device, strerror(errno));
    00587       return -1;
    00588    }
    00589    if (o->owner)
    00590       o->owner->fds[0] = fd;
    00591
    00592 #if __BYTE_ORDER == __LITTLE_ENDIAN
    00593    fmt = AFMT_S16_LE;
    00594 #else
    00595    fmt = AFMT_S16_BE;
    00596 #endif
    00597    res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt);
    00598    if (res < 0) {
    00599       ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n");
    00600       return -1;
    00601    }
    00602    switch (mode) {
    00603    case O_RDWR:
    00604       res = ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
    00605       /* Check to see if duplex set (FreeBSD Bug)*/
    00606       res = ioctl(fd, SNDCTL_DSP_GETCAPS, &fmt);
    00607       if (res == 0 && (fmt & DSP_CAP_DUPLEX)) {
    00608          if (option_verbose > 1)
    00609             ast_verbose(VERBOSE_PREFIX_2 "Console is full duplex\n");
    00610          o->duplex = M_FULL;
    00611       };
    00612       break;
    00613    case O_WRONLY:
    00614       o->duplex = M_WRITE;
    00615       break;
    00616    case O_RDONLY:
    00617       o->duplex = M_READ;
    00618       break;
    00619    }
    00620
    00621    fmt = 0;
    00622    res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt);
    00623    if (res < 0) {
    00624       ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
    00625       return -1;
    00626    }
    00627    fmt = desired = 8000; /* 8000 Hz desired */
    00628    res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt);
    00629
    00630    if (res < 0) {
    00631       ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
    00632       return -1;
    00633    }
    00634    if (fmt != desired) {
    00635       if (!(o->warned & WARN_speed)) {
    00636          ast_log(LOG_WARNING,
    00637              "Requested %d Hz, got %d Hz -- sound may be choppy\n",
    00638              desired, fmt);
    00639          o->warned |= WARN_speed;
    00640       }
    00641    }
    00642    /*
    00643     * on Freebsd, SETFRAGMENT does not work very well on some cards.
    00644     * Default to use 256 bytes, let the user override
    00645     */
    00646    if (o->frags) {
    00647       fmt = o->frags;
    00648       res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt);
    00649       if (res < 0) {
    00650          if (!(o->warned & WARN_frag)) {
    00651             ast_log(LOG_WARNING,
    00652                "Unable to set fragment size -- sound may be choppy\n");
    00653             o->warned |= WARN_frag;
    00654          }
    00655       }
    00656    }
    00657    /* on some cards, we need SNDCTL_DSP_SETTRIGGER to start outputting */
    00658    res = PCM_ENABLE_INPUT | PCM_ENABLE_OUTPUT;
    00659    res = ioctl(fd, SNDCTL_DSP_SETTRIGGER, &res);
    00660    /* it may fail if we are in half duplex, never mind */
    00661    return 0;
    00662 }
    00663
    00664 /*
    00665  * some of the standard methods supported by channels.
    00666  */
    00667 static int oss_digit(struct ast_channel *c, char digit)
    00668 {
    00669    /* no better use for received digits than print them */
    00670    ast_verbose( " << Console Received digit %c >> \n", digit);
    00671    return 0;
    00672 }
    00673
    00674 static int oss_text(struct ast_channel *c, const char *text)
    00675 {
    00676    /* print received messages */
    00677    ast_verbose( " << Console Received text %s >> \n", text);
    00678    return 0;
    00679 }
    00680
    00681 /* Play ringtone 'x' on device 'o' */
    00682 static void ring(struct chan_oss_pvt *o, int x)
    00683 {
    00684    write(o->sndcmd[1], &x, sizeof(x));
    00685 }
    00686
    00687
    00688 /*
    00689  * handler for incoming calls. Either autoanswer, or start ringing
    00690  */
    00691 static int oss_call(struct ast_channel *c, char *dest, int timeout)
    00692 {
    00693    struct chan_oss_pvt *o = c->tech_pvt;
    00694    struct ast_frame f = { 0, };
    00695
    00696    ast_verbose(" << Call to '%s' on console from <%s><%s><%s> >>\n",
    00697       dest, c->cid.cid_dnid, c->cid.cid_num, c->cid.cid_name);
    00698    if (o->autoanswer) {
    00699       ast_verbose( " << Auto-answered >> \n" );
    00700       f.frametype = AST_FRAME_CONTROL;
    00701       f.subclass = AST_CONTROL_ANSWER;
    00702       ast_queue_frame(c, &f);
    00703    } else {
    00704       ast_verbose("<< Type 'answer' to answer, or use 'autoanswer' for future calls >> \n");
    00705       f.frametype = AST_FRAME_CONTROL;
    00706       f.subclass = AST_CONTROL_RINGING;
    00707       ast_queue_frame(c, &f);
    00708       ring(o, AST_CONTROL_RING);
    00709    }
    00710    return 0;
    00711 }
    00712
    00713 /*
    00714  * remote side answered the phone
    00715  */
    00716 static int oss_answer(struct ast_channel *c)
    00717 {
    00718    struct chan_oss_pvt *o = c->tech_pvt;
    00719
    00720    ast_verbose( " << Console call has been answered >> \n");
    00721 #if 0
    00722    /* play an answer tone (XXX do we really need it ?) */
    00723    ring(o, AST_CONTROL_ANSWER);
    00724 #endif
    00725    ast_setstate(c, AST_STATE_UP);
    00726    o->cursound = -1;
    00727    o->nosound=0;
    00728    return 0;
    00729 }
    00730
    00731 static int oss_hangup(struct ast_channel *c)
    00732 {
    00733    struct chan_oss_pvt *o = c->tech_pvt;
    00734
    00735    o->cursound = -1;
    00736    o->nosound = 0;
    00737    c->tech_pvt = NULL;
    00738    o->owner = NULL;
    00739    ast_verbose( " << Hangup on console >> \n");
    00740    ast_mutex_lock(&usecnt_lock); /* XXX not sure why */
    00741    usecnt--;
    00742    ast_mutex_unlock(&usecnt_lock);
    00743    if (o->hookstate) {
    00744       if (o->autoanswer || o->autohangup) {
    00745          /* Assume auto-hangup too */
    00746          o->hookstate = 0;
    00747          setformat(o, O_CLOSE);
    00748       } else {
    00749          /* Make congestion noise */
    00750          ring(o, AST_CONTROL_CONGESTION);
    00751       }
    00752    }
    00753    return 0;
    00754 }
    00755
    00756 /* used for data coming from the network */
    00757 static int oss_write(struct ast_channel *c, struct ast_frame *f)
    00758 {
    00759    int src;
    00760    struct chan_oss_pvt *o = c->tech_pvt;
    00761
    00762    /* Immediately return if no sound is enabled */
    00763    if (o->nosound)
    00764       return 0;
    00765    /* Stop any currently playing sound */
    00766    o->cursound = -1;
    00767    /*
    00768     * we could receive a block which is not a multiple of our
    00769     * FRAME_SIZE, so buffer it locally and write to the device
    00770     * in FRAME_SIZE chunks.
    00771     * Keep the residue stored for future use.
    00772     */
    00773    src = 0; /* read position into f->data */
    00774    while ( src < f->datalen ) {
    00775       /* Compute spare room in the buffer */
    00776       int l = sizeof(o->oss_write_buf) - o->oss_write_dst;
    00777
    00778       if (f->datalen - src >= l) {  /* enough to fill a frame */
    00779          memcpy(o->oss_write_buf + o->oss_write_dst,
    00780             f->data + src, l);
    00781          soundcard_writeframe(o, (short *)o->oss_write_buf);
    00782          src += l;
    00783          o->oss_write_dst = 0;
    00784       } else { /* copy residue */
    00785          l = f->datalen - src;
    00786          memcpy(o->oss_write_buf + o->oss_write_dst,
    00787             f->data + src, l);
    00788          src += l;   /* but really, we are done */
    00789          o->oss_write_dst += l;
    00790       }
    00791    }
    00792    return 0;
    00793 }
    00794
    00795 static struct ast_frame *oss_read(struct ast_channel *c)
    00796 {
    00797    int res;
    00798    struct chan_oss_pvt *o = c->tech_pvt;
    00799    struct ast_frame *f = &o->read_f;
    00800
    00801    /* prepare a NULL frame in case we don't have enough data to return */
    00802    bzero(f, sizeof(struct ast_frame));
    00803    f->frametype = AST_FRAME_NULL;
    00804    f->src = o->type;
    00805
    00806    res = read(o->sounddev, o->oss_read_buf + o->readpos,
    00807    sizeof(o->oss_read_buf) - o->readpos);
    00808    if (res < 0)   /* audio data not ready, return a NULL frame */
    00809       return f;
    00810
    00811    o->readpos += res;
    00812    if (o->readpos < sizeof(o->oss_read_buf)) /* not enough samples */
    00813       return f;
    00814
    00815    if (o->mute)
    00816       return f;
    00817
    00818    o->readpos = AST_FRIENDLY_OFFSET;   /* reset read pointer for next frame */
    00819    if (c->_state != AST_STATE_UP)   /* drop data if frame is not up */
    00820       return f;
    00821    /* ok we can build and deliver the frame to the caller */
    00822    f->frametype = AST_FRAME_VOICE;
    00823    f->subclass = AST_FORMAT_SLINEAR;
    00824    f->samples = FRAME_SIZE;
    00825    f->datalen = FRAME_SIZE * 2;
    00826    f->data = o->oss_read_buf + AST_FRIENDLY_OFFSET;
    00827    f->offset = AST_FRIENDLY_OFFSET;
    00828    return f;
    00829 }
    00830
    00831 static int oss_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
    00832 {
    00833    struct chan_oss_pvt *o = newchan->tech_pvt;
    00834    o->owner = newchan;
    00835    return 0;
    00836 }
    00837
    00838 static int oss_indicate(struct ast_channel *c, int cond)
    00839 {
    00840    struct chan_oss_pvt *o = c->tech_pvt;
    00841    int res;
    00842
    00843    switch(cond) {
    00844    case AST_CONTROL_BUSY:
    00845    case AST_CONTROL_CONGESTION:
    00846    case AST_CONTROL_RINGING:
    00847       res = cond;
    00848       break;
    00849
    00850    case -1:
    00851       o->cursound = -1;
    00852       o->nosound = 0; /* when cursound is -1 nosound must be 0 */
    00853       return 0;
    00854
    00855    case AST_CONTROL_VIDUPDATE:
    00856       res = -1;
    00857       break;
    00858    default:
    00859       ast_log(LOG_WARNING,
    00860           "Don't know how to display condition %d on %s\n",
    00861           cond, c->name);
    00862       return -1;
    00863    }
    00864    if (res > -1)
    00865       ring(o, res);
    00866    return 0;
    00867 }
    00868
    00869 /*
    00870  * allocate a new channel.
    00871  */
    00872 static struct ast_channel *oss_new(struct chan_oss_pvt *o,
    00873    char *ext, char *ctx, int state)
    00874 {
    00875    struct ast_channel *c;
    00876
    00877    c = ast_channel_alloc(1);
    00878    if (c == NULL)
    00879       return NULL;
    00880    c->tech = &oss_tech;
    00881    snprintf(c->name, sizeof(c->name), "OSS/%s", o->device + 5);
    00882    c->type = o->type;
    00883    c->fds[0] = o->sounddev; /* -1 if device closed, override later */
    00884    c->nativeformats = AST_FORMAT_SLINEAR;
    00885    c->readformat = AST_FORMAT_SLINEAR;
    00886    c->writeformat = AST_FORMAT_SLINEAR;
    00887    c->tech_pvt = o;
    00888
    00889    if (!ast_strlen_zero(ctx))
    00890       ast_copy_string(c->context, ctx, sizeof(c->context));
    00891    if (!ast_strlen_zero(ext))
    00892       ast_copy_string(c->exten, ext, sizeof(c->exten));
    00893    if (!ast_strlen_zero(o->language))
    00894       ast_copy_string(c->language, o->language, sizeof(c->language));
    00895
    00896    o->owner = c;
    00897    ast_setstate(c, state);
    00898    ast_mutex_lock(&usecnt_lock);
    00899    usecnt++;
    00900    ast_mutex_unlock(&usecnt_lock);
    00901    ast_update_use_count();
    00902    if (state != AST_STATE_DOWN) {
    00903       if (ast_pbx_start(c)) {
    00904          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", c->name);
    00905          ast_hangup(c);
    00906          o->owner = c = NULL;
    00907          /* XXX what about the channel itself ? */
    00908          /* XXX what about usecnt ? */
    00909       }
    00910    }
    00911    return c;
    00912 }
    00913
    00914 static struct ast_channel *oss_request(const char *type,
    00915    int format, void *data, int *cause)
    00916 {
    00917    struct ast_channel *c;
    00918    struct chan_oss_pvt *o = find_desc(data);
    00919
    00920    ast_log(LOG_WARNING, "oss_request ty <%s> data 0x%p <%s>\n",
    00921       type, data, (char *)data);
    00922    if (o == NULL) {
    00923       ast_log(LOG_NOTICE, "Device %s not found\n", (char *)data);
    00924       /* XXX we could default to 'dsp' perhaps ? */
    00925       return NULL;
    00926    }
    00927    if ((format & AST_FORMAT_SLINEAR) == 0) {
    00928       ast_log(LOG_NOTICE, "Format 0x%x unsupported\n", format);
    00929       return NULL;
    00930    }
    00931    if (o->owner) {
    00932       ast_log(LOG_NOTICE, "Already have a call (chan %p) on the OSS channel\n", o->owner);
    00933       *cause = AST_CAUSE_BUSY;
    00934       return NULL;
    00935    }
    00936    c= oss_new(o, NULL, NULL, AST_STATE_DOWN);
    00937    if (c == NULL) {
    00938       ast_log(LOG_WARNING, "Unable to create new OSS channel\n");
    00939       return NULL;
    00940    }
    00941    return c;
    00942 }
    00943
    00944 static int console_autoanswer(int fd, int argc, char *argv[])
    00945 {
    00946    struct chan_oss_pvt *o = find_desc(oss_active);
    00947
    00948    if (argc == 1) {
    00949       ast_cli(fd, "Auto answer is %s.\n", o->autoanswer ? "on" : "off");
    00950       return RESULT_SUCCESS;
    00951    }
    00952    if (argc != 2)
    00953       return RESULT_SHOWUSAGE;
    00954    if (o == NULL) {
    00955       ast_log(LOG_WARNING, "Cannot find device %s (should not happen!)\n",
    00956           oss_active);
    00957       return RESULT_FAILURE;
    00958    }
    00959    if (!strcasecmp(argv[1], "on"))
    00960       o->autoanswer = -1;
    00961    else if (!strcasecmp(argv[1], "off"))
    00962       o->autoanswer = 0;
    00963    else
    00964       return RESULT_SHOWUSAGE;
    00965    return RESULT_SUCCESS;
    00966 }
    00967
    00968 static char *autoanswer_complete(char *line, char *word, int pos, int state)
    00969 {
    00970    int l = strlen(word);
    00971
    00972    switch(state) {
    00973    case 0:
    00974       if (l && !strncasecmp(word, "on", MIN(l, 2)))
    00975          return strdup("on");
    00976    case 1:
    00977       if (l && !strncasecmp(word, "off", MIN(l, 3)))
    00978          return strdup("off");
    00979    default:
    00980       return NULL;
    00981    }
    00982    return NULL;
    00983 }
    00984
    00985 static char autoanswer_usage[] =
    00986 "Usage: autoanswer [on|off]\n"
    00987 "       Enables or disables autoanswer feature.  If used without\n"
    00988 "       argument, displays the current on/off status of autoanswer.\n"
    00989 "       The default value of autoanswer is in 'oss.conf'.\n";
    00990
    00991 /*
    00992  * answer command from the console
    00993  */
    00994 static int console_answer(int fd, int argc, char *argv[])
    00995 {
    00996    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
    00997    struct chan_oss_pvt *o = find_desc(oss_active);
    00998
    00999    if (argc != 1)
    01000       return RESULT_SHOWUSAGE;
    01001    if (!o->owner) {
    01002       ast_cli(fd, "No one is calling us\n");
    01003       return RESULT_FAILURE;
    01004    }
    01005    o->hookstate = 1;
    01006    o->cursound = -1;
    01007    o->nosound = 0;
    01008    ast_queue_frame(o->owner, &f);
    01009 #if 0
    01010    /* XXX do we really need it ? considering we shut down immediately... */
    01011    ring(o, AST_CONTROL_ANSWER);
    01012 #endif
    01013    return RESULT_SUCCESS;
    01014 }
    01015
    01016 static char sendtext_usage[] =
    01017 "Usage: send text <message>\n"
    01018 "       Sends a text message for display on the remote terminal.\n";
    01019
    01020 /*
    01021  * concatenate all arguments into a single string
    01022  */
    01023 static int console_sendtext(int fd, int argc, char *argv[])
    01024 {
    01025    struct chan_oss_pvt *o = find_desc(oss_active);
    01026    int tmparg = 2;
    01027    char text2send[TEXT_SIZE] = "";
    01028    struct ast_frame f = { 0, };
    01029
    01030    if (argc < 2)
    01031       return RESULT_SHOWUSAGE;
    01032    if (!o->owner) {
    01033       ast_cli(fd, "Not in a call\n");
    01034       return RESULT_FAILURE;
    01035    }
    01036    while (tmparg < argc) {
    01037       strncat(text2send, argv[tmparg++],
    01038          sizeof(text2send) - strlen(text2send) - 1);
    01039       strncat(text2send, " ",
    01040          sizeof(text2send) - strlen(text2send) - 1);
    01041    }
    01042    if (!ast_strlen_zero(text2send)) {
    01043       text2send[strlen(text2send) - 1] = '\n';
    01044       f.frametype = AST_FRAME_TEXT;
    01045       f.subclass = 0;
    01046       f.data = text2send;
    01047       f.datalen = strlen(text2send);
    01048       ast_queue_frame(o->owner, &f);
    01049    }
    01050    return RESULT_SUCCESS;
    01051 }
    01052
    01053 static char answer_usage[] =
    01054 "Usage: answer\n"
    01055 "       Answers an incoming call on the console (OSS) channel.\n";
    01056
    01057 static int console_hangup(int fd, int argc, char *argv[])
    01058 {
    01059    struct chan_oss_pvt *o = find_desc(oss_active);
    01060
    01061    if (argc != 1)
    01062       return RESULT_SHOWUSAGE;
    01063    o->cursound = -1;
    01064    o->nosound = 0;
    01065    if (!o->owner && !o->hookstate) { /* XXX maybe only one ? */
    01066       ast_cli(fd, "No call to hang up\n");
    01067       return RESULT_FAILURE;
    01068    }
    01069    o->hookstate = 0;
    01070    if (o->owner)
    01071       ast_queue_hangup(o->owner);
    01072    setformat(o, O_CLOSE);
    01073    return RESULT_SUCCESS;
    01074 }
    01075
    01076 static char hangup_usage[] =
    01077 "Usage: hangup\n"
    01078 "       Hangs up any call currently placed on the console.\n";
    01079
    01080
    01081 static int console_flash(int fd, int argc, char *argv[])
    01082 {
    01083    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_FLASH };
    01084    struct chan_oss_pvt *o = find_desc(oss_active);
    01085
    01086    if (argc != 1)
    01087       return RESULT_SHOWUSAGE;
    01088    o->cursound = -1;
    01089    o->nosound = 0; /* when cursound is -1 nosound must be 0 */
    01090    if (!o->owner) { /* XXX maybe !o->hookstate too ? */
    01091       ast_cli(fd, "No call to flash\n");
    01092       return RESULT_FAILURE;
    01093    }
    01094    o->hookstate = 0;
    01095    if (o->owner) /* XXX must be true, right ? */
    01096       ast_queue_frame(o->owner, &f);
    01097    return RESULT_SUCCESS;
    01098 }
    01099
    01100
    01101 static char flash_usage[] =
    01102 "Usage: flash\n"
    01103 "       Flashes the call currently placed on the console.\n";
    01104
    01105
    01106
    01107 static int console_dial(int fd, int argc, char *argv[])
    01108 {
    01109    char *s = NULL, *mye = NULL, *myc = NULL;
    01110    struct chan_oss_pvt *o = find_desc(oss_active);
    01111
    01112    if (argc != 1 && argc != 2)
    01113       return RESULT_SHOWUSAGE;
    01114    if (o->owner) {   /* already in a call */
    01115       int i;
    01116       struct ast_frame f = { AST_FRAME_DTMF, 0 };
    01117
    01118       if (argc == 1) {  /* argument is mandatory here */
    01119          ast_cli(fd, "Already in a call. You can only dial digits until you hangup.\n");
    01120          return RESULT_FAILURE;
    01121       }
    01122       s = argv[1];
    01123       /* send the string one char at a time */
    01124       for (i=0; i<strlen(s); i++) {
    01125          f.subclass = s[i];
    01126          ast_queue_frame(o->owner, &f);
    01127       }
    01128       return RESULT_SUCCESS;
    01129    }
    01130    /* if we have an argument split it into extension and context */
    01131    if (argc == 2)
    01132       s = ast_ext_ctx(argv[1], &mye, &myc);
    01133    /* supply default values if needed */
    01134    if (mye == NULL)
    01135       mye = o->ext;
    01136    if (myc == NULL)
    01137       myc = o->ctx;
    01138    if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
    01139       o->hookstate = 1;
    01140       oss_new(o, mye, myc, AST_STATE_RINGING);
    01141    } else
    01142       ast_cli(fd, "No such extension '%s' in context '%s'\n", mye, myc);
    01143    if (s)
    01144       free(s);
    01145    return RESULT_SUCCESS;
    01146 }
    01147
    01148 static char dial_usage[] =
    01149 "Usage: dial [extension[@context]]\n"
    01150 "       Dials a given extension (and context if specified)\n";
    01151
    01152 static char mute_usage[] =
    01153 "Usage: mute\nMutes the microphone\n";
    01154
    01155 static char unmute_usage[] =
    01156 "Usage: unmute\nUnmutes the microphone\n";
    01157
    01158 static int console_mute(int fd, int argc, char *argv[])
    01159 {
    01160    struct chan_oss_pvt *o = find_desc(oss_active);
    01161
    01162    if (argc != 1)
    01163       return RESULT_SHOWUSAGE;
    01164    o->mute = 1;
    01165    return RESULT_SUCCESS;
    01166 }
    01167
    01168 static int console_unmute(int fd, int argc, char *argv[])
    01169 {
    01170    struct chan_oss_pvt *o = find_desc(oss_active);
    01171
    01172    if (argc != 1)
    01173       return RESULT_SHOWUSAGE;
    01174    o->mute = 0;
    01175    return RESULT_SUCCESS;
    01176 }
    01177
    01178 static int console_transfer(int fd, int argc, char *argv[])
    01179 {
    01180    struct chan_oss_pvt *o = find_desc(oss_active);
    01181    struct ast_channel *b = NULL;
    01182    char *tmp, *ext, *ctx;
    01183
    01184    if (argc != 2)
    01185       return RESULT_SHOWUSAGE;
    01186    if (o == NULL)
    01187       return RESULT_FAILURE;
    01188    if (o->owner ==NULL || (b = ast_bridged_channel(o->owner)) == NULL) {
    01189       ast_cli(fd, "There is no call to transfer\n");
    01190       return RESULT_SUCCESS;
    01191    }
    01192
    01193    tmp = ast_ext_ctx(argv[1], &ext, &ctx);
    01194    if (ctx == NULL)     /* supply default context if needed */
    01195       ctx = o->owner->context;
    01196    if (!ast_exists_extension(b, ctx, ext, 1, b->cid.cid_num))
    01197       ast_cli(fd, "No such extension exists\n");
    01198    else {
    01199       ast_cli(fd, "Whee, transferring %s to %s@%s.\n",
    01200          b->name, ext, ctx);
    01201       if (ast_async_goto(b, ctx, ext, 1))
    01202          ast_cli(fd, "Failed to transfer :(\n");
    01203    }
    01204    if (tmp)
    01205       free(tmp);
    01206    return RESULT_SUCCESS;
    01207 }
    01208
    01209 static char transfer_usage[] =
    01210 "Usage: transfer <extension>[@context]\n"
    01211 "       Transfers the currently connected call to the given extension (and\n"
    01212 "context if specified)\n";
    01213
    01214 static char console_usage[] =
    01215 "Usage: console [device]\n"
    01216 "       If used without a parameter, displays which device is the current\n"
    01217 "console.  If a device is specified, the console sound device is changed to\n"
    01218 "the device specified.\n";
    01219
    01220 static int console_active(int fd, int argc, char *argv[])
    01221 {
    01222    if (argc == 1)
    01223       ast_cli(fd, "active console is [%s]\n", oss_active);
    01224    else if (argc != 2)
    01225       return RESULT_SHOWUSAGE;
    01226    else {
    01227       struct chan_oss_pvt *o;
    01228       if (strcmp(argv[1], "show") == 0) {
    01229          for (o = oss_default.next; o ; o = o->next)
    01230              ast_cli(fd, "device [%s] exists\n", o->name);
    01231          return RESULT_SUCCESS;
    01232       }
    01233       o = find_desc(argv[1]);
    01234       if (o == NULL)
    01235          ast_cli(fd, "No device [%s] exists\n", argv[1]);
    01236       else
    01237          oss_active = o->name;
    01238    }
    01239    return RESULT_SUCCESS;
    01240 }
    01241
    01242 static struct ast_cli_entry myclis[] = {
    01243    { { "answer", NULL }, console_answer, "Answer an incoming console call", answer_usage },
    01244    { { "hangup", NULL }, console_hangup, "Hangup a call on the console", hangup_usage },
    01245    { { "flash", NULL }, console_flash, "Flash a call on the console", flash_usage },
    01246    { { "dial", NULL }, console_dial, "Dial an extension on the console", dial_usage },
    01247    { { "mute", NULL }, console_mute, "Disable mic input", mute_usage },
    01248    { { "unmute", NULL }, console_unmute, "Enable mic input", unmute_usage },
    01249    { { "transfer", NULL }, console_transfer, "Transfer a call to a different extension", transfer_usage },
    01250    { { "send", "text", NULL }, console_sendtext, "Send text to the remote device", sendtext_usage },
    01251    { { "autoanswer", NULL }, console_autoanswer, "Sets/displays autoanswer", autoanswer_usage, autoanswer_complete },
    01252    { { "console", NULL }, console_active, "Sets/displays active console", console_usage },
    01253 };
    01254
    01255 /*
    01256  * store the mixer argument from the config file, filtering possibly
    01257  * invalid or dangerous values (the string is used as argument for
    01258  * system("mixer %s")
    01259  */
    01260 static void store_mixer(struct chan_oss_pvt *o, char *s)
    01261 {
    01262    int i;
    01263
    01264    for (i=0; i < strlen(s); i++) {
    01265       if (!isalnum(s[i]) && index(" \t-/", s[i]) == NULL) {
    01266          ast_log(LOG_WARNING,
    01267             "Suspect char %c in mixer cmd, ignoring:\n\t%s\n", s[i], s);
    01268          return;
    01269       }
    01270    }
    01271    if (o->mixer_cmd)
    01272       free(o->mixer_cmd);
    01273    o->mixer_cmd = strdup(s);
    01274    ast_log(LOG_WARNING, "setting mixer %s\n", s);
    01275 }
    01276
    01277 /*
    01278  * grab fields from the config file, init the descriptor and open the device.
    01279  */
    01280 static struct chan_oss_pvt * store_config(struct ast_config *cfg, char *ctg)
    01281 {
    01282    struct ast_variable *v;
    01283    struct chan_oss_pvt *o;
    01284
    01285    if (ctg == NULL) {
    01286       o = &oss_default;
    01287       ctg = "general";
    01288    } else {
    01289       o = (struct chan_oss_pvt *)malloc(sizeof *o);
    01290       if (o == NULL)    /* fail */
    01291          return NULL;
    01292       *o = oss_default;
    01293       /* "general" is also the default thing */
    01294       if (strcmp(ctg, "general") == 0) {
    01295          o->name = strdup("dsp");
    01296          oss_active = o->name;
    01297          goto openit;
    01298       }
    01299       o->name = strdup(ctg);
    01300    }
    01301
    01302    o->lastopen = ast_tvnow(); /* don't leave it 0 or tvdiff may wrap */
    01303    /* fill other fields from configuration */
    01304    for (v = ast_variable_browse(cfg, ctg);v; v=v->next) {
    01305       M_START(v->name, v->value);
    01306
    01307       M_BOOL("autoanswer", o->autoanswer)
    01308       M_BOOL("autohangup", o->autohangup)
    01309       M_BOOL("overridecontext", o->overridecontext)
    01310       M_STR("device", o->device)
    01311       M_UINT("frags", o->frags)
    01312       M_UINT("debug", oss_debug)
    01313       M_UINT("queuesize", o->queuesize)
    01314       M_STR("context", o->ctx)
    01315       M_STR("language", o->language)
    01316       M_STR("extension", o->ext)
    01317       M_F("mixer", store_mixer(o, v->value))
    01318       M_END(;);
    01319    }
    01320    if (ast_strlen_zero(o->device))
    01321       ast_copy_string(o->device, DEV_DSP, sizeof(o->device));
    01322    if (o->mixer_cmd) {
    01323       char *cmd;
    01324
    01325       asprintf(&cmd, "mixer %s", o->mixer_cmd);
    01326       ast_log(LOG_WARNING, "running [%s]\n", cmd);
    01327       system(cmd);
    01328       free(cmd);
    01329    }
    01330    if (o == &oss_default)  /* we are done with the default */
    01331       return NULL;
    01332
    01333 openit:
    01334 #if TRYOPEN
    01335    if (setformat(o, O_RDWR) < 0) {  /* open device */
    01336       if (option_verbose > 0) {
    01337          ast_verbose(VERBOSE_PREFIX_2 "Device %s not detected\n", ctg);
    01338          ast_verbose(VERBOSE_PREFIX_2 "Turn off OSS support by adding "
    01339              "'noload=chan_oss.so' in /etc/asterisk/modules.conf\n");
    01340       }
    01341       goto error;
    01342    }
    01343    if (o->duplex != M_FULL)
    01344       ast_log(LOG_WARNING, "XXX I don't work right with non "
    01345          "full-duplex sound cards XXX\n");
    01346 #endif /* TRYOPEN */
    01347    if (pipe(o->sndcmd) != 0) {
    01348       ast_log(LOG_ERROR, "Unable to create pipe\n");
    01349       goto error;
    01350    }
    01351    ast_pthread_create(&o->sthread, NULL, sound_thread, o);
    01352    /* link into list of devices */
    01353    if (o != &oss_default) {
    01354       o->next = oss_default.next;
    01355       oss_default.next = o;
    01356    }
    01357    return o;
    01358
    01359 error:
    01360    if (o != &oss_default)
    01361       free(o);
    01362    return NULL;
    01363 }
    01364
    01365 int load_module(void)
    01366 {
    01367    int i;
    01368    struct ast_config *cfg;
    01369
    01370    /* load config file */
    01371    cfg = ast_config_load(config);
    01372    if (cfg != NULL) {
    01373       char *ctg = NULL; /* first pass is 'general' */
    01374
    01375       do {
    01376          store_config(cfg, ctg);
    01377       } while ( (ctg = ast_category_browse(cfg, ctg)) != NULL);
    01378       ast_config_destroy(cfg);
    01379    } else {
    01380        ast_log(LOG_NOTICE, "Unable to load config oss.conf\n");
    01381        return -1;
    01382    }
    01383    if (find_desc(oss_active) == NULL) {
    01384       ast_log(LOG_NOTICE, "Device %s not found\n", oss_active);
    01385       /* XXX we could default to 'dsp' perhaps ? */
    01386       /* XXX should cleanup allocated memory etc. */
    01387       return -1;
    01388    }
    01389    i = ast_channel_register(&oss_tech);
    01390    if (i < 0) {
    01391       ast_log(LOG_ERROR, "Unable to register channel class '%s'\n",
    01392          oss_default.type);
    01393       /* XXX should cleanup allocated memory etc. */
    01394       return -1;
    01395    }
    01396    ast_cli_register_multiple(myclis, sizeof(myclis)/sizeof(struct ast_cli_entry));
    01397    return 0;
    01398 }
    01399
    01400
    01401 int unload_module()
    01402 {
    01403    struct chan_oss_pvt *o;
    01404
    01405    ast_channel_unregister(&oss_tech);
    01406    ast_cli_unregister_multiple(myclis,
    01407       sizeof(myclis)/sizeof(struct ast_cli_entry));
    01408
    01409    for (o = oss_default.next; o ; o = o->next) {
    01410       close(o->sounddev);
    01411       if (o->sndcmd[0] > 0) {
    01412          close(o->sndcmd[0]);
    01413          close(o->sndcmd[1]);
    01414       }
    01415       if (o->owner)
    01416          ast_softhangup(o->owner, AST_SOFTHANGUP_APPUNLOAD);
    01417       if (o->owner) /* XXX how ??? */
    01418          return -1;
    01419       /* XXX what about the thread ? */
    01420       /* XXX what about the memory allocated ? */
    01421    }
    01422    return 0;
    01423 }
    01424
    01425 char *description()
    01426 {
    01427    return (char *)oss_tech.description;
    01428 }
    01429
    01430 int usecount()
    01431 {
    01432    return usecnt;
    01433 }
    01434
    01435 char *key()
    01436 {
    01437    return ASTERISK_GPL_KEY;
    01438 }