From 01f0f27c84c7a22a2bf0938de7415181d2239816 Mon Sep 17 00:00:00 2001 From: James Turner Date: Mon, 25 Dec 2017 18:13:03 +0000 Subject: [PATCH] =?UTF-8?q?HID-input:=20don=E2=80=99t=20crash=20when=20ope?= =?UTF-8?q?n=20fails?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Important since hidraw devices need special permissions on Linux. --- src/Input/FGEventInput.cxx | 8 ++++++-- src/Input/FGEventInput.hxx | 2 +- src/Input/FGHIDEventInput.cxx | 33 +++++++++++++++++++++++++------- src/Input/FGLinuxEventInput.cxx | 6 ++++-- src/Input/FGLinuxEventInput.hxx | 8 ++++---- src/Input/FGMacOSXEventInput.cxx | 13 +++++++++---- 6 files changed, 50 insertions(+), 20 deletions(-) diff --git a/src/Input/FGEventInput.cxx b/src/Input/FGEventInput.cxx index 722300106..9e46ec2ea 100644 --- a/src/Input/FGEventInput.cxx +++ b/src/Input/FGEventInput.cxx @@ -410,8 +410,12 @@ unsigned FGEventInput::AddDevice( FGInputDevice * inputDevice ) inputDevice->Configure( deviceNode ); try { - inputDevice->Open(); - input_devices[ deviceNode->getIndex() ] = inputDevice; + bool ok = inputDevice->Open(); + if (ok) { + input_devices[ deviceNode->getIndex() ] = inputDevice; + } else { + throw sg_exception("Opening input device failed"); + } } catch( ... ) { delete inputDevice; diff --git a/src/Input/FGEventInput.hxx b/src/Input/FGEventInput.hxx index 9bd62d5da..055611a9d 100644 --- a/src/Input/FGEventInput.hxx +++ b/src/Input/FGEventInput.hxx @@ -223,7 +223,7 @@ public: virtual ~FGInputDevice(); - virtual void Open() = 0; + virtual bool Open() = 0; virtual void Close() = 0; virtual void Send( const char * eventName, double value ) = 0; diff --git a/src/Input/FGHIDEventInput.cxx b/src/Input/FGHIDEventInput.cxx index 6935114a8..0c0592e4b 100644 --- a/src/Input/FGHIDEventInput.cxx +++ b/src/Input/FGHIDEventInput.cxx @@ -219,7 +219,7 @@ public: virtual ~FGHIDDevice(); - void Open() override; + bool Open() override; void Close() override; void update(double dt) override; @@ -322,15 +322,17 @@ FGHIDDevice::FGHIDDevice(hid_device_info *devInfo, FGHIDEventInput *) FGHIDDevice::~FGHIDDevice() { - + if (_device) { + hid_close(_device); + } } -void FGHIDDevice::Open() +bool FGHIDDevice::Open() { _device = hid_open_path(_hidPath.c_str()); - if (_device == 0) { - SG_LOG(SG_INPUT, SG_WARN, "Failed to open:" << _hidPath); - return; + if (_device == nullptr) { + SG_LOG(SG_INPUT, SG_WARN, "HID: Failed to open:" << _hidPath); + return false; } unsigned char reportDescriptor[1024]; @@ -354,6 +356,8 @@ void FGHIDDevice::Open() // SG_LOG(SG_INPUT, SG_INFO, "found item for event:" << v.first); reportItem.second->event = event; } + + return true; } void FGHIDDevice::scanCollection(hid_item* c) @@ -475,11 +479,18 @@ void FGHIDDevice::scanItem(hid_item* item) void FGHIDDevice::Close() { - hid_close(_device); + if (_device) { + hid_close(_device); + _device = nullptr; + } } void FGHIDDevice::update(double dt) { + if (!_device) { + return; + } + uint8_t reportBuf[65]; int readCount = 0; while (true) { @@ -528,6 +539,10 @@ void writeBits(uint8_t* bytes, size_t bitOffset, size_t bitSize, int value) void FGHIDDevice::sendReport(Report* report) const { + if (!_device) { + return; + } + uint8_t reportBytes[65]; size_t reportLength = 0; memset(reportBytes, 0, sizeof(reportBytes)); @@ -632,6 +647,10 @@ void FGHIDDevice::processInputReport(Report* report, unsigned char* data, void FGHIDDevice::SendFeatureReport(unsigned int reportId, const std::string& data) { + if (!_device) { + return; + } + uint8_t buf[65]; size_t len = std::min(data.length() + 1, sizeof(buf)); buf[0] = reportId; diff --git a/src/Input/FGLinuxEventInput.cxx b/src/Input/FGLinuxEventInput.cxx index 64c42c2e1..6dae43660 100644 --- a/src/Input/FGLinuxEventInput.cxx +++ b/src/Input/FGLinuxEventInput.cxx @@ -286,9 +286,9 @@ static inline bool bitSet( unsigned char * buf, unsigned bit ) return (buf[bit/sizeof(unsigned char)/8] >> (bit%(sizeof(unsigned char)*8))) & 1; } -void FGLinuxInputDevice::Open() +bool FGLinuxInputDevice::Open() { - if( fd != -1 ) return; + if( fd != -1 ) return true; if( (fd = ::open( devname.c_str(), O_RDWR )) == -1 ) { throw std::exception(); } @@ -371,6 +371,8 @@ void FGLinuxInputDevice::Open() } } } + + return true; } double FGLinuxInputDevice::Normalize( struct input_event & event ) diff --git a/src/Input/FGLinuxEventInput.hxx b/src/Input/FGLinuxEventInput.hxx index 5ee37b64b..63e7f99ad 100644 --- a/src/Input/FGLinuxEventInput.hxx +++ b/src/Input/FGLinuxEventInput.hxx @@ -45,10 +45,10 @@ public: FGLinuxInputDevice( std::string name, std::string devname, std::string aSerial ); virtual ~FGLinuxInputDevice(); - virtual void Open(); - virtual void Close(); - virtual void Send( const char * eventName, double value ); - virtual const char * TranslateEventName( FGEventData & eventData ); + bool Open() override; + void Close() override; + void Send( const char * eventName, double value ) override; + const char * TranslateEventName( FGEventData & eventData ) override; void SetDevname( const std::string & name ); std::string GetDevname() const { return devname; } diff --git a/src/Input/FGMacOSXEventInput.cxx b/src/Input/FGMacOSXEventInput.cxx index 58bec9d4a..226c2664e 100644 --- a/src/Input/FGMacOSXEventInput.cxx +++ b/src/Input/FGMacOSXEventInput.cxx @@ -153,7 +153,7 @@ public: virtual ~FGMacOSXInputDevice(); - void Open() override; + bool Open() override; void Close() override; virtual void update(double dt); @@ -344,16 +344,21 @@ FGMacOSXInputDevice::~FGMacOSXInputDevice() CFRelease(_hid); } -void FGMacOSXInputDevice::Open() +bool FGMacOSXInputDevice::Open() { - - IOHIDDeviceOpen(_hid, kIOHIDOptionsTypeNone); + IOReturn result = IOHIDDeviceOpen(_hid, kIOHIDOptionsTypeNone); + if (result != kIOReturnSuccess) { + return false; + } + IOHIDDeviceScheduleWithRunLoop(_hid, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); // IOHIDQueueRegisterValueAvailableCallback(_queue, valueAvailableCallback, this); IOHIDQueueScheduleWithRunLoop(_queue, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); IOHIDQueueStart(_queue); + + return true; } void FGMacOSXInputDevice::buildElementNameDictionary()