[89] | 1 | /*!
|
---|
| 2 | * \file qextserialenumerator.h
|
---|
| 3 | * \author Michal Policht
|
---|
| 4 | * \see QextSerialEnumerator
|
---|
| 5 | */
|
---|
| 6 |
|
---|
| 7 | #ifndef _QEXTSERIALENUMERATOR_H_
|
---|
| 8 | #define _QEXTSERIALENUMERATOR_H_
|
---|
| 9 |
|
---|
| 10 |
|
---|
| 11 | #include <QString>
|
---|
| 12 | #include <QList>
|
---|
| 13 | #include <QObject>
|
---|
| 14 | #include "qextserialport_global.h"
|
---|
| 15 |
|
---|
| 16 | #ifdef Q_OS_WIN
|
---|
| 17 | #include <windows.h>
|
---|
| 18 | #include <setupapi.h>
|
---|
| 19 | #include <dbt.h>
|
---|
| 20 | #endif /*Q_OS_WIN*/
|
---|
| 21 |
|
---|
| 22 | #ifdef Q_OS_MAC
|
---|
| 23 | #include <IOKit/usb/IOUSBLib.h>
|
---|
| 24 | #endif
|
---|
| 25 |
|
---|
| 26 | /*!
|
---|
| 27 | * Structure containing port information.
|
---|
| 28 | */
|
---|
| 29 | struct QextPortInfo {
|
---|
| 30 | QString portName; ///< Port name.
|
---|
| 31 | QString physName; ///< Physical name.
|
---|
| 32 | QString friendName; ///< Friendly name.
|
---|
| 33 | QString enumName; ///< Enumerator name.
|
---|
| 34 | int vendorID; ///< Vendor ID.
|
---|
| 35 | int productID; ///< Product ID
|
---|
| 36 | };
|
---|
| 37 |
|
---|
| 38 | #ifdef Q_OS_WIN
|
---|
| 39 | #ifdef QT_GUI_LIB
|
---|
| 40 | #include <QWidget>
|
---|
| 41 | class QextSerialEnumerator;
|
---|
| 42 |
|
---|
| 43 | class QextSerialRegistrationWidget : public QWidget
|
---|
| 44 | {
|
---|
| 45 | Q_OBJECT
|
---|
| 46 | public:
|
---|
| 47 | QextSerialRegistrationWidget( QextSerialEnumerator* qese ) {
|
---|
| 48 | this->qese = qese;
|
---|
| 49 | }
|
---|
| 50 | ~QextSerialRegistrationWidget( ) { }
|
---|
| 51 |
|
---|
| 52 | protected:
|
---|
| 53 | QextSerialEnumerator* qese;
|
---|
| 54 | bool winEvent( MSG* message, long* result );
|
---|
| 55 | };
|
---|
| 56 | #endif // QT_GUI_LIB
|
---|
| 57 | #endif // Q_OS_WIN
|
---|
| 58 |
|
---|
| 59 | /*!
|
---|
| 60 | Provides list of ports available in the system.
|
---|
| 61 |
|
---|
| 62 | \section Usage
|
---|
| 63 | To poll the system for a list of connected devices, simply use getPorts(). Each
|
---|
| 64 | QextPortInfo structure will populated with information about the corresponding device.
|
---|
| 65 |
|
---|
| 66 | \b Example
|
---|
| 67 | \code
|
---|
| 68 | QList<QextPortInfo> ports = QextSerialEnumerator::getPorts();
|
---|
| 69 | foreach( QextPortInfo port, ports ) {
|
---|
| 70 | // inspect port...
|
---|
| 71 | }
|
---|
| 72 | \endcode
|
---|
| 73 |
|
---|
| 74 | To enable event-driven notification of device connection events, first call
|
---|
| 75 | setUpNotifications() and then connect to the deviceDiscovered() and deviceRemoved()
|
---|
| 76 | signals. Event-driven behavior is currently available only on Windows and OS X.
|
---|
| 77 |
|
---|
| 78 | \b Example
|
---|
| 79 | \code
|
---|
| 80 | QextSerialEnumerator* enumerator = new QextSerialEnumerator();
|
---|
| 81 | connect(enumerator, SIGNAL(deviceDiscovered(const QextPortInfo &)),
|
---|
| 82 | myClass, SLOT(onDeviceDiscovered(const QextPortInfo &)));
|
---|
| 83 | connect(enumerator, SIGNAL(deviceRemoved(const QextPortInfo &)),
|
---|
| 84 | myClass, SLOT(onDeviceRemoved(const QextPortInfo &)));
|
---|
| 85 | \endcode
|
---|
| 86 |
|
---|
| 87 | \section Credits
|
---|
| 88 | Windows implementation is based on Zach Gorman's work from
|
---|
| 89 | <a href="http://www.codeproject.com">The Code Project</a> (http://www.codeproject.com/system/setupdi.asp).
|
---|
| 90 |
|
---|
| 91 | OS X implementation, see
|
---|
| 92 | http://developer.apple.com/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_Finding_Devices/chapter_4_section_2.html
|
---|
| 93 |
|
---|
| 94 | \author Michal Policht, Liam Staskawicz
|
---|
| 95 | */
|
---|
| 96 | class QEXTSERIALPORT_EXPORT QextSerialEnumerator : public QObject
|
---|
| 97 | {
|
---|
| 98 | Q_OBJECT
|
---|
| 99 | public:
|
---|
| 100 | QextSerialEnumerator( );
|
---|
| 101 | ~QextSerialEnumerator( );
|
---|
| 102 |
|
---|
| 103 | #ifdef Q_OS_WIN
|
---|
| 104 | LRESULT onDeviceChangeWin( WPARAM wParam, LPARAM lParam );
|
---|
| 105 | private:
|
---|
| 106 | /*!
|
---|
| 107 | * Get value of specified property from the registry.
|
---|
| 108 | * \param key handle to an open key.
|
---|
| 109 | * \param property property name.
|
---|
| 110 | * \return property value.
|
---|
| 111 | */
|
---|
| 112 | static QString getRegKeyValue(HKEY key, LPCTSTR property);
|
---|
| 113 |
|
---|
| 114 | /*!
|
---|
| 115 | * Get specific property from registry.
|
---|
| 116 | * \param devInfo pointer to the device information set that contains the interface
|
---|
| 117 | * and its underlying device. Returned by SetupDiGetClassDevs() function.
|
---|
| 118 | * \param devData pointer to an SP_DEVINFO_DATA structure that defines the device instance.
|
---|
| 119 | * this is returned by SetupDiGetDeviceInterfaceDetail() function.
|
---|
| 120 | * \param property registry property. One of defined SPDRP_* constants.
|
---|
| 121 | * \return property string.
|
---|
| 122 | */
|
---|
| 123 | static QString getDeviceProperty(HDEVINFO devInfo, PSP_DEVINFO_DATA devData, DWORD property);
|
---|
| 124 |
|
---|
| 125 | /*!
|
---|
| 126 | * Search for serial ports using setupapi.
|
---|
| 127 | * \param infoList list with result.
|
---|
| 128 | */
|
---|
| 129 | static void setupAPIScan(QList<QextPortInfo> & infoList);
|
---|
| 130 | void setUpNotificationWin( );
|
---|
| 131 | static bool getDeviceDetailsWin( QextPortInfo* portInfo, HDEVINFO devInfo,
|
---|
| 132 | PSP_DEVINFO_DATA devData, WPARAM wParam = DBT_DEVICEARRIVAL );
|
---|
| 133 | static void enumerateDevicesWin( const GUID & guidDev, QList<QextPortInfo>* infoList );
|
---|
| 134 | bool matchAndDispatchChangedDevice(const QString & deviceID, const GUID & guid, WPARAM wParam);
|
---|
| 135 | #ifdef QT_GUI_LIB
|
---|
| 136 | QextSerialRegistrationWidget* notificationWidget;
|
---|
| 137 | #endif
|
---|
| 138 | #endif /*Q_OS_WIN*/
|
---|
| 139 |
|
---|
| 140 | #ifdef Q_OS_UNIX
|
---|
| 141 | #ifdef Q_OS_MAC
|
---|
| 142 | private:
|
---|
| 143 | /*!
|
---|
| 144 | * Search for serial ports using IOKit.
|
---|
| 145 | * \param infoList list with result.
|
---|
| 146 | */
|
---|
| 147 | static void scanPortsOSX(QList<QextPortInfo> & infoList);
|
---|
| 148 | static void iterateServicesOSX(io_object_t service, QList<QextPortInfo> & infoList);
|
---|
| 149 | static bool getServiceDetailsOSX( io_object_t service, QextPortInfo* portInfo );
|
---|
| 150 |
|
---|
| 151 | void setUpNotificationOSX( );
|
---|
| 152 | void onDeviceDiscoveredOSX( io_object_t service );
|
---|
| 153 | void onDeviceTerminatedOSX( io_object_t service );
|
---|
| 154 | friend void deviceDiscoveredCallbackOSX( void *ctxt, io_iterator_t serialPortIterator );
|
---|
| 155 | friend void deviceTerminatedCallbackOSX( void *ctxt, io_iterator_t serialPortIterator );
|
---|
| 156 |
|
---|
| 157 | IONotificationPortRef notificationPortRef;
|
---|
| 158 |
|
---|
| 159 | #else // Q_OS_MAC
|
---|
| 160 | private:
|
---|
| 161 | /*!
|
---|
| 162 | * Search for serial ports on unix.
|
---|
| 163 | * \param infoList list with result.
|
---|
| 164 | */
|
---|
| 165 | static void scanPortsNix(QList<QextPortInfo> & infoList);
|
---|
| 166 | #endif // Q_OS_MAC
|
---|
| 167 | #endif /* Q_OS_UNIX */
|
---|
| 168 |
|
---|
| 169 | public:
|
---|
| 170 | /*!
|
---|
| 171 | Get list of ports.
|
---|
| 172 | \return list of ports currently available in the system.
|
---|
| 173 | */
|
---|
| 174 | static QList<QextPortInfo> getPorts();
|
---|
| 175 | /*!
|
---|
| 176 | Enable event-driven notifications of board discovery/removal.
|
---|
| 177 | */
|
---|
| 178 | void setUpNotifications( );
|
---|
| 179 |
|
---|
| 180 | signals:
|
---|
| 181 | /*!
|
---|
| 182 | A new device has been connected to the system.
|
---|
| 183 |
|
---|
| 184 | setUpNotifications() must be called first to enable event-driven device notifications.
|
---|
| 185 | Currently only implemented on Windows and OS X.
|
---|
| 186 | \param info The device that has been discovered.
|
---|
| 187 | */
|
---|
| 188 | void deviceDiscovered( const QextPortInfo & info );
|
---|
| 189 | /*!
|
---|
| 190 | A device has been disconnected from the system.
|
---|
| 191 |
|
---|
| 192 | setUpNotifications() must be called first to enable event-driven device notifications.
|
---|
| 193 | Currently only implemented on Windows and OS X.
|
---|
| 194 | \param info The device that was disconnected.
|
---|
| 195 | */
|
---|
| 196 | void deviceRemoved( const QextPortInfo & info );
|
---|
| 197 | };
|
---|
| 198 |
|
---|
| 199 | #endif /*_QEXTSERIALENUMERATOR_H_*/
|
---|