mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-02-21 11:54:15 +01:00
OP-334 OP-332 Linux usb monitor working fine now, and rawhidplugin.cpp updated to use this new mechanism, no more polling thread opening the device every second!
git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@2957 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
parent
623bdb6298
commit
e4535ed575
@ -358,7 +358,7 @@ void pjrc_rawhid::hid_close(hid_t *hid)
|
|||||||
if (!hid) return;
|
if (!hid) return;
|
||||||
if (!hid->open) return;
|
if (!hid->open) return;
|
||||||
|
|
||||||
usb_release_interface(hid->usb, hid->iface);
|
usb_release_interface(hid->usb, hid->iface);
|
||||||
|
|
||||||
int others = 0;
|
int others = 0;
|
||||||
for (hid_t *p = first_hid; p; p = p->next)
|
for (hid_t *p = first_hid; p; p = p->next)
|
||||||
@ -370,4 +370,5 @@ void pjrc_rawhid::hid_close(hid_t *hid)
|
|||||||
usb_close(hid->usb);
|
usb_close(hid->usb);
|
||||||
|
|
||||||
hid->usb = NULL;
|
hid->usb = NULL;
|
||||||
|
hid->open = 0;
|
||||||
}
|
}
|
||||||
|
@ -36,83 +36,19 @@
|
|||||||
|
|
||||||
#include "rawhid_const.h"
|
#include "rawhid_const.h"
|
||||||
|
|
||||||
// **********************************************************************
|
|
||||||
|
|
||||||
RawHIDEnumerationThread::RawHIDEnumerationThread(RawHIDConnection *rawhid) :
|
|
||||||
QThread(rawhid), // Pip
|
|
||||||
m_rawhid(rawhid),
|
|
||||||
m_running(true)
|
|
||||||
{
|
|
||||||
if (m_rawhid)
|
|
||||||
connect(m_rawhid, SLOT(destroyed(QObject *)), this, SLOT(onRawHidConnectionDestroyed(QObject *))); // Pip
|
|
||||||
}
|
|
||||||
|
|
||||||
RawHIDEnumerationThread::~RawHIDEnumerationThread()
|
|
||||||
{
|
|
||||||
m_rawhid = NULL; // safe guard
|
|
||||||
|
|
||||||
m_running = false;
|
|
||||||
|
|
||||||
// wait for the thread to terminate
|
|
||||||
if (!wait(100))
|
|
||||||
qDebug() << "Cannot terminate RawHIDEnumerationThread";
|
|
||||||
}
|
|
||||||
|
|
||||||
void RawHIDEnumerationThread::onRawHidConnectionDestroyed(QObject *obj) // Pip
|
|
||||||
{
|
|
||||||
if (!m_rawhid || m_rawhid != obj)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_rawhid = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RawHIDEnumerationThread::run()
|
|
||||||
{
|
|
||||||
QStringList devices = m_rawhid->availableDevices();
|
|
||||||
|
|
||||||
int counter = 0;
|
|
||||||
|
|
||||||
while (m_running)
|
|
||||||
{
|
|
||||||
// update available devices every second (doesn't need more)
|
|
||||||
if (m_rawhid)
|
|
||||||
{
|
|
||||||
if (!m_rawhid->deviceOpened()) // this was stopping us getting enumerations changes fed back
|
|
||||||
{
|
|
||||||
if (++counter >= 100)
|
|
||||||
{
|
|
||||||
counter = 0;
|
|
||||||
|
|
||||||
QStringList newDev = m_rawhid->availableDevices();
|
|
||||||
if (devices != newDev)
|
|
||||||
{
|
|
||||||
devices = newDev;
|
|
||||||
emit enumerationChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// else
|
|
||||||
// counter = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
counter = 0;
|
|
||||||
|
|
||||||
msleep(10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// **********************************************************************
|
// **********************************************************************
|
||||||
|
|
||||||
RawHIDConnection::RawHIDConnection()
|
RawHIDConnection::RawHIDConnection()
|
||||||
: m_enumerateThread(this)
|
: m_usbMonitor(this)
|
||||||
{
|
{
|
||||||
//added by andrew
|
//added by andrew
|
||||||
RawHidHandle = NULL;
|
RawHidHandle = NULL;
|
||||||
enablePolling = true;
|
enablePolling = true;
|
||||||
|
|
||||||
QObject::connect(&m_enumerateThread, SIGNAL(enumerationChanged()), this, SLOT(onEnumerationChanged()));
|
connect(&m_usbMonitor, SIGNAL(deviceDiscovered(USBPortInfo)), this, SLOT(onDeviceConnected()));
|
||||||
|
connect(&m_usbMonitor, SIGNAL(deviceRemoved(USBPortInfo)), this, SLOT(onDeviceDisconnected()));
|
||||||
|
|
||||||
m_enumerateThread.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RawHIDConnection::~RawHIDConnection()
|
RawHIDConnection::~RawHIDConnection()
|
||||||
@ -122,47 +58,42 @@ RawHIDConnection::~RawHIDConnection()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RawHIDConnection::onEnumerationChanged()
|
/**
|
||||||
|
The USB monitor tells us a new device appeared
|
||||||
|
*/
|
||||||
|
void RawHIDConnection::onDeviceConnected()
|
||||||
{
|
{
|
||||||
if (RawHidHandle) // Pip
|
emit availableDevChanged(this);
|
||||||
{ // check to see if the connection has closed
|
}
|
||||||
if (!RawHidHandle->isOpen())
|
|
||||||
{ // connection has closed .. hmmmm, this connection is still showing as open after the USB device is unplugged from PC
|
|
||||||
delete RawHidHandle;
|
|
||||||
RawHidHandle = NULL;
|
|
||||||
|
|
||||||
emit deviceClosed(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
The USB monitor tells us a device disappeard
|
||||||
|
*/
|
||||||
|
void RawHIDConnection::onDeviceDisconnected()
|
||||||
|
{
|
||||||
|
emit deviceClosed(this);
|
||||||
if (enablePolling)
|
if (enablePolling)
|
||||||
emit availableDevChanged(this);
|
emit availableDevChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the list of all currently available devices
|
||||||
|
*/
|
||||||
QStringList RawHIDConnection::availableDevices()
|
QStringList RawHIDConnection::availableDevices()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_enumMutex);
|
|
||||||
|
|
||||||
QStringList devices;
|
QStringList devices;
|
||||||
|
|
||||||
if (enablePolling)
|
QList<USBPortInfo> portsList = m_usbMonitor.availableDevices();
|
||||||
{
|
// We currently list devices by their serial number
|
||||||
pjrc_rawhid dev;
|
foreach(USBPortInfo prt, portsList) {
|
||||||
|
devices.append(prt.serialNumber);
|
||||||
// open all device we can
|
|
||||||
int opened = dev.open(USB_MAX_DEVICES, USB_VID, USB_PID, USB_USAGE_PAGE, USB_USAGE);
|
|
||||||
|
|
||||||
// for each devices found, get serial number and close it back
|
|
||||||
for (int i = 0; i < opened; i++)
|
|
||||||
{
|
|
||||||
devices.append(dev.getserial(i));
|
|
||||||
dev.close(i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return devices;
|
return devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// TODO: still needed ???
|
||||||
void RawHIDConnection::onRawHidDestroyed(QObject *obj) // Pip
|
void RawHIDConnection::onRawHidDestroyed(QObject *obj) // Pip
|
||||||
{
|
{
|
||||||
if (!RawHidHandle || RawHidHandle != obj)
|
if (!RawHidHandle || RawHidHandle != obj)
|
||||||
@ -171,13 +102,11 @@ void RawHIDConnection::onRawHidDestroyed(QObject *obj) // Pip
|
|||||||
RawHidHandle = NULL;
|
RawHidHandle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// TODO: still needed ???
|
||||||
void RawHIDConnection::onRawHidClosed()
|
void RawHIDConnection::onRawHidClosed()
|
||||||
{
|
{
|
||||||
if (RawHidHandle)
|
if (RawHidHandle)
|
||||||
{
|
{
|
||||||
// delete RawHidHandle;
|
|
||||||
// RawHidHandle = NULL;
|
|
||||||
|
|
||||||
emit deviceClosed(this);
|
emit deviceClosed(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,6 +130,7 @@ QIODevice *RawHIDConnection::openDevice(const QString &deviceName)
|
|||||||
return RawHidHandle;
|
return RawHidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RawHIDConnection::closeDevice(const QString &deviceName)
|
void RawHIDConnection::closeDevice(const QString &deviceName)
|
||||||
{
|
{
|
||||||
Q_UNUSED(deviceName);
|
Q_UNUSED(deviceName);
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include "rawhid_global.h"
|
#include "rawhid_global.h"
|
||||||
#include "rawhid.h"
|
#include "rawhid.h"
|
||||||
|
#include "usbmonitor.h"
|
||||||
|
|
||||||
#include "coreplugin/iconnection.h"
|
#include "coreplugin/iconnection.h"
|
||||||
#include <extensionsystem/iplugin.h>
|
#include <extensionsystem/iplugin.h>
|
||||||
@ -41,32 +42,6 @@ class IConnection;
|
|||||||
class RawHIDConnection;
|
class RawHIDConnection;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper thread to check on device connection/disconnection
|
|
||||||
* Underlying HID library is not really easy to use,
|
|
||||||
* so we have to poll for device modification in a separate thread
|
|
||||||
*/
|
|
||||||
class RAWHID_EXPORT RawHIDEnumerationThread : public QThread
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
RawHIDEnumerationThread(RawHIDConnection *rawhid);
|
|
||||||
virtual ~RawHIDEnumerationThread();
|
|
||||||
|
|
||||||
virtual void run();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void enumerationChanged();
|
|
||||||
|
|
||||||
protected slots:
|
|
||||||
void onRawHidConnectionDestroyed(QObject *obj); // Pip
|
|
||||||
|
|
||||||
protected:
|
|
||||||
RawHIDConnection *m_rawhid;
|
|
||||||
bool m_running;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a connection via the IConnection interface
|
* Define a connection via the IConnection interface
|
||||||
* Plugin will add a instance of this class to the pool,
|
* Plugin will add a instance of this class to the pool,
|
||||||
@ -89,7 +64,7 @@ public:
|
|||||||
virtual void suspendPolling();
|
virtual void suspendPolling();
|
||||||
virtual void resumePolling();
|
virtual void resumePolling();
|
||||||
|
|
||||||
bool deviceOpened() { return (RawHidHandle != NULL); } // Pip
|
bool deviceOpened() { return (RawHidHandle != NULL); } // Pip
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void deviceClosed(QObject *obj); // Pip
|
void deviceClosed(QObject *obj); // Pip
|
||||||
@ -98,10 +73,11 @@ public slots:
|
|||||||
void onRawHidClosed();
|
void onRawHidClosed();
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void onEnumerationChanged();
|
void onDeviceConnected();
|
||||||
|
void onDeviceDisconnected();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onRawHidDestroyed(QObject *obj);
|
void onRawHidDestroyed(QObject *obj);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RawHID *RawHidHandle;
|
RawHID *RawHidHandle;
|
||||||
@ -109,7 +85,7 @@ private:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
QMutex m_enumMutex;
|
QMutex m_enumMutex;
|
||||||
RawHIDEnumerationThread m_enumerateThread;
|
USBMonitor m_usbMonitor;
|
||||||
bool m_deviceOpened;
|
bool m_deviceOpened;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -42,12 +42,12 @@ void USBMonitor::deviceEventReceived() {
|
|||||||
|
|
||||||
dev = udev_monitor_receive_device(this->monitor);
|
dev = udev_monitor_receive_device(this->monitor);
|
||||||
if (dev) {
|
if (dev) {
|
||||||
printf("Got Device");
|
printf("------- Got Device Event");
|
||||||
QString action = QString(udev_device_get_action(dev));
|
QString action = QString(udev_device_get_action(dev));
|
||||||
if (action == "add") {
|
QString devtype = QString(udev_device_get_devtype(dev));
|
||||||
|
if (action == "add" && devtype == "usb_device") {
|
||||||
emit deviceDiscovered(makePortInfo(dev));
|
emit deviceDiscovered(makePortInfo(dev));
|
||||||
|
} else if (action == "remove" && devtype == "usb_device"){
|
||||||
} else if (action == "remove"){
|
|
||||||
emit deviceRemoved(makePortInfo(dev));
|
emit deviceRemoved(makePortInfo(dev));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,8 +67,8 @@ USBMonitor::USBMonitor(QObject *parent): QThread(parent) {
|
|||||||
this->context = udev_new();
|
this->context = udev_new();
|
||||||
|
|
||||||
this->monitor = udev_monitor_new_from_netlink(this->context, "udev");
|
this->monitor = udev_monitor_new_from_netlink(this->context, "udev");
|
||||||
// udev_monitor_filter_add_match_subsystem_devtype(
|
udev_monitor_filter_add_match_subsystem_devtype(
|
||||||
// this->monitor, "hidraw", NULL);
|
this->monitor, "usb", NULL);
|
||||||
udev_monitor_enable_receiving(this->monitor);
|
udev_monitor_enable_receiving(this->monitor);
|
||||||
this->monitorNotifier = new QSocketNotifier(
|
this->monitorNotifier = new QSocketNotifier(
|
||||||
udev_monitor_get_fd(this->monitor), QSocketNotifier::Read, this);
|
udev_monitor_get_fd(this->monitor), QSocketNotifier::Read, this);
|
||||||
@ -95,7 +95,8 @@ QList<USBPortInfo> USBMonitor::availableDevices()
|
|||||||
struct udev_device *dev;
|
struct udev_device *dev;
|
||||||
|
|
||||||
enumerate = udev_enumerate_new(this->context);
|
enumerate = udev_enumerate_new(this->context);
|
||||||
udev_enumerate_add_match_subsystem(enumerate,"hidwraw");
|
// udev_enumerate_add_match_subsystem(enumerate,"usb");
|
||||||
|
udev_enumerate_add_match_sysattr(enumerate, "idVendor", "20a0");
|
||||||
udev_enumerate_scan_devices(enumerate);
|
udev_enumerate_scan_devices(enumerate);
|
||||||
devices = udev_enumerate_get_list_entry(enumerate);
|
devices = udev_enumerate_get_list_entry(enumerate);
|
||||||
// Will use the 'native' udev functions to loop:
|
// Will use the 'native' udev functions to loop:
|
||||||
@ -113,6 +114,7 @@ QList<USBPortInfo> USBMonitor::availableDevices()
|
|||||||
subsystem/devtype pair of "usb"/"usb_device". This will
|
subsystem/devtype pair of "usb"/"usb_device". This will
|
||||||
be several levels up the tree, but the function will find
|
be several levels up the tree, but the function will find
|
||||||
it.*/
|
it.*/
|
||||||
|
/*
|
||||||
dev = udev_device_get_parent_with_subsystem_devtype(
|
dev = udev_device_get_parent_with_subsystem_devtype(
|
||||||
dev,
|
dev,
|
||||||
"usb",
|
"usb",
|
||||||
@ -121,24 +123,10 @@ QList<USBPortInfo> USBMonitor::availableDevices()
|
|||||||
printf("Unable to find parent usb device.");
|
printf("Unable to find parent usb device.");
|
||||||
return devicesList;
|
return devicesList;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/* From here, we can call get_sysattr_value() for each file
|
|
||||||
in the device's /sys entry. The strings passed into these
|
|
||||||
functions (idProduct, idVendor, serial, etc.) correspond
|
|
||||||
directly to the files in the directory which represents
|
|
||||||
the USB device. Note that USB strings are Unicode, UCS2
|
|
||||||
encoded, but the strings returned from
|
|
||||||
udev_device_get_sysattr_value() are UTF-8 encoded. */
|
|
||||||
printf(" VID/PID: %s %s\n",
|
|
||||||
udev_device_get_sysattr_value(dev,"idVendor"),
|
|
||||||
udev_device_get_sysattr_value(dev, "idProduct"));
|
|
||||||
printf(" %s\n %s\n",
|
|
||||||
udev_device_get_sysattr_value(dev,"manufacturer"),
|
|
||||||
udev_device_get_sysattr_value(dev,"product"));
|
|
||||||
printf(" serial: %s\n",
|
|
||||||
udev_device_get_sysattr_value(dev, "serial"));
|
|
||||||
devicesList.append(makePortInfo(dev));
|
devicesList.append(makePortInfo(dev));
|
||||||
udev_device_unref(dev);
|
udev_device_unref(dev);
|
||||||
}
|
}
|
||||||
/* free the enumerator object */
|
/* free the enumerator object */
|
||||||
udev_enumerate_unref(enumerate);
|
udev_enumerate_unref(enumerate);
|
||||||
@ -171,6 +159,21 @@ USBPortInfo USBMonitor::makePortInfo(struct udev_device *dev)
|
|||||||
printf(" Subsystem: %s", udev_device_get_subsystem(dev));
|
printf(" Subsystem: %s", udev_device_get_subsystem(dev));
|
||||||
printf(" Devtype: %s", udev_device_get_devtype(dev));
|
printf(" Devtype: %s", udev_device_get_devtype(dev));
|
||||||
printf(" Action: %s", udev_device_get_action(dev));
|
printf(" Action: %s", udev_device_get_action(dev));
|
||||||
|
/* From here, we can call get_sysattr_value() for each file
|
||||||
|
in the device's /sys entry. The strings passed into these
|
||||||
|
functions (idProduct, idVendor, serial, etc.) correspond
|
||||||
|
directly to the files in the directory which represents
|
||||||
|
the USB device. Note that USB strings are Unicode, UCS2
|
||||||
|
encoded, but the strings returned from
|
||||||
|
udev_device_get_sysattr_value() are UTF-8 encoded. */
|
||||||
|
printf(" VID/PID: %s %s",
|
||||||
|
udev_device_get_sysattr_value(dev,"idVendor"),
|
||||||
|
udev_device_get_sysattr_value(dev, "idProduct"));
|
||||||
|
printf(" %s - %s",
|
||||||
|
udev_device_get_sysattr_value(dev,"manufacturer"),
|
||||||
|
udev_device_get_sysattr_value(dev,"product"));
|
||||||
|
printf(" serial: %s",
|
||||||
|
udev_device_get_sysattr_value(dev, "serial"));
|
||||||
|
|
||||||
prtInfo.vendorID = QString(udev_device_get_sysattr_value(dev, "idVendor")).toInt();
|
prtInfo.vendorID = QString(udev_device_get_sysattr_value(dev, "idVendor")).toInt();
|
||||||
prtInfo.productID = QString(udev_device_get_sysattr_value(dev, "idProduct")).toInt();
|
prtInfo.productID = QString(udev_device_get_sysattr_value(dev, "idProduct")).toInt();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user