2 extern crate windows_service
;
9 atomic
::{AtomicBool
, Ordering
},
13 time
::{self, Duration
},
17 use log
::{debug
, error
, info
, trace
, warn
};
18 use windows
::Win32
::Foundation
::{ERROR_SERVICE_DOES_NOT_EXIST
, WIN32_ERROR
};
19 use windows_service
::{
21 ServiceAccess
, ServiceControl
, ServiceControlAccept
, ServiceErrorControl
, ServiceExitCode
,
22 ServiceInfo
, ServiceStartType
, ServiceState
, ServiceStatus
, ServiceType
,
24 service_control_handler
::{self, ServiceControlHandlerResult
, ServiceStatusHandle
},
26 service_manager
::{ServiceManager
, ServiceManagerAccess
},
28 use wmi
::{COMLibrary
, Variant
, WMIConnection
};
32 define_windows_service!(ffi_service_main
, service_main
);
35 #![allow(warnings, unused)]
36 include!(concat!(env!("OUT_DIR"), "/ols_api.rs"));
40 #![allow(warnings, unused)]
41 include!(concat!(env!("OUT_DIR"), "/intel_arc.rs"));
50 mod corsair_vengeance
;
53 // mod roccat; Disabled.
58 fn main() -> Result
<()> {
59 let is_debug
= cfg!(debug_assertions
);
61 flexi_logger
::Logger
::try_with_str(if is_debug
{ "debug" } else { "info" })?
63 flexi_logger
::FileSpec
::default()
64 .directory(dirs
::config_dir().unwrap().join(consts
::SERVICE_NAME
))
65 .basename(consts
::SERVICE_NAME
),
67 .duplicate_to_stdout(flexi_logger
::Duplicate
::All
)
69 flexi_logger
::default_format
71 flexi_logger
::detailed_format
74 flexi_logger
::Criterion
::Size(1024 * 1024),
75 flexi_logger
::Naming
::Timestamps
,
76 flexi_logger
::Cleanup
::KeepLogFiles(10),
81 let args
: Vec
<String
> = env
::args().collect();
83 info!("Temperature to RGB");
85 if args
.contains(&"--no-service".to_string()) {
86 let completed
: Arc
<AtomicBool
> = Arc
::new(AtomicBool
::new(false));
87 main_loop
::main_loop(completed
.clone());
88 } else if args
.contains(&"--tests".to_string()) {
90 } else if args
.contains(&"--install-service".to_string()) {
91 println!("Installing service...");
93 } else if args
.contains(&"--uninstall-service".to_string()) {
94 println!("Uninstalling service...");
97 service_dispatcher
::start(consts
::SERVICE_NAME
, ffi_service_main
)?
;
103 fn install_service() -> windows_service
::Result
<()> {
104 let manager_access
= ServiceManagerAccess
::CONNECT
| ServiceManagerAccess
::CREATE_SERVICE
;
105 let service_manager
= ServiceManager
::local_computer(None
::<&str>, manager_access
)?
;
107 let service_binary_path
= std
::env
::current_exe()
109 .with_file_name("temp_2_rgb.exe");
111 println!("Installing service: {service_binary_path:?}");
113 let service_info
= ServiceInfo
{
114 name
: OsString
::from(consts
::SERVICE_NAME
),
115 display_name
: OsString
::from(consts
::SERVICE_NAME
),
116 service_type
: ServiceType
::OWN_PROCESS
,
117 start_type
: ServiceStartType
::AutoStart
,
118 error_control
: ServiceErrorControl
::Normal
,
119 executable_path
: service_binary_path
,
120 launch_arguments
: vec
![],
121 dependencies
: vec
![],
122 account_name
: None
, // run as System
123 account_password
: None
,
125 let service
= service_manager
.create_service(&service_info
, ServiceAccess
::CHANGE_CONFIG
)?
;
126 service
.set_description(
127 "A service to set the color of hardware according to the temperature of GPU and CPU",
132 fn uninstall_service() -> windows_service
::Result
<()> {
133 let manager_access
= ServiceManagerAccess
::CONNECT
;
134 let service_manager
= ServiceManager
::local_computer(None
::<&str>, manager_access
)?
;
136 let service_access
= ServiceAccess
::QUERY_STATUS
| ServiceAccess
::STOP
| ServiceAccess
::DELETE
;
137 let service
= service_manager
.open_service(consts
::SERVICE_NAME
, service_access
)?
;
139 // The service will be marked for deletion as long as this function call succeeds.
140 // However, it will not be deleted from the database until it is stopped and all open handles to it are closed.
143 // Our handle to it is not closed yet. So we can still query it.
144 if service
.query_status()?
.current_state
!= ServiceState
::Stopped
{
145 // If the service cannot be stopped, it will be deleted when the system restarts.
149 // Explicitly close our open handle to the service. This is automatically called when `service` goes out of scope.
152 // Win32 API does not give us a way to wait for service deletion.
153 // To check if the service is deleted from the database, we have to poll it ourselves.
154 let start
= time
::Instant
::now();
155 let timeout
= Duration
::from_secs(5);
156 while start
.elapsed() < timeout
{
157 if let Err(windows_service
::Error
::Winapi(e
)) =
158 service_manager
.open_service(consts
::SERVICE_NAME
, ServiceAccess
::QUERY_STATUS
)
160 let WIN32_ERROR(error_num
) = ERROR_SERVICE_DOES_NOT_EXIST
;
161 if e
.raw_os_error() == Some(error_num
as i32) {
162 println!("{} is deleted.", consts
::SERVICE_NAME
);
166 sleep(Duration
::from_secs(1));
168 println!("{} is marked for deletion.", consts
::SERVICE_NAME
);
173 fn service_main(arguments
: Vec
<OsString
>) {
174 if let Err(error
) = run_service(arguments
) {
179 fn run_service(_arguments
: Vec
<OsString
>) -> Result
<(), windows_service
::Error
> {
180 let completed
: Arc
<AtomicBool
> = Arc
::new(AtomicBool
::new(false));
182 let completed_event_handler
= Arc
::clone(&completed
);
184 info!("Setuping the event handler...");
186 let event_handler
= move |control_event
| -> ServiceControlHandlerResult
{
187 match control_event
{
188 ServiceControl
::Stop
=> {
189 completed_event_handler
.store(true, Ordering
::Relaxed
);
190 // Handle stop event and return control back to the system.
191 ServiceControlHandlerResult
::NoError
193 ServiceControl
::Shutdown
=> {
194 completed_event_handler
.store(true, Ordering
::Relaxed
);
195 // Handle stop event and return control back to the system.
196 ServiceControlHandlerResult
::NoError
198 // ServiceControl::Preshutdown => {
199 // completed_event_handler.store(true, Ordering::Relaxed);
200 // ServiceControlHandlerResult::NoError
202 // ServiceControl::PowerEvent(param) => {
203 // ServiceControlHandlerResult::NotImplemented
205 // All services must accept Interrogate even if it's a no-op.
206 ServiceControl
::Interrogate
=> ServiceControlHandlerResult
::NoError
,
207 _
=> ServiceControlHandlerResult
::NotImplemented
,
211 // Register system service event handler
212 let status_handle
= service_control_handler
::register(consts
::SERVICE_NAME
, event_handler
)?
;
214 status_handle
.set_service_status(ServiceStatus
{
215 service_type
: ServiceType
::OWN_PROCESS
,
216 current_state
: ServiceState
::Running
,
217 controls_accepted
: ServiceControlAccept
::STOP
| ServiceControlAccept
::SHUTDOWN
,
218 exit_code
: ServiceExitCode
::Win32(0),
220 wait_hint
: Duration
::default(),
221 process_id
: None
, //Some(std::process::id()),
224 main_loop
::main_loop(completed
.clone());
226 status_handle
.set_service_status(ServiceStatus
{
227 service_type
: ServiceType
::OWN_PROCESS
,
228 current_state
: ServiceState
::Stopped
,
229 controls_accepted
: ServiceControlAccept
::empty(),
230 exit_code
: ServiceExitCode
::Win32(0),
232 wait_hint
: Duration
::default(),
233 process_id
: None
, //Some(std::process::id()),
236 info!("Main loop stopped: Temperature to RGB will now shut down");
242 println!("Running some tests...");
245 // list_usb_devices();
252 println!("Press any key to continue...");
253 std
::io
::stdin().read_line(&mut String
::new()).unwrap();
257 let com_con
= COMLibrary
::new().unwrap();
258 let wmi_con
= WMIConnection
::new(com_con
.into()).unwrap();
260 //let results: Vec<HashMap<String, Variant>> = wmi_con.raw_query("SELECT * FROM Win32_PnPSignedDriver WHERE Description LIKE '%SMBUS%' OR Description LIKE '%SM BUS%'").unwrap();
261 //let results: Vec<HashMap<String, Variant>> = wmi_con.raw_query("SELECT * FROM Win32_PnPSignedDriver WHERE Description LIKE 'Intel(R) NF I2C Host Controller'").unwrap();
262 let results
: Vec
<HashMap
<String
, Variant
>> = wmi_con
263 .raw_query("SELECT * FROM Win32_PnPSignedDriver")
265 //let results: Vec<HashMap<String, Variant>> = wmi_con.raw_query("SELECT * FROM Win32_PnPAllocatedResource").unwrap();
268 println!("-------------------");
269 println!("{:#?}", os
);
272 fn list_usb_devices() {
273 let api
= hidapi
::HidApi
::new().unwrap();
274 for device
in api
.device_list() {
275 println!("{:?}", device
);
276 println!("name: {}", device
.product_string().unwrap());
277 println!("interface number: {}", device
.interface_number());
278 println!("page: {}", device
.usage_page());
279 println!("usage: {}", device
.usage());
284 // fn test_roccat() {
285 // let api = hidapi::HidApi::new().unwrap();
286 // let roccat_device = roccat::get_device(&api);
288 // let manufacturer = roccat_device.get_manufacturer_string().unwrap();
289 // dbg!(manufacturer);
291 // let product = roccat_device.get_product_string().unwrap();
294 // let serial = roccat_device.get_serial_number_string().unwrap();
297 // roccat::init(&roccat_device);
298 // roccat::set_color(
309 let api
= hidapi
::HidApi
::new().unwrap();
311 let b650e_device
= b650_e
::get_device(&api
);
313 println!("Firmware: {}", b650_e
::get_firmware_string(&b650e_device
));
315 let configuration
= b650_e
::get_configuration_table(&b650e_device
);
316 println!("Configuration:");
318 print!("{:02X} ", configuration
[i
]);
319 if (i
+ 1) % 6 == 0 {
324 // Only once, at start.
325 b650_e
::set_fixed_mode(&b650e_device
);
335 b650_e
::save_current_color(&b650e_device
);
339 let corsair_controllers
= [
340 corsair_vengeance
::Controller
::new(0x19),
341 corsair_vengeance
::Controller
::new(0x1B),
343 for controller
in corsair_controllers
{
344 controller
.set_color(&RGB
{
353 // a770::set_rgb(255, 0, 0);
354 let mut a770
= a770
::A770
::new();
355 a770
.set_color(255, 0, 0);
358 fn test_read_temp() {
359 let sensors
= sensors_jiji
::Sensors
::new();
360 println!("temp cpu: {}", sensors
.read_cpu_temp());
361 println!("temp gpu: {}", sensors
.read_gpu_temp());