00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "asterisk.h"
00027
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 193546 $")
00029
00030 #include "asterisk/module.h"
00031 #include "asterisk/channel.h"
00032 #include "asterisk/pbx.h"
00033 #include "asterisk/utils.h"
00034 #include "asterisk/app.h"
00035 #include "asterisk/indications.h"
00036 #include "asterisk/stringfields.h"
00037
00038 #define locked_copy_string(chan, dest, source, len) \
00039 do { \
00040 ast_channel_lock(chan); \
00041 ast_copy_string(dest, source, len); \
00042 ast_channel_unlock(chan); \
00043 } while (0)
00044 #define locked_string_field_set(chan, field, source) \
00045 do { \
00046 ast_channel_lock(chan); \
00047 ast_string_field_set(chan, field, source); \
00048 ast_channel_unlock(chan); \
00049 } while (0)
00050
00051 char *transfercapability_table[0x20] = {
00052 "SPEECH", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
00053 "DIGITAL", "RESTRICTED_DIGITAL", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
00054 "3K1AUDIO", "DIGITAL_W_TONES", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK",
00055 "VIDEO", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", };
00056
00057 static int func_channel_read(struct ast_channel *chan, const char *function,
00058 char *data, char *buf, size_t len)
00059 {
00060 int ret = 0;
00061
00062 if (!strcasecmp(data, "audionativeformat"))
00063
00064
00065 ast_copy_string(buf, ast_getformatname(chan->nativeformats & AST_FORMAT_AUDIO_MASK), len);
00066 else if (!strcasecmp(data, "videonativeformat"))
00067
00068
00069 ast_copy_string(buf, ast_getformatname(chan->nativeformats & AST_FORMAT_VIDEO_MASK), len);
00070 else if (!strcasecmp(data, "audioreadformat"))
00071 ast_copy_string(buf, ast_getformatname(chan->readformat), len);
00072 else if (!strcasecmp(data, "audiowriteformat"))
00073 ast_copy_string(buf, ast_getformatname(chan->writeformat), len);
00074 #ifdef CHANNEL_TRACE
00075 else if (!strcasecmp(data, "trace")) {
00076 ast_channel_lock(chan);
00077 ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len);
00078 ast_channel_unlock(chan);
00079 }
00080 #endif
00081 else if (!strcasecmp(data, "tonezone") && chan->zone)
00082 locked_copy_string(chan, buf, chan->zone->country, len);
00083 else if (!strcasecmp(data, "language"))
00084 locked_copy_string(chan, buf, chan->language, len);
00085 else if (!strcasecmp(data, "musicclass"))
00086 locked_copy_string(chan, buf, chan->musicclass, len);
00087 else if (!strcasecmp(data, "state"))
00088 locked_copy_string(chan, buf, ast_state2str(chan->_state), len);
00089 else if (!strcasecmp(data, "channeltype"))
00090 locked_copy_string(chan, buf, chan->tech->type, len);
00091 else if (!strcasecmp(data, "transfercapability"))
00092 locked_copy_string(chan, buf, transfercapability_table[chan->transfercapability & 0x1f], len);
00093 else if (!strcasecmp(data, "callgroup")) {
00094 char groupbuf[256];
00095 locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), chan->callgroup), len);
00096 } else if (!chan->tech->func_channel_read
00097 || chan->tech->func_channel_read(chan, function, data, buf, len)) {
00098 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
00099 ret = -1;
00100 }
00101
00102 return ret;
00103 }
00104
00105 static int func_channel_write(struct ast_channel *chan, const char *function,
00106 char *data, const char *value)
00107 {
00108 int ret = 0;
00109 signed char gainset;
00110
00111 if (!strcasecmp(data, "language"))
00112 locked_string_field_set(chan, language, value);
00113 else if (!strcasecmp(data, "musicclass"))
00114 locked_string_field_set(chan, musicclass, value);
00115 #ifdef CHANNEL_TRACE
00116 else if (!strcasecmp(data, "trace")) {
00117 ast_channel_lock(chan);
00118 if (ast_true(value))
00119 ret = ast_channel_trace_enable(chan);
00120 else if (ast_false(value))
00121 ret = ast_channel_trace_disable(chan);
00122 else {
00123 ret = -1;
00124 ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace).");
00125 }
00126 ast_channel_unlock(chan);
00127 }
00128 #endif
00129 else if (!strcasecmp(data, "tonezone")) {
00130 struct tone_zone *new_zone;
00131 if (!(new_zone = ast_get_indication_zone(value))) {
00132 ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
00133 ret = -1;
00134 } else
00135 chan->zone = new_zone;
00136 } else if (!strcasecmp(data, "callgroup"))
00137 chan->callgroup = ast_get_group(value);
00138 else if (!strcasecmp(data, "txgain")) {
00139 sscanf(value, "%hhd", &gainset);
00140 ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
00141 } else if (!strcasecmp(data, "rxgain")) {
00142 sscanf(value, "%hhd", &gainset);
00143 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
00144 } else if (!strcasecmp(data, "transfercapability")) {
00145 unsigned short i;
00146 for (i = 0; i < 0x20; i++) {
00147 if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
00148 chan->transfercapability = i;
00149 break;
00150 }
00151 }
00152 } else if (!chan->tech->func_channel_write
00153 || chan->tech->func_channel_write(chan, function, data, value)) {
00154 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
00155 data);
00156 ret = -1;
00157 }
00158
00159 return ret;
00160 }
00161
00162 static struct ast_custom_function channel_function = {
00163 .name = "CHANNEL",
00164 .synopsis = "Gets/sets various pieces of information about the channel.",
00165 .syntax = "CHANNEL(item)",
00166 .desc = "Gets/set various pieces of information about the channel.\n"
00167 "Standard items (provided by all channel technologies) are:\n"
00168 "R/O audioreadformat format currently being read\n"
00169 "R/O audionativeformat format used natively for audio\n"
00170 "R/O audiowriteformat format currently being written\n"
00171 "R/W callgroup call groups for call pickup\n"
00172 "R/O channeltype technology used for channel\n"
00173 "R/W language language for sounds played\n"
00174 "R/W musicclass class (from musiconhold.conf) for hold music\n"
00175 "R/W rxgain set rxgain level on channel drivers that support it\n"
00176 "R/O state state for channel\n"
00177 "R/W tonezone zone for indications played\n"
00178 "R/W transfercapability ISDN transfer capability (one of SPEECH, DIGITAL,\n"
00179 " RESTRICTED_DIGITAL, 3K1AUDIO, DIGITAL_W_TONES, or VIDEO).\n"
00180 "R/W txgain set txgain level on channel drivers that support it\n"
00181 "R/O videonativeformat format used natively for video\n"
00182 #ifdef CHANNEL_TRACE
00183 "R/W trace whether or not context tracing is enabled\n"
00184 #endif
00185 "\n"
00186 "chan_sip provides the following additional options:\n"
00187 "R/O rtpqos Get QOS information about the RTP stream\n"
00188 " This option takes two additional arguments:\n"
00189 " Argument 1:\n"
00190 " audio Get data about the audio stream\n"
00191 " video Get data about the video stream\n"
00192 " text Get data about the text stream\n"
00193 " Argument 2:\n"
00194 " local_ssrc Local SSRC (stream ID)\n"
00195 " local_lostpackets Local lost packets\n"
00196 " local_jitter Local calculated jitter\n"
00197 " local_count Number of received packets\n"
00198 " remote_ssrc Remote SSRC (stream ID)\n"
00199 " remote_lostpackets Remote lost packets\n"
00200 " remote_jitter Remote reported jitter\n"
00201 " remote_count Number of transmitted packets\n"
00202 " rtt Round trip time\n"
00203 " all All statistics (in a form suited to logging, but not for parsing)\n"
00204 "R/O rtpdest Get remote RTP destination information\n"
00205 " This option takes one additional argument:\n"
00206 " Argument 1:\n"
00207 " audio Get audio destination\n"
00208 " video Get video destination\n"
00209 "\n"
00210 "chan_iax2 provides the following additional options:\n"
00211 "R/W osptoken Get or set the OSP token information for a call\n"
00212 "\n"
00213 "Additional items may be available from the channel driver providing\n"
00214 "the channel; see its documentation for details.\n"
00215 "\n"
00216 "Any item requested that is not available on the current channel will\n"
00217 "return an empty string.\n",
00218 .read = func_channel_read,
00219 .write = func_channel_write,
00220 };
00221
00222 static int unload_module(void)
00223 {
00224 return ast_custom_function_unregister(&channel_function);
00225 }
00226
00227 static int load_module(void)
00228 {
00229 return ast_custom_function_register(&channel_function);
00230 }
00231
00232 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel information dialplan function");