#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 = "ac1f6a56484a8820659555499174e588" , .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 284 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 290 of file func_channel.c.
Referenced by func_channel_write_real().
static void __reg_module | ( | void | ) | [static] |
Definition at line 672 of file func_channel.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 672 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 303 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.
00305 { 00306 int ret = 0; 00307 00308 if (!strcasecmp(data, "audionativeformat")) 00309 /* use the _multiple version when chan->nativeformats holds multiple formats */ 00310 /* ast_getformatname_multiple(buf, len, chan->nativeformats & AST_FORMAT_AUDIO_MASK); */ 00311 ast_copy_string(buf, ast_getformatname(chan->nativeformats & AST_FORMAT_AUDIO_MASK), len); 00312 else if (!strcasecmp(data, "videonativeformat")) 00313 /* use the _multiple version when chan->nativeformats holds multiple formats */ 00314 /* ast_getformatname_multiple(buf, len, chan->nativeformats & AST_FORMAT_VIDEO_MASK); */ 00315 ast_copy_string(buf, ast_getformatname(chan->nativeformats & AST_FORMAT_VIDEO_MASK), len); 00316 else if (!strcasecmp(data, "audioreadformat")) 00317 ast_copy_string(buf, ast_getformatname(chan->readformat), len); 00318 else if (!strcasecmp(data, "audiowriteformat")) 00319 ast_copy_string(buf, ast_getformatname(chan->writeformat), len); 00320 #ifdef CHANNEL_TRACE 00321 else if (!strcasecmp(data, "trace")) { 00322 ast_channel_lock(chan); 00323 ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len); 00324 ast_channel_unlock(chan); 00325 } 00326 #endif 00327 else if (!strcasecmp(data, "tonezone") && chan->zone) 00328 locked_copy_string(chan, buf, chan->zone->country, len); 00329 else if (!strcasecmp(data, "language")) 00330 locked_copy_string(chan, buf, chan->language, len); 00331 else if (!strcasecmp(data, "musicclass")) 00332 locked_copy_string(chan, buf, chan->musicclass, len); 00333 else if (!strcasecmp(data, "name")) { 00334 locked_copy_string(chan, buf, chan->name, len); 00335 } else if (!strcasecmp(data, "parkinglot")) 00336 locked_copy_string(chan, buf, chan->parkinglot, len); 00337 else if (!strcasecmp(data, "state")) 00338 locked_copy_string(chan, buf, ast_state2str(chan->_state), len); 00339 else if (!strcasecmp(data, "channeltype")) 00340 locked_copy_string(chan, buf, chan->tech->type, len); 00341 else if (!strcasecmp(data, "accountcode")) 00342 locked_copy_string(chan, buf, chan->accountcode, len); 00343 else if (!strcasecmp(data, "checkhangup")) { 00344 ast_channel_lock(chan); 00345 ast_copy_string(buf, ast_check_hangup(chan) ? "1" : "0", len); 00346 ast_channel_unlock(chan); 00347 } else if (!strcasecmp(data, "peeraccount")) 00348 locked_copy_string(chan, buf, chan->peeraccount, len); 00349 else if (!strcasecmp(data, "hangupsource")) 00350 locked_copy_string(chan, buf, chan->hangupsource, len); 00351 else if (!strcasecmp(data, "appname") && chan->appl) 00352 locked_copy_string(chan, buf, chan->appl, len); 00353 else if (!strcasecmp(data, "appdata") && chan->data) 00354 locked_copy_string(chan, buf, chan->data, len); 00355 else if (!strcasecmp(data, "exten") && chan->data) 00356 locked_copy_string(chan, buf, chan->exten, len); 00357 else if (!strcasecmp(data, "context") && chan->data) 00358 locked_copy_string(chan, buf, chan->context, len); 00359 else if (!strcasecmp(data, "userfield") && chan->data) 00360 locked_copy_string(chan, buf, chan->userfield, len); 00361 else if (!strcasecmp(data, "channame") && chan->data) 00362 locked_copy_string(chan, buf, chan->name, len); 00363 else if (!strcasecmp(data, "linkedid")) { 00364 ast_channel_lock(chan); 00365 if (ast_strlen_zero(chan->linkedid)) { 00366 /* fall back on the channel's uniqueid if linkedid is unset */ 00367 ast_copy_string(buf, chan->uniqueid, len); 00368 } 00369 else { 00370 ast_copy_string(buf, chan->linkedid, len); 00371 } 00372 ast_channel_unlock(chan); 00373 } else if (!strcasecmp(data, "peer")) { 00374 struct ast_channel *p; 00375 ast_channel_lock(chan); 00376 p = ast_bridged_channel(chan); 00377 if (p || chan->tech || chan->cdr) /* dummy channel? if so, we hid the peer name in the language */ 00378 ast_copy_string(buf, (p ? p->name : ""), len); 00379 else { 00380 /* a dummy channel can still pass along bridged peer info via 00381 the BRIDGEPEER variable */ 00382 const char *pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER"); 00383 if (!ast_strlen_zero(pname)) 00384 ast_copy_string(buf, pname, len); /* a horrible kludge, but... how else? */ 00385 else 00386 buf[0] = 0; 00387 } 00388 ast_channel_unlock(chan); 00389 } else if (!strcasecmp(data, "uniqueid")) { 00390 locked_copy_string(chan, buf, chan->uniqueid, len); 00391 } else if (!strcasecmp(data, "transfercapability")) 00392 locked_copy_string(chan, buf, transfercapability_table[chan->transfercapability & 0x1f], len); 00393 else if (!strcasecmp(data, "callgroup")) { 00394 char groupbuf[256]; 00395 locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), chan->callgroup), len); 00396 } else if (!strcasecmp(data, "amaflags")) { 00397 char amabuf[256]; 00398 snprintf(amabuf,sizeof(amabuf), "%d", chan->amaflags); 00399 locked_copy_string(chan, buf, amabuf, len); 00400 } else if (!strncasecmp(data, "secure_bridge_", 14)) { 00401 struct ast_datastore *ds; 00402 ast_channel_lock(chan); 00403 if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) { 00404 struct ast_secure_call_store *encrypt = ds->data; 00405 if (!strcasecmp(data, "secure_bridge_signaling")) { 00406 snprintf(buf, len, "%s", encrypt->signaling ? "1" : ""); 00407 } else if (!strcasecmp(data, "secure_bridge_media")) { 00408 snprintf(buf, len, "%s", encrypt->media ? "1" : ""); 00409 } 00410 } 00411 ast_channel_unlock(chan); 00412 } else if (!chan->tech || !chan->tech->func_channel_read || chan->tech->func_channel_read(chan, function, data, buf, len)) { 00413 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data); 00414 ret = -1; 00415 } 00416 00417 return ret; 00418 }
static int func_channel_write | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 538 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().
00539 { 00540 int res; 00541 ast_chan_write_info_t write_info = { 00542 .version = AST_CHAN_WRITE_INFO_T_VERSION, 00543 .write_fn = func_channel_write_real, 00544 .chan = chan, 00545 .function = function, 00546 .data = data, 00547 .value = value, 00548 }; 00549 00550 res = func_channel_write_real(chan, function, data, value); 00551 ast_channel_setoption(chan, AST_OPTION_CHANNEL_WRITE, &write_info, sizeof(write_info), 0); 00552 00553 return res; 00554 }
static int func_channel_write_real | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 420 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().
00422 { 00423 int ret = 0; 00424 signed char gainset; 00425 00426 if (!strcasecmp(data, "language")) 00427 locked_string_field_set(chan, language, value); 00428 else if (!strcasecmp(data, "parkinglot")) 00429 locked_string_field_set(chan, parkinglot, value); 00430 else if (!strcasecmp(data, "musicclass")) 00431 locked_string_field_set(chan, musicclass, value); 00432 else if (!strcasecmp(data, "accountcode")) 00433 locked_string_field_set(chan, accountcode, value); 00434 else if (!strcasecmp(data, "userfield")) 00435 locked_string_field_set(chan, userfield, value); 00436 else if (!strcasecmp(data, "amaflags")) { 00437 ast_channel_lock(chan); 00438 if(isdigit(*value)) { 00439 sscanf(value, "%30d", &chan->amaflags); 00440 } else if (!strcasecmp(value,"OMIT")){ 00441 chan->amaflags = 1; 00442 } else if (!strcasecmp(value,"BILLING")){ 00443 chan->amaflags = 2; 00444 } else if (!strcasecmp(value,"DOCUMENTATION")){ 00445 chan->amaflags = 3; 00446 } 00447 ast_channel_unlock(chan); 00448 } else if (!strcasecmp(data, "peeraccount")) 00449 locked_string_field_set(chan, peeraccount, value); 00450 else if (!strcasecmp(data, "hangupsource")) 00451 /* XXX - should we be forcing this here? */ 00452 ast_set_hangupsource(chan, value, 0); 00453 #ifdef CHANNEL_TRACE 00454 else if (!strcasecmp(data, "trace")) { 00455 ast_channel_lock(chan); 00456 if (ast_true(value)) 00457 ret = ast_channel_trace_enable(chan); 00458 else if (ast_false(value)) 00459 ret = ast_channel_trace_disable(chan); 00460 else { 00461 ret = -1; 00462 ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace).\n"); 00463 } 00464 ast_channel_unlock(chan); 00465 } 00466 #endif 00467 else if (!strcasecmp(data, "tonezone")) { 00468 struct ast_tone_zone *new_zone; 00469 if (!(new_zone = ast_get_indication_zone(value))) { 00470 ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value); 00471 ret = -1; 00472 } else { 00473 ast_channel_lock(chan); 00474 if (chan->zone) { 00475 chan->zone = ast_tone_zone_unref(chan->zone); 00476 } 00477 chan->zone = ast_tone_zone_ref(new_zone); 00478 ast_channel_unlock(chan); 00479 new_zone = ast_tone_zone_unref(new_zone); 00480 } 00481 } else if (!strcasecmp(data, "callgroup")) 00482 chan->callgroup = ast_get_group(value); 00483 else if (!strcasecmp(data, "txgain")) { 00484 sscanf(value, "%4hhd", &gainset); 00485 ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0); 00486 } else if (!strcasecmp(data, "rxgain")) { 00487 sscanf(value, "%4hhd", &gainset); 00488 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0); 00489 } else if (!strcasecmp(data, "transfercapability")) { 00490 unsigned short i; 00491 for (i = 0; i < 0x20; i++) { 00492 if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) { 00493 chan->transfercapability = i; 00494 break; 00495 } 00496 } 00497 } else if (!strncasecmp(data, "secure_bridge_", 14)) { 00498 struct ast_datastore *ds; 00499 struct ast_secure_call_store *store; 00500 00501 if (!chan || !value) { 00502 return -1; 00503 } 00504 00505 ast_channel_lock(chan); 00506 if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) { 00507 if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) { 00508 ast_channel_unlock(chan); 00509 return -1; 00510 } 00511 if (!(store = ast_calloc(1, sizeof(*store)))) { 00512 ast_channel_unlock(chan); 00513 ast_free(ds); 00514 return -1; 00515 } 00516 ds->data = store; 00517 ast_channel_datastore_add(chan, ds); 00518 } else { 00519 store = ds->data; 00520 } 00521 ast_channel_unlock(chan); 00522 00523 if (!strcasecmp(data, "secure_bridge_signaling")) { 00524 store->signaling = ast_true(value) ? 1 : 0; 00525 } else if (!strcasecmp(data, "secure_bridge_media")) { 00526 store->media = ast_true(value) ? 1 : 0; 00527 } 00528 } else if (!chan->tech->func_channel_write 00529 || chan->tech->func_channel_write(chan, function, data, value)) { 00530 ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", 00531 data); 00532 ret = -1; 00533 } 00534 00535 return ret; 00536 }
static int func_channels_read | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
char * | buf, | |||
size_t | maxlen | |||
) | [static] |
Definition at line 562 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.
00563 { 00564 struct ast_channel *c = NULL; 00565 regex_t re; 00566 int res; 00567 size_t buflen = 0; 00568 struct ast_channel_iterator *iter; 00569 00570 buf[0] = '\0'; 00571 00572 if (!ast_strlen_zero(data)) { 00573 if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) { 00574 regerror(res, &re, buf, maxlen); 00575 ast_log(LOG_WARNING, "Error compiling regular expression for %s(%s): %s\n", function, data, buf); 00576 return -1; 00577 } 00578 } 00579 00580 if (!(iter = ast_channel_iterator_all_new())) { 00581 if (!ast_strlen_zero(data)) { 00582 regfree(&re); 00583 } 00584 return -1; 00585 } 00586 00587 while ((c = ast_channel_iterator_next(iter))) { 00588 ast_channel_lock(c); 00589 if (ast_strlen_zero(data) || regexec(&re, c->name, 0, NULL, 0) == 0) { 00590 size_t namelen = strlen(c->name); 00591 if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) { 00592 if (!ast_strlen_zero(buf)) { 00593 strcat(buf, " "); 00594 buflen++; 00595 } 00596 strcat(buf, c->name); 00597 buflen += namelen; 00598 } else { 00599 ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space. Output will be truncated!\n"); 00600 } 00601 } 00602 ast_channel_unlock(c); 00603 c = ast_channel_unref(c); 00604 } 00605 00606 ast_channel_iterator_destroy(iter); 00607 00608 if (!ast_strlen_zero(data)) { 00609 regfree(&re); 00610 } 00611 00612 return 0; 00613 }
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 620 of file func_channel.c.
References ast_channel_get_by_name(), ast_channel_unref, ast_str_substitute_variables(), and ast_channel::linkedid.
00622 { 00623 struct ast_channel *mchan = ast_channel_get_by_name(chan->linkedid); 00624 char *template = alloca(4 + strlen(data)); 00625 sprintf(template, "${%s}", data); /* SAFE */ 00626 ast_str_substitute_variables(buf, len, mchan ? mchan : chan, template); 00627 if (mchan) { 00628 ast_channel_unref(mchan); 00629 } 00630 return 0; 00631 }
static int func_mchan_write | ( | struct ast_channel * | chan, | |
const char * | function, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 633 of file func_channel.c.
References ast_channel_get_by_name(), ast_channel_unref, ast_channel::linkedid, and pbx_builtin_setvar_helper().
00635 { 00636 struct ast_channel *mchan = ast_channel_get_by_name(chan->linkedid); 00637 pbx_builtin_setvar_helper(mchan ? mchan : chan, data, value); 00638 if (mchan) { 00639 ast_channel_unref(mchan); 00640 } 00641 return 0; 00642 }
static int load_module | ( | void | ) | [static] |
Definition at line 661 of file func_channel.c.
References ast_custom_function_register, channel_function, channels_function, and mchan_function.
00662 { 00663 int res = 0; 00664 00665 res |= ast_custom_function_register(&channel_function); 00666 res |= ast_custom_function_register(&channels_function); 00667 res |= ast_custom_function_register(&mchan_function); 00668 00669 return res; 00670 }
static int unload_module | ( | void | ) | [static] |
Definition at line 650 of file func_channel.c.
References ast_custom_function_unregister(), channel_function, channels_function, and mchan_function.
00651 { 00652 int res = 0; 00653 00654 res |= ast_custom_function_unregister(&channel_function); 00655 res |= ast_custom_function_unregister(&channels_function); 00656 res |= ast_custom_function_unregister(&mchan_function); 00657 00658 return res; 00659 }
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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static] |
Definition at line 672 of file func_channel.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 672 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 556 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 615 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 644 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 297 of file func_channel.c.