rework usbwatcher avoiding thread
This commit is contained in:
parent
0d609b3992
commit
99578f28c4
@ -27,13 +27,9 @@
|
||||
//=========================================================================//
|
||||
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
|
||||
#include "ch341a.h"
|
||||
#include "usbwatcher.h"
|
||||
|
||||
class USBWatcher;
|
||||
|
||||
int LIBUSB_CALL hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev,
|
||||
libusb_hotplug_event event, void *user_data)
|
||||
{
|
||||
@ -41,133 +37,112 @@ int LIBUSB_CALL hotplug_callback(struct libusb_context *ctx, struct libusb_devic
|
||||
|
||||
(void)libusb_get_device_descriptor(dev, &desc);
|
||||
|
||||
//unsigned char ser[256] = "";
|
||||
//int n = libusb_get_string_descriptor_ascii(dev, desc.iSerialNumber, ser, sizeof(ser));
|
||||
struct usb_data ud = { .vid = desc.idVendor, .pid = desc.idProduct };
|
||||
//if (n > 0)
|
||||
// ud.serial = QString(ser);
|
||||
|
||||
//QVector <usb_data> *v;
|
||||
//v = (QVector <usb_data> *)user_data;
|
||||
USBWatcher *w = (USBWatcher *)user_data;
|
||||
Q_CHECK_PTR(w);
|
||||
|
||||
if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event)
|
||||
{
|
||||
emit reinterpret_cast<USBWatcher *>(user_data)->USBConnected((const quint16 &)desc.idVendor, (const quint16 &)desc.idProduct);
|
||||
return 0;
|
||||
}
|
||||
w->vUSB.append(ud);
|
||||
emit w->notify(true, (const quint16 &)desc.idVendor, (const quint16 &)desc.idProduct);
|
||||
|
||||
if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event)
|
||||
qDebug() << "Connected VID:PID " << (hex) << desc.idVendor << " - " << desc.idProduct;
|
||||
}
|
||||
else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event)
|
||||
{
|
||||
emit reinterpret_cast<USBWatcher *>(user_data)->USBDisconnected();
|
||||
int idx = w->vUSB.indexOf(ud);
|
||||
if (idx != -1)
|
||||
{
|
||||
w->vUSB.remove(idx);
|
||||
}
|
||||
emit w->notify(false, (const quint16 &)desc.idVendor, (const quint16 &)desc.idProduct);
|
||||
|
||||
qDebug() << "Disconnected VID:PID " << (hex) << desc.idVendor << " - " << desc.idProduct;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief constructor
|
||||
* init vector of supported devices
|
||||
*/
|
||||
USBWatcher::USBWatcher(QObject *p) : QThread(p)
|
||||
void USBWatcher::doPoll()
|
||||
{
|
||||
vUSB << (usb_data)
|
||||
{
|
||||
CH34x_VENDOR_ID2, CH340_UART_PRODUCT
|
||||
};
|
||||
vUSB << (usb_data)
|
||||
{
|
||||
CH34x_VENDOR_ID2, CH341_UART_PRODUCT
|
||||
};
|
||||
struct timeval zero_tv = { .tv_sec = 0, .tv_usec = 0 };
|
||||
//zero_tv.tv_sec = 1; // timeout 1 sec
|
||||
|
||||
// autostart 1 second later
|
||||
QTimer::singleShot(1000, this, SLOT(autoStart()));
|
||||
int rv = libusb_handle_events_timeout_completed(usb_ctx,
|
||||
const_cast<timeval *>(&zero_tv),
|
||||
NULL);
|
||||
if (rv != LIBUSB_SUCCESS)
|
||||
qWarning() << "libusb_handle_events_timeout_completed() failed: " << rv;
|
||||
}
|
||||
|
||||
USBWatcher::USBWatcher()
|
||||
: cbHandle(0),
|
||||
usb_ctx(0),
|
||||
timer(0)
|
||||
{
|
||||
//vUSB << (usb_data)
|
||||
//{
|
||||
// CH34x_VENDOR_ID2, CH340_UART_PRODUCT
|
||||
//};
|
||||
//vUSB << (usb_data)
|
||||
//{
|
||||
// CH34x_VENDOR_ID2, CH341_UART_PRODUCT
|
||||
//};
|
||||
|
||||
vUSB.clear();
|
||||
|
||||
hotplug_register();
|
||||
}
|
||||
|
||||
USBWatcher::~USBWatcher()
|
||||
{
|
||||
for (int i = 0; i < vHandle.count(); i++)
|
||||
hotplug_deregister();
|
||||
}
|
||||
|
||||
void USBWatcher::hotplug_deregister()
|
||||
{
|
||||
if (timer)
|
||||
{
|
||||
libusb_hotplug_deregister_callback(usb_ctx, vHandle.at(i));
|
||||
timer->stop();
|
||||
delete timer;
|
||||
}
|
||||
|
||||
vHandle.clear();
|
||||
|
||||
libusb_exit(usb_ctx);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void USBWatcher::autoStart()
|
||||
{
|
||||
this->start();
|
||||
}
|
||||
|
||||
void USBWatcher::run()
|
||||
{
|
||||
hotplug_register();
|
||||
|
||||
struct timeval zero_tv;
|
||||
zero_tv.tv_sec = 1; // timeout 1 sec
|
||||
zero_tv.tv_usec = 0;
|
||||
|
||||
while (usb_thread_loop)
|
||||
if (usb_ctx)
|
||||
{
|
||||
libusb_handle_events_timeout_completed(usb_ctx, const_cast<timeval *>(&zero_tv), NULL);
|
||||
libusb_hotplug_deregister_callback(usb_ctx, cbHandle);
|
||||
libusb_exit(usb_ctx);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
void USBWatcher::hotplug_register()
|
||||
bool USBWatcher::hotplug_register(quint16 vid, quint16 pid)
|
||||
{
|
||||
usb_thread_loop = true;
|
||||
|
||||
libusb_init(&usb_ctx);
|
||||
|
||||
foreach (usb_data u, vUSB)
|
||||
{
|
||||
int rc;
|
||||
libusb_hotplug_callback_handle h;
|
||||
libusb_device_handle *devh;
|
||||
devh = libusb_open_device_with_vid_pid(usb_ctx, u.vendor, u.product);
|
||||
if (devh != NULL) // connected
|
||||
{
|
||||
|
||||
#ifndef Q_OS_WIN32
|
||||
if (libusb_kernel_driver_active(devh, 0))
|
||||
{
|
||||
rc = libusb_detach_kernel_driver(devh, 0);
|
||||
|
||||
if (rc)
|
||||
{
|
||||
qCritical("Failed to detach kernel driver: '%s'", strerror(-rc));
|
||||
// CloseHandle();
|
||||
// return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Detach kernel driver";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
quint16 v = u.vendor;
|
||||
quint16 p = u.product;
|
||||
|
||||
// after detach from kernel it will automatically hotplugged from registered function
|
||||
// TODO what is under windows?
|
||||
emit USBConnected(v, p);
|
||||
libusb_close(devh);
|
||||
}
|
||||
|
||||
rc = libusb_hotplug_register_callback(usb_ctx, (libusb_hotplug_event)(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
|
||||
int rc = libusb_hotplug_register_callback(usb_ctx,
|
||||
(libusb_hotplug_event)(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
|
||||
LIBUSB_HOTPLUG_ENUMERATE,
|
||||
u.vendor,
|
||||
u.product,
|
||||
(vid == 0) ? LIBUSB_HOTPLUG_MATCH_ANY : vid,
|
||||
(pid == 0) ? LIBUSB_HOTPLUG_MATCH_ANY : pid,
|
||||
LIBUSB_HOTPLUG_MATCH_ANY,
|
||||
hotplug_callback,
|
||||
this,
|
||||
&h);
|
||||
if (LIBUSB_SUCCESS != rc)
|
||||
{
|
||||
libusb_exit(usb_ctx);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
vHandle << h;
|
||||
this, //&vUSB,
|
||||
&cbHandle);
|
||||
if (LIBUSB_SUCCESS != rc)
|
||||
{
|
||||
libusb_exit(usb_ctx);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
QTimer *timer = new QTimer(this);
|
||||
connect(timer, SIGNAL(timeout()), this, SLOT(doPoll()));
|
||||
timer->start(100);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,52 +26,54 @@
|
||||
// //
|
||||
//=========================================================================//
|
||||
|
||||
|
||||
#ifndef USBWATCHER_H
|
||||
#define USBWATCHER_H
|
||||
|
||||
#include <QThread>
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
#include <QTimer>
|
||||
|
||||
#include <libusb-1.0/libusb.h> //Include libsub
|
||||
|
||||
|
||||
|
||||
class USBWatcher: public QThread
|
||||
class usb_data
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
USBWatcher(QObject *p);
|
||||
~USBWatcher();
|
||||
|
||||
struct usb_data
|
||||
bool operator==(const usb_data &a)
|
||||
{
|
||||
quint16 vendor;
|
||||
quint16 product;
|
||||
};
|
||||
|
||||
void hotplug_register();
|
||||
|
||||
public:
|
||||
QVector <libusb_hotplug_callback_handle> vHandle;
|
||||
libusb_context *usb_ctx;
|
||||
|
||||
signals:
|
||||
void USBConnected(const quint16 &vid, const quint16 &pid);
|
||||
void USBDisconnected();
|
||||
|
||||
private slots:
|
||||
void autoStart();
|
||||
|
||||
private:
|
||||
void run();
|
||||
|
||||
private:
|
||||
QVector <usb_data> vUSB;
|
||||
bool usb_thread_loop;
|
||||
return (a.pid == pid && a.vid == vid);
|
||||
}
|
||||
quint16 vid;
|
||||
quint16 pid;
|
||||
//QString serial;
|
||||
};
|
||||
|
||||
class USBWatcher : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
//QThread workerThread;
|
||||
|
||||
public:
|
||||
USBWatcher();
|
||||
~USBWatcher();
|
||||
|
||||
QVector <usb_data> vUSB;
|
||||
|
||||
signals:
|
||||
void notify(bool connected, const quint16 &vid, const quint16 &pid);
|
||||
|
||||
public slots:
|
||||
void doPoll();
|
||||
|
||||
private:
|
||||
bool hotplug_register(quint16 vid = 0, quint16 pid = 0);
|
||||
void hotplug_deregister();
|
||||
|
||||
libusb_hotplug_callback_handle cbHandle;
|
||||
libusb_context *usb_ctx;
|
||||
QTimer *timer;
|
||||
};
|
||||
|
||||
#endif // USBWATCHER_H
|
||||
|
||||
|
@ -178,6 +178,7 @@ SOURCES += SrcPony/aboutmdlg.cpp \
|
||||
SrcPony/x2444bus.cpp \
|
||||
SrcPony/sdebus.cpp \
|
||||
SrcPony/Translator.cpp \
|
||||
SrcPony/usbwatcher.cpp \
|
||||
qhexedit2/src/chunks.cpp \
|
||||
qhexedit2/src/commands.cpp \
|
||||
qhexedit2/src/qhexedit.cpp \
|
||||
@ -260,6 +261,7 @@ HEADERS += SrcPony/e2app.h \
|
||||
SrcPony/x2444.h \
|
||||
SrcPony/Translator.h \
|
||||
SrcPony/interfconv.h \
|
||||
SrcPony/usbwatcher.h \
|
||||
qhexedit2/src/chunks.h \
|
||||
qhexedit2/src/commands.h \
|
||||
qhexedit2/src/qhexedit.h
|
||||
|
Loading…
x
Reference in New Issue
Block a user