Thu Oct 11 06:35:13 2012

Asterisk developer's documentation


chan_oss.c File Reference

Channel driver for OSS sound cards. More...

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

Include dependency graph for chan_oss.c:

Go to the source code of this file.

Data Structures

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

Defines

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

Functions

static void __reg_module (void)
static void __unreg_module (void)
static char * ast_ext_ctx (const char *src, char **ext, char **ctx)
static char * console_active (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_answer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 answer command from the console
static char * console_autoanswer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_boost (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_dial (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_do_answer (int fd)
 helper function for the answer key/cli command
static char * console_flash (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_hangup (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_mute (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * console_sendtext (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Console send text CLI command.
static char * console_transfer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct chan_oss_pvtfind_desc (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 char *linkedid)
 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_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_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
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

Definition in file chan_oss.c.


Define Documentation

#define BOOST_MAX   40

slightly less than 7 bits

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

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

#define DEV_DSP   "/dev/dsp"

Definition at line 238 of file chan_oss.c.

Referenced by store_config().

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

Definition at line 221 of file chan_oss.c.

#define FRAME_SIZE   160

Definition at line 215 of file chan_oss.c.

#define O_CLOSE   0x444

Definition at line 233 of file chan_oss.c.

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

#define QUEUE_SIZE   10

Definition at line 216 of file chan_oss.c.

#define TEXT_SIZE   256

Definition at line 228 of file chan_oss.c.

#define WARN_frag   4

Definition at line 270 of file chan_oss.c.

Referenced by setformat().

#define WARN_speed   2

Definition at line 269 of file chan_oss.c.

Referenced by setformat().

#define WARN_used_blocks   1

Definition at line 268 of file chan_oss.c.

Referenced by used_blocks().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1529 of file chan_oss.c.

static void __unreg_module ( void   )  [static]

Definition at line 1529 of file chan_oss.c.

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

Definition at line 398 of file chan_oss.c.

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

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

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

Definition at line 1217 of file chan_oss.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static char* console_do_answer ( int  fd  )  [static]

helper function for the answer key/cli command

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

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

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

Definition at line 1063 of file chan_oss.c.

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

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

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

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

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

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

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

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

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 1003 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(), 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, chan_oss_pvt::owner, ast_frame::ptr, ast_frame::subclass, TEXT_SIZE, and ast_cli_entry::usage.

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

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

Definition at line 1174 of file chan_oss.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_async_goto(), ast_bridged_channel(), ast_channel_caller(), ast_channel_context(), ast_channel_name(), ast_cli(), ast_exists_extension(), ast_ext_ctx(), ast_free, ast_strdupa, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ext, ast_cli_args::fd, find_desc(), chan_oss_pvt::owner, S_COR, and ast_cli_entry::usage.

01175 {
01176    struct chan_oss_pvt *o = find_desc(oss_active);
01177    struct ast_channel *b = NULL;
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 || (b = ast_bridged_channel(o->owner)) == NULL) {
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    if (!ast_exists_extension(b, ctx, ext, 1,
01205       S_COR(ast_channel_caller(b)->id.number.valid, ast_channel_caller(b)->id.number.str, NULL))) {
01206       ast_cli(a->fd, "No such extension exists\n");
01207    } else {
01208       ast_cli(a->fd, "Whee, transferring %s to %s@%s.\n", ast_channel_name(b), ext, ctx);
01209       if (ast_async_goto(b, ctx, ext, 1))
01210          ast_cli(a->fd, "Failed to transfer :(\n");
01211    }
01212    if (tmp)
01213       ast_free(tmp);
01214    return CLI_SUCCESS;
01215 }

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

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

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

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

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

return the pointer to the video descriptor

Definition at line 315 of file chan_oss.c.

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

Referenced by oss_new().

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

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 1455 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_add(), ast_format_cap_alloc(), ast_format_set(), AST_FORMAT_SLINEAR, 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, and store_config().

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

static int oss_answer ( struct ast_channel c  )  [static]

remote side answered the phone

Definition at line 641 of file chan_oss.c.

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

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

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

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

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

Definition at line 576 of file chan_oss.c.

00577 {
00578    return 0;
00579 }

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

Definition at line 581 of file chan_oss.c.

References ast_verbose.

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

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

Definition at line 750 of file chan_oss.c.

References ast_channel_tech_pvt(), and chan_oss_pvt::owner.

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

static int oss_hangup ( struct ast_channel c  )  [static]

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

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

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

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

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

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

allocate a new channel.

Definition at line 795 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(), ast_channel_readformat(), ast_channel_set_fd(), ast_channel_tech_pvt_set(), ast_channel_tech_set(), ast_channel_writeformat(), ast_format_cap_add(), ast_format_set(), AST_FORMAT_SLINEAR, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), AST_STATE_DOWN, ast_strdup, ast_strlen_zero(), 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, 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().

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

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

Definition at line 701 of file chan_oss.c.

References ast_channel_tech_pvt(), ast_format_set(), AST_FORMAT_SLINEAR, AST_FRAME_NULL, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, AST_STATE_UP, chan_oss_pvt::boost, BOOST_SCALE, ast_frame::data, ast_frame::datalen, f, 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.

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

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

Definition at line 844 of file chan_oss.c.

References args, AST_APP_ARG, AST_CAUSE_BUSY, ast_channel_linkedid(), AST_DECLARE_APP_ARGS, ast_format_cap_iscompatible(), ast_format_set(), AST_FORMAT_SLINEAR, ast_getformatname_multiple(), 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().

00845 {
00846    struct ast_channel *c;
00847    struct chan_oss_pvt *o;
00848    AST_DECLARE_APP_ARGS(args,
00849       AST_APP_ARG(name);
00850       AST_APP_ARG(flags);
00851    );
00852    char *parse = ast_strdupa(data);
00853    char buf[256];
00854    struct ast_format tmpfmt;
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(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)))) {
00866       ast_log(LOG_NOTICE, "Format %s unsupported\n", ast_getformatname_multiple(buf, sizeof(buf), cap));
00867       return NULL;
00868    }
00869    if (o->owner) {
00870       ast_log(LOG_NOTICE, "Already have a call (chan %p) on the OSS channel\n", o->owner);
00871       *cause = AST_CAUSE_BUSY;
00872       return NULL;
00873    }
00874    c = oss_new(o, NULL, NULL, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL);
00875    if (c == NULL) {
00876       ast_log(LOG_WARNING, "Unable to create new OSS channel\n");
00877       return NULL;
00878    }
00879    return c;
00880 }

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

Definition at line 589 of file chan_oss.c.

References ast_verbose.

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

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

used for data coming from the network

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

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

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

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

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

Write an exactly FRAME_SIZE sized frame

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

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

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

store the boost factor

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

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

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

store the callerid components

Definition at line 1334 of file chan_oss.c.

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

01335 {
01336    ast_callerid_split(s, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num));
01337 }

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 1370 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, get_gui_startup(), chan_oss_pvt::lastopen, LOG_WARNING, chan_oss_pvt::M_FULL, chan_oss_pvt::mixer_cmd, chan_oss_pvt::mohinterpret, ast_variable::name, chan_oss_pvt::name, chan_oss_pvt::next, ast_variable::next, setformat(), store_config_core(), and ast_variable::value.

Referenced by load_module().

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

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

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

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

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

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

static int unload_module ( void   )  [static]

Definition at line 1506 of file chan_oss.c.

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

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

static int used_blocks ( struct chan_oss_pvt o  )  [static]

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

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

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


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 1529 of file chan_oss.c.

Definition at line 1529 of file chan_oss.c.

struct ast_cli_entry cli_oss[] [static]

Definition at line 1296 of file chan_oss.c.

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

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

struct ast_jb_conf global_jbconf [static]

Definition at line 85 of file chan_oss.c.

char* oss_active [static]

the active device

Definition at line 312 of file chan_oss.c.

int oss_debug [static]

Definition at line 243 of file chan_oss.c.

struct chan_oss_pvt oss_default [static]

Definition at line 320 of file chan_oss.c.

struct ast_channel_tech oss_tech [static]

Definition at line 352 of file chan_oss.c.

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

Definition at line 349 of file chan_oss.c.


Generated on Thu Oct 11 06:35:13 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6