qextserialenumerator.h 7.04 KB
Newer Older
lm's avatar
lm committed
1 2 3 4 5 6 7 8 9 10 11 12
/*!
 * \file qextserialenumerator.h
 * \author Michal Policht
 * \see QextSerialEnumerator
 */

#ifndef _QEXTSERIALENUMERATOR_H_
#define _QEXTSERIALENUMERATOR_H_


#include <QtCore/qglobal.h>

13 14 15 16 17 18 19
//#ifdef QEXTSERIALPORT_LIB
//# define QEXTSERIALPORT_EXPORT Q_DECL_EXPORT
//#else
//# define QEXTSERIALPORT_EXPORT Q_DECL_IMPORT
//#endif

#define QEXTSERIALPORT_EXPORT
lm's avatar
lm committed
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209

#include <QString>
#include <QList>
#include <QObject>
//#include "qextserialport_global.h"

#ifdef Q_OS_WIN
    #include <windows.h>
    #include <setupapi.h>
    #include <dbt.h>
#endif /*Q_OS_WIN*/

#ifdef Q_OS_MAC
    #include <IOKit/usb/IOUSBLib.h>
#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 <QWidget>
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<QextPortInfo> 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
  <a href="http://www.codeproject.com">The Code Project</a> (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<QextPortInfo> & 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<QextPortInfo>* 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<QextPortInfo> & infoList);
              static void iterateServicesOSX(io_object_t service, QList<QextPortInfo> & 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<QextPortInfo> & 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<QextPortInfo> 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_*/