#include "asterisk.h"
#include <ctype.h>
#include <math.h>
#include <sys/ioctl.h>
#include <soundcard.h>
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/callerid.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/cli.h"
#include "asterisk/causes.h"
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "console_video.h"
Go to the source code of this file.
Data Structures | |
struct | chan_oss_pvt |
descriptor for one of our channels. More... | |
Defines | |
#define | BOOST_MAX 40 |
#define | BOOST_SCALE (1<<9) |
#define | DEV_DSP "/dev/dsp" |
#define | FRAGS ( ( (6 * 5) << 16 ) | 0x6 ) |
#define | FRAME_SIZE 160 |
#define | MAX(a, b) ((a) > (b) ? (a) : (b)) |
#define | MIN(a, b) ((a) < (b) ? (a) : (b)) |
#define | O_CLOSE 0x444 |
#define | QUEUE_SIZE 10 |
#define | TEXT_SIZE 256 |
#define | WARN_frag 4 |
#define | WARN_speed 2 |
#define | WARN_used_blocks 1 |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static char * | ast_ext_ctx (const char *src, char **ext, char **ctx) |
static char * | console_active (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | console_answer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
answer command from the console | |
static char * | console_autoanswer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | console_boost (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | console_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | console_dial (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | console_do_answer (int fd) |
helper function for the answer key/cli command | |
static char * | console_flash (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | console_hangup (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | console_mute (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | console_sendtext (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Console send text CLI command. | |
static char * | console_transfer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static struct chan_oss_pvt * | find_desc (char *dev) |
returns a pointer to the descriptor with the given name | |
video_desc * | get_video_desc (struct ast_channel *c) |
return the pointer to the video descriptor | |
static int | load_module (void) |
static int | oss_answer (struct ast_channel *c) |
remote side answered the phone | |
static int | oss_call (struct ast_channel *c, char *dest, int timeout) |
handler for incoming calls. Either autoanswer, or start ringing | |
static int | oss_digit_begin (struct ast_channel *c, char digit) |
static int | oss_digit_end (struct ast_channel *c, char digit, unsigned int duration) |
static int | oss_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
static int | oss_hangup (struct ast_channel *c) |
static int | oss_indicate (struct ast_channel *chan, int cond, const void *data, size_t datalen) |
static struct ast_channel * | oss_new (struct chan_oss_pvt *o, char *ext, char *ctx, int state) |
allocate a new channel. | |
static struct ast_frame * | oss_read (struct ast_channel *chan) |
static struct ast_channel * | oss_request (const char *type, int format, void *data, int *cause) |
static int | oss_text (struct ast_channel *c, const char *text) |
static int | oss_write (struct ast_channel *c, struct ast_frame *f) |
used for data coming from the network | |
static int | setformat (struct chan_oss_pvt *o, int mode) |
static int | soundcard_writeframe (struct chan_oss_pvt *o, short *data) |
static void | store_boost (struct chan_oss_pvt *o, const char *s) |
store the boost factor | |
static void | store_callerid (struct chan_oss_pvt *o, const char *s) |
static struct chan_oss_pvt * | store_config (struct ast_config *cfg, char *ctg) |
static void | store_config_core (struct chan_oss_pvt *o, const char *var, const char *value) |
static void | store_mixer (struct chan_oss_pvt *o, const char *s) |
static int | unload_module (void) |
static int | used_blocks (struct chan_oss_pvt *o) |
Returns the number of blocks used in the audio output channel. | |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "OSS Console Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } |
static struct ast_module_info * | ast_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" |
Luigi Rizzo
Definition in file chan_oss.c.
#define BOOST_MAX 40 |
#define BOOST_SCALE (1<<9) |
boost support. BOOST_SCALE * 10 ^(BOOST_MAX/20) must be representable in 16 bits to avoid overflows.
Definition at line 278 of file chan_oss.c.
Referenced by console_boost(), oss_read(), store_boost(), and usbradio_read().
#define DEV_DSP "/dev/dsp" |
#define FRAGS ( ( (6 * 5) << 16 ) | 0x6 ) |
Definition at line 212 of file chan_oss.c.
#define FRAME_SIZE 160 |
Definition at line 206 of file chan_oss.c.
#define MAX | ( | a, | |||
b | ) | ((a) > (b) ? (a) : (b)) |
Definition at line 236 of file chan_oss.c.
#define MIN | ( | a, | |||
b | ) | ((a) < (b) ? (a) : (b)) |
Definition at line 233 of file chan_oss.c.
#define O_CLOSE 0x444 |
Definition at line 224 of file chan_oss.c.
Referenced by console_hangup(), oss_hangup(), setformat(), and usbradio_hangup().
#define QUEUE_SIZE 10 |
Definition at line 207 of file chan_oss.c.
#define TEXT_SIZE 256 |
Definition at line 219 of file chan_oss.c.
#define WARN_frag 4 |
#define WARN_speed 2 |
#define WARN_used_blocks 1 |
static void __reg_module | ( | void | ) | [static] |
Definition at line 1494 of file chan_oss.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 1494 of file chan_oss.c.
static char* ast_ext_ctx | ( | const char * | src, | |
char ** | ext, | |||
char ** | ctx | |||
) | [static] |
Definition at line 396 of file chan_oss.c.
References ast_strdup, find_desc(), and chan_oss_pvt::overridecontext.
00397 { 00398 struct chan_oss_pvt *o = find_desc(oss_active); 00399 00400 if (ext == NULL || ctx == NULL) 00401 return NULL; /* error */ 00402 00403 *ext = *ctx = NULL; 00404 00405 if (src && *src != '\0') 00406 *ext = ast_strdup(src); 00407 00408 if (*ext == NULL) 00409 return NULL; 00410 00411 if (!o->overridecontext) { 00412 /* parse from the right */ 00413 *ctx = strrchr(*ext, '@'); 00414 if (*ctx) 00415 *(*ctx)++ = '\0'; 00416 } 00417 00418 return *ext; 00419 }
static char* console_active | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1201 of file chan_oss.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, find_desc(), chan_oss_pvt::name, chan_oss_pvt::next, oss_default, and ast_cli_entry::usage.
01202 { 01203 switch (cmd) { 01204 case CLI_INIT: 01205 e->command = "console active"; 01206 e->usage = 01207 "Usage: console active [device]\n" 01208 " If used without a parameter, displays which device is the current\n" 01209 " console. If a device is specified, the console sound device is changed to\n" 01210 " the device specified.\n"; 01211 return NULL; 01212 case CLI_GENERATE: 01213 return NULL; 01214 } 01215 01216 if (a->argc == 2) 01217 ast_cli(a->fd, "active console is [%s]\n", oss_active); 01218 else if (a->argc != 3) 01219 return CLI_SHOWUSAGE; 01220 else { 01221 struct chan_oss_pvt *o; 01222 if (strcmp(a->argv[2], "show") == 0) { 01223 for (o = oss_default.next; o; o = o->next) 01224 ast_cli(a->fd, "device [%s] exists\n", o->name); 01225 return CLI_SUCCESS; 01226 } 01227 o = find_desc(a->argv[2]); 01228 if (o == NULL) 01229 ast_cli(a->fd, "No device [%s] exists\n", a->argv[2]); 01230 else 01231 oss_active = o->name; 01232 } 01233 return CLI_SUCCESS; 01234 }
static char* console_answer | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
answer command from the console
Definition at line 966 of file chan_oss.c.
References ast_cli_args::argc, ast_cli_entry::args, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, console_do_answer(), ast_cli_args::fd, and ast_cli_entry::usage.
00967 { 00968 switch (cmd) { 00969 case CLI_INIT: 00970 e->command = "console answer"; 00971 e->usage = 00972 "Usage: console answer\n" 00973 " Answers an incoming call on the console (OSS) channel.\n"; 00974 return NULL; 00975 00976 case CLI_GENERATE: 00977 return NULL; /* no completion */ 00978 } 00979 if (a->argc != e->args) 00980 return CLI_SHOWUSAGE; 00981 return console_do_answer(a->fd); 00982 }
static char* console_autoanswer | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 910 of file chan_oss.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_log(), chan_oss_pvt::autoanswer, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, find_desc(), LOG_WARNING, and ast_cli_entry::usage.
00911 { 00912 struct chan_oss_pvt *o = find_desc(oss_active); 00913 00914 switch (cmd) { 00915 case CLI_INIT: 00916 e->command = "console autoanswer [on|off]"; 00917 e->usage = 00918 "Usage: console autoanswer [on|off]\n" 00919 " Enables or disables autoanswer feature. If used without\n" 00920 " argument, displays the current on/off status of autoanswer.\n" 00921 " The default value of autoanswer is in 'oss.conf'.\n"; 00922 return NULL; 00923 00924 case CLI_GENERATE: 00925 return NULL; 00926 } 00927 00928 if (a->argc == e->args - 1) { 00929 ast_cli(a->fd, "Auto answer is %s.\n", o->autoanswer ? "on" : "off"); 00930 return CLI_SUCCESS; 00931 } 00932 if (a->argc != e->args) 00933 return CLI_SHOWUSAGE; 00934 if (o == NULL) { 00935 ast_log(LOG_WARNING, "Cannot find device %s (should not happen!)\n", 00936 oss_active); 00937 return CLI_FAILURE; 00938 } 00939 if (!strcasecmp(a->argv[e->args-1], "on")) 00940 o->autoanswer = 1; 00941 else if (!strcasecmp(a->argv[e->args - 1], "off")) 00942 o->autoanswer = 0; 00943 else 00944 return CLI_SHOWUSAGE; 00945 return CLI_SUCCESS; 00946 }
static char* console_boost | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1258 of file chan_oss.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), chan_oss_pvt::boost, BOOST_SCALE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, find_desc(), store_boost(), and ast_cli_entry::usage.
01259 { 01260 struct chan_oss_pvt *o = find_desc(oss_active); 01261 01262 switch (cmd) { 01263 case CLI_INIT: 01264 e->command = "console boost"; 01265 e->usage = 01266 "Usage: console boost [boost in dB]\n" 01267 " Sets or display mic boost in dB\n"; 01268 return NULL; 01269 case CLI_GENERATE: 01270 return NULL; 01271 } 01272 01273 if (a->argc == 2) 01274 ast_cli(a->fd, "boost currently %5.1f\n", 20 * log10(((double) o->boost / (double) BOOST_SCALE))); 01275 else if (a->argc == 3) 01276 store_boost(o, a->argv[2]); 01277 return CLI_SUCCESS; 01278 }
static char* console_cmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Generic console command handler. Basically a wrapper for a subset of config file options which are also available from the CLI
Definition at line 874 of file chan_oss.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_log(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, console_video_cli(), CONSOLE_VIDEO_CMDS, ast_cli_args::fd, find_desc(), LOG_WARNING, store_config_core(), ast_cli_entry::usage, and var.
00875 { 00876 struct chan_oss_pvt *o = find_desc(oss_active); 00877 const char *var, *value; 00878 switch (cmd) { 00879 case CLI_INIT: 00880 e->command = CONSOLE_VIDEO_CMDS; 00881 e->usage = 00882 "Usage: " CONSOLE_VIDEO_CMDS "...\n" 00883 " Generic handler for console commands.\n"; 00884 return NULL; 00885 00886 case CLI_GENERATE: 00887 return NULL; 00888 } 00889 00890 if (a->argc < e->args) 00891 return CLI_SHOWUSAGE; 00892 if (o == NULL) { 00893 ast_log(LOG_WARNING, "Cannot find device %s (should not happen!)\n", 00894 oss_active); 00895 return CLI_FAILURE; 00896 } 00897 var = a->argv[e->args-1]; 00898 value = a->argc > e->args ? a->argv[e->args] : NULL; 00899 if (value) /* handle setting */ 00900 store_config_core(o, var, value); 00901 if (!console_video_cli(o->env, var, a->fd)) /* print video-related values */ 00902 return CLI_SUCCESS; 00903 /* handle other values */ 00904 if (!strcasecmp(var, "device")) { 00905 ast_cli(a->fd, "device is [%s]\n", o->device); 00906 } 00907 return CLI_SUCCESS; 00908 }
static char* console_dial | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1076 of file chan_oss.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_exists_extension(), ast_ext_ctx(), AST_FRAME_DTMF, ast_free, ast_queue_frame(), AST_STATE_RINGING, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, chan_oss_pvt::ctx, chan_oss_pvt::ext, f, ast_cli_args::fd, find_desc(), chan_oss_pvt::hookstate, oss_new(), chan_oss_pvt::owner, s, and ast_cli_entry::usage.
01077 { 01078 char *s = NULL, *mye = NULL, *myc = NULL; 01079 struct chan_oss_pvt *o = find_desc(oss_active); 01080 01081 if (cmd == CLI_INIT) { 01082 e->command = "console dial"; 01083 e->usage = 01084 "Usage: console dial [extension[@context]]\n" 01085 " Dials a given extension (and context if specified)\n"; 01086 return NULL; 01087 } else if (cmd == CLI_GENERATE) 01088 return NULL; 01089 01090 if (a->argc > e->args + 1) 01091 return CLI_SHOWUSAGE; 01092 if (o->owner) { /* already in a call */ 01093 int i; 01094 struct ast_frame f = { AST_FRAME_DTMF, 0 }; 01095 01096 if (a->argc == e->args) { /* argument is mandatory here */ 01097 ast_cli(a->fd, "Already in a call. You can only dial digits until you hangup.\n"); 01098 return CLI_FAILURE; 01099 } 01100 s = a->argv[e->args]; 01101 /* send the string one char at a time */ 01102 for (i = 0; i < strlen(s); i++) { 01103 f.subclass = s[i]; 01104 ast_queue_frame(o->owner, &f); 01105 } 01106 return CLI_SUCCESS; 01107 } 01108 /* if we have an argument split it into extension and context */ 01109 if (a->argc == e->args + 1) 01110 s = ast_ext_ctx(a->argv[e->args], &mye, &myc); 01111 /* supply default values if needed */ 01112 if (mye == NULL) 01113 mye = o->ext; 01114 if (myc == NULL) 01115 myc = o->ctx; 01116 if (ast_exists_extension(NULL, myc, mye, 1, NULL)) { 01117 o->hookstate = 1; 01118 oss_new(o, mye, myc, AST_STATE_RINGING); 01119 } else 01120 ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc); 01121 if (s) 01122 ast_free(s); 01123 return CLI_SUCCESS; 01124 }
static char* console_do_answer | ( | int | fd | ) | [static] |
helper function for the answer key/cli command
Definition at line 949 of file chan_oss.c.
References ast_cli(), AST_CONTROL_ANSWER, AST_FRAME_CONTROL, ast_queue_frame(), CLI_FAILURE, CLI_SUCCESS, f, find_desc(), chan_oss_pvt::hookstate, and chan_oss_pvt::owner.
Referenced by console_answer().
00950 { 00951 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER }; 00952 struct chan_oss_pvt *o = find_desc(oss_active); 00953 if (!o->owner) { 00954 if (fd > -1) 00955 ast_cli(fd, "No one is calling us\n"); 00956 return CLI_FAILURE; 00957 } 00958 o->hookstate = 1; 00959 ast_queue_frame(o->owner, &f); 00960 return CLI_SUCCESS; 00961 }
static char* console_flash | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1050 of file chan_oss.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli(), AST_CONTROL_FLASH, AST_FRAME_CONTROL, ast_queue_frame(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, f, ast_cli_args::fd, find_desc(), chan_oss_pvt::hookstate, chan_oss_pvt::owner, and ast_cli_entry::usage.
01051 { 01052 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_FLASH }; 01053 struct chan_oss_pvt *o = find_desc(oss_active); 01054 01055 if (cmd == CLI_INIT) { 01056 e->command = "console flash"; 01057 e->usage = 01058 "Usage: console flash\n" 01059 " Flashes the call currently placed on the console.\n"; 01060 return NULL; 01061 } else if (cmd == CLI_GENERATE) 01062 return NULL; 01063 01064 if (a->argc != e->args) 01065 return CLI_SHOWUSAGE; 01066 if (!o->owner) { /* XXX maybe !o->hookstate too ? */ 01067 ast_cli(a->fd, "No call to flash\n"); 01068 return CLI_FAILURE; 01069 } 01070 o->hookstate = 0; 01071 if (o->owner) 01072 ast_queue_frame(o->owner, &f); 01073 return CLI_SUCCESS; 01074 }
static char* console_hangup | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1024 of file chan_oss.c.
References ast_cli_args::argc, ast_cli_entry::args, AST_CAUSE_NORMAL_CLEARING, ast_cli(), ast_queue_hangup_with_cause(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, find_desc(), chan_oss_pvt::hookstate, O_CLOSE, chan_oss_pvt::owner, setformat(), and ast_cli_entry::usage.
01025 { 01026 struct chan_oss_pvt *o = find_desc(oss_active); 01027 01028 if (cmd == CLI_INIT) { 01029 e->command = "console hangup"; 01030 e->usage = 01031 "Usage: console hangup\n" 01032 " Hangs up any call currently placed on the console.\n"; 01033 return NULL; 01034 } else if (cmd == CLI_GENERATE) 01035 return NULL; 01036 01037 if (a->argc != e->args) 01038 return CLI_SHOWUSAGE; 01039 if (!o->owner && !o->hookstate) { /* XXX maybe only one ? */ 01040 ast_cli(a->fd, "No call to hang up\n"); 01041 return CLI_FAILURE; 01042 } 01043 o->hookstate = 0; 01044 if (o->owner) 01045 ast_queue_hangup_with_cause(o->owner, AST_CAUSE_NORMAL_CLEARING); 01046 setformat(o, O_CLOSE); 01047 return CLI_SUCCESS; 01048 }
static char* console_mute | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1126 of file chan_oss.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, find_desc(), chan_oss_pvt::mute, s, and ast_cli_entry::usage.
01127 { 01128 struct chan_oss_pvt *o = find_desc(oss_active); 01129 char *s; 01130 int toggle = 0; 01131 01132 if (cmd == CLI_INIT) { 01133 e->command = "console {mute|unmute} [toggle]"; 01134 e->usage = 01135 "Usage: console {mute|unmute} [toggle]\n" 01136 " Mute/unmute the microphone.\n"; 01137 return NULL; 01138 } else if (cmd == CLI_GENERATE) 01139 return NULL; 01140 01141 if (a->argc > e->args) 01142 return CLI_SHOWUSAGE; 01143 if (a->argc == e->args) { 01144 if (strcasecmp(a->argv[e->args-1], "toggle")) 01145 return CLI_SHOWUSAGE; 01146 toggle = 1; 01147 } 01148 s = a->argv[e->args-2]; 01149 if (!strcasecmp(s, "mute")) 01150 o->mute = toggle ? ~o->mute : 1; 01151 else if (!strcasecmp(s, "unmute")) 01152 o->mute = toggle ? ~o->mute : 0; 01153 else 01154 return CLI_SHOWUSAGE; 01155 ast_cli(a->fd, "Console mic is %s\n", o->mute ? "off" : "on"); 01156 return CLI_SUCCESS; 01157 }
static char* console_sendtext | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Console send text CLI command.
Definition at line 990 of file chan_oss.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), AST_FRAME_TEXT, ast_join(), ast_queue_frame(), ast_strlen_zero(), buf, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, f, ast_cli_args::fd, find_desc(), chan_oss_pvt::owner, TEXT_SIZE, and ast_cli_entry::usage.
00991 { 00992 struct chan_oss_pvt *o = find_desc(oss_active); 00993 char buf[TEXT_SIZE]; 00994 00995 if (cmd == CLI_INIT) { 00996 e->command = "console send text"; 00997 e->usage = 00998 "Usage: console send text <message>\n" 00999 " Sends a text message for display on the remote terminal.\n"; 01000 return NULL; 01001 } else if (cmd == CLI_GENERATE) 01002 return NULL; 01003 01004 if (a->argc < e->args + 1) 01005 return CLI_SHOWUSAGE; 01006 if (!o->owner) { 01007 ast_cli(a->fd, "Not in a call\n"); 01008 return CLI_FAILURE; 01009 } 01010 ast_join(buf, sizeof(buf) - 1, a->argv + e->args); 01011 if (!ast_strlen_zero(buf)) { 01012 struct ast_frame f = { 0, }; 01013 int i = strlen(buf); 01014 buf[i] = '\n'; 01015 f.frametype = AST_FRAME_TEXT; 01016 f.subclass = 0; 01017 f.data.ptr = buf; 01018 f.datalen = i + 1; 01019 ast_queue_frame(o->owner, &f); 01020 } 01021 return CLI_SUCCESS; 01022 }
static char* console_transfer | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1159 of file chan_oss.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_async_goto(), ast_bridged_channel(), ast_cli(), ast_exists_extension(), ast_ext_ctx(), ast_free, ast_channel::cid, ast_callerid::cid_num, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_channel::context, ext, ast_cli_args::fd, find_desc(), ast_channel::name, chan_oss_pvt::owner, and ast_cli_entry::usage.
01160 { 01161 struct chan_oss_pvt *o = find_desc(oss_active); 01162 struct ast_channel *b = NULL; 01163 char *tmp, *ext, *ctx; 01164 01165 switch (cmd) { 01166 case CLI_INIT: 01167 e->command = "console transfer"; 01168 e->usage = 01169 "Usage: console transfer <extension>[@context]\n" 01170 " Transfers the currently connected call to the given extension (and\n" 01171 " context if specified)\n"; 01172 return NULL; 01173 case CLI_GENERATE: 01174 return NULL; 01175 } 01176 01177 if (a->argc != 3) 01178 return CLI_SHOWUSAGE; 01179 if (o == NULL) 01180 return CLI_FAILURE; 01181 if (o->owner == NULL || (b = ast_bridged_channel(o->owner)) == NULL) { 01182 ast_cli(a->fd, "There is no call to transfer\n"); 01183 return CLI_SUCCESS; 01184 } 01185 01186 tmp = ast_ext_ctx(a->argv[2], &ext, &ctx); 01187 if (ctx == NULL) /* supply default context if needed */ 01188 ctx = o->owner->context; 01189 if (!ast_exists_extension(b, ctx, ext, 1, b->cid.cid_num)) 01190 ast_cli(a->fd, "No such extension exists\n"); 01191 else { 01192 ast_cli(a->fd, "Whee, transferring %s to %s@%s.\n", b->name, ext, ctx); 01193 if (ast_async_goto(b, ctx, ext, 1)) 01194 ast_cli(a->fd, "Failed to transfer :(\n"); 01195 } 01196 if (tmp) 01197 ast_free(tmp); 01198 return CLI_SUCCESS; 01199 }
static struct chan_oss_pvt * find_desc | ( | char * | dev | ) | [static] |
returns a pointer to the descriptor with the given name
forward declaration
Definition at line 370 of file chan_oss.c.
References ast_log(), LOG_WARNING, chan_oss_pvt::name, chan_oss_pvt::next, and oss_default.
Referenced by ast_ext_ctx(), console_active(), console_autoanswer(), console_boost(), console_cmd(), console_dial(), console_do_answer(), console_flash(), console_hangup(), console_key(), console_mute(), console_sendtext(), console_transfer(), console_unkey(), get_video_desc(), keypad_toggle(), load_module(), oss_request(), radio_active(), radio_set_debug(), radio_set_debug_off(), radio_set_xpmr_debug(), radio_tune(), usbradio_request(), and usbradio_text().
00371 { 00372 struct chan_oss_pvt *o = NULL; 00373 00374 if (!dev) 00375 ast_log(LOG_WARNING, "null dev\n"); 00376 00377 for (o = oss_default.next; o && o->name && dev && strcmp(o->name, dev) != 0; o = o->next); 00378 00379 if (!o) 00380 ast_log(LOG_WARNING, "could not find <%s>\n", dev ? dev : "--no-device--"); 00381 00382 return o; 00383 }
struct video_desc* get_video_desc | ( | struct ast_channel * | c | ) |
return the pointer to the video descriptor
Definition at line 313 of file chan_oss.c.
References chan_oss_pvt::env, find_desc(), and ast_channel::tech_pvt.
Referenced by oss_new().
00314 { 00315 struct chan_oss_pvt *o = c ? c->tech_pvt : find_desc(oss_active); 00316 return o ? o->env : NULL; 00317 }
static int load_module | ( | void | ) | [static] |
Definition at line 1431 of file chan_oss.c.
References ast_category_browse(), ast_channel_register(), ast_cli_register_multiple(), ast_config_destroy(), ast_config_load, ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_channel_tech::capabilities, cli_oss, config_flags, console_video_formats, default_jbconf, find_desc(), global_jbconf, LOG_ERROR, LOG_NOTICE, oss_tech, and store_config().
01432 { 01433 struct ast_config *cfg = NULL; 01434 char *ctg = NULL; 01435 struct ast_flags config_flags = { 0 }; 01436 01437 /* Copy the default jb config over global_jbconf */ 01438 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 01439 01440 /* load config file */ 01441 if (!(cfg = ast_config_load(config, config_flags))) { 01442 ast_log(LOG_NOTICE, "Unable to load config %s\n", config); 01443 return AST_MODULE_LOAD_DECLINE; 01444 } 01445 01446 do { 01447 store_config(cfg, ctg); 01448 } while ( (ctg = ast_category_browse(cfg, ctg)) != NULL); 01449 01450 ast_config_destroy(cfg); 01451 01452 if (find_desc(oss_active) == NULL) { 01453 ast_log(LOG_NOTICE, "Device %s not found\n", oss_active); 01454 /* XXX we could default to 'dsp' perhaps ? */ 01455 /* XXX should cleanup allocated memory etc. */ 01456 return AST_MODULE_LOAD_FAILURE; 01457 } 01458 01459 oss_tech.capabilities |= console_video_formats; 01460 01461 if (ast_channel_register(&oss_tech)) { 01462 ast_log(LOG_ERROR, "Unable to register channel type 'OSS'\n"); 01463 return AST_MODULE_LOAD_FAILURE; 01464 } 01465 01466 ast_cli_register_multiple(cli_oss, sizeof(cli_oss) / sizeof(struct ast_cli_entry)); 01467 01468 return AST_MODULE_LOAD_SUCCESS; 01469 }
static int oss_answer | ( | struct ast_channel * | c | ) | [static] |
remote side answered the phone
Definition at line 638 of file chan_oss.c.
References ast_setstate(), AST_STATE_UP, ast_verbose, chan_oss_pvt::hookstate, and ast_channel::tech_pvt.
00639 { 00640 struct chan_oss_pvt *o = c->tech_pvt; 00641 ast_verbose(" << Console call has been answered >> \n"); 00642 ast_setstate(c, AST_STATE_UP); 00643 o->hookstate = 1; 00644 return 0; 00645 }
static int oss_call | ( | struct ast_channel * | c, | |
char * | dest, | |||
int | timeout | |||
) | [static] |
handler for incoming calls. Either autoanswer, or start ringing
Definition at line 597 of file chan_oss.c.
References AST_APP_ARG, AST_CONTROL_ANSWER, AST_CONTROL_RINGING, AST_DECLARE_APP_ARGS, AST_FRAME_CONTROL, ast_indicate(), AST_NONSTANDARD_APP_ARGS, ast_queue_frame(), ast_strdupa, ast_strlen_zero(), ast_verbose, chan_oss_pvt::autoanswer, ast_channel::cid, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_rdnis, f, ast_frame::flags, chan_oss_pvt::hookstate, name, parse(), and ast_channel::tech_pvt.
00598 { 00599 struct chan_oss_pvt *o = c->tech_pvt; 00600 struct ast_frame f = { 0, }; 00601 AST_DECLARE_APP_ARGS(args, 00602 AST_APP_ARG(name); 00603 AST_APP_ARG(flags); 00604 ); 00605 char *parse = ast_strdupa(dest); 00606 00607 AST_NONSTANDARD_APP_ARGS(args, parse, '/'); 00608 00609 ast_verbose(" << Call to device '%s' dnid '%s' rdnis '%s' on console from '%s' <%s> >>\n", dest, c->cid.cid_dnid, c->cid.cid_rdnis, c->cid.cid_name, c->cid.cid_num); 00610 if (!ast_strlen_zero(args.flags) && strcasecmp(args.flags, "answer") == 0) { 00611 f.frametype = AST_FRAME_CONTROL; 00612 f.subclass = AST_CONTROL_ANSWER; 00613 ast_queue_frame(c, &f); 00614 } else if (!ast_strlen_zero(args.flags) && strcasecmp(args.flags, "noanswer") == 0) { 00615 f.frametype = AST_FRAME_CONTROL; 00616 f.subclass = AST_CONTROL_RINGING; 00617 ast_queue_frame(c, &f); 00618 ast_indicate(c, AST_CONTROL_RINGING); 00619 } else if (o->autoanswer) { 00620 ast_verbose(" << Auto-answered >> \n"); 00621 f.frametype = AST_FRAME_CONTROL; 00622 f.subclass = AST_CONTROL_ANSWER; 00623 ast_queue_frame(c, &f); 00624 o->hookstate = 1; 00625 } else { 00626 ast_verbose("<< Type 'answer' to answer, or use 'autoanswer' for future calls >> \n"); 00627 f.frametype = AST_FRAME_CONTROL; 00628 f.subclass = AST_CONTROL_RINGING; 00629 ast_queue_frame(c, &f); 00630 ast_indicate(c, AST_CONTROL_RINGING); 00631 } 00632 return 0; 00633 }
static int oss_digit_begin | ( | struct ast_channel * | c, | |
char | digit | |||
) | [static] |
static int oss_digit_end | ( | struct ast_channel * | c, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 579 of file chan_oss.c.
References ast_verbose.
00580 { 00581 /* no better use for received digits than print them */ 00582 ast_verbose(" << Console Received digit %c of duration %u ms >> \n", 00583 digit, duration); 00584 return 0; 00585 }
static int oss_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 747 of file chan_oss.c.
References chan_oss_pvt::owner, and ast_channel::tech_pvt.
00748 { 00749 struct chan_oss_pvt *o = newchan->tech_pvt; 00750 o->owner = newchan; 00751 return 0; 00752 }
static int oss_hangup | ( | struct ast_channel * | c | ) | [static] |
Definition at line 647 of file chan_oss.c.
References ast_module_unref(), ast_verbose, chan_oss_pvt::autoanswer, chan_oss_pvt::autohangup, console_video_uninit(), chan_oss_pvt::env, chan_oss_pvt::hookstate, O_CLOSE, chan_oss_pvt::owner, setformat(), and ast_channel::tech_pvt.
00648 { 00649 struct chan_oss_pvt *o = c->tech_pvt; 00650 00651 c->tech_pvt = NULL; 00652 o->owner = NULL; 00653 ast_verbose(" << Hangup on console >> \n"); 00654 console_video_uninit(o->env); 00655 ast_module_unref(ast_module_info->self); 00656 if (o->hookstate) { 00657 if (o->autoanswer || o->autohangup) { 00658 /* Assume auto-hangup too */ 00659 o->hookstate = 0; 00660 setformat(o, O_CLOSE); 00661 } 00662 } 00663 return 0; 00664 }
static int oss_indicate | ( | struct ast_channel * | chan, | |
int | cond, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 754 of file chan_oss.c.
References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_log(), ast_moh_start(), ast_moh_stop(), ast_verbose, LOG_WARNING, chan_oss_pvt::mohinterpret, ast_channel::name, and ast_channel::tech_pvt.
00755 { 00756 struct chan_oss_pvt *o = c->tech_pvt; 00757 int res = 0; 00758 00759 switch (cond) { 00760 case AST_CONTROL_BUSY: 00761 case AST_CONTROL_CONGESTION: 00762 case AST_CONTROL_RINGING: 00763 case -1: 00764 res = -1; 00765 break; 00766 case AST_CONTROL_PROGRESS: 00767 case AST_CONTROL_PROCEEDING: 00768 case AST_CONTROL_VIDUPDATE: 00769 case AST_CONTROL_SRCUPDATE: 00770 break; 00771 case AST_CONTROL_HOLD: 00772 ast_verbose(" << Console Has Been Placed on Hold >> \n"); 00773 ast_moh_start(c, data, o->mohinterpret); 00774 break; 00775 case AST_CONTROL_UNHOLD: 00776 ast_verbose(" << Console Has Been Retrieved from Hold >> \n"); 00777 ast_moh_stop(c); 00778 break; 00779 default: 00780 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name); 00781 return -1; 00782 } 00783 00784 return res; 00785 }
static struct ast_channel* oss_new | ( | struct chan_oss_pvt * | o, | |
char * | ext, | |||
char * | ctx, | |||
int | state | |||
) | [static] |
allocate a new channel.
Definition at line 790 of file chan_oss.c.
References ast_channel_alloc(), ast_channel_set_fd(), AST_FORMAT_SLINEAR, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), AST_STATE_DOWN, AST_STATE_RINGING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, chan_oss_pvt::cid_name, chan_oss_pvt::cid_num, console_video_formats, console_video_start(), chan_oss_pvt::device, get_video_desc(), global_jbconf, language, chan_oss_pvt::language, LOG_WARNING, ast_channel::nativeformats, oss_tech, chan_oss_pvt::owner, ast_channel::readformat, setformat(), chan_oss_pvt::sounddev, ast_channel::tech, ast_channel::tech_pvt, and ast_channel::writeformat.
Referenced by console_dial(), and oss_request().
00791 { 00792 struct ast_channel *c; 00793 00794 c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, 0, "Console/%s", o->device + 5); 00795 if (c == NULL) 00796 return NULL; 00797 c->tech = &oss_tech; 00798 if (o->sounddev < 0) 00799 setformat(o, O_RDWR); 00800 ast_channel_set_fd(c, 0, o->sounddev); /* -1 if device closed, override later */ 00801 c->nativeformats = AST_FORMAT_SLINEAR; 00802 /* if the console makes the call, add video to the offer */ 00803 if (state == AST_STATE_RINGING) 00804 c->nativeformats |= console_video_formats; 00805 00806 c->readformat = AST_FORMAT_SLINEAR; 00807 c->writeformat = AST_FORMAT_SLINEAR; 00808 c->tech_pvt = o; 00809 00810 if (!ast_strlen_zero(o->language)) 00811 ast_string_field_set(c, language, o->language); 00812 /* Don't use ast_set_callerid() here because it will 00813 * generate a needless NewCallerID event */ 00814 c->cid.cid_ani = ast_strdup(o->cid_num); 00815 if (!ast_strlen_zero(ext)) 00816 c->cid.cid_dnid = ast_strdup(ext); 00817 00818 o->owner = c; 00819 ast_module_ref(ast_module_info->self); 00820 ast_jb_configure(c, &global_jbconf); 00821 if (state != AST_STATE_DOWN) { 00822 if (ast_pbx_start(c)) { 00823 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", c->name); 00824 ast_hangup(c); 00825 o->owner = c = NULL; 00826 } 00827 } 00828 console_video_start(get_video_desc(c), c); /* XXX cleanup */ 00829 00830 return c; 00831 }
static struct ast_frame * oss_read | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 698 of file chan_oss.c.
References ast_channel::_state, AST_FORMAT_SLINEAR, AST_FRAME_NULL, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, AST_STATE_UP, chan_oss_pvt::boost, BOOST_SCALE, f, FRAME_SIZE, chan_oss_pvt::mute, chan_oss_pvt::oss_read_buf, oss_tech, chan_oss_pvt::read_f, chan_oss_pvt::readpos, chan_oss_pvt::sounddev, ast_channel::tech_pvt, and ast_channel_tech::type.
00699 { 00700 int res; 00701 struct chan_oss_pvt *o = c->tech_pvt; 00702 struct ast_frame *f = &o->read_f; 00703 00704 /* XXX can be simplified returning &ast_null_frame */ 00705 /* prepare a NULL frame in case we don't have enough data to return */ 00706 memset(f, '\0', sizeof(struct ast_frame)); 00707 f->frametype = AST_FRAME_NULL; 00708 f->src = oss_tech.type; 00709 00710 res = read(o->sounddev, o->oss_read_buf + o->readpos, sizeof(o->oss_read_buf) - o->readpos); 00711 if (res < 0) /* audio data not ready, return a NULL frame */ 00712 return f; 00713 00714 o->readpos += res; 00715 if (o->readpos < sizeof(o->oss_read_buf)) /* not enough samples */ 00716 return f; 00717 00718 if (o->mute) 00719 return f; 00720 00721 o->readpos = AST_FRIENDLY_OFFSET; /* reset read pointer for next frame */ 00722 if (c->_state != AST_STATE_UP) /* drop data if frame is not up */ 00723 return f; 00724 /* ok we can build and deliver the frame to the caller */ 00725 f->frametype = AST_FRAME_VOICE; 00726 f->subclass = AST_FORMAT_SLINEAR; 00727 f->samples = FRAME_SIZE; 00728 f->datalen = FRAME_SIZE * 2; 00729 f->data.ptr = o->oss_read_buf + AST_FRIENDLY_OFFSET; 00730 if (o->boost != BOOST_SCALE) { /* scale and clip values */ 00731 int i, x; 00732 int16_t *p = (int16_t *) f->data.ptr; 00733 for (i = 0; i < f->samples; i++) { 00734 x = (p[i] * o->boost) / BOOST_SCALE; 00735 if (x > 32767) 00736 x = 32767; 00737 else if (x < -32768) 00738 x = -32768; 00739 p[i] = x; 00740 } 00741 } 00742 00743 f->offset = AST_FRIENDLY_OFFSET; 00744 return f; 00745 }
static struct ast_channel * oss_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 833 of file chan_oss.c.
References AST_APP_ARG, AST_CAUSE_BUSY, AST_DECLARE_APP_ARGS, AST_FORMAT_SLINEAR, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STATE_DOWN, ast_strdupa, find_desc(), LOG_NOTICE, LOG_WARNING, name, oss_new(), chan_oss_pvt::owner, and parse().
00834 { 00835 struct ast_channel *c; 00836 struct chan_oss_pvt *o; 00837 AST_DECLARE_APP_ARGS(args, 00838 AST_APP_ARG(name); 00839 AST_APP_ARG(flags); 00840 ); 00841 char *parse = ast_strdupa(data); 00842 00843 AST_NONSTANDARD_APP_ARGS(args, parse, '/'); 00844 o = find_desc(args.name); 00845 00846 ast_log(LOG_WARNING, "oss_request ty <%s> data 0x%p <%s>\n", type, data, (char *) data); 00847 if (o == NULL) { 00848 ast_log(LOG_NOTICE, "Device %s not found\n", args.name); 00849 /* XXX we could default to 'dsp' perhaps ? */ 00850 return NULL; 00851 } 00852 if ((format & AST_FORMAT_SLINEAR) == 0) { 00853 ast_log(LOG_NOTICE, "Format 0x%x unsupported\n", format); 00854 return NULL; 00855 } 00856 if (o->owner) { 00857 ast_log(LOG_NOTICE, "Already have a call (chan %p) on the OSS channel\n", o->owner); 00858 *cause = AST_CAUSE_BUSY; 00859 return NULL; 00860 } 00861 c = oss_new(o, NULL, NULL, AST_STATE_DOWN); 00862 if (c == NULL) { 00863 ast_log(LOG_WARNING, "Unable to create new OSS channel\n"); 00864 return NULL; 00865 } 00866 return c; 00867 }
static int oss_text | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 587 of file chan_oss.c.
References ast_verbose.
00588 { 00589 /* print received messages */ 00590 ast_verbose(" << Console Received text %s >> \n", text); 00591 return 0; 00592 }
static int oss_write | ( | struct ast_channel * | chan, | |
struct ast_frame * | f | |||
) | [static] |
used for data coming from the network
Definition at line 667 of file chan_oss.c.
References f, chan_oss_pvt::oss_write_buf, chan_oss_pvt::oss_write_dst, soundcard_writeframe(), and ast_channel::tech_pvt.
00668 { 00669 int src; 00670 struct chan_oss_pvt *o = c->tech_pvt; 00671 00672 /* 00673 * we could receive a block which is not a multiple of our 00674 * FRAME_SIZE, so buffer it locally and write to the device 00675 * in FRAME_SIZE chunks. 00676 * Keep the residue stored for future use. 00677 */ 00678 src = 0; /* read position into f->data */ 00679 while (src < f->datalen) { 00680 /* Compute spare room in the buffer */ 00681 int l = sizeof(o->oss_write_buf) - o->oss_write_dst; 00682 00683 if (f->datalen - src >= l) { /* enough to fill a frame */ 00684 memcpy(o->oss_write_buf + o->oss_write_dst, f->data.ptr + src, l); 00685 soundcard_writeframe(o, (short *) o->oss_write_buf); 00686 src += l; 00687 o->oss_write_dst = 0; 00688 } else { /* copy residue */ 00689 l = f->datalen - src; 00690 memcpy(o->oss_write_buf + o->oss_write_dst, f->data.ptr + src, l); 00691 src += l; /* but really, we are done */ 00692 o->oss_write_dst += l; 00693 } 00694 } 00695 return 0; 00696 }
static int setformat | ( | struct chan_oss_pvt * | o, | |
int | mode | |||
) | [static] |
reset and close the device if opened, then open and initialize it in the desired mode, trigger reads and writes so we can start using it.
Definition at line 475 of file chan_oss.c.
References ast_channel_set_fd(), ast_log(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, DEFAULT_SAMPLE_RATE, chan_oss_pvt::device, chan_oss_pvt::duplex, errno, chan_oss_pvt::frags, chan_oss_pvt::lastopen, LOG_WARNING, O_CLOSE, chan_oss_pvt::owner, chan_oss_pvt::sounddev, WARN_frag, WARN_speed, and chan_oss_pvt::warned.
Referenced by console_hangup(), oss_hangup(), oss_new(), soundcard_writeframe(), usbradio_hangup(), and usbradio_new().
00476 { 00477 int fmt, desired, res, fd; 00478 00479 if (o->sounddev >= 0) { 00480 ioctl(o->sounddev, SNDCTL_DSP_RESET, 0); 00481 close(o->sounddev); 00482 o->duplex = M_UNSET; 00483 o->sounddev = -1; 00484 } 00485 if (mode == O_CLOSE) /* we are done */ 00486 return 0; 00487 if (ast_tvdiff_ms(ast_tvnow(), o->lastopen) < 1000) 00488 return -1; /* don't open too often */ 00489 o->lastopen = ast_tvnow(); 00490 fd = o->sounddev = open(o->device, mode | O_NONBLOCK); 00491 if (fd < 0) { 00492 ast_log(LOG_WARNING, "Unable to re-open DSP device %s: %s\n", o->device, strerror(errno)); 00493 return -1; 00494 } 00495 if (o->owner) 00496 ast_channel_set_fd(o->owner, 0, fd); 00497 00498 #if __BYTE_ORDER == __LITTLE_ENDIAN 00499 fmt = AFMT_S16_LE; 00500 #else 00501 fmt = AFMT_S16_BE; 00502 #endif 00503 res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt); 00504 if (res < 0) { 00505 ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n"); 00506 return -1; 00507 } 00508 switch (mode) { 00509 case O_RDWR: 00510 res = ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0); 00511 /* Check to see if duplex set (FreeBSD Bug) */ 00512 res = ioctl(fd, SNDCTL_DSP_GETCAPS, &fmt); 00513 if (res == 0 && (fmt & DSP_CAP_DUPLEX)) { 00514 ast_verb(2, "Console is full duplex\n"); 00515 o->duplex = M_FULL; 00516 }; 00517 break; 00518 00519 case O_WRONLY: 00520 o->duplex = M_WRITE; 00521 break; 00522 00523 case O_RDONLY: 00524 o->duplex = M_READ; 00525 break; 00526 } 00527 00528 fmt = 0; 00529 res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt); 00530 if (res < 0) { 00531 ast_log(LOG_WARNING, "Failed to set audio device to mono\n"); 00532 return -1; 00533 } 00534 fmt = desired = DEFAULT_SAMPLE_RATE; /* 8000 Hz desired */ 00535 res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt); 00536 00537 if (res < 0) { 00538 ast_log(LOG_WARNING, "Failed to set audio device to mono\n"); 00539 return -1; 00540 } 00541 if (fmt != desired) { 00542 if (!(o->warned & WARN_speed)) { 00543 ast_log(LOG_WARNING, 00544 "Requested %d Hz, got %d Hz -- sound may be choppy\n", 00545 desired, fmt); 00546 o->warned |= WARN_speed; 00547 } 00548 } 00549 /* 00550 * on Freebsd, SETFRAGMENT does not work very well on some cards. 00551 * Default to use 256 bytes, let the user override 00552 */ 00553 if (o->frags) { 00554 fmt = o->frags; 00555 res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt); 00556 if (res < 0) { 00557 if (!(o->warned & WARN_frag)) { 00558 ast_log(LOG_WARNING, 00559 "Unable to set fragment size -- sound may be choppy\n"); 00560 o->warned |= WARN_frag; 00561 } 00562 } 00563 } 00564 /* on some cards, we need SNDCTL_DSP_SETTRIGGER to start outputting */ 00565 res = PCM_ENABLE_INPUT | PCM_ENABLE_OUTPUT; 00566 res = ioctl(fd, SNDCTL_DSP_SETTRIGGER, &res); 00567 /* it may fail if we are in half duplex, never mind */ 00568 return 0; 00569 }
static int soundcard_writeframe | ( | struct chan_oss_pvt * | o, | |
short * | data | |||
) | [static] |
Write an exactly FRAME_SIZE sized frame
Definition at line 446 of file chan_oss.c.
References ast_log(), FRAME_SIZE, LOG_WARNING, chan_oss_pvt::queuesize, setformat(), chan_oss_pvt::sounddev, used_blocks(), and chan_oss_pvt::w_errors.
Referenced by oss_write(), and usbradio_read().
00447 { 00448 int res; 00449 00450 if (o->sounddev < 0) 00451 setformat(o, O_RDWR); 00452 if (o->sounddev < 0) 00453 return 0; /* not fatal */ 00454 /* 00455 * Nothing complex to manage the audio device queue. 00456 * If the buffer is full just drop the extra, otherwise write. 00457 * XXX in some cases it might be useful to write anyways after 00458 * a number of failures, to restart the output chain. 00459 */ 00460 res = used_blocks(o); 00461 if (res > o->queuesize) { /* no room to write a block */ 00462 if (o->w_errors++ == 0 && (oss_debug & 0x4)) 00463 ast_log(LOG_WARNING, "write: used %d blocks (%d)\n", res, o->w_errors); 00464 return 0; 00465 } 00466 o->w_errors = 0; 00467 return write(o->sounddev, (void *)data, FRAME_SIZE * 2); 00468 }
static void store_boost | ( | struct chan_oss_pvt * | o, | |
const char * | s | |||
) | [static] |
store the boost factor
Definition at line 1239 of file chan_oss.c.
References ast_log(), chan_oss_pvt::boost, BOOST_MAX, BOOST_SCALE, and LOG_WARNING.
Referenced by console_boost(), and store_config_core().
01240 { 01241 double boost = 0; 01242 if (sscanf(s, "%lf", &boost) != 1) { 01243 ast_log(LOG_WARNING, "invalid boost <%s>\n", s); 01244 return; 01245 } 01246 if (boost < -BOOST_MAX) { 01247 ast_log(LOG_WARNING, "boost %s too small, using %d\n", s, -BOOST_MAX); 01248 boost = -BOOST_MAX; 01249 } else if (boost > BOOST_MAX) { 01250 ast_log(LOG_WARNING, "boost %s too large, using %d\n", s, BOOST_MAX); 01251 boost = BOOST_MAX; 01252 } 01253 boost = exp(log(10) * boost / 20) * BOOST_SCALE; 01254 o->boost = boost; 01255 ast_log(LOG_WARNING, "setting boost %s to %d\n", s, o->boost); 01256 }
static void store_callerid | ( | struct chan_oss_pvt * | o, | |
const char * | s | |||
) | [static] |
store the callerid components
Definition at line 1318 of file chan_oss.c.
References ast_callerid_split(), chan_oss_pvt::cid_name, and chan_oss_pvt::cid_num.
01319 { 01320 ast_callerid_split(s, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num)); 01321 }
static struct chan_oss_pvt* store_config | ( | struct ast_config * | cfg, | |
char * | ctg | |||
) | [static] |
grab fields from the config file, init the descriptor and open the device.
Definition at line 1354 of file chan_oss.c.
References asprintf, ast_calloc, ast_copy_string(), ast_log(), ast_strdup, ast_strlen_zero(), ast_tvnow(), ast_variable_browse(), DEV_DSP, chan_oss_pvt::device, errno, chan_oss_pvt::lastopen, LOG_WARNING, chan_oss_pvt::mixer_cmd, chan_oss_pvt::mohinterpret, ast_variable::name, chan_oss_pvt::name, ast_variable::next, oss_default, store_config_core(), and ast_variable::value.
Referenced by load_module().
01355 { 01356 struct ast_variable *v; 01357 struct chan_oss_pvt *o; 01358 01359 if (ctg == NULL) { 01360 o = &oss_default; 01361 ctg = "general"; 01362 } else { 01363 if (!(o = ast_calloc(1, sizeof(*o)))) 01364 return NULL; 01365 *o = oss_default; 01366 /* "general" is also the default thing */ 01367 if (strcmp(ctg, "general") == 0) { 01368 o->name = ast_strdup("dsp"); 01369 oss_active = o->name; 01370 goto openit; 01371 } 01372 o->name = ast_strdup(ctg); 01373 } 01374 01375 strcpy(o->mohinterpret, "default"); 01376 01377 o->lastopen = ast_tvnow(); /* don't leave it 0 or tvdiff may wrap */ 01378 /* fill other fields from configuration */ 01379 for (v = ast_variable_browse(cfg, ctg); v; v = v->next) { 01380 store_config_core(o, v->name, v->value); 01381 } 01382 if (ast_strlen_zero(o->device)) 01383 ast_copy_string(o->device, DEV_DSP, sizeof(o->device)); 01384 if (o->mixer_cmd) { 01385 char *cmd; 01386 01387 if (asprintf(&cmd, "mixer %s", o->mixer_cmd) < 0) { 01388 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 01389 } else { 01390 ast_log(LOG_WARNING, "running [%s]\n", cmd); 01391 if (system(cmd) < 0) { 01392 ast_log(LOG_WARNING, "system() failed: %s\n", strerror(errno)); 01393 } 01394 ast_free(cmd); 01395 } 01396 } 01397 01398 /* if the config file requested to start the GUI, do it */ 01399 if (get_gui_startup(o->env)) 01400 console_video_start(o->env, NULL); 01401 01402 if (o == &oss_default) /* we are done with the default */ 01403 return NULL; 01404 01405 openit: 01406 #ifdef TRYOPEN 01407 if (setformat(o, O_RDWR) < 0) { /* open device */ 01408 ast_verb(1, "Device %s not detected\n", ctg); 01409 ast_verb(1, "Turn off OSS support by adding " "'noload=chan_oss.so' in /etc/asterisk/modules.conf\n"); 01410 goto error; 01411 } 01412 if (o->duplex != M_FULL) 01413 ast_log(LOG_WARNING, "XXX I don't work right with non " "full-duplex sound cards XXX\n"); 01414 #endif /* TRYOPEN */ 01415 01416 /* link into list of devices */ 01417 if (o != &oss_default) { 01418 o->next = oss_default.next; 01419 oss_default.next = o; 01420 } 01421 return o; 01422 01423 #ifdef TRYOPEN 01424 error: 01425 if (o != &oss_default) 01426 ast_free(o); 01427 return NULL; 01428 #endif 01429 }
static void store_config_core | ( | struct chan_oss_pvt * | o, | |
const char * | var, | |||
const char * | value | |||
) | [static] |
Definition at line 1323 of file chan_oss.c.
References ast_jb_read_conf(), chan_oss_pvt::autoanswer, chan_oss_pvt::autohangup, console_video_config(), chan_oss_pvt::ctx, CV_BOOL, CV_END, CV_F, CV_START, CV_STR, CV_UINT, chan_oss_pvt::device, chan_oss_pvt::env, chan_oss_pvt::ext, chan_oss_pvt::frags, global_jbconf, chan_oss_pvt::language, chan_oss_pvt::mohinterpret, chan_oss_pvt::overridecontext, chan_oss_pvt::queuesize, store_boost(), store_callerid(), and store_mixer().
01324 { 01325 CV_START(var, value); 01326 01327 /* handle jb conf */ 01328 if (!ast_jb_read_conf(&global_jbconf, var, value)) 01329 return; 01330 01331 if (!console_video_config(&o->env, var, value)) 01332 return; /* matched there */ 01333 CV_BOOL("autoanswer", o->autoanswer); 01334 CV_BOOL("autohangup", o->autohangup); 01335 CV_BOOL("overridecontext", o->overridecontext); 01336 CV_STR("device", o->device); 01337 CV_UINT("frags", o->frags); 01338 CV_UINT("debug", oss_debug); 01339 CV_UINT("queuesize", o->queuesize); 01340 CV_STR("context", o->ctx); 01341 CV_STR("language", o->language); 01342 CV_STR("mohinterpret", o->mohinterpret); 01343 CV_STR("extension", o->ext); 01344 CV_F("mixer", store_mixer(o, value)); 01345 CV_F("callerid", store_callerid(o, value)) ; 01346 CV_F("boost", store_boost(o, value)); 01347 01348 CV_END; 01349 }
static void store_mixer | ( | struct chan_oss_pvt * | o, | |
const char * | s | |||
) | [static] |
store the mixer argument from the config file, filtering possibly invalid or dangerous values (the string is used as argument for system("mixer %s")
Definition at line 1299 of file chan_oss.c.
References ast_free, ast_log(), ast_strdup, LOG_WARNING, and chan_oss_pvt::mixer_cmd.
Referenced by store_config_core().
01300 { 01301 int i; 01302 01303 for (i = 0; i < strlen(s); i++) { 01304 if (!isalnum(s[i]) && strchr(" \t-/", s[i]) == NULL) { 01305 ast_log(LOG_WARNING, "Suspect char %c in mixer cmd, ignoring:\n\t%s\n", s[i], s); 01306 return; 01307 } 01308 } 01309 if (o->mixer_cmd) 01310 ast_free(o->mixer_cmd); 01311 o->mixer_cmd = ast_strdup(s); 01312 ast_log(LOG_WARNING, "setting mixer %s\n", s); 01313 }
static int unload_module | ( | void | ) | [static] |
Definition at line 1472 of file chan_oss.c.
References ast_channel_unregister(), ast_cli_unregister_multiple(), ast_free, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, cli_oss, chan_oss_pvt::name, chan_oss_pvt::next, oss_default, oss_tech, chan_oss_pvt::owner, and chan_oss_pvt::sounddev.
01473 { 01474 struct chan_oss_pvt *o, *next; 01475 01476 ast_channel_unregister(&oss_tech); 01477 ast_cli_unregister_multiple(cli_oss, sizeof(cli_oss) / sizeof(struct ast_cli_entry)); 01478 01479 o = oss_default.next; 01480 while (o) { 01481 close(o->sounddev); 01482 if (o->owner) 01483 ast_softhangup(o->owner, AST_SOFTHANGUP_APPUNLOAD); 01484 if (o->owner) 01485 return -1; 01486 next = o->next; 01487 ast_free(o->name); 01488 ast_free(o); 01489 o = next; 01490 } 01491 return 0; 01492 }
static int used_blocks | ( | struct chan_oss_pvt * | o | ) | [static] |
Returns the number of blocks used in the audio output channel.
Definition at line 424 of file chan_oss.c.
References ast_log(), LOG_WARNING, chan_oss_pvt::sounddev, chan_oss_pvt::total_blocks, WARN_used_blocks, and chan_oss_pvt::warned.
Referenced by soundcard_writeframe().
00425 { 00426 struct audio_buf_info info; 00427 00428 if (ioctl(o->sounddev, SNDCTL_DSP_GETOSPACE, &info)) { 00429 if (!(o->warned & WARN_used_blocks)) { 00430 ast_log(LOG_WARNING, "Error reading output space\n"); 00431 o->warned |= WARN_used_blocks; 00432 } 00433 return 1; 00434 } 00435 00436 if (o->total_blocks == 0) { 00437 if (0) /* debugging */ 00438 ast_log(LOG_WARNING, "fragtotal %d size %d avail %d\n", info.fragstotal, info.fragsize, info.fragments); 00439 o->total_blocks = info.fragments; 00440 } 00441 00442 return o->total_blocks - info.fragments; 00443 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "OSS Console Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 1494 of file chan_oss.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1494 of file chan_oss.c.
struct ast_cli_entry cli_oss[] [static] |
char* config = "oss.conf" [static] |
Definition at line 239 of file chan_oss.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 69 of file chan_oss.c.
struct ast_jb_conf global_jbconf [static] |
Definition at line 76 of file chan_oss.c.
char* oss_active [static] |
int oss_debug [static] |
Definition at line 241 of file chan_oss.c.
struct chan_oss_pvt oss_default [static] |
Definition at line 318 of file chan_oss.c.
Referenced by console_active(), find_desc(), store_config(), and unload_module().
struct ast_channel_tech oss_tech [static] |
Definition at line 349 of file chan_oss.c.
Referenced by load_module(), oss_new(), oss_read(), and unload_module().
char tdesc[] = "OSS Console Channel Driver" [static] |
Definition at line 346 of file chan_oss.c.