📄 command.c
字号:
/*************************************************************************
command.c
This is the CobraNet Module line command processing module.
Besides parsing the line command, this module also provides support
functions and routines for validating the line command parameters.
Copyright (C) 2001-2004 by Cirrus Logic Inc. All Rights Reserved
*************************************************************************/
#include <8051.h>
#include <intrpt.h>
#include <conio.h>
#include <ctype.h>
#include <string.h>
#include "serial.h"
#include "command.h"
#include "test.h"
#include "hmi.h"
#include "error.h"
#include "mib.h"
#include "led.h"
#include "query.h"
#include "cnmutil.h"
#include "audio.h"
#include "packet.h"
#include "evif.h"
#include "mystrings.h"
#include "host_reg.h"
#define cESC_KEY_IGNORE 0
#define cESC_KEY_RIGHT 1
#define cESC_KEY_LEFT 2
#define cESC_KEY_CANCEL 3
#define cESC_KEY_NOT 4
#define cESC_KEY_FUNCTION 5
static char *command_arg_ptr[ cNUM_COM_ARG ];
static char command_buffer[ cCMND_BUF_SIZE ];
void parse_line_command( char * line_command_ptr, char *com_arg_ptr[] );
void process_line_command( char * com_arg_ptr[] );
unsigned char command_in_list( char * line_command_ptr );
unsigned char do_escape( char * ret_char );
extern near unsigned char gRXD_RD_idx;
extern near unsigned char gRXD_WR_idx;
//this is the array of line command function pointers.
code struct command_item_t * code command_list[] = {
&peek_command,
&poke_command,
&route_command,
&led_command,
&query_command,
&audio_command,
&testev_command,
&packet_command,
&read_command,
&write_command,
&peekev_command,
&pokeev_command,
NULL
};
extern void service_Line_Command( void ) {
//this keeps sucking in characters until a carriage return or linefeed
unsigned char c = 0;
static unsigned short counter = 0; //ignore backspace as first chars,
//until counter != 0
static char * edit_ptr = command_buffer;
unsigned char escape_char = 0;
unsigned char init_buffer = 0;
if ( edit_ptr == command_buffer ) {
*edit_ptr = cASCII_NULL;
*( edit_ptr + 1 ) = cASCII_NULL;
}
c = getch();
if ( ( c != cASCII_CR ) && ( c != cASCII_LF ) ) {
switch( c ) {
case cASCII_BS: //deal with backspaces
putch( c );
putch( ' ' );
putch( c );
if ( counter != 0 ) {
*--edit_ptr = cASCII_NULL;
counter--;
}
else
printStrCode( str_Prompt );
break;
case cASCII_CNTRLC: //a control-c aborts the input
printStrCodeC( str_Prompt );
init_buffer = 1;
break;
case cASCII_ESC: //for the future, escape control?
escape_char = do_escape( ( char * ) &c );
switch( escape_char ) {
case cESC_KEY_IGNORE:
case cESC_KEY_NOT:
case cESC_KEY_FUNCTION: //ignore for now, maybe something later.
case cESC_KEY_RIGHT: //ditto
case cESC_KEY_LEFT: //ditto
waiting( 0x0606,0x00 ); //about 2.2ms
if ( gRXD_RD_idx != gRXD_WR_idx )
c = getch(); //clear out buffer
break;
case cESC_KEY_CANCEL:
printStrCode( str_CRLF ); //send a CR/LF
printStrCode( str_Prompt );
init_buffer = 1;
break;
default:
break;
};
break;
default:
putch( c );
if ( isupper( c ) )
c += 'a' - 'A';
*edit_ptr++ = c;
if ( *edit_ptr == cASCII_NULL )
*( edit_ptr + 1 ) = cASCII_NULL;
counter++;
break;
}; //switch
}
else {
putch( c );
//*edit_ptr = cASCII_NULL; //null terminate string
printStrCode( str_CRLF ); //send a CR/LF
parse_line_command( command_buffer, command_arg_ptr );
process_line_command( command_arg_ptr );
putch( '>' );
init_buffer = 1;
}
if ( init_buffer ) {
edit_ptr = command_buffer;
counter = 0;
init_buffer = 0;
}
}
unsigned char do_escape( char * ret_char ) {
//this is mostly for possible expansion, not used at this time.
unsigned char c;
unsigned short cntr = 0;
unsigned char esc_code = cESC_KEY_IGNORE;
do
cntr++;
while ( ( gRXD_RD_idx == gRXD_WR_idx ) && ( cntr != 350 ) ); // ~1 ms
//if another character is waiting than not just escape
if ( gRXD_RD_idx != gRXD_WR_idx ) {
c = getch(); //get next character
if ( c == cASCII_LB ) { //this is part of the control sequence '['
c = getch(); //get the main control char
switch ( c ) {//only support a limited set of control char
case 'C': //right arrow
esc_code = cESC_KEY_RIGHT;
break;
case 'D': //left arrow
esc_code = cESC_KEY_LEFT;
break;
default:
esc_code = cESC_KEY_IGNORE;
break;
};
}
else {//if not part of the control sequence
if ( c == 'O' ) { //this detects a function key press
*ret_char = getch(); //return which key
esc_code = cESC_KEY_FUNCTION;
}
else {
*ret_char = c; //need this to process it if valid?????
esc_code = cESC_KEY_NOT;
}
}
}
else
return( cESC_KEY_CANCEL );
return( esc_code );
}
void parse_line_command(char * line_command_ptr, char * com_arg_ptr[] ) {
//puts everything in lower case and creates an array of pointers
//to the command and arguments
unsigned char c;
c = *line_command_ptr;
// ignore comments, line feeds, carriage returns and
// null terminators for first character.
if ( ( c == '#' ) || ( c == cASCII_CR ) || ( c == cASCII_LF ) ||
( c == cASCII_NULL ) ) {
//returning a null in first pointer indicates an ignore.
*com_arg_ptr = NULL;
return;
}
else {//get the command and arguments
while ( ( c = *line_command_ptr ) != cASCII_NULL ) {
//parse till end of line reached
if ( c != cASCII_SPACE ) {//ignore leading spaces
*com_arg_ptr++ = line_command_ptr;//point to first non null/space
*com_arg_ptr = NULL;
//look for next white space or end of line
while ( ( c != cASCII_SPACE ) && ( c != cASCII_NULL ) )
c = *line_command_ptr++;
line_command_ptr--; //move pointer back to point to space/null
if ( c == cASCII_SPACE ) {
*line_command_ptr = cASCII_NULL;//replace with null termination
line_command_ptr++; //point to next character
}
}
else
line_command_ptr++;
}
}
}
void process_line_command( char * com_arg_ptr[] ) {
//execute the command
unsigned char c;
unsigned char i = 0;
if ( *com_arg_ptr[ 0 ] == '?' ) {
printStrCodeC( str_list );
while ( command_list[ i ] != NULL ) {
strCodecpy( com_arg_ptr[ 0 ], command_list[ i ]->command_name );
command_list[ i ]->command_function( com_arg_ptr );
i++;
}
printStrCodeC( str_Info );
}
else {
c = command_in_list( com_arg_ptr[ 0 ] );
if ( c != cASCII_DEL ) //then execute the command function.
command_list[ c ]->command_function( com_arg_ptr );
else
if ( *com_arg_ptr[ 0 ] != cASCII_NULL )
printStrCodeC( str_unknown );
}
}
unsigned char command_in_list( char * command_ptr ) {
//determines if the command is a valid command
unsigned char i = 0;
char * local_command_ptr; //need local copies
code char * local_list_ptr;
while ( command_list[ i ] != NULL ) {
local_command_ptr = command_ptr;
local_list_ptr = command_list[ i ]->command_name;
for ( ; *local_command_ptr == *local_list_ptr;
local_command_ptr++, local_list_ptr++ )
if ( ( *local_command_ptr == cASCII_NULL ) &&
( *local_list_ptr == cASCII_NULL ) )
return ( i );
i++;
}
return ( cASCII_DEL ); //if it gets to here there is no match.
}
//a packet command is a line command that has come over the Ethernet
//interface via CobraNet packet bridging. This will be processed like a
//normal line command with the exception that any response is piped to
//an array to be sent back to the initiating CobraNet device.
extern void do_packet_command( char * a_command ) {
strcpy( command_buffer, a_command );
parse_line_command( command_buffer, command_arg_ptr );
*a_command = cASCII_NULL;
set_print_packet(); //make sure response is piped to memory.
process_line_command( command_arg_ptr );
clr_print_packet(); //return response state to normal.
}
extern unsigned char validate_hex_string( const char * hex_str_ptr,
unsigned char num_hex_char ) {
//makes sure that the hex string is valid
const char * str_ptr;
char c = 0;
if ( *hex_str_ptr == cASCII_NULL )
return ( cERR_ADDR_MISSING );
if ( ( hex_str_ptr[ 0 ] == '0' ) && ( hex_str_ptr[ 1 ] == 'x' ) ) {
str_ptr = hex_str_ptr + 2;//skip 0x prefix and point to rest of string
for ( ; *str_ptr; c++, str_ptr++ )
if ( !( isxdigit( *str_ptr ) ) )
return( cERR_ADDR_HEX_BAD );
if ( c > num_hex_char )
return( cERR_ADDR_TOO_MANY ); //too many hex characters
}
else //must be in hex format or return error, for future expansion
return( cERR_ADDR_HEX_NOT );
return ( 0 ); //good hex number syntax
}
extern unsigned char validate_dec_string( char * dec_str_ptr ) {
//may want to support decimal format in the future
const char * str_ptr;
str_ptr = dec_str_ptr;
for ( ; *str_ptr; str_ptr++ )
if ( ( *str_ptr < '0' ) || ( *str_ptr > '9' ) )
return( cERR_DECIMAL_NOT );
return( cERR_NO_ERROR ); //good decimal number format,
//does not check value
}
extern unsigned char validate_ip_string( char * ip_str_ptr ) {
//validates an IP string of the format 000.000.000.000 where
//the 000 are decimal numbers. checks for max value as well
unsigned char str_ptr[ 4 ]; //for the longest string
unsigned char i, j;
unsigned char err;
if ( ip_str_ptr == NULL )
return( cERR_MISSING_ARG );
j = 0;
while ( *ip_str_ptr ) {
i = 0;
while ( ( *ip_str_ptr != '.' ) && ( *ip_str_ptr ) && ( i < 4 ) )
str_ptr[ i++ ] = *ip_str_ptr++;
str_ptr[ i ] = cASCII_NULL;
if ( i > 3 )
return( cERR_ADDR_TOO_MANY );
if ( *ip_str_ptr == '.' )
ip_str_ptr++;
if ( err = validate_dec_string( ( char * ) str_ptr ) )
return( err );
if ( alpha2long( ( char * ) str_ptr ) > 255 )
return( cERR_OUT_OF_RANGE );
j++;
}
if ( j > 4 )
return( cERR_ADDR_TOO_MANY );
if ( j < 4 )
return( cERR_TOO_FEW );
return( cERR_NO_ERROR );
}
extern void make_arg_string( char * com_arg_ptr[],
char the_starting_point ) {
char i = the_starting_point - 1;
while ( com_arg_ptr[ ++i ] )
if ( com_arg_ptr[ i + 1 ] ) //only if next is not last.
*( com_arg_ptr[ i ] + strlen( com_arg_ptr[ i ] ) ) = ' ';
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -