mirror of
https://github.com/CalcProgrammer1/OpenRGB.git
synced 2026-10-30 04:21:08 -04:00
139 lines
4.7 KiB
C++
139 lines
4.7 KiB
C++
/*---------------------------------------------------------*\
|
|
| FrameworkDesktopController_Linux.cpp |
|
|
| |
|
|
| Driver for the Framework Desktop ARGB header, |
|
|
| controlled through the ChromeOS Embedded Controller |
|
|
| (cros_ec) |
|
|
| |
|
|
| Francis De Brabandere (francisdb@gmail.com) 16 Oct 2026 |
|
|
| |
|
|
| This file is part of the OpenRGB project |
|
|
| SPDX-License-Identifier: GPL-2.0-or-later |
|
|
\*---------------------------------------------------------*/
|
|
|
|
#include <cerrno>
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <sys/ioctl.h>
|
|
#include <unistd.h>
|
|
#include "FrameworkDesktopController_Linux.h"
|
|
#include "LogManager.h"
|
|
|
|
/*---------------------------------------------------------*\
|
|
| cros_ec character device interface, as defined by the |
|
|
| kernel in include/linux/platform_data/cros_ec_chardev.h |
|
|
| (not exported to userspace headers). The kernel struct |
|
|
| ends in a flexible data array, so the ioctl number only |
|
|
| encodes the size of the fixed header. |
|
|
\*---------------------------------------------------------*/
|
|
struct cros_ec_command_v2_header
|
|
{
|
|
uint32_t version;
|
|
uint32_t command;
|
|
uint32_t outsize;
|
|
uint32_t insize;
|
|
uint32_t result;
|
|
};
|
|
|
|
struct cros_ec_command_v2
|
|
{
|
|
cros_ec_command_v2_header header;
|
|
uint8_t data[256];
|
|
};
|
|
|
|
#define CROS_EC_DEV_IOC_V2 0xEC
|
|
#define CROS_EC_DEV_IOCXCMD_V2 _IOWR(CROS_EC_DEV_IOC_V2, 0, struct cros_ec_command_v2_header)
|
|
|
|
/*---------------------------------------------------------*\
|
|
| EC_CMD_RGBKBD_SET_COLOR parameters: |
|
|
| uint8_t start_key |
|
|
| uint8_t length |
|
|
| struct { uint8_t r, g, b; } color[length] |
|
|
| |
|
|
| This is the command sent by framework_tool --rgbkbd |
|
|
| https://github.com/FrameworkComputer/framework-system |
|
|
\*---------------------------------------------------------*/
|
|
#define EC_CMD_RGBKBD_SET_COLOR 0x013A
|
|
|
|
FrameworkDesktopController::FrameworkDesktopController(int fd, std::string dev_path)
|
|
{
|
|
this->fd = fd;
|
|
location = dev_path;
|
|
last_led_count = 0;
|
|
}
|
|
|
|
FrameworkDesktopController::~FrameworkDesktopController()
|
|
{
|
|
close(fd);
|
|
}
|
|
|
|
std::string FrameworkDesktopController::GetLocation()
|
|
{
|
|
return(location);
|
|
}
|
|
|
|
void FrameworkDesktopController::SetLEDs(const std::vector<RGBColor>& colors)
|
|
{
|
|
std::vector<RGBColor> send_colors = colors;
|
|
|
|
/*-----------------------------------------------------*\
|
|
| The EC keeps refreshing every LED it has been sent |
|
|
| since it booted. When the LED count is reduced, turn |
|
|
| the LEDs that are no longer used off once. |
|
|
\*-----------------------------------------------------*/
|
|
if(send_colors.size() < last_led_count)
|
|
{
|
|
send_colors.resize(last_led_count, ToRGBColor(0, 0, 0));
|
|
}
|
|
|
|
if(send_colors.size() > FRAMEWORK_DESKTOP_MAX_LEDS)
|
|
{
|
|
send_colors.resize(FRAMEWORK_DESKTOP_MAX_LEDS);
|
|
}
|
|
|
|
last_led_count = colors.size();
|
|
|
|
for(std::size_t start = 0; start < send_colors.size(); start += FRAMEWORK_DESKTOP_LEDS_PER_CMD)
|
|
{
|
|
std::size_t count = send_colors.size() - start;
|
|
|
|
if(count > FRAMEWORK_DESKTOP_LEDS_PER_CMD)
|
|
{
|
|
count = FRAMEWORK_DESKTOP_LEDS_PER_CMD;
|
|
}
|
|
|
|
SendColors((unsigned char)start, &send_colors[start], (unsigned char)count);
|
|
}
|
|
}
|
|
|
|
void FrameworkDesktopController::SendColors(unsigned char start, const RGBColor* colors, unsigned char count)
|
|
{
|
|
cros_ec_command_v2 cmd;
|
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
|
|
cmd.header.version = 0;
|
|
cmd.header.command = EC_CMD_RGBKBD_SET_COLOR;
|
|
cmd.header.outsize = (uint32_t)(2 + count * 3);
|
|
cmd.header.insize = 0;
|
|
|
|
cmd.data[0] = start;
|
|
cmd.data[1] = count;
|
|
|
|
for(unsigned int led_idx = 0; led_idx < count; led_idx++)
|
|
{
|
|
cmd.data[2 + led_idx * 3 + 0] = RGBGetRValue(colors[led_idx]);
|
|
cmd.data[2 + led_idx * 3 + 1] = RGBGetGValue(colors[led_idx]);
|
|
cmd.data[2 + led_idx * 3 + 2] = RGBGetBValue(colors[led_idx]);
|
|
}
|
|
|
|
if(ioctl(fd, CROS_EC_DEV_IOCXCMD_V2, &cmd) < 0)
|
|
{
|
|
LOG_ERROR("[Framework Desktop] EC_CMD_RGBKBD_SET_COLOR ioctl failed: %s", strerror(errno));
|
|
}
|
|
else if(cmd.header.result != 0)
|
|
{
|
|
LOG_ERROR("[Framework Desktop] EC_CMD_RGBKBD_SET_COLOR returned EC error %u", cmd.header.result);
|
|
}
|
|
}
|