Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Windows (10) and QSerialPort



  • Hi all -

    One of the "features" of Windows 10 is that COM ports are created and deleted dynamically -- when you plug something in, you get a new port; when you unplug it, it goes away. (At least this is the behavior when using the FTDI-style USB-serial interface.)

    This is a bit of a problem for me, in that I'd like to be notified when a new device is plugged in, but I don't know of any way to cause this to happen automatically -- in order for a QSerialPort device to emit a signal, it of course first needs to be created, and I can't create it without knowing it's there.

    I could put an interval-based poll into my worker thread, where every so often it scans for new devices. I think this will work, but it will be kind of clunky. Can anyone think of a better mechanism?

    Thanks...



  • Are you stuck with windoze? The udev rules in Linux handle this once you understand enough of the udev rules alchemy.



  • @Kent-Dorfman sadly, yes. Our user community is the prototypical Fortune 500 company, heavily imbued with all kind of Redmond-ware.

    I've given it some more thought, and I don't see any way around this Catch-22. Unless one of our resident Qt demiurges can think of something, I'll probably just go the polling route.



  • gotcha...there is probably a udev type event system in windoze but unless you are a high priest in the church of Redmond you wouldn't know about it.



  • @mzimmers hi, I think you can use qabstractnativeeventfilter and look for WM_DEVICECHANGE Windows event, and then refresh your devices list at this moment. Here is an example here https://forum.qt.io/topic/32640/help-with-qabstractnativeeventfilter



  • @Gojir4 oh, that looks promising. I'll experiment with it and report back. Thanks!



  • @mzimmers can I ask what is your goal ?



  • @Gojir4 I'm just looking for a way to maintain a list of our products that are connected to the PC. Step one is to be notified of a connection, then I send it a discovery message. If it responds, I know it's one of ours, and I add it to the list.



  • @mzimmers ok, that's very interesting. Hope it will work


  • Qt Champions 2020

    Look on this.

    Shortly: you can subscribe on some events from the specific classes of devices (e.g. when the device appeared or disappeared in the system) using Win32 API such as SetupAPI.

    One of the "features" of Windows 10 is that COM ports are created and deleted dynamically

    It present on all NT-based Windows, it is Plug & Play.. No? :).



  • @Gojir4: I'm getting close on this. Here's a cleaned-up version of the example:

    class MyNativeEventFilter: public QAbstractNativeEventFilter
    {
    public:
        virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result)
        Q_DECL_OVERRIDE;
    Q_SIGNALS:
        void notify();
    };
    bool MyNativeEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
    {
        Q_UNUSED(eventType) // unneeded as long as we're only running on Windows
        Q_UNUSED(result)
        MSG *msg = (MSG *)(message);
    
        if ((msg->message == WM_DEVICECHANGE)
           && (msg->wParam == DBT_DEVNODES_CHANGED))
        {
            qDebug() << "we hit our event!";
            emit notify();
        }
        return false;
    }
    

    If I comment out the emit statement, it runs and traps the device connect/disconnect (verified in the debugger). But, I can't compile with the emit -- I get an undefined reference. This is probably more of a C++ issue than a Qt issue, but can someone tell me what I'm doing wrong? The example is interesting, but not very useful if it can't notify other QObjects in my application.

    Thanks...



  • Here's my solution for this, in case anyone's interested:

    The header file:

    #include <windows.h>
    #include <dbt.h>
    
    #include <QObject>
    #include <QAbstractNativeEventFilter>
    
    class DeviceEventFilter: public QObject, public QAbstractNativeEventFilter
    {
        Q_OBJECT
    public:
        DeviceEventFilter(QObject *parent);
        bool nativeEventFilter(const QByteArray &eventType, void *message, long *result)
        Q_DECL_OVERRIDE;
    Q_SIGNALS:
        void notify();
    };
    

    And the source file:

    #include "eventfilter.h"
    
    DeviceEventFilter::DeviceEventFilter(QObject *parent)
    {
        Q_UNUSED(parent)
    }
    
    bool DeviceEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
    {
        Q_UNUSED(eventType) // unneeded as long as we're only running on Windows
        Q_UNUSED(result)
        MSG *msg = (MSG *)(message);
    
        if ((msg->message == WM_DEVICECHANGE)
                && (msg->wParam == DBT_DEVNODES_CHANGED))
        {
            emit notify();
        }
        return false;
    }
    

Log in to reply