Advertisement
Guest User

Untitled

a guest
Feb 24th, 2018
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.61 KB | None | 0 0
  1. #include "digitizerdevice.h"
  2.  
  3. #include <functional>
  4. #include <QThread>
  5.  
  6. struct Defer {
  7.     using F = std::function<void(void)>;
  8.     Defer(F func) { m_func = func; }
  9.     ~Defer() { m_func(); }
  10.     F m_func;
  11. };
  12.  
  13. bool DigitizerDevice::init()
  14. {
  15.     auto err = libusb_init(&context);
  16.     libusb_set_debug(context, LIBUSB_LOG_LEVEL_WARNING);
  17.     if ( err ) {
  18.         qFatal("libusb initialization failed");
  19.     }
  20.     return true;
  21. }
  22.  
  23. bool DigitizerDevice::connectDevice()
  24. {
  25.     libusb_device** list;
  26.     int err = 0;
  27.  
  28.     auto numDevices = libusb_get_device_list(context, &list);
  29.     Defer free_device_list([list]() { libusb_free_device_list(list, 0); });
  30.  
  31.     libusb_device* rdev = nullptr;
  32.     for ( int i = 0; i < numDevices; i++ ) {
  33.         rdev = list[i];
  34.         libusb_device_descriptor descriptor;
  35.         libusb_get_device_descriptor(rdev, &descriptor);
  36.         if ( descriptor.idVendor == 0x1fc9 && descriptor.idProduct == 0x2047 ) {
  37.             err = libusb_open(rdev, &dev);
  38.             if ( err ) {
  39.                 qDebug() << "failed to open device";
  40.                 return false;
  41.             }
  42.             break;
  43.         }
  44.     }
  45.     if ( !dev ) {
  46.         qDebug() << "device not found";
  47.         return false;
  48.     }
  49.  
  50.     err = libusb_detach_kernel_driver(dev, 0);
  51.     if ( err && err != LIBUSB_ERROR_NOT_FOUND ) {
  52.         qDebug() << "failed to detach kernel driver from interface";
  53.         return false;
  54.     }
  55.  
  56.     err = libusb_claim_interface(dev, 0);
  57.     if ( err ) {
  58.         qDebug() << "failed to claim interface";
  59.         return false;
  60.     }
  61.  
  62.     libusb_config_descriptor* config;
  63.     err = libusb_get_config_descriptor(rdev, 0, &config);
  64.     if ( err ) {
  65.         qDebug() << "failed to retrieve config descriptor: " << err << "\n";
  66.         return false;
  67.     }
  68.     auto rinterface = config->interface[1];
  69.     auto interface = rinterface.altsetting[0];
  70.     qDebug() << "got interface with" << (int) interface.bNumEndpoints << "endpoints";
  71.  
  72.     for ( int i = 0; i < interface.bNumEndpoints; i++ ) {
  73.         auto endpoint = interface.endpoint[i];
  74.         if ( endpoint.bEndpointAddress & LIBUSB_ENDPOINT_IN ) {
  75.             qDebug() << "OUT endpoint, address" << (int) endpoint.bEndpointAddress;
  76.             inEndpoint = endpoint.bEndpointAddress;
  77.         }
  78.         else {
  79.             outEndpoint = endpoint.bEndpointAddress;
  80.             qDebug() << "IN endpoint, address" << (int) endpoint.bEndpointAddress;
  81.         }
  82.     }
  83.  
  84.     qDebug() << "opened device:" << dev;
  85.  
  86.     Q_EMIT deviceConnected();
  87.     return true;
  88. }
  89.  
  90. bool DigitizerDevice::isConnected() const
  91. {
  92.     return dev != nullptr;
  93. }
  94.  
  95. QByteArray DigitizerDevice::read(int size)
  96. {
  97.     QByteArray ret;
  98.     ret.resize(size);
  99.  
  100.     int transferred = 0;
  101.     while ( transferred < size ) {
  102.         int transferred_chunk;
  103.         auto err = libusb_bulk_transfer(dev, inEndpoint,
  104.                                         (unsigned char*) ret.data() + transferred, size - transferred,
  105.                                         &transferred_chunk, 300);
  106.         transferred += transferred_chunk;
  107.         if ( err == LIBUSB_ERROR_OVERFLOW ) {
  108.             // no data available, try again
  109.             QThread::currentThread()->usleep(10);
  110.             continue;
  111.         }
  112.         if ( err != 0 || (err == LIBUSB_ERROR_TIMEOUT && transferred_chunk == 0) ) {
  113.             // error or timed out with no data transferred, assume we're disconnected
  114.             resetDevice();
  115.             return {};
  116.         }
  117.     }
  118.  
  119.     return ret;
  120. }
  121.  
  122. bool DigitizerDevice::transmit(const char* data, int size)
  123. {
  124.     return transmit({data, size});
  125. }
  126.  
  127. bool DigitizerDevice::transmit(const QByteArray& data)
  128. {
  129.     int transferred = 0;
  130.     auto buf = (unsigned char*) data.data();
  131.     while ( transferred < data.size() ) {
  132.         int transferred_chunk;
  133.         qDebug() << "initiate OUT bulk transfer:" << data.size() - transferred << "bytes";
  134.         auto err = libusb_bulk_transfer(dev, outEndpoint,
  135.                                         buf + transferred, qMin(512, data.size() - transferred),
  136.                                         &transferred_chunk, 300);
  137.         if ( err != 0 || (err == LIBUSB_ERROR_TIMEOUT && transferred_chunk == 0) ) {
  138.             resetDevice();
  139.             return false;
  140.         }
  141.         transferred += transferred_chunk;
  142.     }
  143.     return true;
  144. }
  145.  
  146. void DigitizerDevice::resetDevice()
  147. {
  148.     qWarning() << "resetting USB device";
  149.     libusb_reset_device(dev);
  150.     dev = nullptr;
  151.     Q_EMIT deviceDisconnected();
  152. }
  153.  
  154. DigitizerDevice::~DigitizerDevice()
  155. {
  156.     if ( dev ) {
  157.         libusb_close(dev);
  158.     }
  159. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement