/*---------------------------------------------------------*\ | ResourceManager.h | | | | OpenRGB Resource Manager controls access to application | | components including RGBControllers, I2C interfaces, | | and network SDK components | | | | Adam Honse (CalcProgrammer1) 27 Sep 2020 | | | | This file is part of the OpenRGB project | | SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ #pragma once #include #include #include #include #include #include #include "SPDWrapper.h" #include "hidapi_wrapper.h" #include "i2c_smbus.h" #include "ResourceManagerInterface.h" #include "filesystem.h" #include using json = nlohmann::json; #define HID_INTERFACE_ANY -1 #define HID_USAGE_ANY -1 #define HID_USAGE_PAGE_ANY -1L #define CONTROLLER_LIST_HID 0 struct hid_device_info; class NetworkClient; class NetworkServer; class ProfileManager; class RGBController; class SettingsManager; typedef std::function I2CBusDetectorFunction; typedef std::function DeviceDetectorFunction; typedef std::function&)> I2CDeviceDetectorFunction; typedef std::function&)> I2CDIMMDeviceDetectorFunction; typedef std::function I2CPCIDeviceDetectorFunction; typedef std::function HIDDeviceDetectorFunction; typedef std::function HIDWrappedDeviceDetectorFunction; typedef std::function DynamicDetectorFunction; typedef std::function PreDetectionHookFunction; class BasicHIDBlock { public: std::string name; uint16_t vid; uint16_t pid; int interface; int usage_page; int usage; bool compare(hid_device_info* info); }; class HIDDeviceDetectorBlock : public BasicHIDBlock { public: HIDDeviceDetectorFunction function; }; class HIDWrappedDeviceDetectorBlock : public BasicHIDBlock { public: HIDWrappedDeviceDetectorFunction function; }; typedef struct { std::string name; I2CPCIDeviceDetectorFunction function; uint16_t ven_id; uint16_t dev_id; uint16_t subven_id; uint16_t subdev_id; uint8_t i2c_addr; } I2CPCIDeviceDetectorBlock; typedef struct { std::string name; I2CDIMMDeviceDetectorFunction function; uint16_t jedec_id; uint8_t dimm_type; } I2CDIMMDeviceDetectorBlock; /*-------------------------------------------------------------------------*\ | Define a macro for QT lupdate to parse | \*-------------------------------------------------------------------------*/ #define QT_TRANSLATE_NOOP(scope, x) x extern const char* I2C_ERR_WIN; extern const char* I2C_ERR_LINUX; extern const char* UDEV_MISSING; extern const char* UDEV_MULTI; class ResourceManager: public ResourceManagerInterface { public: static ResourceManager *get(); ResourceManager(); ~ResourceManager(); void RegisterI2CBus(i2c_smbus_interface *); std::vector & GetI2CBusses(); void RegisterRGBController(RGBController *rgb_controller); void UnregisterRGBController(RGBController *rgb_controller); std::vector & GetRGBControllers(); void RegisterI2CBusDetector (I2CBusDetectorFunction detector); void RegisterDeviceDetector (std::string name, DeviceDetectorFunction detector); void RegisterI2CDeviceDetector (std::string name, I2CDeviceDetectorFunction detector); void RegisterI2CDIMMDeviceDetector (std::string name, I2CDIMMDeviceDetectorFunction detector, uint16_t jedec_id, uint8_t dimm_type); void RegisterI2CPCIDeviceDetector (std::string name, I2CPCIDeviceDetectorFunction detector, uint16_t ven_id, uint16_t dev_id, uint16_t subven_id, uint16_t subdev_id, uint8_t i2c_addr); void RegisterHIDDeviceDetector (std::string name, HIDDeviceDetectorFunction detector, uint16_t vid, uint16_t pid, int interface = HID_INTERFACE_ANY, int usage_page = HID_USAGE_PAGE_ANY, int usage = HID_USAGE_ANY); void RegisterHIDWrappedDeviceDetector (std::string name, HIDWrappedDeviceDetectorFunction detector, uint16_t vid, uint16_t pid, int interface = HID_INTERFACE_ANY, int usage_page = HID_USAGE_PAGE_ANY, int usage = HID_USAGE_ANY); void RegisterDynamicDetector (std::string name, DynamicDetectorFunction detector); void RegisterPreDetectionHook (PreDetectionHookFunction hook); void RegisterDeviceListChangeCallback(DeviceListChangeCallback new_callback, void * new_callback_arg); void RegisterDetectionProgressCallback(DetectionProgressCallback new_callback, void * new_callback_arg); void RegisterDetectionStartCallback(DetectionStartCallback new_callback, void * new_callback_arg); void RegisterDetectionEndCallback(DetectionEndCallback new_callback, void * new_callback_arg); void RegisterI2CBusListChangeCallback(I2CBusListChangeCallback new_callback, void * new_callback_arg); void UnregisterDeviceListChangeCallback(DeviceListChangeCallback callback, void * callback_arg); void UnregisterDetectionProgressCallback(DetectionProgressCallback callback, void *callback_arg); void UnregisterDetectionStartCallback(DetectionStartCallback callback, void *callback_arg); void UnregisterDetectionEndCallback(DetectionEndCallback callback, void *callback_arg); void UnregisterI2CBusListChangeCallback(I2CBusListChangeCallback callback, void * callback_arg); bool GetDetectionEnabled(); unsigned int GetDetectionPercent(); const char* GetDetectionString(); filesystem::path GetConfigurationDirectory(); void RegisterNetworkClient(NetworkClient* new_client); void UnregisterNetworkClient(NetworkClient* network_client); std::vector& GetClients(); NetworkServer* GetServer(); ProfileManager* GetProfileManager(); SettingsManager* GetSettingsManager(); void SetConfigurationDirectory(const filesystem::path &directory); void ProcessPreDetectionHooks(); // Consider making private void ProcessDynamicDetectors(); // Consider making private void UpdateDeviceList(); void DeviceListChanged(); void DetectionProgressChanged(); void I2CBusListChanged(); void Initialize(bool tryConnect, bool detectDevices, bool startServer, bool applyPostOptions); void Cleanup(); void DetectDevices(); void DisableDetection(); void StopDeviceDetection(); void WaitForInitialization(); void WaitForDeviceDetection(); private: void UpdateDetectorSettings(); void SetupConfigurationDirectory(); bool AttemptLocalConnection(); bool ProcessPreDetection(); void ProcessPostDetection(); bool IsAnyDimmDetectorEnabled(json &detector_settings); void RunInBackgroundThread(std::function); void BackgroundThreadFunction(); /*-------------------------------------------------------------------------------------*\ | Functions that must be run in the background thread | | These are not related to STL coroutines, yet this name is the most convenient | \*-------------------------------------------------------------------------------------*/ void InitCoroutine(); void DetectDevicesCoroutine(); void HidExitCoroutine(); /*-------------------------------------------------------------------------------------*\ | Static pointer to shared instance of ResourceManager | \*-------------------------------------------------------------------------------------*/ static ResourceManager* instance; /*-------------------------------------------------------------------------------------*\ | Auto connection permitting flag | \*-------------------------------------------------------------------------------------*/ bool tryAutoConnect; /*-------------------------------------------------------------------------------------*\ | Detection enabled flag | \*-------------------------------------------------------------------------------------*/ bool detection_enabled; /*-------------------------------------------------------------------------------------*\ | Auto connection permitting flag | \*-------------------------------------------------------------------------------------*/ bool start_server; /*-------------------------------------------------------------------------------------*\ | Auto connection permitting flag | \*-------------------------------------------------------------------------------------*/ bool apply_post_options; /*-------------------------------------------------------------------------------------*\ | Initialization completion flag | \*-------------------------------------------------------------------------------------*/ std::atomic init_finished; /*-------------------------------------------------------------------------------------*\ | Profile Manager | \*-------------------------------------------------------------------------------------*/ ProfileManager* profile_manager; /*-------------------------------------------------------------------------------------*\ | Settings Manager | \*-------------------------------------------------------------------------------------*/ SettingsManager* settings_manager; /*-------------------------------------------------------------------------------------*\ | I2C/SMBus Interfaces | \*-------------------------------------------------------------------------------------*/ std::vector busses; /*-------------------------------------------------------------------------------------*\ | RGBControllers | \*-------------------------------------------------------------------------------------*/ std::vector rgb_controllers_sizes; std::vector rgb_controllers_hw; std::vector rgb_controllers; /*-------------------------------------------------------------------------------------*\ | Network Server | \*-------------------------------------------------------------------------------------*/ NetworkServer* server; /*-------------------------------------------------------------------------------------*\ | Network Clients | \*-------------------------------------------------------------------------------------*/ std::vector clients; /*-------------------------------------------------------------------------------------*\ | Detectors | \*-------------------------------------------------------------------------------------*/ std::vector device_detectors; std::vector device_detector_strings; std::vector i2c_bus_detectors; std::vector i2c_device_detectors; std::vector i2c_device_detector_strings; std::vector i2c_dimm_device_detectors; std::vector i2c_pci_device_detectors; std::vector hid_device_detectors; std::vector hid_wrapped_device_detectors; std::vector dynamic_detectors; std::vector dynamic_detector_strings; std::vector pre_detection_hooks; bool dynamic_detectors_processed; /*-------------------------------------------------------------------------------------*\ | Detection Thread and Detection State | \*-------------------------------------------------------------------------------------*/ std::thread * DetectDevicesThread; std::mutex DetectDeviceMutex; std::function ScheduledBackgroundFunction; std::mutex BackgroundThreadStateMutex; std::condition_variable BackgroundFunctionStartTrigger; // NOTE: wakes up the background detection thread std::atomic background_thread_running; std::atomic detection_is_required; std::atomic detection_percent; std::atomic detection_prev_size; std::vector detection_size_entry_used; const char* detection_string; /*-------------------------------------------------------------------------------------*\ | Device List Changed Callback | \*-------------------------------------------------------------------------------------*/ std::mutex DeviceListChangeMutex; std::vector DeviceListChangeCallbacks; std::vector DeviceListChangeCallbackArgs; /*-------------------------------------------------------------------------------------*\ | Detection Progress, Start, and End Callbacks | \*-------------------------------------------------------------------------------------*/ std::mutex DetectionProgressMutex; std::vector DetectionProgressCallbacks; std::vector DetectionProgressCallbackArgs; std::vector DetectionStartCallbacks; std::vector DetectionStartCallbackArgs; std::vector DetectionEndCallbacks; std::vector DetectionEndCallbackArgs; /*-------------------------------------------------------------------------------------*\ | I2C/SMBus Adapter List Changed Callback | \*-------------------------------------------------------------------------------------*/ std::mutex I2CBusListChangeMutex; std::vector I2CBusListChangeCallbacks; std::vector I2CBusListChangeCallbackArgs; filesystem::path config_dir; };