1
0
forked from drath/libratbag

Compare commits

..

2 Commits

Author SHA1 Message Date
Thomas H.P. Andersen
84b1519ebd steelseries: port to using the firmware field in device 2020-09-29 00:54:01 +02:00
Thomas H.P. Andersen
99b8c80aee device: add firmware major/minor
This adds fields to the device struct to store the
firmware version on the device. It is also exposed
over dbus to the clients.

The firmware of a device can define the protocol
or memory layout that should be used to talk to
the device. Several devices can query the firmware
version via separate commands and we can use this
information in the drivers to change behavior of the
driver based on the device firmware.

The firmware version is also exposed over dbus so that
it is easily available for users via e.g. ratbagctl. It
can also be used in piper to warn users that a known bug
in a firmware version can cause problems when trying to
configure with libratbag.
2020-09-29 00:53:52 +02:00
27 changed files with 129 additions and 628 deletions

View File

@@ -231,10 +231,10 @@ docs_deploy: &docs_deploy
version: 2
jobs:
fedora_32:
fedora_31:
<<: *fedora_settings
docker:
- image: fedora:32
- image: fedora:31
arch:
<<: *arch_settings
docker:
@@ -246,11 +246,11 @@ jobs:
doc_build:
<<: *doc_build
docker:
- image: fedora:32
- image: fedora:31
doc_deploy:
<<: *docs_deploy
docker:
- image: fedora:32
- image: fedora:31
workflows:
@@ -258,8 +258,8 @@ workflows:
compile_and_test:
jobs:
- ubuntu_20_04
# - arch
- fedora_32
- arch
- fedora_31
- doc_build
- doc_deploy:
requires:

View File

@@ -1,5 +0,0 @@
# Logitech M500s
[Device]
Name=Logitech M500s
DeviceMatch=usb:046d:c093
Driver=hidpp20

View File

@@ -1,5 +0,0 @@
# Logitech M545
[Device]
Name=Logitech M545
DeviceMatch=usb:046d:4052
Driver=hidpp20

View File

@@ -1,5 +0,0 @@
# Logitech MX Anywhere 3
[Device]
Name=Logitech MX Anywhere 3
DeviceMatch=bluetooth:046d:b025;usb:046d:4090
Driver=hidpp20

View File

@@ -1,4 +1,4 @@
[Device]
Name=Logitech MX Anywhere 2
DeviceMatch=usb:046d:404a;usb:046d:4072;usb:046d:4063;bluetooth:046d:b013;bluetooth:046d:b018;bluetooth:046d:b01f
DeviceMatch=usb:046d:404a;bluetooth:046d:b013;bluetooth:046d:b018;bluetooth:046d:b01f
Driver=hidpp20

View File

@@ -1,4 +1,4 @@
[Device]
Name=Logitech MX Vertical
DeviceMatch=bluetooth:046d:b020;usb:046d:407b;usb:046d:c08a
DeviceMatch=bluetooth:046d:b020;usb:046d:407b
Driver=hidpp20

View File

@@ -1,5 +0,0 @@
[Device]
Name=Logitech G Pro X Wireless Superlight
DeviceMatch=usb:046d:4093;usb:046d:c094
LedTypes=logo;battery;dpi;
Driver=hidpp20

View File

@@ -1,8 +0,0 @@
[Device]
Name=Logitech G915 TKL
DeviceMatch=usb:046d:c343;bluetooth:046d:b35f
LedTypes=logo;switches
Driver=hidpp20
[Driver/hidpp20]
DeviceIndex=1

View File

@@ -1,4 +0,0 @@
[Device]
Name=openinput
DeviceMatch=usb:1d50:616a
Driver=openinput

View File

@@ -1,4 +1,4 @@
[Device]
Name=Roccat Kone Pure
DeviceMatch=usb:1e7d:2dc2;usb:1e7d:2dbe;usb:1e7d:2dcb
DeviceMatch=usb:1e7d:2dc2;usb:1e7d:2dbe
Driver=roccat-kone-pure

View File

@@ -1,11 +0,0 @@
[Device]
Name=SteelSeries Kinzu V2 Pro Edition
DeviceMatch=usb:1038:1366
Driver=steelseries
[Driver/steelseries]
DeviceVersion=1
Buttons=3
Leds=0
DpiList=400;800;1600;3200
MacroLength=0

View File

@@ -151,6 +151,20 @@ known to ratbagd.
Vendor or product IDs of 0 are valid IDs (e.g. used used by test
devices).
.. attribute:: FirmwareMajor
:type: i
:flags: read-only, constant
The device's firmware major version.
.. attribute:: FirmwareMinor
:type: i
:flags: read-only, constant
The device's firmware minor version.
.. attribute:: Name
:type: s

View File

@@ -1,5 +1,5 @@
project('libratbag', 'c',
version : '0.16',
version : '0.15',
license : 'MIT/Expat',
default_options : [ 'c_std=gnu99', 'warning_level=2' ],
meson_version : '>= 0.40.0')
@@ -174,7 +174,6 @@ src_libratbag = [
'src/driver-roccat.c',
'src/driver-roccat-kone-pure.c',
'src/driver-gskill.c',
'src/driver-openinput.c',
'src/driver-steelseries.c',
'src/driver-sinowealth.c',
'src/driver-sinowealth-nubwo.c',
@@ -284,8 +283,6 @@ data_files = files(
'data/devices/etekcity-scroll-alpha.device',
'data/devices/gskill-MX-780.device',
'data/devices/logitech-M325.device',
'data/devices/logitech-M500s.device',
'data/devices/logitech-M545.device',
'data/devices/logitech-M570.device',
'data/devices/logitech-M585-M590.device',
'data/devices/logitech-M705.device',
@@ -299,7 +296,6 @@ data_files = files(
'data/devices/logitech-Wireless-Touchpad.device',
'data/devices/logitech-g-powerplay.device',
'data/devices/logitech-g-pro-wireless.device',
'data/devices/logitech-g-pro-x-wireless-superlight.device',
'data/devices/logitech-g-pro.device',
'data/devices/logitech-g102-g203.device',
'data/devices/logitech-g300.device',
@@ -336,20 +332,16 @@ data_files = files(
'data/devices/logitech-g815.device',
'data/devices/logitech-g910.device',
'data/devices/logitech-g915.device',
'data/devices/logitech-g915-tkl.device',
'data/devices/logitech-g935.device',
'data/devices/logitech-g9x-Call-of-Duty-MW3-Edition.device',
'data/devices/logitech-g9x-Original.device',
'data/devices/logitech-Marathon-M705.device',
'data/devices/logitech-MX-Anywhere2.device',
'data/devices/logitech-MX-Anywhere2S.device',
'data/devices/logitech-MX-Anywhere-3.device',
'data/devices/logitech-MX-Vertical.device',
'data/devices/openinput.device',
'data/devices/roccat-kone-pure.device',
'data/devices/roccat-kone-xtd.device',
'data/devices/steelseries-kinzu-v2.device',
'data/devices/steelseries-kinzu-v2-pro.device',
'data/devices/steelseries-kinzu-v3.device',
'data/devices/steelseries-rival-310.device',
'data/devices/steelseries-rival-600.device',

View File

@@ -220,9 +220,45 @@ ratbag_device_get_model(sd_bus *bus,
return sd_bus_message_append(reply, "s", model);
}
static int
ratbag_device_get_firmware_major(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error)
{
struct ratbagd_device *device = userdata;
int version = ratbag_device_get_firmware_major_version(device->lib_device);
CHECK_CALL(sd_bus_message_append(reply, "i", version));
return 0;
}
static int
ratbag_device_get_firmware_minor(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error)
{
struct ratbagd_device *device = userdata;
int version = ratbag_device_get_firmware_minor_version(device->lib_device);
CHECK_CALL(sd_bus_message_append(reply, "i", version));
return 0;
}
const sd_bus_vtable ratbagd_device_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Model", "s", ratbag_device_get_model, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("FirmwareMajor", "i", ratbag_device_get_firmware_major, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("FirmwareMinor", "i", ratbag_device_get_firmware_minor, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Name", "s", ratbagd_device_get_device_name, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Profiles", "ao", ratbagd_device_get_profiles, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_METHOD("Commit", "", "u", ratbagd_device_commit, SD_BUS_VTABLE_UNPRIVILEGED),

View File

@@ -515,7 +515,6 @@ int ratbagd_parse_json(const char *data, struct ratbag_test_device *device)
JsonArray *arr;
int r = -EINVAL;
g_autoptr(GError) error = NULL;
g_autoptr(GList) list = NULL;
error = 0;
parser = json_parser_new();
@@ -541,7 +540,7 @@ int ratbagd_parse_json(const char *data, struct ratbag_test_device *device)
num_buttons = device->num_buttons;
num_leds = device->num_leds;
list = json_array_get_elements(arr);
g_autoptr(GList) list = json_array_get_elements(arr);
GList *l = list;
int idx = 0;
while (l != NULL) {

View File

@@ -697,5 +697,5 @@ void ratbagd_schedule_task(struct ratbagd *ctx,
cb->callback = callback;
cb->userdata = userdata;
sd_event_add_defer(ctx->event, &source, ratbagd_callback_handler, cb);
sd_event_add_post(ctx->event, &source, ratbagd_callback_handler, cb);
}

View File

@@ -34,7 +34,7 @@
#include "libratbag-hidraw.h"
#define LOGITECH_G600_NUM_PROFILES 3
#define LOGITECH_G600_NUM_BUTTONS 41 // 20 buttons + 1 color buffer + 20 G-shift
#define LOGITECH_G600_NUM_BUTTONS 20
#define LOGITECH_G600_NUM_DPI 4
#define LOGITECH_G600_NUM_LED 1
#define LOGITECH_G600_DPI_MIN 200
@@ -109,41 +109,20 @@ static const struct logitech_g600_button_type_mapping logitech_g600_button_type_
{ 3, RATBAG_BUTTON_TYPE_WHEEL_LEFT },
{ 4, RATBAG_BUTTON_TYPE_WHEEL_RIGHT },
{ 5, RATBAG_BUTTON_TYPE_PINKIE },
{ 6, RATBAG_BUTTON_TYPE_PROFILE_CYCLE_UP }, // G07
{ 7, RATBAG_BUTTON_TYPE_RESOLUTION_CYCLE_UP }, // G08
{ 8, RATBAG_BUTTON_TYPE_SIDE }, // G09
{ 9, RATBAG_BUTTON_TYPE_SIDE }, // G10
{ 10, RATBAG_BUTTON_TYPE_SIDE }, // G11
{ 11, RATBAG_BUTTON_TYPE_SIDE }, // G12
{ 12, RATBAG_BUTTON_TYPE_SIDE }, // G13
{ 13, RATBAG_BUTTON_TYPE_SIDE }, // G14
{ 14, RATBAG_BUTTON_TYPE_SIDE }, // G15
{ 15, RATBAG_BUTTON_TYPE_SIDE }, // G16
{ 16, RATBAG_BUTTON_TYPE_SIDE }, // G17
{ 17, RATBAG_BUTTON_TYPE_SIDE }, // G18
{ 18, RATBAG_BUTTON_TYPE_SIDE }, // G19
{ 19, RATBAG_BUTTON_TYPE_SIDE }, // G20
{ 20, RATBAG_BUTTON_TYPE_UNKNOWN }, //HACK is where the G-shift color information is located
{ 21, RATBAG_BUTTON_TYPE_LEFT }, // G-shift + left
{ 22, RATBAG_BUTTON_TYPE_RIGHT }, // G-shift + right click
{ 23, RATBAG_BUTTON_TYPE_MIDDLE }, // G-shift + middle
{ 24, RATBAG_BUTTON_TYPE_WHEEL_LEFT}, // G-shift + scroll left
{ 25, RATBAG_BUTTON_TYPE_WHEEL_RIGHT}, // G-shift + scroll right
{ 26, RATBAG_BUTTON_TYPE_PINKIE }, // G-shift + Pinky(shift modifer)
{ 27, RATBAG_BUTTON_TYPE_PROFILE_CYCLE_UP }, // G-shift + 07
{ 28, RATBAG_BUTTON_TYPE_RESOLUTION_CYCLE_UP }, // G-shift + G08
{ 29, RATBAG_BUTTON_TYPE_SIDE }, // G-shift + G09
{ 30, RATBAG_BUTTON_TYPE_SIDE }, // G-shift + G10
{ 31, RATBAG_BUTTON_TYPE_SIDE }, // G-shift + G11
{ 32, RATBAG_BUTTON_TYPE_SIDE }, // G-shift + G12
{ 33, RATBAG_BUTTON_TYPE_SIDE }, // G-shift + G13
{ 34, RATBAG_BUTTON_TYPE_SIDE }, // G-shift + G14
{ 35, RATBAG_BUTTON_TYPE_SIDE }, // G-shift + G15
{ 36, RATBAG_BUTTON_TYPE_SIDE }, // G-shift + G16
{ 37, RATBAG_BUTTON_TYPE_SIDE }, // G-shift + G17
{ 38, RATBAG_BUTTON_TYPE_SIDE }, // G-shift + G18
{ 39, RATBAG_BUTTON_TYPE_SIDE }, // G-shift + G19
{ 40, RATBAG_BUTTON_TYPE_SIDE }, // G-shift + G20
{ 6, RATBAG_BUTTON_TYPE_PROFILE_CYCLE_UP },
{ 7, RATBAG_BUTTON_TYPE_RESOLUTION_CYCLE_UP },
{ 8, RATBAG_BUTTON_TYPE_SIDE }, // 8 = G9 ... 19 = G20
{ 9, RATBAG_BUTTON_TYPE_SIDE },
{ 10, RATBAG_BUTTON_TYPE_SIDE },
{ 11, RATBAG_BUTTON_TYPE_SIDE },
{ 12, RATBAG_BUTTON_TYPE_SIDE },
{ 13, RATBAG_BUTTON_TYPE_SIDE },
{ 14, RATBAG_BUTTON_TYPE_SIDE },
{ 15, RATBAG_BUTTON_TYPE_SIDE },
{ 16, RATBAG_BUTTON_TYPE_SIDE },
{ 17, RATBAG_BUTTON_TYPE_SIDE },
{ 18, RATBAG_BUTTON_TYPE_SIDE },
{ 19, RATBAG_BUTTON_TYPE_SIDE },
};
static enum ratbag_button_type
@@ -165,7 +144,7 @@ struct logitech_g600_button_mapping {
};
static struct logitech_g600_button_mapping logitech_g600_button_mapping[] = {
/* 0x00 is either key or unassigned. Must be handled separately */
/* 0x00 is either key or unassigned. Must be handled separatly */
{ 0x01, BUTTON_ACTION_BUTTON(1) },
{ 0x02, BUTTON_ACTION_BUTTON(2) },
{ 0x03, BUTTON_ACTION_BUTTON(3) },
@@ -621,12 +600,6 @@ logitech_g600_write_profile(struct ratbag_profile *profile)
report->led_duration = 0x0f;
}
// For now the default will copy over the main color into the g-shift color
// future update may add support to set this via cli command
report->g_shift_color[0] = report->led_red;
report->g_shift_color[1] = report->led_green;
report->g_shift_color[2] = report->led_blue;
buf = (uint8_t*)report;
rc = ratbag_hidraw_raw_request(device, report->id,

View File

@@ -1,482 +0,0 @@
/*
* Copyright © 2021 Filipe Laíns
*
* 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.
*/
#include "config.h"
#include "libratbag-private.h"
/* reports */
#define OI_REPORT_SHORT 0x20
#define OI_REPORT_LONG 0x21
#define OI_REPORT_SHORT_SIZE 8
#define OI_REPORT_LONG_SIZE 32
#define OI_REPORT_MAX_SIZE OI_REPORT_LONG_SIZE
#define OI_REPORT_DATA_INDEX 3
#define OI_REPORT_DATA_MAX_SIZE OI_REPORT_LONG_SIZE - OI_REPORT_DATA_INDEX
/* protocol function pages */
#define OI_PAGE_INFO 0x00
#define OI_PAGE_GIMMICKS 0xFD
#define OI_PAGE_DEBUG 0xFE
#define OI_PAGE_ERROR 0xFF
/* info page (0x00) functions */
#define OI_FUNCTION_VERSION 0x00
#define OI_FUNCTION_FW_INFO 0x01
#define OI_FUNCTION_SUPPORTED_FUNCTION_PAGES 0x02
#define OI_FUNCTION_SUPPORTED_FUNCTIONS 0x03
/* error page (0xFF) */
#define OI_ERROR_INVALID_VALUE 0x01
#define OI_ERROR_UNSUPPORTED_FUNCTION 0x02
#define OI_ERROR_CUSTOM 0xFE
static unsigned int report_rates[] = { 125, 250, 500, 750, 1000 };
struct openinput_drv_data {
unsigned int num_profiles;
unsigned int num_resolutions;
unsigned int num_buttons;
unsigned int num_leds;
unsigned int fw_major;
unsigned int fw_minor;
unsigned int fw_patch;
uint64_t supported;
};
struct oi_report_t {
uint8_t id;
uint8_t function_page;
uint8_t function;
uint8_t data[29];
} __attribute__((__packed__));
#define CASE_RETURN_STRING(a) case a: return #a; break
static const char*
openinput_function_page_get_name(uint8_t page)
{
static char numeric[16];
char *str;
switch(page) {
CASE_RETURN_STRING(OI_PAGE_INFO);
CASE_RETURN_STRING(OI_PAGE_GIMMICKS);
CASE_RETURN_STRING(OI_PAGE_DEBUG);
CASE_RETURN_STRING(OI_PAGE_ERROR);
default:
sprintf_safe(numeric, "0x%02x", page);
str = numeric;
break;
}
return str;
}
static const char*
openinput_function_get_name(uint8_t page, uint8_t function)
{
static char numeric[32];
char *str = NULL;
switch(page) {
case OI_PAGE_INFO:
switch (function) {
CASE_RETURN_STRING(OI_FUNCTION_VERSION);
CASE_RETURN_STRING(OI_FUNCTION_FW_INFO);
CASE_RETURN_STRING(OI_FUNCTION_SUPPORTED_FUNCTION_PAGES);
CASE_RETURN_STRING(OI_FUNCTION_SUPPORTED_FUNCTIONS);
}
}
if (!str) {
sprintf_safe(numeric, "0x%02x 0x%02x", page, function);
str = numeric;
}
return str;
}
#undef CASE_RETURN_STRING
static const char*
openinput_get_error_string(struct oi_report_t *report)
{
char help_str[OI_REPORT_LONG_SIZE - OI_REPORT_DATA_INDEX + 1] = {0};
char *str;
switch (report->function) {
case OI_ERROR_INVALID_VALUE:
xasprintf(&str, "Invalid value (in position %u)", report->data[2]);
break;
case OI_ERROR_CUSTOM:
memcpy(help_str, report->data, sizeof(help_str)-1); /* copy error string */
xasprintf(&str, "Custom error (%s)", help_str);
break;
case OI_ERROR_UNSUPPORTED_FUNCTION:
xasprintf(&str, "Unsupported function (0x%02x, 0x%02x)", report->data[0], report->data[1]);
break;
default:
xasprintf(&str, "Unkown error (%u)", report->function);
break;
}
return str;
}
static size_t
openinput_get_report_size(unsigned int report)
{
switch (report) {
case OI_REPORT_SHORT:
return OI_REPORT_SHORT_SIZE;
case OI_REPORT_LONG:
return OI_REPORT_LONG_SIZE;
default:
return 0;
}
}
static int
openinput_send_report(struct ratbag_device *device, struct oi_report_t *report)
{
int ret;
uint8_t buffer[OI_REPORT_MAX_SIZE];
size_t size = openinput_get_report_size(report->id);
memcpy(buffer, report, size);
ret = ratbag_hidraw_output_report(device, buffer, size);
if (ret < 0) {
log_error(device->ratbag, "openinput: failed to send data to device (%s)\n",
strerror(-ret));
return ret;
}
ret = ratbag_hidraw_read_input_report(device, buffer, OI_REPORT_MAX_SIZE);
if (ret < 0) {
log_error(device->ratbag, "openinput: failed to read data from device (%s)\n",
strerror(-ret));
return ret;
}
memcpy(report, buffer, openinput_get_report_size(buffer[0]));
/* check for error */
if (report->function_page == OI_PAGE_ERROR) {
log_error(device->ratbag, "openinput: %s\n", openinput_get_error_string(report));
return report->function;
}
return 0;
}
static int
openinput_info_version(struct ratbag_device *device)
{
int ret;
struct openinput_drv_data *drv_data = ratbag_get_drv_data(device);
struct oi_report_t report = {
.id = OI_REPORT_SHORT,
.function_page = OI_PAGE_INFO,
.function = OI_FUNCTION_VERSION
};
ret = openinput_send_report(device, &report);
if (ret)
return ret;
drv_data->fw_major = report.data[0];
drv_data->fw_minor = report.data[1];
drv_data->fw_patch = report.data[2];
log_info(device->ratbag, "openinput: protocol version %u.%u.%u\n",
drv_data->fw_major, drv_data->fw_minor, drv_data->fw_patch);
return 0;
}
#define OI_FUNCTION_FW_INFO_VENDOR 0x00
#define OI_FUNCTION_FW_INFO_VERSION 0x01
#define OI_FUNCTION_FW_INFO_DEVICE_NAME 0x02
static int
openinput_info_fw_info(struct ratbag_device *device,
uint8_t field_id,
unsigned char *description,
size_t description_size)
{
int ret;
struct oi_report_t report = {
.id = OI_REPORT_SHORT,
.function_page = OI_PAGE_INFO,
.function = OI_FUNCTION_FW_INFO,
.data = {field_id}
};
ret = openinput_send_report(device, &report);
if (ret)
return ret;
memcpy(description, report.data, min(sizeof(report.data), description_size));
return 0;
}
static int
openinput_info_supported_function_pages(struct ratbag_device *device,
uint8_t start_index,
uint8_t *pages_count,
uint8_t *pages_left,
uint8_t *pages,
size_t pages_size)
{
int ret;
struct oi_report_t report = {
.id = OI_REPORT_SHORT,
.function_page = OI_PAGE_INFO,
.function = OI_FUNCTION_SUPPORTED_FUNCTION_PAGES,
.data = {start_index}
};
ret = openinput_send_report(device, &report);
if (ret)
return ret;
*pages_count = report.data[0];
*pages_left = report.data[1];
memcpy(pages, report.data + 2, min(sizeof(report.data), pages_size));
return 0;
}
static int
openinput_info_supported_functions(struct ratbag_device *device,
uint8_t function_page,
uint8_t start_index,
uint8_t *functions_count,
uint8_t *functions_left,
uint8_t *functions,
size_t functions_size)
{
int ret;
struct oi_report_t report = {
.id = OI_REPORT_SHORT,
.function_page = OI_PAGE_INFO,
.function = OI_FUNCTION_SUPPORTED_FUNCTIONS,
.data = {function_page, start_index}
};
ret = openinput_send_report(device, &report);
if (ret)
return ret;
*functions_count = report.data[0];
*functions_left = report.data[1];
memcpy(functions, report.data + 2, min(sizeof(report.data), functions_size));
return 0;
}
static int
openinput_read_supported_functions(struct ratbag_device *device, uint8_t page)
{
struct ratbag *ratbag = device->ratbag;
int ret;
uint8_t i, total, read = 0, count = 0, left = 0;
uint8_t buffer[OI_REPORT_DATA_MAX_SIZE];
ret = openinput_info_supported_functions(device,
page,
read,
&count, &left,
buffer, sizeof(buffer));
if (ret)
return ret;
total = count + left;
uint8_t functions[total];
memcpy(functions, buffer, count);
/* there are still functions left to read! */
while (left) {
ret = openinput_info_supported_functions(device,
page,
read,
&count, &left,
buffer, sizeof(buffer));
if (ret)
return ret;
/* make sure the new size values make sense, to avoid deadlocks */
if (total != (read + count + left)) {
log_error(ratbag, "openinput: invalid number of functions left to read (%u)\n", left);
return -EINVAL;
}
log_debug(ratbag, "openinput: read %u functions, %u left\n", count, left);
memcpy(functions + read, buffer, count);
read += count;
}
/* iterate over read functions */
for (i = 0; i < total; i++) {
log_debug(ratbag, "openinput: found function %s\n", openinput_function_get_name(page, functions[i]));
/* TODO: set bits in drv_data->supported when we implement support for certain capabilities */
}
return 0;
}
static int
openinput_read_supported_function_pages(struct ratbag_device *device)
{
struct ratbag *ratbag = device->ratbag;
int ret;
uint8_t i, total, read = 0, count = 0, left = 0;
uint8_t buffer[OI_REPORT_DATA_MAX_SIZE];
log_debug(ratbag, "openinput: starting reading device functions...\n");
ret = openinput_info_supported_function_pages(device,
read,
&count, &left,
buffer, sizeof(buffer));
if (ret)
return ret;
total = count + left;
uint8_t pages[total];
memcpy(pages, buffer, count);
/* there are still function pages left to read! */
while (left) {
ret = openinput_info_supported_function_pages(device,
read,
&count, &left,
buffer, sizeof(buffer));
if (ret)
return ret;
/* make sure the new size values make sense, to avoid deadlocks */
if (total != (read + count + left)) {
log_error(ratbag, "openinput: invalid number of function pages left to read (%u)\n", left);
return -EINVAL;
}
log_debug(ratbag, "openinput: read %u pages, %u left\n", count, left);
memcpy(pages + read, buffer, count);
read += count;
}
/* iterate over read function pages, and read their functions */
for (i = 0; i < total; i++) {
log_debug(ratbag, "openinput: found function page %s\n", openinput_function_page_get_name(pages[i]));
openinput_read_supported_functions(device, pages[i]);
}
return 0;
}
static void
openinput_read_profile(struct ratbag_profile *profile)
{
ratbag_profile_set_report_rate_list(profile, report_rates, sizeof(*report_rates));
profile->is_active = true;
}
static int
openinput_test_hidraw(struct ratbag_device *device)
{
return ratbag_hidraw_has_report(device, OI_REPORT_SHORT);
}
static int
openinput_probe(struct ratbag_device *device)
{
int ret;
struct openinput_drv_data *drv_data;
struct ratbag_profile *profile;
unsigned char str[OI_REPORT_DATA_MAX_SIZE];
ret = ratbag_find_hidraw(device, openinput_test_hidraw);
if (ret)
return ret;
drv_data = zalloc(sizeof(*drv_data));
drv_data->num_profiles = 1;
ratbag_set_drv_data(device, drv_data);
openinput_info_version(device);
ret = openinput_info_fw_info(device, OI_FUNCTION_FW_INFO_VENDOR, str, sizeof(str));
if (ret)
return ret;
log_info(device->ratbag, "openinput: firmware vendor: %s\n", str);
ret = openinput_info_fw_info(device, OI_FUNCTION_FW_INFO_VERSION, str, sizeof(str));
if (ret)
return ret;
log_info(device->ratbag, "openinput: firmware version: %s\n", str);
ret = openinput_info_fw_info(device, OI_FUNCTION_FW_INFO_DEVICE_NAME, str, sizeof(str));
if (ret)
return ret;
log_info(device->ratbag, "openinput: device: %s\n", str);
ret = openinput_read_supported_function_pages(device);
if (ret)
return ret;
ratbag_device_init_profiles(device,
drv_data->num_profiles,
drv_data->num_resolutions,
drv_data->num_buttons,
drv_data->num_leds);
ratbag_device_for_each_profile(device, profile)
openinput_read_profile(profile);
return 0;
}
static void
openinput_remove(struct ratbag_device *device)
{
ratbag_close_hidraw(device);
free(ratbag_get_drv_data(device));
}
struct ratbag_driver openinput_driver = {
.name = "openinput",
.id = "openinput",
.probe = openinput_probe,
.remove = openinput_remove,
};

View File

@@ -21,7 +21,6 @@
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include "libratbag-enums.h"
#include "libratbag-hidraw.h"
#include "libratbag-private.h"

View File

@@ -245,20 +245,6 @@ sinowealth_read_profile(struct ratbag_profile *profile)
unsigned int hz = 1000; /* TODO */
int rc;
/* Print firmware version */
uint8_t version[6] = {SINOWEALTH_REPORT_ID_CMD, SINOWEALTH_CMD_FIRMWARE_VERSION};
rc = ratbag_hidraw_set_feature_report(device, SINOWEALTH_REPORT_ID_CMD, version, sizeof(version));
if (rc != sizeof(version)) {
log_error(device->ratbag, "Error while sending read firmware version command: %d\n", rc);
return -1;
}
rc = ratbag_hidraw_get_feature_report(device, SINOWEALTH_REPORT_ID_CMD, version, sizeof(version));
if (rc != sizeof(version)) {
log_error(device->ratbag, "Could not read firmware version: %d\n", rc);
return -1;
}
log_debug(device->ratbag, "firmware version: %.4s\n", version + 2);
uint8_t cmd[6] = {SINOWEALTH_REPORT_ID_CMD, SINOWEALTH_CMD_GET_CONFIG};
rc = ratbag_hidraw_set_feature_report(device, SINOWEALTH_REPORT_ID_CMD, cmd, sizeof(cmd));
if (rc != sizeof(cmd)) {
@@ -291,7 +277,7 @@ sinowealth_read_profile(struct ratbag_profile *profile)
resolution->dpi_x = 0;
resolution->dpi_y = 0;
}
resolution->is_active = resolution->index == config->active_dpi - 1u;
resolution->is_active = resolution->index == config->active_dpi - 1;
resolution->is_default = resolution->is_active;
}

View File

@@ -78,11 +78,6 @@
#define STEELSERIES_BUTTON_KBD 0x51
#define STEELSERIES_BUTTON_CONSUMER 0x61
struct steelseries_data {
int firmware_major;
int firmware_minor;
};
struct steelseries_point {
struct list link;
@@ -177,7 +172,6 @@ button_defaults_for_layout(struct ratbag_button *button, int button_count)
static int
steelseries_get_firmware_version(struct ratbag_device *device)
{
struct steelseries_data *drv_data = device->drv_data;
int device_version = ratbag_device_data_steelseries_get_device_version(device->data);
size_t buf_len = STEELSERIES_REPORT_SIZE;
uint8_t buf[STEELSERIES_REPORT_SIZE] = {0};
@@ -199,8 +193,8 @@ steelseries_get_firmware_version(struct ratbag_device *device)
if (ret < 0)
return ret;
drv_data->firmware_major = buf[1];
drv_data->firmware_minor = buf[0];
device->firmware_major = buf[1];
device->firmware_minor = buf[0];
return 0;
}
@@ -265,7 +259,6 @@ steelseries_read_settings(struct ratbag_device *device)
static int
steelseries_probe(struct ratbag_device *device)
{
struct steelseries_data *drv_data = NULL;
struct ratbag_profile *profile = NULL;
struct ratbag_resolution *resolution;
struct ratbag_button *button;
@@ -363,14 +356,11 @@ steelseries_probe(struct ratbag_device *device)
}
}
drv_data = zalloc(sizeof(*drv_data));
ratbag_set_drv_data(device, drv_data);
rc = steelseries_get_firmware_version(device);
if(rc == 0)
log_debug(device->ratbag, "SteelSeries firmware version %d.%d\n",
drv_data->firmware_major,
drv_data->firmware_minor);
device->firmware_major,
device->firmware_minor);
steelseries_read_settings(device);
@@ -960,7 +950,6 @@ steelseries_remove(struct ratbag_device *device)
{
ratbag_close_hidraw_index(device, 0);
ratbag_close_hidraw_index(device, 1);
free(ratbag_get_drv_data(device));
}
struct ratbag_driver steelseries_driver = {

View File

@@ -34,7 +34,6 @@
#include "libratbag-private.h"
#include "libratbag-data.h"
#include "hidpp20.h"
#include "usb-ids.h"
#define GROUP_DEVICE "Device"
@@ -54,7 +53,6 @@ enum driver {
STEELSERIES,
SINOWEALTH,
SINOWEALTH_NUBWO,
OPENINPUT,
};
struct data_hidpp20 {
@@ -273,7 +271,6 @@ static const struct driver_map {
{ STEELSERIES, "steelseries", init_data_steelseries },
{ SINOWEALTH, "sinowealth", NULL },
{ SINOWEALTH_NUBWO, "sinowealth_nubwo", NULL},
{ OPENINPUT, "openinput", NULL },
};
const char *
@@ -520,9 +517,7 @@ ratbag_device_data_new_for_id(struct ratbag *ratbag, const struct input_id *id)
goto out;
}
if (id->vendor == USB_VENDOR_ID_LOGITECH && (id->product & 0xff00) == 0xc500)
log_debug(ratbag, "%04x:%04x is a Logitech receiver, not a device. Ignoring...\n", id->vendor, id->product);
else if (!data)
if (!data)
log_debug(ratbag, "No data file found for %04x:%04x\n", id->vendor, id->product);
out:

View File

@@ -147,6 +147,9 @@ struct ratbag_device {
unsigned num_buttons;
unsigned num_leds;
int firmware_major;
int firmware_minor;
void *drv_data;
struct list link;
@@ -597,7 +600,6 @@ extern struct ratbag_driver gskill_driver;
extern struct ratbag_driver steelseries_driver;
extern struct ratbag_driver sinowealth_driver;
extern struct ratbag_driver sinowealth_nubwo_driver;
extern struct ratbag_driver openinput_driver;
struct ratbag_device*
ratbag_device_new(struct ratbag *ratbag, struct udev_device *udev_device,

View File

@@ -545,6 +545,18 @@ ratbag_device_get_product_id(const struct ratbag_device *device)
return device->ids.product;
}
LIBRATBAG_EXPORT int32_t
ratbag_device_get_firmware_major_version(const struct ratbag_device *device)
{
return device->firmware_major;
}
LIBRATBAG_EXPORT int32_t
ratbag_device_get_firmware_minor_version(const struct ratbag_device *device)
{
return device->firmware_minor;
}
LIBRATBAG_EXPORT uint32_t
ratbag_device_get_product_version(const struct ratbag_device *device)
{
@@ -604,7 +616,6 @@ ratbag_create_context(const struct ratbag_interface *interface,
ratbag_register_driver(ratbag, &steelseries_driver);
ratbag_register_driver(ratbag, &sinowealth_driver);
ratbag_register_driver(ratbag, &sinowealth_nubwo_driver);
ratbag_register_driver(ratbag, &openinput_driver);
return ratbag;
}

View File

@@ -421,6 +421,24 @@ ratbag_device_set_user_data(struct ratbag_device *device, void *userdata);
void*
ratbag_device_get_user_data(const struct ratbag_device *device);
/**
* @ingroup device
*
* @param device A previously initialized ratbag device
* @return The firmware major version of the device.
*/
int32_t
ratbag_device_get_firmware_major_version(const struct ratbag_device *device);
/**
* @ingroup device
*
* @param device A previously initialized ratbag device
* @return The firmware minor version of the device.
*/
int32_t
ratbag_device_get_firmware_minor_version(const struct ratbag_device *device);
/**
* @ingroup device
*

View File

@@ -212,6 +212,8 @@ def print_device(d, level):
print(" " * level + "{} - {}".format(d.id, d.name))
print(" " * level + " Model: {}".format(d.model))
if d.firmware_major > 0 or d.firmware_minor > 0:
print(" " * level + " Firmware version: {}.{}".format(d.firmware_major, d.firmware_minor))
print(" " * level + " Number of Buttons: {}".format(len(p.buttons)))
print(" " * level + " Number of Leds: {}".format(len(p.leds)))
print(" " * level + "Number of Profiles: {}".format(len(d.profiles)))

View File

@@ -342,6 +342,16 @@ class RatbagdDevice(_RatbagdDBus):
"""The unique identifier for this device model."""
return self._get_dbus_property("Model")
@GObject.Property
def firmware_major(self):
"""The firmware major version."""
return self._get_dbus_property("FirmwareMajor")
@GObject.Property
def firmware_minor(self):
"""The firmware minor version."""
return self._get_dbus_property("FirmwareMinor")
@GObject.Property
def name(self):
"""The device name, usually provided by the kernel."""