Mon Jun 27 16:51:07 2011

Asterisk developer's documentation


chan_oss.c File Reference

Channel driver for OSS sound cards. More...

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

Go to the source code of this file.

Data Structures

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

Defines

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

Functions

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

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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

See also

Definition in file chan_oss.c.


Define Documentation

#define BOOST_MAX   40

slightly less than 7 bits

Definition at line 273 of file chan_oss.c.

Referenced by store_boost().

#define BOOST_SCALE   (1<<9)

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

Definition at line 272 of file chan_oss.c.

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

#define DEV_DSP   "/dev/dsp"

Definition at line 230 of file chan_oss.c.

Referenced by store_config().

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

Definition at line 213 of file chan_oss.c.

#define FRAME_SIZE   160

Definition at line 207 of file chan_oss.c.

#define O_CLOSE   0x444

Definition at line 225 of file chan_oss.c.

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

#define QUEUE_SIZE   10

Definition at line 208 of file chan_oss.c.

#define TEXT_SIZE   256

Definition at line 220 of file chan_oss.c.

#define WARN_frag   4

Definition at line 262 of file chan_oss.c.

Referenced by setformat().

#define WARN_speed   2

Definition at line 261 of file chan_oss.c.

Referenced by setformat().

#define WARN_used_blocks   1

Definition at line 260 of file chan_oss.c.

Referenced by used_blocks().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1501 of file chan_oss.c.

static void __unreg_module ( void   )  [static]

Definition at line 1501 of file chan_oss.c.

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

Definition at line 391 of file chan_oss.c.

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

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

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

Definition at line 1205 of file chan_oss.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 1077 of file chan_oss.c.

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

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

static char* console_do_answer ( int  fd  )  [static]

helper function for the answer key/cli command

Definition at line 950 of file chan_oss.c.

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

Referenced by console_answer().

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

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

Definition at line 1051 of file chan_oss.c.

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

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

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

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

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

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

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

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

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 991 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, f, ast_cli_args::fd, find_desc(), chan_oss_pvt::owner, TEXT_SIZE, and ast_cli_entry::usage.

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

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

Definition at line 1162 of file chan_oss.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_async_goto(), ast_bridged_channel(), ast_cli(), ast_exists_extension(), ast_ext_ctx(), ast_free, ast_channel::caller, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_channel::context, ext, ast_cli_args::fd, find_desc(), ast_party_caller::id, ast_channel::name, ast_party_id::number, chan_oss_pvt::owner, S_COR, ast_party_number::str, ast_cli_entry::usage, and ast_party_number::valid.

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

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

returns a pointer to the descriptor with the given name

forward declaration

Definition at line 365 of file chan_oss.c.

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

Referenced by ast_ext_ctx(), console_active(), console_autoanswer(), console_boost(), console_cmd(), console_dial(), console_do_answer(), console_flash(), console_hangup(), console_key(), console_mute(), console_sendtext(), console_transfer(), console_unkey(), get_video_desc(), keypad_toggle(), load_module(), oss_request(), radio_active(), radio_set_debug(), radio_set_debug_off(), radio_set_xpmr_debug(), radio_tune(), usbradio_request(), and usbradio_text().

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

struct video_desc* get_video_desc ( struct ast_channel c  ) 

return the pointer to the video descriptor

Definition at line 307 of file chan_oss.c.

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

Referenced by oss_new().

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

static int load_module ( void   )  [static]

Definition at line 1435 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_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_channel_tech::capabilities, cli_oss, config_flags, CONFIG_STATUS_FILEINVALID, console_video_formats, default_jbconf, find_desc(), global_jbconf, LOG_ERROR, LOG_NOTICE, oss_tech, and store_config().

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

static int oss_answer ( struct ast_channel c  )  [static]

remote side answered the phone

Definition at line 634 of file chan_oss.c.

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

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

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

handler for incoming calls. Either autoanswer, or start ringing

Definition at line 592 of file chan_oss.c.

References args, AST_APP_ARG, AST_CONTROL_ANSWER, AST_CONTROL_RINGING, AST_DECLARE_APP_ARGS, AST_FRAME_CONTROL, ast_indicate(), AST_NONSTANDARD_APP_ARGS, ast_queue_frame(), ast_strdupa, ast_strlen_zero(), ast_verbose, chan_oss_pvt::autoanswer, ast_channel::caller, ast_channel::dialed, f, ast_frame::flags, ast_party_redirecting::from, chan_oss_pvt::hookstate, ast_party_caller::id, ast_party_id::name, name, ast_party_id::number, ast_party_dialed::number, parse(), ast_channel::redirecting, S_COR, S_OR, ast_party_name::str, ast_party_number::str, ast_party_dialed::str, ast_channel::tech_pvt, ast_party_name::valid, and ast_party_number::valid.

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

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

Definition at line 569 of file chan_oss.c.

00570 {
00571    return 0;
00572 }

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

Definition at line 574 of file chan_oss.c.

References ast_verbose.

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

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

Definition at line 743 of file chan_oss.c.

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

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

static int oss_hangup ( struct ast_channel c  )  [static]

Definition at line 643 of file chan_oss.c.

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

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

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

Definition at line 750 of file chan_oss.c.

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

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

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

allocate a new channel.

Definition at line 786 of file chan_oss.c.

References ast_party_caller::ani, ast_channel_alloc, ast_channel_set_fd(), AST_FORMAT_SLINEAR, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), AST_STATE_DOWN, AST_STATE_RINGING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_channel::caller, chan_oss_pvt::cid_name, chan_oss_pvt::cid_num, console_video_formats, console_video_start(), chan_oss_pvt::device, ast_channel::dialed, get_video_desc(), global_jbconf, language, chan_oss_pvt::language, LOG_WARNING, ast_channel::nativeformats, ast_party_dialed::number, ast_party_id::number, oss_tech, chan_oss_pvt::owner, ast_channel::readformat, setformat(), chan_oss_pvt::sounddev, ast_party_dialed::str, ast_party_number::str, ast_channel::tech, ast_channel::tech_pvt, ast_party_number::valid, and ast_channel::writeformat.

Referenced by console_dial(), and oss_request().

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

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

Definition at line 694 of file chan_oss.c.

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

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

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

Definition at line 833 of file chan_oss.c.

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

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

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

Definition at line 582 of file chan_oss.c.

References ast_verbose.

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

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

used for data coming from the network

Definition at line 663 of file chan_oss.c.

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

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

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

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

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

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

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

Write an exactly FRAME_SIZE sized frame

Definition at line 441 of file chan_oss.c.

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

Referenced by oss_write(), and usbradio_read().

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

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

store the boost factor

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

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

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

store the callerid components

Definition at line 1322 of file chan_oss.c.

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

01323 {
01324    ast_callerid_split(s, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num));
01325 }

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

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

Definition at line 1358 of file chan_oss.c.

References asprintf, ast_calloc, ast_copy_string(), ast_log(), ast_strdup, ast_strlen_zero(), ast_tvnow(), ast_variable_browse(), DEV_DSP, chan_oss_pvt::device, errno, chan_oss_pvt::lastopen, LOG_WARNING, chan_oss_pvt::mixer_cmd, chan_oss_pvt::mohinterpret, ast_variable::name, chan_oss_pvt::name, ast_variable::next, oss_default, store_config_core(), and ast_variable::value.

Referenced by load_module().

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

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

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

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

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

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

static int unload_module ( void   )  [static]

Definition at line 1479 of file chan_oss.c.

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

01480 {
01481    struct chan_oss_pvt *o, *next;
01482 
01483    ast_channel_unregister(&oss_tech);
01484    ast_cli_unregister_multiple(cli_oss, ARRAY_LEN(cli_oss));
01485 
01486    o = oss_default.next;
01487    while (o) {
01488       close(o->sounddev);
01489       if (o->owner)
01490          ast_softhangup(o->owner, AST_SOFTHANGUP_APPUNLOAD);
01491       if (o->owner)
01492          return -1;
01493       next = o->next;
01494       ast_free(o->name);
01495       ast_free(o);
01496       o = next;
01497    }
01498    return 0;
01499 }

static int used_blocks ( struct chan_oss_pvt o  )  [static]

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

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

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


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

Definition at line 1501 of file chan_oss.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1501 of file chan_oss.c.

struct ast_cli_entry cli_oss[] [static]

Definition at line 1284 of file chan_oss.c.

Referenced by load_module(), and unload_module().

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

Definition at line 233 of file chan_oss.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 69 of file chan_oss.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 77 of file chan_oss.c.

char* oss_active [static]

the active device

Definition at line 304 of file chan_oss.c.

Referenced by keypad_toggle().

int oss_debug [static]

Definition at line 235 of file chan_oss.c.

struct chan_oss_pvt oss_default [static]

Definition at line 312 of file chan_oss.c.

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

struct ast_channel_tech oss_tech [static]

Definition at line 344 of file chan_oss.c.

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

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

Definition at line 341 of file chan_oss.c.


Generated on Mon Jun 27 16:51:07 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7