www.pudn.com > commutil.zip > CONFIG.CPP
// ******************************************************************** //
// //
// CONFIG.CPP //
// Copyright (c) 1993, Michael Holmes and Bob Flanders //
// C++ Communication Utilities //
// //
// Chapter 7: Receiving a FAX //
// Last changed in chapter 4 //
// //
// This file contains the functions that are under the //
// Alt-Configure on the main menu. These functions manage //
// the selection and line setup of the communications ports. //
// //
// ******************************************************************** //
/* ******************************************************************** *
*
* ports() -- port selection menu routine
*
* ******************************************************************** */
int ports(int c, int r) // column and row for window
{
int i, // loop counter
k, // keyboard input
idx, // line index
old_port; // starting port number
char b[20]; // work buffer
Window port_win(c, r, c + 19, // define temporary window
r + nbr_ports + 1, // ..to hold port list
menu_cn, menu_cr); // ..using system colors
port_win.Open(double_line); // open window with a border
idx = old_port = comport; // save current port number
while(1) // loop till user exits
{
for (i = 0, k = 1; // walk thru port table
i < COUNT(com_ports); i++) // ..displaying available ones
{
if (NOT com_ports[i].available) // q. port available?
continue; // a. no .. skip to next port
sprintf(b, "%c %s %X IRQ%d", // format a buffer
i == comport ? 0xfe : 0xfa, // ..for each port, showing
com_ports[i].name, // ..selected port flag,
com_ports[i].port, // ..port name, base
com_ports[i].irq); // ..address and irq number
port_win.GotoXY(2, k++); // cursor to start of line
if (i == idx) // q. selected line?
port_win.DisplayReverse(b); // a. yes .. highlight line
else
port_win.Display(b); // else .. just display it
}
while (NOT (k = get_key(NO_ALT))) // wait for a key
; // ..before continuing
switch (k) // based on keyboard input
{
case SPACE: // select current item
case CR: // . . . .
comport = idx; // set entry as active
status_line(); // update the status line
break; // ..and wait for next key
case UP: // move up list
for (i = idx - 1; i >= 0; i--) // search to top of list
if (com_ports[i].available) // q. find available one?
{
idx = i; // a. yes .. set up index
break; // ..and exit this loop
}
if (idx == i) // q. find a new port?
break; // a. yes .. wait for next key
for (i = COUNT(com_ports) - 1; // now search from bottom
i >= 0; i--)
if (com_ports[i].available) // q. find available one?
{
idx = i; // a. yes .. set up index
break; // ..and exit this loop
}
break; // wait for next key
case DOWN: // move down list
for (i = idx + 1; // search to bottom
i < COUNT(com_ports); i++)
if (com_ports[i].available) // q. find available one?
{
idx = i; // a. yes .. set up index
break; // ..and exit this loop
}
if (idx == i) // q. find a new port?
break; // a. yes .. wait for next key
for (i = 0; // now from the top
i < COUNT(com_ports); i++)
if (com_ports[i].available) // q. find available one?
{
idx = i; // a. yes .. set up index
break; // ..and exit this loop
}
break; // wait for next key
case ESC: // escape from this menu
k = 0; // set key value to zero
// ..and fall into next case
case LEFT: // move left
case RIGHT: // ..or move right
if (old_port != comport) // q. change ports?
build_comm(); // a. yes .. build new Comm
return(k); // then rtn with the keystroke
default: // error case
printf(BELL); // ..just ring the bell
}
}
return(0); // help keep MSC happy
}
/* ******************************************************************** *
*
* comm_parms() -- communications parameters menu routine
*
* ******************************************************************** */
int comm_parms(int c, int r) // column and row for window
{
int chg, // change flag
i, // loop variable
k, // keyboard input
idx = 0; // line index
char b[20]; // work buffer
Window comm_win(c, r, c + 18, r + 5, // define temporary window
menu_cn, menu_cr); // ..using system colors
comm_win.Open(double_line); // open window with a border
while(1) // loop till user exits
{
for (i = 0; i < 4; i++) // display each parm
{
sprintf(b, "%-9s %5s", // format a buffer
line[i].name, // ..for each line parameter
line[i].lp->parm); // ..and its selected option
comm_win.GotoXY(2, i + 1); // cursor to start of line
if (i == idx) // q. selected line?
comm_win.DisplayReverse(b); // a. yes .. highlight line
else
comm_win.Display(b); // else .. just display it
}
while (NOT (k = get_key(NO_ALT))) // wait for a key
; // ..before continuing
switch (k) // based on keyboard input
{
case SPACE: // change to next item
case CR: // . . . .
line[idx].lp = // find next item in the list
&line_parms[line[idx].lp->next];
status_line(); // update the status line
chg = 1; // post change flag
break; // ..and wait for next key
case UP: // move up list
if (--idx < 0) // q. reach past top of list?
idx = 3; // a. yes .. reset at bottom
break; // ..and wait for next key
case DOWN: // move down list
if (++idx > 3) // q. reaching past bottom?
idx = 0; // a. yes .. reset to top
break; // ..and wait for next key
case ESC: // escape from this menu
k = 0; // set key value to zero
// ..and fall into next case
case LEFT: // move left
case RIGHT: // ..or move right
if (chg) // q. parms changed?
{
comm->SetSpeed( // a. yes .. set baud rate
line[SPEED].lp->value);
comm->SetLine( // ..and line ctrl register
line[PARITY].lp->value | // ..for parity
line[DATA].lp->value | // ..data bits
line[STOP].lp->value); // ..and stop bits
}
return(k); // return with the keystroke
default: // error case
printf(BELL); // ..just ring the bell
}
}
return(0); // keep MSC happy
}
/* ******************************************************************** *
*
* load_config() -- load modem configuration file
*
* ******************************************************************** */
void load_config(char *s) // modem configuration file
{
int i, j; // work integer
char buf[256], // file buffer
c_path[MAX_PATH], // config file w/path
*p, *q, // work character pointer
userfile = 0; // user filename flag
long v; // value of comsetting token
FILE *f; // config file handle
if (NOT s) // q. filename given?
s = cfg_file; // a. no .. use default name
else
userfile = 1; // else .. cfg file specified
strcpy(buf, s); // copy filename to work area
s = buf; // ..and reset pointer
if (NOT strchr(s, '.')) // q. file extension given?
strcat(s, cfg_extension); // a. no .. append one
_searchenv(s, "PATH", c_path); // find the config file
if (*c_path) // q. find a config file?
{ // a. yes .. process file
if (NOT (f = fopen(c_path, "r"))) // q. file open ok?
quit_with(open_error, c_path); // a. no .. quit w/error msg
printf(loading_cfg, c_path); // else .. inform user
}
else if (userfile) // q. user specify file?
quit_with(no_config, s); // a. yes .. quit w/error msg
else
return; // else .. just use defaults
while(NOT feof(f) && // read thru whole file
fgets(buf, sizeof(buf), f)) // ..and while still data
{
if (*(first_nonblank(buf)) == ';') // q. find a comment?
continue; // a. yes .. get next line
if ((p = strtok(buf, delimit_1)) == 0) // q. find a token?
continue; // a. no .. get next line
if (NOT stricmp(p, COMPORT)) // q. get the COMPORT parm?
{
p = strtok(0, delimit_1); // a. yes .. get next token
i = atoi(p); // ..then get port number
if (i >= 1 && i <= 8) // q. in the right range?
comport = --i; // a. yes .. save index
else
quit_with(bad_setting, // else .. quit w/error msg
COMPORT, p); // ..telling them the problem
}
else if (NOT stricmp(p, COMSETTING)) // q. COMSETTING command?
{
p = strtok(0, delimit_3); // a. yes .. get operands
p += strspn(p, delimit_1); // find first token
for (i = 0;; i++) // loop thru sub-tokens
{
p = strtok(i == 0 ? p : 0, // get a sub-token from the
delimit_2); // ..command
if (NOT p) // q. out of sub-tokens?
break; // a. yes .. exit loop
v = atol(p); // check if numeric token
for (j = 0; // validate line parameters
j < COUNT(line_parms); j++)
if ((v && NOT stricmp(p, // q. does numeric token
line_parms[j].parm))// ..match the table entry?
|| (NOT v && NOT // ..or does non-numeric match
strnicmp(p, // ..some portion of the
line_parms[j].parm, // ..table entry?
strlen(p))))
{
line[line_parms[j].idx].lp // a. yes .. point to the
= &line_parms[j]; // ..table entry for later
break; // ..and do next parameter
}
if (j == COUNT (line_parms)) // q. find parameter?
quit_with(bad_parm, p); // a. no .. quit w/error msg
}
}
else if (NOT stricmp(p, NOCOMCHECK)) // q. NOCOMCHECK command?
comcheck = 0; // a. yes .. don't check ports
else if (NOT stricmp(p, FLOWCTL)) // q. FLOWCTL command?
{
p = strtok(0, delimit_1); // a. yes .. get next token
if (NOT stricmp(p, ON)) // q. user specify "on"?
flowctl = 1; // a. yes .. set flag
else if (NOT stricmp(p, OFF)) // q. did they say "off"?
flowctl = 0; // a. yes .. clear flag
else
quit_with(bad_setting, // else .. quit w/error msg
FLOWCTL, p); // ..telling them the problem
}
else if (NOT strnicmp(p, COM, 3) && // q. COMn command
(p[3] >= '1' && p[3] <= '8') && // ..in the right range
NOT p[4]) // ..and the right format?
{
j = p[3] - '1'; // a. yes .. get index
p = strtok(0, delimit_3); // get remainder of operands
p += strspn(p, delimit_1); // skip white space
p = strtok(p, delimit_2); // get next token
sscanf(p, "%x", &i); // ..which is port base addr
if (i >= 0x100 && i <= 0x7f8 // q. in the right range
|| i == 0) // ..or zero?
com_ports[j].port = i; // a. yes .. save number
else
quit_with(bad_port, j + 1, p); // else .. quit w/error msg
p = strtok(0, delimit_2); // get next token
i = atoi(p); // ..get interrupt number
if (i >= 2 && i <= 7 // q. in the right range
|| i == 0) // ..or zero?
com_ports[j].irq = i; // a. yes .. save number
else
quit_with(bad_irq, j + 1, p); // else .. quit w/error msg
}
else if (NOT strnicmp(p, PC, 3)) // q. user command (PC:)?
{ // a. yes .. process statement
if (NOT strlen(&p[3])) // q. missing the cmd name?
quit_with(bad_pc_cmd); // a. yes .. quit w/error msg
q = strtok(0, delimit_eol); // get rest of the line
q = ascii_encode(q); // ..compress ctrl sequences
new List(&user_commands, &p[3], q); // ..and store in list
}
else
{
for (i = 0; // for each entry in the list
i < COUNT(commands); i++)
{
if (NOT stricmp(p, // q. find the command
commands[i][0])) // ..in the list?
{
p = strtok(0, delimit_eol); // a. yes .. get next token
commands[i][1] = // get a copy of the
strdup(ascii_encode(p));// ..packed ctrl chars
break; // ..and exit loop
}
}
if (i == (COUNT(commands) / 2)) // q. find command in table?
quit_with(unknown_cmd, p); // a. no .. quit w/error msg
}
}
fclose(f); // close config file
}
/* ******************************************************************** *
*
* check_port() -- check one comm port for presence and type
*
* ******************************************************************** */
port_type check_port(int base) // base port address
{
char mcr, // modem control register
msr; // modem status register
if (comcheck) // q. check comports?
{ // a. yes .. proceed
mcr = IN(MCR); // get current MCR contents
OUT(MCR, 0x18); // set local loop mode
msr = IN(MSR); // ..and read delta bits
OUT(MCR, mcr); // restore modem control reg
if ((msr & 0xf0) != 0x80) // q. state proper now?
return(no_port); // a. no .. no UART available
}
// check for UART type
OUT(SCR, 0x55); // write to scratch register
if (IN(SCR) != 0x55) // q. scratch register work?
return(std_uart); // a. no .. must be 8250
OUT(FCR, 0xcf); // try to enable FIFOs
if ((IN(IIR) & 0xc0) != 0xc0) // q. FIFO bits found?
return(std_uart); // a. no .. must be 16450
OUT(FCR, 0); // turn off FIFOs
return(fifo_uart); // ..show it is a 1655x
}
/* ******************************************************************** *
*
* check_ports() -- check for availability of comm ports
*
* ******************************************************************** */
void check_ports(void)
{
int i, // loop control
first = -1, // first found port
p; // base port address
for (i = 0; i < COUNT(com_ports); i++) // search thru port array ..
{
p = com_ports[i].port; // get base port address
if (p == 0 || com_ports[i].irq == 0) // q. good table entry?
continue; // a. no .. skip to next port
if ((com_ports[i].available = // q. comm port there?
check_port(p)) == no_port) //
continue; // a. no .. continue
nbr_ports++; // bump port counter
if (comport == -1) // q. selected a port yet?
comport = i; // a. no .. use this one
if (first == -1) // q. found first port yet?
first = i; // a. no .. use this one
}
if (NOT nbr_ports) // q. any ports found?
quit_with(no_ports); // a. no .. quit w/error msg
if (NOT com_ports[comport].available) // q. req'd port unavailable?
comport = first; // a. yes .. use first found
}