#include "asterisk.h"
#include <regex.h>
#include <ctype.h>
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/indications.h"
#include "asterisk/stringfields.h"
#include "asterisk/global_datastores.h"
Go to the source code of this file.
Defines | |
#define | locked_copy_string(chan, dest, source, len) |
#define | locked_string_field_set(chan, field, source) |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | func_channel_read (struct ast_channel *chan, const char *function, char *data, char *buf, size_t len) |
static int | func_channel_write (struct ast_channel *chan, const char *function, char *data, const char *value) |
static int | func_channel_write_real (struct ast_channel *chan, const char *function, char *data, const char *value) |
static int | func_channels_read (struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen) |
static int | func_mchan_read (struct ast_channel *chan, const char *function, char *data, struct ast_str **buf, ssize_t len) |
static int | func_mchan_write (struct ast_channel *chan, const char *function, char *data, const char *value) |
static int | load_module (void) |
static int | unload_module (void) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Channel information dialplan functions" , .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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } |
static struct ast_module_info * | ast_module_info = &__mod_info |
static struct ast_custom_function | channel_function |
static struct ast_custom_function | channels_function |
static struct ast_custom_function | mchan_function |
static const char *const | transfercapability_table [0x20] |
Ben Winslow
Definition in file func_channel.c.
#define locked_copy_string | ( | chan, | |||
dest, | |||||
source, | |||||
len | ) |
Value:
do { \ ast_channel_lock(chan); \ ast_copy_string(dest, source, len); \ ast_channel_unlock(chan); \ } while (0)
Definition at line 264 of file func_channel.c.
Referenced by func_channel_read().
#define locked_string_field_set | ( | chan, | |||
field, | |||||
source | ) |
Value:
do { \ ast_channel_lock(chan); \ ast_string_field_set(chan, field, source); \ ast_channel_unlock(chan); \ } while (0)
Definition at line 270 of file func_channel.c.
Referenced by func_channel_write_real().
static void __reg_module | ( | void | ) | [static] |
Definition at line 652 of file func_channel.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 652 of file func_channel.c.
static int func_channel_read | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 283 of file func_channel.c.
References ast_channel::_state, ast_channel::accountcode, ast_channel::amaflags, ast_channel::appl, ast_bridged_channel(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_check_hangup(), ast_copy_string(), AST_FORMAT_AUDIO_MASK, AST_FORMAT_VIDEO_MASK, ast_getformatname(), ast_log(), ast_print_group(), ast_state2str(), ast_strlen_zero(), ast_channel::callgroup, ast_channel::cdr, ast_channel::context, ast_tone_zone::country, ast_datastore::data, ast_channel::data, ast_channel::exten, ast_channel_tech::func_channel_read, ast_channel::hangupsource, ast_channel::language, ast_channel::linkedid, locked_copy_string, LOG_WARNING, ast_secure_call_store::media, ast_channel::musicclass, ast_channel::name, ast_channel::nativeformats, ast_channel::parkinglot, pbx_builtin_getvar_helper(), ast_channel::peeraccount, ast_channel::readformat, secure_call_info, ast_secure_call_store::signaling, ast_channel::tech, ast_channel::transfercapability, ast_channel_tech::type, ast_channel::uniqueid, ast_channel::userfield, ast_channel::writeformat, and ast_channel::zone.
00285 { 00286 int ret = 0; 00287 00288 if (!strcasecmp(data, "audionativeformat")) 00289 /* use the _multiple version when chan->nativeformats holds multiple formats */ 00290 /* ast_getformatname_multiple(buf, len, chan->nativeformats & AST_FORMAT_AUDIO_MASK); */ 00291 ast_copy_string(buf, ast_getformatname(chan->nativeformats & AST_FORMAT_AUDIO_MASK), len); 00292 else if (!strcasecmp(data, "videonativeformat")) 00293 /* use the _multiple version when chan->nativeformats holds multiple formats */ 00294 /* ast_getformatname_multiple(buf, len, chan->nativeformats & AST_FORMAT_VIDEO_MASK); */ 00295 ast_copy_string(buf, ast_getformatname(chan->nativeformats & AST_FORMAT_VIDEO_MASK), len); 00296 else if (!strcasecmp(data, "audioreadformat")) 00297 ast_copy_string(buf, ast_getformatname(chan->readformat), len); 00298 else if (!strcasecmp(data, "audiowriteformat")) 00299 ast_copy_string(buf, ast_getformatname(chan->writeformat), len); 00300 #ifdef CHANNEL_TRACE 00301 else if (!strcasecmp(data, "trace")) { 00302 ast_channel_lock(chan); 00303 ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len); 00304 ast_channel_unlock(chan); 00305 } 00306 #endif 00307 else if (!strcasecmp(data, "tonezone") && chan->zone) 00308 locked_copy_string(chan, buf, chan->zone->country, len); 00309 else if (!strcasecmp(data, "language")) 00310 locked_copy_string(chan, buf, chan->language, len); 00311 else if (!strcasecmp(data, "musicclass")) 00312 locked_copy_string(chan, buf, chan->musicclass, len); 00313 else if (!strcasecmp(data, "name")) { 00314 locked_copy_string(chan, buf, chan->name, len); 00315 } else if (!strcasecmp(data, "parkinglot")) 00316 locked_copy_string(chan, buf, chan->parkinglot, len); 00317 else if (!strcasecmp(data, "state")) 00318 locked_copy_string(chan, buf, ast_state2str(chan->_state), len); 00319 else if (!strcasecmp(data, "channeltype")) 00320 locked_copy_string(chan, buf, chan->tech->type, len); 00321 else if (!strcasecmp(data, "accountcode")) 00322 locked_copy_string(chan, buf, chan->accountcode, len); 00323 else if (!strcasecmp(data, "checkhangup")) { 00324 ast_channel_lock(chan); 00325 ast_copy_string(buf, ast_check_hangup(chan) ? "1" : "0", len); 00326 ast_channel_unlock(chan); 00327 } else if (!strcasecmp(data, "peeraccount")) 00328 locked_copy_string(chan, buf, chan->peeraccount, len); 00329 else if (!strcasecmp(data, "hangupsource")) 00330 locked_copy_string(chan, buf, chan->hangupsource, len); 00331 else if (!strcasecmp(data, "appname") && chan->appl) 00332 locked_copy_string(chan, buf, chan->appl, len); 00333 else if (!strcasecmp(data, "appdata") && chan->data) 00334 locked_copy_string(chan, buf, chan->data, len); 00335 else if (!strcasecmp(data, "exten") && chan->data) 00336 locked_copy_string(chan, buf, chan->exten, len); 00337 else if (!strcasecmp(data, "context") && chan->data) 00338 locked_copy_string(chan, buf, chan->context, len); 00339 else if (!strcasecmp(data, "userfield") && chan->data) 00340 locked_copy_string(chan, buf, chan->userfield, len); 00341 else if (!strcasecmp(data, "channame") && chan->data) 00342 locked_copy_string(chan, buf, chan->name, len); 00343 else if (!strcasecmp(data, "linkedid")) { 00344 ast_channel_lock(chan); 00345 if (ast_strlen_zero(chan->linkedid)) { 00346 /* fall back on the channel's uniqueid if linkedid is unset */ 00347 ast_copy_string(buf, chan->uniqueid, len); 00348 } 00349 else { 00350 ast_copy_string(buf, chan->linkedid, len); 00351 } 00352 ast_channel_unlock(chan); 00353 } else if (!strcasecmp(data, "peer")) { 00354 struct ast_channel *p; 00355 ast_channel_lock(chan); 00356 p = ast_bridged_channel(chan); 00357 if (p || chan->tech || chan->cdr) /* dummy channel? if so, we hid the peer name in the language */ 00358 ast_copy_string(buf, (p ? p->name : ""), len); 00359 else { 00360 /* a dummy channel can still pass along bridged peer info via 00361 the BRIDGEPEER variable */ 00362 const char *pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER"); 00363 if (!ast_strlen_zero(pname)) 00364 ast_copy_string(buf, pname, len); /* a horrible kludge, but... how else? */ 00365 else 00366 buf[0] = 0; 00367 } 00368 ast_channel_unlock(chan); 00369 } else if (!strcasecmp(data, "uniqueid")) { 00370 locked_copy_string(chan, buf, chan->uniqueid, len); 00371 } else if (!strcasecmp(data, "transfercapability")) 00372 locked_copy_string(chan, buf, transfercapability_table[chan->transfercapability & 0x1f], len); 00373 else if (!strcasecmp(data, "callgroup")) { 00374 char groupbuf[256]; 00375 locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), chan->callgroup), len); 00376 } else if (!strcasecmp(data, "amaflags")) { 00377 char amabuf[256]; 00378 snprintf(amabuf,sizeof(amabuf), "%d", chan->amaflags); 00379 locked_copy_string(chan, buf, amabuf, len); 00380 } else if (!strncasecmp(data, "secure_bridge_", 14)) { 00381 struct ast_datastore *ds; 00382 ast_channel_lock(chan); 00383 if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) { 00384 struct ast_secure_call_store *encrypt = ds->data; 00385 if (!strcasecmp(data, "secure_bridge_signaling")) { 00386 snprintf(buf, len, "%s", encrypt->signaling ? "1" : ""); 00387 } else if (!strcasecmp(data, "secure_bridge_media")) { 00388 snprintf(buf, len, "%s", encrypt->media ? "1" : ""); 00389 } 00390 } 00391 ast_channel_unlock(chan); 00392 } else if (!chan->tech || !chan->tech->func_channel_read || chan->tech->func_channel_read(chan, function, data, buf, len)) { 00393 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data); 00394 ret = -1; 00395 } 00396 00397 return ret; 00398 }
static int func_channel_write | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 518 of file func_channel.c.
References AST_CHAN_WRITE_INFO_T_VERSION, ast_channel_setoption(), AST_OPTION_CHANNEL_WRITE, ast_channel::data, and func_channel_write_real().
00519 { 00520 int res; 00521 ast_chan_write_info_t write_info = { 00522 .version = AST_CHAN_WRITE_INFO_T_VERSION, 00523 .write_fn = func_channel_write_real, 00524 .chan = chan, 00525 .function = function, 00526 .data = data, 00527 .value = value, 00528 }; 00529 00530 res = func_channel_write_real(chan, function, data, value); 00531 ast_channel_setoption(chan, AST_OPTION_CHANNEL_WRITE, &write_info, sizeof(write_info), 0); 00532 00533 return res; 00534 }
static int func_channel_write_real | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 400 of file func_channel.c.
References accountcode, ast_channel::amaflags, ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_setoption(), ast_channel_unlock, ast_datastore_alloc, ast_false(), ast_free, ast_get_group(), ast_get_indication_zone(), ast_log(), AST_OPTION_RXGAIN, AST_OPTION_TXGAIN, ast_set_hangupsource(), ast_tone_zone_ref(), ast_tone_zone_unref(), ast_true(), ast_channel::callgroup, ast_channel_tech::func_channel_write, language, locked_string_field_set, LOG_ERROR, LOG_WARNING, ast_secure_call_store::media, musicclass, parkinglot, secure_call_info, ast_secure_call_store::signaling, ast_channel::tech, ast_channel::transfercapability, and ast_channel::zone.
Referenced by func_channel_write().
00402 { 00403 int ret = 0; 00404 signed char gainset; 00405 00406 if (!strcasecmp(data, "language")) 00407 locked_string_field_set(chan, language, value); 00408 else if (!strcasecmp(data, "parkinglot")) 00409 locked_string_field_set(chan, parkinglot, value); 00410 else if (!strcasecmp(data, "musicclass")) 00411 locked_string_field_set(chan, musicclass, value); 00412 else if (!strcasecmp(data, "accountcode")) 00413 locked_string_field_set(chan, accountcode, value); 00414 else if (!strcasecmp(data, "userfield")) 00415 locked_string_field_set(chan, userfield, value); 00416 else if (!strcasecmp(data, "amaflags")) { 00417 ast_channel_lock(chan); 00418 if(isdigit(*value)) { 00419 sscanf(value, "%30d", &chan->amaflags); 00420 } else if (!strcasecmp(value,"OMIT")){ 00421 chan->amaflags = 1; 00422 } else if (!strcasecmp(value,"BILLING")){ 00423 chan->amaflags = 2; 00424 } else if (!strcasecmp(value,"DOCUMENTATION")){ 00425 chan->amaflags = 3; 00426 } 00427 ast_channel_unlock(chan); 00428 } else if (!strcasecmp(data, "peeraccount")) 00429 locked_string_field_set(chan, peeraccount, value); 00430 else if (!strcasecmp(data, "hangupsource")) 00431 /* XXX - should we be forcing this here? */ 00432 ast_set_hangupsource(chan, value, 0); 00433 #ifdef CHANNEL_TRACE 00434 else if (!strcasecmp(data, "trace")) { 00435 ast_channel_lock(chan); 00436 if (ast_true(value)) 00437 ret = ast_channel_trace_enable(chan); 00438 else if (ast_false(value)) 00439 ret = ast_channel_trace_disable(chan); 00440 else { 00441 ret = -1; 00442 ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace)."); 00443 } 00444 ast_channel_unlock(chan); 00445 } 00446 #endif 00447 else if (!strcasecmp(data, "tonezone")) { 00448 struct ast_tone_zone *new_zone; 00449 if (!(new_zone = ast_get_indication_zone(value))) { 00450 ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value); 00451 ret = -1; 00452 } else { 00453 ast_channel_lock(chan); 00454 if (chan->zone) { 00455 chan->zone = ast_tone_zone_unref(chan->zone); 00456 } 00457 chan->zone = ast_tone_zone_ref(new_zone); 00458 ast_channel_unlock(chan); 00459 new_zone = ast_tone_zone_unref(new_zone); 00460 } 00461 } else if (!strcasecmp(data, "callgroup")) 00462 chan->callgroup = ast_get_group(value); 00463 else if (!strcasecmp(data, "txgain")) { 00464 sscanf(value, "%4hhd", &gainset); 00465 ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0); 00466 } else if (!strcasecmp(data, "rxgain")) { 00467 sscanf(value, "%4hhd", &gainset); 00468 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0); 00469 } else if (!strcasecmp(data, "transfercapability")) { 00470 unsigned short i; 00471 for (i = 0; i < 0x20; i++) { 00472 if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) { 00473 chan->transfercapability = i; 00474 break; 00475 } 00476 } 00477 } else if (!strncasecmp(data, "secure_bridge_", 14)) { 00478 struct ast_datastore *ds; 00479 struct ast_secure_call_store *store; 00480 00481 if (!chan || !value) { 00482 return -1; 00483 } 00484 00485 ast_channel_lock(chan); 00486 if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) { 00487 if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) { 00488 ast_channel_unlock(chan); 00489 return -1; 00490 } 00491 if (!(store = ast_calloc(1, sizeof(*store)))) { 00492 ast_channel_unlock(chan); 00493 ast_free(ds); 00494 return -1; 00495 } 00496 ds->data = store; 00497 ast_channel_datastore_add(chan, ds); 00498 } else { 00499 store = ds->data; 00500 } 00501 ast_channel_unlock(chan); 00502 00503 if (!strcasecmp(data, "secure_bridge_signaling")) { 00504 store->signaling = ast_true(value) ? 1 : 0; 00505 } else if (!strcasecmp(data, "secure_bridge_media")) { 00506 store->media = ast_true(value) ? 1 : 0; 00507 } 00508 } else if (!chan->tech->func_channel_write 00509 || chan->tech->func_channel_write(chan, function, data, value)) { 00510 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", 00511 data); 00512 ret = -1; 00513 } 00514 00515 return ret; 00516 }
static int func_channels_read | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
char * | buf, | |||
size_t | maxlen | |||
) | [static] |
Definition at line 542 of file func_channel.c.
References ast_channel_iterator_all_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_log(), ast_strlen_zero(), and LOG_WARNING.
00543 { 00544 struct ast_channel *c = NULL; 00545 regex_t re; 00546 int res; 00547 size_t buflen = 0; 00548 struct ast_channel_iterator *iter; 00549 00550 buf[0] = '\0'; 00551 00552 if (!ast_strlen_zero(data)) { 00553 if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) { 00554 regerror(res, &re, buf, maxlen); 00555 ast_log(LOG_WARNING, "Error compiling regular expression for %s(%s): %s\n", function, data, buf); 00556 return -1; 00557 } 00558 } 00559 00560 if (!(iter = ast_channel_iterator_all_new())) { 00561 if (!ast_strlen_zero(data)) { 00562 regfree(&re); 00563 } 00564 return -1; 00565 } 00566 00567 while ((c = ast_channel_iterator_next(iter))) { 00568 ast_channel_lock(c); 00569 if (ast_strlen_zero(data) || regexec(&re, c->name, 0, NULL, 0) == 0) { 00570 size_t namelen = strlen(c->name); 00571 if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) { 00572 if (!ast_strlen_zero(buf)) { 00573 strcat(buf, " "); 00574 buflen++; 00575 } 00576 strcat(buf, c->name); 00577 buflen += namelen; 00578 } else { 00579 ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space. Output will be truncated!\n"); 00580 } 00581 } 00582 ast_channel_unlock(c); 00583 c = ast_channel_unref(c); 00584 } 00585 00586 ast_channel_iterator_destroy(iter); 00587 00588 if (!ast_strlen_zero(data)) { 00589 regfree(&re); 00590 } 00591 00592 return 0; 00593 }
static int func_mchan_read | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
struct ast_str ** | buf, | |||
ssize_t | len | |||
) | [static] |
Definition at line 600 of file func_channel.c.
References ast_channel_get_by_name(), ast_channel_unref, ast_str_substitute_variables(), and ast_channel::linkedid.
00602 { 00603 struct ast_channel *mchan = ast_channel_get_by_name(chan->linkedid); 00604 char *template = alloca(4 + strlen(data)); 00605 sprintf(template, "${%s}", data); /* SAFE */ 00606 ast_str_substitute_variables(buf, len, mchan ? mchan : chan, template); 00607 if (mchan) { 00608 ast_channel_unref(mchan); 00609 } 00610 return 0; 00611 }
static int func_mchan_write | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 613 of file func_channel.c.
References ast_channel_get_by_name(), ast_channel_unref, ast_channel::linkedid, and pbx_builtin_setvar_helper().
00615 { 00616 struct ast_channel *mchan = ast_channel_get_by_name(chan->linkedid); 00617 pbx_builtin_setvar_helper(mchan ? mchan : chan, data, value); 00618 if (mchan) { 00619 ast_channel_unref(mchan); 00620 } 00621 return 0; 00622 }
static int load_module | ( | void | ) | [static] |
Definition at line 641 of file func_channel.c.
References ast_custom_function_register, channel_function, channels_function, and mchan_function.
00642 { 00643 int res = 0; 00644 00645 res |= ast_custom_function_register(&channel_function); 00646 res |= ast_custom_function_register(&channels_function); 00647 res |= ast_custom_function_register(&mchan_function); 00648 00649 return res; 00650 }
static int unload_module | ( | void | ) | [static] |
Definition at line 630 of file func_channel.c.
References ast_custom_function_unregister(), channel_function, channels_function, and mchan_function.
00631 { 00632 int res = 0; 00633 00634 res |= ast_custom_function_unregister(&channel_function); 00635 res |= ast_custom_function_unregister(&channels_function); 00636 res |= ast_custom_function_unregister(&mchan_function); 00637 00638 return res; 00639 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Channel information dialplan functions" , .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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static] |
Definition at line 652 of file func_channel.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 652 of file func_channel.c.
struct ast_custom_function channel_function [static] |
Initial value:
{ .name = "CHANNEL", .read = func_channel_read, .write = func_channel_write, }
Definition at line 536 of file func_channel.c.
Referenced by load_module(), and unload_module().
struct ast_custom_function channels_function [static] |
Initial value:
{ .name = "CHANNELS", .read = func_channels_read, }
Definition at line 595 of file func_channel.c.
Referenced by load_module(), and unload_module().
struct ast_custom_function mchan_function [static] |
Initial value:
{ .name = "MASTER_CHANNEL", .read2 = func_mchan_read, .write = func_mchan_write, }
Definition at line 624 of file func_channel.c.
Referenced by load_module(), and unload_module().
const char* const transfercapability_table[0x20] [static] |
Initial value:
{ "SPEECH", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "DIGITAL", "RESTRICTED_DIGITAL", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "3K1AUDIO", "DIGITAL_W_TONES", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "VIDEO", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", "UNK", }
Definition at line 277 of file func_channel.c.