📄 qextserialenumerator.cpp
字号:
/**
* @file qextserialenumerator.cpp
* @author Michał Policht
* @see QextSerialEnumerator
*/
#include "qextserialenumerator.h"
#include <objbase.h>
#include <initguid.h>
#ifdef _TTY_WIN_
//this is serial port GUID
#ifndef GUID_CLASS_COMPORT
DEFINE_GUID(GUID_CLASS_COMPORT, 0x86e0d1e0L, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73);
#endif
/* Gordon Schumacher's macros for TCHAR -> QString conversions and vice versa */
#ifdef UNICODE
#define QStringToTCHAR(x) (wchar_t*) x.utf16()
#define PQStringToTCHAR(x) (wchar_t*) x->utf16()
#define TCHARToQString(x) QString::fromUtf16((ushort*)(x))
#define TCHARToQStringN(x,y) QString::fromUtf16((ushort*)(x),(y))
#else
#define QStringToTCHAR(x) x.local8Bit().constData()
#define PQStringToTCHAR(x) x->local8Bit().constData()
#define TCHARToQString(x) QString::fromLocal8Bit((x))
#define TCHARToQStringN(x,y) QString::fromLocal8Bit((x),(y))
#endif /*UNICODE*/
//static
QString QextSerialEnumerator::getRegKeyValue(HKEY key, LPCTSTR property)
{
DWORD size = 0;
RegQueryValueEx(key, property, NULL, NULL, NULL, & size);
BYTE * buff = new BYTE[size];
if (RegQueryValueEx(key, property, NULL, NULL, buff, & size) == ERROR_SUCCESS) {
return TCHARToQStringN(buff, size);
delete [] buff;
} else {
qWarning("QextSerialEnumerator::getRegKeyValue: can not obtain value from registry");
delete [] buff;
return QString();
}
}
//static
QString QextSerialEnumerator::getDeviceProperty(HDEVINFO devInfo, PSP_DEVINFO_DATA devData, DWORD property)
{
DWORD buffSize = 0;
SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, NULL, 0, & buffSize);
BYTE * buff = new BYTE[buffSize];
if (!SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, buff, buffSize, NULL))
qCritical("Can not obtain property: %ld from registry", property);
QString result = TCHARToQString(buff);
delete [] buff;
return result;
}
//static
void QextSerialEnumerator::setupAPIScan(QList<QextPortInfo> & infoList)
{
HDEVINFO devInfo = INVALID_HANDLE_VALUE;
GUID * guidDev = (GUID *) & GUID_CLASS_COMPORT;
devInfo = SetupDiGetClassDevs(guidDev, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if(devInfo == INVALID_HANDLE_VALUE) {
qCritical("SetupDiGetClassDevs failed. Error code: %ld", GetLastError());
return;
}
//enumerate the devices
bool ok = true;
SP_DEVICE_INTERFACE_DATA ifcData;
ifcData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
SP_DEVICE_INTERFACE_DETAIL_DATA * detData = NULL;
DWORD detDataSize = 0;
DWORD oldDetDataSize = 0;
for (DWORD i = 0; ok; i++) {
ok = SetupDiEnumDeviceInterfaces(devInfo, NULL, guidDev, i, &ifcData);
if (ok) {
SP_DEVINFO_DATA devData = {sizeof(SP_DEVINFO_DATA)};
//check for required detData size
SetupDiGetDeviceInterfaceDetail(devInfo, & ifcData, NULL, 0, & detDataSize, & devData);
//if larger than old detData size then reallocate the buffer
if (detDataSize > oldDetDataSize) {
delete [] detData;
detData = (SP_DEVICE_INTERFACE_DETAIL_DATA *) new char[detDataSize];
detData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
oldDetDataSize = detDataSize;
}
//check the details
if (SetupDiGetDeviceInterfaceDetail(devInfo, & ifcData, detData, detDataSize,
NULL, & devData)) {
// Got a device. Get the details.
QextPortInfo info;
info.friendName = getDeviceProperty(devInfo, & devData, SPDRP_FRIENDLYNAME);
info.physName = getDeviceProperty(devInfo, & devData, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME);
info.enumName = getDeviceProperty(devInfo, & devData, SPDRP_ENUMERATOR_NAME);
//anyway, to get the port name we must still open registry directly :( ???
//Eh...
HKEY devKey = SetupDiOpenDevRegKey(devInfo, & devData, DICS_FLAG_GLOBAL, 0,
DIREG_DEV, KEY_READ);
info.portName = getRegKeyValue(devKey, TEXT("PortName"));
RegCloseKey(devKey);
infoList.append(info);
} else {
qCritical("SetupDiGetDeviceInterfaceDetail failed. Error code: %ld", GetLastError());
delete [] detData;
return;
}
} else {
if (GetLastError() != ERROR_NO_MORE_ITEMS) {
delete [] detData;
qCritical("SetupDiEnumDeviceInterfaces failed. Error code: %ld", GetLastError());
return;
}
}
}
delete [] detData;
}
#endif /*_TTY_WIN_*/
//static
QList<QextPortInfo> QextSerialEnumerator::getPorts()
{
QList<QextPortInfo> ports;
#ifdef _TTY_WIN_
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(vi);
if (!::GetVersionEx(&vi)) {
qCritical("Could not get OS version.");
return ports;
}
// Handle windows 9x and NT4 specially
if (vi.dwMajorVersion < 5) {
qCritical("Enumeration for this version of Windows is not implemented yet");
/* if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT)
EnumPortsWNt4(ports);
else
EnumPortsW9x(ports);*/
} else //w2k or later
setupAPIScan(ports);
#endif /*_TTY_WIN_*/
#ifdef _TTY_POSIX_
qCritical("Enumeration for POSIX systems is not implemented yet.");
#endif /*_TTY_POSIX_*/
return ports;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -