#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_pvt * | find_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_channel * | oss_new (struct chan_oss_pvt *o, char *ext, char *ctx, int state, const char *linkedid) |
allocate a new channel. | |
static struct ast_frame * | oss_read (struct ast_channel *chan) |
static struct ast_channel * | oss_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_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_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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } |
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 274 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 215 of file chan_oss.c.
#define FRAME_SIZE 160 |
Definition at line 209 of file chan_oss.c.
#define O_CLOSE 0x444 |
Definition at line 227 of file chan_oss.c.
Referenced by console_hangup(), oss_hangup(), setformat(), and usbradio_hangup().
#define QUEUE_SIZE 10 |
Definition at line 210 of file chan_oss.c.
#define TEXT_SIZE 256 |
Definition at line 222 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 1504 of file chan_oss.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 1504 of file chan_oss.c.
static char* ast_ext_ctx | ( | const char * | src, | |
char ** | ext, | |||
char ** | ctx | |||
) | [static] |
Definition at line 393 of file chan_oss.c.
References ast_strdup, find_desc(), and chan_oss_pvt::overridecontext.
00394 { 00395 struct chan_oss_pvt *o = find_desc(oss_active); 00396 00397 if (ext == NULL || ctx == NULL) 00398 return NULL; /* error */ 00399 00400 *ext = *ctx = NULL; 00401 00402 if (src && *src != '\0') 00403 *ext = ast_strdup(src); 00404 00405 if (*ext == NULL) 00406 return NULL; 00407 00408 if (!o->overridecontext) { 00409 /* parse from the right */ 00410 *ctx = strrchr(*ext, '@'); 00411 if (*ctx) 00412 *(*ctx)++ = '\0'; 00413 } 00414 00415 return *ext; 00416 }
static char* console_active | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1208 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.
01209 { 01210 switch (cmd) { 01211 case CLI_INIT: 01212 e->command = "console {set|show} active [<device>]"; 01213 e->usage = 01214 "Usage: console active [device]\n" 01215 " If used without a parameter, displays which device is the current\n" 01216 " console. If a device is specified, the console sound device is changed to\n" 01217 " the device specified.\n"; 01218 return NULL; 01219 case CLI_GENERATE: 01220 return NULL; 01221 } 01222 01223 if (a->argc == 3) 01224 ast_cli(a->fd, "active console is [%s]\n", oss_active); 01225 else if (a->argc != 4) 01226 return CLI_SHOWUSAGE; 01227 else { 01228 struct chan_oss_pvt *o; 01229 if (strcmp(a->argv[3], "show") == 0) { 01230 for (o = oss_default.next; o; o = o->next) 01231 ast_cli(a->fd, "device [%s] exists\n", o->name); 01232 return CLI_SUCCESS; 01233 } 01234 o = find_desc(a->argv[3]); 01235 if (o == NULL) 01236 ast_cli(a->fd, "No device [%s] exists\n", a->argv[3]); 01237 else 01238 oss_active = o->name; 01239 } 01240 return CLI_SUCCESS; 01241 }
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 970 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.
00971 { 00972 switch (cmd) { 00973 case CLI_INIT: 00974 e->command = "console answer"; 00975 e->usage = 00976 "Usage: console answer\n" 00977 " Answers an incoming call on the console (OSS) channel.\n"; 00978 return NULL; 00979 00980 case CLI_GENERATE: 00981 return NULL; /* no completion */ 00982 } 00983 if (a->argc != e->args) 00984 return CLI_SHOWUSAGE; 00985 return console_do_answer(a->fd); 00986 }
static char* console_autoanswer | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 914 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.
00915 { 00916 struct chan_oss_pvt *o = find_desc(oss_active); 00917 00918 switch (cmd) { 00919 case CLI_INIT: 00920 e->command = "console {set|show} autoanswer [on|off]"; 00921 e->usage = 00922 "Usage: console {set|show} autoanswer [on|off]\n" 00923 " Enables or disables autoanswer feature. If used without\n" 00924 " argument, displays the current on/off status of autoanswer.\n" 00925 " The default value of autoanswer is in 'oss.conf'.\n"; 00926 return NULL; 00927 00928 case CLI_GENERATE: 00929 return NULL; 00930 } 00931 00932 if (a->argc == e->args - 1) { 00933 ast_cli(a->fd, "Auto answer is %s.\n", o->autoanswer ? "on" : "off"); 00934 return CLI_SUCCESS; 00935 } 00936 if (a->argc != e->args) 00937 return CLI_SHOWUSAGE; 00938 if (o == NULL) { 00939 ast_log(LOG_WARNING, "Cannot find device %s (should not happen!)\n", 00940 oss_active); 00941 return CLI_FAILURE; 00942 } 00943 if (!strcasecmp(a->argv[e->args-1], "on")) 00944 o->autoanswer = 1; 00945 else if (!strcasecmp(a->argv[e->args - 1], "off")) 00946 o->autoanswer = 0; 00947 else 00948 return CLI_SHOWUSAGE; 00949 return CLI_SUCCESS; 00950 }
static char* console_boost | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1265 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.
01266 { 01267 struct chan_oss_pvt *o = find_desc(oss_active); 01268 01269 switch (cmd) { 01270 case CLI_INIT: 01271 e->command = "console boost"; 01272 e->usage = 01273 "Usage: console boost [boost in dB]\n" 01274 " Sets or display mic boost in dB\n"; 01275 return NULL; 01276 case CLI_GENERATE: 01277 return NULL; 01278 } 01279 01280 if (a->argc == 2) 01281 ast_cli(a->fd, "boost currently %5.1f\n", 20 * log10(((double) o->boost / (double) BOOST_SCALE))); 01282 else if (a->argc == 3) 01283 store_boost(o, a->argv[2]); 01284 return CLI_SUCCESS; 01285 }
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 878 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.
00879 { 00880 struct chan_oss_pvt *o = find_desc(oss_active); 00881 const char *var, *value; 00882 switch (cmd) { 00883 case CLI_INIT: 00884 e->command = CONSOLE_VIDEO_CMDS; 00885 e->usage = 00886 "Usage: " CONSOLE_VIDEO_CMDS "...\n" 00887 " Generic handler for console commands.\n"; 00888 return NULL; 00889 00890 case CLI_GENERATE: 00891 return NULL; 00892 } 00893 00894 if (a->argc < e->args) 00895 return CLI_SHOWUSAGE; 00896 if (o == NULL) { 00897 ast_log(LOG_WARNING, "Cannot find device %s (should not happen!)\n", 00898 oss_active); 00899 return CLI_FAILURE; 00900 } 00901 var = a->argv[e->args-1]; 00902 value = a->argc > e->args ? a->argv[e->args] : NULL; 00903 if (value) /* handle setting */ 00904 store_config_core(o, var, value); 00905 if (!console_video_cli(o->env, var, a->fd)) /* print video-related values */ 00906 return CLI_SUCCESS; 00907 /* handle other values */ 00908 if (!strcasecmp(var, "device")) { 00909 ast_cli(a->fd, "device is [%s]\n", o->device); 00910 } 00911 return CLI_SUCCESS; 00912 }
static char* console_dial | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1080 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.
01081 { 01082 char *s = NULL; 01083 char *mye = NULL, *myc = NULL; 01084 struct chan_oss_pvt *o = find_desc(oss_active); 01085 01086 if (cmd == CLI_INIT) { 01087 e->command = "console dial"; 01088 e->usage = 01089 "Usage: console dial [extension[@context]]\n" 01090 " Dials a given extension (and context if specified)\n"; 01091 return NULL; 01092 } else if (cmd == CLI_GENERATE) 01093 return NULL; 01094 01095 if (a->argc > e->args + 1) 01096 return CLI_SHOWUSAGE; 01097 if (o->owner) { /* already in a call */ 01098 int i; 01099 struct ast_frame f = { AST_FRAME_DTMF, { 0 } }; 01100 const char *s; 01101 01102 if (a->argc == e->args) { /* argument is mandatory here */ 01103 ast_cli(a->fd, "Already in a call. You can only dial digits until you hangup.\n"); 01104 return CLI_FAILURE; 01105 } 01106 s = a->argv[e->args]; 01107 /* send the string one char at a time */ 01108 for (i = 0; i < strlen(s); i++) { 01109 f.subclass.integer = s[i]; 01110 ast_queue_frame(o->owner, &f); 01111 } 01112 return CLI_SUCCESS; 01113 } 01114 /* if we have an argument split it into extension and context */ 01115 if (a->argc == e->args + 1) 01116 s = ast_ext_ctx(a->argv[e->args], &mye, &myc); 01117 /* supply default values if needed */ 01118 if (mye == NULL) 01119 mye = o->ext; 01120 if (myc == NULL) 01121 myc = o->ctx; 01122 if (ast_exists_extension(NULL, myc, mye, 1, NULL)) { 01123 o->hookstate = 1; 01124 oss_new(o, mye, myc, AST_STATE_RINGING, NULL); 01125 } else 01126 ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc); 01127 if (s) 01128 ast_free(s); 01129 return CLI_SUCCESS; 01130 }
static char* console_do_answer | ( | int | fd | ) | [static] |
helper function for the answer key/cli command
Definition at line 953 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().
00954 { 00955 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_ANSWER } }; 00956 struct chan_oss_pvt *o = find_desc(oss_active); 00957 if (!o->owner) { 00958 if (fd > -1) 00959 ast_cli(fd, "No one is calling us\n"); 00960 return CLI_FAILURE; 00961 } 00962 o->hookstate = 1; 00963 ast_queue_frame(o->owner, &f); 00964 return CLI_SUCCESS; 00965 }
static char* console_flash | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1054 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.
01055 { 01056 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_FLASH } }; 01057 struct chan_oss_pvt *o = find_desc(oss_active); 01058 01059 if (cmd == CLI_INIT) { 01060 e->command = "console flash"; 01061 e->usage = 01062 "Usage: console flash\n" 01063 " Flashes the call currently placed on the console.\n"; 01064 return NULL; 01065 } else if (cmd == CLI_GENERATE) 01066 return NULL; 01067 01068 if (a->argc != e->args) 01069 return CLI_SHOWUSAGE; 01070 if (!o->owner) { /* XXX maybe !o->hookstate too ? */ 01071 ast_cli(a->fd, "No call to flash\n"); 01072 return CLI_FAILURE; 01073 } 01074 o->hookstate = 0; 01075 if (o->owner) 01076 ast_queue_frame(o->owner, &f); 01077 return CLI_SUCCESS; 01078 }
static char* console_hangup | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1028 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.
01029 { 01030 struct chan_oss_pvt *o = find_desc(oss_active); 01031 01032 if (cmd == CLI_INIT) { 01033 e->command = "console hangup"; 01034 e->usage = 01035 "Usage: console hangup\n" 01036 " Hangs up any call currently placed on the console.\n"; 01037 return NULL; 01038 } else if (cmd == CLI_GENERATE) 01039 return NULL; 01040 01041 if (a->argc != e->args) 01042 return CLI_SHOWUSAGE; 01043 if (!o->owner && !o->hookstate) { /* XXX maybe only one ? */ 01044 ast_cli(a->fd, "No call to hang up\n"); 01045 return CLI_FAILURE; 01046 } 01047 o->hookstate = 0; 01048 if (o->owner) 01049 ast_queue_hangup_with_cause(o->owner, AST_CAUSE_NORMAL_CLEARING); 01050 setformat(o, O_CLOSE); 01051 return CLI_SUCCESS; 01052 }
static char* console_mute | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1132 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.
01133 { 01134 struct chan_oss_pvt *o = find_desc(oss_active); 01135 const char *s; 01136 int toggle = 0; 01137 01138 if (cmd == CLI_INIT) { 01139 e->command = "console {mute|unmute} [toggle]"; 01140 e->usage = 01141 "Usage: console {mute|unmute} [toggle]\n" 01142 " Mute/unmute the microphone.\n"; 01143 return NULL; 01144 } else if (cmd == CLI_GENERATE) 01145 return NULL; 01146 01147 if (a->argc > e->args) 01148 return CLI_SHOWUSAGE; 01149 if (a->argc == e->args) { 01150 if (strcasecmp(a->argv[e->args-1], "toggle")) 01151 return CLI_SHOWUSAGE; 01152 toggle = 1; 01153 } 01154 s = a->argv[e->args-2]; 01155 if (!strcasecmp(s, "mute")) 01156 o->mute = toggle ? !o->mute : 1; 01157 else if (!strcasecmp(s, "unmute")) 01158 o->mute = toggle ? !o->mute : 0; 01159 else 01160 return CLI_SHOWUSAGE; 01161 ast_cli(a->fd, "Console mic is %s\n", o->mute ? "off" : "on"); 01162 return CLI_SUCCESS; 01163 }
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 994 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.
00995 { 00996 struct chan_oss_pvt *o = find_desc(oss_active); 00997 char buf[TEXT_SIZE]; 00998 00999 if (cmd == CLI_INIT) { 01000 e->command = "console send text"; 01001 e->usage = 01002 "Usage: console send text <message>\n" 01003 " Sends a text message for display on the remote terminal.\n"; 01004 return NULL; 01005 } else if (cmd == CLI_GENERATE) 01006 return NULL; 01007 01008 if (a->argc < e->args + 1) 01009 return CLI_SHOWUSAGE; 01010 if (!o->owner) { 01011 ast_cli(a->fd, "Not in a call\n"); 01012 return CLI_FAILURE; 01013 } 01014 ast_join(buf, sizeof(buf) - 1, a->argv + e->args); 01015 if (!ast_strlen_zero(buf)) { 01016 struct ast_frame f = { 0, }; 01017 int i = strlen(buf); 01018 buf[i] = '\n'; 01019 f.frametype = AST_FRAME_TEXT; 01020 f.subclass.integer = 0; 01021 f.data.ptr = buf; 01022 f.datalen = i + 1; 01023 ast_queue_frame(o->owner, &f); 01024 } 01025 return CLI_SUCCESS; 01026 }
static char* console_transfer | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1165 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.
01166 { 01167 struct chan_oss_pvt *o = find_desc(oss_active); 01168 struct ast_channel *b = NULL; 01169 char *tmp, *ext, *ctx; 01170 01171 switch (cmd) { 01172 case CLI_INIT: 01173 e->command = "console transfer"; 01174 e->usage = 01175 "Usage: console transfer <extension>[@context]\n" 01176 " Transfers the currently connected call to the given extension (and\n" 01177 " context if specified)\n"; 01178 return NULL; 01179 case CLI_GENERATE: 01180 return NULL; 01181 } 01182 01183 if (a->argc != 3) 01184 return CLI_SHOWUSAGE; 01185 if (o == NULL) 01186 return CLI_FAILURE; 01187 if (o->owner == NULL || (b = ast_bridged_channel(o->owner)) == NULL) { 01188 ast_cli(a->fd, "There is no call to transfer\n"); 01189 return CLI_SUCCESS; 01190 } 01191 01192 tmp = ast_ext_ctx(a->argv[2], &ext, &ctx); 01193 if (ctx == NULL) /* supply default context if needed */ 01194 ctx = o->owner->context; 01195 if (!ast_exists_extension(b, ctx, ext, 1, 01196 S_COR(b->caller.id.number.valid, b->caller.id.number.str, NULL))) { 01197 ast_cli(a->fd, "No such extension exists\n"); 01198 } else { 01199 ast_cli(a->fd, "Whee, transferring %s to %s@%s.\n", b->name, ext, ctx); 01200 if (ast_async_goto(b, ctx, ext, 1)) 01201 ast_cli(a->fd, "Failed to transfer :(\n"); 01202 } 01203 if (tmp) 01204 ast_free(tmp); 01205 return CLI_SUCCESS; 01206 }
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 367 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().
00368 { 00369 struct chan_oss_pvt *o = NULL; 00370 00371 if (!dev) 00372 ast_log(LOG_WARNING, "null dev\n"); 00373 00374 for (o = oss_default.next; o && o->name && dev && strcmp(o->name, dev) != 0; o = o->next); 00375 00376 if (!o) 00377 ast_log(LOG_WARNING, "could not find <%s>\n", dev ? dev : "--no-device--"); 00378 00379 return o; 00380 }
struct video_desc* get_video_desc | ( | struct ast_channel * | c | ) |
return the pointer to the video descriptor
Definition at line 309 of file chan_oss.c.
References chan_oss_pvt::env, find_desc(), and ast_channel::tech_pvt.
Referenced by oss_new().
00310 { 00311 struct chan_oss_pvt *o = c ? c->tech_pvt : find_desc(oss_active); 00312 return o ? o->env : NULL; 00313 }
static int load_module | ( | void | ) | [static] |
Definition at line 1438 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().
01439 { 01440 struct ast_config *cfg = NULL; 01441 char *ctg = NULL; 01442 struct ast_flags config_flags = { 0 }; 01443 01444 /* Copy the default jb config over global_jbconf */ 01445 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 01446 01447 /* load config file */ 01448 if (!(cfg = ast_config_load(config, config_flags))) { 01449 ast_log(LOG_NOTICE, "Unable to load config %s\n", config); 01450 return AST_MODULE_LOAD_DECLINE; 01451 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 01452 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config); 01453 return AST_MODULE_LOAD_DECLINE; 01454 } 01455 01456 do { 01457 store_config(cfg, ctg); 01458 } while ( (ctg = ast_category_browse(cfg, ctg)) != NULL); 01459 01460 ast_config_destroy(cfg); 01461 01462 if (find_desc(oss_active) == NULL) { 01463 ast_log(LOG_NOTICE, "Device %s not found\n", oss_active); 01464 /* XXX we could default to 'dsp' perhaps ? */ 01465 /* XXX should cleanup allocated memory etc. */ 01466 return AST_MODULE_LOAD_FAILURE; 01467 } 01468 01469 oss_tech.capabilities |= console_video_formats; 01470 01471 if (ast_channel_register(&oss_tech)) { 01472 ast_log(LOG_ERROR, "Unable to register channel type 'OSS'\n"); 01473 return AST_MODULE_LOAD_DECLINE; 01474 } 01475 01476 ast_cli_register_multiple(cli_oss, ARRAY_LEN(cli_oss)); 01477 01478 return AST_MODULE_LOAD_SUCCESS; 01479 }
static int oss_answer | ( | struct ast_channel * | c | ) | [static] |
remote side answered the phone
Definition at line 636 of file chan_oss.c.
References ast_setstate(), AST_STATE_UP, ast_verbose, chan_oss_pvt::hookstate, and ast_channel::tech_pvt.
00637 { 00638 struct chan_oss_pvt *o = c->tech_pvt; 00639 ast_verbose(" << Console call has been answered >> \n"); 00640 ast_setstate(c, AST_STATE_UP); 00641 o->hookstate = 1; 00642 return 0; 00643 }
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 594 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.
00595 { 00596 struct chan_oss_pvt *o = c->tech_pvt; 00597 struct ast_frame f = { AST_FRAME_CONTROL, }; 00598 AST_DECLARE_APP_ARGS(args, 00599 AST_APP_ARG(name); 00600 AST_APP_ARG(flags); 00601 ); 00602 char *parse = ast_strdupa(dest); 00603 00604 AST_NONSTANDARD_APP_ARGS(args, parse, '/'); 00605 00606 ast_verbose(" << Call to device '%s' dnid '%s' rdnis '%s' on console from '%s' <%s> >>\n", 00607 dest, 00608 S_OR(c->dialed.number.str, ""), 00609 S_COR(c->redirecting.from.number.valid, c->redirecting.from.number.str, ""), 00610 S_COR(c->caller.id.name.valid, c->caller.id.name.str, ""), 00611 S_COR(c->caller.id.number.valid, c->caller.id.number.str, "")); 00612 if (!ast_strlen_zero(args.flags) && strcasecmp(args.flags, "answer") == 0) { 00613 f.subclass.integer = AST_CONTROL_ANSWER; 00614 ast_queue_frame(c, &f); 00615 } else if (!ast_strlen_zero(args.flags) && strcasecmp(args.flags, "noanswer") == 0) { 00616 f.subclass.integer = 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.subclass.integer = AST_CONTROL_ANSWER; 00622 ast_queue_frame(c, &f); 00623 o->hookstate = 1; 00624 } else { 00625 ast_verbose("<< Type 'answer' to answer, or use 'autoanswer' for future calls >> \n"); 00626 f.subclass.integer = AST_CONTROL_RINGING; 00627 ast_queue_frame(c, &f); 00628 ast_indicate(c, AST_CONTROL_RINGING); 00629 } 00630 return 0; 00631 }
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 576 of file chan_oss.c.
References ast_verbose.
00577 { 00578 /* no better use for received digits than print them */ 00579 ast_verbose(" << Console Received digit %c of duration %u ms >> \n", 00580 digit, duration); 00581 return 0; 00582 }
static int oss_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 745 of file chan_oss.c.
References chan_oss_pvt::owner, and ast_channel::tech_pvt.
00746 { 00747 struct chan_oss_pvt *o = newchan->tech_pvt; 00748 o->owner = newchan; 00749 return 0; 00750 }
static int oss_hangup | ( | struct ast_channel * | c | ) | [static] |
Definition at line 645 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.
00646 { 00647 struct chan_oss_pvt *o = c->tech_pvt; 00648 00649 c->tech_pvt = NULL; 00650 o->owner = NULL; 00651 ast_verbose(" << Hangup on console >> \n"); 00652 console_video_uninit(o->env); 00653 ast_module_unref(ast_module_info->self); 00654 if (o->hookstate) { 00655 if (o->autoanswer || o->autohangup) { 00656 /* Assume auto-hangup too */ 00657 o->hookstate = 0; 00658 setformat(o, O_CLOSE); 00659 } 00660 } 00661 return 0; 00662 }
static int oss_indicate | ( | struct ast_channel * | chan, | |
int | cond, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 752 of file chan_oss.c.
References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, 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.
00753 { 00754 struct chan_oss_pvt *o = c->tech_pvt; 00755 int res = 0; 00756 00757 switch (cond) { 00758 case AST_CONTROL_INCOMPLETE: 00759 case AST_CONTROL_BUSY: 00760 case AST_CONTROL_CONGESTION: 00761 case AST_CONTROL_RINGING: 00762 case -1: 00763 res = -1; 00764 break; 00765 case AST_CONTROL_PROGRESS: 00766 case AST_CONTROL_PROCEEDING: 00767 case AST_CONTROL_VIDUPDATE: 00768 case AST_CONTROL_SRCUPDATE: 00769 break; 00770 case AST_CONTROL_HOLD: 00771 ast_verbose(" << Console Has Been Placed on Hold >> \n"); 00772 ast_moh_start(c, data, o->mohinterpret); 00773 break; 00774 case AST_CONTROL_UNHOLD: 00775 ast_verbose(" << Console Has Been Retrieved from Hold >> \n"); 00776 ast_moh_stop(c); 00777 break; 00778 default: 00779 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name); 00780 return -1; 00781 } 00782 00783 return res; 00784 }
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 789 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().
00790 { 00791 struct ast_channel *c; 00792 00793 c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, linkedid, 0, "Console/%s", o->device + 5); 00794 if (c == NULL) 00795 return NULL; 00796 c->tech = &oss_tech; 00797 if (o->sounddev < 0) 00798 setformat(o, O_RDWR); 00799 ast_channel_set_fd(c, 0, o->sounddev); /* -1 if device closed, override later */ 00800 c->nativeformats = AST_FORMAT_SLINEAR; 00801 /* if the console makes the call, add video to the offer */ 00802 if (state == AST_STATE_RINGING) 00803 c->nativeformats |= console_video_formats; 00804 00805 c->readformat = AST_FORMAT_SLINEAR; 00806 c->writeformat = AST_FORMAT_SLINEAR; 00807 c->tech_pvt = o; 00808 00809 if (!ast_strlen_zero(o->language)) 00810 ast_string_field_set(c, language, o->language); 00811 /* Don't use ast_set_callerid() here because it will 00812 * generate a needless NewCallerID event */ 00813 if (!ast_strlen_zero(o->cid_num)) { 00814 c->caller.ani.number.valid = 1; 00815 c->caller.ani.number.str = ast_strdup(o->cid_num); 00816 } 00817 if (!ast_strlen_zero(ext)) { 00818 c->dialed.number.str = ast_strdup(ext); 00819 } 00820 00821 o->owner = c; 00822 ast_module_ref(ast_module_info->self); 00823 ast_jb_configure(c, &global_jbconf); 00824 if (state != AST_STATE_DOWN) { 00825 if (ast_pbx_start(c)) { 00826 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", c->name); 00827 ast_hangup(c); 00828 o->owner = c = NULL; 00829 } 00830 } 00831 console_video_start(get_video_desc(c), c); /* XXX cleanup */ 00832 00833 return c; 00834 }
static struct ast_frame * oss_read | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 696 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.
00697 { 00698 int res; 00699 struct chan_oss_pvt *o = c->tech_pvt; 00700 struct ast_frame *f = &o->read_f; 00701 00702 /* XXX can be simplified returning &ast_null_frame */ 00703 /* prepare a NULL frame in case we don't have enough data to return */ 00704 memset(f, '\0', sizeof(struct ast_frame)); 00705 f->frametype = AST_FRAME_NULL; 00706 f->src = oss_tech.type; 00707 00708 res = read(o->sounddev, o->oss_read_buf + o->readpos, sizeof(o->oss_read_buf) - o->readpos); 00709 if (res < 0) /* audio data not ready, return a NULL frame */ 00710 return f; 00711 00712 o->readpos += res; 00713 if (o->readpos < sizeof(o->oss_read_buf)) /* not enough samples */ 00714 return f; 00715 00716 if (o->mute) 00717 return f; 00718 00719 o->readpos = AST_FRIENDLY_OFFSET; /* reset read pointer for next frame */ 00720 if (c->_state != AST_STATE_UP) /* drop data if frame is not up */ 00721 return f; 00722 /* ok we can build and deliver the frame to the caller */ 00723 f->frametype = AST_FRAME_VOICE; 00724 f->subclass.codec = AST_FORMAT_SLINEAR; 00725 f->samples = FRAME_SIZE; 00726 f->datalen = FRAME_SIZE * 2; 00727 f->data.ptr = o->oss_read_buf + AST_FRIENDLY_OFFSET; 00728 if (o->boost != BOOST_SCALE) { /* scale and clip values */ 00729 int i, x; 00730 int16_t *p = (int16_t *) f->data.ptr; 00731 for (i = 0; i < f->samples; i++) { 00732 x = (p[i] * o->boost) / BOOST_SCALE; 00733 if (x > 32767) 00734 x = 32767; 00735 else if (x < -32768) 00736 x = -32768; 00737 p[i] = x; 00738 } 00739 } 00740 00741 f->offset = AST_FRIENDLY_OFFSET; 00742 return f; 00743 }
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 836 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().
00837 { 00838 struct ast_channel *c; 00839 struct chan_oss_pvt *o; 00840 AST_DECLARE_APP_ARGS(args, 00841 AST_APP_ARG(name); 00842 AST_APP_ARG(flags); 00843 ); 00844 char *parse = ast_strdupa(data); 00845 char buf[256]; 00846 00847 AST_NONSTANDARD_APP_ARGS(args, parse, '/'); 00848 o = find_desc(args.name); 00849 00850 ast_log(LOG_WARNING, "oss_request ty <%s> data 0x%p <%s>\n", type, data, (char *) data); 00851 if (o == NULL) { 00852 ast_log(LOG_NOTICE, "Device %s not found\n", args.name); 00853 /* XXX we could default to 'dsp' perhaps ? */ 00854 return NULL; 00855 } 00856 if ((format & AST_FORMAT_SLINEAR) == 0) { 00857 ast_log(LOG_NOTICE, "Format %s unsupported\n", ast_getformatname_multiple(buf, sizeof(buf), format)); 00858 return NULL; 00859 } 00860 if (o->owner) { 00861 ast_log(LOG_NOTICE, "Already have a call (chan %p) on the OSS channel\n", o->owner); 00862 *cause = AST_CAUSE_BUSY; 00863 return NULL; 00864 } 00865 c = oss_new(o, NULL, NULL, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL); 00866 if (c == NULL) { 00867 ast_log(LOG_WARNING, "Unable to create new OSS channel\n"); 00868 return NULL; 00869 } 00870 return c; 00871 }
static int oss_text | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 584 of file chan_oss.c.
References ast_verbose.
00585 { 00586 /* print received messages */ 00587 ast_verbose(" << Console Received text %s >> \n", text); 00588 return 0; 00589 }
static int oss_write | ( | struct ast_channel * | chan, | |
struct ast_frame * | f | |||
) | [static] |
used for data coming from the network
Definition at line 665 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.
00666 { 00667 int src; 00668 struct chan_oss_pvt *o = c->tech_pvt; 00669 00670 /* 00671 * we could receive a block which is not a multiple of our 00672 * FRAME_SIZE, so buffer it locally and write to the device 00673 * in FRAME_SIZE chunks. 00674 * Keep the residue stored for future use. 00675 */ 00676 src = 0; /* read position into f->data */ 00677 while (src < f->datalen) { 00678 /* Compute spare room in the buffer */ 00679 int l = sizeof(o->oss_write_buf) - o->oss_write_dst; 00680 00681 if (f->datalen - src >= l) { /* enough to fill a frame */ 00682 memcpy(o->oss_write_buf + o->oss_write_dst, f->data.ptr + src, l); 00683 soundcard_writeframe(o, (short *) o->oss_write_buf); 00684 src += l; 00685 o->oss_write_dst = 0; 00686 } else { /* copy residue */ 00687 l = f->datalen - src; 00688 memcpy(o->oss_write_buf + o->oss_write_dst, f->data.ptr + src, l); 00689 src += l; /* but really, we are done */ 00690 o->oss_write_dst += l; 00691 } 00692 } 00693 return 0; 00694 }
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 472 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().
00473 { 00474 int fmt, desired, res, fd; 00475 00476 if (o->sounddev >= 0) { 00477 ioctl(o->sounddev, SNDCTL_DSP_RESET, 0); 00478 close(o->sounddev); 00479 o->duplex = M_UNSET; 00480 o->sounddev = -1; 00481 } 00482 if (mode == O_CLOSE) /* we are done */ 00483 return 0; 00484 if (ast_tvdiff_ms(ast_tvnow(), o->lastopen) < 1000) 00485 return -1; /* don't open too often */ 00486 o->lastopen = ast_tvnow(); 00487 fd = o->sounddev = open(o->device, mode | O_NONBLOCK); 00488 if (fd < 0) { 00489 ast_log(LOG_WARNING, "Unable to re-open DSP device %s: %s\n", o->device, strerror(errno)); 00490 return -1; 00491 } 00492 if (o->owner) 00493 ast_channel_set_fd(o->owner, 0, fd); 00494 00495 #if __BYTE_ORDER == __LITTLE_ENDIAN 00496 fmt = AFMT_S16_LE; 00497 #else 00498 fmt = AFMT_S16_BE; 00499 #endif 00500 res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt); 00501 if (res < 0) { 00502 ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n"); 00503 return -1; 00504 } 00505 switch (mode) { 00506 case O_RDWR: 00507 res = ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0); 00508 /* Check to see if duplex set (FreeBSD Bug) */ 00509 res = ioctl(fd, SNDCTL_DSP_GETCAPS, &fmt); 00510 if (res == 0 && (fmt & DSP_CAP_DUPLEX)) { 00511 ast_verb(2, "Console is full duplex\n"); 00512 o->duplex = M_FULL; 00513 }; 00514 break; 00515 00516 case O_WRONLY: 00517 o->duplex = M_WRITE; 00518 break; 00519 00520 case O_RDONLY: 00521 o->duplex = M_READ; 00522 break; 00523 } 00524 00525 fmt = 0; 00526 res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt); 00527 if (res < 0) { 00528 ast_log(LOG_WARNING, "Failed to set audio device to mono\n"); 00529 return -1; 00530 } 00531 fmt = desired = DEFAULT_SAMPLE_RATE; /* 8000 Hz desired */ 00532 res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt); 00533 00534 if (res < 0) { 00535 ast_log(LOG_WARNING, "Failed to set audio device to mono\n"); 00536 return -1; 00537 } 00538 if (fmt != desired) { 00539 if (!(o->warned & WARN_speed)) { 00540 ast_log(LOG_WARNING, 00541 "Requested %d Hz, got %d Hz -- sound may be choppy\n", 00542 desired, fmt); 00543 o->warned |= WARN_speed; 00544 } 00545 } 00546 /* 00547 * on Freebsd, SETFRAGMENT does not work very well on some cards. 00548 * Default to use 256 bytes, let the user override 00549 */ 00550 if (o->frags) { 00551 fmt = o->frags; 00552 res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt); 00553 if (res < 0) { 00554 if (!(o->warned & WARN_frag)) { 00555 ast_log(LOG_WARNING, 00556 "Unable to set fragment size -- sound may be choppy\n"); 00557 o->warned |= WARN_frag; 00558 } 00559 } 00560 } 00561 /* on some cards, we need SNDCTL_DSP_SETTRIGGER to start outputting */ 00562 res = PCM_ENABLE_INPUT | PCM_ENABLE_OUTPUT; 00563 res = ioctl(fd, SNDCTL_DSP_SETTRIGGER, &res); 00564 /* it may fail if we are in half duplex, never mind */ 00565 return 0; 00566 }
static int soundcard_writeframe | ( | struct chan_oss_pvt * | o, | |
short * | data | |||
) | [static] |
Write an exactly FRAME_SIZE sized frame
Definition at line 443 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().
00444 { 00445 int res; 00446 00447 if (o->sounddev < 0) 00448 setformat(o, O_RDWR); 00449 if (o->sounddev < 0) 00450 return 0; /* not fatal */ 00451 /* 00452 * Nothing complex to manage the audio device queue. 00453 * If the buffer is full just drop the extra, otherwise write. 00454 * XXX in some cases it might be useful to write anyways after 00455 * a number of failures, to restart the output chain. 00456 */ 00457 res = used_blocks(o); 00458 if (res > o->queuesize) { /* no room to write a block */ 00459 if (o->w_errors++ == 0 && (oss_debug & 0x4)) 00460 ast_log(LOG_WARNING, "write: used %d blocks (%d)\n", res, o->w_errors); 00461 return 0; 00462 } 00463 o->w_errors = 0; 00464 return write(o->sounddev, (void *)data, FRAME_SIZE * 2); 00465 }
static void store_boost | ( | struct chan_oss_pvt * | o, | |
const char * | s | |||
) | [static] |
store the boost factor
Definition at line 1246 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().
01247 { 01248 double boost = 0; 01249 if (sscanf(s, "%30lf", &boost) != 1) { 01250 ast_log(LOG_WARNING, "invalid boost <%s>\n", s); 01251 return; 01252 } 01253 if (boost < -BOOST_MAX) { 01254 ast_log(LOG_WARNING, "boost %s too small, using %d\n", s, -BOOST_MAX); 01255 boost = -BOOST_MAX; 01256 } else if (boost > BOOST_MAX) { 01257 ast_log(LOG_WARNING, "boost %s too large, using %d\n", s, BOOST_MAX); 01258 boost = BOOST_MAX; 01259 } 01260 boost = exp(log(10) * boost / 20) * BOOST_SCALE; 01261 o->boost = boost; 01262 ast_log(LOG_WARNING, "setting boost %s to %d\n", s, o->boost); 01263 }
static void store_callerid | ( | struct chan_oss_pvt * | o, | |
const char * | s | |||
) | [static] |
store the callerid components
Definition at line 1325 of file chan_oss.c.
References ast_callerid_split(), chan_oss_pvt::cid_name, and chan_oss_pvt::cid_num.
01326 { 01327 ast_callerid_split(s, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num)); 01328 }
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 1361 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().
01362 { 01363 struct ast_variable *v; 01364 struct chan_oss_pvt *o; 01365 01366 if (ctg == NULL) { 01367 o = &oss_default; 01368 ctg = "general"; 01369 } else { 01370 if (!(o = ast_calloc(1, sizeof(*o)))) 01371 return NULL; 01372 *o = oss_default; 01373 /* "general" is also the default thing */ 01374 if (strcmp(ctg, "general") == 0) { 01375 o->name = ast_strdup("dsp"); 01376 oss_active = o->name; 01377 goto openit; 01378 } 01379 o->name = ast_strdup(ctg); 01380 } 01381 01382 strcpy(o->mohinterpret, "default"); 01383 01384 o->lastopen = ast_tvnow(); /* don't leave it 0 or tvdiff may wrap */ 01385 /* fill other fields from configuration */ 01386 for (v = ast_variable_browse(cfg, ctg); v; v = v->next) { 01387 store_config_core(o, v->name, v->value); 01388 } 01389 if (ast_strlen_zero(o->device)) 01390 ast_copy_string(o->device, DEV_DSP, sizeof(o->device)); 01391 if (o->mixer_cmd) { 01392 char *cmd; 01393 01394 if (asprintf(&cmd, "mixer %s", o->mixer_cmd) < 0) { 01395 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 01396 } else { 01397 ast_log(LOG_WARNING, "running [%s]\n", cmd); 01398 if (system(cmd) < 0) { 01399 ast_log(LOG_WARNING, "system() failed: %s\n", strerror(errno)); 01400 } 01401 ast_free(cmd); 01402 } 01403 } 01404 01405 /* if the config file requested to start the GUI, do it */ 01406 if (get_gui_startup(o->env)) 01407 console_video_start(o->env, NULL); 01408 01409 if (o == &oss_default) /* we are done with the default */ 01410 return NULL; 01411 01412 openit: 01413 #ifdef TRYOPEN 01414 if (setformat(o, O_RDWR) < 0) { /* open device */ 01415 ast_verb(1, "Device %s not detected\n", ctg); 01416 ast_verb(1, "Turn off OSS support by adding " "'noload=chan_oss.so' in /etc/asterisk/modules.conf\n"); 01417 goto error; 01418 } 01419 if (o->duplex != M_FULL) 01420 ast_log(LOG_WARNING, "XXX I don't work right with non " "full-duplex sound cards XXX\n"); 01421 #endif /* TRYOPEN */ 01422 01423 /* link into list of devices */ 01424 if (o != &oss_default) { 01425 o->next = oss_default.next; 01426 oss_default.next = o; 01427 } 01428 return o; 01429 01430 #ifdef TRYOPEN 01431 error: 01432 if (o != &oss_default) 01433 ast_free(o); 01434 return NULL; 01435 #endif 01436 }
static void store_config_core | ( | struct chan_oss_pvt * | o, | |
const char * | var, | |||
const char * | value | |||
) | [static] |
Definition at line 1330 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().
01331 { 01332 CV_START(var, value); 01333 01334 /* handle jb conf */ 01335 if (!ast_jb_read_conf(&global_jbconf, var, value)) 01336 return; 01337 01338 if (!console_video_config(&o->env, var, value)) 01339 return; /* matched there */ 01340 CV_BOOL("autoanswer", o->autoanswer); 01341 CV_BOOL("autohangup", o->autohangup); 01342 CV_BOOL("overridecontext", o->overridecontext); 01343 CV_STR("device", o->device); 01344 CV_UINT("frags", o->frags); 01345 CV_UINT("debug", oss_debug); 01346 CV_UINT("queuesize", o->queuesize); 01347 CV_STR("context", o->ctx); 01348 CV_STR("language", o->language); 01349 CV_STR("mohinterpret", o->mohinterpret); 01350 CV_STR("extension", o->ext); 01351 CV_F("mixer", store_mixer(o, value)); 01352 CV_F("callerid", store_callerid(o, value)) ; 01353 CV_F("boost", store_boost(o, value)); 01354 01355 CV_END; 01356 }
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 1306 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().
01307 { 01308 int i; 01309 01310 for (i = 0; i < strlen(s); i++) { 01311 if (!isalnum(s[i]) && strchr(" \t-/", s[i]) == NULL) { 01312 ast_log(LOG_WARNING, "Suspect char %c in mixer cmd, ignoring:\n\t%s\n", s[i], s); 01313 return; 01314 } 01315 } 01316 if (o->mixer_cmd) 01317 ast_free(o->mixer_cmd); 01318 o->mixer_cmd = ast_strdup(s); 01319 ast_log(LOG_WARNING, "setting mixer %s\n", s); 01320 }
static int unload_module | ( | void | ) | [static] |
Definition at line 1482 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.
01483 { 01484 struct chan_oss_pvt *o, *next; 01485 01486 ast_channel_unregister(&oss_tech); 01487 ast_cli_unregister_multiple(cli_oss, ARRAY_LEN(cli_oss)); 01488 01489 o = oss_default.next; 01490 while (o) { 01491 close(o->sounddev); 01492 if (o->owner) 01493 ast_softhangup(o->owner, AST_SOFTHANGUP_APPUNLOAD); 01494 if (o->owner) 01495 return -1; 01496 next = o->next; 01497 ast_free(o->name); 01498 ast_free(o); 01499 o = next; 01500 } 01501 return 0; 01502 }
static int used_blocks | ( | struct chan_oss_pvt * | o | ) | [static] |
Returns the number of blocks used in the audio output channel.
Definition at line 421 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().
00422 { 00423 struct audio_buf_info info; 00424 00425 if (ioctl(o->sounddev, SNDCTL_DSP_GETOSPACE, &info)) { 00426 if (!(o->warned & WARN_used_blocks)) { 00427 ast_log(LOG_WARNING, "Error reading output space\n"); 00428 o->warned |= WARN_used_blocks; 00429 } 00430 return 1; 00431 } 00432 00433 if (o->total_blocks == 0) { 00434 if (0) /* debugging */ 00435 ast_log(LOG_WARNING, "fragtotal %d size %d avail %d\n", info.fragstotal, info.fragsize, info.fragments); 00436 o->total_blocks = info.fragments; 00437 } 00438 00439 return o->total_blocks - info.fragments; 00440 }
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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static] |
Definition at line 1504 of file chan_oss.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1504 of file chan_oss.c.
struct ast_cli_entry cli_oss[] [static] |
char* config = "oss.conf" [static] |
Definition at line 235 of file chan_oss.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 71 of file chan_oss.c.
struct ast_jb_conf global_jbconf [static] |
Definition at line 79 of file chan_oss.c.
char* oss_active [static] |
int oss_debug [static] |
Definition at line 237 of file chan_oss.c.
struct chan_oss_pvt oss_default [static] |
Definition at line 314 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 346 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 343 of file chan_oss.c.