예제 #1
0
/*
    Enable event-driven notifications of board discovery/removal.
*/
bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool setup)
{
#ifndef HAS_QWIDGET
    Q_UNUSED(setup)
    QESP_WARNING("QextSerialEnumerator: GUI not enabled - can't register for device notifications.");
    return false;
#else
    Q_Q(QextSerialEnumerator);
    if(setup && notificationWidget) //already setup
        return true;
    notificationWidget = new QextSerialRegistrationWidget(this);

    DEV_BROADCAST_DEVICEINTERFACE dbh;
    ::ZeroMemory(&dbh, sizeof(dbh));
    dbh.dbcc_size = sizeof(dbh);
    dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    ::CopyMemory(&dbh.dbcc_classguid, &GUID_DEVCLASS_PORTS, sizeof(GUID));
    if(::RegisterDeviceNotification((HWND)notificationWidget->winId(), &dbh, DEVICE_NOTIFY_WINDOW_HANDLE ) == NULL) {
        QESP_WARNING() << "RegisterDeviceNotification failed:" << GetLastError();
        return false;
    }
    // setting up notifications doesn't tell us about devices already connected
    // so get those manually
    foreach(QextPortInfo port, getPorts_sys())
      Q_EMIT q->deviceDiscovered(port);
    return true;
#endif
}
예제 #2
0
void QextSerialPortPrivate::setParity(ParityType parity, bool update)
{
    switch (parity) {
    case PAR_SPACE:
        if (Settings.DataBits==DATA_8) {
#ifdef Q_OS_WIN
            QESP_PORTABILITY_WARNING("QextSerialPort Portability Warning: Space parity with 8 data bits is not supported by POSIX systems.");
#else
            QESP_WARNING("Space parity with 8 data bits is not supported by POSIX systems.");
#endif
        }
        break;

#ifdef Q_OS_WIN
        /*mark parity - WINDOWS ONLY*/
    case PAR_MARK:
        QESP_PORTABILITY_WARNING("QextSerialPort Portability Warning:  Mark parity is not supported by POSIX systems");
        break;
#endif

    case PAR_NONE:
    case PAR_EVEN:
    case PAR_ODD:
        break;
    default:
        QESP_WARNING()<<"QextSerialPort does not support Parity:" << parity;
    }

    Settings.Parity=parity;
    settingsDirtyFlags |= DFE_Parity;
    if (update && q_func()->isOpen())
        updatePortSettings();
}
예제 #3
0
void QextSerialPortPrivate::setDataBits(DataBitsType dataBits, bool update)
{
    switch(dataBits) {

    case DATA_5:
        if (Settings.StopBits==STOP_2) {
            QESP_WARNING("QextSerialPort: 5 Data bits cannot be used with 2 stop bits.");
        }
        else {
            Settings.DataBits=dataBits;
            settingsDirtyFlags |= DFE_DataBits;
        }
        break;

    case DATA_6:
#ifdef Q_OS_WIN
        if (Settings.StopBits==STOP_1_5) {
            QESP_WARNING("QextSerialPort: 6 Data bits cannot be used with 1.5 stop bits.");
        }
        else
#endif
        {
            Settings.DataBits=dataBits;
            settingsDirtyFlags |= DFE_DataBits;
        }
        break;

    case DATA_7:
#ifdef Q_OS_WIN
        if (Settings.StopBits==STOP_1_5) {
            QESP_WARNING("QextSerialPort: 7 Data bits cannot be used with 1.5 stop bits.");
        }
        else
#endif
        {
            Settings.DataBits=dataBits;
            settingsDirtyFlags |= DFE_DataBits;
        }
        break;

    case DATA_8:
#ifdef Q_OS_WIN
        if (Settings.StopBits==STOP_1_5) {
            QESP_WARNING("QextSerialPort: 8 Data bits cannot be used with 1.5 stop bits.");
        }
        else
#endif
        {
            Settings.DataBits=dataBits;
            settingsDirtyFlags |= DFE_DataBits;
        }
        break;
    default:
        QESP_WARNING()<<"QextSerialPort does not support Data bits:"<<dataBits;
    }
    if (update && q_func()->isOpen())
        updatePortSettings();
}
예제 #4
0
void QextSerialPortPrivate::setStopBits(StopBitsType stopBits, bool update)
{
    switch (stopBits) {

        /*one stop bit*/
    case STOP_1:
        Settings.StopBits = stopBits;
        settingsDirtyFlags |= DFE_StopBits;
        break;

#ifdef Q_OS_WIN
        /*1.5 stop bits*/
    case STOP_1_5:
        QESP_PORTABILITY_WARNING("QextSerialPort Portability Warning: 1.5 stop bit operation is not supported by POSIX.");
        if (Settings.DataBits!=DATA_5) {
            QESP_WARNING("QextSerialPort: 1.5 stop bits can only be used with 5 data bits");
        }
        else {
            Settings.StopBits = stopBits;
            settingsDirtyFlags |= DFE_StopBits;
        }
        break;
#endif

        /*two stop bits*/
    case STOP_2:
        if (Settings.DataBits==DATA_5) {
            QESP_WARNING("QextSerialPort: 2 stop bits cannot be used with 5 data bits");
        }
        else {
            Settings.StopBits = stopBits;
            settingsDirtyFlags |= DFE_StopBits;
        }
        break;
    default:
        QESP_WARNING()<<"QextSerialPort does not support stop bits: "<<stopBits;
    }
    if (update && q_func()->isOpen())
        updatePortSettings();
}
예제 #5
0
// static
QList<QextPortInfo> QextSerialEnumeratorPrivate::getPorts_sys()
{
    QList<QextPortInfo> infoList;
    io_iterator_t serialPortIterator = 0;
    kern_return_t kernResult = KERN_FAILURE;
    CFMutableDictionaryRef matchingDictionary;

    // first try to get any serialbsd devices, then try any USBCDC devices
    if (!(matchingDictionary = IOServiceMatching(kIOSerialBSDServiceValue))) {
        QESP_WARNING("IOServiceMatching returned a nullptr dictionary.");
        return infoList;
    }
    CFDictionaryAddValue(matchingDictionary, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));

    // then create the iterator with all the matching devices
    if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &serialPortIterator) != KERN_SUCCESS) {
        qCritical() << "IOServiceGetMatchingServices failed, returned" << kernResult;
        return infoList;
    }
    iterateServicesOSX(serialPortIterator, infoList);
    IOObjectRelease(serialPortIterator);
    serialPortIterator = 0;

    if (!(matchingDictionary = IOServiceNameMatching("AppleUSBCDC"))) {
        QESP_WARNING("IOServiceNameMatching returned a nullptr dictionary.");
        return infoList;
    }

    if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &serialPortIterator) != KERN_SUCCESS) {
        qCritical() << "IOServiceGetMatchingServices failed, returned" << kernResult;
        return infoList;
    }
    iterateServicesOSX(serialPortIterator, infoList);
    IOObjectRelease(serialPortIterator);

    return infoList;
}
예제 #6
0
bool QextSerialPortPrivate::open_sys(QIODevice::OpenMode mode)
{
    Q_Q(QextSerialPort);
    DWORD confSize = sizeof(COMMCONFIG);
    commConfig.dwSize = confSize;
    DWORD dwFlagsAndAttributes = 0;
    if (queryMode == QextSerialPort::EventDriven)
        dwFlagsAndAttributes += FILE_FLAG_OVERLAPPED;

    /*open the port*/
    handle = CreateFileW((wchar_t *)fullPortNameWin(port).utf16(), GENERIC_READ|GENERIC_WRITE,
                           0, nullptr, OPEN_EXISTING, dwFlagsAndAttributes, nullptr);
    if (handle != INVALID_HANDLE_VALUE) {
        q->setOpenMode(mode);
        /*configure port settings*/
        GetCommConfig(handle, &commConfig, &confSize);
        GetCommState(handle, &(commConfig.dcb));

        /*set up parameters*/
        commConfig.dcb.fBinary = TRUE;
        commConfig.dcb.fInX = FALSE;
        commConfig.dcb.fOutX = FALSE;
        commConfig.dcb.fAbortOnError = FALSE;
        commConfig.dcb.fNull = FALSE;
        /* Dtr default to true. See Issue 122*/
        commConfig.dcb.fDtrControl = TRUE;
        /*flush all settings*/
        settingsDirtyFlags = DFE_ALL;
        updatePortSettings();

        //init event driven approach
        if (queryMode == QextSerialPort::EventDriven) {
            if (!SetCommMask(handle, EV_TXEMPTY | EV_RXCHAR | EV_DSR)) {
                QESP_WARNING()<<"failed to set Comm Mask. Error code:"<<GetLastError();
                return false;
            }
            winEventNotifier = new QWinEventNotifier(overlap.hEvent, q);
            qRegisterMetaType<HANDLE>("HANDLE");
            q->connect(winEventNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_onWinEvent(HANDLE)), Qt::DirectConnection);
            WaitCommEvent(handle, &eventMask, &overlap);
        }
        return true;
    }
    return false;
}
예제 #7
0
void QextSerialPortPrivate::setBaudRate(BaudRateType baudRate, bool update)
{
    switch (baudRate) {
#ifdef Q_OS_WIN
    //Windows Special
    case BAUD14400:
    case BAUD56000:
    case BAUD128000:
    case BAUD256000:
        QESP_PORTABILITY_WARNING()<<"QextSerialPort Portability Warning: POSIX does not support baudRate:"<<baudRate;
#elif defined(Q_OS_UNIX)
    //Unix Special
    case BAUD50:
    case BAUD75:
    case BAUD134:
    case BAUD150:
    case BAUD200:
    case BAUD1800:
#  ifdef B76800
    case BAUD76800:
#  endif
#  if defined(B230400) && defined(B4000000)
    case BAUD230400:
    case BAUD250000:
    case BAUD460800:
    case BAUD500000:
    case BAUD576000:
    case BAUD921600:
    case BAUD1000000:
    case BAUD1152000:
    case BAUD1500000:
    case BAUD2000000:
    case BAUD2500000:
    case BAUD3000000:
    case BAUD3500000:
    case BAUD4000000:
#  endif
        QESP_PORTABILITY_WARNING()<<"QextSerialPort Portability Warning: Windows does not support baudRate:"<<baudRate;
#endif
    case BAUD110:
    case BAUD300:
    case BAUD600:
    case BAUD1200:
    case BAUD2400:
    case BAUD4800:
    case BAUD9600:
    case BAUD19200:
    case BAUD38400:
    case BAUD57600:
    case BAUD115200:
#ifdef Q_OS_WIN
    default:
#endif
        Settings.BaudRate=baudRate;
        settingsDirtyFlags |= DFE_BaudRate;
        if (update && q_func()->isOpen())
            updatePortSettings();
        break;
#ifndef Q_OS_WIN
    default:
        QESP_WARNING()<<"QextSerialPort does not support baudRate:"<<baudRate;
#endif
    }
}
예제 #8
0
/*
  Create matching dictionaries for the devices we want to get notifications for,
  and add them to the current run loop.  Invoke the callbacks that will be responding
  to these notifications once to arm them, and discover any devices that
  are currently connected at the time notifications are setup.
*/
bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool /*setup*/)
{
    kern_return_t kernResult;
    mach_port_t masterPort;
    CFRunLoopSourceRef notificationRunLoopSource;
    CFMutableDictionaryRef classesToMatch;
    CFMutableDictionaryRef cdcClassesToMatch;
    io_iterator_t portIterator;

    kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort);
    if (KERN_SUCCESS != kernResult) {
        qDebug() << "IOMasterPort returned:" << kernResult;
        return false;
    }

    classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
    if (classesToMatch == nullptr)
        qDebug("IOServiceMatching returned a nullptr dictionary.");
    else
        CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));

    if (!(cdcClassesToMatch = IOServiceNameMatching("AppleUSBCDC"))) {
        QESP_WARNING("couldn't create cdc matching dict");
        return false;
    }

    // Retain an additional reference since each call to IOServiceAddMatchingNotification consumes one.
    classesToMatch = (CFMutableDictionaryRef) CFRetain(classesToMatch);
    cdcClassesToMatch = (CFMutableDictionaryRef) CFRetain(cdcClassesToMatch);

    notificationPortRef = IONotificationPortCreate(masterPort);
    if (notificationPortRef == nullptr) {
        qDebug("IONotificationPortCreate return a nullptr IONotificationPortRef.");
        return false;
    }

    notificationRunLoopSource = IONotificationPortGetRunLoopSource(notificationPortRef);
    if (notificationRunLoopSource == nullptr) {
        qDebug("IONotificationPortGetRunLoopSource returned nullptr CFRunLoopSourceRef.");
        return false;
    }

    CFRunLoopAddSource(CFRunLoopGetCurrent(), notificationRunLoopSource, kCFRunLoopDefaultMode);

    kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOMatchedNotification, classesToMatch,
                                                  deviceDiscoveredCallbackOSX, this, &portIterator);
    if (kernResult != KERN_SUCCESS) {
        qDebug() << "IOServiceAddMatchingNotification return:" << kernResult;
        return false;
    }

    // arm the callback, and grab any devices that are already connected
    deviceDiscoveredCallbackOSX(this, portIterator);

    kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOMatchedNotification, cdcClassesToMatch,
                                                  deviceDiscoveredCallbackOSX, this, &portIterator);
    if (kernResult != KERN_SUCCESS) {
        qDebug() << "IOServiceAddMatchingNotification return:" << kernResult;
        return false;
    }

    // arm the callback, and grab any devices that are already connected
    deviceDiscoveredCallbackOSX(this, portIterator);

    kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOTerminatedNotification, classesToMatch,
                                                  deviceTerminatedCallbackOSX, this, &portIterator);
    if (kernResult != KERN_SUCCESS) {
        qDebug() << "IOServiceAddMatchingNotification return:" << kernResult;
        return false;
    }

    // arm the callback, and clear any devices that are terminated
    deviceTerminatedCallbackOSX(this, portIterator);

    kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOTerminatedNotification, cdcClassesToMatch,
                                                  deviceTerminatedCallbackOSX, this, &portIterator);
    if (kernResult != KERN_SUCCESS) {
        qDebug() << "IOServiceAddMatchingNotification return:" << kernResult;
        return false;
    }

    // arm the callback, and clear any devices that are terminated
    deviceTerminatedCallbackOSX(this, portIterator);
    return true;
}
bool QextSerialEnumeratorPrivate::setUpNotifications_sys(bool setup) {
    Q_UNUSED(setup)
    QESP_WARNING("Notifications for *Nix/FreeBSD are not implemented yet");
    return false;
}
QList<QextPortInfo> QextSerialEnumeratorPrivate::getPorts_sys() {
    QList<QextPortInfo> infoList;
    QESP_WARNING("Enumeration for POSIX systems (except Linux) is not implemented yet.");
    return infoList;
}