Thu Jul 9 13:41:02 2009

Asterisk developer's documentation


chan_oss.c File Reference

Channel driver for OSS sound cards. More...

#include "asterisk.h"
#include <ctype.h>
#include <math.h>
#include <sys/ioctl.h>
#include <soundcard.h>
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/callerid.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/cli.h"
#include "asterisk/causes.h"
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "console_video.h"

Go to the source code of this file.

Data Structures

struct  chan_oss_pvt
 descriptor for one of our channels. More...

Defines

#define BOOST_MAX   40
#define BOOST_SCALE   (1<<9)
#define DEV_DSP   "/dev/dsp"
#define FRAGS   ( ( (6 * 5) << 16 ) | 0x6 )
#define FRAME_SIZE   160
#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 void __reg_module (void)
static void __unreg_module (void)
static char * ast_ext_ctx (const char *src, char **ext, char **ctx)
static char * console_active (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_answer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 answer command from the console
static char * console_autoanswer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_boost (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_dial (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_do_answer (int fd)
 helper function for the answer key/cli command
static char * console_flash (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_hangup (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_mute (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_sendtext (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Console send text CLI command.
static char * console_transfer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct chan_oss_pvtfind_desc (char *dev)
 returns a pointer to the descriptor with the given name
video_desc * get_video_desc (struct ast_channel *c)
 return the pointer to the video descriptor
static int load_module (void)
static int oss_answer (struct ast_channel *c)
 remote side answered the phone
static int oss_call (struct ast_channel *c, char *dest, int timeout)
 handler for incoming calls. Either autoanswer, or start ringing
static int oss_digit_begin (struct ast_channel *c, char digit)
static int oss_digit_end (struct ast_channel *c, char digit, unsigned int duration)
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, const void *data, size_t datalen)
static struct ast_channeloss_new (struct chan_oss_pvt *o, char *ext, char *ctx, int state)
 allocate a new channel.
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 *c, struct ast_frame *f)
 used for data coming from the network
static int setformat (struct chan_oss_pvt *o, int mode)
static int soundcard_writeframe (struct chan_oss_pvt *o, short *data)
static void store_boost (struct chan_oss_pvt *o, const char *s)
 store the boost factor
static void store_callerid (struct chan_oss_pvt *o, const char *s)
static struct chan_oss_pvtstore_config (struct ast_config *cfg, char *ctg)
static void store_config_core (struct chan_oss_pvt *o, const char *var, const char *value)
static void store_mixer (struct chan_oss_pvt *o, const char *s)
static int unload_module (void)
static int used_blocks (struct chan_oss_pvt *o)
 Returns the number of blocks used in the audio output channel.

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "OSS Console Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, }
static const struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry cli_oss []
static char * config = "oss.conf"
static struct ast_jb_conf default_jbconf
static struct ast_jb_conf global_jbconf
static char * oss_active
static int oss_debug
static struct chan_oss_pvt oss_default
static struct ast_channel_tech oss_tech
static char tdesc [] = "OSS Console Channel Driver"


Detailed Description

Channel driver for OSS sound cards.

Author:
Mark Spencer <markster@digium.com>

Luigi Rizzo

See also

Definition in file chan_oss.c.


Define Documentation

#define BOOST_MAX   40

slightly less than 7 bits

Definition at line 279 of file chan_oss.c.

Referenced by store_boost().

#define BOOST_SCALE   (1<<9)

boost support. BOOST_SCALE * 10 ^(BOOST_MAX/20) must be representable in 16 bits to avoid overflows.

Definition at line 278 of file chan_oss.c.

Referenced by console_boost(), oss_read(), store_boost(), and usbradio_read().

#define DEV_DSP   "/dev/dsp"

Definition at line 229 of file chan_oss.c.

Referenced by store_config().

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

Definition at line 212 of file chan_oss.c.

#define FRAME_SIZE   160

Definition at line 206 of file chan_oss.c.

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

Definition at line 236 of file chan_oss.c.

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

Definition at line 233 of file chan_oss.c.

#define O_CLOSE   0x444

Definition at line 224 of file chan_oss.c.

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

#define QUEUE_SIZE   10

Definition at line 207 of file chan_oss.c.

#define TEXT_SIZE   256

Definition at line 219 of file chan_oss.c.

#define WARN_frag   4

Definition at line 268 of file chan_oss.c.

Referenced by setformat().

#define WARN_speed   2

Definition at line 267 of file chan_oss.c.

Referenced by setformat().

#define WARN_used_blocks   1

Definition at line 266 of file chan_oss.c.

Referenced by used_blocks().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1481 of file chan_oss.c.

static void __unreg_module ( void   )  [static]

Definition at line 1481 of file chan_oss.c.

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

Definition at line 396 of file chan_oss.c.

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

00397 {
00398    struct chan_oss_pvt *o = find_desc(oss_active);
00399 
00400    if (ext == NULL || ctx == NULL)
00401       return NULL;         /* error */
00402 
00403    *ext = *ctx = NULL;
00404 
00405    if (src && *src != '\0')
00406       *ext = ast_strdup(src);
00407 
00408    if (*ext == NULL)
00409       return NULL;
00410 
00411    if (!o->overridecontext) {
00412       /* parse from the right */
00413       *ctx = strrchr(*ext, '@');
00414       if (*ctx)
00415          *(*ctx)++ = '\0';
00416    }
00417 
00418    return *ext;
00419 }

static char* console_active ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1193 of file chan_oss.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, find_desc(), chan_oss_pvt::name, chan_oss_pvt::next, oss_default, and ast_cli_entry::usage.

01194 {
01195    switch (cmd) {
01196    case CLI_INIT:
01197       e->command = "console active";
01198       e->usage =
01199          "Usage: console active [device]\n"
01200          "       If used without a parameter, displays which device is the current\n"
01201          "       console.  If a device is specified, the console sound device is changed to\n"
01202          "       the device specified.\n";
01203       return NULL;
01204    case CLI_GENERATE:
01205       return NULL;
01206    }
01207 
01208    if (a->argc == 2)
01209       ast_cli(a->fd, "active console is [%s]\n", oss_active);
01210    else if (a->argc != 3)
01211       return CLI_SHOWUSAGE;
01212    else {
01213       struct chan_oss_pvt *o;
01214       if (strcmp(a->argv[2], "show") == 0) {
01215          for (o = oss_default.next; o; o = o->next)
01216             ast_cli(a->fd, "device [%s] exists\n", o->name);
01217          return CLI_SUCCESS;
01218       }
01219       o = find_desc(a->argv[2]);
01220       if (o == NULL)
01221          ast_cli(a->fd, "No device [%s] exists\n", a->argv[2]);
01222       else
01223          oss_active = o->name;
01224    }
01225    return CLI_SUCCESS;
01226 }

static char* console_answer ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

answer command from the console

Definition at line 965 of file chan_oss.c.

References ast_cli_args::argc, ast_cli_entry::args, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, console_do_answer(), ast_cli_args::fd, and ast_cli_entry::usage.

00966 {
00967    switch (cmd) {
00968    case CLI_INIT:
00969       e->command = "console answer";
00970       e->usage =
00971          "Usage: console answer\n"
00972          "       Answers an incoming call on the console (OSS) channel.\n";
00973       return NULL;
00974 
00975    case CLI_GENERATE:
00976       return NULL;   /* no completion */
00977    }
00978    if (a->argc != e->args)
00979       return CLI_SHOWUSAGE;
00980    return console_do_answer(a->fd);
00981 }

static char* console_autoanswer ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 909 of file chan_oss.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_log(), chan_oss_pvt::autoanswer, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, find_desc(), LOG_WARNING, and ast_cli_entry::usage.

00910 {
00911    struct chan_oss_pvt *o = find_desc(oss_active);
00912 
00913    switch (cmd) {
00914    case CLI_INIT:
00915       e->command = "console autoanswer [on|off]";
00916       e->usage =
00917          "Usage: console autoanswer [on|off]\n"
00918          "       Enables or disables autoanswer feature.  If used without\n"
00919          "       argument, displays the current on/off status of autoanswer.\n"
00920          "       The default value of autoanswer is in 'oss.conf'.\n";
00921       return NULL;
00922 
00923    case CLI_GENERATE:
00924       return NULL;
00925    }
00926 
00927    if (a->argc == e->args - 1) {
00928       ast_cli(a->fd, "Auto answer is %s.\n", o->autoanswer ? "on" : "off");
00929       return CLI_SUCCESS;
00930    }
00931    if (a->argc != e->args)
00932       return CLI_SHOWUSAGE;
00933    if (o == NULL) {
00934       ast_log(LOG_WARNING, "Cannot find device %s (should not happen!)\n",
00935           oss_active);
00936       return CLI_FAILURE;
00937    }
00938    if (!strcasecmp(a->argv[e->args-1], "on"))
00939       o->autoanswer = 1;
00940    else if (!strcasecmp(a->argv[e->args - 1], "off"))
00941       o->autoanswer = 0;
00942    else
00943       return CLI_SHOWUSAGE;
00944    return CLI_SUCCESS;
00945 }

static char* console_boost ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1250 of file chan_oss.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), chan_oss_pvt::boost, BOOST_SCALE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, find_desc(), store_boost(), and ast_cli_entry::usage.

01251 {
01252    struct chan_oss_pvt *o = find_desc(oss_active);
01253 
01254    switch (cmd) {
01255    case CLI_INIT:
01256       e->command = "console boost";
01257       e->usage =
01258          "Usage: console boost [boost in dB]\n"
01259          "       Sets or display mic boost in dB\n";
01260       return NULL;
01261    case CLI_GENERATE:
01262       return NULL;
01263    }
01264 
01265    if (a->argc == 2)
01266       ast_cli(a->fd, "boost currently %5.1f\n", 20 * log10(((double) o->boost / (double) BOOST_SCALE)));
01267    else if (a->argc == 3)
01268       store_boost(o, a->argv[2]);
01269    return CLI_SUCCESS;
01270 }

static char* console_cmd ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Generic console command handler. Basically a wrapper for a subset of config file options which are also available from the CLI

Definition at line 874 of file chan_oss.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_log(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, console_video_cli(), CONSOLE_VIDEO_CMDS, ast_cli_args::fd, find_desc(), LOG_WARNING, store_config_core(), ast_cli_entry::usage, and var.

00875 {
00876    struct chan_oss_pvt *o = find_desc(oss_active);
00877    const char *var, *value;
00878    switch (cmd) {
00879    case CLI_INIT:
00880       e->command = CONSOLE_VIDEO_CMDS;
00881       e->usage = "Usage: " CONSOLE_VIDEO_CMDS "...\n"
00882       "       Generic handler for console commands.\n";
00883       return NULL;
00884 
00885    case CLI_GENERATE:
00886       return NULL;
00887    }
00888 
00889    if (a->argc < e->args)
00890       return CLI_SHOWUSAGE;
00891    if (o == NULL) {
00892       ast_log(LOG_WARNING, "Cannot find device %s (should not happen!)\n",
00893          oss_active);
00894       return CLI_FAILURE;
00895    }
00896    var = a->argv[e->args-1];
00897    value = a->argc > e->args ? a->argv[e->args] : NULL;
00898    if (value)      /* handle setting */
00899       store_config_core(o, var, value);
00900    if (!console_video_cli(o->env, var, a->fd))  /* print video-related values */
00901       return CLI_SUCCESS;
00902    /* handle other values */
00903    if (!strcasecmp(var, "device")) {
00904       ast_cli(a->fd, "device is [%s]\n", o->device);
00905    }
00906    return CLI_SUCCESS;
00907 }

static char* console_dial ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1075 of file chan_oss.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_exists_extension(), ast_ext_ctx(), AST_FRAME_DTMF, ast_free, ast_queue_frame(), AST_STATE_RINGING, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, chan_oss_pvt::ctx, chan_oss_pvt::ext, f, ast_cli_args::fd, find_desc(), chan_oss_pvt::hookstate, oss_new(), chan_oss_pvt::owner, s, and ast_cli_entry::usage.

01076 {
01077    char *s = NULL, *mye = NULL, *myc = NULL;
01078    struct chan_oss_pvt *o = find_desc(oss_active);
01079 
01080    if (cmd == CLI_INIT) {
01081       e->command = "console dial";
01082       e->usage =
01083          "Usage: console dial [extension[@context]]\n"
01084          "       Dials a given extension (and context if specified)\n";
01085       return NULL;
01086    } else if (cmd == CLI_GENERATE)
01087       return NULL;
01088 
01089    if (a->argc > e->args + 1)
01090       return CLI_SHOWUSAGE;
01091    if (o->owner) {   /* already in a call */
01092       int i;
01093       struct ast_frame f = { AST_FRAME_DTMF, 0 };
01094 
01095       if (a->argc == e->args) {  /* argument is mandatory here */
01096          ast_cli(a->fd, "Already in a call. You can only dial digits until you hangup.\n");
01097          return CLI_FAILURE;
01098       }
01099       s = a->argv[e->args];
01100       /* send the string one char at a time */
01101       for (i = 0; i < strlen(s); i++) {
01102          f.subclass = s[i];
01103          ast_queue_frame(o->owner, &f);
01104       }
01105       return CLI_SUCCESS;
01106    }
01107    /* if we have an argument split it into extension and context */
01108    if (a->argc == e->args + 1)
01109       s = ast_ext_ctx(a->argv[e->args], &mye, &myc);
01110    /* supply default values if needed */
01111    if (mye == NULL)
01112       mye = o->ext;
01113    if (myc == NULL)
01114       myc = o->ctx;
01115    if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
01116       o->hookstate = 1;
01117       oss_new(o, mye, myc, AST_STATE_RINGING);
01118    } else
01119       ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc);
01120    if (s)
01121       ast_free(s);
01122    return CLI_SUCCESS;
01123 }

static char* console_do_answer ( int  fd  )  [static]

helper function for the answer key/cli command

Definition at line 948 of file chan_oss.c.

References ast_cli(), AST_CONTROL_ANSWER, AST_FRAME_CONTROL, ast_queue_frame(), CLI_FAILURE, CLI_SUCCESS, f, find_desc(), chan_oss_pvt::hookstate, and chan_oss_pvt::owner.

Referenced by console_answer().

00949 {
00950    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
00951    struct chan_oss_pvt *o = find_desc(oss_active);
00952    if (!o->owner) {
00953       if (fd > -1)
00954          ast_cli(fd, "No one is calling us\n");
00955       return CLI_FAILURE;
00956    }
00957    o->hookstate = 1;
00958    ast_queue_frame(o->owner, &f);
00959    return CLI_SUCCESS;
00960 }

static char* console_flash ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1049 of file chan_oss.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli(), AST_CONTROL_FLASH, AST_FRAME_CONTROL, ast_queue_frame(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, f, ast_cli_args::fd, find_desc(), chan_oss_pvt::hookstate, chan_oss_pvt::owner, and ast_cli_entry::usage.

01050 {
01051    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_FLASH };
01052    struct chan_oss_pvt *o = find_desc(oss_active);
01053 
01054    if (cmd == CLI_INIT) {
01055       e->command = "console flash";
01056       e->usage =
01057          "Usage: console flash\n"
01058          "       Flashes the call currently placed on the console.\n";
01059       return NULL;
01060    } else if (cmd == CLI_GENERATE)
01061       return NULL;
01062 
01063    if (a->argc != e->args)
01064       return CLI_SHOWUSAGE;
01065    if (!o->owner) {        /* XXX maybe !o->hookstate too ? */
01066       ast_cli(a->fd, "No call to flash\n");
01067       return CLI_FAILURE;
01068    }
01069    o->hookstate = 0;
01070    if (o->owner)
01071       ast_queue_frame(o->owner, &f);
01072    return CLI_SUCCESS;
01073 }

static char* console_hangup ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1023 of file chan_oss.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli(), ast_queue_hangup(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, find_desc(), chan_oss_pvt::hookstate, O_CLOSE, chan_oss_pvt::owner, setformat(), and ast_cli_entry::usage.

01024 {
01025    struct chan_oss_pvt *o = find_desc(oss_active);
01026 
01027    if (cmd == CLI_INIT) {
01028       e->command = "console hangup";
01029       e->usage =
01030          "Usage: console hangup\n"
01031          "       Hangs up any call currently placed on the console.\n";
01032       return NULL;
01033    } else if (cmd == CLI_GENERATE)
01034       return NULL;
01035 
01036    if (a->argc != e->args)
01037       return CLI_SHOWUSAGE;
01038    if (!o->owner && !o->hookstate) { /* XXX maybe only one ? */
01039       ast_cli(a->fd, "No call to hang up\n");
01040       return CLI_FAILURE;
01041    }
01042    o->hookstate = 0;
01043    if (o->owner)
01044       ast_queue_hangup(o->owner);
01045    setformat(o, O_CLOSE);
01046    return CLI_SUCCESS;
01047 }

static char* console_mute ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1125 of file chan_oss.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, find_desc(), chan_oss_pvt::mute, s, and ast_cli_entry::usage.

01126 {
01127    struct chan_oss_pvt *o = find_desc(oss_active);
01128    char *s;
01129    
01130    if (cmd == CLI_INIT) {
01131       e->command = "console {mute|unmute}";
01132       e->usage =
01133          "Usage: console {mute|unmute}\n"
01134          "       Mute/unmute the microphone.\n";
01135       return NULL;
01136    } else if (cmd == CLI_GENERATE)
01137       return NULL;
01138 
01139    if (a->argc != e->args)
01140       return CLI_SHOWUSAGE;
01141    s = a->argv[e->args-1];
01142    if (!strcasecmp(s, "mute"))
01143       o->mute = 1;
01144    else if (!strcasecmp(s, "unmute"))
01145       o->mute = 0;
01146    else
01147       return CLI_SHOWUSAGE;
01148    return CLI_SUCCESS;
01149 }

static char* console_sendtext ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Console send text CLI command.

Note:
concatenate all arguments into a single string. argv is NULL-terminated so we can use it right away

Definition at line 989 of file chan_oss.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), AST_FRAME_TEXT, ast_join(), ast_queue_frame(), ast_strlen_zero(), buf, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, f, ast_cli_args::fd, find_desc(), chan_oss_pvt::owner, TEXT_SIZE, and ast_cli_entry::usage.

00990 {
00991    struct chan_oss_pvt *o = find_desc(oss_active);
00992    char buf[TEXT_SIZE];
00993 
00994    if (cmd == CLI_INIT) {
00995       e->command = "console send text";
00996       e->usage =
00997          "Usage: console send text <message>\n"
00998          "       Sends a text message for display on the remote terminal.\n";
00999       return NULL;
01000    } else if (cmd == CLI_GENERATE)
01001       return NULL;
01002 
01003    if (a->argc < e->args + 1)
01004       return CLI_SHOWUSAGE;
01005    if (!o->owner) {
01006       ast_cli(a->fd, "Not in a call\n");
01007       return CLI_FAILURE;
01008    }
01009    ast_join(buf, sizeof(buf) - 1, a->argv + e->args);
01010    if (!ast_strlen_zero(buf)) {
01011       struct ast_frame f = { 0, };
01012       int i = strlen(buf);
01013       buf[i] = '\n';
01014       f.frametype = AST_FRAME_TEXT;
01015       f.subclass = 0;
01016       f.data = buf;
01017       f.datalen = i + 1;
01018       ast_queue_frame(o->owner, &f);
01019    }
01020    return CLI_SUCCESS;
01021 }

static char* console_transfer ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1151 of file chan_oss.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_async_goto(), ast_bridged_channel(), ast_cli(), ast_exists_extension(), ast_ext_ctx(), ast_free, ast_channel::cid, ast_callerid::cid_num, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_channel::context, ext, ast_cli_args::fd, find_desc(), ast_channel::name, chan_oss_pvt::owner, and ast_cli_entry::usage.

01152 {
01153    struct chan_oss_pvt *o = find_desc(oss_active);
01154    struct ast_channel *b = NULL;
01155    char *tmp, *ext, *ctx;
01156 
01157    switch (cmd) {
01158    case CLI_INIT:
01159       e->command = "console transfer";
01160       e->usage =
01161          "Usage: console transfer <extension>[@context]\n"
01162          "       Transfers the currently connected call to the given extension (and\n"
01163          "       context if specified)\n";
01164       return NULL;
01165    case CLI_GENERATE:
01166       return NULL;
01167    }
01168 
01169    if (a->argc != 3)
01170       return CLI_SHOWUSAGE;
01171    if (o == NULL)
01172       return CLI_FAILURE;
01173    if (o->owner == NULL || (b = ast_bridged_channel(o->owner)) == NULL) {
01174       ast_cli(a->fd, "There is no call to transfer\n");
01175       return CLI_SUCCESS;
01176    }
01177 
01178    tmp = ast_ext_ctx(a->argv[2], &ext, &ctx);
01179    if (ctx == NULL)        /* supply default context if needed */
01180       ctx = o->owner->context;
01181    if (!ast_exists_extension(b, ctx, ext, 1, b->cid.cid_num))
01182       ast_cli(a->fd, "No such extension exists\n");
01183    else {
01184       ast_cli(a->fd, "Whee, transferring %s to %s@%s.\n", b->name, ext, ctx);
01185       if (ast_async_goto(b, ctx, ext, 1))
01186          ast_cli(a->fd, "Failed to transfer :(\n");
01187    }
01188    if (tmp)
01189       ast_free(tmp);
01190    return CLI_SUCCESS;
01191 }

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

returns a pointer to the descriptor with the given name

forward declaration

Definition at line 370 of file chan_oss.c.

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

Referenced by ast_ext_ctx(), console_active(), console_autoanswer(), console_boost(), console_cmd(), console_dial(), console_do_answer(), console_flash(), console_hangup(), console_mute(), console_sendtext(), console_transfer(), get_video_desc(), handle_cli_radio_key(), handle_cli_radio_set_debug(), handle_cli_radio_set_debug_deprecated(), handle_cli_radio_tune(), handle_cli_radio_unkey(), keypad_toggle(), load_module(), oss_request(), and usbradio_request().

00371 {
00372    struct chan_oss_pvt *o = NULL;
00373 
00374    if (!dev)
00375       ast_log(LOG_WARNING, "null dev\n");
00376 
00377    for (o = oss_default.next; o && o->name && dev && strcmp(o->name, dev) != 0; o = o->next);
00378 
00379    if (!o)
00380       ast_log(LOG_WARNING, "could not find <%s>\n", dev ? dev : "--no-device--");
00381 
00382    return o;
00383 }

struct video_desc* get_video_desc ( struct ast_channel c  ) 

return the pointer to the video descriptor

Definition at line 313 of file chan_oss.c.

References chan_oss_pvt::env, find_desc(), and ast_channel::tech_pvt.

Referenced by oss_new().

00314 {
00315    struct chan_oss_pvt *o = c ? c->tech_pvt : find_desc(oss_active);
00316    return o ? o->env : NULL;
00317 }

static int load_module ( void   )  [static]

Definition at line 1418 of file chan_oss.c.

References ast_category_browse(), ast_channel_register(), ast_cli_register_multiple(), ast_config_destroy(), ast_config_load, ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_channel_tech::capabilities, cli_oss, console_video_formats, default_jbconf, find_desc(), global_jbconf, LOG_ERROR, LOG_NOTICE, oss_tech, and store_config().

01419 {
01420    struct ast_config *cfg = NULL;
01421    char *ctg = NULL;
01422    struct ast_flags config_flags = { 0 };
01423 
01424    /* Copy the default jb config over global_jbconf */
01425    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
01426 
01427    /* load config file */
01428    if (!(cfg = ast_config_load(config, config_flags))) {
01429       ast_log(LOG_NOTICE, "Unable to load config %s\n", config);
01430       return AST_MODULE_LOAD_DECLINE;
01431    }
01432 
01433    do {
01434       store_config(cfg, ctg);
01435    } while ( (ctg = ast_category_browse(cfg, ctg)) != NULL);
01436 
01437    ast_config_destroy(cfg);
01438 
01439    if (find_desc(oss_active) == NULL) {
01440       ast_log(LOG_NOTICE, "Device %s not found\n", oss_active);
01441       /* XXX we could default to 'dsp' perhaps ? */
01442       /* XXX should cleanup allocated memory etc. */
01443       return AST_MODULE_LOAD_FAILURE;
01444    }
01445 
01446    oss_tech.capabilities |= console_video_formats;
01447 
01448    if (ast_channel_register(&oss_tech)) {
01449       ast_log(LOG_ERROR, "Unable to register channel type 'OSS'\n");
01450       return AST_MODULE_LOAD_FAILURE;
01451    }
01452 
01453    ast_cli_register_multiple(cli_oss, sizeof(cli_oss) / sizeof(struct ast_cli_entry));
01454 
01455    return AST_MODULE_LOAD_SUCCESS;
01456 }

static int oss_answer ( struct ast_channel c  )  [static]

remote side answered the phone

Definition at line 638 of file chan_oss.c.

References ast_setstate(), AST_STATE_UP, ast_verbose(), chan_oss_pvt::hookstate, and ast_channel::tech_pvt.

00639 {
00640    struct chan_oss_pvt *o = c->tech_pvt;
00641    ast_verbose(" << Console call has been answered >> \n");
00642    ast_setstate(c, AST_STATE_UP);
00643    o->hookstate = 1;
00644    return 0;
00645 }

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

handler for incoming calls. Either autoanswer, or start ringing

Definition at line 597 of file chan_oss.c.

References AST_APP_ARG, AST_CONTROL_ANSWER, AST_CONTROL_RINGING, AST_DECLARE_APP_ARGS, AST_FRAME_CONTROL, ast_indicate(), AST_NONSTANDARD_APP_ARGS, ast_queue_frame(), ast_strdupa, ast_strlen_zero(), ast_verbose(), chan_oss_pvt::autoanswer, ast_channel::cid, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_rdnis, f, ast_frame::flags, chan_oss_pvt::hookstate, name, parse(), and ast_channel::tech_pvt.

00598 {
00599    struct chan_oss_pvt *o = c->tech_pvt;
00600    struct ast_frame f = { 0, };
00601    AST_DECLARE_APP_ARGS(args,
00602       AST_APP_ARG(name);
00603       AST_APP_ARG(flags);
00604    );
00605    char *parse = ast_strdupa(dest);
00606 
00607    AST_NONSTANDARD_APP_ARGS(args, parse, '/');
00608 
00609    ast_verbose(" << Call to device '%s' dnid '%s' rdnis '%s' on console from '%s' <%s> >>\n", dest, c->cid.cid_dnid, c->cid.cid_rdnis, c->cid.cid_name, c->cid.cid_num);
00610    if (!ast_strlen_zero(args.flags) && strcasecmp(args.flags, "answer") == 0) {
00611       f.frametype = AST_FRAME_CONTROL;
00612       f.subclass = AST_CONTROL_ANSWER;
00613       ast_queue_frame(c, &f);
00614    } else if (!ast_strlen_zero(args.flags) && strcasecmp(args.flags, "noanswer") == 0) {
00615       f.frametype = AST_FRAME_CONTROL;
00616       f.subclass = AST_CONTROL_RINGING;
00617       ast_queue_frame(c, &f);
00618       ast_indicate(c, AST_CONTROL_RINGING);
00619    } else if (o->autoanswer) {
00620       ast_verbose(" << Auto-answered >> \n");
00621       f.frametype = AST_FRAME_CONTROL;
00622       f.subclass = AST_CONTROL_ANSWER;
00623       ast_queue_frame(c, &f);
00624       o->hookstate = 1;
00625    } else {
00626       ast_verbose("<< Type 'answer' to answer, or use 'autoanswer' for future calls >> \n");
00627       f.frametype = AST_FRAME_CONTROL;
00628       f.subclass = AST_CONTROL_RINGING;
00629       ast_queue_frame(c, &f);
00630       ast_indicate(c, AST_CONTROL_RINGING);
00631    }
00632    return 0;
00633 }

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

Definition at line 574 of file chan_oss.c.

00575 {
00576    return 0;
00577 }

static int oss_digit_end ( struct ast_channel c,
char  digit,
unsigned int  duration 
) [static]

Definition at line 579 of file chan_oss.c.

References ast_verbose().

00580 {
00581    /* no better use for received digits than print them */
00582    ast_verbose(" << Console Received digit %c of duration %u ms >> \n", 
00583       digit, duration);
00584    return 0;
00585 }

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

Definition at line 747 of file chan_oss.c.

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

00748 {
00749    struct chan_oss_pvt *o = newchan->tech_pvt;
00750    o->owner = newchan;
00751    return 0;
00752 }

static int oss_hangup ( struct ast_channel c  )  [static]

Definition at line 647 of file chan_oss.c.

References ast_module_unref(), ast_verbose(), chan_oss_pvt::autoanswer, chan_oss_pvt::autohangup, console_video_uninit(), chan_oss_pvt::env, chan_oss_pvt::hookstate, O_CLOSE, chan_oss_pvt::owner, setformat(), and ast_channel::tech_pvt.

00648 {
00649    struct chan_oss_pvt *o = c->tech_pvt;
00650 
00651    c->tech_pvt = NULL;
00652    o->owner = NULL;
00653    ast_verbose(" << Hangup on console >> \n");
00654    console_video_uninit(o->env);
00655    ast_module_unref(ast_module_info->self);
00656    if (o->hookstate) {
00657       if (o->autoanswer || o->autohangup) {
00658          /* Assume auto-hangup too */
00659          o->hookstate = 0;
00660          setformat(o, O_CLOSE);
00661       }
00662    }
00663    return 0;
00664 }

static int oss_indicate ( struct ast_channel chan,
int  cond,
const void *  data,
size_t  datalen 
) [static]

Definition at line 754 of file chan_oss.c.

References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_log(), ast_moh_start(), ast_moh_stop(), ast_verbose(), LOG_WARNING, chan_oss_pvt::mohinterpret, ast_channel::name, and ast_channel::tech_pvt.

00755 {
00756    struct chan_oss_pvt *o = c->tech_pvt;
00757    int res = 0;
00758 
00759    switch (cond) {
00760    case AST_CONTROL_BUSY:
00761    case AST_CONTROL_CONGESTION:
00762    case AST_CONTROL_RINGING:
00763    case -1:
00764       res = -1;
00765       break;
00766    case AST_CONTROL_PROGRESS:
00767    case AST_CONTROL_PROCEEDING:
00768    case AST_CONTROL_VIDUPDATE:
00769    case AST_CONTROL_SRCUPDATE:
00770       break;
00771    case AST_CONTROL_HOLD:
00772       ast_verbose(" << Console Has Been Placed on Hold >> \n");
00773       ast_moh_start(c, data, o->mohinterpret);
00774       break;
00775    case AST_CONTROL_UNHOLD:
00776       ast_verbose(" << Console Has Been Retrieved from Hold >> \n");
00777       ast_moh_stop(c);
00778       break;
00779    default:
00780       ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name);
00781       return -1;
00782    }
00783 
00784    return res;
00785 }

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

allocate a new channel.

Definition at line 790 of file chan_oss.c.

References ast_channel_alloc, ast_channel_set_fd(), AST_FORMAT_SLINEAR, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), AST_STATE_DOWN, AST_STATE_RINGING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, chan_oss_pvt::cid_name, chan_oss_pvt::cid_num, console_video_formats, console_video_start(), chan_oss_pvt::device, get_video_desc(), global_jbconf, language, chan_oss_pvt::language, LOG_WARNING, ast_channel::nativeformats, oss_tech, chan_oss_pvt::owner, ast_channel::readformat, setformat(), chan_oss_pvt::sounddev, ast_channel::tech, ast_channel::tech_pvt, and ast_channel::writeformat.

Referenced by console_dial(), and oss_request().

00791 {
00792    struct ast_channel *c;
00793 
00794    c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, 0, "Console/%s", o->device + 5);
00795    if (c == NULL)
00796       return NULL;
00797    c->tech = &oss_tech;
00798    if (o->sounddev < 0)
00799       setformat(o, O_RDWR);
00800    ast_channel_set_fd(c, 0, o->sounddev); /* -1 if device closed, override later */
00801    c->nativeformats = AST_FORMAT_SLINEAR;
00802    /* if the console makes the call, add video to the offer */
00803    if (state == AST_STATE_RINGING)
00804       c->nativeformats |= console_video_formats;
00805 
00806    c->readformat = AST_FORMAT_SLINEAR;
00807    c->writeformat = AST_FORMAT_SLINEAR;
00808    c->tech_pvt = o;
00809 
00810    if (!ast_strlen_zero(o->language))
00811       ast_string_field_set(c, language, o->language);
00812    /* Don't use ast_set_callerid() here because it will
00813     * generate a needless NewCallerID event */
00814    c->cid.cid_ani = ast_strdup(o->cid_num);
00815    if (!ast_strlen_zero(ext))
00816       c->cid.cid_dnid = ast_strdup(ext);
00817 
00818    o->owner = c;
00819    ast_module_ref(ast_module_info->self);
00820    ast_jb_configure(c, &global_jbconf);
00821    if (state != AST_STATE_DOWN) {
00822       if (ast_pbx_start(c)) {
00823          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", c->name);
00824          ast_hangup(c);
00825          o->owner = c = NULL;
00826       }
00827    }
00828    console_video_start(get_video_desc(c), c); /* XXX cleanup */
00829 
00830    return c;
00831 }

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

Definition at line 698 of file chan_oss.c.

References ast_channel::_state, AST_FORMAT_SLINEAR, AST_FRAME_NULL, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, AST_STATE_UP, chan_oss_pvt::boost, BOOST_SCALE, f, FRAME_SIZE, chan_oss_pvt::mute, chan_oss_pvt::oss_read_buf, oss_tech, chan_oss_pvt::read_f, chan_oss_pvt::readpos, chan_oss_pvt::sounddev, ast_channel::tech_pvt, and ast_channel_tech::type.

00699 {
00700    int res;
00701    struct chan_oss_pvt *o = c->tech_pvt;
00702    struct ast_frame *f = &o->read_f;
00703 
00704    /* XXX can be simplified returning &ast_null_frame */
00705    /* prepare a NULL frame in case we don't have enough data to return */
00706    memset(f, '\0', sizeof(struct ast_frame));
00707    f->frametype = AST_FRAME_NULL;
00708    f->src = oss_tech.type;
00709 
00710    res = read(o->sounddev, o->oss_read_buf + o->readpos, sizeof(o->oss_read_buf) - o->readpos);
00711    if (res < 0)            /* audio data not ready, return a NULL frame */
00712       return f;
00713 
00714    o->readpos += res;
00715    if (o->readpos < sizeof(o->oss_read_buf)) /* not enough samples */
00716       return f;
00717 
00718    if (o->mute)
00719       return f;
00720 
00721    o->readpos = AST_FRIENDLY_OFFSET;   /* reset read pointer for next frame */
00722    if (c->_state != AST_STATE_UP)   /* drop data if frame is not up */
00723       return f;
00724    /* ok we can build and deliver the frame to the caller */
00725    f->frametype = AST_FRAME_VOICE;
00726    f->subclass = AST_FORMAT_SLINEAR;
00727    f->samples = FRAME_SIZE;
00728    f->datalen = FRAME_SIZE * 2;
00729    f->data = o->oss_read_buf + AST_FRIENDLY_OFFSET;
00730    if (o->boost != BOOST_SCALE) {   /* scale and clip values */
00731       int i, x;
00732       int16_t *p = (int16_t *) f->data;
00733       for (i = 0; i < f->samples; i++) {
00734          x = (p[i] * o->boost) / BOOST_SCALE;
00735          if (x > 32767)
00736             x = 32767;
00737          else if (x < -32768)
00738             x = -32768;
00739          p[i] = x;
00740       }
00741    }
00742 
00743    f->offset = AST_FRIENDLY_OFFSET;
00744    return f;
00745 }

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

Definition at line 833 of file chan_oss.c.

References AST_APP_ARG, AST_CAUSE_BUSY, AST_DECLARE_APP_ARGS, AST_FORMAT_SLINEAR, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STATE_DOWN, ast_strdupa, find_desc(), LOG_NOTICE, LOG_WARNING, name, oss_new(), chan_oss_pvt::owner, and parse().

00834 {
00835    struct ast_channel *c;
00836    struct chan_oss_pvt *o;
00837    AST_DECLARE_APP_ARGS(args,
00838       AST_APP_ARG(name);
00839       AST_APP_ARG(flags);
00840    );
00841    char *parse = ast_strdupa(data);
00842 
00843    AST_NONSTANDARD_APP_ARGS(args, parse, '/');
00844    o = find_desc(args.name);
00845 
00846    ast_log(LOG_WARNING, "oss_request ty <%s> data 0x%p <%s>\n", type, data, (char *) data);
00847    if (o == NULL) {
00848       ast_log(LOG_NOTICE, "Device %s not found\n", args.name);
00849       /* XXX we could default to 'dsp' perhaps ? */
00850       return NULL;
00851    }
00852    if ((format & AST_FORMAT_SLINEAR) == 0) {
00853       ast_log(LOG_NOTICE, "Format 0x%x unsupported\n", format);
00854       return NULL;
00855    }
00856    if (o->owner) {
00857       ast_log(LOG_NOTICE, "Already have a call (chan %p) on the OSS channel\n", o->owner);
00858       *cause = AST_CAUSE_BUSY;
00859       return NULL;
00860    }
00861    c = oss_new(o, NULL, NULL, AST_STATE_DOWN);
00862    if (c == NULL) {
00863       ast_log(LOG_WARNING, "Unable to create new OSS channel\n");
00864       return NULL;
00865    }
00866    return c;
00867 }

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

Definition at line 587 of file chan_oss.c.

References ast_verbose().

00588 {
00589    /* print received messages */
00590    ast_verbose(" << Console Received text %s >> \n", text);
00591    return 0;
00592 }

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

used for data coming from the network

Definition at line 667 of file chan_oss.c.

References f, chan_oss_pvt::oss_write_buf, chan_oss_pvt::oss_write_dst, soundcard_writeframe(), and ast_channel::tech_pvt.

00668 {
00669    int src;
00670    struct chan_oss_pvt *o = c->tech_pvt;
00671 
00672    /*
00673     * we could receive a block which is not a multiple of our
00674     * FRAME_SIZE, so buffer it locally and write to the device
00675     * in FRAME_SIZE chunks.
00676     * Keep the residue stored for future use.
00677     */
00678    src = 0;             /* read position into f->data */
00679    while (src < f->datalen) {
00680       /* Compute spare room in the buffer */
00681       int l = sizeof(o->oss_write_buf) - o->oss_write_dst;
00682 
00683       if (f->datalen - src >= l) {  /* enough to fill a frame */
00684          memcpy(o->oss_write_buf + o->oss_write_dst, f->data + src, l);
00685          soundcard_writeframe(o, (short *) o->oss_write_buf);
00686          src += l;
00687          o->oss_write_dst = 0;
00688       } else {          /* copy residue */
00689          l = f->datalen - src;
00690          memcpy(o->oss_write_buf + o->oss_write_dst, f->data + src, l);
00691          src += l;         /* but really, we are done */
00692          o->oss_write_dst += l;
00693       }
00694    }
00695    return 0;
00696 }

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

reset and close the device if opened, then open and initialize it in the desired mode, trigger reads and writes so we can start using it.

Definition at line 475 of file chan_oss.c.

References ast_channel_set_fd(), ast_log(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, DEFAULT_SAMPLE_RATE, chan_oss_pvt::device, chan_oss_pvt::duplex, errno, chan_oss_pvt::frags, chan_oss_pvt::lastopen, LOG_WARNING, O_CLOSE, chan_oss_pvt::owner, chan_oss_pvt::sounddev, WARN_frag, WARN_speed, and chan_oss_pvt::warned.

Referenced by console_hangup(), oss_hangup(), oss_new(), soundcard_writeframe(), usbradio_hangup(), and usbradio_new().

00476 {
00477    int fmt, desired, res, fd;
00478 
00479    if (o->sounddev >= 0) {
00480       ioctl(o->sounddev, SNDCTL_DSP_RESET, 0);
00481       close(o->sounddev);
00482       o->duplex = M_UNSET;
00483       o->sounddev = -1;
00484    }
00485    if (mode == O_CLOSE)    /* we are done */
00486       return 0;
00487    if (ast_tvdiff_ms(ast_tvnow(), o->lastopen) < 1000)
00488       return -1;           /* don't open too often */
00489    o->lastopen = ast_tvnow();
00490    fd = o->sounddev = open(o->device, mode | O_NONBLOCK);
00491    if (fd < 0) {
00492       ast_log(LOG_WARNING, "Unable to re-open DSP device %s: %s\n", o->device, strerror(errno));
00493       return -1;
00494    }
00495    if (o->owner)
00496       ast_channel_set_fd(o->owner, 0, fd);
00497 
00498 #if __BYTE_ORDER == __LITTLE_ENDIAN
00499    fmt = AFMT_S16_LE;
00500 #else
00501    fmt = AFMT_S16_BE;
00502 #endif
00503    res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt);
00504    if (res < 0) {
00505       ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n");
00506       return -1;
00507    }
00508    switch (mode) {
00509    case O_RDWR:
00510       res = ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
00511       /* Check to see if duplex set (FreeBSD Bug) */
00512       res = ioctl(fd, SNDCTL_DSP_GETCAPS, &fmt);
00513       if (res == 0 && (fmt & DSP_CAP_DUPLEX)) {
00514          ast_verb(2, "Console is full duplex\n");
00515          o->duplex = M_FULL;
00516       };
00517       break;
00518 
00519    case O_WRONLY:
00520       o->duplex = M_WRITE;
00521       break;
00522 
00523    case O_RDONLY:
00524       o->duplex = M_READ;
00525       break;
00526    }
00527 
00528    fmt = 0;
00529    res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt);
00530    if (res < 0) {
00531       ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
00532       return -1;
00533    }
00534    fmt = desired = DEFAULT_SAMPLE_RATE;   /* 8000 Hz desired */
00535    res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt);
00536 
00537    if (res < 0) {
00538       ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
00539       return -1;
00540    }
00541    if (fmt != desired) {
00542       if (!(o->warned & WARN_speed)) {
00543          ast_log(LOG_WARNING,
00544              "Requested %d Hz, got %d Hz -- sound may be choppy\n",
00545              desired, fmt);
00546          o->warned |= WARN_speed;
00547       }
00548    }
00549    /*
00550     * on Freebsd, SETFRAGMENT does not work very well on some cards.
00551     * Default to use 256 bytes, let the user override
00552     */
00553    if (o->frags) {
00554       fmt = o->frags;
00555       res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt);
00556       if (res < 0) {
00557          if (!(o->warned & WARN_frag)) {
00558             ast_log(LOG_WARNING,
00559                "Unable to set fragment size -- sound may be choppy\n");
00560             o->warned |= WARN_frag;
00561          }
00562       }
00563    }
00564    /* on some cards, we need SNDCTL_DSP_SETTRIGGER to start outputting */
00565    res = PCM_ENABLE_INPUT | PCM_ENABLE_OUTPUT;
00566    res = ioctl(fd, SNDCTL_DSP_SETTRIGGER, &res);
00567    /* it may fail if we are in half duplex, never mind */
00568    return 0;
00569 }

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

Write an exactly FRAME_SIZE sized frame

Definition at line 446 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().

00447 {
00448    int res;
00449 
00450    if (o->sounddev < 0)
00451       setformat(o, O_RDWR);
00452    if (o->sounddev < 0)
00453       return 0;            /* not fatal */
00454    /*
00455     * Nothing complex to manage the audio device queue.
00456     * If the buffer is full just drop the extra, otherwise write.
00457     * XXX in some cases it might be useful to write anyways after
00458     * a number of failures, to restart the output chain.
00459     */
00460    res = used_blocks(o);
00461    if (res > o->queuesize) {  /* no room to write a block */
00462       if (o->w_errors++ == 0 && (oss_debug & 0x4))
00463          ast_log(LOG_WARNING, "write: used %d blocks (%d)\n", res, o->w_errors);
00464       return 0;
00465    }
00466    o->w_errors = 0;
00467    return write(o->sounddev, (void *)data, FRAME_SIZE * 2);
00468 }

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

store the boost factor

Definition at line 1231 of file chan_oss.c.

References ast_log(), chan_oss_pvt::boost, BOOST_MAX, BOOST_SCALE, and LOG_WARNING.

Referenced by console_boost(), and store_config_core().

01232 {
01233    double boost = 0;
01234    if (sscanf(s, "%lf", &boost) != 1) {
01235       ast_log(LOG_WARNING, "invalid boost <%s>\n", s);
01236       return;
01237    }
01238    if (boost < -BOOST_MAX) {
01239       ast_log(LOG_WARNING, "boost %s too small, using %d\n", s, -BOOST_MAX);
01240       boost = -BOOST_MAX;
01241    } else if (boost > BOOST_MAX) {
01242       ast_log(LOG_WARNING, "boost %s too large, using %d\n", s, BOOST_MAX);
01243       boost = BOOST_MAX;
01244    }
01245    boost = exp(log(10) * boost / 20) * BOOST_SCALE;
01246    o->boost = boost;
01247    ast_log(LOG_WARNING, "setting boost %s to %d\n", s, o->boost);
01248 }

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

store the callerid components

Definition at line 1310 of file chan_oss.c.

References ast_callerid_split(), chan_oss_pvt::cid_name, and chan_oss_pvt::cid_num.

01311 {
01312    ast_callerid_split(s, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num));
01313 }

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

grab fields from the config file, init the descriptor and open the device.

Definition at line 1346 of file chan_oss.c.

References asprintf, ast_calloc, ast_copy_string(), ast_log(), ast_strdup, ast_strlen_zero(), ast_tvnow(), ast_variable_browse(), DEV_DSP, chan_oss_pvt::device, errno, chan_oss_pvt::lastopen, LOG_WARNING, chan_oss_pvt::mixer_cmd, chan_oss_pvt::mohinterpret, ast_variable::name, chan_oss_pvt::name, ast_variable::next, oss_default, store_config_core(), and ast_variable::value.

Referenced by load_module().

01347 {
01348    struct ast_variable *v;
01349    struct chan_oss_pvt *o;
01350 
01351    if (ctg == NULL) {
01352       o = &oss_default;
01353       ctg = "general";
01354    } else {
01355       if (!(o = ast_calloc(1, sizeof(*o))))
01356          return NULL;
01357       *o = oss_default;
01358       /* "general" is also the default thing */
01359       if (strcmp(ctg, "general") == 0) {
01360          o->name = ast_strdup("dsp");
01361          oss_active = o->name;
01362          goto openit;
01363       }
01364       o->name = ast_strdup(ctg);
01365    }
01366 
01367    strcpy(o->mohinterpret, "default");
01368 
01369    o->lastopen = ast_tvnow(); /* don't leave it 0 or tvdiff may wrap */
01370    /* fill other fields from configuration */
01371    for (v = ast_variable_browse(cfg, ctg); v; v = v->next) {
01372       store_config_core(o, v->name, v->value);
01373    }
01374    if (ast_strlen_zero(o->device))
01375       ast_copy_string(o->device, DEV_DSP, sizeof(o->device));
01376    if (o->mixer_cmd) {
01377       char *cmd;
01378 
01379       if (asprintf(&cmd, "mixer %s", o->mixer_cmd) < 0) {
01380          ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
01381       } else {
01382          ast_log(LOG_WARNING, "running [%s]\n", cmd);
01383          if (system(cmd) < 0) {
01384             ast_log(LOG_WARNING, "system() failed: %s\n", strerror(errno));
01385          }
01386          ast_free(cmd);
01387       }
01388    }
01389    if (o == &oss_default)     /* we are done with the default */
01390       return NULL;
01391 
01392 openit:
01393 #ifdef TRYOPEN
01394    if (setformat(o, O_RDWR) < 0) {  /* open device */
01395       ast_verb(1, "Device %s not detected\n", ctg);
01396       ast_verb(1, "Turn off OSS support by adding " "'noload=chan_oss.so' in /etc/asterisk/modules.conf\n");
01397       goto error;
01398    }
01399    if (o->duplex != M_FULL)
01400       ast_log(LOG_WARNING, "XXX I don't work right with non " "full-duplex sound cards XXX\n");
01401 #endif /* TRYOPEN */
01402 
01403    /* link into list of devices */
01404    if (o != &oss_default) {
01405       o->next = oss_default.next;
01406       oss_default.next = o;
01407    }
01408    return o;
01409 
01410 #ifdef TRYOPEN
01411 error:
01412    if (o != &oss_default)
01413       ast_free(o);
01414    return NULL;
01415 #endif
01416 }

static void store_config_core ( struct chan_oss_pvt o,
const char *  var,
const char *  value 
) [static]

Definition at line 1315 of file chan_oss.c.

References ast_jb_read_conf(), chan_oss_pvt::autoanswer, chan_oss_pvt::autohangup, console_video_config(), chan_oss_pvt::ctx, CV_BOOL, CV_END, CV_F, CV_START, CV_STR, CV_UINT, chan_oss_pvt::device, chan_oss_pvt::env, chan_oss_pvt::ext, chan_oss_pvt::frags, global_jbconf, chan_oss_pvt::language, chan_oss_pvt::mohinterpret, chan_oss_pvt::overridecontext, chan_oss_pvt::queuesize, store_boost(), store_callerid(), and store_mixer().

01316 {
01317    CV_START(var, value);
01318 
01319    /* handle jb conf */
01320    if (!ast_jb_read_conf(&global_jbconf, var, value))
01321       return;
01322 
01323    if (!console_video_config(&o->env, var, value))
01324       return;  /* matched there */
01325    CV_BOOL("autoanswer", o->autoanswer);
01326    CV_BOOL("autohangup", o->autohangup);
01327    CV_BOOL("overridecontext", o->overridecontext);
01328    CV_STR("device", o->device);
01329    CV_UINT("frags", o->frags);
01330    CV_UINT("debug", oss_debug);
01331    CV_UINT("queuesize", o->queuesize);
01332    CV_STR("context", o->ctx);
01333    CV_STR("language", o->language);
01334    CV_STR("mohinterpret", o->mohinterpret);
01335    CV_STR("extension", o->ext);
01336    CV_F("mixer", store_mixer(o, value));
01337    CV_F("callerid", store_callerid(o, value))  ;
01338    CV_F("boost", store_boost(o, value));
01339 
01340    CV_END;
01341 }

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

store the mixer argument from the config file, filtering possibly invalid or dangerous values (the string is used as argument for system("mixer %s")

Definition at line 1291 of file chan_oss.c.

References ast_free, ast_log(), ast_strdup, LOG_WARNING, and chan_oss_pvt::mixer_cmd.

Referenced by store_config_core().

01292 {
01293    int i;
01294 
01295    for (i = 0; i < strlen(s); i++) {
01296       if (!isalnum(s[i]) && strchr(" \t-/", s[i]) == NULL) {
01297          ast_log(LOG_WARNING, "Suspect char %c in mixer cmd, ignoring:\n\t%s\n", s[i], s);
01298          return;
01299       }
01300    }
01301    if (o->mixer_cmd)
01302       ast_free(o->mixer_cmd);
01303    o->mixer_cmd = ast_strdup(s);
01304    ast_log(LOG_WARNING, "setting mixer %s\n", s);
01305 }

static int unload_module ( void   )  [static]

Definition at line 1459 of file chan_oss.c.

References ast_channel_unregister(), ast_cli_unregister_multiple(), ast_free, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, cli_oss, chan_oss_pvt::name, chan_oss_pvt::next, oss_default, oss_tech, chan_oss_pvt::owner, and chan_oss_pvt::sounddev.

01460 {
01461    struct chan_oss_pvt *o, *next;
01462 
01463    ast_channel_unregister(&oss_tech);
01464    ast_cli_unregister_multiple(cli_oss, sizeof(cli_oss) / sizeof(struct ast_cli_entry));
01465 
01466    o = oss_default.next;
01467    while (o) {
01468       close(o->sounddev);
01469       if (o->owner)
01470          ast_softhangup(o->owner, AST_SOFTHANGUP_APPUNLOAD);
01471       if (o->owner)
01472          return -1;
01473       next = o->next;
01474       ast_free(o->name);
01475       ast_free(o);
01476       o = next;
01477    }
01478    return 0;
01479 }

static int used_blocks ( struct chan_oss_pvt o  )  [static]

Returns the number of blocks used in the audio output channel.

Definition at line 424 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().

00425 {
00426    struct audio_buf_info info;
00427 
00428    if (ioctl(o->sounddev, SNDCTL_DSP_GETOSPACE, &info)) {
00429       if (!(o->warned & WARN_used_blocks)) {
00430          ast_log(LOG_WARNING, "Error reading output space\n");
00431          o->warned |= WARN_used_blocks;
00432       }
00433       return 1;
00434    }
00435 
00436    if (o->total_blocks == 0) {
00437       if (0)               /* debugging */
00438          ast_log(LOG_WARNING, "fragtotal %d size %d avail %d\n", info.fragstotal, info.fragsize, info.fragments);
00439       o->total_blocks = info.fragments;
00440    }
00441 
00442    return o->total_blocks - info.fragments;
00443 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "OSS Console Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, } [static]

Definition at line 1481 of file chan_oss.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1481 of file chan_oss.c.

struct ast_cli_entry cli_oss[] [static]

Definition at line 1272 of file chan_oss.c.

Referenced by load_module(), and unload_module().

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

Definition at line 239 of file chan_oss.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 69 of file chan_oss.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 76 of file chan_oss.c.

char* oss_active [static]

the active device

Definition at line 310 of file chan_oss.c.

Referenced by keypad_toggle().

int oss_debug [static]

Definition at line 241 of file chan_oss.c.

struct chan_oss_pvt oss_default [static]

Definition at line 318 of file chan_oss.c.

Referenced by console_active(), find_desc(), store_config(), and unload_module().

struct ast_channel_tech oss_tech [static]

Definition at line 349 of file chan_oss.c.

Referenced by load_module(), oss_new(), oss_read(), and unload_module().

char tdesc[] = "OSS Console Channel Driver" [static]

Definition at line 346 of file chan_oss.c.


Generated on Thu Jul 9 13:41:02 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7