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