mirror of
https://github.com/miskcoo/ugreen_dx4600_leds_controller.git
synced 2025-07-22 20:10:36 +02:00
Squashed commit of the following:
commit 48ad47c2cb990c7550325e798064cfab612c3e7e
Author: Yuhao Zhou <miskcoo@gmail.com>
Date: Fri Jun 7 01:51:01 2024 +0800
update README.md
commit 576cc1e21d629e83ac589cd7f806698814da4858
Author: Yuhao Zhou <miskcoo@gmail.com>
Date: Fri Jun 7 01:23:31 2024 +0800
update makefiles
commit 577e2fc326df4d8edc8c303a89bde89ceca90949
Author: Yuhao Zhou <miskcoo@gmail.com>
Date: Fri Jun 7 00:29:26 2024 +0800
change the i2c device name
commit 303a05e1f4695dcc0bc117c412b0e668dd7bb2a5
Author: Yuhao Zhou <miskcoo@gmail.com>
Date: Thu Jun 6 22:46:18 2024 +0800
add the status attribute
commit ca1a51522b9ad28b04dc12d6012994bc6dce022c
Author: Yuhao Zhou <miskcoo@gmail.com>
Date: Thu Jun 6 22:34:33 2024 +0800
fix including filename
commit 4684bd1aaaa0de089537686d65caee4352df3bcf
Author: Yuhao Zhou <miskcoo@gmail.com>
Date: Thu Jun 6 22:18:11 2024 +0800
add dkms.conf
commit 4925eec10259c5c626c9459a65a7abeb115c4050
Author: Yuhao Zhou <miskcoo@gmail.com>
Date: Thu Jun 6 19:35:37 2024 +0800
Update the manual of the kernel module
commit e07f1570efab507221092d9f2d09d6b98e32f2eb
Author: Yuhao Zhou <miskcoo@gmail.com>
Date: Thu Jun 6 16:25:30 2024 +0800
add a netdev monitoring script
commit 813884f0bd928424b3e5be9053a7cc9289ab2263
Author: Yuhao Zhou <miskcoo@gmail.com>
Date: Thu Jun 6 15:33:28 2024 +0800
support blink and breath
commit 991db7c11521a2b7e2f841bf5916ff58003b951a
Merge: a4e540c c3e6324
Author: Yuhao Zhou <miskcoo@gmail.com>
Date: Thu Jun 6 13:35:16 2024 +0800
Merge branch 'master' into kmod
commit a4e540cbbde41d6a8570881a85bbfebab9def1ad
Author: Yuhao Zhou <miskcoo@gmail.com>
Date: Thu Jun 6 13:20:28 2024 +0800
add a script of monitoring diskio
commit 5b65173ec68d2a9ebc952d120935e0f533f6760f
Author: Yuhao Zhou <miskcoo@gmail.com>
Date: Wed Jun 5 23:26:09 2024 +0800
add a kernel driver of leds
139 lines
4.0 KiB
C++
139 lines
4.0 KiB
C++
#include "ugreen_leds.h"
|
|
#include <string>
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
|
|
#define I2C_DEV_PATH "/sys/class/i2c-dev/"
|
|
|
|
int ugreen_leds_t::start() {
|
|
namespace fs = std::filesystem;
|
|
|
|
if (!fs::exists(I2C_DEV_PATH))
|
|
return -1;
|
|
|
|
for (const auto& entry : fs::directory_iterator(I2C_DEV_PATH)) {
|
|
if (entry.is_directory()) {
|
|
std::ifstream ifs(entry.path() / "device/name");
|
|
std::string line;
|
|
std::getline(ifs, line);
|
|
|
|
if (line.rfind("SMBus I801 adapter", 0) == 0) {
|
|
const auto i2c_dev = "/dev/" + entry.path().filename().string();
|
|
return _i2c.start(i2c_dev.c_str(), UGREEN_LED_I2C_ADDR);
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static int compute_checksum(const std::vector<uint8_t>& data, int size) {
|
|
if (size < 2 || size > (int)data.size())
|
|
return 0;
|
|
|
|
int sum = 0;
|
|
for (int i = 0; i < size; ++i)
|
|
sum += (int)data[i];
|
|
|
|
return sum;
|
|
}
|
|
|
|
static bool verify_checksum(const std::vector<uint8_t>& data) {
|
|
int size = data.size();
|
|
if (size < 2) return false;
|
|
int sum = compute_checksum(data, size - 2);
|
|
return sum != 0 && sum == (data[size - 1] | (((int)data[size - 2]) << 8));
|
|
}
|
|
|
|
static void append_checksum(std::vector<uint8_t>& data) {
|
|
int size = data.size();
|
|
int sum = compute_checksum(data, size);
|
|
data.push_back((sum >> 8) & 0xff);
|
|
data.push_back(sum & 0xff);
|
|
}
|
|
|
|
ugreen_leds_t::led_data_t ugreen_leds_t::get_status(led_type_t id) {
|
|
led_data_t data { };
|
|
data.is_available = false;
|
|
|
|
auto raw_data = _i2c.read_block_data(0x81 + (uint8_t)id, 0xb);
|
|
if (raw_data.size() != 0xb || !verify_checksum(raw_data))
|
|
return data;
|
|
|
|
switch (raw_data[0]) {
|
|
case 0: data.op_mode = op_mode_t::off; break;
|
|
case 1: data.op_mode = op_mode_t::on; break;
|
|
case 2: data.op_mode = op_mode_t::blink; break;
|
|
case 3: data.op_mode = op_mode_t::breath; break;
|
|
default: return data;
|
|
};
|
|
|
|
|
|
data.brightness = raw_data[1];
|
|
data.color_r = raw_data[2];
|
|
data.color_g = raw_data[3];
|
|
data.color_b = raw_data[4];
|
|
int t_hight = (((int)raw_data[5]) << 8) | raw_data[6];
|
|
int t_low = (((int)raw_data[7]) << 8) | raw_data[8];
|
|
data.t_on = t_low;
|
|
data.t_off = t_hight - t_low;
|
|
data.is_available = true;
|
|
|
|
return data;
|
|
}
|
|
|
|
int ugreen_leds_t::_change_status(led_type_t id, uint8_t command, std::array<std::optional<uint8_t>, 4> params) {
|
|
std::vector<uint8_t> data {
|
|
// 3c 3b 3a
|
|
0x00, 0xa0, 0x01,
|
|
// 39 38 37
|
|
0x00, 0x00, command,
|
|
// 36 - 33
|
|
params[0].value_or(0x00),
|
|
params[1].value_or(0x00),
|
|
params[2].value_or(0x00),
|
|
params[3].value_or(0x00),
|
|
};
|
|
|
|
append_checksum(data);
|
|
data[0] = (uint8_t)id;
|
|
return _i2c.write_block_data((uint8_t)id, data);
|
|
}
|
|
|
|
int ugreen_leds_t::set_onoff(led_type_t id, uint8_t status) {
|
|
if (status >= 2) return -1;
|
|
return _change_status(id, 0x03, { status } );
|
|
}
|
|
|
|
int ugreen_leds_t::_set_blink_or_breath(uint8_t command, led_type_t id, uint16_t t_on, uint16_t t_off) {
|
|
uint16_t t_hight = t_on + t_off;
|
|
uint16_t t_low = t_on;
|
|
return _change_status(id, command, {
|
|
(uint8_t)(t_hight >> 8),
|
|
(uint8_t)(t_hight & 0xff),
|
|
(uint8_t)(t_low >> 8),
|
|
(uint8_t)(t_low & 0xff),
|
|
} );
|
|
}
|
|
|
|
int ugreen_leds_t::set_rgb(led_type_t id, uint8_t r, uint8_t g, uint8_t b) {
|
|
return _change_status(id, 0x02, { r, g, b } );
|
|
}
|
|
|
|
int ugreen_leds_t::set_brightness(led_type_t id, uint8_t brightness) {
|
|
return _change_status(id, 0x01, { brightness } );
|
|
}
|
|
|
|
bool ugreen_leds_t::is_last_modification_successful() {
|
|
return _i2c.read_byte_data(0x80) == 1;
|
|
}
|
|
|
|
int ugreen_leds_t::set_blink(led_type_t id, uint16_t t_on, uint16_t t_off) {
|
|
return _set_blink_or_breath(0x04, id, t_on, t_off);
|
|
}
|
|
|
|
int ugreen_leds_t::set_breath(led_type_t id, uint16_t t_on, uint16_t t_off) {
|
|
return _set_blink_or_breath(0x05, id, t_on, t_off);
|
|
}
|