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:
parent
1d20913b1f
commit
96cce67040
3 changed files with 39 additions and 26 deletions
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue