#include #include #include #include #include #include #include #include "hidapi.h" #include "SpaceNav.h" #include "printutils.h" #define WSTRLEN 256 #define BUFLEN 16 #define VENDOR_ID 0x046d #define PRODUCT_ID 0xc626 using namespace std; const QEvent::Type SpaceNavEvent::my_type = static_cast< QEvent::Type>( QEvent::registerEventType()); static void sleep_iter( void) { struct timespec schnarch = { 1, 0}; while (nanosleep( &schnarch, &schnarch) < 0) {}; } class SpaceNav::Impl { private: hid_device* dev; public: Impl( SpaceNav& parent); void operator()( void); private: SpaceNav& parent; }; SpaceNav::Impl::Impl( SpaceNav& p) : parent( p) { } void SpaceNav::Impl::operator()( void) { if (hid_init() < 0) { PRINTD( "Can't hid_init().\n"); return; } uint16_t buttons = 0; for (;; sleep_iter()) { // Try a list of product IDs. But up to now I know of only one. dev = hid_open( VENDOR_ID, PRODUCT_ID, NULL); if (dev == NULL) { PRINTD( "Can't open 3D device.\n"); continue; } unsigned char buf[ BUFLEN]; int len; while ((len = hid_read( dev, buf, BUFLEN)) > 0) { // QWidget* widget = QApplication::focusWidget(); doesn't do the tric. QWidget* widget = QApplication::activeWindow(); if (widget == 0) { continue; } QEvent* event = 0; if ((buf[ 0] == 1 || buf[ 0] == 2) && len == 7) { // Values are in the range -10..10 at min. speed and -2595..2595 at max. speed. int16_t x_value = buf[ 1] | buf[ 2] << 8; int16_t y_value = buf[ 3] | buf[ 4] << 8; int16_t z_value = buf[ 5] | buf[ 6] << 8; if (buf[ 0] == 1) { event = new SpaceNavEventTranslate( x_value, y_value, z_value); } else { event = new SpaceNavEventRotate( x_value, y_value, z_value); } } if (buf[ 0] == 3 && len == 3) { // Is either 0, 1 or 2. uint16_t bitmask = buf[ 1] | buf[ 2] << 8; uint16_t down = ~buttons & bitmask; uint16_t up = buttons & ~bitmask; buttons = bitmask; event = new SpaceNavEventButton( down, up); } if (event != 0) { QCoreApplication::postEvent( widget, event); } } hid_close( dev); } } SpaceNav::SpaceNav( void) : pimpl_thread( NULL) { }; void SpaceNav::operator()( void) { pimpl_thread = new std::thread( Impl( *this)); pimpl_thread->detach(); }; SpaceNav::~SpaceNav( void) { if (pimpl_thread != NULL) { delete pimpl_thread; } }; SpaceNav spacenav;