Wed Aug 18 22:34:11 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"

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
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 273 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 272 of file chan_oss.c.

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

#define DEV_DSP   "/dev/dsp"

Definition at line 230 of file chan_oss.c.

Referenced by store_config().

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

Definition at line 213 of file chan_oss.c.

#define FRAME_SIZE   160

Definition at line 207 of file chan_oss.c.

#define O_CLOSE   0x444

Definition at line 225 of file chan_oss.c.

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

#define QUEUE_SIZE   10

Definition at line 208 of file chan_oss.c.

#define TEXT_SIZE   256

Definition at line 220 of file chan_oss.c.

#define WARN_frag   4

Definition at line 262 of file chan_oss.c.

Referenced by setformat().

#define WARN_speed   2

Definition at line 261 of file chan_oss.c.

Referenced by setformat().

#define WARN_used_blocks   1

Definition at line 260 of file chan_oss.c.

Referenced by used_blocks().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1488 of file chan_oss.c.

static void __unreg_module ( void   )  [static]

Definition at line 1488 of file chan_oss.c.

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

Definition at line 390 of file chan_oss.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static char* console_do_answer ( int  fd  )  [static]

helper function for the answer key/cli command

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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 364 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_key(), console_mute(), console_sendtext(), console_transfer(), console_unkey(), get_video_desc(), keypad_toggle(), load_module(), oss_request(), radio_active(), radio_set_debug(), radio_set_debug_off(), radio_set_xpmr_debug(), radio_tune(), usbradio_request(), and usbradio_text().

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

struct video_desc* get_video_desc ( struct ast_channel c  ) 

return the pointer to the video descriptor

Definition at line 307 of file chan_oss.c.

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

Referenced by oss_new().

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

static int load_module ( void   )  [static]

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

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

static int oss_answer ( struct ast_channel c  )  [static]

remote side answered the phone

Definition at line 632 of file chan_oss.c.

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

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

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

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

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

Definition at line 568 of file chan_oss.c.

00569 {
00570    return 0;
00571 }

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

Definition at line 573 of file chan_oss.c.

References ast_verbose.

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

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

Definition at line 741 of file chan_oss.c.

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

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

static int oss_hangup ( struct ast_channel c  )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 581 of file chan_oss.c.

References ast_verbose.

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

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

used for data coming from the network

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

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

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

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

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

Write an exactly FRAME_SIZE sized frame

Definition at line 440 of file chan_oss.c.

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

Referenced by oss_write(), and usbradio_read().

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

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

store the boost factor

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

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

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

store the callerid components

Definition at line 1312 of file chan_oss.c.

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

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

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

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

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

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

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

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

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

static int unload_module ( void   )  [static]

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

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

static int used_blocks ( struct chan_oss_pvt o  )  [static]

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

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

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


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 1488 of file chan_oss.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1488 of file chan_oss.c.

struct ast_cli_entry cli_oss[] [static]

Definition at line 1274 of file chan_oss.c.

Referenced by load_module(), and unload_module().

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

Definition at line 233 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 77 of file chan_oss.c.

char* oss_active [static]

the active device

Definition at line 304 of file chan_oss.c.

Referenced by keypad_toggle().

int oss_debug [static]

Definition at line 235 of file chan_oss.c.

struct chan_oss_pvt oss_default [static]

Definition at line 312 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 343 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 340 of file chan_oss.c.


Generated on Wed Aug 18 22:34:11 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7