Fri Jun 19 12:10:17 2009

Asterisk developer's documentation


chan_oss.c File Reference

Channel driver for OSS sound cards. More...

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

Go to the source code of this file.

Data Structures

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

Defines

#define BOOST_MAX   40
#define BOOST_SCALE   (1<<9)
#define DEV_DSP   "/dev/dsp"
#define FRAGS   ( ( (6 * 5) << 16 ) | 0x6 )
#define FRAME_SIZE   160
#define MAX(a, b)   ((a) > (b) ? (a) : (b))
#define MIN(a, b)   ((a) < (b) ? (a) : (b))
#define O_CLOSE   0x444
#define QUEUE_SIZE   10
#define TEXT_SIZE   256
#define WARN_frag   4
#define WARN_speed   2
#define WARN_used_blocks   1

Functions

static void __reg_module (void)
static void __unreg_module (void)
static char * ast_ext_ctx (const char *src, char **ext, char **ctx)
static char * console_active (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_answer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 answer command from the console
static char * console_autoanswer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_boost (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_dial (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_do_answer (int fd)
 helper function for the answer key/cli command
static char * console_flash (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_hangup (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_mute (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_sendtext (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Console send text CLI command.
static char * console_transfer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct chan_oss_pvtfind_desc (char *dev)
 returns a pointer to the descriptor with the given name
video_desc * get_video_desc (struct ast_channel *c)
 return the pointer to the video descriptor
static int load_module (void)
static int oss_answer (struct ast_channel *c)
 remote side answered the phone
static int oss_call (struct ast_channel *c, char *dest, int timeout)
 handler for incoming calls. Either autoanswer, or start ringing
static int oss_digit_begin (struct ast_channel *c, char digit)
static int oss_digit_end (struct ast_channel *c, char digit, unsigned int duration)
static int oss_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static int oss_hangup (struct ast_channel *c)
static int oss_indicate (struct ast_channel *chan, int cond, const void *data, size_t datalen)
static struct ast_channeloss_new (struct chan_oss_pvt *o, char *ext, char *ctx, int state)
 allocate a new channel.
static struct ast_frameoss_read (struct ast_channel *chan)
static struct ast_channeloss_request (const char *type, int format, void *data, int *cause)
static int oss_text (struct ast_channel *c, const char *text)
static int oss_write (struct ast_channel *c, struct ast_frame *f)
 used for data coming from the network
static int setformat (struct chan_oss_pvt *o, int mode)
static int soundcard_writeframe (struct chan_oss_pvt *o, short *data)
static void store_boost (struct chan_oss_pvt *o, const char *s)
 store the boost factor
static void store_callerid (struct chan_oss_pvt *o, const char *s)
static struct chan_oss_pvtstore_config (struct ast_config *cfg, char *ctg)
static void store_config_core (struct chan_oss_pvt *o, const char *var, const char *value)
static void store_mixer (struct chan_oss_pvt *o, const char *s)
static int unload_module (void)
static int used_blocks (struct chan_oss_pvt *o)
 Returns the number of blocks used in the audio output channel.

Variables

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

Referenced by store_boost().

#define BOOST_SCALE   (1<<9)

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

Definition at line 278 of file chan_oss.c.

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

#define DEV_DSP   "/dev/dsp"

Definition at line 229 of file chan_oss.c.

Referenced by store_config().

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

Definition at line 212 of file chan_oss.c.

#define FRAME_SIZE   160

Definition at line 206 of file chan_oss.c.

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

Definition at line 236 of file chan_oss.c.

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

Definition at line 233 of file chan_oss.c.

#define O_CLOSE   0x444

Definition at line 224 of file chan_oss.c.

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

#define QUEUE_SIZE   10

Definition at line 207 of file chan_oss.c.

#define TEXT_SIZE   256

Definition at line 219 of file chan_oss.c.

#define WARN_frag   4

Definition at line 268 of file chan_oss.c.

Referenced by setformat().

#define WARN_speed   2

Definition at line 267 of file chan_oss.c.

Referenced by setformat().

#define WARN_used_blocks   1

Definition at line 266 of file chan_oss.c.

Referenced by used_blocks().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1494 of file chan_oss.c.

static void __unreg_module ( void   )  [static]

Definition at line 1494 of file chan_oss.c.

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

Definition at line 396 of file chan_oss.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 874 of file chan_oss.c.

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

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

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

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

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

static char* console_do_answer ( int  fd  )  [static]

helper function for the answer key/cli command

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

returns a pointer to the descriptor with the given name

forward declaration

Definition at line 370 of file chan_oss.c.

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

Referenced by ast_ext_ctx(), console_active(), console_autoanswer(), console_boost(), console_cmd(), console_dial(), console_do_answer(), console_flash(), console_hangup(), console_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().

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

struct video_desc* get_video_desc ( struct ast_channel c  ) 

return the pointer to the video descriptor

Definition at line 313 of file chan_oss.c.

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

Referenced by oss_new().

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

static int load_module ( void   )  [static]

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

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

static int oss_answer ( struct ast_channel c  )  [static]

remote side answered the phone

Definition at line 638 of file chan_oss.c.

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

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

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

handler for incoming calls. Either autoanswer, or start ringing

Definition at line 597 of file chan_oss.c.

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

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

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

Definition at line 574 of file chan_oss.c.

00575 {
00576    return 0;
00577 }

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

Definition at line 579 of file chan_oss.c.

References ast_verbose.

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

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

Definition at line 747 of file chan_oss.c.

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

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

static int oss_hangup ( struct ast_channel c  )  [static]

Definition at line 647 of file chan_oss.c.

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

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

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

Definition at line 754 of file chan_oss.c.

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

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

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

allocate a new channel.

Definition at line 790 of file chan_oss.c.

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

Referenced by console_dial(), and oss_request().

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

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

Definition at line 698 of file chan_oss.c.

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

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

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

Definition at line 833 of file chan_oss.c.

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

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

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

Definition at line 587 of file chan_oss.c.

References ast_verbose.

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

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

used for data coming from the network

Definition at line 667 of file chan_oss.c.

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

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

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

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

Definition at line 475 of file chan_oss.c.

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

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

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

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

Write an exactly FRAME_SIZE sized frame

Definition at line 446 of file chan_oss.c.

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

Referenced by oss_write(), and usbradio_read().

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

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

store the boost factor

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

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

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

store the callerid components

Definition at line 1318 of file chan_oss.c.

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

01319 {
01320    ast_callerid_split(s, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num));
01321 }

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

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

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

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

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

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

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

static int unload_module ( void   )  [static]

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

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

static int used_blocks ( struct chan_oss_pvt o  )  [static]

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

Definition at line 424 of file chan_oss.c.

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

Referenced by soundcard_writeframe().

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


Variable Documentation

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

Definition at line 1494 of file chan_oss.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1494 of file chan_oss.c.

struct ast_cli_entry cli_oss[] [static]

Definition at line 1280 of file chan_oss.c.

Referenced by load_module(), and unload_module().

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

Definition at line 239 of file chan_oss.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 69 of file chan_oss.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 76 of file chan_oss.c.

char* oss_active [static]

the active device

Definition at line 310 of file chan_oss.c.

Referenced by keypad_toggle().

int oss_debug [static]

Definition at line 241 of file chan_oss.c.

struct chan_oss_pvt oss_default [static]

Definition at line 318 of file chan_oss.c.

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

struct ast_channel_tech oss_tech [static]

Definition at line 349 of file chan_oss.c.

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

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

Definition at line 346 of file chan_oss.c.


Generated on Fri Jun 19 12:10:18 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7