Build udev from DetectionManager

This commit is contained in:
Adam Honse
2026-08-20 10:37:46 -05:00
parent 8121ee29f4
commit 33854f8886
4 changed files with 140 additions and 0 deletions
+106
View File
@@ -11,6 +11,8 @@
\*---------------------------------------------------------*/
#include <chrono>
#include <cctype>
#include <cstdio>
#include "DetectionManager.h"
#include "JsonUtils.h"
#include "LogManager.h"
@@ -2068,3 +2070,107 @@ bool DetectionManager::IsAnyDimmDetectorEnabled(json &detector_settings)
}
return false;
}
#ifdef __linux__
/*---------------------------------------------------------*\
| Udev rules generation function |
\*---------------------------------------------------------*/
bool DetectionManager::GenerateUdevRules(const std::string& filepath)
{
LOG_INFO("[%s] Generating udev rules file: %s", DETECTIONMANAGER, filepath.c_str());
FILE* output_file = fopen(filepath.c_str(), "w");
if(!output_file)
{
LOG_ERROR("[%s] Failed to open output file: %s", DETECTIONMANAGER, filepath.c_str());
return false;
}
/*-----------------------------------------------------*\
| Write udev rules header |
\*-----------------------------------------------------*/
fprintf(output_file, "#---------------------------------------------------------------#\n");
fprintf(output_file, "# OpenRGB udev rules - Generated by DetectionManager #\n");
fprintf(output_file, "#---------------------------------------------------------------#\n");
fprintf(output_file, "\n");
fprintf(output_file, "#---------------------------------------------------------------#\n");
fprintf(output_file, "# User I2C/SMBus Access #\n");
fprintf(output_file, "#---------------------------------------------------------------#\n");
fprintf(output_file, "KERNEL==\"i2c-[0-99]*\", TAG+=\"uaccess\"\n");
fprintf(output_file, "\n");
fprintf(output_file, "#---------------------------------------------------------------#\n");
fprintf(output_file, "# Super I/O Access #\n");
fprintf(output_file, "#---------------------------------------------------------------#\n");
fprintf(output_file, "KERNEL==\"port\", TAG+=\"uaccess\"\n");
fprintf(output_file, "\n");
/*-----------------------------------------------------*\
| Group detectors by name to avoid duplicate headers |
\*-----------------------------------------------------*/
std::map<std::string, std::vector<std::pair<uint16_t, uint16_t>>> detector_groups;
for(std::size_t detector_idx = 0; detector_idx < hid_specific_detectors.size(); detector_idx++)
{
HIDDeviceDetectorBlock& detector = hid_specific_detectors[detector_idx];
if(detector.vid == HID_VID_ANY || detector.pid == HID_PID_ANY)
{
continue;
}
detector_groups[detector.name].push_back({(uint16_t)detector.vid, (uint16_t)detector.pid});
}
for(std::size_t detector_idx = 0; detector_idx < hid_wrapped_specific_detectors.size(); detector_idx++)
{
HIDWrappedDeviceDetectorBlock& detector = hid_wrapped_specific_detectors[detector_idx];
if(detector.vid == HID_VID_ANY || detector.pid == HID_PID_ANY)
{
continue;
}
std::string group_name = detector.name + " (libusb)";
detector_groups[group_name].push_back({(uint16_t)detector.vid, (uint16_t)detector.pid});
}
/*-----------------------------------------------------*\
| Write grouped HID device rules |
\*-----------------------------------------------------*/
for(const std::pair<const std::string, std::vector<std::pair<uint16_t, uint16_t>>>& group : detector_groups)
{
fprintf(output_file, "#---------------------------------------------------------------#\n");
fprintf(output_file, "# %s\n", group.first.c_str());
fprintf(output_file, "#---------------------------------------------------------------#\n");
std::string device_name_tag = group.first;
for(auto it = device_name_tag.begin(); it != device_name_tag.end();)
{
if(*it == ' ')
{
*it = '_';
++it;
}
else if(!isalnum(*it))
{
it = device_name_tag.erase(it);
}
else
{
++it;
}
}
for(const std::pair<uint16_t, uint16_t>& vid_pid : group.second)
{
fprintf(output_file, "SUBSYSTEMS==\"usb|hidraw\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", TAG+=\"uaccess\", TAG+=\"%s\"\n", vid_pid.first, vid_pid.second, device_name_tag.c_str());
}
fprintf(output_file, "\n");
}
fclose(output_file);
LOG_INFO("[%s] Successfully generated udev rules file: %s", DETECTIONMANAGER, filepath.c_str());
return true;
}
#endif
+7
View File
@@ -205,6 +205,13 @@ public:
std::string GetDetectionString();
void WaitForDetection();
#ifdef __linux__
/*-----------------------------------------------------*\
| Udev rules generation function |
\*-----------------------------------------------------*/
bool GenerateUdevRules(const std::string& filepath);
#endif
private:
/*-----------------------------------------------------*\
| Static pointer to shared instance of DetectionManager |
+26
View File
@@ -22,6 +22,10 @@
#include "ResourceManager.h"
#include "RGBController.h"
#ifdef __linux__
#include "DetectionManager.h"
#endif
/*---------------------------------------------------------*\
| Quirk for MSVC; which doesn't support this |
| case-insensitive function |
@@ -452,6 +456,9 @@ void OptionHelp()
help_text += "--autostart-check Check if OpenRGB starting at login is enabled.\n";
help_text += "--autostart-disable Disable OpenRGB starting at login.\n";
help_text += "--autostart-enable arguments Enable OpenRGB to start at login. Requires arguments to give to OpenRGB at login.\n";
#ifdef __linux__
help_text += "--generate-udev-rules [filename] Generate the OpenRGB udev rules file and save it to the given filename.\n";
#endif
std::cout << help_text << std::endl;
}
@@ -957,6 +964,13 @@ bool OptionSaveProfile(std::string argument)
return(true);
}
#ifdef __linux__
void OptionGenerateUdevRules(std::string argument)
{
DetectionManager::get()->GenerateUdevRules(argument);
}
#endif
int ProcessOptions(Options* options, std::vector<RGBController *>& rgb_controllers)
{
unsigned int ret_flags = 0;
@@ -1134,6 +1148,18 @@ int ProcessOptions(Options* options, std::vector<RGBController *>& rgb_controlle
arg_index++;
}
#ifdef __linux__
/*-------------------------------------------------*\
| --generate-udev-rules |
\*-------------------------------------------------*/
else if(option == "--generate-udev-rules")
{
OptionGenerateUdevRules(arg_path.generic_u8string());
arg_index++;
}
#endif
/*-------------------------------------------------*\
| Invalid option |
\*-------------------------------------------------*/
+1
View File
@@ -26,4 +26,5 @@ enum
RET_FLAG_CLI_POST_DETECTION = 32,
RET_FLAG_START_SERVER = 64,
RET_FLAG_NO_AUTO_CONNECT = 128,
RET_FLAG_GENERATE_UDEV_RULES = 256,
};