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