1
0
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:
edouard 2011-03-03 21:44:59 +00:00 committed by edouard
parent 623bdb6298
commit e4535ed575
4 changed files with 60 additions and 150 deletions

View File

@ -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;
} }

View File

@ -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);

View File

@ -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;
}; };

View File

@ -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();