1
0
Fork 0

HID input: fix multi-device Nasal support

Ensure each laoded device gets a unique Nasal module name,
otherwise they combine with each other and Stuff Breaks(TM)
This commit is contained in:
James Turner 2018-09-30 11:25:51 +01:00
parent 1d20913b1f
commit 96cce67040
3 changed files with 39 additions and 26 deletions

View file

@ -241,11 +241,12 @@ void FGInputDevice::Configure( SGPropertyNode_ptr aDeviceNode )
{ {
deviceNode = aDeviceNode; deviceNode = aDeviceNode;
nasalModule = string("__event:") + GetName(); // use _uniqueName here so each loaded device gets its own Nasal module
nasalModule = string("__event:") + _uniqueName;
PropertyList eventNodes = deviceNode->getChildren( "event" ); for (auto ev : deviceNode->getChildren( "event" )) {
for( PropertyList::iterator it = eventNodes.begin(); it != eventNodes.end(); ++it ) AddHandledEvent( FGInputEvent::NewObject( this, ev) );
AddHandledEvent( FGInputEvent::NewObject( this, *it ) ); }
debugEvents = deviceNode->getBoolValue("debug-events", debugEvents ); debugEvents = deviceNode->getBoolValue("debug-events", debugEvents );
grab = deviceNode->getBoolValue("grab", grab ); grab = deviceNode->getBoolValue("grab", grab );
@ -300,7 +301,7 @@ void FGInputDevice::HandleEvent( FGEventData & eventData )
{ {
string eventName = TranslateEventName( eventData ); string eventName = TranslateEventName( eventData );
if( debugEvents ) { if( debugEvents ) {
SG_LOG(SG_INPUT, SG_INFO, GetName() << " has event " << SG_LOG(SG_INPUT, SG_INFO, GetUniqueName() << " has event " <<
eventName << " modifiers=" << eventData.modifiers << " value=" << eventData.value); eventName << " modifiers=" << eventData.modifiers << " value=" << eventData.value);
} }
@ -314,6 +315,11 @@ void FGInputDevice::SetName( string name )
this->name = name; this->name = name;
} }
void FGInputDevice::SetUniqueName(const std::string &name)
{
_uniqueName = name;
}
void FGInputDevice::SetSerialNumber( std::string serial ) void FGInputDevice::SetSerialNumber( std::string serial )
{ {
serialNumber = serial; serialNumber = serial;
@ -393,12 +399,13 @@ unsigned FGEventInput::AddDevice( FGInputDevice * inputDevice )
configNode = configMap.configurationForDeviceName(nameWithSerial); configNode = configMap.configurationForDeviceName(nameWithSerial);
SG_LOG(SG_INPUT, SG_INFO, "using instance-specific configuration for device " SG_LOG(SG_INPUT, SG_INFO, "using instance-specific configuration for device "
<< nameWithSerial << " : " << configNode->getStringValue("source")); << nameWithSerial << " : " << configNode->getStringValue("source"));
inputDevice->SetUniqueName(nameWithSerial);
} }
} }
// try instanced (counted) name // try instanced (counted) name
if (configNode == nullptr) {
const auto nameWithIndex = computeDeviceIndexName(inputDevice); const auto nameWithIndex = computeDeviceIndexName(inputDevice);
if (configNode == nullptr) {
if (configMap.hasConfiguration(nameWithIndex)) { if (configMap.hasConfiguration(nameWithIndex)) {
configNode = configMap.configurationForDeviceName(nameWithIndex); configNode = configMap.configurationForDeviceName(nameWithIndex);
SG_LOG(SG_INPUT, SG_INFO, "using instance-specific configuration for device " SG_LOG(SG_INPUT, SG_INFO, "using instance-specific configuration for device "
@ -416,8 +423,13 @@ unsigned FGEventInput::AddDevice( FGInputDevice * inputDevice )
configNode = configMap.configurationForDeviceName(deviceName); configNode = configMap.configurationForDeviceName(deviceName);
} }
// found - copy to /input/event/device[n] // if we didn't generate a name based on the serial number,
// use the name with the index suffix _0, _1, etc
if (inputDevice->GetUniqueName().empty()) {
inputDevice->SetUniqueName(nameWithIndex);
}
// found - copy to /input/event/device[n]
// find a free index // find a free index
unsigned int index; unsigned int index;
for ( index = 0; index < MAX_DEVICES; index++ ) { for ( index = 0; index < MAX_DEVICES; index++ ) {
@ -426,7 +438,7 @@ unsigned FGEventInput::AddDevice( FGInputDevice * inputDevice )
} }
if (index == MAX_DEVICES) { if (index == MAX_DEVICES) {
SG_LOG(SG_INPUT, SG_WARN, "To many event devices - ignoring " << inputDevice->GetName() ); SG_LOG(SG_INPUT, SG_WARN, "To many event devices - ignoring " << inputDevice->GetUniqueName() );
delete inputDevice; delete inputDevice;
return INVALID_DEVICE_INDEX; return INVALID_DEVICE_INDEX;
} }
@ -449,11 +461,11 @@ unsigned FGEventInput::AddDevice( FGInputDevice * inputDevice )
} }
catch( ... ) { catch( ... ) {
delete inputDevice; delete inputDevice;
SG_LOG(SG_INPUT, SG_ALERT, "can't open InputDevice " << inputDevice->GetName() ); SG_LOG(SG_INPUT, SG_ALERT, "can't open InputDevice " << inputDevice->GetUniqueName() );
return INVALID_DEVICE_INDEX; return INVALID_DEVICE_INDEX;
} }
SG_LOG(SG_INPUT, SG_DEBUG, "using InputDevice " << inputDevice->GetName() ); SG_LOG(SG_INPUT, SG_DEBUG, "using InputDevice " << inputDevice->GetUniqueName() );
return deviceNode->getIndex(); return deviceNode->getIndex();
} }

View file

@ -240,6 +240,10 @@ public:
void SetName( std::string name ); void SetName( std::string name );
std::string & GetName() { return name; } std::string & GetName() { return name; }
void SetUniqueName(const std::string& name);
const std::string GetUniqueName() const
{ return _uniqueName; }
void SetSerialNumber( std::string serial ); void SetSerialNumber( std::string serial );
std::string& GetSerialNumber() { return serialNumber; } std::string& GetSerialNumber() { return serialNumber; }
@ -280,6 +284,11 @@ protected:
std::string nasalModule; std::string nasalModule;
report_setting_list_t reportSettings; report_setting_list_t reportSettings;
/// name, but with suffix / serial appended. This is important
/// when loading the device multiple times, to ensure the Nasal
/// module is unique
std::string _uniqueName;
}; };
typedef SGSharedPtr<FGInputDevice> FGInputDevice_ptr; typedef SGSharedPtr<FGInputDevice> FGInputDevice_ptr;

View file

@ -315,28 +315,20 @@ FGHIDDevice::FGHIDDevice(hid_device_info *devInfo, FGHIDEventInput *)
{ {
_hidPath = devInfo->path; _hidPath = devInfo->path;
std::wstring manufactuerName, std::wstring manufacturerName,
productName = std::wstring(devInfo->product_string); productName = std::wstring(devInfo->product_string);
if (devInfo->manufacturer_string) { if (devInfo->manufacturer_string) {
manufactuerName = std::wstring(devInfo->manufacturer_string); manufacturerName = std::wstring(devInfo->manufacturer_string);
SetName(simgear::strutils::convertWStringToUtf8(manufactuerName) + " " + SetName(simgear::strutils::convertWStringToUtf8(manufacturerName) + " " +
simgear::strutils::convertWStringToUtf8(productName)); simgear::strutils::convertWStringToUtf8(productName));
} else { } else {
SetName(simgear::strutils::convertWStringToUtf8(productName)); SetName(simgear::strutils::convertWStringToUtf8(productName));
} }
const auto serial = devInfo->serial_number; const auto serial = devInfo->serial_number;
// every device so far encountered returns a blank serial number, so we
// fall back to the device path to disambiguate.
std::string path(devInfo->path); std::string path(devInfo->path);
if ((serial == nullptr) || std::wcslen(serial) == 0) { // most devices rreturnturn an empty serial number, unfortunately
// use device path to disambiguate if ((serial != nullptr) && std::wcslen(serial) > 0) {
if (!path.empty()) {
SG_LOG(SG_INPUT, SG_INFO, "Missing serial on device '" <<
simgear::strutils::convertWStringToUtf8(productName) << "', using path: " << path);
SetSerialNumber(path);
}
} else {
SetSerialNumber(simgear::strutils::convertWStringToUtf8(serial)); SetSerialNumber(simgear::strutils::convertWStringToUtf8(serial));
} }
} }
@ -488,11 +480,11 @@ void FGHIDDevice::scanItem(hid_item* item)
auto report = getReport(ty, item->report_id, true /* create */); auto report = getReport(ty, item->report_id, true /* create */);
uint32_t bitOffset = report->currentBitSize(); uint32_t bitOffset = report->currentBitSize();
SG_LOG(SG_INPUT, SG_INFO, "adding item:" << name); // SG_LOG(SG_INPUT, SG_INFO, "adding item:" << name);
Item* itemObject = new Item{name, bitOffset, item->report_size}; Item* itemObject = new Item{name, bitOffset, item->report_size};
itemObject->isRelative = hid_parse_is_relative(item); itemObject->isRelative = hid_parse_is_relative(item);
SG_LOG(SG_INPUT, SG_INFO, "\t logical min-max:" << item->logical_min << " / " << item->logical_max); // SG_LOG(SG_INPUT, SG_INFO, "\t logical min-max:" << item->logical_min << " / " << item->logical_max);
itemObject->doSignExtend = (item->logical_min < 0) || (item->logical_max < 0); itemObject->doSignExtend = (item->logical_min < 0) || (item->logical_max < 0);
report->items.push_back(itemObject); report->items.push_back(itemObject);