44#include <netinet/in.h>
56static const char app[] =
"ADSIProg";
103 { 15,
"DISTINCTIVERING" },
105 { 17,
"REMINDERRING" },
106 { 18,
"SPECIALRING" },
122#define STATE_NORMAL 0
127#define MAX_RET_CODE 20
128#define MAX_SUB_LEN 255
129#define MAX_MAIN_LEN 1600
131#define ARG_STRING (1 << 0)
132#define ARG_NUMBER (1 << 1)
201 if ((strlen(src) > 1) && src[0] ==
'\"') {
207 if (maxlen > strlen(src) - 1)
208 maxlen = strlen(src) - 1;
209 memcpy(
out, src, maxlen);
210 ((
char *)
out)[maxlen] =
'\0';
215 if (sscanf(src,
"%30o", (
unsigned *)
out) != 1)
219 *((
unsigned int *)
out) = htonl(*((
unsigned int *)
out));
221 }
else if ((strlen(src) > 2) && (src[0] ==
'0') && (tolower(src[1]) ==
'x')) {
225 if (sscanf(src + 2,
"%30x", (
unsigned int *)
out) != 1)
229 *((
unsigned int *)
out) = htonl(*((
unsigned int *)
out));
235 if (sscanf(src,
"%30d", (
int *)
out) != 1)
239 *((
unsigned int *)
out) = htonl(*((
unsigned int *)
out));
248 char *tmp = *
buf, *keyword;
252 while(*tmp && (*tmp < 33))
257 while(*tmp && ((*tmp > 32) || quoted)) {
269 while(*tmp && (*tmp < 33))
280 char dtmfstr[80], *
a;
284 ast_log(
LOG_WARNING,
"Expecting something to send for SENDDTMF at line %d of %s\n", lineno, script);
289 ast_log(
LOG_WARNING,
"Invalid token for SENDDTMF at line %d of %s\n", lineno, script);
301 ast_log(
LOG_WARNING,
"'%c' is not a valid DTMF tone at line %d of %s\n", *
a, lineno, script);
315 if (!page || !gline) {
316 ast_log(
LOG_WARNING,
"Expecting page and line number for GOTOLINE at line %d of %s\n", lineno, script);
320 if (!strcasecmp(page,
"INFO"))
322 else if (!strcasecmp(page,
"COMM"))
325 ast_log(
LOG_WARNING,
"Expecting either 'INFO' or 'COMM' page, got '%s' at line %d of %s\n", page, lineno, script);
330 ast_log(
LOG_WARNING,
"Invalid line number '%s' at line %d of %s\n", gline, lineno, script);
348 if (!dir || !gline) {
349 ast_log(
LOG_WARNING,
"Expecting direction and number of lines for GOTOLINEREL at line %d of %s\n", lineno, script);
353 if (!strcasecmp(dir,
"UP"))
355 else if (!strcasecmp(dir,
"DOWN"))
358 ast_log(
LOG_WARNING,
"Expecting either 'UP' or 'DOWN' direction, got '%s' at line %d of %s\n", dir, lineno, script);
363 ast_log(
LOG_WARNING,
"Invalid line number '%s' at line %d of %s\n", gline, lineno, script);
380 ast_log(
LOG_WARNING,
"Expecting number of milliseconds to wait at line %d of %s\n", lineno, script);
385 ast_log(
LOG_WARNING,
"Invalid delay milliseconds '%s' at line %d of %s\n", gtime, lineno, script);
410 ast_log(
LOG_WARNING,
"Invalid state number '%s' at line %d of %s\n", gstate, lineno, script);
425 ast_log(
LOG_WARNING,
"Clearing timer requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
442 for (x = 0; x <
state->numflags; x++) {
443 if (!strcasecmp(
state->flags[x].vname,
name))
444 return &
state->flags[x];
451 if (
state->numflags > 6) {
470 ast_log(
LOG_WARNING,
"Setting flag requires a flag number at line %d of %s\n", lineno, script);
480 ast_log(
LOG_WARNING,
"Flag '%s' is undeclared at line %d of %s\n", sname, lineno, script);
485 buf[1] = ((
flag->id & 0x7) << 4) | 1;
497 ast_log(
LOG_WARNING,
"Clearing flag requires a flag number at line %d of %s\n", lineno, script);
507 ast_log(
LOG_WARNING,
"Flag '%s' is undeclared at line %d of %s\n", sname, lineno, script);
512 buf[1] = ((
flag->id & 0x7) << 4);
528 ast_log(
LOG_WARNING,
"Invalid number of seconds '%s' at line %d of %s\n", tok, lineno, script);
567 for (x = 0; x <
state->numkeys; x++) {
568 if (!strcasecmp(
state->keys[x].vname,
name))
569 return &
state->keys[x];
572 if (
state->numkeys > 61) {
588 for (x = 0; x <
state->numsubs; x++) {
589 if (!strcasecmp(
state->subs[x].vname,
name))
590 return &
state->subs[x];
593 if (
state->numsubs > 127) {
609 for (x = 0; x <
state->numstates; x++) {
610 if (!strcasecmp(
state->states[x].vname,
name))
611 return &
state->states[x];
618 if (
state->numstates > 253) {
634 for (x = 0; x <
state->numdisplays; x++) {
635 if (!strcasecmp(
state->displays[x].vname,
name))
636 return &
state->displays[x];
643 if (
state->numdisplays > 61) {
650 state->numdisplays++;
652 return &
state->displays[
state->numdisplays-1];
657 char *tok, newkey[80];
658 int bytes, x, flagid = 0;
659 unsigned char keyid[6];
663 for (x = 0; x < 7; x++) {
667 if (!strcasecmp(tok,
"UNLESS")) {
670 ast_log(
LOG_WARNING,
"Missing argument for UNLESS clause at line %d of %s\n", lineno, script);
672 ast_log(
LOG_WARNING,
"Invalid flag name '%s' at line %d of %s\n", tok, lineno, script);
674 ast_log(
LOG_WARNING,
"Flag '%s' is undeclared at line %d of %s\n", newkey, lineno, script);
678 ast_log(
LOG_WARNING,
"Extra arguments after UNLESS clause: '%s' at line %d of %s\n", tok, lineno, script);
682 ast_log(
LOG_WARNING,
"Only 6 keys can be defined, ignoring '%s' at line %d of %s\n", tok, lineno, script);
695 buf[1] = (flagid & 0x7) << 3 | (x & 0x7);
696 for (bytes = 0; bytes < x; bytes++)
697 buf[bytes + 2] = keyid[bytes];
704 char *tok, dispname[80];
705 int line = 0,
flag = 0, cmd = 3;
710 ast_log(
LOG_WARNING,
"Invalid display name: %s at line %d of %s\n", tok ? tok :
"<nothing>", lineno, script);
715 ast_log(
LOG_WARNING,
"Display '%s' is undefined at line %d of %s\n", dispname, lineno, script);
719 if (!(tok =
get_token(&
args, script, lineno)) || strcasecmp(tok,
"AT")) {
726 ast_log(
LOG_WARNING,
"Invalid line: '%s' at line %d of %s\n", tok ? tok :
"<nothing>", lineno, script);
730 if ((tok =
get_token(&
args, script, lineno)) && !strcasecmp(tok,
"NOUPDATE")) {
735 if (tok && !strcasecmp(tok,
"UNLESS")) {
738 ast_log(
LOG_WARNING,
"Missing argument for UNLESS clause at line %d of %s\n", lineno, script);
740 ast_log(
LOG_WARNING,
"Invalid flag number '%s' at line %d of %s\n", tok, lineno, script);
743 ast_log(
LOG_WARNING,
"Extra arguments after UNLESS clause: '%s' at line %d of %s\n", tok, lineno, script);
747 buf[1] = (cmd << 6) | (disp->
id & 0x3f);
748 buf[2] = ((line & 0x1f) << 3) | (
flag & 0x7);
758 ast_log(
LOG_WARNING,
"Clearing display requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
770 ast_log(
LOG_WARNING,
"Digitdirect requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
782 ast_log(
LOG_WARNING,
"CLEARCB1 requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
794 ast_log(
LOG_WARNING,
"Digitcollect requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
813 ast_log(
LOG_WARNING,
"Invalid number of seconds '%s' at line %d of %s\n", tok, lineno, script);
829 char subscr[80], sname[80];
830 int sawin = 0,
event, snums[8], scnt = 0, x;
834 ast_log(
LOG_WARNING,
"Missing event for 'ONEVENT' at line %d of %s\n", lineno, script);
844 while ((!sawin && !strcasecmp(tok,
"IN")) || (sawin && !strcasecmp(tok,
"OR"))) {
847 ast_log(
LOG_WARNING,
"No more than 8 states may be specified for inclusion at line %d of %s\n", lineno, script);
853 ast_log(
LOG_WARNING,
"'%s' is not a valid state name at line %d of %s\n", tok, lineno, script);
857 ast_log(
LOG_WARNING,
"State '%s' not declared at line %d of %s\n", sname, lineno, script);
864 if (!tok || strcasecmp(tok,
"GOTO")) {
868 ast_log(
LOG_WARNING,
"Got '%s' while looking for 'GOTO' or 'OR' at line %d of %s\n", tok, lineno, script);
870 ast_log(
LOG_WARNING,
"Got '%s' while looking for 'GOTO' or 'IN' at line %d of %s\n", tok, lineno, script);
877 ast_log(
LOG_WARNING,
"Invalid subscript '%s' at line %d of %s\n", tok, lineno, script);
885 for (x = 0; x < scnt; x++)
886 buf[3 + x] = snums[x];
902 {
"WAITDIALTONE", 0x84 },
905 {
"SENDCHARS", 0x87 },
906 {
"CLEARCHARS", 0x88 },
907 {
"BACKSPACE", 0x89 },
912 {
"PAGEDOWN", 0x8e },
915 {
"DIALPULSEONE", 0x91 },
916 {
"DATAMODE", 0x92 },
917 {
"VOICEMODE", 0x93 },
997 if ((
sub->datalen + res + 1) <=
max)
1006 if ((
sub->datalen + 2) <=
max) {
1015 sub->data[
sub->datalen] = 0xff;
1027 char *
args, vname[256], tmp[80], tmp2[80];
1028 int lrci, wi,
event;
1035 switch(
state->state) {
1037 if (!strcasecmp(keyword,
"DESCRIPTION")) {
1040 ast_log(
LOG_WARNING,
"'%s' is not a valid token for DESCRIPTION at line %d of %s\n",
args, lineno, script);
1042 ast_log(
LOG_WARNING,
"Missing argument for DESCRIPTION at line %d of %s\n", lineno, script);
1043 }
else if (!strcasecmp(keyword,
"VERSION")) {
1048 ast_log(
LOG_WARNING,
"Missing argument for VERSION at line %d of %s\n", lineno, script);
1049 }
else if (!strcasecmp(keyword,
"SECURITY")) {
1054 ast_log(
LOG_WARNING,
"Missing argument for SECURITY at line %d of %s\n", lineno, script);
1055 }
else if (!strcasecmp(keyword,
"FDN")) {
1061 }
else if (!strcasecmp(keyword,
"KEY")) {
1063 ast_log(
LOG_WARNING,
"KEY definition missing name at line %d of %s\n", lineno, script);
1067 ast_log(
LOG_WARNING,
"'%s' is not a valid token for a KEY name at line %d of %s\n",
args, lineno, script);
1074 if (
state->key->defined) {
1083 ast_log(
LOG_WARNING,
"KEY definition missing short name at line %d of %s\n", lineno, script);
1087 ast_log(
LOG_WARNING,
"'%s' is not a valid token for a KEY short name at line %d of %s\n",
args, lineno, script);
1091 if (strcasecmp(
args,
"OR")) {
1096 ast_log(
LOG_WARNING,
"KEY definition missing optional long name at line %d of %s\n", lineno, script);
1100 ast_log(
LOG_WARNING,
"'%s' is not a valid token for a KEY long name at line %d of %s\n",
args, lineno, script);
1106 if (strlen(tmp2) > 18) {
1107 ast_log(
LOG_WARNING,
"Truncating full name to 18 characters at line %d of %s\n", lineno, script);
1110 if (strlen(tmp) > 7) {
1111 ast_log(
LOG_WARNING,
"Truncating short name to 7 bytes at line %d of %s\n", lineno, script);
1115 state->key->retstr[0] = 0x80;
1119 memcpy(
state->key->retstr + 3, tmp2, strlen(tmp2));
1121 state->key->retstrlen = strlen(tmp2) + 3;
1123 state->key->retstr[
state->key->retstrlen++] = 0xff;
1125 memcpy(
state->key->retstr +
state->key->retstrlen, tmp, strlen(tmp));
1127 state->key->retstrlen += strlen(tmp);
1129 state->key->retstr[
state->key->retstrlen++] = 0xff;
1133 }
else if (!strcasecmp(keyword,
"SUB")) {
1135 ast_log(
LOG_WARNING,
"SUB definition missing name at line %d of %s\n", lineno, script);
1139 ast_log(
LOG_WARNING,
"'%s' is not a valid token for a KEY name at line %d of %s\n",
args, lineno, script);
1146 if (
state->sub->defined) {
1151 state->sub->data[0] = 0x82;
1153 state->sub->data[2] = 0x0;
1154 state->sub->datalen = 3;
1155 if (
state->sub->id) {
1157 state->sub->data[3] = 9;
1160 state->sub->data[6] = 0xff;
1161 state->sub->datalen = 7;
1168 }
else if (!strcasecmp(keyword,
"STATE")) {
1170 ast_log(
LOG_WARNING,
"STATE definition missing name at line %d of %s\n", lineno, script);
1174 ast_log(
LOG_WARNING,
"'%s' is not a valid token for a STATE name at line %d of %s\n",
args, lineno, script);
1182 }
else if (!strcasecmp(keyword,
"FLAG")) {
1184 ast_log(
LOG_WARNING,
"FLAG definition missing name at line %d of %s\n", lineno, script);
1188 ast_log(
LOG_WARNING,
"'%s' is not a valid token for a FLAG name at line %d of %s\n",
args, lineno, script);
1196 }
else if (!strcasecmp(keyword,
"DISPLAY")) {
1200 ast_log(
LOG_WARNING,
"SUB definition missing name at line %d of %s\n", lineno, script);
1204 ast_log(
LOG_WARNING,
"'%s' is not a valid token for a KEY name at line %d of %s\n",
args, lineno, script);
1225 if (strlen(tmp) > 20) {
1226 ast_log(
LOG_WARNING,
"Truncating column one to 20 characters at line %d of %s\n", lineno, script);
1229 memcpy(disp->
data + 5, tmp, strlen(tmp));
1230 disp->
datalen = strlen(tmp) + 5;
1236 if (strlen(tmp) > 20) {
1237 ast_log(
LOG_WARNING,
"Truncating column two to 20 characters at line %d of %s\n", lineno, script);
1240 memcpy(disp->
data + disp->
datalen, tmp, strlen(tmp));
1245 if (!strcasecmp(
args,
"JUSTIFY")) {
1248 ast_log(
LOG_WARNING,
"Qualifier 'JUSTIFY' requires an argument at line %d of %s\n", lineno, script);
1256 }
else if (!strcasecmp(
args,
"WRAP")) {
1268 disp->
data[0] = 0x81;
1270 disp->
data[2] = ((lrci & 0x3) << 6) | disp->
id;
1272 disp->
data[4] = 0xff;
1279 if (!strcasecmp(keyword,
"ENDKEY")) {
1282 state->key->defined = 1;
1283 state->key->retstr[1] =
state->key->retstrlen - 2;
1286 ast_log(
LOG_WARNING,
"Invalid or Unknown keyword '%s' in SOFTKEY definition at line %d of %s\n", keyword, lineno, script);
1292 if (!strcasecmp(keyword,
"ENDIF")) {
1295 state->sub->defined = 1;
1297 state->sub->ifdata[2] =
state->sub->ifinscount;
1298 }
else if (!strcasecmp(keyword,
"GOTO")) {
1300 ast_log(
LOG_WARNING,
"GOTO clause missing Subscript name at line %d of %s\n", lineno, script);
1304 ast_log(
LOG_WARNING,
"'%s' is not a valid subscript name token at line %d of %s\n",
args, lineno, script);
1310 state->sub->data[
state->sub->datalen++] = 0x8;
1314 state->sub->data[
state->sub->datalen++] = 0xff;
1316 state->sub->inscount++;
1317 state->sub->ifinscount++;
1319 ast_log(
LOG_WARNING,
"Invalid or Unknown keyword '%s' in IF clause at line %d of %s\n", keyword, lineno, script);
1322 state->sub->ifinscount++;
1326 if (!strcasecmp(keyword,
"ENDSUB")) {
1329 state->sub->defined = 1;
1331 state->sub->data[1] =
state->sub->datalen - 2;
1332 if (
state->sub->id) {
1337 }
else if (!strcasecmp(keyword,
"IFEVENT")) {
1339 ast_log(
LOG_WARNING,
"IFEVENT clause missing Event name at line %d of %s\n", lineno, script);
1347 ast_log(
LOG_WARNING,
"IFEVENT clause missing 'THEN' at line %d of %s\n", lineno, script);
1350 state->sub->ifinscount = 0;
1353 state->sub->ifdata[0] = 0x1;
1356 state->sub->ifdata[3] = 0xff;
1357 state->sub->datalen += 4;
1359 state->sub->inscount++;
1362 ast_log(
LOG_WARNING,
"Invalid or Unknown keyword '%s' in SUB definition at line %d of %s\n", keyword, lineno, script);
1375 char fn[256],
buf[256], *
c;
1376 int lineno = 0, x, err;
1379 if (script[0] ==
'/')
1384 if (!(f = fopen(fn,
"r"))) {
1397 if (!fgets(
buf,
sizeof(
buf), f)) {
1403 buf[strlen(
buf) - 1] =
'\0';
1405 if ((
c = strchr(
buf,
';')))
1413 switch(scr->
state) {
1428 for (x = 0; x < scr->
numkeys; x++) {
1436 for (x = 0; x < scr->
numsubs; x++) {
1441 if (x == (scr->
numsubs - 1)) {
1455static void dump_message(
char *
type,
char *vname,
unsigned char *
buf,
int buflen)
1458 printf(
"%s %s: [ ",
type, vname);
1459 for (x = 0; x < buflen; x++)
1460 printf(
"%02hhx ",
buf[x]);
1469 unsigned char buf[1024];
1481 ast_verb(3,
"User rejected download attempt\n");
1489 for (x = 0; x < scr->
numkeys; x++) {
1537 for (x = 0; x < scr->
numsubs; x++) {
1566 ast_verb(3,
"Download attempt failed\n");
1581 data =
"asterisk.adsi";
1584 ast_verb(3,
"ADSI Unavailable on CPE. Not bothering to try.\n");
1586 ast_verb(3,
"ADSI Available on CPE. Attempting Upload.\n");
1619 .
requires =
"res_adsi",
ADSI Support (built upon Caller*ID)
int ast_adsi_display(unsigned char *buf, int page, int line, int just, int wrap, char *col1, char *col2)
Loads a line of info into the display.
#define ADSI_MSG_DOWNLOAD
int ast_adsi_unload_session(struct ast_channel *chan)
int ast_adsi_begin_download(struct ast_channel *chan, char *service, unsigned char *fdn, unsigned char *sec, int version)
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
int ast_adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int data)
Check if scripts for a given app are already loaded. Version may be -1, if any version is okay,...
int ast_adsi_end_download(struct ast_channel *chan)
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
static int process_returncode(struct adsi_soft_key *key, char *code, char *args, struct adsi_script *state, const char *script, int lineno)
static int cleardisplay(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
static int process_token(void *out, char *src, int maxlen, int argtype)
static int clearflag(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static const struct adsi_event events[]
static int goto_line(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static struct adsi_script * compile_script(const char *script)
static int showkeys(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static struct adsi_flag * getflagbyname(struct adsi_script *state, char *name, const char *script, int lineno, int create)
static int adsi_exec(struct ast_channel *chan, const char *data)
static struct adsi_soft_key * getkeybyname(struct adsi_script *state, char *name, const char *script, int lineno)
static int subscript(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static struct adsi_subscript * getsubbyname(struct adsi_script *state, char *name, const char *script, int lineno)
static int geteventbyname(char *name)
static int process_opcode(struct adsi_subscript *sub, char *code, char *args, struct adsi_script *state, const char *script, int lineno)
static int adsi_process(struct adsi_script *state, char *buf, const char *script, int lineno)
static int send_delay(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static int cleartimer(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
static const struct adsi_key_cmd kcmds[]
static int adsi_prog(struct ast_channel *chan, const char *script)
static int goto_line_rel(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static struct adsi_display * getdisplaybyname(struct adsi_script *state, char *name, const char *script, int lineno, int create)
static int setflag(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static int set_state(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
static int starttimer(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
static const struct adsi_key_cmd opcmds[]
static int load_module(void)
Load the module.
static int getjustifybyname(char *name)
static int onevent(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static int unload_module(void)
static char * get_token(char **buf, const char *script, int lineno)
static struct adsi_state * getstatebyname(struct adsi_script *state, char *name, const char *script, int lineno, int create)
static int send_dtmf(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static const struct adsi_event justify[]
static int showdisplay(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static int clearcbone(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
static int digitcollect(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
static int digitdirect(char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
Asterisk main include file. File version handling, generic pbx functions.
#define ast_calloc(num, len)
A wrapper for calloc()
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
Generic File Format Support. Should be included by clients of the file handling routines....
#define ast_verb(level,...)
Asterisk locking-related definitions:
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODULE_SUPPORT_DEPRECATED
#define ASTERISK_GPL_KEY
The text the key() function should return.
int ast_unregister_application(const char *app)
Unregister an application.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_CONFIG_DIR
Core PBX routines and definitions.
struct stasis_forward * sub
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
int(* add_args)(char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
struct adsi_subscript subs[128]
struct adsi_subscript * sub
struct adsi_state states[256]
struct adsi_flag flags[7]
struct adsi_display displays[63]
struct adsi_soft_key keys[62]
struct adsi_soft_key * key
Main Channel structure associated with a channel.