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