#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 | |
| struct video_desc * | get_video_desc (struct ast_channel *c) |
| return the pointer to the video descriptor | |
| static int | load_module (void) |
| Load the module. | |
| static int | oss_answer (struct ast_channel *c) |
| remote side answered the phone | |
| static int | oss_call (struct ast_channel *c, const 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, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *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 = AST_BUILDOPT_SUM, .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" |
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 280 of file chan_oss.c.
Referenced by console_boost(), oss_read(), and store_boost().
| #define DEV_DSP "/dev/dsp" |
| #define FRAGS ( ( (6 * 5) << 16 ) | 0x6 ) |
Definition at line 221 of file chan_oss.c.
| #define FRAME_SIZE 160 |
Definition at line 215 of file chan_oss.c.
| #define O_CLOSE 0x444 |
Definition at line 233 of file chan_oss.c.
Referenced by console_hangup(), oss_hangup(), and setformat().
| #define QUEUE_SIZE 10 |
Definition at line 216 of file chan_oss.c.
| #define TEXT_SIZE 256 |
Definition at line 228 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 1529 of file chan_oss.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 1529 of file chan_oss.c.
| static char* ast_ext_ctx | ( | const char * | src, | |
| char ** | ext, | |||
| char ** | ctx | |||
| ) | [static] |
Definition at line 398 of file chan_oss.c.
References ast_strdup, find_desc(), and chan_oss_pvt::overridecontext.
00399 { 00400 struct chan_oss_pvt *o = find_desc(oss_active); 00401 00402 if (ext == NULL || ctx == NULL) 00403 return NULL; /* error */ 00404 00405 *ext = *ctx = NULL; 00406 00407 if (src && *src != '\0') 00408 *ext = ast_strdup(src); 00409 00410 if (*ext == NULL) 00411 return NULL; 00412 00413 if (!o->overridecontext) { 00414 /* parse from the right */ 00415 *ctx = strrchr(*ext, '@'); 00416 if (*ctx) 00417 *(*ctx)++ = '\0'; 00418 } 00419 00420 return *ext; 00421 }
| static char* console_active | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1217 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, and ast_cli_entry::usage.
01218 { 01219 switch (cmd) { 01220 case CLI_INIT: 01221 e->command = "console {set|show} active [<device>]"; 01222 e->usage = 01223 "Usage: console active [device]\n" 01224 " If used without a parameter, displays which device is the current\n" 01225 " console. If a device is specified, the console sound device is changed to\n" 01226 " the device specified.\n"; 01227 return NULL; 01228 case CLI_GENERATE: 01229 return NULL; 01230 } 01231 01232 if (a->argc == 3) 01233 ast_cli(a->fd, "active console is [%s]\n", oss_active); 01234 else if (a->argc != 4) 01235 return CLI_SHOWUSAGE; 01236 else { 01237 struct chan_oss_pvt *o; 01238 if (strcmp(a->argv[3], "show") == 0) { 01239 for (o = oss_default.next; o; o = o->next) 01240 ast_cli(a->fd, "device [%s] exists\n", o->name); 01241 return CLI_SUCCESS; 01242 } 01243 o = find_desc(a->argv[3]); 01244 if (o == NULL) 01245 ast_cli(a->fd, "No device [%s] exists\n", a->argv[3]); 01246 else 01247 oss_active = o->name; 01248 } 01249 return CLI_SUCCESS; 01250 }
| 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 979 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.
00980 { 00981 switch (cmd) { 00982 case CLI_INIT: 00983 e->command = "console answer"; 00984 e->usage = 00985 "Usage: console answer\n" 00986 " Answers an incoming call on the console (OSS) channel.\n"; 00987 return NULL; 00988 00989 case CLI_GENERATE: 00990 return NULL; /* no completion */ 00991 } 00992 if (a->argc != e->args) 00993 return CLI_SHOWUSAGE; 00994 return console_do_answer(a->fd); 00995 }
| static char* console_autoanswer | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 923 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.
00924 { 00925 struct chan_oss_pvt *o = find_desc(oss_active); 00926 00927 switch (cmd) { 00928 case CLI_INIT: 00929 e->command = "console {set|show} autoanswer [on|off]"; 00930 e->usage = 00931 "Usage: console {set|show} autoanswer [on|off]\n" 00932 " Enables or disables autoanswer feature. If used without\n" 00933 " argument, displays the current on/off status of autoanswer.\n" 00934 " The default value of autoanswer is in 'oss.conf'.\n"; 00935 return NULL; 00936 00937 case CLI_GENERATE: 00938 return NULL; 00939 } 00940 00941 if (a->argc == e->args - 1) { 00942 ast_cli(a->fd, "Auto answer is %s.\n", o->autoanswer ? "on" : "off"); 00943 return CLI_SUCCESS; 00944 } 00945 if (a->argc != e->args) 00946 return CLI_SHOWUSAGE; 00947 if (o == NULL) { 00948 ast_log(LOG_WARNING, "Cannot find device %s (should not happen!)\n", 00949 oss_active); 00950 return CLI_FAILURE; 00951 } 00952 if (!strcasecmp(a->argv[e->args-1], "on")) 00953 o->autoanswer = 1; 00954 else if (!strcasecmp(a->argv[e->args - 1], "off")) 00955 o->autoanswer = 0; 00956 else 00957 return CLI_SHOWUSAGE; 00958 return CLI_SUCCESS; 00959 }
| static char* console_boost | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1274 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.
01275 { 01276 struct chan_oss_pvt *o = find_desc(oss_active); 01277 01278 switch (cmd) { 01279 case CLI_INIT: 01280 e->command = "console boost"; 01281 e->usage = 01282 "Usage: console boost [boost in dB]\n" 01283 " Sets or display mic boost in dB\n"; 01284 return NULL; 01285 case CLI_GENERATE: 01286 return NULL; 01287 } 01288 01289 if (a->argc == 2) 01290 ast_cli(a->fd, "boost currently %5.1f\n", 20 * log10(((double) o->boost / (double) BOOST_SCALE))); 01291 else if (a->argc == 3) 01292 store_boost(o, a->argv[2]); 01293 return CLI_SUCCESS; 01294 }
| 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 887 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, chan_oss_pvt::device, chan_oss_pvt::env, ast_cli_args::fd, find_desc(), LOG_WARNING, store_config_core(), ast_cli_entry::usage, value, and var.
00888 { 00889 struct chan_oss_pvt *o = find_desc(oss_active); 00890 const char *var, *value; 00891 switch (cmd) { 00892 case CLI_INIT: 00893 e->command = CONSOLE_VIDEO_CMDS; 00894 e->usage = 00895 "Usage: " CONSOLE_VIDEO_CMDS "...\n" 00896 " Generic handler for console commands.\n"; 00897 return NULL; 00898 00899 case CLI_GENERATE: 00900 return NULL; 00901 } 00902 00903 if (a->argc < e->args) 00904 return CLI_SHOWUSAGE; 00905 if (o == NULL) { 00906 ast_log(LOG_WARNING, "Cannot find device %s (should not happen!)\n", 00907 oss_active); 00908 return CLI_FAILURE; 00909 } 00910 var = a->argv[e->args-1]; 00911 value = a->argc > e->args ? a->argv[e->args] : NULL; 00912 if (value) /* handle setting */ 00913 store_config_core(o, var, value); 00914 if (!console_video_cli(o->env, var, a->fd)) /* print video-related values */ 00915 return CLI_SUCCESS; 00916 /* handle other values */ 00917 if (!strcasecmp(var, "device")) { 00918 ast_cli(a->fd, "device is [%s]\n", o->device); 00919 } 00920 return CLI_SUCCESS; 00921 }
| static char* console_dial | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1089 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, ast_cli_args::fd, find_desc(), chan_oss_pvt::hookstate, ast_frame_subclass::integer, oss_new(), chan_oss_pvt::owner, ast_frame::subclass, and ast_cli_entry::usage.
01090 { 01091 char *s = NULL; 01092 char *mye = NULL, *myc = NULL; 01093 struct chan_oss_pvt *o = find_desc(oss_active); 01094 01095 if (cmd == CLI_INIT) { 01096 e->command = "console dial"; 01097 e->usage = 01098 "Usage: console dial [extension[@context]]\n" 01099 " Dials a given extension (and context if specified)\n"; 01100 return NULL; 01101 } else if (cmd == CLI_GENERATE) 01102 return NULL; 01103 01104 if (a->argc > e->args + 1) 01105 return CLI_SHOWUSAGE; 01106 if (o->owner) { /* already in a call */ 01107 int i; 01108 struct ast_frame f = { AST_FRAME_DTMF, { 0 } }; 01109 const char *digits; 01110 01111 if (a->argc == e->args) { /* argument is mandatory here */ 01112 ast_cli(a->fd, "Already in a call. You can only dial digits until you hangup.\n"); 01113 return CLI_FAILURE; 01114 } 01115 digits = a->argv[e->args]; 01116 /* send the string one char at a time */ 01117 for (i = 0; i < strlen(digits); i++) { 01118 f.subclass.integer = digits[i]; 01119 ast_queue_frame(o->owner, &f); 01120 } 01121 return CLI_SUCCESS; 01122 } 01123 /* if we have an argument split it into extension and context */ 01124 if (a->argc == e->args + 1) 01125 s = ast_ext_ctx(a->argv[e->args], &mye, &myc); 01126 /* supply default values if needed */ 01127 if (mye == NULL) 01128 mye = o->ext; 01129 if (myc == NULL) 01130 myc = o->ctx; 01131 if (ast_exists_extension(NULL, myc, mye, 1, NULL)) { 01132 o->hookstate = 1; 01133 oss_new(o, mye, myc, AST_STATE_RINGING, NULL); 01134 } else 01135 ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc); 01136 if (s) 01137 ast_free(s); 01138 return CLI_SUCCESS; 01139 }
| static char* console_do_answer | ( | int | fd | ) | [static] |
helper function for the answer key/cli command
Definition at line 962 of file chan_oss.c.
References ast_cli(), AST_CONTROL_ANSWER, AST_FRAME_CONTROL, ast_queue_frame(), CLI_FAILURE, CLI_SUCCESS, find_desc(), chan_oss_pvt::hookstate, and chan_oss_pvt::owner.
Referenced by console_answer().
00963 { 00964 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_ANSWER } }; 00965 struct chan_oss_pvt *o = find_desc(oss_active); 00966 if (!o->owner) { 00967 if (fd > -1) 00968 ast_cli(fd, "No one is calling us\n"); 00969 return CLI_FAILURE; 00970 } 00971 o->hookstate = 1; 00972 ast_queue_frame(o->owner, &f); 00973 return CLI_SUCCESS; 00974 }
| static char* console_flash | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1063 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, ast_cli_args::fd, find_desc(), chan_oss_pvt::hookstate, chan_oss_pvt::owner, and ast_cli_entry::usage.
01064 { 01065 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_FLASH } }; 01066 struct chan_oss_pvt *o = find_desc(oss_active); 01067 01068 if (cmd == CLI_INIT) { 01069 e->command = "console flash"; 01070 e->usage = 01071 "Usage: console flash\n" 01072 " Flashes the call currently placed on the console.\n"; 01073 return NULL; 01074 } else if (cmd == CLI_GENERATE) 01075 return NULL; 01076 01077 if (a->argc != e->args) 01078 return CLI_SHOWUSAGE; 01079 if (!o->owner) { /* XXX maybe !o->hookstate too ? */ 01080 ast_cli(a->fd, "No call to flash\n"); 01081 return CLI_FAILURE; 01082 } 01083 o->hookstate = 0; 01084 if (o->owner) 01085 ast_queue_frame(o->owner, &f); 01086 return CLI_SUCCESS; 01087 }
| static char* console_hangup | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1037 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.
01038 { 01039 struct chan_oss_pvt *o = find_desc(oss_active); 01040 01041 if (cmd == CLI_INIT) { 01042 e->command = "console hangup"; 01043 e->usage = 01044 "Usage: console hangup\n" 01045 " Hangs up any call currently placed on the console.\n"; 01046 return NULL; 01047 } else if (cmd == CLI_GENERATE) 01048 return NULL; 01049 01050 if (a->argc != e->args) 01051 return CLI_SHOWUSAGE; 01052 if (!o->owner && !o->hookstate) { /* XXX maybe only one ? */ 01053 ast_cli(a->fd, "No call to hang up\n"); 01054 return CLI_FAILURE; 01055 } 01056 o->hookstate = 0; 01057 if (o->owner) 01058 ast_queue_hangup_with_cause(o->owner, AST_CAUSE_NORMAL_CLEARING); 01059 setformat(o, O_CLOSE); 01060 return CLI_SUCCESS; 01061 }
| static char* console_mute | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1141 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.
01142 { 01143 struct chan_oss_pvt *o = find_desc(oss_active); 01144 const char *s; 01145 int toggle = 0; 01146 01147 if (cmd == CLI_INIT) { 01148 e->command = "console {mute|unmute} [toggle]"; 01149 e->usage = 01150 "Usage: console {mute|unmute} [toggle]\n" 01151 " Mute/unmute the microphone.\n"; 01152 return NULL; 01153 } else if (cmd == CLI_GENERATE) 01154 return NULL; 01155 01156 if (a->argc > e->args) 01157 return CLI_SHOWUSAGE; 01158 if (a->argc == e->args) { 01159 if (strcasecmp(a->argv[e->args-1], "toggle")) 01160 return CLI_SHOWUSAGE; 01161 toggle = 1; 01162 } 01163 s = a->argv[e->args-2]; 01164 if (!strcasecmp(s, "mute")) 01165 o->mute = toggle ? !o->mute : 1; 01166 else if (!strcasecmp(s, "unmute")) 01167 o->mute = toggle ? !o->mute : 0; 01168 else 01169 return CLI_SHOWUSAGE; 01170 ast_cli(a->fd, "Console mic is %s\n", o->mute ? "off" : "on"); 01171 return CLI_SUCCESS; 01172 }
| 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 1003 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, ast_frame::data, ast_frame::datalen, ast_cli_args::fd, find_desc(), ast_frame::frametype, ast_frame_subclass::integer, chan_oss_pvt::owner, ast_frame::ptr, ast_frame::subclass, TEXT_SIZE, and ast_cli_entry::usage.
01004 { 01005 struct chan_oss_pvt *o = find_desc(oss_active); 01006 char buf[TEXT_SIZE]; 01007 01008 if (cmd == CLI_INIT) { 01009 e->command = "console send text"; 01010 e->usage = 01011 "Usage: console send text <message>\n" 01012 " Sends a text message for display on the remote terminal.\n"; 01013 return NULL; 01014 } else if (cmd == CLI_GENERATE) 01015 return NULL; 01016 01017 if (a->argc < e->args + 1) 01018 return CLI_SHOWUSAGE; 01019 if (!o->owner) { 01020 ast_cli(a->fd, "Not in a call\n"); 01021 return CLI_FAILURE; 01022 } 01023 ast_join(buf, sizeof(buf) - 1, a->argv + e->args); 01024 if (!ast_strlen_zero(buf)) { 01025 struct ast_frame f = { 0, }; 01026 int i = strlen(buf); 01027 buf[i] = '\n'; 01028 f.frametype = AST_FRAME_TEXT; 01029 f.subclass.integer = 0; 01030 f.data.ptr = buf; 01031 f.datalen = i + 1; 01032 ast_queue_frame(o->owner, &f); 01033 } 01034 return CLI_SUCCESS; 01035 }
| static char* console_transfer | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1174 of file chan_oss.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_async_goto(), ast_bridged_channel(), ast_channel_caller(), ast_channel_context(), ast_channel_name(), ast_cli(), ast_exists_extension(), ast_ext_ctx(), ast_free, ast_strdupa, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ext, ast_cli_args::fd, find_desc(), chan_oss_pvt::owner, S_COR, and ast_cli_entry::usage.
01175 { 01176 struct chan_oss_pvt *o = find_desc(oss_active); 01177 struct ast_channel *b = NULL; 01178 char *tmp, *ext, *ctx; 01179 01180 switch (cmd) { 01181 case CLI_INIT: 01182 e->command = "console transfer"; 01183 e->usage = 01184 "Usage: console transfer <extension>[@context]\n" 01185 " Transfers the currently connected call to the given extension (and\n" 01186 " context if specified)\n"; 01187 return NULL; 01188 case CLI_GENERATE: 01189 return NULL; 01190 } 01191 01192 if (a->argc != 3) 01193 return CLI_SHOWUSAGE; 01194 if (o == NULL) 01195 return CLI_FAILURE; 01196 if (o->owner == NULL || (b = ast_bridged_channel(o->owner)) == NULL) { 01197 ast_cli(a->fd, "There is no call to transfer\n"); 01198 return CLI_SUCCESS; 01199 } 01200 01201 tmp = ast_ext_ctx(a->argv[2], &ext, &ctx); 01202 if (ctx == NULL) /* supply default context if needed */ 01203 ctx = ast_strdupa(ast_channel_context(o->owner)); 01204 if (!ast_exists_extension(b, ctx, ext, 1, 01205 S_COR(ast_channel_caller(b)->id.number.valid, ast_channel_caller(b)->id.number.str, NULL))) { 01206 ast_cli(a->fd, "No such extension exists\n"); 01207 } else { 01208 ast_cli(a->fd, "Whee, transferring %s to %s@%s.\n", ast_channel_name(b), ext, ctx); 01209 if (ast_async_goto(b, ctx, ext, 1)) 01210 ast_cli(a->fd, "Failed to transfer :(\n"); 01211 } 01212 if (tmp) 01213 ast_free(tmp); 01214 return CLI_SUCCESS; 01215 }
| static struct chan_oss_pvt * find_desc | ( | const char * | dev | ) | [static, read] |
returns a pointer to the descriptor with the given name
forward declaration
Definition at line 372 of file chan_oss.c.
References ast_log(), LOG_WARNING, chan_oss_pvt::name, and chan_oss_pvt::next.
Referenced by ast_ext_ctx(), console_active(), console_autoanswer(), console_boost(), console_cmd(), console_dial(), console_do_answer(), console_flash(), console_hangup(), console_mute(), console_sendtext(), console_transfer(), get_video_desc(), load_module(), and oss_request().
00373 { 00374 struct chan_oss_pvt *o = NULL; 00375 00376 if (!dev) 00377 ast_log(LOG_WARNING, "null dev\n"); 00378 00379 for (o = oss_default.next; o && o->name && dev && strcmp(o->name, dev) != 0; o = o->next); 00380 00381 if (!o) 00382 ast_log(LOG_WARNING, "could not find <%s>\n", dev ? dev : "--no-device--"); 00383 00384 return o; 00385 }
| struct video_desc* get_video_desc | ( | struct ast_channel * | c | ) | [read] |
return the pointer to the video descriptor
Definition at line 315 of file chan_oss.c.
References ast_channel_tech_pvt(), chan_oss_pvt::env, and find_desc().
Referenced by oss_new().
00316 { 00317 struct chan_oss_pvt *o = c ? ast_channel_tech_pvt(c) : find_desc(oss_active); 00318 return o ? o->env : NULL; 00319 }
| static int load_module | ( | void | ) | [static] |
Load the module.
Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
Definition at line 1455 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_format_cap_add(), ast_format_cap_alloc(), ast_format_set(), AST_FORMAT_SLINEAR, ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_channel_tech::capabilities, CONFIG_STATUS_FILEINVALID, find_desc(), global_jbconf, LOG_ERROR, LOG_NOTICE, and store_config().
01456 { 01457 struct ast_config *cfg = NULL; 01458 char *ctg = NULL; 01459 struct ast_flags config_flags = { 0 }; 01460 struct ast_format tmpfmt; 01461 01462 /* Copy the default jb config over global_jbconf */ 01463 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 01464 01465 /* load config file */ 01466 if (!(cfg = ast_config_load(config, config_flags))) { 01467 ast_log(LOG_NOTICE, "Unable to load config %s\n", config); 01468 return AST_MODULE_LOAD_DECLINE; 01469 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 01470 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config); 01471 return AST_MODULE_LOAD_DECLINE; 01472 } 01473 01474 do { 01475 store_config(cfg, ctg); 01476 } while ( (ctg = ast_category_browse(cfg, ctg)) != NULL); 01477 01478 ast_config_destroy(cfg); 01479 01480 if (find_desc(oss_active) == NULL) { 01481 ast_log(LOG_NOTICE, "Device %s not found\n", oss_active); 01482 /* XXX we could default to 'dsp' perhaps ? */ 01483 /* XXX should cleanup allocated memory etc. */ 01484 return AST_MODULE_LOAD_FAILURE; 01485 } 01486 01487 if (!(oss_tech.capabilities = ast_format_cap_alloc())) { 01488 return AST_MODULE_LOAD_FAILURE; 01489 } 01490 ast_format_cap_add(oss_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); 01491 01492 /* TODO XXX CONSOLE VIDEO IS DISABLE UNTIL IT HAS A MAINTAINER 01493 * add console_video_formats to oss_tech.capabilities once this occurs. */ 01494 01495 if (ast_channel_register(&oss_tech)) { 01496 ast_log(LOG_ERROR, "Unable to register channel type 'OSS'\n"); 01497 return AST_MODULE_LOAD_DECLINE; 01498 } 01499 01500 ast_cli_register_multiple(cli_oss, ARRAY_LEN(cli_oss)); 01501 01502 return AST_MODULE_LOAD_SUCCESS; 01503 }
| static int oss_answer | ( | struct ast_channel * | c | ) | [static] |
remote side answered the phone
Definition at line 641 of file chan_oss.c.
References ast_channel_tech_pvt(), ast_setstate(), AST_STATE_UP, ast_verbose, and chan_oss_pvt::hookstate.
00642 { 00643 struct chan_oss_pvt *o = ast_channel_tech_pvt(c); 00644 ast_verbose(" << Console call has been answered >> \n"); 00645 ast_setstate(c, AST_STATE_UP); 00646 o->hookstate = 1; 00647 return 0; 00648 }
| static int oss_call | ( | struct ast_channel * | c, | |
| const char * | dest, | |||
| int | timeout | |||
| ) | [static] |
handler for incoming calls. Either autoanswer, or start ringing
Definition at line 599 of file chan_oss.c.
References args, AST_APP_ARG, ast_channel_caller(), ast_channel_dialed(), ast_channel_redirecting(), ast_channel_tech_pvt(), 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_frame::flags, chan_oss_pvt::hookstate, ast_frame_subclass::integer, name, parse(), S_COR, S_OR, ast_party_dialed::str, and ast_frame::subclass.
00600 { 00601 struct chan_oss_pvt *o = ast_channel_tech_pvt(c); 00602 struct ast_frame f = { AST_FRAME_CONTROL, }; 00603 AST_DECLARE_APP_ARGS(args, 00604 AST_APP_ARG(name); 00605 AST_APP_ARG(flags); 00606 ); 00607 char *parse = ast_strdupa(dest); 00608 00609 AST_NONSTANDARD_APP_ARGS(args, parse, '/'); 00610 00611 ast_verbose(" << Call to device '%s' dnid '%s' rdnis '%s' on console from '%s' <%s> >>\n", 00612 dest, 00613 S_OR(ast_channel_dialed(c)->number.str, ""), 00614 S_COR(ast_channel_redirecting(c)->from.number.valid, ast_channel_redirecting(c)->from.number.str, ""), 00615 S_COR(ast_channel_caller(c)->id.name.valid, ast_channel_caller(c)->id.name.str, ""), 00616 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, "")); 00617 if (!ast_strlen_zero(args.flags) && strcasecmp(args.flags, "answer") == 0) { 00618 f.subclass.integer = AST_CONTROL_ANSWER; 00619 ast_queue_frame(c, &f); 00620 } else if (!ast_strlen_zero(args.flags) && strcasecmp(args.flags, "noanswer") == 0) { 00621 f.subclass.integer = AST_CONTROL_RINGING; 00622 ast_queue_frame(c, &f); 00623 ast_indicate(c, AST_CONTROL_RINGING); 00624 } else if (o->autoanswer) { 00625 ast_verbose(" << Auto-answered >> \n"); 00626 f.subclass.integer = AST_CONTROL_ANSWER; 00627 ast_queue_frame(c, &f); 00628 o->hookstate = 1; 00629 } else { 00630 ast_verbose("<< Type 'answer' to answer, or use 'autoanswer' for future calls >> \n"); 00631 f.subclass.integer = AST_CONTROL_RINGING; 00632 ast_queue_frame(c, &f); 00633 ast_indicate(c, AST_CONTROL_RINGING); 00634 } 00635 return 0; 00636 }
| 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 581 of file chan_oss.c.
References ast_verbose.
00582 { 00583 /* no better use for received digits than print them */ 00584 ast_verbose(" << Console Received digit %c of duration %u ms >> \n", 00585 digit, duration); 00586 return 0; 00587 }
| static int oss_fixup | ( | struct ast_channel * | oldchan, | |
| struct ast_channel * | newchan | |||
| ) | [static] |
Definition at line 750 of file chan_oss.c.
References ast_channel_tech_pvt(), and chan_oss_pvt::owner.
00751 { 00752 struct chan_oss_pvt *o = ast_channel_tech_pvt(newchan); 00753 o->owner = newchan; 00754 return 0; 00755 }
| static int oss_hangup | ( | struct ast_channel * | c | ) | [static] |
Definition at line 650 of file chan_oss.c.
References ast_channel_tech_pvt(), ast_channel_tech_pvt_set(), 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, and setformat().
00651 { 00652 struct chan_oss_pvt *o = ast_channel_tech_pvt(c); 00653 00654 ast_channel_tech_pvt_set(c, NULL); 00655 o->owner = NULL; 00656 ast_verbose(" << Hangup on console >> \n"); 00657 console_video_uninit(o->env); 00658 ast_module_unref(ast_module_info->self); 00659 if (o->hookstate) { 00660 if (o->autoanswer || o->autohangup) { 00661 /* Assume auto-hangup too */ 00662 o->hookstate = 0; 00663 setformat(o, O_CLOSE); 00664 } 00665 } 00666 return 0; 00667 }
| static int oss_indicate | ( | struct ast_channel * | chan, | |
| int | cond, | |||
| const void * | data, | |||
| size_t | datalen | |||
| ) | [static] |
Definition at line 757 of file chan_oss.c.
References ast_channel_name(), ast_channel_tech_pvt(), AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_PVT_CAUSE_CODE, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_log(), ast_moh_start(), ast_moh_stop(), ast_verbose, LOG_WARNING, and chan_oss_pvt::mohinterpret.
00758 { 00759 struct chan_oss_pvt *o = ast_channel_tech_pvt(c); 00760 int res = 0; 00761 00762 switch (cond) { 00763 case AST_CONTROL_INCOMPLETE: 00764 case AST_CONTROL_BUSY: 00765 case AST_CONTROL_CONGESTION: 00766 case AST_CONTROL_RINGING: 00767 case AST_CONTROL_PVT_CAUSE_CODE: 00768 case -1: 00769 res = -1; 00770 break; 00771 case AST_CONTROL_PROGRESS: 00772 case AST_CONTROL_PROCEEDING: 00773 case AST_CONTROL_VIDUPDATE: 00774 case AST_CONTROL_SRCUPDATE: 00775 break; 00776 case AST_CONTROL_HOLD: 00777 ast_verbose(" << Console Has Been Placed on Hold >> \n"); 00778 ast_moh_start(c, data, o->mohinterpret); 00779 break; 00780 case AST_CONTROL_UNHOLD: 00781 ast_verbose(" << Console Has Been Retrieved from Hold >> \n"); 00782 ast_moh_stop(c); 00783 break; 00784 default: 00785 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, ast_channel_name(c)); 00786 return -1; 00787 } 00788 00789 return res; 00790 }
| static struct ast_channel* oss_new | ( | struct chan_oss_pvt * | o, | |
| char * | ext, | |||
| char * | ctx, | |||
| int | state, | |||
| const char * | linkedid | |||
| ) | [static, read] |
allocate a new channel.
Definition at line 795 of file chan_oss.c.
References ast_party_caller::ani, ast_channel_alloc, ast_channel_caller(), ast_channel_dialed(), ast_channel_name(), ast_channel_nativeformats(), ast_channel_readformat(), ast_channel_set_fd(), ast_channel_tech_pvt_set(), ast_channel_tech_set(), ast_channel_writeformat(), ast_format_cap_add(), ast_format_set(), AST_FORMAT_SLINEAR, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), AST_STATE_DOWN, ast_strdup, ast_strlen_zero(), chan_oss_pvt::cid_name, chan_oss_pvt::cid_num, console_video_start(), chan_oss_pvt::device, get_video_desc(), global_jbconf, chan_oss_pvt::language, LOG_WARNING, ast_party_dialed::number, ast_party_id::number, chan_oss_pvt::owner, setformat(), chan_oss_pvt::sounddev, ast_party_dialed::str, ast_party_number::str, and ast_party_number::valid.
Referenced by console_dial(), and oss_request().
00796 { 00797 struct ast_channel *c; 00798 00799 c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, linkedid, 0, "Console/%s", o->device + 5); 00800 if (c == NULL) 00801 return NULL; 00802 ast_channel_tech_set(c, &oss_tech); 00803 if (o->sounddev < 0) 00804 setformat(o, O_RDWR); 00805 ast_channel_set_fd(c, 0, o->sounddev); /* -1 if device closed, override later */ 00806 00807 ast_format_set(ast_channel_readformat(c), AST_FORMAT_SLINEAR, 0); 00808 ast_format_set(ast_channel_writeformat(c), AST_FORMAT_SLINEAR, 0); 00809 ast_format_cap_add(ast_channel_nativeformats(c), ast_channel_readformat(c)); 00810 00811 /* if the console makes the call, add video to the offer */ 00812 /* if (state == AST_STATE_RINGING) TODO XXX CONSOLE VIDEO IS DISABLED UNTIL IT GETS A MAINTAINER 00813 c->nativeformats |= console_video_formats; */ 00814 00815 ast_channel_tech_pvt_set(c, o); 00816 00817 if (!ast_strlen_zero(o->language)) 00818 ast_channel_language_set(c, o->language); 00819 /* Don't use ast_set_callerid() here because it will 00820 * generate a needless NewCallerID event */ 00821 if (!ast_strlen_zero(o->cid_num)) { 00822 ast_channel_caller(c)->ani.number.valid = 1; 00823 ast_channel_caller(c)->ani.number.str = ast_strdup(o->cid_num); 00824 } 00825 if (!ast_strlen_zero(ext)) { 00826 ast_channel_dialed(c)->number.str = ast_strdup(ext); 00827 } 00828 00829 o->owner = c; 00830 ast_module_ref(ast_module_info->self); 00831 ast_jb_configure(c, &global_jbconf); 00832 if (state != AST_STATE_DOWN) { 00833 if (ast_pbx_start(c)) { 00834 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(c)); 00835 ast_hangup(c); 00836 o->owner = c = NULL; 00837 } 00838 } 00839 console_video_start(get_video_desc(c), c); /* XXX cleanup */ 00840 00841 return c; 00842 }
| static struct ast_frame * oss_read | ( | struct ast_channel * | chan | ) | [static, read] |
Definition at line 701 of file chan_oss.c.
References ast_channel_tech_pvt(), ast_format_set(), AST_FORMAT_SLINEAR, AST_FRAME_NULL, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, AST_STATE_UP, chan_oss_pvt::boost, BOOST_SCALE, ast_frame::data, ast_frame::datalen, f, ast_frame_subclass::format, FRAME_SIZE, ast_frame::frametype, chan_oss_pvt::mute, ast_frame::offset, chan_oss_pvt::oss_read_buf, ast_frame::ptr, chan_oss_pvt::read_f, chan_oss_pvt::readpos, ast_frame::samples, chan_oss_pvt::sounddev, ast_frame::src, ast_frame::subclass, and ast_channel_tech::type.
00702 { 00703 int res; 00704 struct chan_oss_pvt *o = ast_channel_tech_pvt(c); 00705 struct ast_frame *f = &o->read_f; 00706 00707 /* XXX can be simplified returning &ast_null_frame */ 00708 /* prepare a NULL frame in case we don't have enough data to return */ 00709 memset(f, '\0', sizeof(struct ast_frame)); 00710 f->frametype = AST_FRAME_NULL; 00711 f->src = oss_tech.type; 00712 00713 res = read(o->sounddev, o->oss_read_buf + o->readpos, sizeof(o->oss_read_buf) - o->readpos); 00714 if (res < 0) /* audio data not ready, return a NULL frame */ 00715 return f; 00716 00717 o->readpos += res; 00718 if (o->readpos < sizeof(o->oss_read_buf)) /* not enough samples */ 00719 return f; 00720 00721 if (o->mute) 00722 return f; 00723 00724 o->readpos = AST_FRIENDLY_OFFSET; /* reset read pointer for next frame */ 00725 if (ast_channel_state(c) != AST_STATE_UP) /* drop data if frame is not up */ 00726 return f; 00727 /* ok we can build and deliver the frame to the caller */ 00728 f->frametype = AST_FRAME_VOICE; 00729 ast_format_set(&f->subclass.format, AST_FORMAT_SLINEAR, 0); 00730 f->samples = FRAME_SIZE; 00731 f->datalen = FRAME_SIZE * 2; 00732 f->data.ptr = o->oss_read_buf + AST_FRIENDLY_OFFSET; 00733 if (o->boost != BOOST_SCALE) { /* scale and clip values */ 00734 int i, x; 00735 int16_t *p = (int16_t *) f->data.ptr; 00736 for (i = 0; i < f->samples; i++) { 00737 x = (p[i] * o->boost) / BOOST_SCALE; 00738 if (x > 32767) 00739 x = 32767; 00740 else if (x < -32768) 00741 x = -32768; 00742 p[i] = x; 00743 } 00744 } 00745 00746 f->offset = AST_FRIENDLY_OFFSET; 00747 return f; 00748 }
| static struct ast_channel * oss_request | ( | const char * | type, | |
| struct ast_format_cap * | cap, | |||
| const struct ast_channel * | requestor, | |||
| const char * | data, | |||
| int * | cause | |||
| ) | [static, read] |
Definition at line 844 of file chan_oss.c.
References args, AST_APP_ARG, AST_CAUSE_BUSY, ast_channel_linkedid(), AST_DECLARE_APP_ARGS, ast_format_cap_iscompatible(), ast_format_set(), AST_FORMAT_SLINEAR, ast_getformatname_multiple(), 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().
00845 { 00846 struct ast_channel *c; 00847 struct chan_oss_pvt *o; 00848 AST_DECLARE_APP_ARGS(args, 00849 AST_APP_ARG(name); 00850 AST_APP_ARG(flags); 00851 ); 00852 char *parse = ast_strdupa(data); 00853 char buf[256]; 00854 struct ast_format tmpfmt; 00855 00856 AST_NONSTANDARD_APP_ARGS(args, parse, '/'); 00857 o = find_desc(args.name); 00858 00859 ast_log(LOG_WARNING, "oss_request ty <%s> data 0x%p <%s>\n", type, data, data); 00860 if (o == NULL) { 00861 ast_log(LOG_NOTICE, "Device %s not found\n", args.name); 00862 /* XXX we could default to 'dsp' perhaps ? */ 00863 return NULL; 00864 } 00865 if (!(ast_format_cap_iscompatible(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)))) { 00866 ast_log(LOG_NOTICE, "Format %s unsupported\n", ast_getformatname_multiple(buf, sizeof(buf), cap)); 00867 return NULL; 00868 } 00869 if (o->owner) { 00870 ast_log(LOG_NOTICE, "Already have a call (chan %p) on the OSS channel\n", o->owner); 00871 *cause = AST_CAUSE_BUSY; 00872 return NULL; 00873 } 00874 c = oss_new(o, NULL, NULL, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL); 00875 if (c == NULL) { 00876 ast_log(LOG_WARNING, "Unable to create new OSS channel\n"); 00877 return NULL; 00878 } 00879 return c; 00880 }
| static int oss_text | ( | struct ast_channel * | c, | |
| const char * | text | |||
| ) | [static] |
Definition at line 589 of file chan_oss.c.
References ast_verbose.
00590 { 00591 /* print received messages */ 00592 ast_verbose(" << Console Received text %s >> \n", text); 00593 return 0; 00594 }
| static int oss_write | ( | struct ast_channel * | chan, | |
| struct ast_frame * | f | |||
| ) | [static] |
used for data coming from the network
Definition at line 670 of file chan_oss.c.
References ast_channel_tech_pvt(), ast_frame::data, ast_frame::datalen, chan_oss_pvt::oss_write_buf, chan_oss_pvt::oss_write_dst, ast_frame::ptr, and soundcard_writeframe().
00671 { 00672 int src; 00673 struct chan_oss_pvt *o = ast_channel_tech_pvt(c); 00674 00675 /* 00676 * we could receive a block which is not a multiple of our 00677 * FRAME_SIZE, so buffer it locally and write to the device 00678 * in FRAME_SIZE chunks. 00679 * Keep the residue stored for future use. 00680 */ 00681 src = 0; /* read position into f->data */ 00682 while (src < f->datalen) { 00683 /* Compute spare room in the buffer */ 00684 int l = sizeof(o->oss_write_buf) - o->oss_write_dst; 00685 00686 if (f->datalen - src >= l) { /* enough to fill a frame */ 00687 memcpy(o->oss_write_buf + o->oss_write_dst, f->data.ptr + src, l); 00688 soundcard_writeframe(o, (short *) o->oss_write_buf); 00689 src += l; 00690 o->oss_write_dst = 0; 00691 } else { /* copy residue */ 00692 l = f->datalen - src; 00693 memcpy(o->oss_write_buf + o->oss_write_dst, f->data.ptr + src, l); 00694 src += l; /* but really, we are done */ 00695 o->oss_write_dst += l; 00696 } 00697 } 00698 return 0; 00699 }
| 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 477 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(), and store_config().
00478 { 00479 int fmt, desired, res, fd; 00480 00481 if (o->sounddev >= 0) { 00482 ioctl(o->sounddev, SNDCTL_DSP_RESET, 0); 00483 close(o->sounddev); 00484 o->duplex = M_UNSET; 00485 o->sounddev = -1; 00486 } 00487 if (mode == O_CLOSE) /* we are done */ 00488 return 0; 00489 if (ast_tvdiff_ms(ast_tvnow(), o->lastopen) < 1000) 00490 return -1; /* don't open too often */ 00491 o->lastopen = ast_tvnow(); 00492 fd = o->sounddev = open(o->device, mode | O_NONBLOCK); 00493 if (fd < 0) { 00494 ast_log(LOG_WARNING, "Unable to re-open DSP device %s: %s\n", o->device, strerror(errno)); 00495 return -1; 00496 } 00497 if (o->owner) 00498 ast_channel_set_fd(o->owner, 0, fd); 00499 00500 #if __BYTE_ORDER == __LITTLE_ENDIAN 00501 fmt = AFMT_S16_LE; 00502 #else 00503 fmt = AFMT_S16_BE; 00504 #endif 00505 res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt); 00506 if (res < 0) { 00507 ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n"); 00508 return -1; 00509 } 00510 switch (mode) { 00511 case O_RDWR: 00512 res = ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0); 00513 /* Check to see if duplex set (FreeBSD Bug) */ 00514 res = ioctl(fd, SNDCTL_DSP_GETCAPS, &fmt); 00515 if (res == 0 && (fmt & DSP_CAP_DUPLEX)) { 00516 ast_verb(2, "Console is full duplex\n"); 00517 o->duplex = M_FULL; 00518 }; 00519 break; 00520 00521 case O_WRONLY: 00522 o->duplex = M_WRITE; 00523 break; 00524 00525 case O_RDONLY: 00526 o->duplex = M_READ; 00527 break; 00528 } 00529 00530 fmt = 0; 00531 res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt); 00532 if (res < 0) { 00533 ast_log(LOG_WARNING, "Failed to set audio device to mono\n"); 00534 return -1; 00535 } 00536 fmt = desired = DEFAULT_SAMPLE_RATE; /* 8000 Hz desired */ 00537 res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt); 00538 00539 if (res < 0) { 00540 ast_log(LOG_WARNING, "Failed to set sample rate to %d\n", desired); 00541 return -1; 00542 } 00543 if (fmt != desired) { 00544 if (!(o->warned & WARN_speed)) { 00545 ast_log(LOG_WARNING, 00546 "Requested %d Hz, got %d Hz -- sound may be choppy\n", 00547 desired, fmt); 00548 o->warned |= WARN_speed; 00549 } 00550 } 00551 /* 00552 * on Freebsd, SETFRAGMENT does not work very well on some cards. 00553 * Default to use 256 bytes, let the user override 00554 */ 00555 if (o->frags) { 00556 fmt = o->frags; 00557 res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt); 00558 if (res < 0) { 00559 if (!(o->warned & WARN_frag)) { 00560 ast_log(LOG_WARNING, 00561 "Unable to set fragment size -- sound may be choppy\n"); 00562 o->warned |= WARN_frag; 00563 } 00564 } 00565 } 00566 /* on some cards, we need SNDCTL_DSP_SETTRIGGER to start outputting */ 00567 res = PCM_ENABLE_INPUT | PCM_ENABLE_OUTPUT; 00568 res = ioctl(fd, SNDCTL_DSP_SETTRIGGER, &res); 00569 /* it may fail if we are in half duplex, never mind */ 00570 return 0; 00571 }
| static int soundcard_writeframe | ( | struct chan_oss_pvt * | o, | |
| short * | data | |||
| ) | [static] |
Write an exactly FRAME_SIZE sized frame
Definition at line 448 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().
00449 { 00450 int res; 00451 00452 if (o->sounddev < 0) 00453 setformat(o, O_RDWR); 00454 if (o->sounddev < 0) 00455 return 0; /* not fatal */ 00456 /* 00457 * Nothing complex to manage the audio device queue. 00458 * If the buffer is full just drop the extra, otherwise write. 00459 * XXX in some cases it might be useful to write anyways after 00460 * a number of failures, to restart the output chain. 00461 */ 00462 res = used_blocks(o); 00463 if (res > o->queuesize) { /* no room to write a block */ 00464 if (o->w_errors++ == 0 && (oss_debug & 0x4)) 00465 ast_log(LOG_WARNING, "write: used %d blocks (%d)\n", res, o->w_errors); 00466 return 0; 00467 } 00468 o->w_errors = 0; 00469 return write(o->sounddev, (void *)data, FRAME_SIZE * 2); 00470 }
| static void store_boost | ( | struct chan_oss_pvt * | o, | |
| const char * | s | |||
| ) | [static] |
store the boost factor
Definition at line 1255 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().
01256 { 01257 double boost = 0; 01258 if (sscanf(s, "%30lf", &boost) != 1) { 01259 ast_log(LOG_WARNING, "invalid boost <%s>\n", s); 01260 return; 01261 } 01262 if (boost < -BOOST_MAX) { 01263 ast_log(LOG_WARNING, "boost %s too small, using %d\n", s, -BOOST_MAX); 01264 boost = -BOOST_MAX; 01265 } else if (boost > BOOST_MAX) { 01266 ast_log(LOG_WARNING, "boost %s too large, using %d\n", s, BOOST_MAX); 01267 boost = BOOST_MAX; 01268 } 01269 boost = exp(log(10) * boost / 20) * BOOST_SCALE; 01270 o->boost = boost; 01271 ast_log(LOG_WARNING, "setting boost %s to %d\n", s, o->boost); 01272 }
| static void store_callerid | ( | struct chan_oss_pvt * | o, | |
| const char * | s | |||
| ) | [static] |
store the callerid components
Definition at line 1334 of file chan_oss.c.
References ast_callerid_split(), chan_oss_pvt::cid_name, and chan_oss_pvt::cid_num.
01335 { 01336 ast_callerid_split(s, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num)); 01337 }
| static struct chan_oss_pvt* store_config | ( | struct ast_config * | cfg, | |
| char * | ctg | |||
| ) | [static, read] |
grab fields from the config file, init the descriptor and open the device.
Definition at line 1370 of file chan_oss.c.
References ast_asprintf, ast_calloc, ast_copy_string(), ast_free, ast_log(), ast_strdup, ast_strlen_zero(), ast_tvnow(), ast_variable_browse(), ast_verb, console_video_start(), DEV_DSP, chan_oss_pvt::device, chan_oss_pvt::duplex, chan_oss_pvt::env, errno, get_gui_startup(), chan_oss_pvt::lastopen, LOG_WARNING, chan_oss_pvt::M_FULL, chan_oss_pvt::mixer_cmd, chan_oss_pvt::mohinterpret, ast_variable::name, chan_oss_pvt::name, chan_oss_pvt::next, ast_variable::next, setformat(), store_config_core(), and ast_variable::value.
Referenced by load_module().
01371 { 01372 struct ast_variable *v; 01373 struct chan_oss_pvt *o; 01374 01375 if (ctg == NULL) { 01376 o = &oss_default; 01377 ctg = "general"; 01378 } else { 01379 if (!(o = ast_calloc(1, sizeof(*o)))) 01380 return NULL; 01381 *o = oss_default; 01382 /* "general" is also the default thing */ 01383 if (strcmp(ctg, "general") == 0) { 01384 o->name = ast_strdup("dsp"); 01385 oss_active = o->name; 01386 goto openit; 01387 } 01388 o->name = ast_strdup(ctg); 01389 } 01390 01391 strcpy(o->mohinterpret, "default"); 01392 01393 o->lastopen = ast_tvnow(); /* don't leave it 0 or tvdiff may wrap */ 01394 /* fill other fields from configuration */ 01395 for (v = ast_variable_browse(cfg, ctg); v; v = v->next) { 01396 store_config_core(o, v->name, v->value); 01397 } 01398 if (ast_strlen_zero(o->device)) 01399 ast_copy_string(o->device, DEV_DSP, sizeof(o->device)); 01400 if (o->mixer_cmd) { 01401 char *cmd; 01402 01403 if (ast_asprintf(&cmd, "mixer %s", o->mixer_cmd) >= 0) { 01404 ast_log(LOG_WARNING, "running [%s]\n", cmd); 01405 if (system(cmd) < 0) { 01406 ast_log(LOG_WARNING, "system() failed: %s\n", strerror(errno)); 01407 } 01408 ast_free(cmd); 01409 } 01410 } 01411 01412 /* if the config file requested to start the GUI, do it */ 01413 if (get_gui_startup(o->env)) 01414 console_video_start(o->env, NULL); 01415 01416 if (o == &oss_default) /* we are done with the default */ 01417 return NULL; 01418 01419 openit: 01420 #ifdef TRYOPEN 01421 if (setformat(o, O_RDWR) < 0) { /* open device */ 01422 ast_verb(1, "Device %s not detected\n", ctg); 01423 ast_verb(1, "Turn off OSS support by adding " "'noload=chan_oss.so' in /etc/asterisk/modules.conf\n"); 01424 goto error; 01425 } 01426 if (o->duplex != M_FULL) 01427 ast_log(LOG_WARNING, "XXX I don't work right with non " "full-duplex sound cards XXX\n"); 01428 #endif /* TRYOPEN */ 01429 01430 /* link into list of devices */ 01431 if (o != &oss_default) { 01432 o->next = oss_default.next; 01433 oss_default.next = o; 01434 } 01435 return o; 01436 01437 #ifdef TRYOPEN 01438 error: 01439 if (o != &oss_default) 01440 ast_free(o); 01441 return NULL; 01442 #endif 01443 }
| static void store_config_core | ( | struct chan_oss_pvt * | o, | |
| const char * | var, | |||
| const char * | value | |||
| ) | [static] |
Definition at line 1339 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().
01340 { 01341 CV_START(var, value); 01342 01343 /* handle jb conf */ 01344 if (!ast_jb_read_conf(&global_jbconf, var, value)) 01345 return; 01346 01347 if (!console_video_config(&o->env, var, value)) 01348 return; /* matched there */ 01349 CV_BOOL("autoanswer", o->autoanswer); 01350 CV_BOOL("autohangup", o->autohangup); 01351 CV_BOOL("overridecontext", o->overridecontext); 01352 CV_STR("device", o->device); 01353 CV_UINT("frags", o->frags); 01354 CV_UINT("debug", oss_debug); 01355 CV_UINT("queuesize", o->queuesize); 01356 CV_STR("context", o->ctx); 01357 CV_STR("language", o->language); 01358 CV_STR("mohinterpret", o->mohinterpret); 01359 CV_STR("extension", o->ext); 01360 CV_F("mixer", store_mixer(o, value)); 01361 CV_F("callerid", store_callerid(o, value)) ; 01362 CV_F("boost", store_boost(o, value)); 01363 01364 CV_END; 01365 }
| 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 1315 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().
01316 { 01317 int i; 01318 01319 for (i = 0; i < strlen(s); i++) { 01320 if (!isalnum(s[i]) && strchr(" \t-/", s[i]) == NULL) { 01321 ast_log(LOG_WARNING, "Suspect char %c in mixer cmd, ignoring:\n\t%s\n", s[i], s); 01322 return; 01323 } 01324 } 01325 if (o->mixer_cmd) 01326 ast_free(o->mixer_cmd); 01327 o->mixer_cmd = ast_strdup(s); 01328 ast_log(LOG_WARNING, "setting mixer %s\n", s); 01329 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 1506 of file chan_oss.c.
References ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_format_cap_destroy(), ast_free, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_channel_tech::capabilities, chan_oss_pvt::name, chan_oss_pvt::next, chan_oss_pvt::owner, and chan_oss_pvt::sounddev.
01507 { 01508 struct chan_oss_pvt *o, *next; 01509 01510 ast_channel_unregister(&oss_tech); 01511 ast_cli_unregister_multiple(cli_oss, ARRAY_LEN(cli_oss)); 01512 01513 o = oss_default.next; 01514 while (o) { 01515 close(o->sounddev); 01516 if (o->owner) 01517 ast_softhangup(o->owner, AST_SOFTHANGUP_APPUNLOAD); 01518 if (o->owner) 01519 return -1; 01520 next = o->next; 01521 ast_free(o->name); 01522 ast_free(o); 01523 o = next; 01524 } 01525 oss_tech.capabilities = ast_format_cap_destroy(oss_tech.capabilities); 01526 return 0; 01527 }
| static int used_blocks | ( | struct chan_oss_pvt * | o | ) | [static] |
Returns the number of blocks used in the audio output channel.
Definition at line 426 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().
00427 { 00428 struct audio_buf_info info; 00429 00430 if (ioctl(o->sounddev, SNDCTL_DSP_GETOSPACE, &info)) { 00431 if (!(o->warned & WARN_used_blocks)) { 00432 ast_log(LOG_WARNING, "Error reading output space\n"); 00433 o->warned |= WARN_used_blocks; 00434 } 00435 return 1; 00436 } 00437 00438 if (o->total_blocks == 0) { 00439 if (0) /* debugging */ 00440 ast_log(LOG_WARNING, "fragtotal %d size %d avail %d\n", info.fragstotal, info.fragsize, info.fragments); 00441 o->total_blocks = info.fragments; 00442 } 00443 00444 return o->total_blocks - info.fragments; 00445 }
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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static] |
Definition at line 1529 of file chan_oss.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1529 of file chan_oss.c.
struct ast_cli_entry cli_oss[] [static] |
Definition at line 1296 of file chan_oss.c.
char* config = "oss.conf" [static] |
Definition at line 241 of file chan_oss.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 77 of file chan_oss.c.
struct ast_jb_conf global_jbconf [static] |
Definition at line 85 of file chan_oss.c.
char* oss_active [static] |
the active device
Definition at line 312 of file chan_oss.c.
int oss_debug [static] |
Definition at line 243 of file chan_oss.c.
struct chan_oss_pvt oss_default [static] |
Definition at line 320 of file chan_oss.c.
struct ast_channel_tech oss_tech [static] |
Definition at line 352 of file chan_oss.c.
char tdesc[] = "OSS Console Channel Driver" [static] |
Definition at line 349 of file chan_oss.c.
1.5.6