Wed Oct 28 15:48:33 2009

Asterisk developer's documentation


chan_oss.c File Reference

Channel driver for OSS sound cards. More...

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/time.h>
#include <stdlib.h>
#include <errno.h>
#include <soundcard.h>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/frame.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/module.h"
#include "asterisk/options.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/endian.h"
#include "busy.h"
#include "ringtone.h"
#include "ring10.h"
#include "answer.h"

Include dependency graph for chan_oss.c:

Go to the source code of this file.

Data Structures

struct  chan_oss_pvt
struct  sound

Defines

#define DEV_DSP   "/dev/dsp"
#define FRAGS   ( ( (6 * 5) << 16 ) | 0x6 )
#define FRAME_SIZE   160
#define M_BOOL(tag, dst)   M_F(tag, (dst) = ast_true(__val) )
#define M_END(x)   x;
#define M_F(tag, f)   if (!strcasecmp((__s), tag)) { f; } else
#define M_START(var, val)   char *__s = var; char *__val = val;
#define M_STR(tag, dst)   M_F(tag, ast_copy_string(dst, __val, sizeof(dst)))
#define M_UINT(tag, dst)   M_F(tag, (dst) = strtoul(__val, NULL, 0) )
#define MAX(a, b)   ((a) > (b) ? (a) : (b))
#define MIN(a, b)   ((a) < (b) ? (a) : (b))
#define O_CLOSE   0x444
#define QUEUE_SIZE   10
#define TEXT_SIZE   256
#define WARN_frag   4
#define WARN_speed   2
#define WARN_used_blocks   1

Functions

static char * ast_ext_ctx (const char *src, char **ext, char **ctx)
 AST_MUTEX_DEFINE_STATIC (usecnt_lock)
static char * autoanswer_complete (char *line, char *word, int pos, int state)
static int console_active (int fd, int argc, char *argv[])
static int console_answer (int fd, int argc, char *argv[])
static int console_autoanswer (int fd, int argc, char *argv[])
static int console_dial (int fd, int argc, char *argv[])
static int console_flash (int fd, int argc, char *argv[])
static int console_hangup (int fd, int argc, char *argv[])
static int console_mute (int fd, int argc, char *argv[])
static int console_sendtext (int fd, int argc, char *argv[])
static int console_transfer (int fd, int argc, char *argv[])
static int console_unmute (int fd, int argc, char *argv[])
char * description ()
 Provides a description of the module.
static struct chan_oss_pvtfind_desc (char *dev)
char * key ()
 Returns the ASTERISK_GPL_KEY.
int load_module (void)
 Initialize the module.
static int oss_answer (struct ast_channel *c)
static int oss_call (struct ast_channel *c, char *dest, int timeout)
static int oss_digit (struct ast_channel *c, char digit)
static int oss_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static int oss_hangup (struct ast_channel *c)
static int oss_indicate (struct ast_channel *chan, int cond)
static struct ast_channeloss_new (struct chan_oss_pvt *o, char *ext, char *ctx, int state)
static struct ast_frameoss_read (struct ast_channel *chan)
static struct ast_channeloss_request (const char *type, int format, void *data, int *cause)
static int oss_text (struct ast_channel *c, const char *text)
static int oss_write (struct ast_channel *chan, struct ast_frame *f)
static void ring (struct chan_oss_pvt *o, int x)
static void send_sound (struct chan_oss_pvt *o)
static int setformat (struct chan_oss_pvt *o, int mode)
static void * sound_thread (void *arg)
static int soundcard_writeframe (struct chan_oss_pvt *o, short *data)
static struct chan_oss_pvtstore_config (struct ast_config *cfg, char *ctg)
static void store_mixer (struct chan_oss_pvt *o, char *s)
int unload_module ()
 Cleanup all module structures, sockets, etc.
int usecount ()
 Provides a usecount.
static int used_blocks (struct chan_oss_pvt *o)

Variables

static char answer_usage []
static char autoanswer_usage []
static char * config = "oss.conf"
static char console_usage []
static char dial_usage []
static char flash_usage []
static char hangup_usage []
static char mute_usage []
static struct ast_cli_entry myclis []
static char * oss_active
static int oss_debug
static struct chan_oss_pvt oss_default
static struct ast_channel_tech oss_tech
static char sendtext_usage []
static struct sound sounds []
static char transfer_usage []
static char unmute_usage []
static int usecnt


Detailed Description

Channel driver for OSS sound cards.

See also

Definition in file chan_oss.c.


Define Documentation

#define DEV_DSP   "/dev/dsp"

#define FRAGS   ( ( (6 * 5) << 16 ) | 0x6 )

Definition at line 176 of file chan_oss.c.

#define FRAME_SIZE   160

Definition at line 170 of file chan_oss.c.

#define M_BOOL ( tag,
dst   )     M_F(tag, (dst) = ast_true(__val) )

Definition at line 136 of file chan_oss.c.

Referenced by store_config().

#define M_END (  )     x;

Definition at line 134 of file chan_oss.c.

Referenced by store_config().

#define M_F ( tag,
 )     if (!strcasecmp((__s), tag)) { f; } else

Definition at line 135 of file chan_oss.c.

Referenced by store_config().

#define M_START ( var,
val   )     char *__s = var; char *__val = val;

Definition at line 132 of file chan_oss.c.

Referenced by store_config().

#define M_STR ( tag,
dst   )     M_F(tag, ast_copy_string(dst, __val, sizeof(dst)))

Definition at line 138 of file chan_oss.c.

Referenced by store_config().

#define M_UINT ( tag,
dst   )     M_F(tag, (dst) = strtoul(__val, NULL, 0) )

Definition at line 137 of file chan_oss.c.

Referenced by store_config().

#define MAX ( a,
 )     ((a) > (b) ? (a) : (b))

Definition at line 200 of file chan_oss.c.

#define MIN ( a,
 )     ((a) < (b) ? (a) : (b))

Definition at line 197 of file chan_oss.c.

#define O_CLOSE   0x444

Definition at line 188 of file chan_oss.c.

Referenced by console_hangup(), oss_hangup(), setformat(), and sound_thread().

#define QUEUE_SIZE   10

Definition at line 171 of file chan_oss.c.

#define TEXT_SIZE   256

Definition at line 183 of file chan_oss.c.

Referenced by console_sendtext().

#define WARN_frag   4

Definition at line 273 of file chan_oss.c.

Referenced by setformat().

#define WARN_speed   2

Definition at line 272 of file chan_oss.c.

Referenced by setformat().

#define WARN_used_blocks   1

Definition at line 271 of file chan_oss.c.

Referenced by used_blocks().


Function Documentation

static char* ast_ext_ctx ( const char *  src,
char **  ext,
char **  ctx 
) [static]

Definition at line 369 of file chan_oss.c.

References find_desc(), chan_oss_pvt::overridecontext, and strdup.

Referenced by console_dial(), and console_transfer().

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 }

AST_MUTEX_DEFINE_STATIC ( usecnt_lock   ) 

static char* autoanswer_complete ( char *  line,
char *  word,
int  pos,
int  state 
) [static]

Definition at line 968 of file chan_oss.c.

References MIN, and strdup.

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 }

static int console_active ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1220 of file chan_oss.c.

References ast_cli(), find_desc(), chan_oss_pvt::name, chan_oss_pvt::next, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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 }

static int console_answer ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 994 of file chan_oss.c.

References ast_cli(), AST_CONTROL_ANSWER, AST_FRAME_CONTROL, ast_queue_frame(), chan_oss_pvt::cursound, find_desc(), chan_oss_pvt::hookstate, chan_oss_pvt::nosound, chan_oss_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, and ring().

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 }

static int console_autoanswer ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 944 of file chan_oss.c.

References ast_cli(), ast_log(), chan_oss_pvt::autoanswer, find_desc(), LOG_WARNING, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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 }

static int console_dial ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1107 of file chan_oss.c.

References ast_cli(), ast_exists_extension(), ast_ext_ctx(), AST_FRAME_DTMF, ast_queue_frame(), AST_STATE_RINGING, chan_oss_pvt::ctx, chan_oss_pvt::ext, find_desc(), free, chan_oss_pvt::hookstate, oss_new(), chan_oss_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, s, and ast_frame::subclass.

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 }

static int console_flash ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1081 of file chan_oss.c.

References ast_cli(), AST_CONTROL_FLASH, AST_FRAME_CONTROL, ast_queue_frame(), chan_oss_pvt::cursound, find_desc(), chan_oss_pvt::hookstate, chan_oss_pvt::nosound, chan_oss_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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 }

static int console_hangup ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1057 of file chan_oss.c.

References ast_cli(), ast_queue_hangup(), chan_oss_pvt::cursound, find_desc(), chan_oss_pvt::hookstate, chan_oss_pvt::nosound, O_CLOSE, chan_oss_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, and setformat().

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 }

static int console_mute ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1158 of file chan_oss.c.

References find_desc(), chan_oss_pvt::mute, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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 }

static int console_sendtext ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1023 of file chan_oss.c.

References ast_cli(), AST_FRAME_TEXT, ast_queue_frame(), ast_strlen_zero(), ast_frame::data, ast_frame::datalen, find_desc(), ast_frame::frametype, chan_oss_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_frame::subclass, and TEXT_SIZE.

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 }

static int console_transfer ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1178 of file chan_oss.c.

References ast_async_goto(), ast_bridged_channel(), ast_cli(), ast_exists_extension(), ast_ext_ctx(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, find_desc(), free, ast_channel::name, chan_oss_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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 }

static int console_unmute ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1168 of file chan_oss.c.

References find_desc(), chan_oss_pvt::mute, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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 }

char* description ( void   ) 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 1425 of file chan_oss.c.

References ast_channel_tech::description.

01426 {
01427    return (char *)oss_tech.description;
01428 }

static struct chan_oss_pvt* find_desc ( char *  dev  )  [static, read]

Definition at line 349 of file chan_oss.c.

References ast_log(), LOG_WARNING, chan_oss_pvt::name, and chan_oss_pvt::next.

Referenced by ast_ext_ctx(), console_active(), console_answer(), console_autoanswer(), console_dial(), console_flash(), console_hangup(), console_mute(), console_sendtext(), console_transfer(), console_unmute(), load_module(), and oss_request().

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 }

char* key ( void   ) 

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

 char *key(void) {
         return ASTERISK_GPL_KEY;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 1435 of file chan_oss.c.

References ASTERISK_GPL_KEY.

01436 {
01437    return ASTERISK_GPL_KEY;
01438 }

int load_module ( void   ) 

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.
Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
int Always 0.
TE STUFF END

Definition at line 1365 of file chan_oss.c.

References ast_category_browse(), ast_channel_register(), ast_cli_register_multiple(), ast_config_destroy(), ast_config_load(), ast_log(), cfg, find_desc(), LOG_ERROR, LOG_NOTICE, store_config(), and chan_oss_pvt::type.

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 }

static int oss_answer ( struct ast_channel c  )  [static]

Definition at line 716 of file chan_oss.c.

References AST_CONTROL_ANSWER, ast_setstate(), AST_STATE_UP, ast_verbose(), chan_oss_pvt::cursound, chan_oss_pvt::nosound, ring(), and ast_channel::tech_pvt.

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 }

static int oss_call ( struct ast_channel c,
char *  dest,
int  timeout 
) [static]

Definition at line 691 of file chan_oss.c.

References AST_CONTROL_ANSWER, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_FRAME_CONTROL, ast_queue_frame(), ast_verbose(), chan_oss_pvt::autoanswer, ast_channel::cid, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_frame::frametype, ring(), ast_frame::subclass, and ast_channel::tech_pvt.

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 }

static int oss_digit ( struct ast_channel c,
char  digit 
) [static]

Definition at line 667 of file chan_oss.c.

References ast_verbose().

00668 {
00669    /* no better use for received digits than print them */
00670    ast_verbose( " << Console Received digit %c >> \n", digit);
00671    return 0;
00672 }

static int oss_fixup ( struct ast_channel oldchan,
struct ast_channel newchan 
) [static]

Definition at line 831 of file chan_oss.c.

References chan_oss_pvt::owner, and ast_channel::tech_pvt.

00832 {
00833    struct chan_oss_pvt *o = newchan->tech_pvt;
00834    o->owner = newchan;
00835    return 0;
00836 }

static int oss_hangup ( struct ast_channel c  )  [static]

Definition at line 731 of file chan_oss.c.

References AST_CONTROL_CONGESTION, ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), chan_oss_pvt::autoanswer, chan_oss_pvt::autohangup, chan_oss_pvt::cursound, chan_oss_pvt::hookstate, chan_oss_pvt::nosound, O_CLOSE, chan_oss_pvt::owner, ring(), setformat(), ast_channel::tech_pvt, and usecnt_lock.

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 }

static int oss_indicate ( struct ast_channel chan,
int  cond 
) [static]

Definition at line 838 of file chan_oss.c.

References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_RINGING, AST_CONTROL_VIDUPDATE, ast_log(), chan_oss_pvt::cursound, LOG_WARNING, ast_channel::name, chan_oss_pvt::nosound, ring(), and ast_channel::tech_pvt.

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 }

static struct ast_channel* oss_new ( struct chan_oss_pvt o,
char *  ext,
char *  ctx,
int  state 
) [static, read]

Definition at line 872 of file chan_oss.c.

References ast_channel_alloc(), AST_FORMAT_SLINEAR, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_setstate(), AST_STATE_DOWN, ast_strlen_zero(), ast_update_use_count(), ast_channel::context, chan_oss_pvt::device, ast_channel::exten, ast_channel::fds, ast_channel::language, chan_oss_pvt::language, LOG_WARNING, ast_channel::name, ast_channel::nativeformats, chan_oss_pvt::owner, ast_channel::readformat, chan_oss_pvt::sounddev, ast_channel::tech, ast_channel::tech_pvt, chan_oss_pvt::type, ast_channel::type, usecnt_lock, and ast_channel::writeformat.

Referenced by console_dial(), and oss_request().

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 }

static struct ast_frame * oss_read ( struct ast_channel chan  )  [static, read]

Definition at line 795 of file chan_oss.c.

References ast_channel::_state, AST_FORMAT_SLINEAR, AST_FRAME_NULL, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, AST_STATE_UP, ast_frame::data, ast_frame::datalen, FRAME_SIZE, ast_frame::frametype, chan_oss_pvt::mute, ast_frame::offset, chan_oss_pvt::oss_read_buf, chan_oss_pvt::read_f, chan_oss_pvt::readpos, ast_frame::samples, chan_oss_pvt::sounddev, ast_frame::src, ast_frame::subclass, ast_channel::tech_pvt, and chan_oss_pvt::type.

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 }

static struct ast_channel * oss_request ( const char *  type,
int  format,
void *  data,
int *  cause 
) [static, read]

Definition at line 914 of file chan_oss.c.

References AST_CAUSE_BUSY, AST_FORMAT_SLINEAR, ast_log(), AST_STATE_DOWN, find_desc(), LOG_NOTICE, LOG_WARNING, oss_new(), and chan_oss_pvt::owner.

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 }

static int oss_text ( struct ast_channel c,
const char *  text 
) [static]

Definition at line 674 of file chan_oss.c.

References ast_verbose().

00675 {
00676    /* print received messages */
00677    ast_verbose( " << Console Received text %s >> \n", text);
00678    return 0;
00679 }

static int oss_write ( struct ast_channel chan,
struct ast_frame f 
) [static]

Definition at line 757 of file chan_oss.c.

References chan_oss_pvt::cursound, ast_frame::data, ast_frame::datalen, chan_oss_pvt::nosound, chan_oss_pvt::oss_write_buf, chan_oss_pvt::oss_write_dst, soundcard_writeframe(), and ast_channel::tech_pvt.

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 }

static void ring ( struct chan_oss_pvt o,
int  x 
) [static]

Definition at line 682 of file chan_oss.c.

References chan_oss_pvt::sndcmd.

Referenced by ast_extension_state2(), console_answer(), ind_load_module(), oss_answer(), oss_call(), oss_hangup(), and oss_indicate().

00683 {
00684    write(o->sndcmd[1], &x, sizeof(x));
00685 }

static void send_sound ( struct chan_oss_pvt o  )  [static]

Definition at line 450 of file chan_oss.c.

References ast_log(), chan_oss_pvt::cursound, sound::data, sound::datalen, FRAME_SIZE, LOG_WARNING, chan_oss_pvt::nosound, sound::repeat, s, sound::samplen, chan_oss_pvt::sampsent, silence, sound::silencelen, and soundcard_writeframe().

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 }

static int setformat ( struct chan_oss_pvt o,
int  mode 
) [static]

Definition at line 568 of file chan_oss.c.

References ast_log(), ast_verbose(), chan_oss_pvt::device, chan_oss_pvt::duplex, ast_channel::fds, fmt, chan_oss_pvt::frags, chan_oss_pvt::lastopen, LOG_WARNING, chan_oss_pvt::M_FULL, chan_oss_pvt::M_READ, chan_oss_pvt::M_UNSET, chan_oss_pvt::M_WRITE, O_CLOSE, option_verbose, chan_oss_pvt::owner, chan_oss_pvt::sounddev, VERBOSE_PREFIX_2, WARN_frag, WARN_speed, and chan_oss_pvt::warned.

Referenced by console_hangup(), oss_hangup(), sound_thread(), soundcard_init(), soundcard_setinput(), soundcard_setoutput(), soundcard_writeframe(), and store_config().

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 }

static void* sound_thread ( void *  arg  )  [static]

Definition at line 498 of file chan_oss.c.

References ast_log(), ast_select(), chan_oss_pvt::cursound, sound::ind, LOG_WARNING, MAX, chan_oss_pvt::nosound, O_CLOSE, chan_oss_pvt::owner, chan_oss_pvt::sampsent, send_sound(), setformat(), chan_oss_pvt::sndcmd, and chan_oss_pvt::sounddev.

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 }

static int soundcard_writeframe ( struct chan_oss_pvt o,
short *  data 
) [static]

Definition at line 415 of file chan_oss.c.

References ast_log(), FRAME_SIZE, LOG_WARNING, chan_oss_pvt::queuesize, setformat(), chan_oss_pvt::sounddev, used_blocks(), and chan_oss_pvt::w_errors.

Referenced by oss_write(), and send_sound().

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 }

static struct chan_oss_pvt* store_config ( struct ast_config cfg,
char *  ctg 
) [static, read]

Definition at line 1280 of file chan_oss.c.

References ast_log(), ast_pthread_create, ast_strlen_zero(), ast_variable_browse(), ast_verbose(), chan_oss_pvt::autoanswer, chan_oss_pvt::autohangup, chan_oss_pvt::ctx, DEV_DSP, chan_oss_pvt::device, chan_oss_pvt::duplex, error(), chan_oss_pvt::ext, chan_oss_pvt::frags, free, chan_oss_pvt::language, chan_oss_pvt::lastopen, LOG_ERROR, LOG_WARNING, M_BOOL, M_END, M_F, chan_oss_pvt::M_FULL, M_START, M_STR, M_UINT, malloc, chan_oss_pvt::mixer_cmd, ast_variable::name, chan_oss_pvt::name, chan_oss_pvt::next, ast_variable::next, option_verbose, chan_oss_pvt::overridecontext, chan_oss_pvt::queuesize, setformat(), chan_oss_pvt::sndcmd, sound_thread(), chan_oss_pvt::sthread, store_mixer(), strdup, ast_variable::value, and VERBOSE_PREFIX_2.

Referenced by load_module().

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 }

static void store_mixer ( struct chan_oss_pvt o,
char *  s 
) [static]

Definition at line 1260 of file chan_oss.c.

References ast_log(), free, LOG_WARNING, chan_oss_pvt::mixer_cmd, and strdup.

Referenced by store_config().

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 }

int unload_module ( void   ) 

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
Zero on success, or non-zero on error.

Definition at line 1401 of file chan_oss.c.

References ast_channel_unregister(), ast_cli_unregister_multiple(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, chan_oss_pvt::next, chan_oss_pvt::owner, chan_oss_pvt::sndcmd, and chan_oss_pvt::sounddev.

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 }

int usecount ( void   ) 

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
The module's usecount.

Definition at line 1430 of file chan_oss.c.

01431 {
01432    return usecnt;
01433 }

static int used_blocks ( struct chan_oss_pvt o  )  [static]

Definition at line 392 of file chan_oss.c.

References ast_log(), LOG_WARNING, chan_oss_pvt::sounddev, chan_oss_pvt::total_blocks, WARN_used_blocks, and chan_oss_pvt::warned.

Referenced by soundcard_writeframe().

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 }


Variable Documentation

char answer_usage[] [static]

Initial value:

"Usage: answer\n"
"       Answers an incoming call on the console (OSS) channel.\n"

Definition at line 1053 of file chan_oss.c.

char autoanswer_usage[] [static]

Initial value:

"Usage: autoanswer [on|off]\n"
"       Enables or disables autoanswer feature.  If used without\n"
"       argument, displays the current on/off status of autoanswer.\n"
"       The default value of autoanswer is in 'oss.conf'.\n"

Definition at line 985 of file chan_oss.c.

char* config = "oss.conf" [static]

Definition at line 207 of file chan_oss.c.

char console_usage[] [static]

Initial value:

"Usage: console [device]\n"
"       If used without a parameter, displays which device is the current\n"
"console.  If a device is specified, the console sound device is changed to\n"
"the device specified.\n"

Definition at line 1214 of file chan_oss.c.

char dial_usage[] [static]

Initial value:

"Usage: dial [extension[@context]]\n"
"       Dials a given extension (and context if specified)\n"

Definition at line 1148 of file chan_oss.c.

char flash_usage[] [static]

Initial value:

"Usage: flash\n"
"       Flashes the call currently placed on the console.\n"

Definition at line 1101 of file chan_oss.c.

char hangup_usage[] [static]

Initial value:

"Usage: hangup\n"
"       Hangs up any call currently placed on the console.\n"

Definition at line 1076 of file chan_oss.c.

char mute_usage[] [static]

Initial value:

"Usage: mute\nMutes the microphone\n"

Definition at line 1152 of file chan_oss.c.

struct ast_cli_entry myclis[] [static]

Definition at line 1242 of file chan_oss.c.

char* oss_active [static]

Definition at line 314 of file chan_oss.c.

int oss_debug [static]

Definition at line 209 of file chan_oss.c.

struct chan_oss_pvt oss_default [static]

Definition at line 299 of file chan_oss.c.

struct ast_channel_tech oss_tech [static]

Definition at line 330 of file chan_oss.c.

char sendtext_usage[] [static]

Initial value:

"Usage: send text <message>\n"
"       Sends a text message for display on the remote terminal.\n"

Definition at line 1016 of file chan_oss.c.

struct sound sounds[] [static]

Definition at line 226 of file chan_oss.c.

char transfer_usage[] [static]

Initial value:

"Usage: transfer <extension>[@context]\n"
"       Transfers the currently connected call to the given extension (and\n"
"context if specified)\n"

Definition at line 1209 of file chan_oss.c.

char unmute_usage[] [static]

Initial value:

"Usage: unmute\nUnmutes the microphone\n"

Definition at line 1155 of file chan_oss.c.

int usecnt [static]

Definition at line 204 of file chan_oss.c.


Generated on Wed Oct 28 15:48:34 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6