/*---------------------------------------------------------*\ | 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 -1 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 RegisterClientInfoChangeCallback(ClientInfoChangeCallback new_callback, void * new_callback_arg); 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 UnregisterClientInfoChangeCallback(ClientInfoChangeCallback 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 ClientInfoChanged(); void DeviceListChanged(); void DetectionProgressChanged(); void I2CBusListChanged(); void Initialize(bool tryConnect, bool detectDevices, bool startServer, bool applyPostOptions); void Cleanup(); void DetectDevices(); void DisableDetection(); void RescanDevices(); 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 active flag | \*-----------------------------------------------------*/ bool auto_connection_active; /*-----------------------------------------------------*\ | Auto connection client pointer | \*-----------------------------------------------------*/ NetworkClient * auto_connection_client; /*-----------------------------------------------------*\ | 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; /*-----------------------------------------------------*\ | NOTE: wakes up the background detection thread | \*-----------------------------------------------------*/ std::condition_variable BackgroundFunctionStartTrigger; 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; /*-----------------------------------------------------*\ | Client Info Changed Callback | \*-----------------------------------------------------*/ std::vector ClientInfoChangeCallbacks; std::vector ClientInfoChangeCallbackArgs; /*-----------------------------------------------------*\ | 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; /*-----------------------------------------------------*\ | OpenRGB configuration directory path | \*-----------------------------------------------------*/ filesystem::path config_dir; };