|
|
/*++
Copyright (c) 1990-2000 Microsoft Corporation
Module Name:
Com
Abstract:
Takes care of request involving a COM device
Author:
Ramon Juan San Andres (ramonsa) 26-Jun-1991
Revision History:
--*/
#include "mode.hxx"
#include "com.hxx"
#include "array.hxx"
#include "arrayit.hxx"
#include "file.hxx"
#include "path.hxx"
#include "registry.hxx"
#include "regvalue.hxx"
#define DEFAULT_PARITY COMM_PARITY_EVEN
#define DEFAULT_DATA_BITS 7
//
// Local prototypes
//
BOOLEAN ComStatus( IN PCPATH DevicePath, IN PREQUEST_HEADER Request );
BOOLEAN ComSetup( IN PCPATH DevicePath, IN PREQUEST_HEADER Request );
BOOLEAN IsAValidCommDevice ( IN DEVICE_TTYPE DeviceType, IN ULONG DeviceNumber, OUT PPATH *DevicePathPointer );
BOOLEAN ComAllocateStuff( )
/*++
Routine Description:
Initializes Data Structures used for COMM processing.
Arguments:
nonde
Return Value:
BOOLEAN - TRUE if global data initialized, FALSE otherwise
Notes:
--*/
{
return TRUE;
}
BOOLEAN ComDeAllocateStuff( )
/*++
Routine Description:
Deallocates the stuff allocated by ComAllocateStuff.
Arguments:
nonde
Return Value:
BOOLEAN - TRUE if global data de-initialized, FALSE otherwise
Notes:
--*/
{
return TRUE;
}
BOOLEAN ComHandler( IN PREQUEST_HEADER Request )
/*++
Routine Description:
Handles serial port requests.
Arguments:
Request - Supplies pointer to request
Return Value:
BOOLEAN - TRUE if request serviced, FALSE otherwise.
Notes:
--*/
{
PPATH DevicePath; // Name of Device
BOOLEAN Served = TRUE; // TRUE if request served OK.
DebugPtrAssert( Request ); DebugAssert( Request->DeviceType == DEVICE_TYPE_COM );
//
// Make sure that the device exists, and at the same time get its
// name ( For calling APIs ).
//
if ( Request->DeviceName ) {
if (!(DevicePath = NEW PATH)) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, (ULONG)EXIT_ERROR ); return FALSE; // help lint
} DevicePath->Initialize( Request->DeviceName );
} else {
if ( !IsAValidCommDevice( Request->DeviceType, Request->DeviceNumber, &DevicePath )) {
DisplayMessageAndExit( MODE_ERROR_INVALID_DEVICE_NAME, DevicePath->GetPathString(), (ULONG)EXIT_ERROR );
} else if ( !IsAValidDevice( Request->DeviceType, Request->DeviceNumber, NULL ) ) {
DisplayMessageAndExit( MODE_ERROR_DEVICE_UNAVAILABLE, DevicePath->GetPathString(), (ULONG)EXIT_ERROR );
} }
//
// So the device is valid. Now serve the request
//
switch( Request->RequestType ) {
case REQUEST_TYPE_STATUS:
//
// Display state of COM device
//
Served = ComStatus( DevicePath, Request ); break;
case REQUEST_TYPE_COM_SET:
//
// Set state of COM device
//
Served = ComSetup( DevicePath, Request ); break;
default:
DebugAssert( FALSE );
}
DELETE( DevicePath );
return Served;
}
BOOLEAN ComStatus( IN PCPATH DevicePath, IN PREQUEST_HEADER Request )
/*++
Routine Description:
Displays status if a COM device
Arguments:
DevicePath - Supplies pointer to path of device Request - Supplies pointer to request
Return Value:
BOOLEAN - TRUE if status displayed successfully, FALSE otherwise
Notes:
--*/
{ DSTRING Data; COMM_DEVICE CommDevice; // Comm object of the device.
BOOLEAN OpenError; BOOLEAN Status;
DebugPtrAssert( DevicePath ); DebugPtrAssert( Request );
//
// Initialize the Comm object
//
Status = CommDevice.Initialize( DevicePath, &OpenError);
if ( Status ) {
//
// Write the Header
//
WriteStatusHeader( DevicePath );
//
// Baud rate
//
Data.Initialize( (ULONG)CommDevice.QueryBaudRate() ); DisplayMessage( MODE_MESSAGE_STATUS_BAUD, &Data );
//
// Parity
//
switch ( CommDevice.QueryParity() ) {
case COMM_PARITY_NONE: Data.Initialize( "None" ); break;
case COMM_PARITY_ODD: Data.Initialize( "Odd" ); break;
case COMM_PARITY_EVEN: Data.Initialize( "Even" ); break;
case COMM_PARITY_MARK: Data.Initialize( "Mark" ); break;
case COMM_PARITY_SPACE: Data.Initialize( "Space" ); break;
default: DebugAssert( FALSE ); }
DisplayMessage( MODE_MESSAGE_STATUS_PARITY, &Data );
//
// Data bits
//
Data.Initialize( (ULONG)CommDevice.QueryDataBits() ); DisplayMessage( MODE_MESSAGE_STATUS_DATA, &Data );
//
// Stop bits
//
switch ( CommDevice.QueryStopBits() ) {
case COMM_STOPBITS_15: Data.Initialize( "1.5" ); break;
case COMM_STOPBITS_1: Data.Initialize( 1 ); break;
case COMM_STOPBITS_2: Data.Initialize( 2 ); break;
default: DebugAssert( FALSE ); }
DisplayMessage( MODE_MESSAGE_STATUS_STOP, &Data );
//
// TimeOut
//
if ( CommDevice.QueryTimeOut() ) { //
// TRUE means infinite timeout == no timeout
//
Data.Initialize( "OFF" ); } else { Data.Initialize( "ON" ); } DisplayMessage( MODE_MESSAGE_STATUS_TIMEOUT, &Data );
//
// XON/XOFF
//
if ( CommDevice.QueryXon() ) { Data.Initialize( "ON" ); } else { Data.Initialize( "OFF" ); } DisplayMessage( MODE_MESSAGE_STATUS_XON, &Data );
//
// CTS
//
if ( CommDevice.QueryOcts() ) { Data.Initialize( "ON" ); } else { Data.Initialize( "OFF" ); } DisplayMessage( MODE_MESSAGE_STATUS_OCTS, &Data );
//
// DSR handshaking
//
if ( CommDevice.QueryOdsr() ) { Data.Initialize( "ON" ); } else { Data.Initialize( "OFF" ); } DisplayMessage( MODE_MESSAGE_STATUS_ODSR, &Data );
//
// DSR sensitivity
//
if ( CommDevice.QueryIdsr() ) { Data.Initialize( "ON" ); } else { Data.Initialize( "OFF" ); } DisplayMessage( MODE_MESSAGE_STATUS_IDSR, &Data );
//
// DTR
//
switch( CommDevice.QueryDtrControl() ) {
case DTR_ENABLE: Data.Initialize( "ON" ); break;
case DTR_DISABLE: Data.Initialize( "OFF" ); break;
case DTR_HANDSHAKE: Data.Initialize( "HANDSHAKE" ); break;
default: Data.Initialize( "UNKNOWN" ); break;
} DisplayMessage( MODE_MESSAGE_STATUS_DTR, &Data );
//
// RTS
//
switch( CommDevice.QueryRtsControl() ) {
case RTS_ENABLE: Data.Initialize( "ON" ); break;
case RTS_DISABLE: Data.Initialize( "OFF" ); break;
case RTS_HANDSHAKE: Data.Initialize( "HANDSHAKE" ); break;
case RTS_TOGGLE: Data.Initialize( "TOGGLE" ); break;
default: Data.Initialize( "UNKNOWN" ); break;
} DisplayMessage( MODE_MESSAGE_STATUS_RTS, &Data );
Get_Standard_Output_Stream()->WriteChar( '\r' ); Get_Standard_Output_Stream()->WriteChar( '\n' );
} else if ( !OpenError ) {
DisplayMessage( MODE_ERROR_CANNOT_ACCESS_DEVICE, DevicePath->GetPathString() );
Status = TRUE; }
return Status; }
BOOLEAN ComSetup( IN PCPATH DevicePath, IN PREQUEST_HEADER Request )
/*++
Routine Description:
Sets the state of a COM port
Arguments:
DevicePath - Supplies pointer to path of device Request - Supplies pointer to request
Return Value:
BOOLEAN - TRUE if state set successfully, FALSE otherwise
Notes:
--*/
{
PCOMM_DEVICE CommDevice; // Comm object of the device.
BOOLEAN Status = FALSE; // Indicates success or failure
PREQUEST_DATA_COM_SET Data; // Request data
BOOLEAN OpenError; DSTRING Number;
DebugPtrAssert( DevicePath ); DebugPtrAssert( Request );
//
// Initialize the Comm object
//
CommDevice = NEW COMM_DEVICE; if ( !CommDevice ) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, (ULONG)EXIT_ERROR ); return FALSE; // help lint
} Status = CommDevice->Initialize( DevicePath, &OpenError ); if ( Status ) {
//
// We have the Comm object. Set the state according to
// the request.
//
Data = &(((PCOM_REQUEST)Request)->Data.Set);
//
// Baud rate
//
if ( Data->SetBaud ) {
CommDevice->SetBaudRate( Data->Baud );
}
//
// Data Bits
//
if ( Data->SetDataBits ) {
CommDevice->SetDataBits( Data->DataBits );
} else {
//
// Set default
//
if ( CommDevice->QueryDataBits() != DEFAULT_DATA_BITS ) { CommDevice->SetDataBits( DEFAULT_DATA_BITS ); Number.Initialize( DEFAULT_DATA_BITS ); DisplayMessage( MODE_MESSAGE_USED_DEFAULT_DATA, &Number ); } }
//
// Stop Bits
//
if ( Data->SetStopBits ) {
CommDevice->SetStopBits( Data->StopBits );
} else {
//
// Set default
//
if ( CommDevice->QueryBaudRate() == 110 ) { if ( CommDevice->QueryStopBits() != COMM_STOPBITS_2 ) { CommDevice->SetStopBits( COMM_STOPBITS_2 ); Number.Initialize( 2 ); DisplayMessage( MODE_MESSAGE_USED_DEFAULT_STOP, &Number ); } } else { if ( CommDevice->QueryStopBits() != COMM_STOPBITS_1 ) { CommDevice->SetStopBits( COMM_STOPBITS_1 ); Number.Initialize( 1 ); DisplayMessage( MODE_MESSAGE_USED_DEFAULT_STOP, &Number ); } } }
//
// Parity
//
if ( Data->SetParity ) {
CommDevice->SetParity( Data->Parity );
} else {
//
// Set default
//
if ( CommDevice->QueryParity() != DEFAULT_PARITY ) { CommDevice->SetParity( DEFAULT_PARITY ); DisplayMessage( MODE_MESSAGE_USED_DEFAULT_PARITY, NULL ); } }
//
// Timeout
//
if ( Data->SetTimeOut ) {
CommDevice->SetTimeOut( Data->TimeOut );
}
//
// XON/XOFF
//
if ( Data->SetXon) {
CommDevice->SetXon( Data->Xon );
}
//
// CTS
//
if ( Data->SetOcts ) {
CommDevice->SetOcts( Data->Octs ); }
//
// DSR handshaking
//
if ( Data->SetOdsr ) {
CommDevice->SetOdsr( Data->Odsr ); }
//
// DSR sensitivity
//
if ( Data->SetIdsr ) {
CommDevice->SetIdsr( Data->Idsr ); }
//
// DTR
//
if ( Data->SetDtrControl ) {
CommDevice->SetDtrControl( Data->DtrControl ); }
//
// RTS
//
if ( Data->SetRtsControl ) {
CommDevice->SetRtsControl( Data->RtsControl ); }
//
// Now Commit the changes
//
if ( !CommDevice->CommitState() ) {
DisplayMessage( MODE_ERROR_SERIAL_OPTIONS_NOT_SUPPORTED, NULL ); DisplayMessageAndExit( MODE_MESSAGE_COM_NO_CHANGE, NULL, (ULONG)EXIT_ERROR ); }
} else if ( !OpenError ) {
DisplayMessageAndExit( MODE_ERROR_CANNOT_ACCESS_DEVICE, DevicePath->GetPathString(), (ULONG)EXIT_ERROR ); }
DELETE( CommDevice );
if ( Status ) { //
// Display the status of the port (as confirmation ).
//
ComStatus( DevicePath, Request );
}
return Status; }
LONG ConvertBaudRate ( IN LONG BaudIn )
/*++
Routine Description:
Validates a baud rate given as an argument to the program, and converts it to something that the COMM_DEVICE understands.
Arguments:
BaudIn - Supplies the baud rate given by the user
Return Value:
LONG - The baud rate
--*/
{ LONG BaudRate;
switch ( BaudIn ) {
case 11: case 110: BaudRate = 110; break;
case 15: case 150: BaudRate = 150; break;
case 30: case 300: BaudRate = 300; break;
case 60: case 600: BaudRate = 600; break;
case 12: case 1200: BaudRate = 1200; break;
case 24: case 2400: BaudRate = 2400; break;
case 48: case 4800: BaudRate = 4800; break;
case 96: case 9600: BaudRate = 9600; break;
case 19: case 19200: BaudRate = 19200; break;
default: BaudRate = BaudIn;
}
return BaudRate; }
LONG ConvertDataBits ( IN LONG DataBitsIn )
/*++
Routine Description:
Validates the number of data bits given as an argument to the program, and converts it to something that the COMM_DEVICE understands.
Arguments:
DataBitsIn - Supplies the number given by the user
Return Value:
LONG - The number of data bits
--*/
{
if ( ( DataBitsIn != 5 ) && ( DataBitsIn != 6 ) && ( DataBitsIn != 7 ) && ( DataBitsIn != 8 ) ) {
ParseError();
}
return DataBitsIn;
}
STOPBITS ConvertStopBits ( IN LONG StopBitsIn )
/*++
Routine Description:
Validates a number of stop bits given as an argument to the program, and converts it to something that the COMM_DEVICE understands.
Arguments:
StopBitsIn - Supplies the number given by the user
Return Value:
STOPBITS - The number of stop bits
--*/
{ STOPBITS StopBits;
switch ( StopBitsIn ) {
case 1: StopBits = COMM_STOPBITS_1; break;
case 2: StopBits = COMM_STOPBITS_2; break;
default: ParseError();
}
return StopBits;
}
PARITY ConvertParity ( IN WCHAR ParityIn )
/*++
Routine Description:
Validates a parity given as an argument to the program, and converts it to something that the COMM_DEVICE understands.
Arguments:
ParityIn - Supplies the baud rate given by the user
Return Value:
PARITY - The parity
--*/
{
DSTRING ParityString;; WCHAR Par; PARITY Parity;
//
// Get the character that specifies parity. We lowercase it
//
ParityString.Initialize( " " ); ParityString.SetChAt( ParityIn, 0 );
ParityString.Strlwr(); Par = ParityString.QueryChAt( 0 );
//
// Set the correct parity value depending on the character.
//
switch ( Par ) {
case 'n': Parity = COMM_PARITY_NONE; break;
case 'o': Parity = COMM_PARITY_ODD; break;
case 'e': Parity = COMM_PARITY_EVEN; break;
case 'm': Parity = COMM_PARITY_MARK; break;
case 's': Parity = COMM_PARITY_SPACE; break;
default: ParseError();
}
return Parity; }
WCHAR ConvertRetry ( IN WCHAR RetryIn )
/*++
Routine Description:
Validates a retry value given as an argument to the program, and converts it to something that the COMM_DEVICE understands.
Arguments:
RetryIn - Supplies the retry value given by the user
Return Value:
WCHAR - The retry value
--*/
{ return RetryIn;
}
DTR_CONTROL ConvertDtrControl ( IN PCWSTRING CmdLine, IN CHNUM IdxBegin, IN CHNUM IdxEnd )
/*++
Routine Description:
Validates a DTR control value given as an argument to the program, and converts it to something that the COMM_DEVICE understands.
Arguments:
CmdLine - Supplies the command line IdxBegin - Supplies Index of first character IdxEnd - Supplies Index of last character
Return Value:
DTR_CONTROL - The DTR control value
--*/
{ DSTRING On; DSTRING Off; DSTRING Hs;
if ( On.Initialize( "ON" ) && Off.Initialize( "OFF" ) && Hs.Initialize( "HS" ) ) {
if ( !CmdLine->Stricmp( &On, IdxBegin, IdxEnd-IdxBegin+1, 0, On.QueryChCount() ) ) {
return DTR_ENABLE; }
if ( !CmdLine->Stricmp( &Off, IdxBegin, IdxEnd-IdxBegin+1, 0, Off.QueryChCount() ) ) {
return DTR_DISABLE; }
if ( !CmdLine->Stricmp( &Hs, IdxBegin, IdxEnd-IdxBegin+1, 0, Hs.QueryChCount() ) ) {
return DTR_HANDSHAKE; } }
ParseError();
return (DTR_CONTROL)-1; }
RTS_CONTROL ConvertRtsControl ( IN PCWSTRING CmdLine, IN CHNUM IdxBegin, IN CHNUM IdxEnd )
/*++
Routine Description:
Validates a RTS control value given as an argument to the program, and converts it to something that the COMM_DEVICE understands.
Arguments:
CmdLine - Supplies the command line IdxBegin - Supplies Index of first character IdxEnd - Supplies Index of last character
Return Value:
RTS_CONTROL - The RTS control value
--*/
{ DSTRING On; DSTRING Off; DSTRING Hs; DSTRING Tg;
if ( On.Initialize( "ON" ) && Off.Initialize( "OFF" ) && Hs.Initialize( "HS" ) && Tg.Initialize( "TG" ) ) {
if ( !CmdLine->Stricmp( &On, IdxBegin, IdxEnd-IdxBegin+1, 0, On.QueryChCount() ) ) {
return RTS_ENABLE; }
if ( !CmdLine->Stricmp( &Off, IdxBegin, IdxEnd-IdxBegin+1, 0, Off.QueryChCount() ) ) {
return RTS_DISABLE; }
if ( !CmdLine->Stricmp( &Hs, IdxBegin, IdxEnd-IdxBegin+1, 0, Hs.QueryChCount() ) ) {
return RTS_HANDSHAKE; }
if ( !CmdLine->Stricmp( &Tg, IdxBegin, IdxEnd-IdxBegin+1, 0, Tg.QueryChCount() ) ) {
return RTS_TOGGLE; } }
ParseError();
return (RTS_CONTROL)-1; }
BOOLEAN IsAValidCommDevice ( IN DEVICE_TTYPE DeviceType, IN ULONG DeviceNumber, OUT PPATH *DevicePathPointer )
/*++
Routine Description:
Determines if a certain comm device exists and optionally creates a path for it.
Arguments:
DeviceType - Supplies the type of device DeviceNumber - Supplies the device number DeviceName - Supplies a pointer to a pointer to the path for the device.
Return Value:
BOOLEAN - TRUE if the device exists, FALSE otherwise.
Notes:
--*/
{ DSTRING DeviceName; DSTRING Number; BOOLEAN Valid = FALSE; REGISTRY Registry; DSTRING ParentName; DSTRING KeyName; ARRAY ValueArray; PARRAY_ITERATOR Iterator; ULONG ErrorCode; PCBYTE Data; DSTRING PortName; PREGISTRY_VALUE_ENTRY Value;
UNREFERENCED_PARAMETER( DeviceType );
if ( DeviceName.Initialize( (LPWSTR)L"COM" )&& Number.Initialize( DeviceNumber ) && DeviceName.Strcat( &Number ) && ParentName.Initialize( "" ) && KeyName.Initialize( COMM_KEY_NAME ) && ValueArray.Initialize() && Registry.Initialize() ) {
//
// Get the names of all the serial ports
//
if ( Registry.QueryValues( PREDEFINED_KEY_LOCAL_MACHINE, &ParentName, &KeyName, &ValueArray, &ErrorCode ) ) {
//
// See if the given name matches any of the serial ports
//
if ( Iterator = (PARRAY_ITERATOR)ValueArray.QueryIterator() ) {
while ( Value = (PREGISTRY_VALUE_ENTRY)(Iterator->GetNext() ) ) {
if ( Value->GetData( &Data ) ) {
if ( PortName.Initialize( (PWSTR)Data ) ) {
if ( !DeviceName.Stricmp( &PortName ) ) {
Valid = TRUE;
break; } } } }
DELETE( Iterator ); } }
if ( DevicePathPointer ) {
if (!(*DevicePathPointer = NEW PATH)) { DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, (ULONG)EXIT_ERROR ); return FALSE; // help lint
} (*DevicePathPointer)->Initialize( &DeviceName ); }
}
return Valid; }
|