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;
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( PropertyList::iterator it = eventNodes.begin(); it != eventNodes.end(); ++it )
AddHandledEvent( FGInputEvent::NewObject( this, *it ) );
for (auto ev : deviceNode->getChildren( "event" )) {
AddHandledEvent( FGInputEvent::NewObject( this, ev) );
}
debugEvents = deviceNode->getBoolValue("debug-events", debugEvents );
grab = deviceNode->getBoolValue("grab", grab );
@ -300,7 +301,7 @@ void FGInputDevice::HandleEvent( FGEventData & eventData )
{
string eventName = TranslateEventName( eventData );
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);
}
@ -314,6 +315,11 @@ void FGInputDevice::SetName( string name )
this->name = name;
}
void FGInputDevice::SetUniqueName(const std::string &name)
{
_uniqueName = name;
}
void FGInputDevice::SetSerialNumber( std::string serial )
{
serialNumber = serial;
@ -393,12 +399,13 @@ unsigned FGEventInput::AddDevice( FGInputDevice * inputDevice )
configNode = configMap.configurationForDeviceName(nameWithSerial);
SG_LOG(SG_INPUT, SG_INFO, "using instance-specific configuration for device "
<< nameWithSerial << " : " << configNode->getStringValue("source"));
inputDevice->SetUniqueName(nameWithSerial);
}
}
// try instanced (counted) name
if (configNode == nullptr) {
const auto nameWithIndex = computeDeviceIndexName(inputDevice);
if (configNode == nullptr) {
if (configMap.hasConfiguration(nameWithIndex)) {
configNode = configMap.configurationForDeviceName(nameWithIndex);
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);
}
// 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
unsigned int index;
for ( index = 0; index < MAX_DEVICES; index++ ) {
@ -426,7 +438,7 @@ unsigned FGEventInput::AddDevice( FGInputDevice * inputDevice )
}
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;
return INVALID_DEVICE_INDEX;
}
@ -449,11 +461,11 @@ unsigned FGEventInput::AddDevice( FGInputDevice * inputDevice )
}
catch( ... ) {
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;
}
SG_LOG(SG_INPUT, SG_DEBUG, "using InputDevice " << inputDevice->GetName() );
SG_LOG(SG_INPUT, SG_DEBUG, "using InputDevice " << inputDevice->GetUniqueName() );
return deviceNode->getIndex();
}

View file

@ -240,6 +240,10 @@ public:
void SetName( std::string name );
std::string & GetName() { return name; }
void SetUniqueName(const std::string& name);
const std::string GetUniqueName() const
{ return _uniqueName; }
void SetSerialNumber( std::string serial );
std::string& GetSerialNumber() { return serialNumber; }
@ -280,6 +284,11 @@ protected:
std::string nasalModule;
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;

View file

@ -315,28 +315,20 @@ FGHIDDevice::FGHIDDevice(hid_device_info *devInfo, FGHIDEventInput *)
{
_hidPath = devInfo->path;
std::wstring manufactuerName,
std::wstring manufacturerName,
productName = std::wstring(devInfo->product_string);
if (devInfo->manufacturer_string) {
manufactuerName = std::wstring(devInfo->manufacturer_string);
SetName(simgear::strutils::convertWStringToUtf8(manufactuerName) + " " +
manufacturerName = std::wstring(devInfo->manufacturer_string);
SetName(simgear::strutils::convertWStringToUtf8(manufacturerName) + " " +
simgear::strutils::convertWStringToUtf8(productName));
} else {
SetName(simgear::strutils::convertWStringToUtf8(productName));
}
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);
if ((serial == nullptr) || std::wcslen(serial) == 0) {
// use device path to disambiguate
if (!path.empty()) {
SG_LOG(SG_INPUT, SG_INFO, "Missing serial on device '" <<
simgear::strutils::convertWStringToUtf8(productName) << "', using path: " << path);
SetSerialNumber(path);
}
} else {
// most devices rreturnturn an empty serial number, unfortunately
if ((serial != nullptr) && std::wcslen(serial) > 0) {
SetSerialNumber(simgear::strutils::convertWStringToUtf8(serial));
}
}
@ -488,11 +480,11 @@ void FGHIDDevice::scanItem(hid_item* item)
auto report = getReport(ty, item->report_id, true /* create */);
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};
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);
report->items.push_back(itemObject);