//功能:实现串口操作的一些函数
#include "StdAfx.h"
#include "ComControlFunction.h"

//查找系统可用的串口号,将所有的串口号保存在pPortList数组里
//输出:串口数portNumber,串口号数组pPortList
//pPortList保存各串口的串口数字
BOOL ScanPCCom( int *pPortList, int& portNumber )
{
	portNumber = 0;  //系统配置的串口总数

	//扫描PC机存在的串口,从注册表读取存在的串口。 
	UINT    nComNum = 0;
	HKEY    hKEY = NULL; 
	LONG    hResult = ::RegOpenKeyEx( HKEY_LOCAL_MACHINE, _T( "HARDWARE\\DEVICEMAP\\SERIALCOMM" ), 0, KEY_READ, &hKEY ); 

	if ( hResult != ERROR_SUCCESS ) //如果无法打开hKEY,则中止程序的执行
	{
		return FALSE;
	} 

	TCHAR   strInf[30]; 
	memset( strInf, 0, sizeof( TCHAR ) * 30 );

	DWORD   type_1 = REG_SZ; 
	DWORD   cbData_1 = 10; 
	DWORD   aa = 30, num = 0; 
	DWORD   a1 = 0, a2 = 0, a3 = 0, a4 = 0, a5 = 0, a6 = 0, a7 = 0; 

	//hResult = ::RegQueryInfoKey( hKEY, strInf, &a7, NULL, &a3, &a1, &a2, &num, &a4, &a5, &a6, NULL ); 
	hResult = ::RegQueryInfoKeyA( hKEY, NULL, NULL, NULL, &a3, &a1, NULL, &num, &a4, &a5, NULL, NULL ); 
	if ( hResult != ERROR_SUCCESS )
	{
		RegCloseKey( hKEY );
		return FALSE;
	} 

	BYTE    portName[15];
	memset( portName, 0, 15 );

	CString csr = _T( "" );

	for ( DWORD i = 0 ; i < num ; ++i )
	{
		aa = 30 ;
		cbData_1 = 10;
		hResult = ::RegEnumValue( hKEY, i, strInf, &aa, NULL, &type_1, portName, &cbData_1 ); 
		if ( hResult != ERROR_SUCCESS )
		{
			continue;
		}
		csr.Format( _T( "%s" ), portName );

		csr.Delete( 0, 3 );

		pPortList[portNumber] = atoi( csr );

		++portNumber;  //系统配置的串口总数

		++nComNum;
	} 
	RegCloseKey( hKEY );
	return TRUE;
}


//判断串口是否被占有,串口可用返回true,否则返回false
bool OnCheckComPort( const CString& portName )
{
	CString str = _T( "//./" ) + portName;
	HANDLE  hCom = CreateFile( str,                                         //打开串口1
		GENERIC_READ | GENERIC_WRITE,                   //允许读和写操作
		0,                                              //独占方式
		0, OPEN_EXISTING,                                  //打开一个存在的串口
		0, 0 );


	if ( hCom == INVALID_HANDLE_VALUE )   //打开串口失败
	{
		return false;
	}
	else
	{
		CloseHandle( hCom );
		hCom = NULL;
		return true;
	}
}


//判断串口是否为空
//串口为空返回true,否则返回false
bool CheckComPortIsEmpty( const CString strPort )
{
	if ( strPort.Compare( _T( "" ) ) == 0 )
	{
		return true;
	}
	return false;
}

//功能:检测2个串口是否相同,相同返回True,否则返回false
bool CompareTwoComPort( const CString port1, const CString port2 )
{
	if ( ( port1.Compare( port2 ) ) == 0 )
	{
		return true;
	}
	else
	{
		return false;
	}
}

//判断串口是否可用
//可用返回true,否则返回false
bool CheckComPortCanWork( const CString strPort )
{
	if ( strPort.GetLength() <= 4 )
	{
		return false;
	}

	CString str = strPort;
	str.Delete( 0, 4 );                     //删除“串口”字符

	CString strSelectCom = _T( "" );
	strSelectCom.Format( "COM%d", atoi( str ) );

	if ( !OnCheckComPort( strSelectCom ) )          //串口被占用,返回false
	{
		return false;
	}
	else                                        //串口可用,返回true
	{
		return true;
	}
}

//判断串口名称是否正确,正确的名称为“串口XX”——前面为“串口”,后面为数字
//串口名称正确返回true, 否则返回false
bool CheckComPortName( const CString strPort )
{
	if ( strPort.GetLength() < 5 )
	{
		return false;
	}
	CString str = strPort;

	if ( str.Left( 4 ) != _T( "串口" ) )
	{
		return false;
	}
	str = strPort;
	str.Delete( 0, 4 );

	for ( int i = 0; i < str.GetLength(); ++i )
	{
		if ( ( str.GetAt( i ) < '0' ) || ( str.GetAt( i ) > '9' ) )
		{
			return false;
		}
	}

	return true;
}
//从串口数组中进行查找,查找出配置文件设置的串口号
//输入:数组portArray,数组长度arrLength,查找元素itemValue
//输出:元素的位置pos
//返回值:查找成功返回true,否则返回false
bool FindItemFromComList( int& pos, const int *portArray, const int& arrLength, const int& itemValue )
{
	for ( int i = 0; i < arrLength; ++i )
	{
		if ( itemValue == portArray[i] )
		{
			pos = i;
			return true;
		}
	}

	return false;
}