summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Shienkov <denis.shienkov@gmail.com>2013-11-08 16:36:26 +0400
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-30 15:58:32 +0100
commitc070632fc73be89889f8297263d86b32390acd4c (patch)
treea5c9a2dd94bf30822838d444f29003867ed1ea59
parent6c234760060b5b16cb089c59c69c7d38ceea9bc6 (diff)
downloadqtserialport-c070632fc73be89889f8297263d86b32390acd4c.tar.gz
Add the additional enumeration through Device Interface Class GUID
The current "Setup Class GUID" approach ignores the devices which has been created by the drivers with a custom setup GUID's (e.g. Eltima Virtual Serial Port Driver and so on). In this case need to add each new custom GUID to the list. But it is not a good solution and shall be used as a last resort. The good solution is use of the "Device Interface Class GUID" instead of the "Setup Class GUID" because it is the recommended way: http://msdn.microsoft.com/en-us/library/windows/hardware/ff545036%28v=vs.85%29.aspx http://msdn.microsoft.com/en-us/library/windows/hardware/ff545046%28v=vs.85%29.aspx A new approach uses the standard GUID_DEVINTERFACE_COMPORT and GUID_DEVINTERFACE_MODEM GUID's which shall be used for the development of any serial port drivers. Besides requires adding of the additional DIGCF_DEVICEINTERFACE flag for the SetupDiGetClassDevs() function, see MSDN: http://msdn.microsoft.com/en-us/library/windows/hardware/ff551069%28v=vs.85%29.aspx It should be noted that this approach also can ignore some devices with drivers which don't use the recommendation. Earlier already there were attempts to implement this approach but unsuccessful, see more 3bfe998860e0bfd3ce48784188eaa0d58bf86da1 and bcdeb589dd9d3b0ff7270d380d043b1882eefdc0 commits. Thus, it seems effective to use both "Setup Class GUID" and "Device Interface Class GUID" approaches that will complement each other. In this case can be keep only the standard GUID's. 1. Now all GUID classes are in the QUuid form and stored in the constant list of pairs as QPair<uuid, flags>. It allows to avoid the old heritage related to the pure-C coding style. 2. The second "flags" parameter from the pair is the DWORD input parameter for the SetupDiGetClassDevs() function which specify the control options that filter the device information elements. It allows to pass the appropriate flags for the each used approach independently. Tested with the cenumerator example on Windows with Qt4 and then Qt5, no regressions found. Task-number: QTBUG-33313 Change-Id: I478905e8ae4b79b7d967e0727d2e1620ad667177 Reviewed-by: Sergey Belyashov <Sergey.Belyashov@gmail.com> Reviewed-by: Laszlo Papp <lpapp@kde.org>
-rw-r--r--src/serialport/qserialportinfo_win.cpp55
1 files changed, 40 insertions, 15 deletions
diff --git a/src/serialport/qserialportinfo_win.cpp b/src/serialport/qserialportinfo_win.cpp
index a584d78..51f529e 100644
--- a/src/serialport/qserialportinfo_win.cpp
+++ b/src/serialport/qserialportinfo_win.cpp
@@ -52,24 +52,28 @@
#include <QtCore/qvariant.h>
#include <QtCore/qstringlist.h>
+#include <QtCore/quuid.h>
+#include <QtCore/qpair.h>
QT_BEGIN_NAMESPACE
#ifndef Q_OS_WINCE
-static const GUID guidsArray[] =
+typedef QPair<QUuid, DWORD> GuidFlagsPair;
+
+static inline const QList<GuidFlagsPair>& guidFlagsPairs()
{
- // Windows Ports Class GUID
- { 0x4D36E978, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } },
- // Virtual Ports Class GUID (i.e. com0com and etc)
- { 0xDF799E12, 0x3C56, 0x421B, { 0xB2, 0x98, 0xB6, 0xD3, 0x64, 0x2B, 0xC8, 0x78 } },
- // Windows Modems Class GUID
- { 0x4D36E96D, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } },
- // Eltima Virtual Serial Port Driver v4 GUID
- { 0xCC0EF009, 0xB820, 0x42F4, { 0x95, 0xA9, 0x9B, 0xFA, 0x6A, 0x5A, 0xB7, 0xAB } },
- // Advanced Virtual COM Port GUID
- { 0x9341CD95, 0x4371, 0x4A37, { 0xA5, 0xAF, 0xFD, 0xB0, 0xA9, 0xD1, 0x96, 0x31 } },
-};
+ static const QList<GuidFlagsPair> guidFlagsPairList = QList<GuidFlagsPair>()
+ // Standard Setup Ports Class GUID
+ << qMakePair(QUuid(0x4D36E978, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18), DWORD(DIGCF_PRESENT))
+ // Standard Setup Modems Class GUID
+ << qMakePair(QUuid(0x4D36E96D, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18), DWORD(DIGCF_PRESENT))
+ // Standard Serial Port Device Interface Class GUID
+ << qMakePair(QUuid(0x86E0D1E0, 0x8089, 0x11D0, 0x9C, 0xE4, 0x08, 0x00, 0x3E, 0x30, 0x1F, 0x73), DWORD(DIGCF_PRESENT | DIGCF_DEVICEINTERFACE))
+ // Standard Modem Device Interface Class GUID
+ << qMakePair(QUuid(0x2C7089AA, 0x2E0E, 0x11D1, 0xB1, 0x14, 0x00, 0xC0, 0x4F, 0xC2, 0xAA, 0xE4), DWORD(DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
+ return guidFlagsPairList;
+}
static QVariant deviceRegistryProperty(HDEVINFO deviceInfoSet,
PSP_DEVINFO_DATA deviceInfoData,
@@ -157,6 +161,23 @@ static QString devicePortName(HDEVINFO deviceInfoSet, PSP_DEVINFO_DATA deviceInf
return QString::fromWCharArray(((const wchar_t *)data.constData()));
}
+class SerialPortNameEqualFunctor
+{
+public:
+ explicit SerialPortNameEqualFunctor(const QString &serialPortName)
+ : m_serialPortName(serialPortName)
+ {
+ }
+
+ bool operator() (const QSerialPortInfo &serialPortInfo) const
+ {
+ return serialPortInfo.portName() == m_serialPortName;
+ }
+
+private:
+ const QString &m_serialPortName;
+};
+
QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
{
static const QString usbVendorIdentifierPrefix(QStringLiteral("VID_"));
@@ -168,10 +189,9 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
static const int productIdentifierSize = 4;
QList<QSerialPortInfo> serialPortInfoList;
- static const int guidCount = sizeof(guidsArray)/sizeof(guidsArray[0]);
- for (int i = 0; i < guidCount; ++i) {
- const HDEVINFO deviceInfoSet = ::SetupDiGetClassDevs(&guidsArray[i], NULL, 0, DIGCF_PRESENT);
+ foreach (const GuidFlagsPair &uniquePair, guidFlagsPairs()) {
+ const HDEVINFO deviceInfoSet = ::SetupDiGetClassDevs(reinterpret_cast<const GUID *>(&uniquePair.first), NULL, 0, uniquePair.second);
if (deviceInfoSet == INVALID_HANDLE_VALUE)
return serialPortInfoList;
@@ -187,6 +207,11 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
if (s.isEmpty() || s.contains(QStringLiteral("LPT")))
continue;
+ if (std::find_if(serialPortInfoList.begin(), serialPortInfoList.end(),
+ SerialPortNameEqualFunctor(s)) != serialPortInfoList.end()) {
+ continue;
+ }
+
serialPortInfo.d_ptr->portName = s;
serialPortInfo.d_ptr->device = QSerialPortPrivate::portNameToSystemLocation(s);
serialPortInfo.d_ptr->description =