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 "asterisk/bridge.h"
#include "asterisk/format_cache.h"
#include "console_video.h"

Include dependency graph for chan_oss.c:

Go to the source code of this file.

Data Structures

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

Defines

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

Functions

static char * ast_ext_ctx (const char *src, char **ext, char **ctx)
 AST_MODULE_INFO_STANDARD_EXTENDED (ASTERISK_GPL_KEY,"OSS Console Channel Driver")
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 (const char *dev)
 returns a pointer to the descriptor with the given name
struct video_desc * get_video_desc (struct ast_channel *c)
 return the pointer to the video descriptor
static int load_module (void)
 Load the module.
static int oss_answer (struct ast_channel *c)
 remote side answered the phone
static int oss_call (struct ast_channel *c, const 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, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
 allocate a new channel.
static struct ast_frameoss_read (struct ast_channel *chan)
static struct ast_channeloss_request (const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *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_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

Definition in file chan_oss.c.


Define Documentation

#define BOOST_MAX   40

slightly less than 7 bits

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

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

#define DEV_DSP   "/dev/dsp"

Definition at line 239 of file chan_oss.c.

Referenced by store_config().

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

Definition at line 222 of file chan_oss.c.

#define FRAME_SIZE   160

Definition at line 216 of file chan_oss.c.

#define O_CLOSE   0x444

Definition at line 234 of file chan_oss.c.

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

#define QUEUE_SIZE   10

Definition at line 217 of file chan_oss.c.

#define TEXT_SIZE   256

Definition at line 229 of file chan_oss.c.

#define WARN_frag   4

Definition at line 271 of file chan_oss.c.

Referenced by setformat().

#define WARN_speed   2

Definition at line 270 of file chan_oss.c.

Referenced by setformat().

#define WARN_used_blocks   1

Definition at line 269 of file chan_oss.c.

Referenced by used_blocks().


Function Documentation

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

Definition at line 399 of file chan_oss.c.

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

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

AST_MODULE_INFO_STANDARD_EXTENDED ( ASTERISK_GPL_KEY  ,
"OSS Console Channel Driver"   
)

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

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

01213 {
01214    switch (cmd) {
01215    case CLI_INIT:
01216       e->command = "console {set|show} active [<device>]";
01217       e->usage =
01218          "Usage: console active [device]\n"
01219          "       If used without a parameter, displays which device is the current\n"
01220          "       console.  If a device is specified, the console sound device is changed to\n"
01221          "       the device specified.\n";
01222       return NULL;
01223    case CLI_GENERATE:
01224       return NULL;
01225    }
01226 
01227    if (a->argc == 3)
01228       ast_cli(a->fd, "active console is [%s]\n", oss_active);
01229    else if (a->argc != 4)
01230       return CLI_SHOWUSAGE;
01231    else {
01232       struct chan_oss_pvt *o;
01233       if (strcmp(a->argv[3], "show") == 0) {
01234          for (o = oss_default.next; o; o = o->next)
01235             ast_cli(a->fd, "device [%s] exists\n", o->name);
01236          return CLI_SUCCESS;
01237       }
01238       o = find_desc(a->argv[3]);
01239       if (o == NULL)
01240          ast_cli(a->fd, "No device [%s] exists\n", a->argv[3]);
01241       else
01242          oss_active = o->name;
01243    }
01244    return CLI_SUCCESS;
01245 }

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 980 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, NULL, and ast_cli_entry::usage.

00981 {
00982    switch (cmd) {
00983    case CLI_INIT:
00984       e->command = "console answer";
00985       e->usage =
00986          "Usage: console answer\n"
00987          "       Answers an incoming call on the console (OSS) channel.\n";
00988       return NULL;
00989 
00990    case CLI_GENERATE:
00991       return NULL;   /* no completion */
00992    }
00993    if (a->argc != e->args)
00994       return CLI_SHOWUSAGE;
00995    return console_do_answer(a->fd);
00996 }

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

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

00925 {
00926    struct chan_oss_pvt *o = find_desc(oss_active);
00927 
00928    switch (cmd) {
00929    case CLI_INIT:
00930       e->command = "console {set|show} autoanswer [on|off]";
00931       e->usage =
00932          "Usage: console {set|show} autoanswer [on|off]\n"
00933          "       Enables or disables autoanswer feature.  If used without\n"
00934          "       argument, displays the current on/off status of autoanswer.\n"
00935          "       The default value of autoanswer is in 'oss.conf'.\n";
00936       return NULL;
00937 
00938    case CLI_GENERATE:
00939       return NULL;
00940    }
00941 
00942    if (a->argc == e->args - 1) {
00943       ast_cli(a->fd, "Auto answer is %s.\n", o->autoanswer ? "on" : "off");
00944       return CLI_SUCCESS;
00945    }
00946    if (a->argc != e->args)
00947       return CLI_SHOWUSAGE;
00948    if (o == NULL) {
00949       ast_log(LOG_WARNING, "Cannot find device %s (should not happen!)\n",
00950           oss_active);
00951       return CLI_FAILURE;
00952    }
00953    if (!strcasecmp(a->argv[e->args-1], "on"))
00954       o->autoanswer = 1;
00955    else if (!strcasecmp(a->argv[e->args - 1], "off"))
00956       o->autoanswer = 0;
00957    else
00958       return CLI_SHOWUSAGE;
00959    return CLI_SUCCESS;
00960 }

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

Definition at line 1269 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(), NULL, store_boost(), and ast_cli_entry::usage.

01270 {
01271    struct chan_oss_pvt *o = find_desc(oss_active);
01272 
01273    switch (cmd) {
01274    case CLI_INIT:
01275       e->command = "console boost";
01276       e->usage =
01277          "Usage: console boost [boost in dB]\n"
01278          "       Sets or display mic boost in dB\n";
01279       return NULL;
01280    case CLI_GENERATE:
01281       return NULL;
01282    }
01283 
01284    if (a->argc == 2)
01285       ast_cli(a->fd, "boost currently %5.1f\n", 20 * log10(((double) o->boost / (double) BOOST_SCALE)));
01286    else if (a->argc == 3)
01287       store_boost(o, a->argv[2]);
01288    return CLI_SUCCESS;
01289 }

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

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

00889 {
00890    struct chan_oss_pvt *o = find_desc(oss_active);
00891    const char *var, *value;
00892    switch (cmd) {
00893    case CLI_INIT:
00894       e->command = CONSOLE_VIDEO_CMDS;
00895       e->usage = 
00896          "Usage: " CONSOLE_VIDEO_CMDS "...\n"
00897          "       Generic handler for console commands.\n";
00898       return NULL;
00899 
00900    case CLI_GENERATE:
00901       return NULL;
00902    }
00903 
00904    if (a->argc < e->args)
00905       return CLI_SHOWUSAGE;
00906    if (o == NULL) {
00907       ast_log(LOG_WARNING, "Cannot find device %s (should not happen!)\n",
00908          oss_active);
00909       return CLI_FAILURE;
00910    }
00911    var = a->argv[e->args-1];
00912    value = a->argc > e->args ? a->argv[e->args] : NULL;
00913    if (value)      /* handle setting */
00914       store_config_core(o, var, value);
00915    if (!console_video_cli(o->env, var, a->fd))  /* print video-related values */
00916       return CLI_SUCCESS;
00917    /* handle other values */
00918    if (!strcasecmp(var, "device")) {
00919       ast_cli(a->fd, "device is [%s]\n", o->device);
00920    }
00921    return CLI_SUCCESS;
00922 }

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

Definition at line 1090 of file chan_oss.c.

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

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

static char* console_do_answer ( int  fd  )  [static]

helper function for the answer key/cli command

Definition at line 963 of file chan_oss.c.

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

Referenced by console_answer().

00964 {
00965    struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_ANSWER } };
00966    struct chan_oss_pvt *o = find_desc(oss_active);
00967    if (!o->owner) {
00968       if (fd > -1)
00969          ast_cli(fd, "No one is calling us\n");
00970       return CLI_FAILURE;
00971    }
00972    o->hookstate = 1;
00973    ast_queue_frame(o->owner, &f);
00974    return CLI_SUCCESS;
00975 }

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

Definition at line 1064 of file chan_oss.c.

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

01065 {
01066    struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_FLASH } };
01067    struct chan_oss_pvt *o = find_desc(oss_active);
01068 
01069    if (cmd == CLI_INIT) {
01070       e->command = "console flash";
01071       e->usage =
01072          "Usage: console flash\n"
01073          "       Flashes the call currently placed on the console.\n";
01074       return NULL;
01075    } else if (cmd == CLI_GENERATE)
01076       return NULL;
01077 
01078    if (a->argc != e->args)
01079       return CLI_SHOWUSAGE;
01080    if (!o->owner) {        /* XXX maybe !o->hookstate too ? */
01081       ast_cli(a->fd, "No call to flash\n");
01082       return CLI_FAILURE;
01083    }
01084    o->hookstate = 0;
01085    if (o->owner)
01086       ast_queue_frame(o->owner, &f);
01087    return CLI_SUCCESS;
01088 }

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

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

01039 {
01040    struct chan_oss_pvt *o = find_desc(oss_active);
01041 
01042    if (cmd == CLI_INIT) {
01043       e->command = "console hangup";
01044       e->usage =
01045          "Usage: console hangup\n"
01046          "       Hangs up any call currently placed on the console.\n";
01047       return NULL;
01048    } else if (cmd == CLI_GENERATE)
01049       return NULL;
01050 
01051    if (a->argc != e->args)
01052       return CLI_SHOWUSAGE;
01053    if (!o->owner && !o->hookstate) { /* XXX maybe only one ? */
01054       ast_cli(a->fd, "No call to hang up\n");
01055       return CLI_FAILURE;
01056    }
01057    o->hookstate = 0;
01058    if (o->owner)
01059       ast_queue_hangup_with_cause(o->owner, AST_CAUSE_NORMAL_CLEARING);
01060    setformat(o, O_CLOSE);
01061    return CLI_SUCCESS;
01062 }

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

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

01143 {
01144    struct chan_oss_pvt *o = find_desc(oss_active);
01145    const char *s;
01146    int toggle = 0;
01147    
01148    if (cmd == CLI_INIT) {
01149       e->command = "console {mute|unmute} [toggle]";
01150       e->usage =
01151          "Usage: console {mute|unmute} [toggle]\n"
01152          "       Mute/unmute the microphone.\n";
01153       return NULL;
01154    } else if (cmd == CLI_GENERATE)
01155       return NULL;
01156 
01157    if (a->argc > e->args)
01158       return CLI_SHOWUSAGE;
01159    if (a->argc == e->args) {
01160       if (strcasecmp(a->argv[e->args-1], "toggle"))
01161          return CLI_SHOWUSAGE;
01162       toggle = 1;
01163    }
01164    s = a->argv[e->args-2];
01165    if (!strcasecmp(s, "mute"))
01166       o->mute = toggle ? !o->mute : 1;
01167    else if (!strcasecmp(s, "unmute"))
01168       o->mute = toggle ? !o->mute : 0;
01169    else
01170       return CLI_SHOWUSAGE;
01171    ast_cli(a->fd, "Console mic is %s\n", o->mute ? "off" : "on");
01172    return CLI_SUCCESS;
01173 }

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

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), AST_FRAME_TEXT, ast_join, ast_queue_frame(), ast_strlen_zero, buf, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_frame::data, ast_frame::datalen, ast_cli_args::fd, find_desc(), ast_frame::frametype, ast_frame_subclass::integer, NULL, chan_oss_pvt::owner, ast_frame::ptr, ast_frame::subclass, TEXT_SIZE, and ast_cli_entry::usage.

01005 {
01006    struct chan_oss_pvt *o = find_desc(oss_active);
01007    char buf[TEXT_SIZE];
01008 
01009    if (cmd == CLI_INIT) {
01010       e->command = "console send text";
01011       e->usage =
01012          "Usage: console send text <message>\n"
01013          "       Sends a text message for display on the remote terminal.\n";
01014       return NULL;
01015    } else if (cmd == CLI_GENERATE)
01016       return NULL;
01017 
01018    if (a->argc < e->args + 1)
01019       return CLI_SHOWUSAGE;
01020    if (!o->owner) {
01021       ast_cli(a->fd, "Not in a call\n");
01022       return CLI_FAILURE;
01023    }
01024    ast_join(buf, sizeof(buf) - 1, a->argv + e->args);
01025    if (!ast_strlen_zero(buf)) {
01026       struct ast_frame f = { 0, };
01027       int i = strlen(buf);
01028       buf[i] = '\n';
01029       f.frametype = AST_FRAME_TEXT;
01030       f.subclass.integer = 0;
01031       f.data.ptr = buf;
01032       f.datalen = i + 1;
01033       ast_queue_frame(o->owner, &f);
01034    }
01035    return CLI_SUCCESS;
01036 }

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

Definition at line 1175 of file chan_oss.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_bridge_transfer_blind(), AST_BRIDGE_TRANSFER_SUCCESS, ast_channel_context(), ast_channel_is_bridged(), ast_channel_name(), ast_cli(), ast_ext_ctx(), ast_free, ast_log, ast_strdupa, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, chan_oss_pvt::ctx, ext, ast_cli_args::fd, find_desc(), LOG_WARNING, NULL, chan_oss_pvt::owner, tmp(), and ast_cli_entry::usage.

01176 {
01177    struct chan_oss_pvt *o = find_desc(oss_active);
01178    char *tmp, *ext, *ctx;
01179 
01180    switch (cmd) {
01181    case CLI_INIT:
01182       e->command = "console transfer";
01183       e->usage =
01184          "Usage: console transfer <extension>[@context]\n"
01185          "       Transfers the currently connected call to the given extension (and\n"
01186          "       context if specified)\n";
01187       return NULL;
01188    case CLI_GENERATE:
01189       return NULL;
01190    }
01191 
01192    if (a->argc != 3)
01193       return CLI_SHOWUSAGE;
01194    if (o == NULL)
01195       return CLI_FAILURE;
01196    if (o->owner == NULL || !ast_channel_is_bridged(o->owner)) {
01197       ast_cli(a->fd, "There is no call to transfer\n");
01198       return CLI_SUCCESS;
01199    }
01200 
01201    tmp = ast_ext_ctx(a->argv[2], &ext, &ctx);
01202    if (ctx == NULL) {         /* supply default context if needed */
01203       ctx = ast_strdupa(ast_channel_context(o->owner));
01204    }
01205    if (ast_bridge_transfer_blind(1, o->owner, ext, ctx, NULL, NULL) != AST_BRIDGE_TRANSFER_SUCCESS) {
01206       ast_log(LOG_WARNING, "Unable to transfer call from channel %s\n", ast_channel_name(o->owner));
01207    }
01208    ast_free(tmp);
01209    return CLI_SUCCESS;
01210 }

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

returns a pointer to the descriptor with the given name

forward declaration

Definition at line 373 of file chan_oss.c.

References ast_log, LOG_WARNING, chan_oss_pvt::name, chan_oss_pvt::next, and NULL.

Referenced by ast_ext_ctx(), console_active(), console_autoanswer(), console_boost(), console_cmd(), console_dial(), console_do_answer(), console_flash(), console_hangup(), console_mute(), console_sendtext(), console_transfer(), get_video_desc(), load_module(), and oss_request().

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

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

return the pointer to the video descriptor

Definition at line 316 of file chan_oss.c.

References ast_channel_tech_pvt(), chan_oss_pvt::env, find_desc(), and NULL.

Referenced by oss_new().

00317 {
00318    struct chan_oss_pvt *o = c ? ast_channel_tech_pvt(c) : find_desc(oss_active);
00319    return o ? o->env : NULL;
00320 }

static int load_module ( void   )  [static]

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 1450 of file chan_oss.c.

References ARRAY_LEN, ast_category_browse(), ast_channel_register(), ast_cli_register_multiple(), ast_config_destroy(), ast_config_load, ast_format_cap_alloc, ast_format_cap_append, ast_format_slin, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_channel_tech::capabilities, CONFIG_STATUS_FILEINVALID, find_desc(), global_jbconf, LOG_ERROR, LOG_NOTICE, NULL, and store_config().

01451 {
01452    struct ast_config *cfg = NULL;
01453    char *ctg = NULL;
01454    struct ast_flags config_flags = { 0 };
01455 
01456    /* Copy the default jb config over global_jbconf */
01457    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
01458 
01459    /* load config file */
01460    if (!(cfg = ast_config_load(config, config_flags))) {
01461       ast_log(LOG_NOTICE, "Unable to load config %s\n", config);
01462       return AST_MODULE_LOAD_DECLINE;
01463    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
01464       ast_log(LOG_ERROR, "Config file %s is in an invalid format.  Aborting.\n", config);
01465       return AST_MODULE_LOAD_DECLINE;
01466    }
01467 
01468    do {
01469       store_config(cfg, ctg);
01470    } while ( (ctg = ast_category_browse(cfg, ctg)) != NULL);
01471 
01472    ast_config_destroy(cfg);
01473 
01474    if (find_desc(oss_active) == NULL) {
01475       ast_log(LOG_NOTICE, "Device %s not found\n", oss_active);
01476       /* XXX we could default to 'dsp' perhaps ? */
01477       /* XXX should cleanup allocated memory etc. */
01478       return AST_MODULE_LOAD_FAILURE;
01479    }
01480 
01481    if (!(oss_tech.capabilities = ast_format_cap_alloc(0))) {
01482       return AST_MODULE_LOAD_FAILURE;
01483    }
01484    ast_format_cap_append(oss_tech.capabilities, ast_format_slin, 0);
01485 
01486    /* TODO XXX CONSOLE VIDEO IS DISABLE UNTIL IT HAS A MAINTAINER
01487     * add console_video_formats to oss_tech.capabilities once this occurs. */
01488 
01489    if (ast_channel_register(&oss_tech)) {
01490       ast_log(LOG_ERROR, "Unable to register channel type 'OSS'\n");
01491       return AST_MODULE_LOAD_DECLINE;
01492    }
01493 
01494    ast_cli_register_multiple(cli_oss, ARRAY_LEN(cli_oss));
01495 
01496    return AST_MODULE_LOAD_SUCCESS;
01497 }

static int oss_answer ( struct ast_channel c  )  [static]

remote side answered the phone

Definition at line 642 of file chan_oss.c.

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

00643 {
00644    struct chan_oss_pvt *o = ast_channel_tech_pvt(c);
00645    ast_verbose(" << Console call has been answered >> \n");
00646    ast_setstate(c, AST_STATE_UP);
00647    o->hookstate = 1;
00648    return 0;
00649 }

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

handler for incoming calls. Either autoanswer, or start ringing

Definition at line 600 of file chan_oss.c.

References args, AST_APP_ARG, ast_channel_caller(), ast_channel_dialed(), ast_channel_redirecting(), ast_channel_tech_pvt(), 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_frame::flags, chan_oss_pvt::hookstate, ast_frame_subclass::integer, name, parse(), S_COR, S_OR, ast_party_dialed::str, and ast_frame::subclass.

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

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

Definition at line 577 of file chan_oss.c.

00578 {
00579    return 0;
00580 }

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

Definition at line 582 of file chan_oss.c.

References ast_verbose.

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

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

Definition at line 751 of file chan_oss.c.

References ast_channel_tech_pvt(), and chan_oss_pvt::owner.

00752 {
00753    struct chan_oss_pvt *o = ast_channel_tech_pvt(newchan);
00754    o->owner = newchan;
00755    return 0;
00756 }

static int oss_hangup ( struct ast_channel c  )  [static]

Definition at line 651 of file chan_oss.c.

References ast_channel_tech_pvt(), ast_channel_tech_pvt_set(), ast_module_unref, ast_verbose, chan_oss_pvt::autoanswer, chan_oss_pvt::autohangup, console_video_uninit(), chan_oss_pvt::env, chan_oss_pvt::hookstate, NULL, O_CLOSE, chan_oss_pvt::owner, and setformat().

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

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

Definition at line 758 of file chan_oss.c.

References ast_channel_name(), ast_channel_tech_pvt(), AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_PVT_CAUSE_CODE, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_log, ast_moh_start(), ast_moh_stop(), ast_verbose, LOG_WARNING, and chan_oss_pvt::mohinterpret.

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

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

allocate a new channel.

Definition at line 796 of file chan_oss.c.

References ast_party_caller::ani, ast_channel_alloc, ast_channel_caller(), ast_channel_dialed(), ast_channel_name(), ast_channel_nativeformats_set(), ast_channel_set_fd(), ast_channel_set_readformat(), ast_channel_set_writeformat(), ast_channel_tech_pvt_set(), ast_channel_tech_set(), ast_channel_unlock, ast_format_slin, ast_hangup(), ast_jb_configure(), ast_log, ast_module_ref, ast_pbx_start(), AST_STATE_DOWN, ast_strdup, ast_strlen_zero, c, ast_channel_tech::capabilities, chan_oss_pvt::cid_name, chan_oss_pvt::cid_num, console_video_start(), chan_oss_pvt::device, get_video_desc(), global_jbconf, chan_oss_pvt::language, LOG_WARNING, NULL, ast_party_dialed::number, ast_party_id::number, chan_oss_pvt::owner, setformat(), chan_oss_pvt::sounddev, ast_party_dialed::str, ast_party_number::str, and ast_party_number::valid.

Referenced by console_dial(), and oss_request().

00797 {
00798    struct ast_channel *c;
00799 
00800    c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, assignedids, requestor, 0, "Console/%s", o->device + 5);
00801    if (c == NULL)
00802       return NULL;
00803    ast_channel_tech_set(c, &oss_tech);
00804    if (o->sounddev < 0)
00805       setformat(o, O_RDWR);
00806    ast_channel_set_fd(c, 0, o->sounddev); /* -1 if device closed, override later */
00807 
00808    ast_channel_set_readformat(c, ast_format_slin);
00809    ast_channel_set_writeformat(c, ast_format_slin);
00810    ast_channel_nativeformats_set(c, oss_tech.capabilities);
00811 
00812    /* if the console makes the call, add video to the offer */
00813    /* if (state == AST_STATE_RINGING) TODO XXX CONSOLE VIDEO IS DISABLED UNTIL IT GETS A MAINTAINER
00814       c->nativeformats |= console_video_formats; */
00815 
00816    ast_channel_tech_pvt_set(c, o);
00817 
00818    if (!ast_strlen_zero(o->language))
00819       ast_channel_language_set(c, o->language);
00820    /* Don't use ast_set_callerid() here because it will
00821     * generate a needless NewCallerID event */
00822    if (!ast_strlen_zero(o->cid_num)) {
00823       ast_channel_caller(c)->ani.number.valid = 1;
00824       ast_channel_caller(c)->ani.number.str = ast_strdup(o->cid_num);
00825    }
00826    if (!ast_strlen_zero(ext)) {
00827       ast_channel_dialed(c)->number.str = ast_strdup(ext);
00828    }
00829 
00830    o->owner = c;
00831    ast_module_ref(ast_module_info->self);
00832    ast_jb_configure(c, &global_jbconf);
00833    ast_channel_unlock(c);
00834    if (state != AST_STATE_DOWN) {
00835       if (ast_pbx_start(c)) {
00836          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(c));
00837          ast_hangup(c);
00838          o->owner = c = NULL;
00839       }
00840    }
00841    console_video_start(get_video_desc(c), c); /* XXX cleanup */
00842 
00843    return c;
00844 }

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

Definition at line 702 of file chan_oss.c.

References ao2_bump, ast_channel_tech_pvt(), ast_format_slin, AST_FRAME_NULL, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, AST_STATE_UP, chan_oss_pvt::boost, BOOST_SCALE, ast_frame::data, ast_frame::datalen, f, ast_frame_subclass::format, FRAME_SIZE, ast_frame::frametype, chan_oss_pvt::mute, ast_frame::offset, chan_oss_pvt::oss_read_buf, ast_frame::ptr, chan_oss_pvt::read_f, chan_oss_pvt::readpos, ast_frame::samples, chan_oss_pvt::sounddev, ast_frame::src, ast_frame::subclass, and ast_channel_tech::type.

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

static struct ast_channel * oss_request ( const char *  type,
struct ast_format_cap cap,
const struct ast_assigned_ids assignedids,
const struct ast_channel requestor,
const char *  data,
int *  cause 
) [static, read]

Definition at line 846 of file chan_oss.c.

References args, AST_APP_ARG, AST_CAUSE_BUSY, AST_DECLARE_APP_ARGS, ast_format_cap_get_names(), ast_format_cap_iscompatible_format(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_slin, ast_log, AST_NONSTANDARD_APP_ARGS, AST_STATE_DOWN, ast_str_alloca, ast_strdupa, c, find_desc(), LOG_NOTICE, LOG_WARNING, name, NULL, oss_new(), chan_oss_pvt::owner, and parse().

00847 {
00848    struct ast_channel *c;
00849    struct chan_oss_pvt *o;
00850    AST_DECLARE_APP_ARGS(args,
00851       AST_APP_ARG(name);
00852       AST_APP_ARG(flags);
00853    );
00854    char *parse = ast_strdupa(data);
00855 
00856    AST_NONSTANDARD_APP_ARGS(args, parse, '/');
00857    o = find_desc(args.name);
00858 
00859    ast_log(LOG_WARNING, "oss_request ty <%s> data 0x%p <%s>\n", type, data, data);
00860    if (o == NULL) {
00861       ast_log(LOG_NOTICE, "Device %s not found\n", args.name);
00862       /* XXX we could default to 'dsp' perhaps ? */
00863       return NULL;
00864    }
00865    if (ast_format_cap_iscompatible_format(cap, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) {
00866       struct ast_str *codec_buf = ast_str_alloca(64);
00867       ast_log(LOG_NOTICE, "Format %s unsupported\n", ast_format_cap_get_names(cap, &codec_buf));
00868       return NULL;
00869    }
00870    if (o->owner) {
00871       ast_log(LOG_NOTICE, "Already have a call (chan %p) on the OSS channel\n", o->owner);
00872       *cause = AST_CAUSE_BUSY;
00873       return NULL;
00874    }
00875    c = oss_new(o, NULL, NULL, AST_STATE_DOWN, assignedids, requestor);
00876    if (c == NULL) {
00877       ast_log(LOG_WARNING, "Unable to create new OSS channel\n");
00878       return NULL;
00879    }
00880    return c;
00881 }

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

Definition at line 590 of file chan_oss.c.

References ast_verbose.

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

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

used for data coming from the network

Definition at line 671 of file chan_oss.c.

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

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

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

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

Referenced by console_hangup(), oss_hangup(), oss_new(), soundcard_writeframe(), and store_config().

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

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

Write an exactly FRAME_SIZE sized frame

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

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

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

store the boost factor

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

01251 {
01252    double boost = 0;
01253    if (sscanf(s, "%30lf", &boost) != 1) {
01254       ast_log(LOG_WARNING, "invalid boost <%s>\n", s);
01255       return;
01256    }
01257    if (boost < -BOOST_MAX) {
01258       ast_log(LOG_WARNING, "boost %s too small, using %d\n", s, -BOOST_MAX);
01259       boost = -BOOST_MAX;
01260    } else if (boost > BOOST_MAX) {
01261       ast_log(LOG_WARNING, "boost %s too large, using %d\n", s, BOOST_MAX);
01262       boost = BOOST_MAX;
01263    }
01264    boost = exp(log(10) * boost / 20) * BOOST_SCALE;
01265    o->boost = boost;
01266    ast_log(LOG_WARNING, "setting boost %s to %d\n", s, o->boost);
01267 }

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

store the callerid components

Definition at line 1329 of file chan_oss.c.

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

01330 {
01331    ast_callerid_split(s, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num));
01332 }

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

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

Definition at line 1365 of file chan_oss.c.

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

Referenced by load_module().

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

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

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

01335 {
01336    CV_START(var, value);
01337 
01338    /* handle jb conf */
01339    if (!ast_jb_read_conf(&global_jbconf, var, value))
01340       return;
01341 
01342    if (!console_video_config(&o->env, var, value))
01343       return;  /* matched there */
01344    CV_BOOL("autoanswer", o->autoanswer);
01345    CV_BOOL("autohangup", o->autohangup);
01346    CV_BOOL("overridecontext", o->overridecontext);
01347    CV_STR("device", o->device);
01348    CV_UINT("frags", o->frags);
01349    CV_UINT("debug", oss_debug);
01350    CV_UINT("queuesize", o->queuesize);
01351    CV_STR("context", o->ctx);
01352    CV_STR("language", o->language);
01353    CV_STR("mohinterpret", o->mohinterpret);
01354    CV_STR("extension", o->ext);
01355    CV_F("mixer", store_mixer(o, value));
01356    CV_F("callerid", store_callerid(o, value))  ;
01357    CV_F("boost", store_boost(o, value));
01358 
01359    CV_END;
01360 }

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

References ast_free, ast_log, ast_strdup, LOG_WARNING, chan_oss_pvt::mixer_cmd, and NULL.

Referenced by store_config_core().

01311 {
01312    int i;
01313 
01314    for (i = 0; i < strlen(s); i++) {
01315       if (!isalnum(s[i]) && strchr(" \t-/", s[i]) == NULL) {
01316          ast_log(LOG_WARNING, "Suspect char %c in mixer cmd, ignoring:\n\t%s\n", s[i], s);
01317          return;
01318       }
01319    }
01320    if (o->mixer_cmd)
01321       ast_free(o->mixer_cmd);
01322    o->mixer_cmd = ast_strdup(s);
01323    ast_log(LOG_WARNING, "setting mixer %s\n", s);
01324 }

static int unload_module ( void   )  [static]

Definition at line 1500 of file chan_oss.c.

References ao2_cleanup, ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_free, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_channel_tech::capabilities, chan_oss_pvt::name, chan_oss_pvt::next, NULL, chan_oss_pvt::owner, and chan_oss_pvt::sounddev.

01501 {
01502    struct chan_oss_pvt *o, *next;
01503 
01504    ast_channel_unregister(&oss_tech);
01505    ast_cli_unregister_multiple(cli_oss, ARRAY_LEN(cli_oss));
01506 
01507    o = oss_default.next;
01508    while (o) {
01509       close(o->sounddev);
01510       if (o->owner)
01511          ast_softhangup(o->owner, AST_SOFTHANGUP_APPUNLOAD);
01512       if (o->owner)
01513          return -1;
01514       next = o->next;
01515       ast_free(o->name);
01516       ast_free(o);
01517       o = next;
01518    }
01519    ao2_cleanup(oss_tech.capabilities);
01520    oss_tech.capabilities = NULL;
01521 
01522    return 0;
01523 }

static int used_blocks ( struct chan_oss_pvt o  )  [static]

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

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

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


Variable Documentation

struct ast_cli_entry cli_oss[] [static]

Definition at line 1291 of file chan_oss.c.

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

Definition at line 242 of file chan_oss.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Note:
Values shown here match the defaults shown in oss.conf.sample

Definition at line 78 of file chan_oss.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 86 of file chan_oss.c.

char* oss_active [static]

the active device

Definition at line 313 of file chan_oss.c.

int oss_debug [static]

Definition at line 244 of file chan_oss.c.

struct chan_oss_pvt oss_default [static]

Definition at line 321 of file chan_oss.c.

struct ast_channel_tech oss_tech [static]

Definition at line 353 of file chan_oss.c.

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

Definition at line 350 of file chan_oss.c.


Generated on Thu Apr 16 06:29:47 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6