Tue Mar 2 17:32:56 2010

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"
Include dependency graph for chan_oss.c:

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 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
struct 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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, }
static 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 272 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 271 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 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 261 of file chan_oss.c.

Referenced by setformat().

#define WARN_speed   2

Definition at line 260 of file chan_oss.c.

Referenced by setformat().

#define WARN_used_blocks   1

Definition at line 259 of file chan_oss.c.

Referenced by used_blocks().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1487 of file chan_oss.c.

static void __unreg_module ( void   )  [static]

Definition at line 1487 of file chan_oss.c.

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

Definition at line 389 of file chan_oss.c.

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

Referenced by console_dial(), and console_transfer().

00390 {
00391    struct chan_oss_pvt *o = find_desc(oss_active);
00392 
00393    if (ext == NULL || ctx == NULL)
00394       return NULL;         /* error */
00395 
00396    *ext = *ctx = NULL;
00397 
00398    if (src && *src != '\0')
00399       *ext = ast_strdup(src);
00400 
00401    if (*ext == NULL)
00402       return NULL;
00403 
00404    if (!o->overridecontext) {
00405       /* parse from the right */
00406       *ctx = strrchr(*ext, '@');
00407       if (*ctx)
00408          *(*ctx)++ = '\0';
00409    }
00410 
00411    return *ext;
00412 }

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

Definition at line 1194 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, and ast_cli_entry::usage.

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

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 959 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.

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

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

Definition at line 903 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.

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

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

Definition at line 1251 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.

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

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 867 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, chan_oss_pvt::device, chan_oss_pvt::env, ast_cli_args::fd, find_desc(), LOG_WARNING, store_config_core(), ast_cli_entry::usage, and var.

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

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

Definition at line 1069 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, ast_cli_args::fd, find_desc(), chan_oss_pvt::hookstate, oss_new(), chan_oss_pvt::owner, s, ast_frame::subclass, and ast_cli_entry::usage.

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

static char* console_do_answer ( int  fd  )  [static]

helper function for the answer key/cli command

Definition at line 942 of file chan_oss.c.

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

Referenced by console_answer().

00943 {
00944    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
00945    struct chan_oss_pvt *o = find_desc(oss_active);
00946    if (!o->owner) {
00947       if (fd > -1)
00948          ast_cli(fd, "No one is calling us\n");
00949       return CLI_FAILURE;
00950    }
00951    o->hookstate = 1;
00952    ast_queue_frame(o->owner, &f);
00953    return CLI_SUCCESS;
00954 }

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

Definition at line 1043 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, ast_cli_args::fd, find_desc(), chan_oss_pvt::hookstate, chan_oss_pvt::owner, and ast_cli_entry::usage.

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

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

Definition at line 1017 of file chan_oss.c.

References ast_cli_args::argc, ast_cli_entry::args, AST_CAUSE_NORMAL_CLEARING, ast_cli(), ast_queue_hangup_with_cause(), 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.

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

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

Definition at line 1119 of file chan_oss.c.

References ast_cli_args::argc, ast_cli_entry::args, 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::mute, s, and ast_cli_entry::usage.

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

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 983 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, ast_frame::data, ast_frame::datalen, ast_cli_args::fd, find_desc(), ast_frame::frametype, chan_oss_pvt::owner, ast_frame::ptr, ast_frame::subclass, TEXT_SIZE, and ast_cli_entry::usage.

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

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

Definition at line 1152 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(), chan_oss_pvt::owner, and ast_cli_entry::usage.

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

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

returns a pointer to the descriptor with the given name

forward declaration

Definition at line 363 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_autoanswer(), console_boost(), console_cmd(), console_dial(), console_do_answer(), console_flash(), console_hangup(), console_mute(), console_sendtext(), console_transfer(), get_video_desc(), load_module(), and oss_request().

00364 {
00365    struct chan_oss_pvt *o = NULL;
00366 
00367    if (!dev)
00368       ast_log(LOG_WARNING, "null dev\n");
00369 
00370    for (o = oss_default.next; o && o->name && dev && strcmp(o->name, dev) != 0; o = o->next);
00371 
00372    if (!o)
00373       ast_log(LOG_WARNING, "could not find <%s>\n", dev ? dev : "--no-device--");
00374 
00375    return o;
00376 }

struct video_desc* get_video_desc ( struct ast_channel c  )  [read]

return the pointer to the video descriptor

Definition at line 306 of file chan_oss.c.

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

Referenced by oss_new().

00307 {
00308    struct chan_oss_pvt *o = c ? c->tech_pvt : find_desc(oss_active);
00309    return o ? o->env : NULL;
00310 }

static int load_module ( void   )  [static]

Definition at line 1424 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, console_video_formats, find_desc(), global_jbconf, LOG_ERROR, LOG_NOTICE, and store_config().

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

static int oss_answer ( struct ast_channel c  )  [static]

remote side answered the phone

Definition at line 631 of file chan_oss.c.

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

00632 {
00633    struct chan_oss_pvt *o = c->tech_pvt;
00634    ast_verbose(" << Console call has been answered >> \n");
00635    ast_setstate(c, AST_STATE_UP);
00636    o->hookstate = 1;
00637    return 0;
00638 }

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 590 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, ast_frame::flags, ast_frame::frametype, chan_oss_pvt::hookstate, name, parse(), ast_frame::subclass, and ast_channel::tech_pvt.

00591 {
00592    struct chan_oss_pvt *o = c->tech_pvt;
00593    struct ast_frame f = { 0, };
00594    AST_DECLARE_APP_ARGS(args,
00595       AST_APP_ARG(name);
00596       AST_APP_ARG(flags);
00597    );
00598    char *parse = ast_strdupa(dest);
00599 
00600    AST_NONSTANDARD_APP_ARGS(args, parse, '/');
00601 
00602    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);
00603    if (!ast_strlen_zero(args.flags) && strcasecmp(args.flags, "answer") == 0) {
00604       f.frametype = AST_FRAME_CONTROL;
00605       f.subclass = AST_CONTROL_ANSWER;
00606       ast_queue_frame(c, &f);
00607    } else if (!ast_strlen_zero(args.flags) && strcasecmp(args.flags, "noanswer") == 0) {
00608       f.frametype = AST_FRAME_CONTROL;
00609       f.subclass = AST_CONTROL_RINGING;
00610       ast_queue_frame(c, &f);
00611       ast_indicate(c, AST_CONTROL_RINGING);
00612    } else if (o->autoanswer) {
00613       ast_verbose(" << Auto-answered >> \n");
00614       f.frametype = AST_FRAME_CONTROL;
00615       f.subclass = AST_CONTROL_ANSWER;
00616       ast_queue_frame(c, &f);
00617       o->hookstate = 1;
00618    } else {
00619       ast_verbose("<< Type 'answer' to answer, or use 'autoanswer' for future calls >> \n");
00620       f.frametype = AST_FRAME_CONTROL;
00621       f.subclass = AST_CONTROL_RINGING;
00622       ast_queue_frame(c, &f);
00623       ast_indicate(c, AST_CONTROL_RINGING);
00624    }
00625    return 0;
00626 }

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

Definition at line 567 of file chan_oss.c.

00568 {
00569    return 0;
00570 }

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

Definition at line 572 of file chan_oss.c.

References ast_verbose.

00573 {
00574    /* no better use for received digits than print them */
00575    ast_verbose(" << Console Received digit %c of duration %u ms >> \n", 
00576       digit, duration);
00577    return 0;
00578 }

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

Definition at line 740 of file chan_oss.c.

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

00741 {
00742    struct chan_oss_pvt *o = newchan->tech_pvt;
00743    o->owner = newchan;
00744    return 0;
00745 }

static int oss_hangup ( struct ast_channel c  )  [static]

Definition at line 640 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.

00641 {
00642    struct chan_oss_pvt *o = c->tech_pvt;
00643 
00644    c->tech_pvt = NULL;
00645    o->owner = NULL;
00646    ast_verbose(" << Hangup on console >> \n");
00647    console_video_uninit(o->env);
00648    ast_module_unref(ast_module_info->self);
00649    if (o->hookstate) {
00650       if (o->autoanswer || o->autohangup) {
00651          /* Assume auto-hangup too */
00652          o->hookstate = 0;
00653          setformat(o, O_CLOSE);
00654       }
00655    }
00656    return 0;
00657 }

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

Definition at line 747 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, and ast_channel::tech_pvt.

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

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

allocate a new channel.

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

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

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

Definition at line 691 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, ast_frame::data, ast_frame::datalen, f, FRAME_SIZE, ast_frame::frametype, chan_oss_pvt::mute, ast_frame::offset, chan_oss_pvt::oss_read_buf, ast_frame::ptr, 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 ast_channel_tech::type.

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

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

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

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

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

Definition at line 580 of file chan_oss.c.

References ast_verbose.

00581 {
00582    /* print received messages */
00583    ast_verbose(" << Console Received text %s >> \n", text);
00584    return 0;
00585 }

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

used for data coming from the network

Definition at line 660 of file chan_oss.c.

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

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

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 468 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(), and store_config().

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

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

Write an exactly FRAME_SIZE sized frame

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

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

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

store the boost factor

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

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

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

store the callerid components

Definition at line 1311 of file chan_oss.c.

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

Referenced by store_config_core().

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

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

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

Definition at line 1347 of file chan_oss.c.

References asprintf, ast_calloc, ast_copy_string(), ast_free, ast_log(), ast_strdup, ast_strlen_zero(), ast_tvnow(), ast_variable_browse(), ast_verb, console_video_start(), DEV_DSP, chan_oss_pvt::device, chan_oss_pvt::duplex, chan_oss_pvt::env, errno, get_gui_startup(), chan_oss_pvt::lastopen, LOG_WARNING, chan_oss_pvt::M_FULL, chan_oss_pvt::mixer_cmd, chan_oss_pvt::mohinterpret, ast_variable::name, chan_oss_pvt::name, chan_oss_pvt::next, ast_variable::next, setformat(), store_config_core(), and ast_variable::value.

Referenced by load_module().

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

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

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

Referenced by console_cmd(), and store_config().

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

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 1292 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().

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

static int unload_module ( void   )  [static]

Definition at line 1465 of file chan_oss.c.

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

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

static int used_blocks ( struct chan_oss_pvt o  )  [static]

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

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

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


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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } [static]

Definition at line 1487 of file chan_oss.c.

Definition at line 1487 of file chan_oss.c.

struct ast_cli_entry cli_oss[] [static]

Definition at line 1273 of file chan_oss.c.

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

Definition at line 232 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.

Referenced by load_module(), oss_new(), and store_config_core().

char* oss_active [static]

the active device

Definition at line 303 of file chan_oss.c.

int oss_debug [static]

Definition at line 234 of file chan_oss.c.

struct chan_oss_pvt oss_default [static]

Definition at line 311 of file chan_oss.c.

struct ast_channel_tech oss_tech [static]

Definition at line 342 of file chan_oss.c.

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

Definition at line 339 of file chan_oss.c.


Generated on 2 Mar 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1