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