HID-input: don’t crash when open fails
Important since hidraw devices need special permissions on Linux.
This commit is contained in:
parent
2538ab717a
commit
01f0f27c84
6 changed files with 50 additions and 20 deletions
|
@ -410,8 +410,12 @@ unsigned FGEventInput::AddDevice( FGInputDevice * inputDevice )
|
||||||
inputDevice->Configure( deviceNode );
|
inputDevice->Configure( deviceNode );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
inputDevice->Open();
|
bool ok = inputDevice->Open();
|
||||||
|
if (ok) {
|
||||||
input_devices[ deviceNode->getIndex() ] = inputDevice;
|
input_devices[ deviceNode->getIndex() ] = inputDevice;
|
||||||
|
} else {
|
||||||
|
throw sg_exception("Opening input device failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch( ... ) {
|
catch( ... ) {
|
||||||
delete inputDevice;
|
delete inputDevice;
|
||||||
|
|
|
@ -223,7 +223,7 @@ public:
|
||||||
|
|
||||||
virtual ~FGInputDevice();
|
virtual ~FGInputDevice();
|
||||||
|
|
||||||
virtual void Open() = 0;
|
virtual bool Open() = 0;
|
||||||
virtual void Close() = 0;
|
virtual void Close() = 0;
|
||||||
|
|
||||||
virtual void Send( const char * eventName, double value ) = 0;
|
virtual void Send( const char * eventName, double value ) = 0;
|
||||||
|
|
|
@ -219,7 +219,7 @@ public:
|
||||||
|
|
||||||
virtual ~FGHIDDevice();
|
virtual ~FGHIDDevice();
|
||||||
|
|
||||||
void Open() override;
|
bool Open() override;
|
||||||
void Close() override;
|
void Close() override;
|
||||||
|
|
||||||
void update(double dt) override;
|
void update(double dt) override;
|
||||||
|
@ -322,15 +322,17 @@ FGHIDDevice::FGHIDDevice(hid_device_info *devInfo, FGHIDEventInput *)
|
||||||
|
|
||||||
FGHIDDevice::~FGHIDDevice()
|
FGHIDDevice::~FGHIDDevice()
|
||||||
{
|
{
|
||||||
|
if (_device) {
|
||||||
|
hid_close(_device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGHIDDevice::Open()
|
bool FGHIDDevice::Open()
|
||||||
{
|
{
|
||||||
_device = hid_open_path(_hidPath.c_str());
|
_device = hid_open_path(_hidPath.c_str());
|
||||||
if (_device == 0) {
|
if (_device == nullptr) {
|
||||||
SG_LOG(SG_INPUT, SG_WARN, "Failed to open:" << _hidPath);
|
SG_LOG(SG_INPUT, SG_WARN, "HID: Failed to open:" << _hidPath);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char reportDescriptor[1024];
|
unsigned char reportDescriptor[1024];
|
||||||
|
@ -354,6 +356,8 @@ void FGHIDDevice::Open()
|
||||||
// SG_LOG(SG_INPUT, SG_INFO, "found item for event:" << v.first);
|
// SG_LOG(SG_INPUT, SG_INFO, "found item for event:" << v.first);
|
||||||
reportItem.second->event = event;
|
reportItem.second->event = event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGHIDDevice::scanCollection(hid_item* c)
|
void FGHIDDevice::scanCollection(hid_item* c)
|
||||||
|
@ -475,11 +479,18 @@ void FGHIDDevice::scanItem(hid_item* item)
|
||||||
|
|
||||||
void FGHIDDevice::Close()
|
void FGHIDDevice::Close()
|
||||||
{
|
{
|
||||||
|
if (_device) {
|
||||||
hid_close(_device);
|
hid_close(_device);
|
||||||
|
_device = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGHIDDevice::update(double dt)
|
void FGHIDDevice::update(double dt)
|
||||||
{
|
{
|
||||||
|
if (!_device) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t reportBuf[65];
|
uint8_t reportBuf[65];
|
||||||
int readCount = 0;
|
int readCount = 0;
|
||||||
while (true) {
|
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
|
void FGHIDDevice::sendReport(Report* report) const
|
||||||
{
|
{
|
||||||
|
if (!_device) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t reportBytes[65];
|
uint8_t reportBytes[65];
|
||||||
size_t reportLength = 0;
|
size_t reportLength = 0;
|
||||||
memset(reportBytes, 0, sizeof(reportBytes));
|
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)
|
void FGHIDDevice::SendFeatureReport(unsigned int reportId, const std::string& data)
|
||||||
{
|
{
|
||||||
|
if (!_device) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t buf[65];
|
uint8_t buf[65];
|
||||||
size_t len = std::min(data.length() + 1, sizeof(buf));
|
size_t len = std::min(data.length() + 1, sizeof(buf));
|
||||||
buf[0] = reportId;
|
buf[0] = reportId;
|
||||||
|
|
|
@ -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;
|
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 ) {
|
if( (fd = ::open( devname.c_str(), O_RDWR )) == -1 ) {
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
}
|
}
|
||||||
|
@ -371,6 +371,8 @@ void FGLinuxInputDevice::Open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
double FGLinuxInputDevice::Normalize( struct input_event & event )
|
double FGLinuxInputDevice::Normalize( struct input_event & event )
|
||||||
|
|
|
@ -45,10 +45,10 @@ public:
|
||||||
FGLinuxInputDevice( std::string name, std::string devname, std::string aSerial );
|
FGLinuxInputDevice( std::string name, std::string devname, std::string aSerial );
|
||||||
virtual ~FGLinuxInputDevice();
|
virtual ~FGLinuxInputDevice();
|
||||||
|
|
||||||
virtual void Open();
|
bool Open() override;
|
||||||
virtual void Close();
|
void Close() override;
|
||||||
virtual void Send( const char * eventName, double value );
|
void Send( const char * eventName, double value ) override;
|
||||||
virtual const char * TranslateEventName( FGEventData & eventData );
|
const char * TranslateEventName( FGEventData & eventData ) override;
|
||||||
|
|
||||||
void SetDevname( const std::string & name );
|
void SetDevname( const std::string & name );
|
||||||
std::string GetDevname() const { return devname; }
|
std::string GetDevname() const { return devname; }
|
||||||
|
|
|
@ -153,7 +153,7 @@ public:
|
||||||
|
|
||||||
virtual ~FGMacOSXInputDevice();
|
virtual ~FGMacOSXInputDevice();
|
||||||
|
|
||||||
void Open() override;
|
bool Open() override;
|
||||||
void Close() override;
|
void Close() override;
|
||||||
|
|
||||||
virtual void update(double dt);
|
virtual void update(double dt);
|
||||||
|
@ -344,16 +344,21 @@ FGMacOSXInputDevice::~FGMacOSXInputDevice()
|
||||||
CFRelease(_hid);
|
CFRelease(_hid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGMacOSXInputDevice::Open()
|
bool FGMacOSXInputDevice::Open()
|
||||||
{
|
{
|
||||||
|
IOReturn result = IOHIDDeviceOpen(_hid, kIOHIDOptionsTypeNone);
|
||||||
|
if (result != kIOReturnSuccess) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
IOHIDDeviceOpen(_hid, kIOHIDOptionsTypeNone);
|
|
||||||
IOHIDDeviceScheduleWithRunLoop(_hid, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
IOHIDDeviceScheduleWithRunLoop(_hid, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
||||||
|
|
||||||
// IOHIDQueueRegisterValueAvailableCallback(_queue, valueAvailableCallback, this);
|
// IOHIDQueueRegisterValueAvailableCallback(_queue, valueAvailableCallback, this);
|
||||||
|
|
||||||
IOHIDQueueScheduleWithRunLoop(_queue, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
IOHIDQueueScheduleWithRunLoop(_queue, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
||||||
IOHIDQueueStart(_queue);
|
IOHIDQueueStart(_queue);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGMacOSXInputDevice::buildElementNameDictionary()
|
void FGMacOSXInputDevice::buildElementNameDictionary()
|
||||||
|
|
Loading…
Reference in a new issue