mirror of
https://github.com/libratbag/libratbag.git
synced 2026-11-07 23:23:52 +01:00
sinowealth: move device-specific data out of the driver
This moves device data out of the driver into device files. However, a _single_ device file contains data for _several mice_ at the same time. The reason for this is that different mice by SinoWealth may use the same VID:PID pair. This is unfortunate, as we only allow a single device file a given VID:PID pair. Also move `sinowealth_led_format` enum into a header file and rename its constants to fit in outside of the driver.
This commit is contained in:
@@ -3,3 +3,9 @@ Name=Glorious Model D
|
||||
DeviceMatch=usb:258a:0033
|
||||
Driver=sinowealth
|
||||
|
||||
[Driver/sinowealth/devices/GloriousModelD]
|
||||
ButtonCount=6
|
||||
DeviceName=Glorious Model D
|
||||
FwVersion=V102
|
||||
LedType=RBG
|
||||
SensorType=PMW3360
|
||||
|
||||
@@ -3,3 +3,9 @@ Name=Glorious Model O/O-
|
||||
DeviceMatch=usb:258a:0036
|
||||
Driver=sinowealth
|
||||
|
||||
[Driver/sinowealth/devices/GloriousModelO]
|
||||
ButtonCount=6
|
||||
DeviceName=Glorious Model O/O- (updated firmware)
|
||||
FwVersion=V103
|
||||
LedType=RBG
|
||||
SensorType=PMW3360
|
||||
|
||||
@@ -1,10 +1,38 @@
|
||||
[Device]
|
||||
# Several mice match this ID:
|
||||
# - Dream Machines DM5 Blink
|
||||
# - G-Wolves Hati HT-M Wired Ace
|
||||
# - G-Wolves Hati HT-M Wired Classic
|
||||
# - Genesys Xenon 770
|
||||
# - Glorious Model O (old firmware)
|
||||
DeviceMatch=usb:258a:0027
|
||||
Driver=sinowealth
|
||||
Name=SinoWealth Generic Mouse (0027)
|
||||
|
||||
[Driver/sinowealth/devices/DreamMachinesDM5Blink]
|
||||
ButtonCount=8
|
||||
DeviceName=DreamMachines DM5 Blink
|
||||
FwVersion=3106
|
||||
LedType=RGB
|
||||
SensorType=PMW3389
|
||||
|
||||
[Driver/sinowealth/devices/GWolvesHatiHTM]
|
||||
ButtonCount=6
|
||||
# Can be both `Ace` and `Classic` version.
|
||||
DeviceName=G-Wolves Hati HT-M Wired
|
||||
FwVersion=V161
|
||||
LedType=None
|
||||
# Can also be PMW3389
|
||||
SensorType=PMW3360
|
||||
|
||||
[Driver/sinowealth/devices/GenesysXenon770]
|
||||
# There are 5 main buttons.
|
||||
# Side buttons are detachable.
|
||||
# There can be either 3 or 9 buttons on the side.
|
||||
# Going for the maximum count: 5 + 9 = 14.
|
||||
ButtonCount=14
|
||||
DeviceName=Genesys Xenon 770
|
||||
FwVersion=3110
|
||||
LedType=RGB
|
||||
SensorType=PMW3327
|
||||
|
||||
[Driver/sinowealth/devices/GloriousModelOOld]
|
||||
ButtonCount=6
|
||||
DeviceName=Glorious Model O (old firmware)
|
||||
FwVersion=V102
|
||||
LedType=RBG
|
||||
SensorType=PMW3360
|
||||
|
||||
20
data/devices/sinowealth-1007.device
Normal file
20
data/devices/sinowealth-1007.device
Normal file
@@ -0,0 +1,20 @@
|
||||
[Device]
|
||||
DeviceMatch=usb:258a:1007
|
||||
Driver=sinowealth
|
||||
Name=SinoWealth Generic Mouse (1007)
|
||||
|
||||
# This does NOT work. See libratbag/libratbag#1296.
|
||||
# For future: ID of A3050 sensor is 0x2, and maximum DPI is 4000.
|
||||
#[Driver/sinowealth/devices/AntEsportsGM500]
|
||||
#ButtonCount=7
|
||||
#DeviceName=Ant Esports GM500
|
||||
#FwVersion=0910
|
||||
#LedType=RBG
|
||||
#SensorType=A3050
|
||||
|
||||
[Driver/sinowealth/devices/MarvoScorpionG961]
|
||||
ButtonCount=6
|
||||
DeviceName=Marvo Scorpion G961
|
||||
FwVersion=9677
|
||||
LedType=RGB
|
||||
SensorType=PMW3327
|
||||
@@ -179,6 +179,7 @@ src_libratbag = [
|
||||
'src/driver-steelseries.c',
|
||||
'src/driver-steelseries.h',
|
||||
'src/driver-sinowealth.c',
|
||||
'src/driver-sinowealth.h',
|
||||
'src/driver-sinowealth-nubwo.c',
|
||||
'src/driver-test.c',
|
||||
'src/libratbag.c',
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "driver-sinowealth.h"
|
||||
|
||||
#include "libratbag-data.h"
|
||||
#include "libratbag-private.h"
|
||||
#include "libratbag-hidraw.h"
|
||||
#include "shared-macro.h"
|
||||
@@ -188,12 +191,6 @@ union sinowealth_dpis {
|
||||
};
|
||||
_Static_assert(sizeof(union sinowealth_dpis) == sizeof(uint8_t[16]), "Invalid size");
|
||||
|
||||
enum sinowealth_led_format {
|
||||
LED_NONE,
|
||||
LED_RBG,
|
||||
LED_RGB,
|
||||
};
|
||||
|
||||
/* Configuration data the way it's stored in mouse memory.
|
||||
* When we want to change a setting, we basically copy the entire mouse
|
||||
* configuration, modify it and send it back.
|
||||
@@ -651,12 +648,12 @@ sinowealth_raw_to_color(struct ratbag_device *device, struct sinowealth_color ra
|
||||
switch (drv_data->led_type) {
|
||||
/* Fall back to RBG if the LED type is incorrect. */
|
||||
default:
|
||||
case LED_RBG:
|
||||
case SINOWEALTH_LED_TYPE_RBG:
|
||||
color.red = raw_color.data[0];
|
||||
color.green = raw_color.data[2];
|
||||
color.blue = raw_color.data[1];
|
||||
break;
|
||||
case LED_RGB:
|
||||
case SINOWEALTH_LED_TYPE_RGB:
|
||||
color.red = raw_color.data[0];
|
||||
color.green = raw_color.data[1];
|
||||
color.blue = raw_color.data[2];
|
||||
@@ -679,12 +676,12 @@ sinowealth_color_to_raw(struct ratbag_device *device, struct ratbag_color color)
|
||||
switch (drv_data->led_type) {
|
||||
/* Fall back to RBG if the LED type is incorrect. */
|
||||
default:
|
||||
case LED_RBG:
|
||||
case SINOWEALTH_LED_TYPE_RBG:
|
||||
raw_color.data[0] = color.red;
|
||||
raw_color.data[1] = color.blue;
|
||||
raw_color.data[2] = color.green;
|
||||
break;
|
||||
case LED_RGB:
|
||||
case SINOWEALTH_LED_TYPE_RGB:
|
||||
raw_color.data[0] = color.red;
|
||||
raw_color.data[1] = color.green;
|
||||
raw_color.data[2] = color.blue;
|
||||
@@ -1373,140 +1370,31 @@ sinowealth_update_macro_from_action(struct ratbag_profile *profile, struct ratba
|
||||
macro->event_count = raw_event_count;
|
||||
}
|
||||
|
||||
struct sinowealth_device_data {
|
||||
const char fw_version[4];
|
||||
const char *device_name;
|
||||
enum sinowealth_led_format led_type;
|
||||
/* Not necessarily the sensor used on the mouse, some mice may have
|
||||
* different sensers per the same model.
|
||||
* We may fall back to this value in the future if we ever find mice
|
||||
* with broken sensor type field.
|
||||
*/
|
||||
enum sinowealth_sensor sensor_type;
|
||||
uint16_t pid;
|
||||
uint16_t vid;
|
||||
unsigned int button_count;
|
||||
};
|
||||
|
||||
static const struct sinowealth_device_data sinowealth_supported_devices[] = {
|
||||
/* 258a:0027 devices. */
|
||||
{
|
||||
.fw_version = "V102",
|
||||
.device_name = "Glorious Model O (old firmware)",
|
||||
.led_type = LED_RBG,
|
||||
.sensor_type = SINOWEALTH_SENSOR_PMW3360,
|
||||
.vid = 0x258a,
|
||||
.pid = 0x27,
|
||||
.button_count = 6,
|
||||
},
|
||||
{
|
||||
.fw_version = "V161",
|
||||
.device_name = "G-Wolves Hati HT-M Wired",
|
||||
.led_type = LED_NONE,
|
||||
/* Can also be PMW3389. */
|
||||
.sensor_type = SINOWEALTH_SENSOR_PMW3360,
|
||||
.vid = 0x258a,
|
||||
.pid = 0x27,
|
||||
.button_count = 6,
|
||||
},
|
||||
{
|
||||
.fw_version = "3106",
|
||||
.device_name = "DreamMachines DM5 Blink",
|
||||
.led_type = LED_RGB,
|
||||
.sensor_type = SINOWEALTH_SENSOR_PMW3389,
|
||||
.vid = 0x258a,
|
||||
.pid = 0x27,
|
||||
.button_count = 8,
|
||||
},
|
||||
{
|
||||
.fw_version = "3110",
|
||||
.device_name = "Genesis Xenon 770",
|
||||
.led_type = LED_RGB,
|
||||
.sensor_type = SINOWEALTH_SENSOR_PMW3327,
|
||||
.vid = 0x258a,
|
||||
.pid = 0x27,
|
||||
/* Side buttons are detachable.
|
||||
* There can be either 3 or 9 buttons on the side.
|
||||
*/
|
||||
.button_count = 5 + 9,
|
||||
},
|
||||
|
||||
/* 258a:0033 devices. */
|
||||
{
|
||||
.fw_version = "V102",
|
||||
.device_name = "Glorious Model D",
|
||||
.led_type = LED_RBG,
|
||||
.sensor_type = SINOWEALTH_SENSOR_PMW3360,
|
||||
.vid = 0x258a,
|
||||
.pid = 0x33,
|
||||
.button_count = 6,
|
||||
},
|
||||
|
||||
/* 258a:0036 devices. */
|
||||
{
|
||||
.fw_version = "V103",
|
||||
.device_name = "Glorious Model O/O- (updated firmware)",
|
||||
.led_type = LED_RBG,
|
||||
.sensor_type = SINOWEALTH_SENSOR_PMW3360,
|
||||
.vid = 0x258a,
|
||||
.pid = 0x36,
|
||||
.button_count = 6,
|
||||
},
|
||||
|
||||
/* 258a:003E devices. */
|
||||
{
|
||||
/* Untested. */
|
||||
/* This matches both Classic and Ace versions. */
|
||||
.fw_version = "3105",
|
||||
.device_name = "G-Wolves Hati HT-S Wired",
|
||||
.led_type = LED_NONE,
|
||||
.sensor_type = SINOWEALTH_SENSOR_PMW3360,
|
||||
.vid = 0x258a,
|
||||
.pid = 0x3e,
|
||||
.button_count = 6,
|
||||
},
|
||||
|
||||
/* 2581:1007 devices. */
|
||||
{
|
||||
.fw_version = "9677",
|
||||
.device_name = "Marvo Scorpion G961",
|
||||
.led_type = LED_RGB,
|
||||
/* Official software allows up to 12000 DPI instead of 10200. */
|
||||
.sensor_type = SINOWEALTH_SENSOR_PMW3327,
|
||||
.vid = 0x258a,
|
||||
.pid = 0x1007,
|
||||
.button_count = 6,
|
||||
},
|
||||
|
||||
/* Dummy device. Make sure it's the last entry. */
|
||||
{
|
||||
.fw_version = "0000",
|
||||
.device_name = "Generic SinoWealth Mouse",
|
||||
.led_type = LED_RBG,
|
||||
.sensor_type = SINOWEALTH_SENSOR_PMW3360,
|
||||
.vid = 0xffff,
|
||||
.pid = 0xffff,
|
||||
.button_count = 6,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* @return Supported device data for the device or `NULL`.
|
||||
*/
|
||||
static const struct sinowealth_device_data *
|
||||
sinowealth_find_device_data(struct input_id ids, const char *fw_version)
|
||||
sinowealth_find_device_data(struct ratbag_device *device, const char *fw_version)
|
||||
{
|
||||
const struct sinowealth_device_data *device_data = NULL;
|
||||
const struct ratbag_device_data *data = device->data;
|
||||
|
||||
ARRAY_FOR_EACH(sinowealth_supported_devices, device_data) {
|
||||
if (device_data->vid != ids.vendor || device_data->pid != ids.product)
|
||||
const struct list *supported_devices = ratbag_device_data_sinowealth_get_supported_devices(data);
|
||||
|
||||
struct sinowealth_device_data *device_data = NULL;
|
||||
list_for_each(device_data, supported_devices, link) {
|
||||
if (device_data->fw_version == NULL || device_data->device_name == NULL) {
|
||||
log_error(device->ratbag, "Skipping invalid device data\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strneq(fw_version, device_data->fw_version, sizeof(device_data->fw_version)))
|
||||
if (!strneq(fw_version, device_data->fw_version, SINOWEALTH_FW_VERSION_LEN))
|
||||
continue;
|
||||
|
||||
return device_data;
|
||||
}
|
||||
|
||||
/* Return the last entry in `sinowealth_device_data` - a dummy. */
|
||||
return device_data;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize profiles for device `device`.
|
||||
@@ -1543,7 +1431,12 @@ sinowealth_init_profile(struct ratbag_device *device)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
const struct sinowealth_device_data *device_data = sinowealth_find_device_data(device->ids, fw_version);
|
||||
const struct sinowealth_device_data *device_data = sinowealth_find_device_data(device, fw_version);
|
||||
|
||||
if (device_data == NULL) {
|
||||
log_error(device->ratbag, "Device with firmware version %s is not supported\n", fw_version);
|
||||
return -1;
|
||||
}
|
||||
|
||||
drv_data->button_count = device_data->button_count;
|
||||
drv_data->led_type = device_data->led_type;
|
||||
@@ -1552,7 +1445,7 @@ sinowealth_init_profile(struct ratbag_device *device)
|
||||
|
||||
/* LED count. */
|
||||
drv_data->led_count = 0;
|
||||
if (config->rgb_effect != RGB_NOT_SUPPORTED && drv_data->led_type != LED_NONE) {
|
||||
if (config->rgb_effect != RGB_NOT_SUPPORTED && drv_data->led_type != SINOWEALTH_LED_TYPE_NONE) {
|
||||
drv_data->led_count += 1;
|
||||
}
|
||||
/* We may want to account for the DPI LEDs in the future.
|
||||
|
||||
41
src/driver-sinowealth.h
Normal file
41
src/driver-sinowealth.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright © 2022 Yaroslav Chvanov
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "libratbag-util.h"
|
||||
|
||||
enum sinowealth_led_format {
|
||||
SINOWEALTH_LED_TYPE_NONE,
|
||||
SINOWEALTH_LED_TYPE_RBG,
|
||||
SINOWEALTH_LED_TYPE_RGB,
|
||||
};
|
||||
|
||||
struct sinowealth_device_data {
|
||||
char *fw_version;
|
||||
char *device_name;
|
||||
enum sinowealth_led_format led_type;
|
||||
unsigned int button_count;
|
||||
|
||||
struct list link;
|
||||
};
|
||||
@@ -30,11 +30,13 @@
|
||||
#include <glib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "driver-sinowealth.h"
|
||||
#include "driver-steelseries.h"
|
||||
#include "libratbag.h"
|
||||
#include "libratbag-private.h"
|
||||
#include "libratbag-data.h"
|
||||
#include "hidpp20.h"
|
||||
#include "shared-macro.h"
|
||||
#include "usb-ids.h"
|
||||
|
||||
#define GROUP_DEVICE "Device"
|
||||
@@ -78,6 +80,10 @@ struct data_hidpp10 {
|
||||
int led_count;
|
||||
};
|
||||
|
||||
struct data_sinowealth {
|
||||
struct list supported_devices;
|
||||
};
|
||||
|
||||
struct data_steelseries {
|
||||
int device_version;
|
||||
int button_count;
|
||||
@@ -98,6 +104,7 @@ struct ratbag_device_data {
|
||||
union {
|
||||
struct data_hidpp20 hidpp20;
|
||||
struct data_hidpp10 hidpp10;
|
||||
struct data_sinowealth sinowealth;
|
||||
struct data_steelseries steelseries;
|
||||
};
|
||||
|
||||
@@ -207,6 +214,56 @@ init_data_hidpp20(struct ratbag *ratbag,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
init_data_sinowealth(struct ratbag *ratbag,
|
||||
GKeyFile *keyfile,
|
||||
struct ratbag_device_data *data)
|
||||
{
|
||||
const char *devices_group = "Driver/sinowealth/devices/";
|
||||
|
||||
GError *error = NULL;
|
||||
|
||||
size_t group_count = 0;
|
||||
_cleanup_(g_strfreevp) char **groups = g_key_file_get_groups(keyfile, &group_count);
|
||||
|
||||
list_init(&data->sinowealth.supported_devices);
|
||||
|
||||
for (size_t i = 0; i < group_count; ++i) {
|
||||
const char *device_group = groups[i];
|
||||
if (startswith(device_group, devices_group) == NULL)
|
||||
continue;
|
||||
|
||||
struct sinowealth_device_data *device = zalloc(sizeof(struct sinowealth_device_data));
|
||||
|
||||
device->button_count = g_key_file_get_integer(keyfile, device_group, "ButtonCount", &error);
|
||||
g_clear_error(&error);
|
||||
|
||||
device->device_name = g_key_file_get_string(keyfile, device_group, "DeviceName", &error);
|
||||
g_clear_error(&error);
|
||||
|
||||
device->fw_version = g_key_file_get_string(keyfile, device_group, "FwVersion", &error);
|
||||
g_clear_error(&error);
|
||||
|
||||
_cleanup_free_ char *led_type_str = g_key_file_get_string(keyfile, device_group, "LedType", &error);
|
||||
if (led_type_str) {
|
||||
if (streq(led_type_str, "RGB")) {
|
||||
device->led_type = SINOWEALTH_LED_TYPE_RGB;
|
||||
} else if (streq(led_type_str, "RBG")) {
|
||||
device->led_type = SINOWEALTH_LED_TYPE_RBG;
|
||||
} else if (streq(led_type_str, "None")) {
|
||||
device->led_type = SINOWEALTH_LED_TYPE_NONE;
|
||||
} else {
|
||||
log_error(ratbag, "Unknown LED type '%s' in group '%s'\n", led_type_str, device_group);
|
||||
|
||||
device->led_type = SINOWEALTH_LED_TYPE_NONE;
|
||||
}
|
||||
}
|
||||
g_clear_error(&error);
|
||||
|
||||
list_insert(&data->sinowealth.supported_devices, &device->link);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
init_data_steelseries(struct ratbag *ratbag,
|
||||
GKeyFile *keyfile,
|
||||
@@ -287,7 +344,7 @@ static const struct driver_map {
|
||||
{ LOGITECH_G300, "logitech_g300", NULL},
|
||||
{ LOGITECH_G600, "logitech_g600", NULL},
|
||||
{ STEELSERIES, "steelseries", init_data_steelseries },
|
||||
{ SINOWEALTH, "sinowealth", NULL },
|
||||
{ SINOWEALTH, "sinowealth", init_data_sinowealth },
|
||||
{ SINOWEALTH_NUBWO, "sinowealth_nubwo", NULL},
|
||||
{ OPENINPUT, "openinput", NULL },
|
||||
};
|
||||
@@ -333,6 +390,18 @@ ratbag_device_data_destroy(struct ratbag_device_data *data)
|
||||
free(data->hidpp10.dpi_range);
|
||||
free(data->hidpp10.profile_type);
|
||||
break;
|
||||
case SINOWEALTH: {
|
||||
struct sinowealth_device_data *device_data = NULL;
|
||||
struct sinowealth_device_data *device_data_next = NULL;
|
||||
|
||||
list_for_each_safe(device_data, device_data_next, &data->sinowealth.supported_devices, link) {
|
||||
free(device_data->device_name);
|
||||
free(device_data->fw_version);
|
||||
free(device_data);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case STEELSERIES:
|
||||
if (data->steelseries.dpi_list) {
|
||||
free(data->steelseries.dpi_list->entries);
|
||||
@@ -656,6 +725,16 @@ ratbag_device_data_hidpp20_get_quirk(const struct ratbag_device_data *data)
|
||||
return data->hidpp20.quirk;
|
||||
}
|
||||
|
||||
/* SinoWealth */
|
||||
|
||||
const struct list *
|
||||
ratbag_device_data_sinowealth_get_supported_devices(const struct ratbag_device_data *data)
|
||||
{
|
||||
assert(data->drivertype == SINOWEALTH);
|
||||
|
||||
return &data->sinowealth.supported_devices;
|
||||
}
|
||||
|
||||
/* SteelSeries */
|
||||
|
||||
int
|
||||
|
||||
@@ -92,6 +92,16 @@ ratbag_device_data_hidpp20_get_report_rate(const struct ratbag_device_data *data
|
||||
enum hidpp20_quirk
|
||||
ratbag_device_data_hidpp20_get_quirk(const struct ratbag_device_data *data);
|
||||
|
||||
/* SinoWealth */
|
||||
|
||||
/*
|
||||
* NOTE: Don't forget to check for NULL in fields of each device data entry.
|
||||
*
|
||||
* @return List of data for supported devices.
|
||||
*/
|
||||
const struct list *
|
||||
ratbag_device_data_sinowealth_get_supported_devices(const struct ratbag_device_data *data);
|
||||
|
||||
/* SteelSeries */
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user