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