<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.flightgear.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Zayamatias</id>
	<title>FlightGear wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.flightgear.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Zayamatias"/>
	<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/Special:Contributions/Zayamatias"/>
	<updated>2026-04-10T16:37:43Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.6</generator>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Building_using_CMake_-_Windows&amp;diff=140780</id>
		<title>Building using CMake - Windows</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Building_using_CMake_-_Windows&amp;diff=140780"/>
		<updated>2024-10-17T18:20:33Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: Added FG_ROOT to launch script&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Main article|Building FlightGear}}&lt;br /&gt;
This article is intended to give an overview of '''building FlightGear on modern Windows systems'''. It was created using Windows 11 and VS 2022. It ought to be transferable to earlier versions of the Windows OS and software.&lt;br /&gt;
&lt;br /&gt;
As FlightGear is now 64-bit only, the guide only describes building on a 64-bit system.&lt;br /&gt;
&lt;br /&gt;
== Required software ==&lt;br /&gt;
* [https://cmake.org/download/ CMake for Windows]. Download and install the Windows Win64-x64 Installer.&lt;br /&gt;
* [https://visualstudio.microsoft.com/downloads/ Microsoft Visual Studio 2022] (MSVC). The Community version is free. There is no need for the premium versions; none of their features are required to build FlightGear. The C++ compiler will not be installed by default. You either choose this component during installation or after installation by starting MSVC and trying to create a new C++ project. The one to download is &amp;quot;Desktop Development with C++&amp;quot;. Make sure to have the latest version of the Windows SDK for your Windows version and the C++ Compiler checked. As of 12/19/2023, the latest version of the compiler is &amp;quot;MSVC v143 - VS 2022 C++ x64/86 build tools&amp;quot;.&lt;br /&gt;
* [https://www.qt.io/download-open-source/ Qt5] for the [[Integrated Qt5 Launcher]]. Download the online installer, and choose the version matching your toolchain of Visual Studio e.g. &amp;quot;Qt 5.15.2 --&amp;gt; MSVC 2019 64-bit&amp;quot;. Any version past 5.9 will be fine; latest 5.x recommended. '''Do NOT use Qt6'''. Enable the &amp;quot;Archive&amp;quot; filter to show 5.x options. Leave the default Developer and Designer Tools selection - these are needed for coding and compiling. Otherwise, here is [https://www.qt.io/offline-installers Offline Qt Downloads] for the optional offline-installer versions of Qt.&lt;br /&gt;
* [https://git-scm.com/download/win Git] to keep your build up to date. It also simplifies downloads of components. Optional, but can't recommend it enough!&lt;br /&gt;
&lt;br /&gt;
== Obtaining source ==&lt;br /&gt;
{{Main article|FlightGear and Git}}&lt;br /&gt;
Throughout this article it is assumed that you have set up git clones of the various source repositories (FlightGear, SimGear, data...).&lt;br /&gt;
Using an organized directory (see below) will help significantly.&lt;br /&gt;
&lt;br /&gt;
The commands to run are:&lt;br /&gt;
&lt;br /&gt;
{{code|git clone https://git.code.sf.net/p/flightgear/simgear simgear}}&lt;br /&gt;
&lt;br /&gt;
{{code|git clone https://git.code.sf.net/p/flightgear/flightgear flightgear}}&lt;br /&gt;
&lt;br /&gt;
{{code|git clone https://git.code.sf.net/p/flightgear/fgdata fgdata}}&lt;br /&gt;
&lt;br /&gt;
{{code|git clone https://git.code.sf.net/p/flightgear/windows-3rd-party windows-3rd-party}}&lt;br /&gt;
&lt;br /&gt;
{{code|git clone https://gitlab.com/flightgear/openscenegraph.git osg}}&lt;br /&gt;
&lt;br /&gt;
{{caution| Cloning fgdata from SourceForge often fails. Therefore, we suggest you use a GitLab mirror repository. Instead of&lt;br /&gt;
&lt;br /&gt;
{{code|git clone https://git.code.sf.net/p/flightgear/fgdata fgdata}} &lt;br /&gt;
&lt;br /&gt;
call:&lt;br /&gt;
&lt;br /&gt;
{{code|git clone https://gitlab.com/flightgear/fgdata.git fgdata}}&lt;br /&gt;
&lt;br /&gt;
and after downloaded all data:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cd fgdata&lt;br /&gt;
git checkout next&lt;br /&gt;
git remote set-url origin https://git.code.sf.net/p/flightgear/fgdata&lt;br /&gt;
git pull&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
After downloading these, I would suggest assembling a folder structure as below:&lt;br /&gt;
&lt;br /&gt;
== Directory Tree ==&lt;br /&gt;
On Windows, assumptions on the directory structure are made to automate the discovery of dependencies. This recommended directory structure is described below. The components can be downloaded from the links above. If you do not use the recommended structure you will need to enter paths by hand and some parts may not input correctly.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Caveat -- spaces in the directory names will cause errors. It is best to make sure there are no spaces in the path anywhere.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;&lt;br /&gt;
: FlightGearBuild / &amp;lt;/tt&amp;gt; (Main root directory) &amp;lt;tt&amp;gt;&lt;br /&gt;
:: fgdata / &amp;lt;/tt&amp;gt; (FlightGear data files) &amp;lt;tt&amp;gt;&lt;br /&gt;
:: flightgear / &amp;lt;/tt&amp;gt; (FlightGear sources) &amp;lt;tt&amp;gt;&lt;br /&gt;
:: install / &amp;lt;/tt&amp;gt; (Directory where you will install the built binaries to) &amp;lt;tt&amp;gt;&lt;br /&gt;
::: launch.bat / &amp;lt;/tt&amp;gt; (launch script if desired, see below) &amp;lt;tt&amp;gt;&lt;br /&gt;
:: osg / &amp;lt;/tt&amp;gt; (OSG sources) &amp;lt;tt&amp;gt;&lt;br /&gt;
:: simgear / &amp;lt;/tt&amp;gt; (SimGear sources) &amp;lt;tt&amp;gt;&lt;br /&gt;
:: windows-3rd-party /&lt;br /&gt;
:: build.bat / &amp;lt;/tt&amp;gt; (build script, see below) &amp;lt;tt&amp;gt;&lt;br /&gt;
:: update.bat / &amp;lt;/tt&amp;gt; (update script, see below)&lt;br /&gt;
&lt;br /&gt;
== Building ==&lt;br /&gt;
=== Scripted Compilation ===&lt;br /&gt;
This script will allow you to build OpenSceneGraph, SimGear and FlightGear automatically.&lt;br /&gt;
 &lt;br /&gt;
{{collapsible script&lt;br /&gt;
| type   = Windows batch file&lt;br /&gt;
| title  = The &amp;lt;code&amp;gt;build.bat&amp;lt;/code&amp;gt; script for configuring and compiling OSG, SG, and FG&lt;br /&gt;
| lang   = batch&lt;br /&gt;
| script =&lt;br /&gt;
SET PATH=%PATH%;%ProgramFiles%\CMake\bin&lt;br /&gt;
SET QT5SDK64=C:\Qt\5.15.2\msvc2019_64&lt;br /&gt;
SET CMAKE_TOOLCHAIN=&amp;quot;Visual Studio 17 2022&amp;quot;&lt;br /&gt;
SET ROOT_DIR=C:\path\to\FlightGearBuild&lt;br /&gt;
&lt;br /&gt;
md osg-build&lt;br /&gt;
md simgear-build&lt;br /&gt;
md flightgear-build&lt;br /&gt;
&lt;br /&gt;
cd %ROOT_DIR%\osg-build&lt;br /&gt;
&lt;br /&gt;
cmake  %ROOT_DIR%\osg -G  %CMAKE_TOOLCHAIN% -A x64 ^&lt;br /&gt;
                 -DACTUAL_3RDPARTY_DIR=%ROOT_DIR%\windows-3rd-party/msvc140/3rdParty.x64 ^&lt;br /&gt;
                 -DCMAKE_RELWITHDEBINFO_POSTFIX:STRING= ^&lt;br /&gt;
                 -DOSG_USE_UTF8_FILENAME:BOOL=ON ^&lt;br /&gt;
                 -DWIN32_USE_MP:BOOL=ON ^&lt;br /&gt;
                 -DCMAKE_INSTALL_PREFIX:PATH=%ROOT_DIR%\install&lt;br /&gt;
cmake --build . --config RelWithDebInfo --target INSTALL&lt;br /&gt;
&lt;br /&gt;
cd %ROOT_DIR%\simgear-build&lt;br /&gt;
cmake  %ROOT_DIR%\simgear -G  %CMAKE_TOOLCHAIN% -A x64 ^&lt;br /&gt;
                 -DOSG_FSTREAM_EXPORT_FIXED:BOOL=ON ^&lt;br /&gt;
                 -DCMAKE_INSTALL_PREFIX:PATH=%ROOT_DIR%\install&lt;br /&gt;
cmake --build . --config RelWithDebInfo --target INSTALL&lt;br /&gt;
&lt;br /&gt;
cd %ROOT_DIR%\flightgear-build&lt;br /&gt;
cmake  %ROOT_DIR%\flightgear -G  %CMAKE_TOOLCHAIN% -A x64 ^&lt;br /&gt;
                  -DCMAKE_INSTALL_PREFIX:PATH=%ROOT_DIR%\install ^&lt;br /&gt;
                  -DCMAKE_PREFIX_PATH=%QT5SDK64% ^&lt;br /&gt;
                  -DOSG_FSTREAM_EXPORT_FIXED:BOOL=ON&lt;br /&gt;
                    &lt;br /&gt;
cmake --build . --config RelWithDebInfo --target INSTALL&lt;br /&gt;
&lt;br /&gt;
pause&lt;br /&gt;
| show  = 1&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tip | 10/2024: When using VS2022 make sure your osg has this fix applied: https://gitlab.com/flightgear/openscenegraph/-/commit/31082758036c12738467a7210a17604275a79517&amp;lt;ref&amp;gt;https://sourceforge.net/p/flightgear/mailman/message/58821522/&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Some folks encountered the following problem when building flightgear:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
 CMake Error at CMakeLists.txt:283 (find_package):&lt;br /&gt;
  By not providing &amp;quot;FindBoost.cmake&amp;quot; in CMAKE_MODULE_PATH this project has&lt;br /&gt;
  asked CMake to find a package configuration file provided by &amp;quot;Boost&amp;quot;, but&lt;br /&gt;
  CMake did not find one.&lt;br /&gt;
&lt;br /&gt;
  Could not find a package configuration file provided by &amp;quot;Boost&amp;quot; with any of&lt;br /&gt;
  the following names:&lt;br /&gt;
&lt;br /&gt;
    BoostConfig.cmake&lt;br /&gt;
    boost-config.cmake&lt;br /&gt;
&lt;br /&gt;
  Add the installation prefix of &amp;quot;Boost&amp;quot; to CMAKE_PREFIX_PATH or set&lt;br /&gt;
  &amp;quot;Boost_DIR&amp;quot; to a directory containing one of the above files.  If &amp;quot;Boost&amp;quot;&lt;br /&gt;
  provides a separate development package or SDK, be sure it has been&lt;br /&gt;
  installed.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This could be solved by doing the following in the top-level &amp;lt;code&amp;gt;CMakeLists.txt&amp;lt;/code&amp;gt; of [https://sourceforge.net/p/flightgear/simgear/ci/next/tree/CMakeLists.txt#l16 simgear] and [https://sourceforge.net/p/flightgear/flightgear/ci/next/tree/CMakeLists.txt#l26 flightgear]:&lt;br /&gt;
&lt;br /&gt;
In each file search for the line&lt;br /&gt;
&amp;lt;syntaxhighlight lang='CMake'&amp;gt;&lt;br /&gt;
cmake_policy(SET CMP0167 NEW)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
(it should be near the top of each file) and change from &amp;lt;code&amp;gt;NEW&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;OLD&amp;lt;/code&amp;gt; like this&amp;lt;ref&amp;gt;https://sourceforge.net/p/flightgear/mailman/message/58815368/&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang='CMake'&amp;gt;&lt;br /&gt;
cmake_policy(SET CMP0167 OLD)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In addition there are reports that a linking error occurs when building flightgear:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
pui.lib(puValue.obj) : error LNK2019: unresolved external symbol __imp_strncat referenced in function &amp;quot;protected: void__cdecl puValue::copy_stringval(char const *)&amp;quot; (?copy_stringval@puValue@@IEAAXPEBD@Z) [F:\git\flightgear-build\src\Main\fgfs.vcxproj]&lt;br /&gt;
F:\git\flightgear-build\src\Main\RelWithDebInfo\fgfs.exe : fatal error LNK1120: 1 unresolved externals [F:\git\flightgear-build\src\Main\fgfs.vcxproj]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
A workaround could be by changing the build type from &amp;lt;code&amp;gt;RelWithDebInfo&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;Release&amp;lt;/code&amp;gt; when building osg, simgear and flightgear&amp;lt;ref&amp;gt;https://sourceforge.net/p/flightgear/mailman/message/58824438/&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
In the &amp;lt;code&amp;gt;build.bat&amp;lt;/code&amp;gt; change all three occurrences of&lt;br /&gt;
&amp;lt;syntaxhighlight lang='batch'&amp;gt;&lt;br /&gt;
cmake --build . --config RelWithDebInfo --target INSTALL&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
to&lt;br /&gt;
&amp;lt;syntaxhighlight lang='batch'&amp;gt;&lt;br /&gt;
cmake --build . --config Release --target INSTALL&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Before starting to use the script, you need to edit the top few lines of the script. You will have to:&lt;br /&gt;
&lt;br /&gt;
1. Set the path to your CMake installation.&lt;br /&gt;
&lt;br /&gt;
2. Ensure that the path to your QT SDK is correct for your version of MSVC.&lt;br /&gt;
&lt;br /&gt;
3. Ensure your toolchain version matches, e.g. &amp;quot;Visual Studio 16 2019&amp;quot; for MSVC 2019 or &amp;quot;Visual Studio 15 2017&amp;quot; for MSVC 2017.&lt;br /&gt;
&lt;br /&gt;
4. Set ROOT_DIR to the FlightGearBuild folder you created (the above directory structure)&lt;br /&gt;
&lt;br /&gt;
==== Post-compilation: Launching FlightGear ====&lt;br /&gt;
'''In the debugger:'''&lt;br /&gt;
Open flightgear-build/FlightGear.sln. You can then perform all your development / debugging directly in VS. You normally only need to run build.bat again, if you update SimGear or OSG. &lt;br /&gt;
&lt;br /&gt;
To launch FlightGear from Visual Studio, you can follow the following steps:&lt;br /&gt;
The first time only:&lt;br /&gt;
# Make sure you set your build type to RelWithDebInfo in the top bar.&lt;br /&gt;
# To start with the launcher, click on the small black arrow beside Local Windows Debugger to open 'fgfs debug properties'. Switch to debugging; add {{code|--launcher}} to the 'Command Arguments'. Click Apply and then OK.&lt;br /&gt;
# Press the green arrow (Local Windows Debugger) to start up FlightGear. &lt;br /&gt;
# The first time you'll have to choose where FGDATA is -- to do this, select the 'fgdata' directory you cloned at the start.&lt;br /&gt;
&lt;br /&gt;
Thereafter, simply press the green arrow directly each time you want to start. If there are any local changes, it will recompile; alternatively it will start up directly. It will take a little longer to start as it loads symbols; however you also have the benefit that any segfaults will be caught allowing you to report them!&lt;br /&gt;
&lt;br /&gt;
'''As a standard .exe:'''&lt;br /&gt;
NB these instructions overall are intended for setting up for development; there's a slightly more convoluted process for setting up for just plain flying (e.g. taking advantage of new features for aircraft development).&lt;br /&gt;
&lt;br /&gt;
Essentially, Visual Studio doesn't copy in the DLLs into the /bin/ folder. It's also not ideal to manually copy in the DLLs as it can cause all sorts of issues. However, without the DLLs FlightGear won't work; therefore, you need to set the PATH so it knows where to look for them.&lt;br /&gt;
This launch script should work, put into your /install/bin/ folder:&lt;br /&gt;
{{collapsible script&lt;br /&gt;
| type   = Windows batch file&lt;br /&gt;
| title  = The &amp;lt;code&amp;gt;launch.bat&amp;lt;/code&amp;gt; script for launching flightgear&lt;br /&gt;
| lang   = batch&lt;br /&gt;
| script =&lt;br /&gt;
SET PATH=C:\path\to\FlightGearBuild\install\bin;C:\path\to\FlightGearBuild\windows-3rd-party\msvc140\3rdParty.x64\bin;C:\Qt\5.15.2\msvc2019_64\bin;%PATH%&lt;br /&gt;
SET FG_ROOT=C:\path\to\FlightGearBuild\fgdata&lt;br /&gt;
fgfs.exe --launcher&lt;br /&gt;
| show  = 1&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Adjust the &amp;quot;path\to&amp;quot; references to suit your own personal installation, as well as the QT5 path.&lt;br /&gt;
&lt;br /&gt;
=== Updating ===&lt;br /&gt;
To update FlightGear, in general, just run ''git pull'' on the source directories and then re-run the build.bat script -- it will update what it needs to, relatively quickly.&lt;br /&gt;
&lt;br /&gt;
{{collapsible script&lt;br /&gt;
| type   = Windows batch file&lt;br /&gt;
| title  = The &amp;lt;code&amp;gt;update.bat&amp;lt;/code&amp;gt; script for updating repositories&lt;br /&gt;
| lang   = batch&lt;br /&gt;
| script =&lt;br /&gt;
SET ROOT_DIR=C:\path\to\FlightGearBuild&lt;br /&gt;
&lt;br /&gt;
cd %ROOT_DIR%\osg&lt;br /&gt;
git pull&lt;br /&gt;
&lt;br /&gt;
cd %ROOT_DIR%\fgdata&lt;br /&gt;
git pull&lt;br /&gt;
&lt;br /&gt;
cd %ROOT_DIR%\flightgear&lt;br /&gt;
git pull&lt;br /&gt;
&lt;br /&gt;
cd %ROOT_DIR%\simgear&lt;br /&gt;
git pull&lt;br /&gt;
&lt;br /&gt;
cd %ROOT_DIR%\windows-3rd-party&lt;br /&gt;
git pull&lt;br /&gt;
&lt;br /&gt;
pause&lt;br /&gt;
| show  = 1&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Changing the Configuration ===&lt;br /&gt;
When the SimGear/FlightGear version numbers change, or you change configuration options (e.g. toggling Compositor, changing OSG versions, changing Qt versions) you do have to re-configure in CMake. To do this, it's usually safest to delete the simgear-build and flightgear-build folders and re-run the build.bat script, to ensure the build is clean. There is no need to delete osg-build unless changing OSG version.&lt;br /&gt;
&lt;br /&gt;
In case of problems, most of the time deleting the simgear-build and flightgear-build folders and re-running the build.bat script will be sufficient.&lt;br /&gt;
&lt;br /&gt;
{{building}}&lt;br /&gt;
[[fr:compiler flightear avec CMake - Windows]]&lt;br /&gt;
[[Category:Windows specific]]&lt;br /&gt;
[[Category:Hackathon Materials]]&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User:Zayamatias/Adding_HID_devices_to_FlightGear&amp;diff=139767</id>
		<title>User:Zayamatias/Adding HID devices to FlightGear</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User:Zayamatias/Adding_HID_devices_to_FlightGear&amp;diff=139767"/>
		<updated>2024-04-22T16:07:51Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Adding HID devices to FlightGear''' hopes to explain how to set-up any HID device to work with FlightGear in a step-by-step easy to follow guide, it is my belief that any HID can and will work with FlightGear&lt;br /&gt;
&lt;br /&gt;
First disclaimer: The HID subsystem seems to be working only under Linux and MacOS, I am not sure if one day it will work in Windows. &lt;br /&gt;
Second Disclaimer: This guide was done under an Ubuntu distribution, this means that other distros may vary slightly. &lt;br /&gt;
Last but not least: I take no responsibility in the unlikely event of you breaking your HID device by using this guide&lt;br /&gt;
&lt;br /&gt;
=== Getting started ===&lt;br /&gt;
&lt;br /&gt;
Before starting, there are a couple of tools you need to install:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/hidviz/hidviz] HIDVIZ&lt;br /&gt;
&lt;br /&gt;
This tool will allow you to have a look at the inner workings of your HID device, I'll talk about it later.&lt;br /&gt;
&lt;br /&gt;
[https://code.visualstudio.com/]VS Code&lt;br /&gt;
&lt;br /&gt;
I use this for creating the XMLfiles and the Nasal code, as it has very nice extensions for this, but this is not mandatory and you can use anything you are used to.&lt;br /&gt;
&lt;br /&gt;
Python&lt;br /&gt;
&lt;br /&gt;
I've created some quick and dirty tools under python to test the device, so make sure Python (3.9 at least) is installed in your system if you want to use them.&lt;br /&gt;
&lt;br /&gt;
=== The Device ===&lt;br /&gt;
&lt;br /&gt;
For this guide, I'll be using the [https://www.logitechg.com/en-gb/products/flight/flight-simulator-cockpit-radio-panel.945-000011.html]Saitek/Logitech radio panel as an example that would hopefully help you with any other device.&lt;br /&gt;
&lt;br /&gt;
So let the fun begin!&lt;br /&gt;
&lt;br /&gt;
=== Understanding what's the name of the device ===&lt;br /&gt;
&lt;br /&gt;
Start your PC and go to the terminal, do not connect any device yet, and let's see what has been detected in the USB connections:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
lsusb&lt;br /&gt;
Bus 002 Device 003: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 002: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub&lt;br /&gt;
Bus 001 Device 012: ID 138a:00ab Validity Sensors, Inc. &lt;br /&gt;
Bus 001 Device 011: ID 093a:2510 Pixart Imaging, Inc. Optical Mouse&lt;br /&gt;
Bus 001 Device 008: ID 258a:0001 SINO WEALTH USB KEYBOARD&lt;br /&gt;
Bus 001 Device 005: ID 214b:7250 Huasheng Electronics USB2.0 HUB&lt;br /&gt;
Bus 001 Device 003: ID 04f2:b669 Chicony Electronics Co., Ltd HP HD Camera&lt;br /&gt;
Bus 001 Device 013: ID 8087:0aaa Intel Corp. Bluetooth 9460/9560 Jefferson Peak (JfP)&lt;br /&gt;
Bus 001 Device 004: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 002: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By issuing the 'lsusb' command you can see what the PC has detected as connected devices, no sign yet of my radio panel, so let's connect it now and issue the same command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
lsusb&lt;br /&gt;
Bus 002 Device 003: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 002: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub&lt;br /&gt;
Bus 001 Device 012: ID 138a:00ab Validity Sensors, Inc. &lt;br /&gt;
Bus 001 Device 011: ID 093a:2510 Pixart Imaging, Inc. Optical Mouse&lt;br /&gt;
Bus 001 Device 008: ID 258a:0001 SINO WEALTH USB KEYBOARD&lt;br /&gt;
Bus 001 Device 005: ID 214b:7250 Huasheng Electronics USB2.0 HUB&lt;br /&gt;
Bus 001 Device 003: ID 04f2:b669 Chicony Electronics Co., Ltd HP HD Camera&lt;br /&gt;
Bus 001 Device 013: ID 8087:0aaa Intel Corp. Bluetooth 9460/9560 Jefferson Peak (JfP)&lt;br /&gt;
Bus 001 Device 014: ID 06a3:0d05 Saitek PLC Pro Flight Radio Panel&lt;br /&gt;
Bus 001 Device 004: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 002: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Interestingly, I now see the ''Bus 001 Device 014: ID 06a3:0d05 Saitek PLC Pro Flight Radio Panel'' being shown in my connected devices.&lt;br /&gt;
&lt;br /&gt;
If your device does not show up, make sure that it is properly connected, and powered if needed, and as a last resort try to see if it is connectable to any other PC. If still it does not show, then either probably it is not an HID device, or it is not working at all.&lt;br /&gt;
&lt;br /&gt;
So now, save the name ''Saitek PLC Pro Flight Radio Panel'', we will need it afterwards.&lt;br /&gt;
&lt;br /&gt;
=== Making sure your Linux user has full access to the device ===&lt;br /&gt;
&lt;br /&gt;
One of the issues with Linux and HID devices is user permissions, Linux is quite secure and usually will let a specific subset of users use the HID device, so let's make sure your user has access to this particular one.&lt;br /&gt;
&lt;br /&gt;
Let's go back to the 'lsusb' output from earlier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
Bus 001 Device 014: ID 06a3:0d05 Saitek PLC Pro Flight Radio Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
See that there are 2 hexadecimal numbers in there: '''06a3:0d05 '''? The part before the colon is the vendor id (or VID for shorts) and the second one is the product ID (or PID) for shorts. The first one will change depending on the manufacturer of the device, you can check [https://the-sz.com/products/usbid/index.php?v=0x06A3&amp;amp;p=0d05&amp;amp;n=]here if you're curious. &lt;br /&gt;
&lt;br /&gt;
Now, keep those numbers somewhere safe, we will need them.&lt;br /&gt;
&lt;br /&gt;
One of the first parameters to have access to a HID device is to make sure that the user belongs to a group we can refer to, for example in Ubuntu, if your user has to have access to joysticks (as any kind of gaming device) then it has to be added to the 'js' group, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
usermod -a -G examplegroup exampleusername&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where ''examplegroup'' is ''js'' in our case and ''exampleusername'' is your Linux user. You will need to run this as root, so add the 'sudo' prefix before the command&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
sudo usermod -a -G examplegroup exampleusername&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remember this 'sudo' for later on.&lt;br /&gt;
&lt;br /&gt;
Ok, so now let's make sure your user belongs to the js group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
groups&lt;br /&gt;
pi adm dialout cdrom sudo dip plugdev lpadmin lxd sambashare usb wireshark js&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
I can see my user's last group is js, well done, one thing less.&lt;br /&gt;
&lt;br /&gt;
Now we have to make sure that your device is recognized as a joystick, for this, you need to create a new udev rule. Do not worry about what this means exactly (although you can read about it at [https://opensource.com/article/18/11/udev]Opensource.com)&lt;br /&gt;
&lt;br /&gt;
We need to tell your Linux install that the Saitek device is a joystick (fun fact, my Linux install though the panel was a mouse, and moving the dials would move the actual mouse...) :&lt;br /&gt;
&lt;br /&gt;
There are several ways you can do this but this one works for me:&lt;br /&gt;
&lt;br /&gt;
Open the (or create a new) rule file under ''/etc/udev/rules.d/'', I have called it ''00-local.rules''&lt;br /&gt;
&lt;br /&gt;
so, let's go for it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
nano /etc/udev/rules.d/00-local.rules&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will open an editor (nano), feel free to use any editor, just remember that you have to be root to be able to save the file. &lt;br /&gt;
&lt;br /&gt;
Add the following line to your file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
SUBSYSTEM==&amp;quot;input&amp;quot;, ATTRS{idVendor}==&amp;quot;06a3&amp;quot;, ATTRS{idProduct}==&amp;quot;0d05&amp;quot;, ENV{ID_INPUT_JOYSTICK}=&amp;quot;1&amp;quot;,ENV{ID_INPUT_MOUSE}=&amp;quot;0&amp;quot;, TAG+=&amp;quot;uaccess&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
We now are saying to Linux that the device with VID 06a3 and PID 0d05 is a joystick and not a mouse (do those numbers ring a bell?)&lt;br /&gt;
&lt;br /&gt;
Just for completion's sake, there's another possibility to do this, alas less 'secure' by Linux standards. You can create a new file:&lt;br /&gt;
''/etc/udev/rules.d/99-hid.rules'' and in it add the following lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
SUBSYSTEM==&amp;quot;usb&amp;quot;, ATTRS{idVendor}==&amp;quot;06a3&amp;quot;, ATTRS{idProduct}==&amp;quot;0d05&amp;quot;, MODE=&amp;quot;0666&amp;quot;&lt;br /&gt;
KERNEL==&amp;quot;hidraw*&amp;quot;, ATTRS{busnum}==&amp;quot;1&amp;quot;, ATTRS{idVendor}==&amp;quot;06a3&amp;quot;, ATTRS{idProduct}==&amp;quot;0d05&amp;quot;, MODE=&amp;quot;0666&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will give anyone access to the device in question (and hence less secure in Linux terms).&lt;br /&gt;
&lt;br /&gt;
So now we have setup the device so it is a joystick and your user can access it. Let's go and play with it:&lt;br /&gt;
&lt;br /&gt;
=== Understanding your device's Inputs and outputs ===&lt;br /&gt;
&lt;br /&gt;
Make sure your device is connected and powered if needed, Once you're sure, launch hidviz:&lt;br /&gt;
&lt;br /&gt;
(I have compiled the version from the link I've put in the tools section, I won't be explaining how to buildit since it is already explained in the github page)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
./hidviz&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will present you with the following screen:&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-selector.png|Screenshot of hidviz tool main screen]]&lt;br /&gt;
&lt;br /&gt;
Click on 'Select Device', this will ask you for your password to gain root access if you have not run the command as 'sudo'&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-selector-2.png|Device selector from hidviz]]&lt;br /&gt;
&lt;br /&gt;
You should see the saitek pro panel there, select it:&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-descriptor-saitek-radio-panelpng.png|Hiviz showing the HiD descritpor for the saitek radio panel]]&lt;br /&gt;
&lt;br /&gt;
As you can see, there are 24 buttons (bits) (top section Collection/Input) and there seem to be 2 features. One containing 20 (report count) 8-bit values (report size) with a maximum logic value of 255 and then another report of 14 times 1-bit values (fun fact, when I started with the HID devices I didn't use hidviz, so I'm intrigued by this second feature report which I was not aware of!).&lt;br /&gt;
&lt;br /&gt;
For completion, HID devices (as far as I am aware) have 3 types of reports, input (which is data sent from device to PC) output (which is data sent from PC to device) and feature, which seems to be also in the PC to device category.  As you can see, here you have 1 input (buttons) 2 features (we'll talk about these later) and a padding of 2 bits, this is there because usually reports need to be of a specific size (multiplier of 24 if I remember correctly), if you do your maths: 24bits + 20*8 (160 bits) + 14 bits = 198 + 2 padding bits  = 200 bits in total, ok it does not add up, go figure, but this is not the only weird thing about this descriptor, look at the actual features described: water cooling device! either Saitek devs had a great sense of humor or they didn't spend much time figuring out how to do proper HID reports. In any case, I was expecting also to have an output report instead of a feature report and each report with its unique ID. Saitek: some improvements are needed here! All of this to say: '''HID is a big grey area amongst manufacturers, so your levels of patience to make the device work may vary'''&lt;br /&gt;
&lt;br /&gt;
If the descriptor would have been set up properly, you should have seen something like this for the output reports: (This is for one of my custom devices):&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-descriptor-fgmod.png|Hidvizz showing the fgmod descriptor]]&lt;br /&gt;
&lt;br /&gt;
This would have allowed you to easily enter values in the output report and understand how the device treated data, alas, it is not the case for the saitek device, so let's go Python!&lt;br /&gt;
&lt;br /&gt;
=== Understanding how data is received and processed by your device: ===&lt;br /&gt;
&lt;br /&gt;
So we now know a little bit more about the device, it has 24 buttons, and it has 20 possible inputs (spoiler: the Saitek panel has 4*5 segment displays, could it be?? Hmmmm...)&lt;br /&gt;
&lt;br /&gt;
Let's try python&lt;br /&gt;
&lt;br /&gt;
First, you need to check which hidraw linux device corresponds to your actual device, Linux will map your device under ''/dev/hidrawx'' and to find it, create  script (call it findhid.sh):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
FILES=/dev/hidraw*&lt;br /&gt;
for f in $FILES&lt;br /&gt;
do&lt;br /&gt;
  FILE=${f##*/}&lt;br /&gt;
  DEVICE=&amp;quot;$(cat /sys/class/hidraw/${FILE}/device/uevent | grep HID_NAME | cut -d '=' -f2)&amp;quot;&lt;br /&gt;
  printf &amp;quot;%s \t %s\n&amp;quot; $FILE &amp;quot;$DEVICE&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
chmod 775 findhid.sh&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
And finally execute it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
./findhid.sh&lt;br /&gt;
hidraw0 	 SYNA3083:00 06CB:8265&lt;br /&gt;
hidraw1 	 ELAN2514:00 04F3:288A&lt;br /&gt;
hidraw2 	 SINO WEALTH USB KEYBOARD&lt;br /&gt;
hidraw3 	 SINO WEALTH USB KEYBOARD&lt;br /&gt;
hidraw4 	 PixA琀 USB Optical Mouse&lt;br /&gt;
hidraw7 	 Logitech Logitech Flight Radio Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
so, this means that our Saitek panel is linked to /dev/hidraw7, nice!&lt;br /&gt;
&lt;br /&gt;
Now, open an editor and create hidtest.py:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def send_data_to_hidraw(data, hidraw_path):&lt;br /&gt;
    try:&lt;br /&gt;
        # Open the HIDRAW device&lt;br /&gt;
        hidraw = os.open(hidraw_path, os.O_RDWR | os.O_NONBLOCK)&lt;br /&gt;
        &lt;br /&gt;
        # Write data to the HIDRAW device&lt;br /&gt;
        os.write(hidraw, bytes(data))&lt;br /&gt;
        &lt;br /&gt;
        print(&amp;quot;Data sent successfully to HIDRAW device.&amp;quot;)&lt;br /&gt;
        &lt;br /&gt;
        # Close the HIDRAW device&lt;br /&gt;
        os.close(hidraw)&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(&amp;quot;Error:&amp;quot;, e)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    # Define your data to send&lt;br /&gt;
    data_to_send = [0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03]  # Example data&lt;br /&gt;
    &lt;br /&gt;
    # Specify the path to your HIDRAW device&lt;br /&gt;
    hidraw_path = &amp;quot;/dev/hidraw7&amp;quot;  # Replace with the actual path to your HIDRAW device&lt;br /&gt;
    &lt;br /&gt;
    # Send the data to the HIDRAW device&lt;br /&gt;
    send_data_to_hidraw(data_to_send, hidraw_path)&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Two important things: change hidraw_path to your devices' correct link and make sure that the data_to_send variable is of the same length as the report we found in hidvix, in this case, we have 20 times one byte, noted in hex format in Python (0xXX).&lt;br /&gt;
&lt;br /&gt;
Small clarification, as you can see I'm sending 21 bytes, the reason behind this is that the first byte indicates the report_id you're sending to, in the case of the saitek panel, there's no real report id, so whatever you put in the first byte will still work. Make sure you consider this when testing your device.&lt;br /&gt;
&lt;br /&gt;
Now run the python script&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
python3 hidtest.py&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nothing happened? well, this could be down to several factors:&lt;br /&gt;
&lt;br /&gt;
- No permissions (go back to the start)&lt;br /&gt;
- The report is of incorrect size (try again, remember you are sending bytes, so a report of 8 times 1 bit, equals a nibble (half byte), and the same goes for bits. The safest thing to do is to count the number of bits and then divide by 8, this is the number of bytes you ill need to send)&lt;br /&gt;
&lt;br /&gt;
If you are lucky you should go from this:&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-radio-off.jpg|Saitek radio panel with all digits off|800x800px]]&lt;br /&gt;
&lt;br /&gt;
To this:&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-radio-on.jpg|Saitek radio panel with all digits on|800x800px]]&lt;br /&gt;
&lt;br /&gt;
Congratulations, you just sent the first pieces of data to your device. As you can see it shows the numbers in the order we sent in the report, or so it looks like.&lt;br /&gt;
&lt;br /&gt;
Now, it is a game of sending reports with different values and understanding what's your device's reaction, for example, if I sent just zeores:&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeros.jpg|800x800px]]&lt;br /&gt;
&lt;br /&gt;
Now the fun starts. &lt;br /&gt;
&lt;br /&gt;
So this is a radio panel right, aren't radio frequencies supposed to have a 'dot' somewhere, but hey, how do I tell the device I want to have a dot? Let's think, why do I have the possibility to send 20 bytes, with a maximum value of 255? Makes no sense right, watch byte represents a number in the panel that can go up to 9 (0 to 9), so anything else is overkill, unless...&lt;br /&gt;
&lt;br /&gt;
Let's try to send something over 9, for example the second byte in data_to send I put it as 0x0A (A is 10 in hex), what happened there?&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeros first-off.jpg|Saitek radio panel showing all zeros except first digit switched off|800x800px]]&lt;br /&gt;
&lt;br /&gt;
My first digit just switched off!! Interesting so now I can show numbers of less than 5 digits (XPDR, DME, hmm...) because I can switch any digit off as I please, let's try that again:&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-alternate-zeros.jpg|Saitek radio panel showing alternate zeroes and off|800x800px]]&lt;br /&gt;
&lt;br /&gt;
Nice!&lt;br /&gt;
&lt;br /&gt;
So we now know, 0 to 9 is the digit in question, 10 switches off the digit, but what about the 'dot' ???&lt;br /&gt;
&lt;br /&gt;
Let's send 11 (0x0B):&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeros first-off.jpg|Saitek radio panel showing all zeros except first digit switched off|800x800px]]&lt;br /&gt;
&lt;br /&gt;
Disappointment, nothing happens, let's keep trying other values.&lt;br /&gt;
&lt;br /&gt;
Hey what's this?&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-ones_and_dots.jpg|800x800px]]&lt;br /&gt;
&lt;br /&gt;
I was at 209, so what if I send all 208 (0xD0)&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeroes_and_dots.jpg|Saitek radio panel showing all zeroe and dots|800x800px]]&lt;br /&gt;
&lt;br /&gt;
Ok! so if I want to add a dot to any digit, I need to add 0xD0 the the value, so 0xD0 for 0, 0xD1 for one and so on)&lt;br /&gt;
&lt;br /&gt;
What If I continue?&lt;br /&gt;
&lt;br /&gt;
This is what happens with 224 (0xE0)&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-dashes.jpg|800x800px]]&lt;br /&gt;
&lt;br /&gt;
I get a 'dash'!&lt;br /&gt;
&lt;br /&gt;
And there's nothing else interesting in the tests, the numbers repeat a lot, but basically when now:&lt;br /&gt;
&lt;br /&gt;
0 to 9 -&amp;gt; the numbers in each digit&lt;br /&gt;
10 -&amp;gt; Switch off the digits&lt;br /&gt;
208-217 -&amp;gt; The numbers with a dot (to the right)&lt;br /&gt;
224 -&amp;gt; A dash&lt;br /&gt;
&lt;br /&gt;
Important point, we have not used any proprietary drivers or anything that could be linked to Saitek's proprietary development (AFAIK, I'm not a lawyer), we're just sending data to the device.&lt;br /&gt;
&lt;br /&gt;
Now that we know the logic, we're ready to go to the next step, make it work in FlightGear! [To be continued in next post]&lt;br /&gt;
&lt;br /&gt;
So now we have understood (more or less) how our device works, how we can send data to it, and what this data does.&lt;br /&gt;
&lt;br /&gt;
Let's fire up FlightGear.&lt;br /&gt;
&lt;br /&gt;
=== Making sure FlightGear detects the device ===&lt;br /&gt;
&lt;br /&gt;
The first thing we need to do is to launch FlightFear with debug on, to do this make sure you set the log level to debug via the ''--log-level=debug'' flag, do this either in the command line or if you use the launcher, in the additional settings.&lt;br /&gt;
&lt;br /&gt;
I would also recommend you to capture the output of the log:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
./dnc-managed/run_fgfs.sh --launcher 2&amp;gt;&amp;amp;1 | tee log.txt&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is my command, yours may be slightly different, the important part is the ''2&amp;gt;&amp;amp;1 | tee log.txt'' at the end of it.&lt;br /&gt;
&lt;br /&gt;
launch FG an let the  log start capturing all the information we need.&lt;br /&gt;
&lt;br /&gt;
Once the airplane's cockpit is showing up, you can shut down FlightGear, that'w all we need for now.&lt;br /&gt;
&lt;br /&gt;
Open the ''log.txt'' and start looking for the name of your device, you should see things like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;  225.20 [DBUG]:input      name=&amp;lt;null&amp;gt;, node=&amp;lt;null&amp;gt;&lt;br /&gt;
  225.20 [DBUG]:input      name=Logitech Logitech Flight Radio Panel, node=/dev/input/event23&lt;br /&gt;
&lt;br /&gt;
225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-0 modifiers=0 value=1&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-1 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-2 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-3 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-4 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-5 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-6 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-7 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-8 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-9 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-266 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-267 modifiers=0 value=1&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-268 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-269 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-270 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-271 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-left modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-right modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-middle modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-side modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-extra modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-forward modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-back modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-task modifiers=0 value=0&lt;br /&gt;
  225.26 [DBUG]:input      using InputDevice Logitech Logitech Flight Radio Panel_0&lt;br /&gt;
&lt;br /&gt;
225.28 [WARN]:input      Unhandled HID generic desktop usage:1&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown, bits: 0:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:2&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-1, bits: 8:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:3&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-2, bits: 16:8, report=0&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:joystick, bits: 24:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:5&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-3, bits: 32:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:6&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-4, bits: 40:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:7&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-5, bits: 48:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:8&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-6, bits: 56:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:9&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-7, bits: 64:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:10&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-8, bits: 72:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:11&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-9, bits: 80:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:12&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-10, bits: 88:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:13&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-11, bits: 96:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:14&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-12, bits: 104:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:15&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-13, bits: 112:8, report=0&lt;br /&gt;
  225.29 [WARN]:input      Unhandled HID generic desktop usage:16&lt;br /&gt;
  225.29 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-14, bits: 120:8, report=0&lt;br /&gt;
  225.29 [WARN]:input      Unhandled HID generic desktop usage:17&lt;br /&gt;
  225.29 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-15, bits: 128:8, report=0&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see from the log, there are already several interesting pieces of information:&lt;br /&gt;
&lt;br /&gt;
The device has ben recognized! ''25.20 [DBUG]:input      name=Logitech Logitech Flight Radio Panel, node=/dev/input/event23''&lt;br /&gt;
&lt;br /&gt;
It has detected the buttons ''225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-0 modifiers=0 value=1''&lt;br /&gt;
&lt;br /&gt;
And even the feature reports '' 225.28 [WARN]:input      Unhandled HID generic desktop usage:2&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-1, bits: 8:8, report=0''&lt;br /&gt;
&lt;br /&gt;
As you can see, we have everything under control, FG has detected the device and has detected the different buttons and feature reports. All of these are called 'events' by Flightgear.&lt;br /&gt;
&lt;br /&gt;
Important point, when we're going to be creating the properties files, we need to refer to the name you see in the logs, as strange as it sounds, you will get different buttons name not necessarily in a sequential order (things like thumb2, or button-333).&lt;br /&gt;
&lt;br /&gt;
=== The properties files ===&lt;br /&gt;
&lt;br /&gt;
The way that FlighGear communicates with the devices is via XML files located under the FlighGear directory ('~/.fgfs' for most linux installs) and then under Input, with 2 different options, either 'Joysticks' or 'Event':&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
drwxr-xr-x 2 pi pi 4096 Mar 27 16:12 Event&lt;br /&gt;
drwxr-xr-x 2 pi pi 4096 Apr  1 15:49 Joysticks&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
The joystick directory will hold, amongst others, the files that are created automatically by the joystick configurator within the simulator, the directory we're interested in is this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;~/.fgfs/Input/Event&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, there's no problem in having both a joystick file and an event file for the same device, I do have this for my Honeycomb alpha, where the axes are in the joystick file and the rest of the buttons in the event file (which allows me to go beyond the 32 button limitation, yes, you can use this HID way of doing things for devices over 32 buttons).&lt;br /&gt;
&lt;br /&gt;
So let's start writing. First of all, create an empty file called 'YOURDEVCIE.xml' (this is an example and the filename is not relevant as FG will read inside to understand to which device each file belongs (although I name it as the device with '-' just for clarity, for example for the saitek panel ''Logitech-Logitech-Flight-Radio-Panel.xml'' )&lt;br /&gt;
&lt;br /&gt;
Put the XML header:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;PropertyList&amp;gt;&lt;br /&gt;
  &amp;lt;name type=&amp;quot;string&amp;quot;&amp;gt;Logitech Logitech Flight Radio Panel&amp;lt;/name&amp;gt;&lt;br /&gt;
  &amp;lt;debug-events type=&amp;quot;bool&amp;quot;&amp;gt;true&amp;lt;/debug-events&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will indicate FG this is the file for your device, as the ''name'' tag defines it.&lt;br /&gt;
&lt;br /&gt;
If you plan to have some 'logic' in your properties file, add the nasal tags:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;PropertyList&amp;gt;&lt;br /&gt;
  &amp;lt;name type=&amp;quot;string&amp;quot;&amp;gt;Logitech Logitech Flight Radio Panel&amp;lt;/name&amp;gt;&lt;br /&gt;
  &amp;lt;debug-events type=&amp;quot;bool&amp;quot;&amp;gt;true&amp;lt;/debug-events&amp;gt;&lt;br /&gt;
  &amp;lt;nasal&amp;gt;&lt;br /&gt;
    &amp;lt;open&amp;gt;&lt;br /&gt;
      &amp;lt;![CDATA[]]&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Your basic file is starting to get some form. Now we need to start defining what do we do when each of the events is triggered:&lt;br /&gt;
I'm going to paste below the bindings (that's how it's called in FG) for the fact that you have switched the upper selector of the radio panel into 'comm1' mode:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;event&amp;gt;&lt;br /&gt;
    &amp;lt;desc&amp;gt;UK COMM1&amp;lt;/desc&amp;gt;&lt;br /&gt;
    &amp;lt;name&amp;gt;button-1&amp;lt;/name&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknoba&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/selected-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobb&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/standby-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobt&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;5&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
 &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobsw&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frq-swap-btn&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobmax&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;137&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobmin&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;118&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobfstep&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;1&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobhstep&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;0.025&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;script&amp;gt;refreshPanels();&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
  &amp;lt;/event&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Do not be scared by that size! I like to make things generic, so you will see a lot of reference and proxy properties being set that would allow to handle the logic of what happens when we're in 'comm1' mode in the upper panel.&lt;br /&gt;
&lt;br /&gt;
First of all we set the property ''saitek/RP/upknoba'' to ''/instrumentation/comm/frequencies/selected-mhz''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknoba&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/selected-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then set the standby frequency to the ''/saitek/RP/upknobb'' property&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobb&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/standby-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then the property ''/saitek/RP/upknobt'' to 5, which is the number of digits a frequency has&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobt&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;5&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then the 'swap' button to change frequencies&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobsw&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frq-swap-btn&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
The some max,min and incremental values, and last but not least, I call the refresh panel function (that I've created) to put the proper values in the panels:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;script&amp;gt;refreshPanels();&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
  &amp;lt;/event&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has to be done to every single button in the device, so they act the way you expect them to do. You can check the full file at the bottom of this post.&lt;br /&gt;
&lt;br /&gt;
Ok, so we have the buttons set up, now we want the display to show the proper values:&lt;br /&gt;
&lt;br /&gt;
We use the same tag, event, only that now we have to link a property to the event, so FG will send that value to the output/feature report in the proper position.&lt;br /&gt;
&lt;br /&gt;
Before we continue, remember that in the log, we saw things like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
225.28 [WARN]:input      Unhandled HID generic desktop usage:1&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown, bits: 0:8, report=0&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
And I did mention that the name that you saw there is the name that should be used for the event, in the case of unknown, you need to add the suffix ''-0'' for the first one, the rest will already have it ''-1, -2,-3 etc..''&lt;br /&gt;
&lt;br /&gt;
Let's add the event to the XML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;event&amp;gt;&lt;br /&gt;
    &amp;lt;desc&amp;gt;RADIO INDICATORS&amp;lt;/desc&amp;gt;&lt;br /&gt;
    &amp;lt;name&amp;gt;unknown-0&amp;lt;/name&amp;gt;&lt;br /&gt;
    &amp;lt;setting&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/ULpanel/digit1&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;/setting&amp;gt;&lt;br /&gt;
  &amp;lt;/event&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
You're telling FlightGear to watch for the property ''/saitek/RP/ULpanel/digit1'' and set its value to the vendor-0 byte.&lt;br /&gt;
&lt;br /&gt;
As you can see there's a strange property there: ''saitek/RP/ULpanel/digit1''. This property is of my choice and you can create any property you want to be sent to the device. Remember that in this particular case, we have a value for each digit, so we cannot send the actual value, we have to slice it so we send each digit in the correct position.&lt;br /&gt;
&lt;br /&gt;
And then again, do the same for the rest of the events.&lt;br /&gt;
&lt;br /&gt;
Once the events have been set and saved, you can launch FG to see if it worked!&lt;br /&gt;
&lt;br /&gt;
Yes! I see the same frequencies in the panel&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-working.jpg|800x800px]]&lt;br /&gt;
&lt;br /&gt;
as in the simulator&lt;br /&gt;
&lt;br /&gt;
[[File:FG-Radio_Panel_for_Saitek.jpg|800x800px]]&lt;br /&gt;
&lt;br /&gt;
Of course, every time you modify the frequencies in any of the sim or panel, the other one reflects the same value as expected.&lt;br /&gt;
&lt;br /&gt;
You can have a look at [[https://github.com/zayamatias/flightgear/blob/main/.fgfs/Input/Event/Logitech-Logitech-Flight-Radio-Panel.xml]the complete xml file, where you can see I use nasal heavily to do some extra logic, for example, do not turn on the panel unless the contact is set on the aeroplane, how I use the swap button to select the digit when in XPDR mode, and so on. There is no limits to what you can do once you understand the properties and what you're able to do with them.&lt;br /&gt;
&lt;br /&gt;
I hope I have not forgotten anything essential and I also hope this has helped. I'm really looking forward to other devices becoming available in FG.&lt;br /&gt;
&lt;br /&gt;
This also opens the possibility of creating your own devices, have a look at my [https://github.com/zayamatias/flightgear]repo.&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User:Zayamatias/Adding_HID_devices_to_FlightGear&amp;diff=139766</id>
		<title>User:Zayamatias/Adding HID devices to FlightGear</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User:Zayamatias/Adding_HID_devices_to_FlightGear&amp;diff=139766"/>
		<updated>2024-04-22T16:07:13Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Adding HID devices to FlightGear''' hopes to explain how to set-up any HID device to work with FlightGear in a step-by-step easy to follow guide, it is my belief that any HID can and will work with FlightGear&lt;br /&gt;
&lt;br /&gt;
First disclaimer: The HID subsystem seems to be working only under Linux and MacOS, I am not sure if one day it will work in Windows. &lt;br /&gt;
Second Disclaimer: This guide was done under an Ubuntu distribution, this means that other distros may vary slightly. &lt;br /&gt;
Last but not least: I take no responsibility in the unlikely event of you breaking your HID device by using this guide&lt;br /&gt;
&lt;br /&gt;
=== Getting started ===&lt;br /&gt;
&lt;br /&gt;
Before starting, there are a couple of tools you need to install:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/hidviz/hidviz] HIDVIZ&lt;br /&gt;
&lt;br /&gt;
This tool will allow you to have a look at the inner workings of your HID device, I'll talk about it later.&lt;br /&gt;
&lt;br /&gt;
[https://code.visualstudio.com/]VS Code&lt;br /&gt;
&lt;br /&gt;
I use this for creating the XMLfiles and the Nasal code, as it has very nice extensions for this, but this is not mandatory and you can use anything you are used to.&lt;br /&gt;
&lt;br /&gt;
Python&lt;br /&gt;
&lt;br /&gt;
I've created some quick and dirty tools under python to test the device, so make sure Python (3.9 at least) is installed in your system if you want to use them.&lt;br /&gt;
&lt;br /&gt;
=== The Device ===&lt;br /&gt;
&lt;br /&gt;
For this guide, I'll be using the [https://www.logitechg.com/en-gb/products/flight/flight-simulator-cockpit-radio-panel.945-000011.html]Saitek/Logitech radio panel as an example that would hopefully help you with any other device.&lt;br /&gt;
&lt;br /&gt;
So let the fun begin!&lt;br /&gt;
&lt;br /&gt;
=== Understanding what's the name of the device ===&lt;br /&gt;
&lt;br /&gt;
Start your PC and go to the terminal, do not connect any device yet, and let's see what has been detected in the USB connections:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
lsusb&lt;br /&gt;
Bus 002 Device 003: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 002: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub&lt;br /&gt;
Bus 001 Device 012: ID 138a:00ab Validity Sensors, Inc. &lt;br /&gt;
Bus 001 Device 011: ID 093a:2510 Pixart Imaging, Inc. Optical Mouse&lt;br /&gt;
Bus 001 Device 008: ID 258a:0001 SINO WEALTH USB KEYBOARD&lt;br /&gt;
Bus 001 Device 005: ID 214b:7250 Huasheng Electronics USB2.0 HUB&lt;br /&gt;
Bus 001 Device 003: ID 04f2:b669 Chicony Electronics Co., Ltd HP HD Camera&lt;br /&gt;
Bus 001 Device 013: ID 8087:0aaa Intel Corp. Bluetooth 9460/9560 Jefferson Peak (JfP)&lt;br /&gt;
Bus 001 Device 004: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 002: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By issuing the 'lsusb' command you can see what the PC has detected as connected devices, no sign yet of my radio panel, so let's connect it now and issue the same command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
lsusb&lt;br /&gt;
Bus 002 Device 003: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 002: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub&lt;br /&gt;
Bus 001 Device 012: ID 138a:00ab Validity Sensors, Inc. &lt;br /&gt;
Bus 001 Device 011: ID 093a:2510 Pixart Imaging, Inc. Optical Mouse&lt;br /&gt;
Bus 001 Device 008: ID 258a:0001 SINO WEALTH USB KEYBOARD&lt;br /&gt;
Bus 001 Device 005: ID 214b:7250 Huasheng Electronics USB2.0 HUB&lt;br /&gt;
Bus 001 Device 003: ID 04f2:b669 Chicony Electronics Co., Ltd HP HD Camera&lt;br /&gt;
Bus 001 Device 013: ID 8087:0aaa Intel Corp. Bluetooth 9460/9560 Jefferson Peak (JfP)&lt;br /&gt;
Bus 001 Device 014: ID 06a3:0d05 Saitek PLC Pro Flight Radio Panel&lt;br /&gt;
Bus 001 Device 004: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 002: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Interestingly, I now see the ''Bus 001 Device 014: ID 06a3:0d05 Saitek PLC Pro Flight Radio Panel'' being shown in my connected devices.&lt;br /&gt;
&lt;br /&gt;
If your device does not show up, make sure that it is properly connected, and powered if needed, and as a last resort try to see if it is connectable to any other PC. If still it does not show, then either probably it is not an HID device, or it is not working at all.&lt;br /&gt;
&lt;br /&gt;
So now, save the name ''Saitek PLC Pro Flight Radio Panel'', we will need it afterwards.&lt;br /&gt;
&lt;br /&gt;
=== Making sure your Linux user has full access to the device ===&lt;br /&gt;
&lt;br /&gt;
One of the issues with Linux and HID devices is user permissions, Linux is quite secure and usually will let a specific subset of users use the HID device, so let's make sure your user has access to this particular one.&lt;br /&gt;
&lt;br /&gt;
Let's go back to the 'lsusb' output from earlier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
Bus 001 Device 014: ID 06a3:0d05 Saitek PLC Pro Flight Radio Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
See that there are 2 hexadecimal numbers in there: '''06a3:0d05 '''? The part before the colon is the vendor id (or VID for shorts) and the second one is the product ID (or PID) for shorts. The first one will change depending on the manufacturer of the device, you can check [https://the-sz.com/products/usbid/index.php?v=0x06A3&amp;amp;p=0d05&amp;amp;n=]here if you're curious. &lt;br /&gt;
&lt;br /&gt;
Now, keep those numbers somewhere safe, we will need them.&lt;br /&gt;
&lt;br /&gt;
One of the first parameters to have access to a HID device is to make sure that the user belongs to a group we can refer to, for example in Ubuntu, if your user has to have access to joysticks (as any kind of gaming device) then it has to be added to the 'js' group, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
usermod -a -G examplegroup exampleusername&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where ''examplegroup'' is ''js'' in our case and ''exampleusername'' is your Linux user. You will need to run this as root, so add the 'sudo' prefix before the command&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
sudo usermod -a -G examplegroup exampleusername&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remember this 'sudo' for later on.&lt;br /&gt;
&lt;br /&gt;
Ok, so now let's make sure your user belongs to the js group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
groups&lt;br /&gt;
pi adm dialout cdrom sudo dip plugdev lpadmin lxd sambashare usb wireshark js&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
I can see my user's last group is js, well done, one thing less.&lt;br /&gt;
&lt;br /&gt;
Now we have to make sure that your device is recognized as a joystick, for this, you need to create a new udev rule. Do not worry about what this means exactly (although you can read about it at [https://opensource.com/article/18/11/udev]Opensource.com)&lt;br /&gt;
&lt;br /&gt;
We need to tell your Linux install that the Saitek device is a joystick (fun fact, my Linux install though the panel was a mouse, and moving the dials would move the actual mouse...) :&lt;br /&gt;
&lt;br /&gt;
There are several ways you can do this but this one works for me:&lt;br /&gt;
&lt;br /&gt;
Open the (or create a new) rule file under ''/etc/udev/rules.d/'', I have called it ''00-local.rules''&lt;br /&gt;
&lt;br /&gt;
so, let's go for it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
nano /etc/udev/rules.d/00-local.rules&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will open an editor (nano), feel free to use any editor, just remember that you have to be root to be able to save the file. &lt;br /&gt;
&lt;br /&gt;
Add the following line to your file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
SUBSYSTEM==&amp;quot;input&amp;quot;, ATTRS{idVendor}==&amp;quot;06a3&amp;quot;, ATTRS{idProduct}==&amp;quot;0d05&amp;quot;, ENV{ID_INPUT_JOYSTICK}=&amp;quot;1&amp;quot;,ENV{ID_INPUT_MOUSE}=&amp;quot;0&amp;quot;, TAG+=&amp;quot;uaccess&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
We now are saying to Linux that the device with VID 06a3 and PID 0d05 is a joystick and not a mouse (do those numbers ring a bell?)&lt;br /&gt;
&lt;br /&gt;
Just for completion's sake, there's another possibility to do this, alas less 'secure' by Linux standards. You can create a new file:&lt;br /&gt;
''/etc/udev/rules.d/99-hid.rules'' and in it add the following lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
SUBSYSTEM==&amp;quot;usb&amp;quot;, ATTRS{idVendor}==&amp;quot;06a3&amp;quot;, ATTRS{idProduct}==&amp;quot;0d05&amp;quot;, MODE=&amp;quot;0666&amp;quot;&lt;br /&gt;
KERNEL==&amp;quot;hidraw*&amp;quot;, ATTRS{busnum}==&amp;quot;1&amp;quot;, ATTRS{idVendor}==&amp;quot;06a3&amp;quot;, ATTRS{idProduct}==&amp;quot;0d05&amp;quot;, MODE=&amp;quot;0666&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will give anyone access to the device in question (and hence less secure in Linux terms).&lt;br /&gt;
&lt;br /&gt;
So now we have setup the device so it is a joystick and your user can access it. Let's go and play with it:&lt;br /&gt;
&lt;br /&gt;
=== Understanding your device's Inputs and outputs ===&lt;br /&gt;
&lt;br /&gt;
Make sure your device is connected and powered if needed, Once you're sure, launch hidviz:&lt;br /&gt;
&lt;br /&gt;
(I have compiled the version from the link I've put in the tools section, I won't be explaining how to buildit since it is already explained in the github page)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
./hidviz&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will present you with the following screen:&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-selector.png|Screenshot of hidviz tool main screen]]&lt;br /&gt;
&lt;br /&gt;
Click on 'Select Device', this will ask you for your password to gain root access if you have not run the command as 'sudo'&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-selector-2.png|Device selector from hidviz]]&lt;br /&gt;
&lt;br /&gt;
You should see the saitek pro panel there, select it:&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-descriptor-saitek-radio-panelpng.png|Hiviz showing the HiD descritpor for the saitek radio panel]]&lt;br /&gt;
&lt;br /&gt;
As you can see, there are 24 buttons (bits) (top section Collection/Input) and there seem to be 2 features. One containing 20 (report count) 8-bit values (report size) with a maximum logic value of 255 and then another report of 14 times 1-bit values (fun fact, when I started with the HID devices I didn't use hidviz, so I'm intrigued by this second feature report which I was not aware of!).&lt;br /&gt;
&lt;br /&gt;
For completion, HID devices (as far as I am aware) have 3 types of reports, input (which is data sent from device to PC) output (which is data sent from PC to device) and feature, which seems to be also in the PC to device category.  As you can see, here you have 1 input (buttons) 2 features (we'll talk about these later) and a padding of 2 bits, this is there because usually reports need to be of a specific size (multiplier of 24 if I remember correctly), if you do your maths: 24bits + 20*8 (160 bits) + 14 bits = 198 + 2 padding bits  = 200 bits in total, ok it does not add up, go figure, but this is not the only weird thing about this descriptor, look at the actual features described: water cooling device! either Saitek devs had a great sense of humor or they didn't spend much time figuring out how to do proper HID reports. In any case, I was expecting also to have an output report instead of a feature report and each report with its unique ID. Saitek: some improvements are needed here! All of this to say: '''HID is a big grey area amongst manufacturers, so your levels of patience to make the device work may vary'''&lt;br /&gt;
&lt;br /&gt;
If the descriptor would have been set up properly, you should have seen something like this for the output reports: (This is for one of my custom devices):&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-descriptor-fgmod.png|Hidvizz showing the fgmod descriptor]]&lt;br /&gt;
&lt;br /&gt;
This would have allowed you to easily enter values in the output report and understand how the device treated data, alas, it is not the case for the saitek device, so let's go Python!&lt;br /&gt;
&lt;br /&gt;
=== Understanding how data is received and processed by your device: ===&lt;br /&gt;
&lt;br /&gt;
So we now know a little bit more about the device, it has 24 buttons, and it has 20 possible inputs (spoiler: the Saitek panel has 4*5 segment displays, could it be?? Hmmmm...)&lt;br /&gt;
&lt;br /&gt;
Let's try python&lt;br /&gt;
&lt;br /&gt;
First, you need to check which hidraw linux device corresponds to your actual device, Linux will map your device under ''/dev/hidrawx'' and to find it, create  script (call it findhid.sh):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
FILES=/dev/hidraw*&lt;br /&gt;
for f in $FILES&lt;br /&gt;
do&lt;br /&gt;
  FILE=${f##*/}&lt;br /&gt;
  DEVICE=&amp;quot;$(cat /sys/class/hidraw/${FILE}/device/uevent | grep HID_NAME | cut -d '=' -f2)&amp;quot;&lt;br /&gt;
  printf &amp;quot;%s \t %s\n&amp;quot; $FILE &amp;quot;$DEVICE&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
chmod 775 findhid.sh&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
And finally execute it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
./findhid.sh&lt;br /&gt;
hidraw0 	 SYNA3083:00 06CB:8265&lt;br /&gt;
hidraw1 	 ELAN2514:00 04F3:288A&lt;br /&gt;
hidraw2 	 SINO WEALTH USB KEYBOARD&lt;br /&gt;
hidraw3 	 SINO WEALTH USB KEYBOARD&lt;br /&gt;
hidraw4 	 PixA琀 USB Optical Mouse&lt;br /&gt;
hidraw7 	 Logitech Logitech Flight Radio Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
so, this means that our Saitek panel is linked to /dev/hidraw7, nice!&lt;br /&gt;
&lt;br /&gt;
Now, open an editor and create hidtest.py:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def send_data_to_hidraw(data, hidraw_path):&lt;br /&gt;
    try:&lt;br /&gt;
        # Open the HIDRAW device&lt;br /&gt;
        hidraw = os.open(hidraw_path, os.O_RDWR | os.O_NONBLOCK)&lt;br /&gt;
        &lt;br /&gt;
        # Write data to the HIDRAW device&lt;br /&gt;
        os.write(hidraw, bytes(data))&lt;br /&gt;
        &lt;br /&gt;
        print(&amp;quot;Data sent successfully to HIDRAW device.&amp;quot;)&lt;br /&gt;
        &lt;br /&gt;
        # Close the HIDRAW device&lt;br /&gt;
        os.close(hidraw)&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(&amp;quot;Error:&amp;quot;, e)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    # Define your data to send&lt;br /&gt;
    data_to_send = [0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03]  # Example data&lt;br /&gt;
    &lt;br /&gt;
    # Specify the path to your HIDRAW device&lt;br /&gt;
    hidraw_path = &amp;quot;/dev/hidraw7&amp;quot;  # Replace with the actual path to your HIDRAW device&lt;br /&gt;
    &lt;br /&gt;
    # Send the data to the HIDRAW device&lt;br /&gt;
    send_data_to_hidraw(data_to_send, hidraw_path)&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Two important things: change hidraw_path to your devices' correct link and make sure that the data_to_send variable is of the same length as the report we found in hidvix, in this case, we have 20 times one byte, noted in hex format in Python (0xXX).&lt;br /&gt;
&lt;br /&gt;
Small clarification, as you can see I'm sending 21 bytes, the reason behind this is that the first byte indicates the report_id you're sending to, in the case of the saitek panel, there's no real report id, so whatever you put in the first byte will still work. Make sure you consider this when testing your device.&lt;br /&gt;
&lt;br /&gt;
Now run the python script&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
python3 hidtest.py&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nothing happened? well, this could be down to several factors:&lt;br /&gt;
&lt;br /&gt;
- No permissions (go back to the start)&lt;br /&gt;
- The report is of incorrect size (try again, remember you are sending bytes, so a report of 8 times 1 bit, equals a nibble (half byte), and the same goes for bits. The safest thing to do is to count the number of bits and then divide by 8, this is the number of bytes you ill need to send)&lt;br /&gt;
&lt;br /&gt;
If you are lucky you should go from this:&lt;br /&gt;
[[File:Saitek-radio-off.jpg|Saitek radio panel with all digits off|800x800px]]&lt;br /&gt;
To this:&lt;br /&gt;
[[File:Saitek-radio-on.jpg|Saitek radio panel with all digits on|800x800px]]&lt;br /&gt;
&lt;br /&gt;
Congratulations, you just sent the first pieces of data to your device. As you can see it shows the numbers in the order we sent in the report, or so it looks like.&lt;br /&gt;
&lt;br /&gt;
Now, it is a game of sending reports with different values and understanding what's your device's reaction, for example, if I sent just zeores:&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeros.jpg|800x800px]]&lt;br /&gt;
&lt;br /&gt;
Now the fun starts. &lt;br /&gt;
&lt;br /&gt;
So this is a radio panel right, aren't radio frequencies supposed to have a 'dot' somewhere, but hey, how do I tell the device I want to have a dot? Let's think, why do I have the possibility to send 20 bytes, with a maximum value of 255? Makes no sense right, watch byte represents a number in the panel that can go up to 9 (0 to 9), so anything else is overkill, unless...&lt;br /&gt;
&lt;br /&gt;
Let's try to send something over 9, for example the second byte in data_to send I put it as 0x0A (A is 10 in hex), what happened there?&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeros first-off.jpg|Saitek radio panel showing all zeros except first digit switched off|800x800px]]&lt;br /&gt;
&lt;br /&gt;
My first digit just switched off!! Interesting so now I can show numbers of less than 5 digits (XPDR, DME, hmm...) because I can switch any digit off as I please, let's try that again:&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-alternate-zeros.jpg|Saitek radio panel showing alternate zeroes and off|800x800px]]&lt;br /&gt;
&lt;br /&gt;
Nice!&lt;br /&gt;
&lt;br /&gt;
So we now know, 0 to 9 is the digit in question, 10 switches off the digit, but what about the 'dot' ???&lt;br /&gt;
&lt;br /&gt;
Let's send 11 (0x0B):&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeros first-off.jpg|Saitek radio panel showing all zeros except first digit switched off|800x800px]]&lt;br /&gt;
&lt;br /&gt;
Disappointment, nothing happens, let's keep trying other values.&lt;br /&gt;
&lt;br /&gt;
Hey what's this?&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-ones_and_dots.jpg|800x800px]]&lt;br /&gt;
&lt;br /&gt;
I was at 209, so what if I send all 208 (0xD0)&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeroes_and_dots.jpg|Saitek radio panel showing all zeroe and dots|800x800px]]&lt;br /&gt;
&lt;br /&gt;
Ok! so if I want to add a dot to any digit, I need to add 0xD0 the the value, so 0xD0 for 0, 0xD1 for one and so on)&lt;br /&gt;
&lt;br /&gt;
What If I continue?&lt;br /&gt;
&lt;br /&gt;
This is what happens with 224 (0xE0)&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-dashes.jpg|800x800px]]&lt;br /&gt;
&lt;br /&gt;
I get a 'dash'!&lt;br /&gt;
&lt;br /&gt;
And there's nothing else interesting in the tests, the numbers repeat a lot, but basically when now:&lt;br /&gt;
&lt;br /&gt;
0 to 9 -&amp;gt; the numbers in each digit&lt;br /&gt;
10 -&amp;gt; Switch off the digits&lt;br /&gt;
208-217 -&amp;gt; The numbers with a dot (to the right)&lt;br /&gt;
224 -&amp;gt; A dash&lt;br /&gt;
&lt;br /&gt;
Important point, we have not used any proprietary drivers or anything that could be linked to Saitek's proprietary development (AFAIK, I'm not a lawyer), we're just sending data to the device.&lt;br /&gt;
&lt;br /&gt;
Now that we know the logic, we're ready to go to the next step, make it work in FlightGear! [To be continued in next post]&lt;br /&gt;
&lt;br /&gt;
So now we have understood (more or less) how our device works, how we can send data to it, and what this data does.&lt;br /&gt;
&lt;br /&gt;
Let's fire up FlightGear.&lt;br /&gt;
&lt;br /&gt;
=== Making sure FlightGear detects the device ===&lt;br /&gt;
&lt;br /&gt;
The first thing we need to do is to launch FlightFear with debug on, to do this make sure you set the log level to debug via the ''--log-level=debug'' flag, do this either in the command line or if you use the launcher, in the additional settings.&lt;br /&gt;
&lt;br /&gt;
I would also recommend you to capture the output of the log:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
./dnc-managed/run_fgfs.sh --launcher 2&amp;gt;&amp;amp;1 | tee log.txt&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is my command, yours may be slightly different, the important part is the ''2&amp;gt;&amp;amp;1 | tee log.txt'' at the end of it.&lt;br /&gt;
&lt;br /&gt;
launch FG an let the  log start capturing all the information we need.&lt;br /&gt;
&lt;br /&gt;
Once the airplane's cockpit is showing up, you can shut down FlightGear, that'w all we need for now.&lt;br /&gt;
&lt;br /&gt;
Open the ''log.txt'' and start looking for the name of your device, you should see things like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;  225.20 [DBUG]:input      name=&amp;lt;null&amp;gt;, node=&amp;lt;null&amp;gt;&lt;br /&gt;
  225.20 [DBUG]:input      name=Logitech Logitech Flight Radio Panel, node=/dev/input/event23&lt;br /&gt;
&lt;br /&gt;
225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-0 modifiers=0 value=1&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-1 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-2 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-3 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-4 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-5 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-6 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-7 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-8 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-9 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-266 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-267 modifiers=0 value=1&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-268 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-269 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-270 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-271 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-left modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-right modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-middle modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-side modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-extra modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-forward modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-back modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-task modifiers=0 value=0&lt;br /&gt;
  225.26 [DBUG]:input      using InputDevice Logitech Logitech Flight Radio Panel_0&lt;br /&gt;
&lt;br /&gt;
225.28 [WARN]:input      Unhandled HID generic desktop usage:1&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown, bits: 0:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:2&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-1, bits: 8:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:3&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-2, bits: 16:8, report=0&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:joystick, bits: 24:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:5&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-3, bits: 32:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:6&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-4, bits: 40:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:7&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-5, bits: 48:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:8&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-6, bits: 56:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:9&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-7, bits: 64:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:10&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-8, bits: 72:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:11&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-9, bits: 80:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:12&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-10, bits: 88:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:13&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-11, bits: 96:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:14&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-12, bits: 104:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:15&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-13, bits: 112:8, report=0&lt;br /&gt;
  225.29 [WARN]:input      Unhandled HID generic desktop usage:16&lt;br /&gt;
  225.29 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-14, bits: 120:8, report=0&lt;br /&gt;
  225.29 [WARN]:input      Unhandled HID generic desktop usage:17&lt;br /&gt;
  225.29 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-15, bits: 128:8, report=0&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see from the log, there are already several interesting pieces of information:&lt;br /&gt;
&lt;br /&gt;
The device has ben recognized! ''25.20 [DBUG]:input      name=Logitech Logitech Flight Radio Panel, node=/dev/input/event23''&lt;br /&gt;
&lt;br /&gt;
It has detected the buttons ''225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-0 modifiers=0 value=1''&lt;br /&gt;
&lt;br /&gt;
And even the feature reports '' 225.28 [WARN]:input      Unhandled HID generic desktop usage:2&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-1, bits: 8:8, report=0''&lt;br /&gt;
&lt;br /&gt;
As you can see, we have everything under control, FG has detected the device and has detected the different buttons and feature reports. All of these are called 'events' by Flightgear.&lt;br /&gt;
&lt;br /&gt;
Important point, when we're going to be creating the properties files, we need to refer to the name you see in the logs, as strange as it sounds, you will get different buttons name not necessarily in a sequential order (things like thumb2, or button-333).&lt;br /&gt;
&lt;br /&gt;
=== The properties files ===&lt;br /&gt;
&lt;br /&gt;
The way that FlighGear communicates with the devices is via XML files located under the FlighGear directory ('~/.fgfs' for most linux installs) and then under Input, with 2 different options, either 'Joysticks' or 'Event':&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
drwxr-xr-x 2 pi pi 4096 Mar 27 16:12 Event&lt;br /&gt;
drwxr-xr-x 2 pi pi 4096 Apr  1 15:49 Joysticks&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
The joystick directory will hold, amongst others, the files that are created automatically by the joystick configurator within the simulator, the directory we're interested in is this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;~/.fgfs/Input/Event&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, there's no problem in having both a joystick file and an event file for the same device, I do have this for my Honeycomb alpha, where the axes are in the joystick file and the rest of the buttons in the event file (which allows me to go beyond the 32 button limitation, yes, you can use this HID way of doing things for devices over 32 buttons).&lt;br /&gt;
&lt;br /&gt;
So let's start writing. First of all, create an empty file called 'YOURDEVCIE.xml' (this is an example and the filename is not relevant as FG will read inside to understand to which device each file belongs (although I name it as the device with '-' just for clarity, for example for the saitek panel ''Logitech-Logitech-Flight-Radio-Panel.xml'' )&lt;br /&gt;
&lt;br /&gt;
Put the XML header:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;PropertyList&amp;gt;&lt;br /&gt;
  &amp;lt;name type=&amp;quot;string&amp;quot;&amp;gt;Logitech Logitech Flight Radio Panel&amp;lt;/name&amp;gt;&lt;br /&gt;
  &amp;lt;debug-events type=&amp;quot;bool&amp;quot;&amp;gt;true&amp;lt;/debug-events&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will indicate FG this is the file for your device, as the ''name'' tag defines it.&lt;br /&gt;
&lt;br /&gt;
If you plan to have some 'logic' in your properties file, add the nasal tags:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;PropertyList&amp;gt;&lt;br /&gt;
  &amp;lt;name type=&amp;quot;string&amp;quot;&amp;gt;Logitech Logitech Flight Radio Panel&amp;lt;/name&amp;gt;&lt;br /&gt;
  &amp;lt;debug-events type=&amp;quot;bool&amp;quot;&amp;gt;true&amp;lt;/debug-events&amp;gt;&lt;br /&gt;
  &amp;lt;nasal&amp;gt;&lt;br /&gt;
    &amp;lt;open&amp;gt;&lt;br /&gt;
      &amp;lt;![CDATA[]]&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Your basic file is starting to get some form. Now we need to start defining what do we do when each of the events is triggered:&lt;br /&gt;
I'm going to paste below the bindings (that's how it's called in FG) for the fact that you have switched the upper selector of the radio panel into 'comm1' mode:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;event&amp;gt;&lt;br /&gt;
    &amp;lt;desc&amp;gt;UK COMM1&amp;lt;/desc&amp;gt;&lt;br /&gt;
    &amp;lt;name&amp;gt;button-1&amp;lt;/name&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknoba&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/selected-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobb&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/standby-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobt&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;5&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
 &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobsw&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frq-swap-btn&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobmax&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;137&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobmin&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;118&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobfstep&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;1&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobhstep&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;0.025&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;script&amp;gt;refreshPanels();&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
  &amp;lt;/event&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Do not be scared by that size! I like to make things generic, so you will see a lot of reference and proxy properties being set that would allow to handle the logic of what happens when we're in 'comm1' mode in the upper panel.&lt;br /&gt;
&lt;br /&gt;
First of all we set the property ''saitek/RP/upknoba'' to ''/instrumentation/comm/frequencies/selected-mhz''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknoba&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/selected-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then set the standby frequency to the ''/saitek/RP/upknobb'' property&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobb&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/standby-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then the property ''/saitek/RP/upknobt'' to 5, which is the number of digits a frequency has&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobt&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;5&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then the 'swap' button to change frequencies&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobsw&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frq-swap-btn&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
The some max,min and incremental values, and last but not least, I call the refresh panel function (that I've created) to put the proper values in the panels:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;script&amp;gt;refreshPanels();&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
  &amp;lt;/event&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has to be done to every single button in the device, so they act the way you expect them to do. You can check the full file at the bottom of this post.&lt;br /&gt;
&lt;br /&gt;
Ok, so we have the buttons set up, now we want the display to show the proper values:&lt;br /&gt;
&lt;br /&gt;
We use the same tag, event, only that now we have to link a property to the event, so FG will send that value to the output/feature report in the proper position.&lt;br /&gt;
&lt;br /&gt;
Before we continue, remember that in the log, we saw things like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
225.28 [WARN]:input      Unhandled HID generic desktop usage:1&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown, bits: 0:8, report=0&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
And I did mention that the name that you saw there is the name that should be used for the event, in the case of unknown, you need to add the suffix ''-0'' for the first one, the rest will already have it ''-1, -2,-3 etc..''&lt;br /&gt;
&lt;br /&gt;
Let's add the event to the XML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;event&amp;gt;&lt;br /&gt;
    &amp;lt;desc&amp;gt;RADIO INDICATORS&amp;lt;/desc&amp;gt;&lt;br /&gt;
    &amp;lt;name&amp;gt;unknown-0&amp;lt;/name&amp;gt;&lt;br /&gt;
    &amp;lt;setting&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/ULpanel/digit1&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;/setting&amp;gt;&lt;br /&gt;
  &amp;lt;/event&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
You're telling FlightGear to watch for the property ''/saitek/RP/ULpanel/digit1'' and set its value to the vendor-0 byte.&lt;br /&gt;
&lt;br /&gt;
As you can see there's a strange property there: ''saitek/RP/ULpanel/digit1''. This property is of my choice and you can create any property you want to be sent to the device. Remember that in this particular case, we have a value for each digit, so we cannot send the actual value, we have to slice it so we send each digit in the correct position.&lt;br /&gt;
&lt;br /&gt;
And then again, do the same for the rest of the events.&lt;br /&gt;
&lt;br /&gt;
Once the events have been set and saved, you can launch FG to see if it worked!&lt;br /&gt;
&lt;br /&gt;
Yes! I see the same frequencies in the panel&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-working.jpg|800x800px]]&lt;br /&gt;
&lt;br /&gt;
as in the simulator&lt;br /&gt;
&lt;br /&gt;
[[File:FG-Radio_Panel_for_Saitek.jpg|800x800px]]&lt;br /&gt;
&lt;br /&gt;
Of course, every time you modify the frequencies in any of the sim or panel, the other one reflects the same value as expected.&lt;br /&gt;
&lt;br /&gt;
You can have a look at [[https://github.com/zayamatias/flightgear/blob/main/.fgfs/Input/Event/Logitech-Logitech-Flight-Radio-Panel.xml]the complete xml file, where you can see I use nasal heavily to do some extra logic, for example, do not turn on the panel unless the contact is set on the aeroplane, how I use the swap button to select the digit when in XPDR mode, and so on. There is no limits to what you can do once you understand the properties and what you're able to do with them.&lt;br /&gt;
&lt;br /&gt;
I hope I have not forgotten anything essential and I also hope this has helped. I'm really looking forward to other devices becoming available in FG.&lt;br /&gt;
&lt;br /&gt;
This also opens the possibility of creating your own devices, have a look at my [https://github.com/zayamatias/flightgear]repo.&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User:Zayamatias/Adding_HID_devices_to_FlightGear&amp;diff=139765</id>
		<title>User:Zayamatias/Adding HID devices to FlightGear</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User:Zayamatias/Adding_HID_devices_to_FlightGear&amp;diff=139765"/>
		<updated>2024-04-22T16:03:10Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: /* 4-Understanding how data is received and processed by your device: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Adding HID devices to FlightGear''' hopes to explain how to set-up any HID device to work with FlightGear in a step-by-step easy to follow guide, it is my belief that any HID can and will work with FlightGear&lt;br /&gt;
&lt;br /&gt;
First disclaimer: The HID subsystem seems to be working only under Linux and MacOS, I am not sure if one day it will work in Windows. &lt;br /&gt;
Second Disclaimer: This guide was done under an Ubuntu distribution, this means that other distros may vary slightly. &lt;br /&gt;
Last but not least: I take no responsibility in the unlikely event of you breaking your HID device by using this guide&lt;br /&gt;
&lt;br /&gt;
=== Getting started ===&lt;br /&gt;
&lt;br /&gt;
Before starting, there are a couple of tools you need to install:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/hidviz/hidviz] HIDVIZ&lt;br /&gt;
&lt;br /&gt;
This tool will allow you to have a look at the inner workings of your HID device, I'll talk about it later.&lt;br /&gt;
&lt;br /&gt;
[https://code.visualstudio.com/]VS Code&lt;br /&gt;
&lt;br /&gt;
I use this for creating the XMLfiles and the Nasal code, as it has very nice extensions for this, but this is not mandatory and you can use anything you are used to.&lt;br /&gt;
&lt;br /&gt;
Python&lt;br /&gt;
&lt;br /&gt;
I've created some quick and dirty tools under python to test the device, so make sure Python (3.9 at least) is installed in your system if you want to use them.&lt;br /&gt;
&lt;br /&gt;
=== The Device ===&lt;br /&gt;
&lt;br /&gt;
For this guide, I'll be using the [https://www.logitechg.com/en-gb/products/flight/flight-simulator-cockpit-radio-panel.945-000011.html]Saitek/Logitech radio panel as an example that would hopefully help you with any other device.&lt;br /&gt;
&lt;br /&gt;
So let the fun begin!&lt;br /&gt;
&lt;br /&gt;
=== Understanding what's the name of the device ===&lt;br /&gt;
&lt;br /&gt;
Start your PC and go to the terminal, do not connect any device yet, and let's see what has been detected in the USB connections:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
lsusb&lt;br /&gt;
Bus 002 Device 003: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 002: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub&lt;br /&gt;
Bus 001 Device 012: ID 138a:00ab Validity Sensors, Inc. &lt;br /&gt;
Bus 001 Device 011: ID 093a:2510 Pixart Imaging, Inc. Optical Mouse&lt;br /&gt;
Bus 001 Device 008: ID 258a:0001 SINO WEALTH USB KEYBOARD&lt;br /&gt;
Bus 001 Device 005: ID 214b:7250 Huasheng Electronics USB2.0 HUB&lt;br /&gt;
Bus 001 Device 003: ID 04f2:b669 Chicony Electronics Co., Ltd HP HD Camera&lt;br /&gt;
Bus 001 Device 013: ID 8087:0aaa Intel Corp. Bluetooth 9460/9560 Jefferson Peak (JfP)&lt;br /&gt;
Bus 001 Device 004: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 002: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By issuing the 'lsusb' command you can see what the PC has detected as connected devices, no sign yet of my radio panel, so let's connect it now and issue the same command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
lsusb&lt;br /&gt;
Bus 002 Device 003: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 002: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub&lt;br /&gt;
Bus 001 Device 012: ID 138a:00ab Validity Sensors, Inc. &lt;br /&gt;
Bus 001 Device 011: ID 093a:2510 Pixart Imaging, Inc. Optical Mouse&lt;br /&gt;
Bus 001 Device 008: ID 258a:0001 SINO WEALTH USB KEYBOARD&lt;br /&gt;
Bus 001 Device 005: ID 214b:7250 Huasheng Electronics USB2.0 HUB&lt;br /&gt;
Bus 001 Device 003: ID 04f2:b669 Chicony Electronics Co., Ltd HP HD Camera&lt;br /&gt;
Bus 001 Device 013: ID 8087:0aaa Intel Corp. Bluetooth 9460/9560 Jefferson Peak (JfP)&lt;br /&gt;
Bus 001 Device 014: ID 06a3:0d05 Saitek PLC Pro Flight Radio Panel&lt;br /&gt;
Bus 001 Device 004: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 002: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Interestingly, I now see the ''Bus 001 Device 014: ID 06a3:0d05 Saitek PLC Pro Flight Radio Panel'' being shown in my connected devices.&lt;br /&gt;
&lt;br /&gt;
If your device does not show up, make sure that it is properly connected, and powered if needed, and as a last resort try to see if it is connectable to any other PC. If still it does not show, then either probably it is not an HID device, or it is not working at all.&lt;br /&gt;
&lt;br /&gt;
So now, save the name ''Saitek PLC Pro Flight Radio Panel'', we will need it afterwards.&lt;br /&gt;
&lt;br /&gt;
=== Making sure your Linux user has full access to the device ===&lt;br /&gt;
&lt;br /&gt;
One of the issues with Linux and HID devices is user permissions, Linux is quite secure and usually will let a specific subset of users use the HID device, so let's make sure your user has access to this particular one.&lt;br /&gt;
&lt;br /&gt;
Let's go back to the 'lsusb' output from earlier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
Bus 001 Device 014: ID 06a3:0d05 Saitek PLC Pro Flight Radio Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
See that there are 2 hexadecimal numbers in there: '''06a3:0d05 '''? The part before the colon is the vendor id (or VID for shorts) and the second one is the product ID (or PID) for shorts. The first one will change depending on the manufacturer of the device, you can check [https://the-sz.com/products/usbid/index.php?v=0x06A3&amp;amp;p=0d05&amp;amp;n=]here if you're curious. &lt;br /&gt;
&lt;br /&gt;
Now, keep those numbers somewhere safe, we will need them.&lt;br /&gt;
&lt;br /&gt;
One of the first parameters to have access to a HID device is to make sure that the user belongs to a group we can refer to, for example in Ubuntu, if your user has to have access to joysticks (as any kind of gaming device) then it has to be added to the 'js' group, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
usermod -a -G examplegroup exampleusername&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where ''examplegroup'' is ''js'' in our case and ''exampleusername'' is your Linux user. You will need to run this as root, so add the 'sudo' prefix before the command&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
sudo usermod -a -G examplegroup exampleusername&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remember this 'sudo' for later on.&lt;br /&gt;
&lt;br /&gt;
Ok, so now let's make sure your user belongs to the js group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
groups&lt;br /&gt;
pi adm dialout cdrom sudo dip plugdev lpadmin lxd sambashare usb wireshark js&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
I can see my user's last group is js, well done, one thing less.&lt;br /&gt;
&lt;br /&gt;
Now we have to make sure that your device is recognized as a joystick, for this, you need to create a new udev rule. Do not worry about what this means exactly (although you can read about it at [https://opensource.com/article/18/11/udev]Opensource.com)&lt;br /&gt;
&lt;br /&gt;
We need to tell your Linux install that the Saitek device is a joystick (fun fact, my Linux install though the panel was a mouse, and moving the dials would move the actual mouse...) :&lt;br /&gt;
&lt;br /&gt;
There are several ways you can do this but this one works for me:&lt;br /&gt;
&lt;br /&gt;
Open the (or create a new) rule file under ''/etc/udev/rules.d/'', I have called it ''00-local.rules''&lt;br /&gt;
&lt;br /&gt;
so, let's go for it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
nano /etc/udev/rules.d/00-local.rules&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will open an editor (nano), feel free to use any editor, just remember that you have to be root to be able to save the file. &lt;br /&gt;
&lt;br /&gt;
Add the following line to your file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
SUBSYSTEM==&amp;quot;input&amp;quot;, ATTRS{idVendor}==&amp;quot;06a3&amp;quot;, ATTRS{idProduct}==&amp;quot;0d05&amp;quot;, ENV{ID_INPUT_JOYSTICK}=&amp;quot;1&amp;quot;,ENV{ID_INPUT_MOUSE}=&amp;quot;0&amp;quot;, TAG+=&amp;quot;uaccess&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
We now are saying to Linux that the device with VID 06a3 and PID 0d05 is a joystick and not a mouse (do those numbers ring a bell?)&lt;br /&gt;
&lt;br /&gt;
Just for completion's sake, there's another possibility to do this, alas less 'secure' by Linux standards. You can create a new file:&lt;br /&gt;
''/etc/udev/rules.d/99-hid.rules'' and in it add the following lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
SUBSYSTEM==&amp;quot;usb&amp;quot;, ATTRS{idVendor}==&amp;quot;06a3&amp;quot;, ATTRS{idProduct}==&amp;quot;0d05&amp;quot;, MODE=&amp;quot;0666&amp;quot;&lt;br /&gt;
KERNEL==&amp;quot;hidraw*&amp;quot;, ATTRS{busnum}==&amp;quot;1&amp;quot;, ATTRS{idVendor}==&amp;quot;06a3&amp;quot;, ATTRS{idProduct}==&amp;quot;0d05&amp;quot;, MODE=&amp;quot;0666&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will give anyone access to the device in question (and hence less secure in Linux terms).&lt;br /&gt;
&lt;br /&gt;
So now we have setup the device so it is a joystick and your user can access it. Let's go and play with it:&lt;br /&gt;
&lt;br /&gt;
=== Understanding your device's Inputs and outputs ===&lt;br /&gt;
&lt;br /&gt;
Make sure your device is connected and powered if needed, Once you're sure, launch hidviz:&lt;br /&gt;
&lt;br /&gt;
(I have compiled the version from the link I've put in the tools section, I won't be explaining how to buildit since it is already explained in the github page)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
./hidviz&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will present you with the following screen:&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-selector.png|Screenshot of hidviz tool main screen]]&lt;br /&gt;
&lt;br /&gt;
Click on 'Select Device', this will ask you for your password to gain root access if you have not run the command as 'sudo'&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-selector-2.png|Device selector from hidviz]]&lt;br /&gt;
&lt;br /&gt;
You should see the saitek pro panel there, select it:&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-descriptor-saitek-radio-panelpng.png|Hiviz showing the HiD descritpor for the saitek radio panel]]&lt;br /&gt;
&lt;br /&gt;
As you can see, there are 24 buttons (bits) (top section Collection/Input) and there seem to be 2 features. One containing 20 (report count) 8-bit values (report size) with a maximum logic value of 255 and then another report of 14 times 1-bit values (fun fact, when I started with the HID devices I didn't use hidviz, so I'm intrigued by this second feature report which I was not aware of!).&lt;br /&gt;
&lt;br /&gt;
For completion, HID devices (as far as I am aware) have 3 types of reports, input (which is data sent from device to PC) output (which is data sent from PC to device) and feature, which seems to be also in the PC to device category.  As you can see, here you have 1 input (buttons) 2 features (we'll talk about these later) and a padding of 2 bits, this is there because usually reports need to be of a specific size (multiplier of 24 if I remember correctly), if you do your maths: 24bits + 20*8 (160 bits) + 14 bits = 198 + 2 padding bits  = 200 bits in total, ok it does not add up, go figure, but this is not the only weird thing about this descriptor, look at the actual features described: water cooling device! either Saitek devs had a great sense of humor or they didn't spend much time figuring out how to do proper HID reports. In any case, I was expecting also to have an output report instead of a feature report and each report with its unique ID. Saitek: some improvements are needed here! All of this to say: '''HID is a big grey area amongst manufacturers, so your levels of patience to make the device work may vary'''&lt;br /&gt;
&lt;br /&gt;
If the descriptor would have been set up properly, you should have seen something like this for the output reports: (This is for one of my custom devices):&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-descriptor-fgmod.png|Hidvizz showing the fgmod descriptor]]&lt;br /&gt;
&lt;br /&gt;
This would have allowed you to easily enter values in the output report and understand how the device treated data, alas, it is not the case for the saitek device, so let's go Python!&lt;br /&gt;
&lt;br /&gt;
=== Understanding how data is received and processed by your device: ===&lt;br /&gt;
&lt;br /&gt;
So we now know a little bit more about the device, it has 24 buttons, and it has 20 possible inputs (spoiler: the Saitek panel has 4*5 segment displays, could it be?? Hmmmm...)&lt;br /&gt;
&lt;br /&gt;
Let's try python&lt;br /&gt;
&lt;br /&gt;
First, you need to check which hidraw linux device corresponds to your actual device, Linux will map your device under ''/dev/hidrawx'' and to find it, create  script (call it findhid.sh):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
FILES=/dev/hidraw*&lt;br /&gt;
for f in $FILES&lt;br /&gt;
do&lt;br /&gt;
  FILE=${f##*/}&lt;br /&gt;
  DEVICE=&amp;quot;$(cat /sys/class/hidraw/${FILE}/device/uevent | grep HID_NAME | cut -d '=' -f2)&amp;quot;&lt;br /&gt;
  printf &amp;quot;%s \t %s\n&amp;quot; $FILE &amp;quot;$DEVICE&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
chmod 775 findhid.sh&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
And finally execute it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
./findhid.sh&lt;br /&gt;
hidraw0 	 SYNA3083:00 06CB:8265&lt;br /&gt;
hidraw1 	 ELAN2514:00 04F3:288A&lt;br /&gt;
hidraw2 	 SINO WEALTH USB KEYBOARD&lt;br /&gt;
hidraw3 	 SINO WEALTH USB KEYBOARD&lt;br /&gt;
hidraw4 	 PixA琀 USB Optical Mouse&lt;br /&gt;
hidraw7 	 Logitech Logitech Flight Radio Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
so, this means that our Saitek panel is linked to /dev/hidraw7, nice!&lt;br /&gt;
&lt;br /&gt;
Now, open an editor and create hidtest.py:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def send_data_to_hidraw(data, hidraw_path):&lt;br /&gt;
    try:&lt;br /&gt;
        # Open the HIDRAW device&lt;br /&gt;
        hidraw = os.open(hidraw_path, os.O_RDWR | os.O_NONBLOCK)&lt;br /&gt;
        &lt;br /&gt;
        # Write data to the HIDRAW device&lt;br /&gt;
        os.write(hidraw, bytes(data))&lt;br /&gt;
        &lt;br /&gt;
        print(&amp;quot;Data sent successfully to HIDRAW device.&amp;quot;)&lt;br /&gt;
        &lt;br /&gt;
        # Close the HIDRAW device&lt;br /&gt;
        os.close(hidraw)&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(&amp;quot;Error:&amp;quot;, e)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    # Define your data to send&lt;br /&gt;
    data_to_send = [0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03]  # Example data&lt;br /&gt;
    &lt;br /&gt;
    # Specify the path to your HIDRAW device&lt;br /&gt;
    hidraw_path = &amp;quot;/dev/hidraw7&amp;quot;  # Replace with the actual path to your HIDRAW device&lt;br /&gt;
    &lt;br /&gt;
    # Send the data to the HIDRAW device&lt;br /&gt;
    send_data_to_hidraw(data_to_send, hidraw_path)&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Two important things: change hidraw_path to your devices' correct link and make sure that the data_to_send variable is of the same length as the report we found in hidvix, in this case, we have 20 times one byte, noted in hex format in Python (0xXX).&lt;br /&gt;
&lt;br /&gt;
Small clarification, as you can see I'm sending 21 bytes, the reason behind this is that the first byte indicates the report_id you're sending to, in the case of the saitek panel, there's no real report id, so whatever you put in the first byte will still work. Make sure you consider this when testing your device.&lt;br /&gt;
&lt;br /&gt;
Now run the python script&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
python3 hidtest.py&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nothing happened? well, this could be down to several factors:&lt;br /&gt;
&lt;br /&gt;
- No permissions (go back to the start)&lt;br /&gt;
- The report is of incorrect size (try again, remember you are sending bytes, so a report of 8 times 1 bit, equals a nibble (half byte), and the same goes for bits. The safest thing to do is to count the number of bits and then divide by 8, this is the number of bytes you ill need to send)&lt;br /&gt;
&lt;br /&gt;
If you are lucky you should go from this:&lt;br /&gt;
[[File:Saitek-radio-off.jpg|Saitek radio panel with all digits off]]&lt;br /&gt;
To this:&lt;br /&gt;
[[File:Saitek-radio-on.jpg|Saitek radio panel with all digits on]]&lt;br /&gt;
&lt;br /&gt;
Congratulations, you just sent the first pieces of data to your device. As you can see it shows the numbers in the order we sent in the report, or so it looks like.&lt;br /&gt;
&lt;br /&gt;
Now, it is a game of sending reports with different values and understanding what's your device's reaction, for example, if I sent just zeores:&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeros.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now the fun starts. &lt;br /&gt;
&lt;br /&gt;
So this is a radio panel right, aren't radio frequencies supposed to have a 'dot' somewhere, but hey, how do I tell the device I want to have a dot? Let's think, why do I have the possibility to send 20 bytes, with a maximum value of 255? Makes no sense right, watch byte represents a number in the panel that can go up to 9 (0 to 9), so anything else is overkill, unless...&lt;br /&gt;
&lt;br /&gt;
Let's try to send something over 9, for example the second byte in data_to send I put it as 0x0A (A is 10 in hex), what happened there?&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeros first-off.jpg|Saitek radio panel showing all zeros except first digit switched off]]&lt;br /&gt;
&lt;br /&gt;
My first digit just switched off!! Interesting so now I can show numbers of less than 5 digits (XPDR, DME, hmm...) because I can switch any digit off as I please, let's try that again:&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-alternate-zeros.jpg|Saitek radio panel showing alternate zeroes and off]]&lt;br /&gt;
&lt;br /&gt;
Nice!&lt;br /&gt;
&lt;br /&gt;
So we now know, 0 to 9 is the digit in question, 10 switches off the digit, but what about the 'dot' ???&lt;br /&gt;
&lt;br /&gt;
Let's send 11 (0x0B):&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeros first-off.jpg|Saitek radio panel showing all zeros except first digit switched off]]&lt;br /&gt;
&lt;br /&gt;
Disappointment, nothing happens, let's keep trying other values.&lt;br /&gt;
&lt;br /&gt;
Hey what's this?&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-ones_and_dots.jpg]]&lt;br /&gt;
&lt;br /&gt;
I was at 209, so what if I send all 208 (0xD0)&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeroes_and_dots.jpg|Saitek radio panel showing all zeroe and dots]]&lt;br /&gt;
&lt;br /&gt;
Ok! so if I want to add a dot to any digit, I need to add 0xD0 the the value, so 0xD0 for 0, 0xD1 for one and so on)&lt;br /&gt;
&lt;br /&gt;
What If I continue?&lt;br /&gt;
&lt;br /&gt;
This is what happens with 224 (0xE0)&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-dashes.jpg]]&lt;br /&gt;
&lt;br /&gt;
I get a 'dash'!&lt;br /&gt;
&lt;br /&gt;
And there's nothing else interesting in the tests, the numbers repeat a lot, but basically when now:&lt;br /&gt;
&lt;br /&gt;
0 to 9 -&amp;gt; the numbers in each digit&lt;br /&gt;
10 -&amp;gt; Switch off the digits&lt;br /&gt;
208-217 -&amp;gt; The numbers with a dot (to the right)&lt;br /&gt;
224 -&amp;gt; A dash&lt;br /&gt;
&lt;br /&gt;
Important point, we have not used any proprietary drivers or anything that could be linked to Saitek's proprietary development (AFAIK, I'm not a lawyer), we're just sending data to the device.&lt;br /&gt;
&lt;br /&gt;
Now that we know the logic, we're ready to go to the next step, make it work in FlightGear! [To be continued in next post]&lt;br /&gt;
&lt;br /&gt;
So now we have understood (more or less) how our device works, how we can send data to it, and what this data does.&lt;br /&gt;
&lt;br /&gt;
Let's fire up FlightGear.&lt;br /&gt;
&lt;br /&gt;
=== Making sure FlightGear detects the device ===&lt;br /&gt;
&lt;br /&gt;
The first thing we need to do is to launch FlightFear with debug on, to do this make sure you set the log level to debug via the ''--log-level=debug'' flag, do this either in the command line or if you use the launcher, in the additional settings.&lt;br /&gt;
&lt;br /&gt;
I would also recommend you to capture the output of the log:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
./dnc-managed/run_fgfs.sh --launcher 2&amp;gt;&amp;amp;1 | tee log.txt&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is my command, yours may be slightly different, the important part is the ''2&amp;gt;&amp;amp;1 | tee log.txt'' at the end of it.&lt;br /&gt;
&lt;br /&gt;
launch FG an let the  log start capturing all the information we need.&lt;br /&gt;
&lt;br /&gt;
Once the airplane's cockpit is showing up, you can shut down FlightGear, that'w all we need for now.&lt;br /&gt;
&lt;br /&gt;
Open the ''log.txt'' and start looking for the name of your device, you should see things like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;  225.20 [DBUG]:input      name=&amp;lt;null&amp;gt;, node=&amp;lt;null&amp;gt;&lt;br /&gt;
  225.20 [DBUG]:input      name=Logitech Logitech Flight Radio Panel, node=/dev/input/event23&lt;br /&gt;
&lt;br /&gt;
225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-0 modifiers=0 value=1&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-1 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-2 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-3 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-4 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-5 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-6 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-7 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-8 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-9 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-266 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-267 modifiers=0 value=1&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-268 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-269 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-270 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-271 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-left modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-right modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-middle modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-side modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-extra modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-forward modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-back modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-task modifiers=0 value=0&lt;br /&gt;
  225.26 [DBUG]:input      using InputDevice Logitech Logitech Flight Radio Panel_0&lt;br /&gt;
&lt;br /&gt;
225.28 [WARN]:input      Unhandled HID generic desktop usage:1&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown, bits: 0:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:2&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-1, bits: 8:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:3&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-2, bits: 16:8, report=0&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:joystick, bits: 24:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:5&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-3, bits: 32:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:6&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-4, bits: 40:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:7&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-5, bits: 48:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:8&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-6, bits: 56:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:9&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-7, bits: 64:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:10&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-8, bits: 72:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:11&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-9, bits: 80:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:12&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-10, bits: 88:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:13&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-11, bits: 96:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:14&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-12, bits: 104:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:15&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-13, bits: 112:8, report=0&lt;br /&gt;
  225.29 [WARN]:input      Unhandled HID generic desktop usage:16&lt;br /&gt;
  225.29 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-14, bits: 120:8, report=0&lt;br /&gt;
  225.29 [WARN]:input      Unhandled HID generic desktop usage:17&lt;br /&gt;
  225.29 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-15, bits: 128:8, report=0&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see from the log, there are already several interesting pieces of information:&lt;br /&gt;
&lt;br /&gt;
The device has ben recognized! ''25.20 [DBUG]:input      name=Logitech Logitech Flight Radio Panel, node=/dev/input/event23''&lt;br /&gt;
&lt;br /&gt;
It has detected the buttons ''225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-0 modifiers=0 value=1''&lt;br /&gt;
&lt;br /&gt;
And even the feature reports '' 225.28 [WARN]:input      Unhandled HID generic desktop usage:2&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-1, bits: 8:8, report=0''&lt;br /&gt;
&lt;br /&gt;
As you can see, we have everything under control, FG has detected the device and has detected the different buttons and feature reports. All of these are called 'events' by Flightgear.&lt;br /&gt;
&lt;br /&gt;
Important point, when we're going to be creating the properties files, we need to refer to the name you see in the logs, as strange as it sounds, you will get different buttons name not necessarily in a sequential order (things like thumb2, or button-333).&lt;br /&gt;
&lt;br /&gt;
=== The properties files ===&lt;br /&gt;
&lt;br /&gt;
The way that FlighGear communicates with the devices is via XML files located under the FlighGear directory ('~/.fgfs' for most linux installs) and then under Input, with 2 different options, either 'Joysticks' or 'Event':&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
drwxr-xr-x 2 pi pi 4096 Mar 27 16:12 Event&lt;br /&gt;
drwxr-xr-x 2 pi pi 4096 Apr  1 15:49 Joysticks&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
The joystick directory will hold, amongst others, the files that are created automatically by the joystick configurator within the simulator, the directory we're interested in is this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;~/.fgfs/Input/Event&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, there's no problem in having both a joystick file and an event file for the same device, I do have this for my Honeycomb alpha, where the axes are in the joystick file and the rest of the buttons in the event file (which allows me to go beyond the 32 button limitation, yes, you can use this HID way of doing things for devices over 32 buttons).&lt;br /&gt;
&lt;br /&gt;
So let's start writing. First of all, create an empty file called 'YOURDEVCIE.xml' (this is an example and the filename is not relevant as FG will read inside to understand to which device each file belongs (although I name it as the device with '-' just for clarity, for example for the saitek panel ''Logitech-Logitech-Flight-Radio-Panel.xml'' )&lt;br /&gt;
&lt;br /&gt;
Put the XML header:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;PropertyList&amp;gt;&lt;br /&gt;
  &amp;lt;name type=&amp;quot;string&amp;quot;&amp;gt;Logitech Logitech Flight Radio Panel&amp;lt;/name&amp;gt;&lt;br /&gt;
  &amp;lt;debug-events type=&amp;quot;bool&amp;quot;&amp;gt;true&amp;lt;/debug-events&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will indicate FG this is the file for your device, as the ''name'' tag defines it.&lt;br /&gt;
&lt;br /&gt;
If you plan to have some 'logic' in your properties file, add the nasal tags:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;PropertyList&amp;gt;&lt;br /&gt;
  &amp;lt;name type=&amp;quot;string&amp;quot;&amp;gt;Logitech Logitech Flight Radio Panel&amp;lt;/name&amp;gt;&lt;br /&gt;
  &amp;lt;debug-events type=&amp;quot;bool&amp;quot;&amp;gt;true&amp;lt;/debug-events&amp;gt;&lt;br /&gt;
  &amp;lt;nasal&amp;gt;&lt;br /&gt;
    &amp;lt;open&amp;gt;&lt;br /&gt;
      &amp;lt;![CDATA[]]&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Your basic file is starting to get some form. Now we need to start defining what do we do when each of the events is triggered:&lt;br /&gt;
I'm going to paste below the bindings (that's how it's called in FG) for the fact that you have switched the upper selector of the radio panel into 'comm1' mode:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;event&amp;gt;&lt;br /&gt;
    &amp;lt;desc&amp;gt;UK COMM1&amp;lt;/desc&amp;gt;&lt;br /&gt;
    &amp;lt;name&amp;gt;button-1&amp;lt;/name&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknoba&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/selected-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobb&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/standby-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobt&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;5&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
 &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobsw&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frq-swap-btn&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobmax&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;137&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobmin&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;118&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobfstep&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;1&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobhstep&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;0.025&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;script&amp;gt;refreshPanels();&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
  &amp;lt;/event&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Do not be scared by that size! I like to make things generic, so you will see a lot of reference and proxy properties being set that would allow to handle the logic of what happens when we're in 'comm1' mode in the upper panel.&lt;br /&gt;
&lt;br /&gt;
First of all we set the property ''saitek/RP/upknoba'' to ''/instrumentation/comm/frequencies/selected-mhz''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknoba&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/selected-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then set the standby frequency to the ''/saitek/RP/upknobb'' property&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobb&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/standby-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then the property ''/saitek/RP/upknobt'' to 5, which is the number of digits a frequency has&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobt&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;5&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then the 'swap' button to change frequencies&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobsw&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frq-swap-btn&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
The some max,min and incremental values, and last but not least, I call the refresh panel function (that I've created) to put the proper values in the panels:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;script&amp;gt;refreshPanels();&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
  &amp;lt;/event&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has to be done to every single button in the device, so they act the way you expect them to do. You can check the full file at the bottom of this post.&lt;br /&gt;
&lt;br /&gt;
Ok, so we have the buttons set up, now we want the display to show the proper values:&lt;br /&gt;
&lt;br /&gt;
We use the same tag, event, only that now we have to link a property to the event, so FG will send that value to the output/feature report in the proper position.&lt;br /&gt;
&lt;br /&gt;
Before we continue, remember that in the log, we saw things like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
225.28 [WARN]:input      Unhandled HID generic desktop usage:1&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown, bits: 0:8, report=0&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
And I did mention that the name that you saw there is the name that should be used for the event, in the case of unknown, you need to add the suffix ''-0'' for the first one, the rest will already have it ''-1, -2,-3 etc..''&lt;br /&gt;
&lt;br /&gt;
Let's add the event to the XML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;event&amp;gt;&lt;br /&gt;
    &amp;lt;desc&amp;gt;RADIO INDICATORS&amp;lt;/desc&amp;gt;&lt;br /&gt;
    &amp;lt;name&amp;gt;unknown-0&amp;lt;/name&amp;gt;&lt;br /&gt;
    &amp;lt;setting&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/ULpanel/digit1&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;/setting&amp;gt;&lt;br /&gt;
  &amp;lt;/event&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
You're telling FlightGear to watch for the property ''/saitek/RP/ULpanel/digit1'' and set its value to the vendor-0 byte.&lt;br /&gt;
&lt;br /&gt;
As you can see there's a strange property there: ''saitek/RP/ULpanel/digit1''. This property is of my choice and you can create any property you want to be sent to the device. Remember that in this particular case, we have a value for each digit, so we cannot send the actual value, we have to slice it so we send each digit in the correct position.&lt;br /&gt;
&lt;br /&gt;
And then again, do the same for the rest of the events.&lt;br /&gt;
&lt;br /&gt;
Once the events have been set and saved, you can launch FG to see if it worked!&lt;br /&gt;
&lt;br /&gt;
Yes! I see the same frequencies in the panel&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-working.jpg]]&lt;br /&gt;
&lt;br /&gt;
as in the simulator&lt;br /&gt;
&lt;br /&gt;
[[File:FG-Radio_Panel_for_Saitek.jpg]]&lt;br /&gt;
&lt;br /&gt;
Of course, every time you modify the frequencies in any of the sim or panel, the other one reflects the same value as expected.&lt;br /&gt;
&lt;br /&gt;
You can have a look at [[https://github.com/zayamatias/flightgear/blob/main/.fgfs/Input/Event/Logitech-Logitech-Flight-Radio-Panel.xml]the complete xml file, where you can see I use nasal heavily to do some extra logic, for example, do not turn on the panel unless the contact is set on the aeroplane, how I use the swap button to select the digit when in XPDR mode, and so on. There is no limits to what you can do once you understand the properties and what you're able to do with them.&lt;br /&gt;
&lt;br /&gt;
I hope I have not forgotten anything essential and I also hope this has helped. I'm really looking forward to other devices becoming available in FG.&lt;br /&gt;
&lt;br /&gt;
This also opens the possibility of creating your own devices, have a look at my [https://github.com/zayamatias/flightgear]repo.&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User:Zayamatias/Adding_HID_devices_to_FlightGear&amp;diff=139764</id>
		<title>User:Zayamatias/Adding HID devices to FlightGear</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User:Zayamatias/Adding_HID_devices_to_FlightGear&amp;diff=139764"/>
		<updated>2024-04-22T16:00:37Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Adding HID devices to FlightGear''' hopes to explain how to set-up any HID device to work with FlightGear in a step-by-step easy to follow guide, it is my belief that any HID can and will work with FlightGear&lt;br /&gt;
&lt;br /&gt;
First disclaimer: The HID subsystem seems to be working only under Linux and MacOS, I am not sure if one day it will work in Windows. &lt;br /&gt;
Second Disclaimer: This guide was done under an Ubuntu distribution, this means that other distros may vary slightly. &lt;br /&gt;
Last but not least: I take no responsibility in the unlikely event of you breaking your HID device by using this guide&lt;br /&gt;
&lt;br /&gt;
=== Getting started ===&lt;br /&gt;
&lt;br /&gt;
Before starting, there are a couple of tools you need to install:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/hidviz/hidviz] HIDVIZ&lt;br /&gt;
&lt;br /&gt;
This tool will allow you to have a look at the inner workings of your HID device, I'll talk about it later.&lt;br /&gt;
&lt;br /&gt;
[https://code.visualstudio.com/]VS Code&lt;br /&gt;
&lt;br /&gt;
I use this for creating the XMLfiles and the Nasal code, as it has very nice extensions for this, but this is not mandatory and you can use anything you are used to.&lt;br /&gt;
&lt;br /&gt;
Python&lt;br /&gt;
&lt;br /&gt;
I've created some quick and dirty tools under python to test the device, so make sure Python (3.9 at least) is installed in your system if you want to use them.&lt;br /&gt;
&lt;br /&gt;
=== The Device ===&lt;br /&gt;
&lt;br /&gt;
For this guide, I'll be using the [https://www.logitechg.com/en-gb/products/flight/flight-simulator-cockpit-radio-panel.945-000011.html]Saitek/Logitech radio panel as an example that would hopefully help you with any other device.&lt;br /&gt;
&lt;br /&gt;
So let the fun begin!&lt;br /&gt;
&lt;br /&gt;
=== Understanding what's the name of the device ===&lt;br /&gt;
&lt;br /&gt;
Start your PC and go to the terminal, do not connect any device yet, and let's see what has been detected in the USB connections:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
lsusb&lt;br /&gt;
Bus 002 Device 003: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 002: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub&lt;br /&gt;
Bus 001 Device 012: ID 138a:00ab Validity Sensors, Inc. &lt;br /&gt;
Bus 001 Device 011: ID 093a:2510 Pixart Imaging, Inc. Optical Mouse&lt;br /&gt;
Bus 001 Device 008: ID 258a:0001 SINO WEALTH USB KEYBOARD&lt;br /&gt;
Bus 001 Device 005: ID 214b:7250 Huasheng Electronics USB2.0 HUB&lt;br /&gt;
Bus 001 Device 003: ID 04f2:b669 Chicony Electronics Co., Ltd HP HD Camera&lt;br /&gt;
Bus 001 Device 013: ID 8087:0aaa Intel Corp. Bluetooth 9460/9560 Jefferson Peak (JfP)&lt;br /&gt;
Bus 001 Device 004: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 002: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By issuing the 'lsusb' command you can see what the PC has detected as connected devices, no sign yet of my radio panel, so let's connect it now and issue the same command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
lsusb&lt;br /&gt;
Bus 002 Device 003: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 002: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub&lt;br /&gt;
Bus 001 Device 012: ID 138a:00ab Validity Sensors, Inc. &lt;br /&gt;
Bus 001 Device 011: ID 093a:2510 Pixart Imaging, Inc. Optical Mouse&lt;br /&gt;
Bus 001 Device 008: ID 258a:0001 SINO WEALTH USB KEYBOARD&lt;br /&gt;
Bus 001 Device 005: ID 214b:7250 Huasheng Electronics USB2.0 HUB&lt;br /&gt;
Bus 001 Device 003: ID 04f2:b669 Chicony Electronics Co., Ltd HP HD Camera&lt;br /&gt;
Bus 001 Device 013: ID 8087:0aaa Intel Corp. Bluetooth 9460/9560 Jefferson Peak (JfP)&lt;br /&gt;
Bus 001 Device 014: ID 06a3:0d05 Saitek PLC Pro Flight Radio Panel&lt;br /&gt;
Bus 001 Device 004: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 002: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Interestingly, I now see the ''Bus 001 Device 014: ID 06a3:0d05 Saitek PLC Pro Flight Radio Panel'' being shown in my connected devices.&lt;br /&gt;
&lt;br /&gt;
If your device does not show up, make sure that it is properly connected, and powered if needed, and as a last resort try to see if it is connectable to any other PC. If still it does not show, then either probably it is not an HID device, or it is not working at all.&lt;br /&gt;
&lt;br /&gt;
So now, save the name ''Saitek PLC Pro Flight Radio Panel'', we will need it afterwards.&lt;br /&gt;
&lt;br /&gt;
=== Making sure your Linux user has full access to the device ===&lt;br /&gt;
&lt;br /&gt;
One of the issues with Linux and HID devices is user permissions, Linux is quite secure and usually will let a specific subset of users use the HID device, so let's make sure your user has access to this particular one.&lt;br /&gt;
&lt;br /&gt;
Let's go back to the 'lsusb' output from earlier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
Bus 001 Device 014: ID 06a3:0d05 Saitek PLC Pro Flight Radio Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
See that there are 2 hexadecimal numbers in there: '''06a3:0d05 '''? The part before the colon is the vendor id (or VID for shorts) and the second one is the product ID (or PID) for shorts. The first one will change depending on the manufacturer of the device, you can check [https://the-sz.com/products/usbid/index.php?v=0x06A3&amp;amp;p=0d05&amp;amp;n=]here if you're curious. &lt;br /&gt;
&lt;br /&gt;
Now, keep those numbers somewhere safe, we will need them.&lt;br /&gt;
&lt;br /&gt;
One of the first parameters to have access to a HID device is to make sure that the user belongs to a group we can refer to, for example in Ubuntu, if your user has to have access to joysticks (as any kind of gaming device) then it has to be added to the 'js' group, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
usermod -a -G examplegroup exampleusername&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where ''examplegroup'' is ''js'' in our case and ''exampleusername'' is your Linux user. You will need to run this as root, so add the 'sudo' prefix before the command&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
sudo usermod -a -G examplegroup exampleusername&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remember this 'sudo' for later on.&lt;br /&gt;
&lt;br /&gt;
Ok, so now let's make sure your user belongs to the js group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
groups&lt;br /&gt;
pi adm dialout cdrom sudo dip plugdev lpadmin lxd sambashare usb wireshark js&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
I can see my user's last group is js, well done, one thing less.&lt;br /&gt;
&lt;br /&gt;
Now we have to make sure that your device is recognized as a joystick, for this, you need to create a new udev rule. Do not worry about what this means exactly (although you can read about it at [https://opensource.com/article/18/11/udev]Opensource.com)&lt;br /&gt;
&lt;br /&gt;
We need to tell your Linux install that the Saitek device is a joystick (fun fact, my Linux install though the panel was a mouse, and moving the dials would move the actual mouse...) :&lt;br /&gt;
&lt;br /&gt;
There are several ways you can do this but this one works for me:&lt;br /&gt;
&lt;br /&gt;
Open the (or create a new) rule file under ''/etc/udev/rules.d/'', I have called it ''00-local.rules''&lt;br /&gt;
&lt;br /&gt;
so, let's go for it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
nano /etc/udev/rules.d/00-local.rules&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will open an editor (nano), feel free to use any editor, just remember that you have to be root to be able to save the file. &lt;br /&gt;
&lt;br /&gt;
Add the following line to your file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
SUBSYSTEM==&amp;quot;input&amp;quot;, ATTRS{idVendor}==&amp;quot;06a3&amp;quot;, ATTRS{idProduct}==&amp;quot;0d05&amp;quot;, ENV{ID_INPUT_JOYSTICK}=&amp;quot;1&amp;quot;,ENV{ID_INPUT_MOUSE}=&amp;quot;0&amp;quot;, TAG+=&amp;quot;uaccess&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
We now are saying to Linux that the device with VID 06a3 and PID 0d05 is a joystick and not a mouse (do those numbers ring a bell?)&lt;br /&gt;
&lt;br /&gt;
Just for completion's sake, there's another possibility to do this, alas less 'secure' by Linux standards. You can create a new file:&lt;br /&gt;
''/etc/udev/rules.d/99-hid.rules'' and in it add the following lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
SUBSYSTEM==&amp;quot;usb&amp;quot;, ATTRS{idVendor}==&amp;quot;06a3&amp;quot;, ATTRS{idProduct}==&amp;quot;0d05&amp;quot;, MODE=&amp;quot;0666&amp;quot;&lt;br /&gt;
KERNEL==&amp;quot;hidraw*&amp;quot;, ATTRS{busnum}==&amp;quot;1&amp;quot;, ATTRS{idVendor}==&amp;quot;06a3&amp;quot;, ATTRS{idProduct}==&amp;quot;0d05&amp;quot;, MODE=&amp;quot;0666&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will give anyone access to the device in question (and hence less secure in Linux terms).&lt;br /&gt;
&lt;br /&gt;
So now we have setup the device so it is a joystick and your user can access it. Let's go and play with it:&lt;br /&gt;
&lt;br /&gt;
=== Understanding your device's Inputs and outputs ===&lt;br /&gt;
&lt;br /&gt;
Make sure your device is connected and powered if needed, Once you're sure, launch hidviz:&lt;br /&gt;
&lt;br /&gt;
(I have compiled the version from the link I've put in the tools section, I won't be explaining how to buildit since it is already explained in the github page)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
./hidviz&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will present you with the following screen:&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-selector.png|Screenshot of hidviz tool main screen]]&lt;br /&gt;
&lt;br /&gt;
Click on 'Select Device', this will ask you for your password to gain root access if you have not run the command as 'sudo'&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-selector-2.png|Device selector from hidviz]]&lt;br /&gt;
&lt;br /&gt;
You should see the saitek pro panel there, select it:&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-descriptor-saitek-radio-panelpng.png|Hiviz showing the HiD descritpor for the saitek radio panel]]&lt;br /&gt;
&lt;br /&gt;
As you can see, there are 24 buttons (bits) (top section Collection/Input) and there seem to be 2 features. One containing 20 (report count) 8-bit values (report size) with a maximum logic value of 255 and then another report of 14 times 1-bit values (fun fact, when I started with the HID devices I didn't use hidviz, so I'm intrigued by this second feature report which I was not aware of!).&lt;br /&gt;
&lt;br /&gt;
For completion, HID devices (as far as I am aware) have 3 types of reports, input (which is data sent from device to PC) output (which is data sent from PC to device) and feature, which seems to be also in the PC to device category.  As you can see, here you have 1 input (buttons) 2 features (we'll talk about these later) and a padding of 2 bits, this is there because usually reports need to be of a specific size (multiplier of 24 if I remember correctly), if you do your maths: 24bits + 20*8 (160 bits) + 14 bits = 198 + 2 padding bits  = 200 bits in total, ok it does not add up, go figure, but this is not the only weird thing about this descriptor, look at the actual features described: water cooling device! either Saitek devs had a great sense of humor or they didn't spend much time figuring out how to do proper HID reports. In any case, I was expecting also to have an output report instead of a feature report and each report with its unique ID. Saitek: some improvements are needed here! All of this to say: '''HID is a big grey area amongst manufacturers, so your levels of patience to make the device work may vary'''&lt;br /&gt;
&lt;br /&gt;
If the descriptor would have been set up properly, you should have seen something like this for the output reports: (This is for one of my custom devices):&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-descriptor-fgmod.png|Hidvizz showing the fgmod descriptor]]&lt;br /&gt;
&lt;br /&gt;
This would have allowed you to easily enter values in the output report and understand how the device treated data, alas, it is not the case for the saitek device, so let's go Python!&lt;br /&gt;
&lt;br /&gt;
=== 4-Understanding how data is received and processed by your device: ===&lt;br /&gt;
&lt;br /&gt;
So we now know a little bit more about the device, it has 24 buttons, and it has 20 possible inputs (spoiler: the Saitek panel has 4*5 segment displays, could it be?? Hmmmm...)&lt;br /&gt;
&lt;br /&gt;
Let's try python&lt;br /&gt;
&lt;br /&gt;
First, you need to check which hidraw linux device corresponds to your actual device, Linux will map your device under ''/dev/hidrawx'' and to find it, create  script (call it findhid.sh):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
FILES=/dev/hidraw*&lt;br /&gt;
for f in $FILES&lt;br /&gt;
do&lt;br /&gt;
  FILE=${f##*/}&lt;br /&gt;
  DEVICE=&amp;quot;$(cat /sys/class/hidraw/${FILE}/device/uevent | grep HID_NAME | cut -d '=' -f2)&amp;quot;&lt;br /&gt;
  printf &amp;quot;%s \t %s\n&amp;quot; $FILE &amp;quot;$DEVICE&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
chmod 775 findhid.sh&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
And finally execute it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
./findhid.sh&lt;br /&gt;
hidraw0 	 SYNA3083:00 06CB:8265&lt;br /&gt;
hidraw1 	 ELAN2514:00 04F3:288A&lt;br /&gt;
hidraw2 	 SINO WEALTH USB KEYBOARD&lt;br /&gt;
hidraw3 	 SINO WEALTH USB KEYBOARD&lt;br /&gt;
hidraw4 	 PixA琀 USB Optical Mouse&lt;br /&gt;
hidraw7 	 Logitech Logitech Flight Radio Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
so, this means that our Saitek panel is linked to /dev/hidraw7, nice!&lt;br /&gt;
&lt;br /&gt;
Now, open an editor and create hidtest.py:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def send_data_to_hidraw(data, hidraw_path):&lt;br /&gt;
    try:&lt;br /&gt;
        # Open the HIDRAW device&lt;br /&gt;
        hidraw = os.open(hidraw_path, os.O_RDWR | os.O_NONBLOCK)&lt;br /&gt;
        &lt;br /&gt;
        # Write data to the HIDRAW device&lt;br /&gt;
        os.write(hidraw, bytes(data))&lt;br /&gt;
        &lt;br /&gt;
        print(&amp;quot;Data sent successfully to HIDRAW device.&amp;quot;)&lt;br /&gt;
        &lt;br /&gt;
        # Close the HIDRAW device&lt;br /&gt;
        os.close(hidraw)&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(&amp;quot;Error:&amp;quot;, e)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    # Define your data to send&lt;br /&gt;
    data_to_send = [0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03]  # Example data&lt;br /&gt;
    &lt;br /&gt;
    # Specify the path to your HIDRAW device&lt;br /&gt;
    hidraw_path = &amp;quot;/dev/hidraw7&amp;quot;  # Replace with the actual path to your HIDRAW device&lt;br /&gt;
    &lt;br /&gt;
    # Send the data to the HIDRAW device&lt;br /&gt;
    send_data_to_hidraw(data_to_send, hidraw_path)&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Two important things: change hidraw_path to your devices' correct link and make sure that the data_to_send variable is of the same length as the report we found in hidvix, in this case, we have 20 times one byte, noted in hex format in Python (0xXX).&lt;br /&gt;
&lt;br /&gt;
Small clarification, as you can see I'm sending 21 bytes, the reason behind this is that the first byte indicates the report_id you're sending to, in the case of the saitek panel, there's no real report id, so whatever you put in the first byte will still work. Make sure you consider this when testing your device.&lt;br /&gt;
&lt;br /&gt;
Now run the python script&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
python3 hidtest.py&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nothing happened? well, this could be down to several factors:&lt;br /&gt;
&lt;br /&gt;
- No permissions (go back to the start)&lt;br /&gt;
- The report is of incorrect size (try again, remember you are sending bytes, so a report of 8 times 1 bit, equals a nibble (half byte), and the same goes for bits. The safest thing to do is to count the number of bits and then divide by 8, this is the number of bytes you ill need to send)&lt;br /&gt;
&lt;br /&gt;
If you are lucky you should go from this:&lt;br /&gt;
[[File:Saitek-radio-off.jpg|Saitek radio panel with all digits off]]&lt;br /&gt;
To this:&lt;br /&gt;
[[File:Saitek-radio-on.jpg|Saitek radio panel with all digits on]]&lt;br /&gt;
&lt;br /&gt;
Congratulations, you just sent the first pieces of data to your device. As you can see it shows the numbers in the order we sent in the report, or so it looks like.&lt;br /&gt;
&lt;br /&gt;
Now, it is a game of sending reports with different values and understanding what's your device's reaction, for example, if I sent just zeores:&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeros.jpg|thumb|Saitek radio panel showing all digits as zeroes]]&lt;br /&gt;
&lt;br /&gt;
Now the fun starts. &lt;br /&gt;
&lt;br /&gt;
So this is a radio panel right, aren't radio frequencies supposed to have a 'dot' somewhere, but hey, how do I tell the device I want to have a dot? Let's think, why do I have the possibility to send 20 bytes, with a maximum value of 255? Makes no sense right, watch byte represents a number in the panel that can go up to 9 (0 to 9), so anything else is overkill, unless...&lt;br /&gt;
&lt;br /&gt;
Let's try to send something over 9, for example the second byte in data_to send I put it as 0x0A (A is 10 in hex), what happened there?&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeros first-off.jpg|Saitek radio panel showing all zeros except first digit switched off]]&lt;br /&gt;
&lt;br /&gt;
My first digit just switched off!! Interesting so now I can show numbers of less than 5 digits (XPDR, DME, hmm...) because I can switch any digit off as I please, let's try that again:&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-alternate-zeros.jpg|Saitek radio panel showing alternate zeroes and off]]&lt;br /&gt;
&lt;br /&gt;
Nice!&lt;br /&gt;
&lt;br /&gt;
So we now know, 0 to 9 is the digit in question, 10 switches off the digit, but what about the 'dot' ???&lt;br /&gt;
&lt;br /&gt;
Let's send 11 (0x0B):&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeros first-off.jpg|Saitek radio panel showing all zeros except first digit switched off]]&lt;br /&gt;
&lt;br /&gt;
Disappointment, nothing happens, let's keep trying other values.&lt;br /&gt;
&lt;br /&gt;
Hey what's this?&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-ones and dots.jpg|thumb|saitek radio panel showing all ones and dots]]&lt;br /&gt;
&lt;br /&gt;
I was at 209, so what if I send all 208 (0xD0)&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeroes_and_dots.jpg|Saitek radio panel showing all zeroe and dots]]&lt;br /&gt;
&lt;br /&gt;
Ok! so if I want to add a dot to any digit, I need to add 0xD0 the the value, so 0xD0 for 0, 0xD1 for one and so on)&lt;br /&gt;
&lt;br /&gt;
What If I continue?&lt;br /&gt;
&lt;br /&gt;
This is what happens with 224 (0xE0)&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-dashes.jpg|thumb|Saitek radio panel showing al dashes]]&lt;br /&gt;
&lt;br /&gt;
I get a 'dash'!&lt;br /&gt;
&lt;br /&gt;
And there's nothing else interesting in the tests, the numbers repeat a lot, but basically when now:&lt;br /&gt;
&lt;br /&gt;
0 to 9 -&amp;gt; the numbers in each digit&lt;br /&gt;
10 -&amp;gt; Switch off the digits&lt;br /&gt;
208-217 -&amp;gt; The numbers with a dot (to the right)&lt;br /&gt;
224 -&amp;gt; A dash&lt;br /&gt;
&lt;br /&gt;
Important point, we have not used any proprietary drivers or anything that could be linked to Saitek's proprietary development (AFAIK, I'm not a lawyer), we're just sending data to the device.&lt;br /&gt;
&lt;br /&gt;
Now that we know the logic, we're ready to go to the next step, make it work in FlightGear! [To be continued in next post]&lt;br /&gt;
&lt;br /&gt;
So now we have understood (more or less) how our device works, how we can send data to it, and what this data does.&lt;br /&gt;
&lt;br /&gt;
Let's fire up FlightGear.&lt;br /&gt;
&lt;br /&gt;
=== Making sure FlightGear detects the device ===&lt;br /&gt;
&lt;br /&gt;
The first thing we need to do is to launch FlightFear with debug on, to do this make sure you set the log level to debug via the ''--log-level=debug'' flag, do this either in the command line or if you use the launcher, in the additional settings.&lt;br /&gt;
&lt;br /&gt;
I would also recommend you to capture the output of the log:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
./dnc-managed/run_fgfs.sh --launcher 2&amp;gt;&amp;amp;1 | tee log.txt&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is my command, yours may be slightly different, the important part is the ''2&amp;gt;&amp;amp;1 | tee log.txt'' at the end of it.&lt;br /&gt;
&lt;br /&gt;
launch FG an let the  log start capturing all the information we need.&lt;br /&gt;
&lt;br /&gt;
Once the airplane's cockpit is showing up, you can shut down FlightGear, that'w all we need for now.&lt;br /&gt;
&lt;br /&gt;
Open the ''log.txt'' and start looking for the name of your device, you should see things like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;  225.20 [DBUG]:input      name=&amp;lt;null&amp;gt;, node=&amp;lt;null&amp;gt;&lt;br /&gt;
  225.20 [DBUG]:input      name=Logitech Logitech Flight Radio Panel, node=/dev/input/event23&lt;br /&gt;
&lt;br /&gt;
225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-0 modifiers=0 value=1&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-1 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-2 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-3 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-4 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-5 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-6 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-7 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-8 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-9 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-266 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-267 modifiers=0 value=1&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-268 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-269 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-270 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-271 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-left modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-right modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-middle modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-side modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-extra modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-forward modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-back modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-task modifiers=0 value=0&lt;br /&gt;
  225.26 [DBUG]:input      using InputDevice Logitech Logitech Flight Radio Panel_0&lt;br /&gt;
&lt;br /&gt;
225.28 [WARN]:input      Unhandled HID generic desktop usage:1&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown, bits: 0:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:2&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-1, bits: 8:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:3&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-2, bits: 16:8, report=0&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:joystick, bits: 24:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:5&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-3, bits: 32:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:6&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-4, bits: 40:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:7&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-5, bits: 48:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:8&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-6, bits: 56:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:9&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-7, bits: 64:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:10&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-8, bits: 72:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:11&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-9, bits: 80:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:12&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-10, bits: 88:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:13&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-11, bits: 96:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:14&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-12, bits: 104:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:15&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-13, bits: 112:8, report=0&lt;br /&gt;
  225.29 [WARN]:input      Unhandled HID generic desktop usage:16&lt;br /&gt;
  225.29 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-14, bits: 120:8, report=0&lt;br /&gt;
  225.29 [WARN]:input      Unhandled HID generic desktop usage:17&lt;br /&gt;
  225.29 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-15, bits: 128:8, report=0&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see fro te log there are already several interesting pieces of information:&lt;br /&gt;
&lt;br /&gt;
The device has ben recognized! ''25.20 [DBUG]:input      name=Logitech Logitech Flight Radio Panel, node=/dev/input/event23''&lt;br /&gt;
&lt;br /&gt;
It has detected the buttons ''225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-0 modifiers=0 value=1''&lt;br /&gt;
&lt;br /&gt;
And even the feature reports '' 225.28 [WARN]:input      Unhandled HID generic desktop usage:2&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-1, bits: 8:8, report=0''&lt;br /&gt;
&lt;br /&gt;
As you can see, we have everything under control, FG has detected the device and has detected the different buttons and feature reports. All of these are called 'events' by Flightgear.&lt;br /&gt;
&lt;br /&gt;
Important point, when we're going to be creating the properties files, we need to refer to the name you see in the logs, as strange as it sounds, you will get different buttons name not necessarily in a sequential order (things like thumb2, or button-333).&lt;br /&gt;
&lt;br /&gt;
=== The properties files ===&lt;br /&gt;
&lt;br /&gt;
The way that FlighGear communicates with the devices is via XML files located under the FlighGear directory ('~/.fgfs' for most linux installs) and then under Input, with 2 different options, either 'Joysticks' or 'Event':&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
drwxr-xr-x 2 pi pi 4096 Mar 27 16:12 Event&lt;br /&gt;
drwxr-xr-x 2 pi pi 4096 Apr  1 15:49 Joysticks&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
The joystick directory will hold, amongst others, the files that are created automatically by the joystick configurator within the simulator, the directory we're interested in is this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;~/.fgfs/Input/Event&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, there's no problem in having both a joystick file and an event file for the same device, I do have this for my Honeycomb alpha, where the axes are in the joystick file and the rest of the buttons in the event file (which allows me to go beyond the 32 button limitation, yes, you can use this HID way of doing things for devices over 32 buttons).&lt;br /&gt;
&lt;br /&gt;
So let's start writing. First of all, create an empty file called 'YOURDEVCIE.xml' (this is an example and the filename is not relevant as FG will read inside to understand to which device each file belongs (although I name it as the device with '-' just for clarity, for example for the saitek panel ''Logitech-Logitech-Flight-Radio-Panel.xml'' )&lt;br /&gt;
&lt;br /&gt;
Put the XML header:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;PropertyList&amp;gt;&lt;br /&gt;
  &amp;lt;name type=&amp;quot;string&amp;quot;&amp;gt;Logitech Logitech Flight Radio Panel&amp;lt;/name&amp;gt;&lt;br /&gt;
  &amp;lt;debug-events type=&amp;quot;bool&amp;quot;&amp;gt;true&amp;lt;/debug-events&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will indicate FG this is the file for your device, as the ''name'' tag defines it.&lt;br /&gt;
&lt;br /&gt;
If you plan to have some 'logic' in your properties file, add the nasal tags:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;PropertyList&amp;gt;&lt;br /&gt;
  &amp;lt;name type=&amp;quot;string&amp;quot;&amp;gt;Logitech Logitech Flight Radio Panel&amp;lt;/name&amp;gt;&lt;br /&gt;
  &amp;lt;debug-events type=&amp;quot;bool&amp;quot;&amp;gt;true&amp;lt;/debug-events&amp;gt;&lt;br /&gt;
  &amp;lt;nasal&amp;gt;&lt;br /&gt;
    &amp;lt;open&amp;gt;&lt;br /&gt;
      &amp;lt;![CDATA[]]&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Your basic file is starting to get some form. Now we need to start defining what do we do when each of the events is triggered:&lt;br /&gt;
I'm going to paste below the bindings (that's how it's called in FG) for the fact that you have switched the upper selector of the radio panel into 'comm1' mode:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;event&amp;gt;&lt;br /&gt;
    &amp;lt;desc&amp;gt;UK COMM1&amp;lt;/desc&amp;gt;&lt;br /&gt;
    &amp;lt;name&amp;gt;button-1&amp;lt;/name&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknoba&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/selected-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobb&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/standby-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobt&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;5&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
 &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobsw&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frq-swap-btn&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobmax&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;137&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobmin&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;118&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobfstep&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;1&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobhstep&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;0.025&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;script&amp;gt;refreshPanels();&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
  &amp;lt;/event&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Do not be scared by that size! I like to make things generic, so you will see a lot of reference and proxy properties being set that would allow to handle the logic of what happens when we're in 'comm1' mode in the upper panel.&lt;br /&gt;
&lt;br /&gt;
First of all we set the property ''saitek/RP/upknoba'' to ''/instrumentation/comm/frequencies/selected-mhz''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknoba&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/selected-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then set the standby frequency to the ''/saitek/RP/upknobb'' property&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobb&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/standby-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then the property ''/saitek/RP/upknobt'' to 5, which is the number of digits a frequency has&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobt&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;5&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then the 'swap' button to change frequencies&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobsw&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frq-swap-btn&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
The some max,min and incremental values, and last but not least, I call the refresh panel function (that I've created) to put the proper values in the panels:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;script&amp;gt;refreshPanels();&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
  &amp;lt;/event&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has to be done to every single button in the device, so they act the way you expect them to do. You can check the full file at the bottom of this post.&lt;br /&gt;
&lt;br /&gt;
Ok, so we have the buttons set up, now we want the display to show the proper values:&lt;br /&gt;
&lt;br /&gt;
We use the same tag, event, only that now we have to link a property to the event, so FG will send that value to the output/feature report in the proper position.&lt;br /&gt;
&lt;br /&gt;
Before we continue, remember that in the log, we saw things like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
225.28 [WARN]:input      Unhandled HID generic desktop usage:1&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown, bits: 0:8, report=0&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
And I did mention that the name that you saw there is the name that should be used for the event, in the case of unknown, you need to add the suffix ''-0'' for the first one, the rest will already have it ''-1, -2,-3 etc..''&lt;br /&gt;
&lt;br /&gt;
Let's add the event to the XML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;event&amp;gt;&lt;br /&gt;
    &amp;lt;desc&amp;gt;RADIO INDICATORS&amp;lt;/desc&amp;gt;&lt;br /&gt;
    &amp;lt;name&amp;gt;unknown-0&amp;lt;/name&amp;gt;&lt;br /&gt;
    &amp;lt;setting&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/ULpanel/digit1&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;/setting&amp;gt;&lt;br /&gt;
  &amp;lt;/event&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
You're telling FlightGear to watch for the property ''/saitek/RP/ULpanel/digit1'' and set its value to the vendor-0 byte.&lt;br /&gt;
&lt;br /&gt;
As you can see there's a strange property there: ''saitek/RP/ULpanel/digit1''. This property is of my choice and you can create any property you want to be sent to the device. Remember that in this particular case, we have a value for each digit, so we cannot send the actual value, we have to slice it so we send each digit in the correct position.&lt;br /&gt;
&lt;br /&gt;
And then again, do the same for the rest of the events.&lt;br /&gt;
&lt;br /&gt;
Once the events have been set and saved, you can launch FG to see if it worked!&lt;br /&gt;
&lt;br /&gt;
Yes! I see the same frequencies in the panel&lt;br /&gt;
[[File:Saitek-working.jpg|thumb|Saitek radio panel working]]&lt;br /&gt;
&lt;br /&gt;
as in the simulator&lt;br /&gt;
[[File:FG-Radio Panel for Saitek.jpg|thumb|Flightgear Cockpit showing radio panel with same values as Saitek radio panel]]&lt;br /&gt;
&lt;br /&gt;
Of course, every time you modify the frequencies in any of the sim or panel, the other one reflects the same value as expected.&lt;br /&gt;
&lt;br /&gt;
You can have a look at [[https://github.com/zayamatias/flightgear/blob/main/.fgfs/Input/Event/Logitech-Logitech-Flight-Radio-Panel.xml]the complete xml file, where you can see I use nasal heavily to do some extra logic, for example, do not turn on the panel unless the contact is set on the aeroplane, how I use the swap button to select the digit when in XPDR mode, and so on. There is no limits to what you can do once you understand the properties and what you're able to do with them.&lt;br /&gt;
&lt;br /&gt;
I hope I have not forgotten anything essential and I also hope this has helped. I'm really looking forward to other devices becoming available in FG.&lt;br /&gt;
&lt;br /&gt;
This also opens the possibility of creating your own devices, have a look at my [https://github.com/zayamatias/flightgear]repo.&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User:Zayamatias/Adding_HID_devices_to_FlightGear&amp;diff=139763</id>
		<title>User:Zayamatias/Adding HID devices to FlightGear</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User:Zayamatias/Adding_HID_devices_to_FlightGear&amp;diff=139763"/>
		<updated>2024-04-22T15:59:54Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: Created page with &amp;quot;'''Adding_HID_devices_to_FlightGear''' hopes to explain how to set-up any HID device to work with FlightGear in a step-by-step easy to follow guide  First disclaimer: The HID subsystem seems to be working only under Linux and MacOS, I am not sure if one day it will work in Windows.  Second Disclaimer: This guide was done under an Ubuntu distribution, this means that other distros may vary slightly.  Last but not least: I take no responsibility in the unlikely event of yo...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Adding_HID_devices_to_FlightGear''' hopes to explain how to set-up any HID device to work with FlightGear in a step-by-step easy to follow guide&lt;br /&gt;
&lt;br /&gt;
First disclaimer: The HID subsystem seems to be working only under Linux and MacOS, I am not sure if one day it will work in Windows. &lt;br /&gt;
Second Disclaimer: This guide was done under an Ubuntu distribution, this means that other distros may vary slightly. &lt;br /&gt;
Last but not least: I take no responsibility in the unlikely event of you breaking your HID device by using this guide&lt;br /&gt;
&lt;br /&gt;
=== Getting started ===&lt;br /&gt;
&lt;br /&gt;
Before starting, there are a couple of tools you need to install:&lt;br /&gt;
&lt;br /&gt;
[https://github.com/hidviz/hidviz] HIDVIZ&lt;br /&gt;
&lt;br /&gt;
This tool will allow you to have a look at the inner workings of your HID device, I'll talk about it later.&lt;br /&gt;
&lt;br /&gt;
[https://code.visualstudio.com/]VS Code&lt;br /&gt;
&lt;br /&gt;
I use this for creating the XMLfiles and the Nasal code, as it has very nice extensions for this, but this is not mandatory and you can use anything you are used to.&lt;br /&gt;
&lt;br /&gt;
Python&lt;br /&gt;
&lt;br /&gt;
I've created some quick and dirty tools under python to test the device, so make sure Python (3.9 at least) is installed in your system if you want to use them.&lt;br /&gt;
&lt;br /&gt;
=== The Device ===&lt;br /&gt;
&lt;br /&gt;
For this guide, I'll be using the [https://www.logitechg.com/en-gb/products/flight/flight-simulator-cockpit-radio-panel.945-000011.html]Saitek/Logitech radio panel as an example that would hopefully help you with any other device.&lt;br /&gt;
&lt;br /&gt;
So let the fun begin!&lt;br /&gt;
&lt;br /&gt;
=== Understanding what's the name of the device ===&lt;br /&gt;
&lt;br /&gt;
Start your PC and go to the terminal, do not connect any device yet, and let's see what has been detected in the USB connections:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
lsusb&lt;br /&gt;
Bus 002 Device 003: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 002: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub&lt;br /&gt;
Bus 001 Device 012: ID 138a:00ab Validity Sensors, Inc. &lt;br /&gt;
Bus 001 Device 011: ID 093a:2510 Pixart Imaging, Inc. Optical Mouse&lt;br /&gt;
Bus 001 Device 008: ID 258a:0001 SINO WEALTH USB KEYBOARD&lt;br /&gt;
Bus 001 Device 005: ID 214b:7250 Huasheng Electronics USB2.0 HUB&lt;br /&gt;
Bus 001 Device 003: ID 04f2:b669 Chicony Electronics Co., Ltd HP HD Camera&lt;br /&gt;
Bus 001 Device 013: ID 8087:0aaa Intel Corp. Bluetooth 9460/9560 Jefferson Peak (JfP)&lt;br /&gt;
Bus 001 Device 004: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 002: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By issuing the 'lsusb' command you can see what the PC has detected as connected devices, no sign yet of my radio panel, so let's connect it now and issue the same command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
lsusb&lt;br /&gt;
Bus 002 Device 003: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 002: ID 045b:0210 Hitachi, Ltd &lt;br /&gt;
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub&lt;br /&gt;
Bus 001 Device 012: ID 138a:00ab Validity Sensors, Inc. &lt;br /&gt;
Bus 001 Device 011: ID 093a:2510 Pixart Imaging, Inc. Optical Mouse&lt;br /&gt;
Bus 001 Device 008: ID 258a:0001 SINO WEALTH USB KEYBOARD&lt;br /&gt;
Bus 001 Device 005: ID 214b:7250 Huasheng Electronics USB2.0 HUB&lt;br /&gt;
Bus 001 Device 003: ID 04f2:b669 Chicony Electronics Co., Ltd HP HD Camera&lt;br /&gt;
Bus 001 Device 013: ID 8087:0aaa Intel Corp. Bluetooth 9460/9560 Jefferson Peak (JfP)&lt;br /&gt;
Bus 001 Device 014: ID 06a3:0d05 Saitek PLC Pro Flight Radio Panel&lt;br /&gt;
Bus 001 Device 004: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 002: ID 045b:0209 Hitachi, Ltd &lt;br /&gt;
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Interestingly, I now see the ''Bus 001 Device 014: ID 06a3:0d05 Saitek PLC Pro Flight Radio Panel'' being shown in my connected devices.&lt;br /&gt;
&lt;br /&gt;
If your device does not show up, make sure that it is properly connected, and powered if needed, and as a last resort try to see if it is connectable to any other PC. If still it does not show, then either probably it is not an HID device, or it is not working at all.&lt;br /&gt;
&lt;br /&gt;
So now, save the name ''Saitek PLC Pro Flight Radio Panel'', we will need it afterwards.&lt;br /&gt;
&lt;br /&gt;
=== Making sure your Linux user has full access to the device ===&lt;br /&gt;
&lt;br /&gt;
One of the issues with Linux and HID devices is user permissions, Linux is quite secure and usually will let a specific subset of users use the HID device, so let's make sure your user has access to this particular one.&lt;br /&gt;
&lt;br /&gt;
Let's go back to the 'lsusb' output from earlier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
Bus 001 Device 014: ID 06a3:0d05 Saitek PLC Pro Flight Radio Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
See that there are 2 hexadecimal numbers in there: '''06a3:0d05 '''? The part before the colon is the vendor id (or VID for shorts) and the second one is the product ID (or PID) for shorts. The first one will change depending on the manufacturer of the device, you can check [https://the-sz.com/products/usbid/index.php?v=0x06A3&amp;amp;p=0d05&amp;amp;n=]here if you're curious. &lt;br /&gt;
&lt;br /&gt;
Now, keep those numbers somewhere safe, we will need them.&lt;br /&gt;
&lt;br /&gt;
One of the first parameters to have access to a HID device is to make sure that the user belongs to a group we can refer to, for example in Ubuntu, if your user has to have access to joysticks (as any kind of gaming device) then it has to be added to the 'js' group, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
usermod -a -G examplegroup exampleusername&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where ''examplegroup'' is ''js'' in our case and ''exampleusername'' is your Linux user. You will need to run this as root, so add the 'sudo' prefix before the command&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
sudo usermod -a -G examplegroup exampleusername&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remember this 'sudo' for later on.&lt;br /&gt;
&lt;br /&gt;
Ok, so now let's make sure your user belongs to the js group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
groups&lt;br /&gt;
pi adm dialout cdrom sudo dip plugdev lpadmin lxd sambashare usb wireshark js&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
I can see my user's last group is js, well done, one thing less.&lt;br /&gt;
&lt;br /&gt;
Now we have to make sure that your device is recognized as a joystick, for this, you need to create a new udev rule. Do not worry about what this means exactly (although you can read about it at [https://opensource.com/article/18/11/udev]Opensource.com)&lt;br /&gt;
&lt;br /&gt;
We need to tell your Linux install that the Saitek device is a joystick (fun fact, my Linux install though the panel was a mouse, and moving the dials would move the actual mouse...) :&lt;br /&gt;
&lt;br /&gt;
There are several ways you can do this but this one works for me:&lt;br /&gt;
&lt;br /&gt;
Open the (or create a new) rule file under ''/etc/udev/rules.d/'', I have called it ''00-local.rules''&lt;br /&gt;
&lt;br /&gt;
so, let's go for it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
nano /etc/udev/rules.d/00-local.rules&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will open an editor (nano), feel free to use any editor, just remember that you have to be root to be able to save the file. &lt;br /&gt;
&lt;br /&gt;
Add the following line to your file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
SUBSYSTEM==&amp;quot;input&amp;quot;, ATTRS{idVendor}==&amp;quot;06a3&amp;quot;, ATTRS{idProduct}==&amp;quot;0d05&amp;quot;, ENV{ID_INPUT_JOYSTICK}=&amp;quot;1&amp;quot;,ENV{ID_INPUT_MOUSE}=&amp;quot;0&amp;quot;, TAG+=&amp;quot;uaccess&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
We now are saying to Linux that the device with VID 06a3 and PID 0d05 is a joystick and not a mouse (do those numbers ring a bell?)&lt;br /&gt;
&lt;br /&gt;
Just for completion's sake, there's another possibility to do this, alas less 'secure' by Linux standards. You can create a new file:&lt;br /&gt;
''/etc/udev/rules.d/99-hid.rules'' and in it add the following lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
SUBSYSTEM==&amp;quot;usb&amp;quot;, ATTRS{idVendor}==&amp;quot;06a3&amp;quot;, ATTRS{idProduct}==&amp;quot;0d05&amp;quot;, MODE=&amp;quot;0666&amp;quot;&lt;br /&gt;
KERNEL==&amp;quot;hidraw*&amp;quot;, ATTRS{busnum}==&amp;quot;1&amp;quot;, ATTRS{idVendor}==&amp;quot;06a3&amp;quot;, ATTRS{idProduct}==&amp;quot;0d05&amp;quot;, MODE=&amp;quot;0666&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will give anyone access to the device in question (and hence less secure in Linux terms).&lt;br /&gt;
&lt;br /&gt;
So now we have setup the device so it is a joystick and your user can access it. Let's go and play with it:&lt;br /&gt;
&lt;br /&gt;
=== Understanding your device's Inputs and outputs ===&lt;br /&gt;
&lt;br /&gt;
Make sure your device is connected and powered if needed, Once you're sure, launch hidviz:&lt;br /&gt;
&lt;br /&gt;
(I have compiled the version from the link I've put in the tools section, I won't be explaining how to buildit since it is already explained in the github page)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
./hidviz&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will present you with the following screen:&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-selector.png|Screenshot of hidviz tool main screen]]&lt;br /&gt;
&lt;br /&gt;
Click on 'Select Device', this will ask you for your password to gain root access if you have not run the command as 'sudo'&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-selector-2.png|Device selector from hidviz]]&lt;br /&gt;
&lt;br /&gt;
You should see the saitek pro panel there, select it:&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-descriptor-saitek-radio-panelpng.png|Hiviz showing the HiD descritpor for the saitek radio panel]]&lt;br /&gt;
&lt;br /&gt;
As you can see, there are 24 buttons (bits) (top section Collection/Input) and there seem to be 2 features. One containing 20 (report count) 8-bit values (report size) with a maximum logic value of 255 and then another report of 14 times 1-bit values (fun fact, when I started with the HID devices I didn't use hidviz, so I'm intrigued by this second feature report which I was not aware of!).&lt;br /&gt;
&lt;br /&gt;
For completion, HID devices (as far as I am aware) have 3 types of reports, input (which is data sent from device to PC) output (which is data sent from PC to device) and feature, which seems to be also in the PC to device category.  As you can see, here you have 1 input (buttons) 2 features (we'll talk about these later) and a padding of 2 bits, this is there because usually reports need to be of a specific size (multiplier of 24 if I remember correctly), if you do your maths: 24bits + 20*8 (160 bits) + 14 bits = 198 + 2 padding bits  = 200 bits in total, ok it does not add up, go figure, but this is not the only weird thing about this descriptor, look at the actual features described: water cooling device! either Saitek devs had a great sense of humor or they didn't spend much time figuring out how to do proper HID reports. In any case, I was expecting also to have an output report instead of a feature report and each report with its unique ID. Saitek: some improvements are needed here! All of this to say: '''HID is a big grey area amongst manufacturers, so your levels of patience to make the device work may vary'''&lt;br /&gt;
&lt;br /&gt;
If the descriptor would have been set up properly, you should have seen something like this for the output reports: (This is for one of my custom devices):&lt;br /&gt;
&lt;br /&gt;
[[File:Hidviz-device-descriptor-fgmod.png|Hidvizz showing the fgmod descriptor]]&lt;br /&gt;
&lt;br /&gt;
This would have allowed you to easily enter values in the output report and understand how the device treated data, alas, it is not the case for the saitek device, so let's go Python!&lt;br /&gt;
&lt;br /&gt;
=== 4-Understanding how data is received and processed by your device: ===&lt;br /&gt;
&lt;br /&gt;
So we now know a little bit more about the device, it has 24 buttons, and it has 20 possible inputs (spoiler: the Saitek panel has 4*5 segment displays, could it be?? Hmmmm...)&lt;br /&gt;
&lt;br /&gt;
Let's try python&lt;br /&gt;
&lt;br /&gt;
First, you need to check which hidraw linux device corresponds to your actual device, Linux will map your device under ''/dev/hidrawx'' and to find it, create  script (call it findhid.sh):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
FILES=/dev/hidraw*&lt;br /&gt;
for f in $FILES&lt;br /&gt;
do&lt;br /&gt;
  FILE=${f##*/}&lt;br /&gt;
  DEVICE=&amp;quot;$(cat /sys/class/hidraw/${FILE}/device/uevent | grep HID_NAME | cut -d '=' -f2)&amp;quot;&lt;br /&gt;
  printf &amp;quot;%s \t %s\n&amp;quot; $FILE &amp;quot;$DEVICE&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
chmod 775 findhid.sh&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
And finally execute it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
./findhid.sh&lt;br /&gt;
hidraw0 	 SYNA3083:00 06CB:8265&lt;br /&gt;
hidraw1 	 ELAN2514:00 04F3:288A&lt;br /&gt;
hidraw2 	 SINO WEALTH USB KEYBOARD&lt;br /&gt;
hidraw3 	 SINO WEALTH USB KEYBOARD&lt;br /&gt;
hidraw4 	 PixA琀 USB Optical Mouse&lt;br /&gt;
hidraw7 	 Logitech Logitech Flight Radio Panel&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
so, this means that our Saitek panel is linked to /dev/hidraw7, nice!&lt;br /&gt;
&lt;br /&gt;
Now, open an editor and create hidtest.py:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def send_data_to_hidraw(data, hidraw_path):&lt;br /&gt;
    try:&lt;br /&gt;
        # Open the HIDRAW device&lt;br /&gt;
        hidraw = os.open(hidraw_path, os.O_RDWR | os.O_NONBLOCK)&lt;br /&gt;
        &lt;br /&gt;
        # Write data to the HIDRAW device&lt;br /&gt;
        os.write(hidraw, bytes(data))&lt;br /&gt;
        &lt;br /&gt;
        print(&amp;quot;Data sent successfully to HIDRAW device.&amp;quot;)&lt;br /&gt;
        &lt;br /&gt;
        # Close the HIDRAW device&lt;br /&gt;
        os.close(hidraw)&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(&amp;quot;Error:&amp;quot;, e)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    # Define your data to send&lt;br /&gt;
    data_to_send = [0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03,0x01, 0x02, 0x03]  # Example data&lt;br /&gt;
    &lt;br /&gt;
    # Specify the path to your HIDRAW device&lt;br /&gt;
    hidraw_path = &amp;quot;/dev/hidraw7&amp;quot;  # Replace with the actual path to your HIDRAW device&lt;br /&gt;
    &lt;br /&gt;
    # Send the data to the HIDRAW device&lt;br /&gt;
    send_data_to_hidraw(data_to_send, hidraw_path)&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Two important things: change hidraw_path to your devices' correct link and make sure that the data_to_send variable is of the same length as the report we found in hidvix, in this case, we have 20 times one byte, noted in hex format in Python (0xXX).&lt;br /&gt;
&lt;br /&gt;
Small clarification, as you can see I'm sending 21 bytes, the reason behind this is that the first byte indicates the report_id you're sending to, in the case of the saitek panel, there's no real report id, so whatever you put in the first byte will still work. Make sure you consider this when testing your device.&lt;br /&gt;
&lt;br /&gt;
Now run the python script&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
python3 hidtest.py&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nothing happened? well, this could be down to several factors:&lt;br /&gt;
&lt;br /&gt;
- No permissions (go back to the start)&lt;br /&gt;
- The report is of incorrect size (try again, remember you are sending bytes, so a report of 8 times 1 bit, equals a nibble (half byte), and the same goes for bits. The safest thing to do is to count the number of bits and then divide by 8, this is the number of bytes you ill need to send)&lt;br /&gt;
&lt;br /&gt;
If you are lucky you should go from this:&lt;br /&gt;
[[File:Saitek-radio-off.jpg|Saitek radio panel with all digits off]]&lt;br /&gt;
To this:&lt;br /&gt;
[[File:Saitek-radio-on.jpg|Saitek radio panel with all digits on]]&lt;br /&gt;
&lt;br /&gt;
Congratulations, you just sent the first pieces of data to your device. As you can see it shows the numbers in the order we sent in the report, or so it looks like.&lt;br /&gt;
&lt;br /&gt;
Now, it is a game of sending reports with different values and understanding what's your device's reaction, for example, if I sent just zeores:&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeros.jpg|thumb|Saitek radio panel showing all digits as zeroes]]&lt;br /&gt;
&lt;br /&gt;
Now the fun starts. &lt;br /&gt;
&lt;br /&gt;
So this is a radio panel right, aren't radio frequencies supposed to have a 'dot' somewhere, but hey, how do I tell the device I want to have a dot? Let's think, why do I have the possibility to send 20 bytes, with a maximum value of 255? Makes no sense right, watch byte represents a number in the panel that can go up to 9 (0 to 9), so anything else is overkill, unless...&lt;br /&gt;
&lt;br /&gt;
Let's try to send something over 9, for example the second byte in data_to send I put it as 0x0A (A is 10 in hex), what happened there?&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeros first-off.jpg|Saitek radio panel showing all zeros except first digit switched off]]&lt;br /&gt;
&lt;br /&gt;
My first digit just switched off!! Interesting so now I can show numbers of less than 5 digits (XPDR, DME, hmm...) because I can switch any digit off as I please, let's try that again:&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-alternate-zeros.jpg|Saitek radio panel showing alternate zeroes and off]]&lt;br /&gt;
&lt;br /&gt;
Nice!&lt;br /&gt;
&lt;br /&gt;
So we now know, 0 to 9 is the digit in question, 10 switches off the digit, but what about the 'dot' ???&lt;br /&gt;
&lt;br /&gt;
Let's send 11 (0x0B):&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeros first-off.jpg|Saitek radio panel showing all zeros except first digit switched off]]&lt;br /&gt;
&lt;br /&gt;
Disappointment, nothing happens, let's keep trying other values.&lt;br /&gt;
&lt;br /&gt;
Hey what's this?&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-ones and dots.jpg|thumb|saitek radio panel showing all ones and dots]]&lt;br /&gt;
&lt;br /&gt;
I was at 209, so what if I send all 208 (0xD0)&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-zeroes_and_dots.jpg|Saitek radio panel showing all zeroe and dots]]&lt;br /&gt;
&lt;br /&gt;
Ok! so if I want to add a dot to any digit, I need to add 0xD0 the the value, so 0xD0 for 0, 0xD1 for one and so on)&lt;br /&gt;
&lt;br /&gt;
What If I continue?&lt;br /&gt;
&lt;br /&gt;
This is what happens with 224 (0xE0)&lt;br /&gt;
&lt;br /&gt;
[[File:Saitek-all-dashes.jpg|thumb|Saitek radio panel showing al dashes]]&lt;br /&gt;
&lt;br /&gt;
I get a 'dash'!&lt;br /&gt;
&lt;br /&gt;
And there's nothing else interesting in the tests, the numbers repeat a lot, but basically when now:&lt;br /&gt;
&lt;br /&gt;
0 to 9 -&amp;gt; the numbers in each digit&lt;br /&gt;
10 -&amp;gt; Switch off the digits&lt;br /&gt;
208-217 -&amp;gt; The numbers with a dot (to the right)&lt;br /&gt;
224 -&amp;gt; A dash&lt;br /&gt;
&lt;br /&gt;
Important point, we have not used any proprietary drivers or anything that could be linked to Saitek's proprietary development (AFAIK, I'm not a lawyer), we're just sending data to the device.&lt;br /&gt;
&lt;br /&gt;
Now that we know the logic, we're ready to go to the next step, make it work in FlightGear! [To be continued in next post]&lt;br /&gt;
&lt;br /&gt;
So now we have understood (more or less) how our device works, how we can send data to it, and what this data does.&lt;br /&gt;
&lt;br /&gt;
Let's fire up FlightGear.&lt;br /&gt;
&lt;br /&gt;
=== Making sure FlightGear detects the device ===&lt;br /&gt;
&lt;br /&gt;
The first thing we need to do is to launch FlightFear with debug on, to do this make sure you set the log level to debug via the ''--log-level=debug'' flag, do this either in the command line or if you use the launcher, in the additional settings.&lt;br /&gt;
&lt;br /&gt;
I would also recommend you to capture the output of the log:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
./dnc-managed/run_fgfs.sh --launcher 2&amp;gt;&amp;amp;1 | tee log.txt&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is my command, yours may be slightly different, the important part is the ''2&amp;gt;&amp;amp;1 | tee log.txt'' at the end of it.&lt;br /&gt;
&lt;br /&gt;
launch FG an let the  log start capturing all the information we need.&lt;br /&gt;
&lt;br /&gt;
Once the airplane's cockpit is showing up, you can shut down FlightGear, that'w all we need for now.&lt;br /&gt;
&lt;br /&gt;
Open the ''log.txt'' and start looking for the name of your device, you should see things like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;  225.20 [DBUG]:input      name=&amp;lt;null&amp;gt;, node=&amp;lt;null&amp;gt;&lt;br /&gt;
  225.20 [DBUG]:input      name=Logitech Logitech Flight Radio Panel, node=/dev/input/event23&lt;br /&gt;
&lt;br /&gt;
225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-0 modifiers=0 value=1&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-1 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-2 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-3 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-4 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-5 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-6 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-7 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-8 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-9 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-266 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-267 modifiers=0 value=1&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-268 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-269 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-270 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-271 modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-left modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-right modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-middle modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-side modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-extra modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-forward modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-back modifiers=0 value=0&lt;br /&gt;
  225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-task modifiers=0 value=0&lt;br /&gt;
  225.26 [DBUG]:input      using InputDevice Logitech Logitech Flight Radio Panel_0&lt;br /&gt;
&lt;br /&gt;
225.28 [WARN]:input      Unhandled HID generic desktop usage:1&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown, bits: 0:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:2&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-1, bits: 8:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:3&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-2, bits: 16:8, report=0&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:joystick, bits: 24:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:5&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-3, bits: 32:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:6&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-4, bits: 40:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:7&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-5, bits: 48:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:8&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-6, bits: 56:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:9&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-7, bits: 64:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:10&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-8, bits: 72:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:11&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-9, bits: 80:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:12&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-10, bits: 88:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:13&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-11, bits: 96:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:14&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-12, bits: 104:8, report=0&lt;br /&gt;
  225.28 [WARN]:input      Unhandled HID generic desktop usage:15&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-13, bits: 112:8, report=0&lt;br /&gt;
  225.29 [WARN]:input      Unhandled HID generic desktop usage:16&lt;br /&gt;
  225.29 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-14, bits: 120:8, report=0&lt;br /&gt;
  225.29 [WARN]:input      Unhandled HID generic desktop usage:17&lt;br /&gt;
  225.29 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-15, bits: 128:8, report=0&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see fro te log there are already several interesting pieces of information:&lt;br /&gt;
&lt;br /&gt;
The device has ben recognized! ''25.20 [DBUG]:input      name=Logitech Logitech Flight Radio Panel, node=/dev/input/event23''&lt;br /&gt;
&lt;br /&gt;
It has detected the buttons ''225.26 [INFO]:input      Logitech Logitech Flight Radio Panel_0 has event button-0 modifiers=0 value=1''&lt;br /&gt;
&lt;br /&gt;
And even the feature reports '' 225.28 [WARN]:input      Unhandled HID generic desktop usage:2&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown-1, bits: 8:8, report=0''&lt;br /&gt;
&lt;br /&gt;
As you can see, we have everything under control, FG has detected the device and has detected the different buttons and feature reports. All of these are called 'events' by Flightgear.&lt;br /&gt;
&lt;br /&gt;
Important point, when we're going to be creating the properties files, we need to refer to the name you see in the logs, as strange as it sounds, you will get different buttons name not necessarily in a sequential order (things like thumb2, or button-333).&lt;br /&gt;
&lt;br /&gt;
=== The properties files ===&lt;br /&gt;
&lt;br /&gt;
The way that FlighGear communicates with the devices is via XML files located under the FlighGear directory ('~/.fgfs' for most linux installs) and then under Input, with 2 different options, either 'Joysticks' or 'Event':&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
drwxr-xr-x 2 pi pi 4096 Mar 27 16:12 Event&lt;br /&gt;
drwxr-xr-x 2 pi pi 4096 Apr  1 15:49 Joysticks&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
The joystick directory will hold, amongst others, the files that are created automatically by the joystick configurator within the simulator, the directory we're interested in is this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;~/.fgfs/Input/Event&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, there's no problem in having both a joystick file and an event file for the same device, I do have this for my Honeycomb alpha, where the axes are in the joystick file and the rest of the buttons in the event file (which allows me to go beyond the 32 button limitation, yes, you can use this HID way of doing things for devices over 32 buttons).&lt;br /&gt;
&lt;br /&gt;
So let's start writing. First of all, create an empty file called 'YOURDEVCIE.xml' (this is an example and the filename is not relevant as FG will read inside to understand to which device each file belongs (although I name it as the device with '-' just for clarity, for example for the saitek panel ''Logitech-Logitech-Flight-Radio-Panel.xml'' )&lt;br /&gt;
&lt;br /&gt;
Put the XML header:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;PropertyList&amp;gt;&lt;br /&gt;
  &amp;lt;name type=&amp;quot;string&amp;quot;&amp;gt;Logitech Logitech Flight Radio Panel&amp;lt;/name&amp;gt;&lt;br /&gt;
  &amp;lt;debug-events type=&amp;quot;bool&amp;quot;&amp;gt;true&amp;lt;/debug-events&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will indicate FG this is the file for your device, as the ''name'' tag defines it.&lt;br /&gt;
&lt;br /&gt;
If you plan to have some 'logic' in your properties file, add the nasal tags:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;PropertyList&amp;gt;&lt;br /&gt;
  &amp;lt;name type=&amp;quot;string&amp;quot;&amp;gt;Logitech Logitech Flight Radio Panel&amp;lt;/name&amp;gt;&lt;br /&gt;
  &amp;lt;debug-events type=&amp;quot;bool&amp;quot;&amp;gt;true&amp;lt;/debug-events&amp;gt;&lt;br /&gt;
  &amp;lt;nasal&amp;gt;&lt;br /&gt;
    &amp;lt;open&amp;gt;&lt;br /&gt;
      &amp;lt;![CDATA[]]&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Your basic file is starting to get some form. Now we need to start defining what do we do when each of the events is triggered:&lt;br /&gt;
I'm going to paste below the bindings (that's how it's called in FG) for the fact that you have switched the upper selector of the radio panel into 'comm1' mode:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;event&amp;gt;&lt;br /&gt;
    &amp;lt;desc&amp;gt;UK COMM1&amp;lt;/desc&amp;gt;&lt;br /&gt;
    &amp;lt;name&amp;gt;button-1&amp;lt;/name&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknoba&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/selected-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobb&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/standby-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobt&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;5&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
 &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobsw&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frq-swap-btn&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobmax&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;137&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobmin&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;118&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobfstep&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;1&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobhstep&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;0.025&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;script&amp;gt;refreshPanels();&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
  &amp;lt;/event&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Do not be scared by that size! I like to make things generic, so you will see a lot of reference and proxy properties being set that would allow to handle the logic of what happens when we're in 'comm1' mode in the upper panel.&lt;br /&gt;
&lt;br /&gt;
First of all we set the property ''saitek/RP/upknoba'' to ''/instrumentation/comm/frequencies/selected-mhz''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknoba&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/selected-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
We then set the standby frequency to the ''/saitek/RP/upknobb'' property&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobb&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frequencies/standby-mhz&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then the property ''/saitek/RP/upknobt'' to 5, which is the number of digits a frequency has&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobt&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;5&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then the 'swap' button to change frequencies&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/upknobsw&amp;lt;/property&amp;gt;&lt;br /&gt;
      &amp;lt;value&amp;gt;/instrumentation/comm/frq-swap-btn&amp;lt;/value&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
The some max,min and incremental values, and last but not least, I call the refresh panel function (that I've created) to put the proper values in the panels:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;script&amp;gt;refreshPanels();&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
  &amp;lt;/event&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has to be done to every single button in the device, so they act the way you expect them to do. You can check the full file at the bottom of this post.&lt;br /&gt;
&lt;br /&gt;
Ok, so we have the buttons set up, now we want the display to show the proper values:&lt;br /&gt;
&lt;br /&gt;
We use the same tag, event, only that now we have to link a property to the event, so FG will send that value to the output/feature report in the proper position.&lt;br /&gt;
&lt;br /&gt;
Before we continue, remember that in the log, we saw things like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
225.28 [WARN]:input      Unhandled HID generic desktop usage:1&lt;br /&gt;
  225.28 [INFO]:input      Logitech Logitech Flight Radio Panel_0: add:unknown, bits: 0:8, report=0&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
And I did mention that the name that you saw there is the name that should be used for the event, in the case of unknown, you need to add the suffix ''-0'' for the first one, the rest will already have it ''-1, -2,-3 etc..''&lt;br /&gt;
&lt;br /&gt;
Let's add the event to the XML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;event&amp;gt;&lt;br /&gt;
    &amp;lt;desc&amp;gt;RADIO INDICATORS&amp;lt;/desc&amp;gt;&lt;br /&gt;
    &amp;lt;name&amp;gt;unknown-0&amp;lt;/name&amp;gt;&lt;br /&gt;
    &amp;lt;setting&amp;gt;&lt;br /&gt;
      &amp;lt;property&amp;gt;/saitek/RP/ULpanel/digit1&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;/setting&amp;gt;&lt;br /&gt;
  &amp;lt;/event&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
You're telling FlightGear to watch for the property ''/saitek/RP/ULpanel/digit1'' and set its value to the vendor-0 byte.&lt;br /&gt;
&lt;br /&gt;
As you can see there's a strange property there: ''saitek/RP/ULpanel/digit1''. This property is of my choice and you can create any property you want to be sent to the device. Remember that in this particular case, we have a value for each digit, so we cannot send the actual value, we have to slice it so we send each digit in the correct position.&lt;br /&gt;
&lt;br /&gt;
And then again, do the same for the rest of the events.&lt;br /&gt;
&lt;br /&gt;
Once the events have been set and saved, you can launch FG to see if it worked!&lt;br /&gt;
&lt;br /&gt;
Yes! I see the same frequencies in the panel&lt;br /&gt;
[[File:Saitek-working.jpg|thumb|Saitek radio panel working]]&lt;br /&gt;
&lt;br /&gt;
as in the simulator&lt;br /&gt;
[[File:FG-Radio Panel for Saitek.jpg|thumb|Flightgear Cockpit showing radio panel with same values as Saitek radio panel]]&lt;br /&gt;
&lt;br /&gt;
Of course, every time you modify the frequencies in any of the sim or panel, the other one reflects the same value as expected.&lt;br /&gt;
&lt;br /&gt;
You can have a look at [[https://github.com/zayamatias/flightgear/blob/main/.fgfs/Input/Event/Logitech-Logitech-Flight-Radio-Panel.xml]the complete xml file, where you can see I use nasal heavily to do some extra logic, for example, do not turn on the panel unless the contact is set on the aeroplane, how I use the swap button to select the digit when in XPDR mode, and so on. There is no limits to what you can do once you understand the properties and what you're able to do with them.&lt;br /&gt;
&lt;br /&gt;
I hope I have not forgotten anything essential and I also hope this has helped. I'm really looking forward to other devices becoming available in FG.&lt;br /&gt;
&lt;br /&gt;
This also opens the possibility of creating your own devices, have a look at my [https://github.com/zayamatias/flightgear]repo.&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:FG-Radio_Panel_for_Saitek.jpg&amp;diff=139762</id>
		<title>File:FG-Radio Panel for Saitek.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:FG-Radio_Panel_for_Saitek.jpg&amp;diff=139762"/>
		<updated>2024-04-22T15:57:15Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: Uploaded own work with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Flightgear Cockpit showing radio panel with same values as Saitek radio panel}}&lt;br /&gt;
|date=2024-04-22&lt;br /&gt;
|source={{own}}&lt;br /&gt;
|author=[[User:Zayamatias|Zayamatias]]&lt;br /&gt;
|permission=&lt;br /&gt;
|other versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{self|cc-by-sa-4.0}}&lt;br /&gt;
&lt;br /&gt;
[[Category:FlightGear]]&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Saitek-working.jpg&amp;diff=139761</id>
		<title>File:Saitek-working.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Saitek-working.jpg&amp;diff=139761"/>
		<updated>2024-04-22T15:55:57Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: Uploaded own work with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Saitek radio panel working}}&lt;br /&gt;
|date=2024-04-22&lt;br /&gt;
|source={{own}}&lt;br /&gt;
|author=[[User:Zayamatias|Zayamatias]]&lt;br /&gt;
|permission=&lt;br /&gt;
|other versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{self|cc-by-sa-4.0}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Hardware images]]&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Saitek-all-dashes.jpg&amp;diff=139760</id>
		<title>File:Saitek-all-dashes.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Saitek-all-dashes.jpg&amp;diff=139760"/>
		<updated>2024-04-22T15:54:18Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: Uploaded own work with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Saitek radio panel showing al dashes}}&lt;br /&gt;
|date=2024-04-22&lt;br /&gt;
|source={{own}}&lt;br /&gt;
|author=[[User:Zayamatias|Zayamatias]]&lt;br /&gt;
|permission=&lt;br /&gt;
|other versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{self|cc-by-sa-4.0}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Hardware images]]&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Saitek-all-zeroes_and_dots.jpg&amp;diff=139759</id>
		<title>File:Saitek-all-zeroes and dots.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Saitek-all-zeroes_and_dots.jpg&amp;diff=139759"/>
		<updated>2024-04-22T15:52:23Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: Uploaded own work with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=saitek radio panel showing all zeroes and dots}}&lt;br /&gt;
|date=2024-04-22&lt;br /&gt;
|source={{own}}&lt;br /&gt;
|author=[[User:Zayamatias|Zayamatias]]&lt;br /&gt;
|permission=&lt;br /&gt;
|other versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{self|cc-by-sa-4.0}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Hardware images]]&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Saitek-all-ones_and_dots.jpg&amp;diff=139758</id>
		<title>File:Saitek-all-ones and dots.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Saitek-all-ones_and_dots.jpg&amp;diff=139758"/>
		<updated>2024-04-22T15:51:21Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: Uploaded own work with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=saitek radio panel showing all ones and dots}}&lt;br /&gt;
|date=2024-04-22&lt;br /&gt;
|source={{own}}&lt;br /&gt;
|author=[[User:Zayamatias|Zayamatias]]&lt;br /&gt;
|permission=&lt;br /&gt;
|other versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{self|cc-by-sa-4.0}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Hardware images]]&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Saitek-alternate-zeros.jpg&amp;diff=139757</id>
		<title>File:Saitek-alternate-zeros.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Saitek-alternate-zeros.jpg&amp;diff=139757"/>
		<updated>2024-04-22T15:47:56Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: Uploaded own work with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Saitek radio panel showing alternate zeroes and off}}&lt;br /&gt;
|date=2024-04-22&lt;br /&gt;
|source={{own}}&lt;br /&gt;
|author=[[User:Zayamatias|Zayamatias]]&lt;br /&gt;
|permission=&lt;br /&gt;
|other versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{self|cc-by-sa-4.0}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Hardware images]]&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Saitek-all-zeros_first-off.jpg&amp;diff=139756</id>
		<title>File:Saitek-all-zeros first-off.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Saitek-all-zeros_first-off.jpg&amp;diff=139756"/>
		<updated>2024-04-22T15:46:12Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: Uploaded own work with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Saitek radio panel showing all zeros except first digit switched off}}&lt;br /&gt;
|date=2024-04-22&lt;br /&gt;
|source={{own}}&lt;br /&gt;
|author=[[User:Zayamatias|Zayamatias]]&lt;br /&gt;
|permission=&lt;br /&gt;
|other versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{self|cc-by-sa-4.0}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Hardware images]]&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Saitek-all-zeros.jpg&amp;diff=139755</id>
		<title>File:Saitek-all-zeros.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Saitek-all-zeros.jpg&amp;diff=139755"/>
		<updated>2024-04-22T15:44:48Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: Uploaded own work with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Saitek radio panel showing all digits as zeroes}}&lt;br /&gt;
|date=2024-04-22&lt;br /&gt;
|source={{own}}&lt;br /&gt;
|author=[[User:Zayamatias|Zayamatias]]&lt;br /&gt;
|permission=&lt;br /&gt;
|other versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{self|cc-by-sa-4.0}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Hardware images]]&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Saitek-radio-on.jpg&amp;diff=139754</id>
		<title>File:Saitek-radio-on.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Saitek-radio-on.jpg&amp;diff=139754"/>
		<updated>2024-04-22T15:43:26Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: Uploaded own work with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Saitek radio panel with all digits on}}&lt;br /&gt;
|date=2024-04-22&lt;br /&gt;
|source={{own}}&lt;br /&gt;
|author=[[User:Zayamatias|Zayamatias]]&lt;br /&gt;
|permission=&lt;br /&gt;
|other versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{self|cc-by-sa-4.0}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Hardware images]]&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Saitek-radio-off.jpg&amp;diff=139753</id>
		<title>File:Saitek-radio-off.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Saitek-radio-off.jpg&amp;diff=139753"/>
		<updated>2024-04-22T15:42:17Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: Uploaded own work with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Saitek radio panel with a;l digits off}}&lt;br /&gt;
|date=2024-04-22&lt;br /&gt;
|source={{own}}&lt;br /&gt;
|author=[[User:Zayamatias|Zayamatias]]&lt;br /&gt;
|permission=&lt;br /&gt;
|other versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{self|cc-by-sa-4.0}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Hardware images]]&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Hidviz-device-descriptor-fgmod.png&amp;diff=139752</id>
		<title>File:Hidviz-device-descriptor-fgmod.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Hidviz-device-descriptor-fgmod.png&amp;diff=139752"/>
		<updated>2024-04-22T15:36:25Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: Uploaded own work with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Hidvizz showing the fgmod descriptor}}&lt;br /&gt;
|date=2024-04-22&lt;br /&gt;
|source={{own}}&lt;br /&gt;
|author=[[User:Zayamatias|Zayamatias]]&lt;br /&gt;
|permission=&lt;br /&gt;
|other versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{self|cc-by-sa-4.0}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Software]]&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Hidviz-device-descriptor-saitek-radio-panelpng.png&amp;diff=139751</id>
		<title>File:Hidviz-device-descriptor-saitek-radio-panelpng.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Hidviz-device-descriptor-saitek-radio-panelpng.png&amp;diff=139751"/>
		<updated>2024-04-22T15:35:13Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: Uploaded own work with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Hiviz showing the HiD descritpor for the saitek radio panel}}&lt;br /&gt;
|date=2024-04-22&lt;br /&gt;
|source={{own}}&lt;br /&gt;
|author=[[User:Zayamatias|Zayamatias]]&lt;br /&gt;
|permission=&lt;br /&gt;
|other versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{self|cc-by-sa-4.0}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Software]]&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Hidviz-device-selector-2.png&amp;diff=139750</id>
		<title>File:Hidviz-device-selector-2.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Hidviz-device-selector-2.png&amp;diff=139750"/>
		<updated>2024-04-22T15:33:37Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: Uploaded own work with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Device selector from hidviz}}&lt;br /&gt;
|date=2024-04-22&lt;br /&gt;
|source={{own}}&lt;br /&gt;
|author=[[User:Zayamatias|Zayamatias]]&lt;br /&gt;
|permission=&lt;br /&gt;
|other versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{self|cc-by-sa-4.0}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Software]]&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Hidviz-device-selector.png&amp;diff=139749</id>
		<title>File:Hidviz-device-selector.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Hidviz-device-selector.png&amp;diff=139749"/>
		<updated>2024-04-22T15:32:03Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: Uploaded own work with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Screenshot of hidvix tool main screen}}&lt;br /&gt;
|date=2024-04-22&lt;br /&gt;
|source={{own}}&lt;br /&gt;
|author=[[User:Zayamatias|Zayamatias]]&lt;br /&gt;
|permission=&lt;br /&gt;
|other versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{self|cc-by-sa-4.0}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Software]]&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User:Zayamatias&amp;diff=139748</id>
		<title>User:Zayamatias</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User:Zayamatias&amp;diff=139748"/>
		<updated>2024-04-22T15:09:36Z</updated>

		<summary type="html">&lt;p&gt;Zayamatias: Created page with &amp;quot;Hi! Main page&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hi! Main page&lt;/div&gt;</summary>
		<author><name>Zayamatias</name></author>
	</entry>
</feed>