1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-02-19 09: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->open) return;
usb_release_interface(hid->usb, hid->iface);
usb_release_interface(hid->usb, hid->iface);
int others = 0;
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);
hid->usb = NULL;
hid->open = 0;
}

View File

@ -36,83 +36,19 @@
#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()
: m_enumerateThread(this)
: m_usbMonitor(this)
{
//added by andrew
RawHidHandle = NULL;
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()
@ -122,47 +58,42 @@ RawHIDConnection::~RawHIDConnection()
}
}
void RawHIDConnection::onEnumerationChanged()
/**
The USB monitor tells us a new device appeared
*/
void RawHIDConnection::onDeviceConnected()
{
if (RawHidHandle) // Pip
{ // 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);
}
}
emit availableDevChanged(this);
}
/**
The USB monitor tells us a device disappeard
*/
void RawHIDConnection::onDeviceDisconnected()
{
emit deviceClosed(this);
if (enablePolling)
emit availableDevChanged(this);
}
/**
Returns the list of all currently available devices
*/
QStringList RawHIDConnection::availableDevices()
{
QMutexLocker locker(&m_enumMutex);
QStringList devices;
if (enablePolling)
{
pjrc_rawhid dev;
// 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);
}
QList<USBPortInfo> portsList = m_usbMonitor.availableDevices();
// We currently list devices by their serial number
foreach(USBPortInfo prt, portsList) {
devices.append(prt.serialNumber);
}
return devices;
}
/// TODO: still needed ???
void RawHIDConnection::onRawHidDestroyed(QObject *obj) // Pip
{
if (!RawHidHandle || RawHidHandle != obj)
@ -171,13 +102,11 @@ void RawHIDConnection::onRawHidDestroyed(QObject *obj) // Pip
RawHidHandle = NULL;
}
/// TODO: still needed ???
void RawHIDConnection::onRawHidClosed()
{
if (RawHidHandle)
{
// delete RawHidHandle;
// RawHidHandle = NULL;
emit deviceClosed(this);
}
}
@ -201,6 +130,7 @@ QIODevice *RawHIDConnection::openDevice(const QString &deviceName)
return RawHidHandle;
}
void RawHIDConnection::closeDevice(const QString &deviceName)
{
Q_UNUSED(deviceName);

View File

@ -30,6 +30,7 @@
#include "rawhid_global.h"
#include "rawhid.h"
#include "usbmonitor.h"
#include "coreplugin/iconnection.h"
#include <extensionsystem/iplugin.h>
@ -41,32 +42,6 @@ class IConnection;
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
* Plugin will add a instance of this class to the pool,
@ -89,7 +64,7 @@ public:
virtual void suspendPolling();
virtual void resumePolling();
bool deviceOpened() { return (RawHidHandle != NULL); } // Pip
bool deviceOpened() { return (RawHidHandle != NULL); } // Pip
signals:
void deviceClosed(QObject *obj); // Pip
@ -98,10 +73,11 @@ public slots:
void onRawHidClosed();
protected slots:
void onEnumerationChanged();
void onDeviceConnected();
void onDeviceDisconnected();
private slots:
void onRawHidDestroyed(QObject *obj);
void onRawHidDestroyed(QObject *obj);
private:
RawHID *RawHidHandle;
@ -109,7 +85,7 @@ private:
protected:
QMutex m_enumMutex;
RawHIDEnumerationThread m_enumerateThread;
USBMonitor m_usbMonitor;
bool m_deviceOpened;
};

View File

@ -42,12 +42,12 @@ void USBMonitor::deviceEventReceived() {
dev = udev_monitor_receive_device(this->monitor);
if (dev) {
printf("Got Device");
printf("------- Got Device Event");
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));
} else if (action == "remove"){
} else if (action == "remove" && devtype == "usb_device"){
emit deviceRemoved(makePortInfo(dev));
}
@ -67,8 +67,8 @@ USBMonitor::USBMonitor(QObject *parent): QThread(parent) {
this->context = udev_new();
this->monitor = udev_monitor_new_from_netlink(this->context, "udev");
// udev_monitor_filter_add_match_subsystem_devtype(
// this->monitor, "hidraw", NULL);
udev_monitor_filter_add_match_subsystem_devtype(
this->monitor, "usb", NULL);
udev_monitor_enable_receiving(this->monitor);
this->monitorNotifier = new QSocketNotifier(
udev_monitor_get_fd(this->monitor), QSocketNotifier::Read, this);
@ -95,7 +95,8 @@ QList<USBPortInfo> USBMonitor::availableDevices()
struct udev_device *dev;
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);
devices = udev_enumerate_get_list_entry(enumerate);
// 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
be several levels up the tree, but the function will find
it.*/
/*
dev = udev_device_get_parent_with_subsystem_devtype(
dev,
"usb",
@ -121,24 +123,10 @@ QList<USBPortInfo> USBMonitor::availableDevices()
printf("Unable to find parent usb device.");
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));
udev_device_unref(dev);
udev_device_unref(dev);
}
/* free the enumerator object */
udev_enumerate_unref(enumerate);
@ -171,6 +159,21 @@ USBPortInfo USBMonitor::makePortInfo(struct udev_device *dev)
printf(" Subsystem: %s", udev_device_get_subsystem(dev));
printf(" Devtype: %s", udev_device_get_devtype(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.productID = QString(udev_device_get_sysattr_value(dev, "idProduct")).toInt();