/*! * \file qextserialenumerator.h * \author Michal Policht * \see QextSerialEnumerator */ #ifndef _QEXTSERIALENUMERATOR_H_ #define _QEXTSERIALENUMERATOR_H_ #include #include #include #include "qextserialport_global.h" #ifdef Q_OS_WIN #include #include #include #endif /*Q_OS_WIN*/ #ifdef Q_OS_MAC #include #endif /*! * Structure containing port information. */ struct QextPortInfo { QString portName; ///< Port name. QString physName; ///< Physical name. QString friendName; ///< Friendly name. QString enumName; ///< Enumerator name. int vendorID; ///< Vendor ID. int productID; ///< Product ID }; #ifdef Q_OS_WIN #ifdef QT_GUI_LIB #include class QextSerialEnumerator; class QextSerialRegistrationWidget : public QWidget { Q_OBJECT public: QextSerialRegistrationWidget( QextSerialEnumerator* qese ) { this->qese = qese; } ~QextSerialRegistrationWidget( ) { } protected: QextSerialEnumerator* qese; bool winEvent( MSG* message, long* result ); }; #endif // QT_GUI_LIB #endif // Q_OS_WIN /*! Provides list of ports available in the system. \section Usage To poll the system for a list of connected devices, simply use getPorts(). Each QextPortInfo structure will populated with information about the corresponding device. \b Example \code QList ports = QextSerialEnumerator::getPorts(); foreach( QextPortInfo port, ports ) { // inspect port... } \endcode To enable event-driven notification of device connection events, first call setUpNotifications() and then connect to the deviceDiscovered() and deviceRemoved() signals. Event-driven behavior is currently available only on Windows and OS X. \b Example \code QextSerialEnumerator* enumerator = new QextSerialEnumerator(); connect(enumerator, SIGNAL(deviceDiscovered(const QextPortInfo &)), myClass, SLOT(onDeviceDiscovered(const QextPortInfo &))); connect(enumerator, SIGNAL(deviceRemoved(const QextPortInfo &)), myClass, SLOT(onDeviceRemoved(const QextPortInfo &))); \endcode \section Credits Windows implementation is based on Zach Gorman's work from The Code Project (http://www.codeproject.com/system/setupdi.asp). OS X implementation, see http://developer.apple.com/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_Finding_Devices/chapter_4_section_2.html \author Michal Policht, Liam Staskawicz */ class QEXTSERIALPORT_EXPORT QextSerialEnumerator : public QObject { Q_OBJECT public: QextSerialEnumerator( ); ~QextSerialEnumerator( ); #ifdef Q_OS_WIN LRESULT onDeviceChangeWin( WPARAM wParam, LPARAM lParam ); private: /*! * Get value of specified property from the registry. * \param key handle to an open key. * \param property property name. * \return property value. */ static QString getRegKeyValue(HKEY key, LPCTSTR property); /*! * Get specific property from registry. * \param devInfo pointer to the device information set that contains the interface * and its underlying device. Returned by SetupDiGetClassDevs() function. * \param devData pointer to an SP_DEVINFO_DATA structure that defines the device instance. * this is returned by SetupDiGetDeviceInterfaceDetail() function. * \param property registry property. One of defined SPDRP_* constants. * \return property string. */ static QString getDeviceProperty(HDEVINFO devInfo, PSP_DEVINFO_DATA devData, DWORD property); /*! * Search for serial ports using setupapi. * \param infoList list with result. */ static void setupAPIScan(QList & infoList); void setUpNotificationWin( ); static bool getDeviceDetailsWin( QextPortInfo* portInfo, HDEVINFO devInfo, PSP_DEVINFO_DATA devData, WPARAM wParam = DBT_DEVICEARRIVAL ); static void enumerateDevicesWin( const GUID & guidDev, QList* infoList ); bool matchAndDispatchChangedDevice(const QString & deviceID, const GUID & guid, WPARAM wParam); #ifdef QT_GUI_LIB QextSerialRegistrationWidget* notificationWidget; #endif #endif /*Q_OS_WIN*/ #ifdef Q_OS_UNIX #ifdef Q_OS_MAC private: /*! * Search for serial ports using IOKit. * \param infoList list with result. */ static void scanPortsOSX(QList & infoList); static void iterateServicesOSX(io_object_t service, QList & infoList); static bool getServiceDetailsOSX( io_object_t service, QextPortInfo* portInfo ); void setUpNotificationOSX( ); void onDeviceDiscoveredOSX( io_object_t service ); void onDeviceTerminatedOSX( io_object_t service ); friend void deviceDiscoveredCallbackOSX( void *ctxt, io_iterator_t serialPortIterator ); friend void deviceTerminatedCallbackOSX( void *ctxt, io_iterator_t serialPortIterator ); IONotificationPortRef notificationPortRef; #else // Q_OS_MAC private: /*! * Search for serial ports on unix. * \param infoList list with result. */ static void scanPortsNix(QList & infoList); #endif // Q_OS_MAC #endif /* Q_OS_UNIX */ public: /*! Get list of ports. \return list of ports currently available in the system. */ static QList getPorts(); /*! Enable event-driven notifications of board discovery/removal. */ void setUpNotifications( ); signals: /*! A new device has been connected to the system. setUpNotifications() must be called first to enable event-driven device notifications. Currently only implemented on Windows and OS X. \param info The device that has been discovered. */ void deviceDiscovered( const QextPortInfo & info ); /*! A device has been disconnected from the system. setUpNotifications() must be called first to enable event-driven device notifications. Currently only implemented on Windows and OS X. \param info The device that was disconnected. */ void deviceRemoved( const QextPortInfo & info ); }; #endif /*_QEXTSERIALENUMERATOR_H_*/