Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "digitizerdevice.h"
- #include <functional>
- #include <QThread>
- struct Defer {
- using F = std::function<void(void)>;
- Defer(F func) { m_func = func; }
- ~Defer() { m_func(); }
- F m_func;
- };
- bool DigitizerDevice::init()
- {
- auto err = libusb_init(&context);
- libusb_set_debug(context, LIBUSB_LOG_LEVEL_WARNING);
- if ( err ) {
- qFatal("libusb initialization failed");
- }
- return true;
- }
- bool DigitizerDevice::connectDevice()
- {
- libusb_device** list;
- int err = 0;
- auto numDevices = libusb_get_device_list(context, &list);
- Defer free_device_list([list]() { libusb_free_device_list(list, 0); });
- libusb_device* rdev = nullptr;
- for ( int i = 0; i < numDevices; i++ ) {
- rdev = list[i];
- libusb_device_descriptor descriptor;
- libusb_get_device_descriptor(rdev, &descriptor);
- if ( descriptor.idVendor == 0x1fc9 && descriptor.idProduct == 0x2047 ) {
- err = libusb_open(rdev, &dev);
- if ( err ) {
- qDebug() << "failed to open device";
- return false;
- }
- break;
- }
- }
- if ( !dev ) {
- qDebug() << "device not found";
- return false;
- }
- err = libusb_detach_kernel_driver(dev, 0);
- if ( err && err != LIBUSB_ERROR_NOT_FOUND ) {
- qDebug() << "failed to detach kernel driver from interface";
- return false;
- }
- err = libusb_claim_interface(dev, 0);
- if ( err ) {
- qDebug() << "failed to claim interface";
- return false;
- }
- libusb_config_descriptor* config;
- err = libusb_get_config_descriptor(rdev, 0, &config);
- if ( err ) {
- qDebug() << "failed to retrieve config descriptor: " << err << "\n";
- return false;
- }
- auto rinterface = config->interface[1];
- auto interface = rinterface.altsetting[0];
- qDebug() << "got interface with" << (int) interface.bNumEndpoints << "endpoints";
- for ( int i = 0; i < interface.bNumEndpoints; i++ ) {
- auto endpoint = interface.endpoint[i];
- if ( endpoint.bEndpointAddress & LIBUSB_ENDPOINT_IN ) {
- qDebug() << "OUT endpoint, address" << (int) endpoint.bEndpointAddress;
- inEndpoint = endpoint.bEndpointAddress;
- }
- else {
- outEndpoint = endpoint.bEndpointAddress;
- qDebug() << "IN endpoint, address" << (int) endpoint.bEndpointAddress;
- }
- }
- qDebug() << "opened device:" << dev;
- Q_EMIT deviceConnected();
- return true;
- }
- bool DigitizerDevice::isConnected() const
- {
- return dev != nullptr;
- }
- QByteArray DigitizerDevice::read(int size)
- {
- QByteArray ret;
- ret.resize(size);
- int transferred = 0;
- while ( transferred < size ) {
- int transferred_chunk;
- auto err = libusb_bulk_transfer(dev, inEndpoint,
- (unsigned char*) ret.data() + transferred, size - transferred,
- &transferred_chunk, 300);
- transferred += transferred_chunk;
- if ( err == LIBUSB_ERROR_OVERFLOW ) {
- // no data available, try again
- QThread::currentThread()->usleep(10);
- continue;
- }
- if ( err != 0 || (err == LIBUSB_ERROR_TIMEOUT && transferred_chunk == 0) ) {
- // error or timed out with no data transferred, assume we're disconnected
- resetDevice();
- return {};
- }
- }
- return ret;
- }
- bool DigitizerDevice::transmit(const char* data, int size)
- {
- return transmit({data, size});
- }
- bool DigitizerDevice::transmit(const QByteArray& data)
- {
- int transferred = 0;
- auto buf = (unsigned char*) data.data();
- while ( transferred < data.size() ) {
- int transferred_chunk;
- qDebug() << "initiate OUT bulk transfer:" << data.size() - transferred << "bytes";
- auto err = libusb_bulk_transfer(dev, outEndpoint,
- buf + transferred, qMin(512, data.size() - transferred),
- &transferred_chunk, 300);
- if ( err != 0 || (err == LIBUSB_ERROR_TIMEOUT && transferred_chunk == 0) ) {
- resetDevice();
- return false;
- }
- transferred += transferred_chunk;
- }
- return true;
- }
- void DigitizerDevice::resetDevice()
- {
- qWarning() << "resetting USB device";
- libusb_reset_device(dev);
- dev = nullptr;
- Q_EMIT deviceDisconnected();
- }
- DigitizerDevice::~DigitizerDevice()
- {
- if ( dev ) {
- libusb_close(dev);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement