Commit e5ff5501 authored by Bryant's avatar Bryant

Removed unnecessary qextserialport libray.

Replaced by /libs/serialport
parent 9d32ca15
/*!
* \file qextserialenumerator.h
* \author Michal Policht
* \see QextSerialEnumerator
*/
#ifndef _QEXTSERIALENUMERATOR_H_
#define _QEXTSERIALENUMERATOR_H_
#include <QtCore/qglobal.h>
//#ifdef QEXTSERIALPORT_LIB
//# define QEXTSERIALPORT_EXPORT Q_DECL_EXPORT
//#else
//# define QEXTSERIALPORT_EXPORT Q_DECL_IMPORT
//#endif
#define QEXTSERIALPORT_EXPORT
#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_*/
This diff is collapsed.
#include "qextserialenumerator.h"
#include <QDebug>
#include <QMetaType>
#include <QStringList>
#include <QDir>
QextSerialEnumerator::QextSerialEnumerator( )
{
if( !QMetaType::isRegistered( QMetaType::type("QextPortInfo") ) )
qRegisterMetaType<QextPortInfo>("QextPortInfo");
}
QextSerialEnumerator::~QextSerialEnumerator( )
{
}
QList<QextPortInfo> QextSerialEnumerator::getPorts()
{
QList<QextPortInfo> infoList;
#ifdef Q_OS_LINUX
QStringList portNamePrefixes, portNameList;
portNamePrefixes << "ttyS*"; // list normal serial ports first
QDir dir("/dev");
portNameList = dir.entryList(portNamePrefixes, (QDir::System | QDir::Files), QDir::Name);
// remove the values which are not serial ports for e.g. /dev/ttysa
for (int i = 0; i < portNameList.size(); i++) {
bool ok;
QString current = portNameList.at(i);
// remove the ttyS part, and check, if the other part is a number
current.remove(0,4).toInt(&ok, 10);
if (!ok) {
portNameList.removeAt(i);
i--;
}
}
// get the non standard serial ports names
// (USB-serial, bluetooth-serial, 18F PICs, and so on)
// if you know an other name prefix for serial ports please let us know
portNamePrefixes.clear();
portNamePrefixes << "ttyACM*" << "ttyUSB*" << "rfcomm*";
portNameList.append(dir.entryList(portNamePrefixes, (QDir::System | QDir::Files), QDir::Name));
foreach (QString str , portNameList) {
QextPortInfo inf;
inf.physName = "/dev/"+str;
inf.portName = str;
if (str.contains("ttyS")) {
inf.friendName = "Serial port "+str.remove(0, 4);
}
else if (str.contains("ttyUSB")) {
inf.friendName = "USB-serial adapter "+str.remove(0, 6);
}
else if (str.contains("rfcomm")) {
inf.friendName = "Bluetooth-serial adapter "+str.remove(0, 6);
}
inf.enumName = "/dev"; // is there a more helpful name for this?
infoList.append(inf);
}
#else
qCritical("Enumeration for POSIX systems (except Linux) is not implemented yet.");
#endif
return infoList;
}
void QextSerialEnumerator::setUpNotifications( )
{
qCritical("Notifications for *Nix/FreeBSD are not implemented yet");
}
#include "qextserialenumerator.h"
#include <QDebug>
#include <QMetaType>
#include <objbase.h>
#include <initguid.h>
//#include "qextserialport.h"
#include <QRegExp>
#ifdef Q_OS_WIN
#ifndef _MSC_VER
#include <windows.h>
#include <dbt.h>
#include <QtCore/qglobal.h>
#endif
#endif
QextSerialEnumerator::QextSerialEnumerator( )
{
if( !QMetaType::isRegistered( QMetaType::type("QextPortInfo") ) )
qRegisterMetaType<QextPortInfo>("QextPortInfo");
#if (defined QT_GUI_LIB)
notificationWidget = 0;
#endif // Q_OS_WIN
}
QextSerialEnumerator::~QextSerialEnumerator( )
{
#if (defined QT_GUI_LIB)
if( notificationWidget )
delete notificationWidget;
#endif
}
// see http://msdn.microsoft.com/en-us/library/ms791134.aspx for list of GUID classes
#ifndef GUID_DEVCLASS_PORTS
DEFINE_GUID(GUID_DEVCLASS_PORTS, 0x4D36E978, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 );
#endif
/* Gordon Schumacher's macros for TCHAR -> QString conversions and vice versa */
#ifdef UNICODE
#define QStringToTCHAR(x) (wchar_t*) x.utf16()
#define PQStringToTCHAR(x) (wchar_t*) x->utf16()
#define TCHARToQString(x) QString::fromUtf16((ushort*)(x))
#define TCHARToQStringN(x,y) QString::fromUtf16((ushort*)(x),(y))
#else
#define QStringToTCHAR(x) x.local8Bit().constData()
#define PQStringToTCHAR(x) x->local8Bit().constData()
#define TCHARToQString(x) QString::fromLocal8Bit((x))
#define TCHARToQStringN(x,y) QString::fromLocal8Bit((x),(y))
#endif /*UNICODE*/
//static
QString QextSerialEnumerator::getRegKeyValue(HKEY key, LPCTSTR property)
{
DWORD size = 0;
DWORD type;
RegQueryValueEx(key, property, NULL, NULL, NULL, & size);
BYTE* buff = new BYTE[size];
QString result;
if( RegQueryValueEx(key, property, NULL, &type, buff, & size) == ERROR_SUCCESS )
result = TCHARToQString(buff);
RegCloseKey(key);
delete [] buff;
return result;
}
//static
QString QextSerialEnumerator::getDeviceProperty(HDEVINFO devInfo, PSP_DEVINFO_DATA devData, DWORD property)
{
DWORD buffSize = 0;
SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, NULL, 0, & buffSize);
BYTE* buff = new BYTE[buffSize];
SetupDiGetDeviceRegistryProperty(devInfo, devData, property, NULL, buff, buffSize, NULL);
QString result = TCHARToQString(buff);
delete [] buff;
return result;
}
QList<QextPortInfo> QextSerialEnumerator::getPorts()
{
QList<QextPortInfo> ports;
enumerateDevicesWin(GUID_DEVCLASS_PORTS, &ports);
return ports;
}
void QextSerialEnumerator::enumerateDevicesWin( const GUID & guid, QList<QextPortInfo>* infoList )
{
HDEVINFO devInfo;
if( (devInfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT)) != INVALID_HANDLE_VALUE)
{
SP_DEVINFO_DATA devInfoData;
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for(int i = 0; SetupDiEnumDeviceInfo(devInfo, i, &devInfoData); i++)
{
QextPortInfo info;
info.productID = info.vendorID = 0;
getDeviceDetailsWin( &info, devInfo, &devInfoData );
infoList->append(info);
}
SetupDiDestroyDeviceInfoList(devInfo);
}
}
#ifdef QT_GUI_LIB
bool QextSerialRegistrationWidget::winEvent( MSG* message, long* result )
{
if ( message->message == WM_DEVICECHANGE ) {
qese->onDeviceChangeWin( message->wParam, message->lParam );
*result = 1;
return true;
}
return false;
}
#endif
void QextSerialEnumerator::setUpNotifications( )
{
#ifdef QT_GUI_LIB
if(notificationWidget)
return;
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( notificationWidget->winId( ), &dbh, DEVICE_NOTIFY_WINDOW_HANDLE ) == NULL)
qWarning() << "RegisterDeviceNotification failed:" << GetLastError();
// setting up notifications doesn't tell us about devices already connected
// so get those manually
foreach( QextPortInfo port, getPorts() )
emit deviceDiscovered( port );
#else
qWarning("QextSerialEnumerator: GUI not enabled - can't register for device notifications.");
#endif // QT_GUI_LIB
}
LRESULT QextSerialEnumerator::onDeviceChangeWin( WPARAM wParam, LPARAM lParam )
{
if ( DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam )
{
PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
if( pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE )
{
PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;
// delimiters are different across APIs...change to backslash. ugh.
QString deviceID = TCHARToQString(pDevInf->dbcc_name).toUpper().replace("#", "\\");
matchAndDispatchChangedDevice(deviceID, GUID_DEVCLASS_PORTS, wParam);
}
}
return 0;
}
bool QextSerialEnumerator::matchAndDispatchChangedDevice(const QString & deviceID, const GUID & guid, WPARAM wParam)
{
bool rv = false;
DWORD dwFlag = (DBT_DEVICEARRIVAL == wParam) ? DIGCF_PRESENT : DIGCF_ALLCLASSES;
HDEVINFO devInfo;
if( (devInfo = SetupDiGetClassDevs(&guid,NULL,NULL,dwFlag)) != INVALID_HANDLE_VALUE )
{
SP_DEVINFO_DATA spDevInfoData;
spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for(int i=0; SetupDiEnumDeviceInfo(devInfo, i, &spDevInfoData); i++)
{
DWORD nSize=0 ;
TCHAR buf[MAX_PATH];
if ( SetupDiGetDeviceInstanceId(devInfo, &spDevInfoData, buf, MAX_PATH, &nSize) &&
deviceID.contains(TCHARToQString(buf))) // we found a match
{
rv = true;
QextPortInfo info;
info.productID = info.vendorID = 0;
getDeviceDetailsWin( &info, devInfo, &spDevInfoData, wParam );
if( wParam == DBT_DEVICEARRIVAL )
emit deviceDiscovered(info);
else if( wParam == DBT_DEVICEREMOVECOMPLETE )
emit deviceRemoved(info);
break;
}
}
SetupDiDestroyDeviceInfoList(devInfo);
}
return rv;
}
bool QextSerialEnumerator::getDeviceDetailsWin( QextPortInfo* portInfo, HDEVINFO devInfo, PSP_DEVINFO_DATA devData, WPARAM wParam )
{
portInfo->friendName = getDeviceProperty(devInfo, devData, SPDRP_FRIENDLYNAME);
if( wParam == DBT_DEVICEARRIVAL)
portInfo->physName = getDeviceProperty(devInfo, devData, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME);
portInfo->enumName = getDeviceProperty(devInfo, devData, SPDRP_ENUMERATOR_NAME);
QString hardwareIDs = getDeviceProperty(devInfo, devData, SPDRP_HARDWAREID);
HKEY devKey = SetupDiOpenDevRegKey(devInfo, devData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
QRegExp rx("^COM(\\d+)");
QString fullName(getRegKeyValue(devKey, TEXT("PortName")));
if(fullName.contains(rx)) {
int portnum = rx.cap(1).toInt();
if(portnum > 9) // COM ports greater than 9 need \\.\ prepended
fullName.prepend("\\\\.\\");
}
portInfo->portName = fullName;
QRegExp idRx("VID_(\\w+)&PID_(\\w+)");
if( hardwareIDs.toUpper().contains(idRx) )
{
bool dummy;
portInfo->vendorID = idRx.cap(1).toInt(&dummy, 16);
portInfo->productID = idRx.cap(2).toInt(&dummy, 16);
//qDebug() << "got vid:" << vid << "pid:" << pid;
}
return true;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment