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