Files
OpenRGB/Controllers/LightSaltController/LightSaltController.cpp

312 lines
8.2 KiB
C++

/*---------------------------------------------------------*\
| LightSaltController.cpp |
| |
| Driver for LightSalt Peripherals |
| |
| James Buren (braewoods) 23 Jul 2024 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#include <cstring>
#include "LightSaltController.h"
#include "StringUtils.h"
static const int mode_map[LIGHTSALT_MODE_MAXIMUM][6] =
{
{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
{0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
{0x0400, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
{0x0700, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
{0x0A00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
{0x0D00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
{0x0E00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
{0x0F00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
{0x1100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
{0x0000, 0x0000, 0x0000, 0x0000, 0x3301, 0x3302},
{0x3402, 0x3401, 0x0000, 0x0000, 0x0000, 0x0000},
{0x3502, 0x3501, 0x0000, 0x0000, 0x0000, 0x0000},
{0x3602, 0x3601, 0x0000, 0x0000, 0x0000, 0x0000},
{0x3802, 0x3801, 0x0000, 0x0000, 0x0000, 0x0000},
{0x0000, 0x0000, 0x3901, 0x3902, 0x0000, 0x0000},
{0x0000, 0x0000, 0x3A01, 0x3A02, 0x0000, 0x0000},
{0x0000, 0x0000, 0x0000, 0x0000, 0x3702, 0x3701},
{0x3B02, 0x3B01, 0x0000, 0x0000, 0x0000, 0x0000}
};
LightSaltController::LightSaltController(hid_device* dev_handle, const hid_device_info& info)
{
wchar_t usb_string[128];
dev = dev_handle;
device_location = info.path;
if(hid_get_manufacturer_string(dev, usb_string, 128) == 0)
{
manufacturer = StringUtils::wstring_to_string(usb_string);
}
else
{
manufacturer = "";
}
if(hid_get_product_string(dev, usb_string, 128) == 0)
{
product = StringUtils::wstring_to_string(usb_string);
}
else
{
product = "";
}
if(strstr(manufacturer.c_str(), "Light&Salt") && strstr(product.c_str(), "Light&Salt"))
{
QueryDeviceModel();
QueryDeviceClass();
SetDeviceType();
}
else
{
device_model = "";
device_class = "";
firmware_version = "";
device_type = LIGHTSALT_TYPE_MAXIMUM;
}
}
LightSaltController::~LightSaltController()
{
hid_close(dev);
}
std::string LightSaltController::GetDeviceLocation()
{
return("HID: " + device_location);
}
std::string LightSaltController::GetSerial()
{
wchar_t serial_string[128];
int ret = hid_get_serial_number_string(dev, serial_string, 128);
if(ret != 0)
{
return("");
}
return(StringUtils::wstring_to_string(serial_string));
}
std::string LightSaltController::GetManufacturer()
{
return(manufacturer);
}
std::string LightSaltController::GetProduct()
{
return(product);
}
std::string LightSaltController::GetDeviceModel()
{
return(device_model);
}
std::string LightSaltController::GetDeviceClass()
{
return(device_class);
}
std::string LightSaltController::GetFirmwareVersion()
{
return(firmware_version);
}
int LightSaltController::GetDeviceType()
{
return(device_type);
}
void LightSaltController::SetColors(RGBColor* colors, int sets, int rows, int columns)
{
uint8_t write_buffer[LIGHTSALT_WRITE_LENGTH];
int color_idx = 0;
write_buffer[0] = 0x00;
for(int set_idx = 0; set_idx < sets; set_idx++)
{
write_buffer[1] = 0x03 + set_idx;
for(int row_idx = 0; row_idx < rows; row_idx++)
{
int write_idx = 2;
write_buffer[write_idx++] = 0x01 + row_idx * columns;
for(int column_idx = 0; column_idx < columns; column_idx++)
{
RGBColor color = colors[color_idx++];
write_buffer[write_idx++] = RGBGetRValue(color);
write_buffer[write_idx++] = RGBGetGValue(color);
write_buffer[write_idx++] = RGBGetBValue(color);
}
hid_write(dev, write_buffer, sizeof(write_buffer));
}
}
}
void LightSaltController::ApplyColors(int sets)
{
uint8_t write_buffer[LIGHTSALT_WRITE_LENGTH];
int write_idx = 1;
memset(write_buffer, 0x00, sizeof(write_buffer));
write_buffer[write_idx++] = 0xFE;
write_buffer[write_idx++] = 0x01;
for(int set_idx = 0; set_idx < sets; set_idx++)
{
write_buffer[write_idx++] = 0x03 + set_idx;
}
hid_write(dev, write_buffer, sizeof(write_buffer));
}
void LightSaltController::SaveColors(int sets)
{
uint8_t write_buffer[LIGHTSALT_WRITE_LENGTH];
int write_idx = 1;
memset(write_buffer, 0x00, sizeof(write_buffer));
write_buffer[write_idx++] = 0xFE;
write_buffer[write_idx++] = 0xF0;
for(int set_idx = 0; set_idx < sets; set_idx++)
{
write_buffer[write_idx++] = 0x03 + set_idx;
}
hid_write(dev, write_buffer, sizeof(write_buffer));
}
void LightSaltController::SetMode(int mode, int direction, int speed)
{
uint8_t write_buffer[LIGHTSALT_WRITE_LENGTH];
int actual_mode = mode_map[mode][direction];
memset(write_buffer, 0x00, sizeof(write_buffer));
write_buffer[1] = 0xFE;
write_buffer[2] = 0x03;
write_buffer[3] = (actual_mode & 0xFF00) >> 8;
write_buffer[4] = (actual_mode & 0x00FF) >> 0;
write_buffer[5] = speed;
hid_write(dev, write_buffer, sizeof(write_buffer));
}
void LightSaltController::SetFilter(RGBColor color)
{
uint8_t write_buffer[LIGHTSALT_WRITE_LENGTH];
memset(write_buffer, 0x00, sizeof(write_buffer));
write_buffer[1] = 0xFE;
write_buffer[2] = 0x04;
write_buffer[3] = RGBGetRValue(color);
write_buffer[4] = RGBGetGValue(color);
write_buffer[5] = RGBGetBValue(color);
hid_write(dev, write_buffer, sizeof(write_buffer));
}
void LightSaltController::SetBrightness(uint8_t brightness)
{
uint8_t write_buffer[LIGHTSALT_WRITE_LENGTH];
memset(write_buffer, 0x00, sizeof(write_buffer));
write_buffer[1] = 0xFE;
write_buffer[2] = 0x05;
write_buffer[3] = brightness;
hid_write(dev, write_buffer, sizeof(write_buffer));
}
void LightSaltController::QueryDeviceModel()
{
uint8_t write_buffer[LIGHTSALT_WRITE_LENGTH];
uint8_t read_buffer[LIGHTSALT_READ_LENGTH];
memset(write_buffer, 0x00, sizeof(write_buffer));
write_buffer[1] = 0xFE;
write_buffer[2] = 0xF5;
write_buffer[3] = 0x06;
if(hid_write(dev, write_buffer, sizeof(write_buffer)) != sizeof(write_buffer))
{
device_model = "";
return;
}
if(hid_read_timeout(dev, read_buffer, sizeof(read_buffer), 100) != sizeof(read_buffer))
{
device_model = "";
return;
}
device_model = (char *)(read_buffer + 3);
}
void LightSaltController::QueryDeviceClass()
{
uint8_t write_buffer[LIGHTSALT_WRITE_LENGTH];
uint8_t read_buffer[LIGHTSALT_READ_LENGTH];
memset(write_buffer, 0x00, sizeof(write_buffer));
write_buffer[1] = 0xFE;
write_buffer[2] = 0xFF;
if(hid_write(dev, write_buffer, sizeof(write_buffer)) != sizeof(write_buffer))
{
device_class = "";
firmware_version = "";
return;
}
if(hid_read_timeout(dev, read_buffer, sizeof(read_buffer), 100) != sizeof(read_buffer))
{
device_class = "";
firmware_version = "";
return;
}
device_class = (char *)(read_buffer );
firmware_version = (char *)(read_buffer + device_class.size() + 1);
}
void LightSaltController::SetDeviceType()
{
struct device_class_table
{
std::string device_class;
int device_type;
};
static const device_class_table table[] =
{
{"Light&Salt_keyboard1", LIGHTSALT_TYPE_KEYBOARD},
{"Light&Salt_KEY_PAD", LIGHTSALT_TYPE_KEYPAD }
};
device_type = LIGHTSALT_TYPE_MAXIMUM;
for(const device_class_table& match : table)
{
if(match.device_class == device_class)
{
device_type = match.device_type;
break;
}
}
}