forked from drath/libratbag
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce377fc36c | ||
|
|
fe1308fe38 | ||
|
|
983d3e2a88 | ||
|
|
3a3d9e1148 | ||
|
|
afbba26feb | ||
|
|
8cc37047fb | ||
|
|
c8f56cc535 | ||
|
|
b6936ddd3b | ||
|
|
d4d9712316 | ||
|
|
2353af214b | ||
|
|
a4d19efb93 | ||
|
|
cb0b458824 | ||
|
|
48c476b28c | ||
|
|
d6c3bf881d | ||
|
|
1b000e627a | ||
|
|
75bcf39114 | ||
|
|
33ced3dfb7 | ||
|
|
906f17add2 | ||
|
|
016de548fc | ||
|
|
665c022382 | ||
|
|
81c7b42bec | ||
|
|
edb054c6f8 | ||
|
|
8ae995b72d | ||
|
|
a941b75ef2 | ||
|
|
8cb85da6be | ||
|
|
7ff59a636f | ||
|
|
6cd050f541 |
@@ -169,7 +169,7 @@ def check_section_hidpp10(section):
|
||||
|
||||
|
||||
def check_section_hidpp20(section):
|
||||
permitted = ['DeviceIndex']
|
||||
permitted = ['DeviceIndex', 'Quirk']
|
||||
for key in section.keys():
|
||||
assertIn(key, permitted)
|
||||
|
||||
|
||||
5
data/devices/logitech-MX-Master-3.device
Normal file
5
data/devices/logitech-MX-Master-3.device
Normal file
@@ -0,0 +1,5 @@
|
||||
# Logitech MX Master 3
|
||||
[Device]
|
||||
Name=Logitech MX Master 3
|
||||
DeviceMatch=bluetooth:046d:b023;usb:046d:4082
|
||||
Driver=hidpp20
|
||||
@@ -1,5 +1,5 @@
|
||||
# Logitech MX Master
|
||||
[Device]
|
||||
Name=Logitech MX Master
|
||||
DeviceMatch=usb:046d:4041;bluetooth:046d:b012;usb:046d:4060;bluetooth:046d:b017
|
||||
DeviceMatch=usb:046d:4041;bluetooth:046d:b012;usb:046d:4060;bluetooth:046d:b017;bluetooth:046d:b01e;usb:046d:4071
|
||||
Driver=hidpp20
|
||||
|
||||
7
data/devices/logitech-g305.device
Normal file
7
data/devices/logitech-g305.device
Normal file
@@ -0,0 +1,7 @@
|
||||
[Device]
|
||||
Name=Logitech Gaming Mouse G305
|
||||
DeviceMatch=usb:046d:4074
|
||||
Driver=hidpp20
|
||||
|
||||
[Driver/hidpp20]
|
||||
Quirk=G305
|
||||
4
data/devices/logitech-g502-hero-wireless.device
Normal file
4
data/devices/logitech-g502-hero-wireless.device
Normal file
@@ -0,0 +1,4 @@
|
||||
[Device]
|
||||
Name=Logitech G502 Hero Wireless
|
||||
DeviceMatch=usb:046d:407f;usb:046d:c08d
|
||||
Driver=hidpp20
|
||||
@@ -6,3 +6,4 @@ Driver=hidpp20
|
||||
|
||||
[Driver/hidpp20]
|
||||
DeviceIndex=1
|
||||
Quirk=G602
|
||||
|
||||
4
data/devices/logitech-g604.device
Normal file
4
data/devices/logitech-g604.device
Normal file
@@ -0,0 +1,4 @@
|
||||
[Device]
|
||||
Name=Logitech G604
|
||||
DeviceMatch=usb:046d:4085;bluetooth:046d:b024
|
||||
Driver=hidpp20
|
||||
11
data/devices/steelseries-kinzu-v3.device
Normal file
11
data/devices/steelseries-kinzu-v3.device
Normal file
@@ -0,0 +1,11 @@
|
||||
[Device]
|
||||
Name=SteelSeries Kinzu V3
|
||||
DeviceMatch=usb:1038:1388
|
||||
Driver=steelseries
|
||||
|
||||
[Driver/steelseries]
|
||||
DeviceVersion=1
|
||||
Buttons=3
|
||||
Leds=0
|
||||
DpiList=400;800;1600;2000
|
||||
MacroLength=0
|
||||
20
meson.build
20
meson.build
@@ -1,5 +1,5 @@
|
||||
project('libratbag', 'c',
|
||||
version : '0.10',
|
||||
version : '0.11',
|
||||
license : 'MIT/Expat',
|
||||
default_options : [ 'c_std=gnu99', 'warning_level=2' ],
|
||||
meson_version : '>= 0.40.0')
|
||||
@@ -285,6 +285,7 @@ data_files = files(
|
||||
'data/devices/logitech-MX-Ergo.device',
|
||||
'data/devices/logitech-MX-Master.device',
|
||||
'data/devices/logitech-MX-Master-2S.device',
|
||||
'data/devices/logitech-MX-Master-3.device',
|
||||
'data/devices/logitech-MX518.device',
|
||||
'data/devices/logitech-T650.device',
|
||||
'data/devices/logitech-Wireless-Touchpad.device',
|
||||
@@ -294,6 +295,7 @@ data_files = files(
|
||||
'data/devices/logitech-g300.device',
|
||||
'data/devices/logitech-g302.device',
|
||||
'data/devices/logitech-g303.device',
|
||||
'data/devices/logitech-g305.device',
|
||||
'data/devices/logitech-g402.device',
|
||||
'data/devices/logitech-g403-hero.device',
|
||||
'data/devices/logitech-g403-wireless.device',
|
||||
@@ -302,12 +304,14 @@ data_files = files(
|
||||
'data/devices/logitech-g5.device',
|
||||
'data/devices/logitech-g500.device',
|
||||
'data/devices/logitech-g500s.device',
|
||||
'data/devices/logitech-g502-hero-wireless.device',
|
||||
'data/devices/logitech-g502-hero.device',
|
||||
'data/devices/logitech-g502-proteus-core.device',
|
||||
'data/devices/logitech-g502-proteus-spectrum.device',
|
||||
'data/devices/logitech-g600.device',
|
||||
'data/devices/logitech-g602.device',
|
||||
'data/devices/logitech-g603.device',
|
||||
'data/devices/logitech-g604.device',
|
||||
'data/devices/logitech-g7.device',
|
||||
'data/devices/logitech-g700-wireless.device',
|
||||
'data/devices/logitech-g700.device',
|
||||
@@ -326,6 +330,7 @@ data_files = files(
|
||||
'data/devices/logitech-MX-Vertical.device',
|
||||
'data/devices/roccat-kone-xtd.device',
|
||||
'data/devices/steelseries-kinzu-v2.device',
|
||||
'data/devices/steelseries-kinzu-v3.device',
|
||||
'data/devices/steelseries-rival-310.device',
|
||||
'data/devices/steelseries-rival-600.device',
|
||||
'data/devices/steelseries-rival.device',
|
||||
@@ -615,6 +620,19 @@ shared_library(
|
||||
install: false,
|
||||
)
|
||||
|
||||
i_source = join_paths(meson.source_root(), 'src', 'hidpp.i')
|
||||
c_source = swig_gen.process(i_source)
|
||||
shared_library(
|
||||
'hidpp',
|
||||
c_source,
|
||||
name_prefix: '_',
|
||||
c_args : ['-Wno-missing-prototypes', '-Wno-format-nonliteral'],
|
||||
extra_files: [ i_source ] + src_libratbag ,
|
||||
dependencies: deps_libratbag + wrapper_deps,
|
||||
include_directories : include_directories('src', 'tools'),
|
||||
install: false,
|
||||
)
|
||||
|
||||
# ratbagc is the layer that maps ratbagctl to the swig bindings
|
||||
ratbagc_py_conf = configuration_data()
|
||||
ratbagc_py_conf.set('LIBRATBAG_DATA_DIR', libratbag_data_dir_devel)
|
||||
|
||||
120
release.sh
120
release.sh
@@ -90,13 +90,11 @@ check_option_args() {
|
||||
#
|
||||
check_modules_specification() {
|
||||
|
||||
if [ x"$MODFILE" = x ]; then
|
||||
if [ x"${INPUT_MODULES}" = x ]; then
|
||||
echo ""
|
||||
echo "Error: no modules specified (blank command line)."
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
if [ x"${INPUT_MODULES}" = x ]; then
|
||||
echo ""
|
||||
echo "Error: no modules specified (blank command line)."
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
}
|
||||
@@ -112,7 +110,7 @@ Subject: [ANNOUNCE] $pkg_name $pkg_version
|
||||
To: $list_to
|
||||
Cc: $list_cc
|
||||
|
||||
libratbag $tag_name is out.
|
||||
$pkg_name $tag_name is out.
|
||||
|
||||
The list of interesting changes are:
|
||||
|
||||
@@ -129,43 +127,12 @@ RELEASE
|
||||
The libratbag project does not generate tarballs for releases, you can
|
||||
grab one directly from github:
|
||||
|
||||
https://github.com/libratbag/libratbag/archive/$tag_name/$tarball
|
||||
https://github.com/libratbag/$pkg_name/archive/$tag_name/$tarball
|
||||
|
||||
RELEASE
|
||||
done
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Function: read_modfile
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Read the module names from the file and set a variable to hold them
|
||||
# This will be the same interface as cmd line supplied modules
|
||||
#
|
||||
read_modfile() {
|
||||
|
||||
if [ x"$MODFILE" != x ]; then
|
||||
# Make sure the file is sane
|
||||
if [ ! -r "$MODFILE" ]; then
|
||||
echo "Error: module file '$MODFILE' is not readable or does not exist."
|
||||
exit 1
|
||||
fi
|
||||
# read from input file, skipping blank and comment lines
|
||||
while read line; do
|
||||
# skip blank lines
|
||||
if [ x"$line" = x ]; then
|
||||
continue
|
||||
fi
|
||||
# skip comment lines
|
||||
if echo "$line" | $GREP -q "^#" ; then
|
||||
continue;
|
||||
fi
|
||||
INPUT_MODULES="$INPUT_MODULES $line"
|
||||
done <"$MODFILE"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Function: print_epilog
|
||||
#------------------------------------------------------------------------------
|
||||
@@ -215,46 +182,6 @@ process_modules() {
|
||||
done
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Function: get_section
|
||||
#------------------------------------------------------------------------------
|
||||
# Code 'return 0' on success
|
||||
# Code 'return 1' on error
|
||||
# Sets global variable $section
|
||||
get_section() {
|
||||
local module_url
|
||||
local full_module_url
|
||||
|
||||
# Obtain the git url in order to find the section to which this module belongs
|
||||
full_module_url=`git config --get remote.$remote_name.url | sed 's:\.git$::'`
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error: unable to obtain git url for remote \"$remote_name\"."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# The last part of the git url will tell us the section. Look for xorg first
|
||||
echo "$full_module_url"
|
||||
module_url=`echo "$full_module_url" | $GREP -o "libratbag/.*"`
|
||||
if [ $? -eq 0 ]; then
|
||||
module_url=`echo $module_url | cut -d'/' -f2,3`
|
||||
else
|
||||
echo "Error: unable to locate a valid project url from \"$full_module_url\"."
|
||||
echo "Cannot establish url as one of libratbag"
|
||||
cd $top_src
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Find the section (subdirs) where the tarballs are to be uploaded
|
||||
# The module relative path can be app/xfs, xserver, or mesa/drm for example
|
||||
section=`echo $module_url | cut -d'/' -f1`
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error: unable to extract section from $module_url first field."
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Function: process_module
|
||||
#------------------------------------------------------------------------------
|
||||
@@ -299,26 +226,27 @@ process_module() {
|
||||
current_branch=`git branch | $GREP "\*" | sed -e "s/\* //"`
|
||||
remote_name=`git config --get branch.$current_branch.remote`
|
||||
remote_branch=`git config --get branch.$current_branch.merge | cut -d'/' -f3,4`
|
||||
remote_url_root="https://github.com/libratbag/libratbag/archive"
|
||||
echo "Info: working off the \"$current_branch\" branch tracking the remote \"$remote_name/$remote_branch\"."
|
||||
|
||||
# Obtain the section
|
||||
get_section
|
||||
if [ $? -ne 0 ]; then
|
||||
cd $top_src
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Find out the tarname from meson.build
|
||||
pkg_name=$($GREP '^project(' meson.build | sed 's|project(\([^\s,]*\).*|\1|' | sed "s/'//g")
|
||||
pkg_version=$($GREP -m 1 '^ version : ' meson.build | sed 's| version : \([^\s,]*\).*|\1|' | sed "s/'//g")
|
||||
pkg_version=$($GREP -m 1 '^[ ]*version \?: ' meson.build | sed 's|[ ]*version \?: \([^\s,]*\).*|\1|' | sed "s/'//g")
|
||||
tar_name="$pkg_name-$pkg_version"
|
||||
targz=$tar_name.tar.gz
|
||||
tag_name=$(echo "v$pkg_version" | sed 's|.0$||')
|
||||
# libratbag tags with v0.3 but piper user just 0.3
|
||||
case `git describe` in
|
||||
v*)
|
||||
tag_name=$(echo "v$pkg_version" | sed 's|\.0$||')
|
||||
;;
|
||||
*)
|
||||
tag_name=$(echo "$pkg_version" | sed 's|\.0$||')
|
||||
;;
|
||||
esac
|
||||
remote_url_root="https://github.com/libratbag/$pkg_name/archive"
|
||||
|
||||
# Now get the tarballs from github directly to compute their checksum
|
||||
remote_targz_url=$remote_url_root/$tag_name/$targz
|
||||
echo "downloading the tarbal from $remote_targz_url"
|
||||
echo "downloading the tarball from $remote_targz_url"
|
||||
curl $remote_targz_url > $targz
|
||||
|
||||
# Obtain the top commit SHA which should be the version bump
|
||||
@@ -513,13 +441,6 @@ do
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
if [ x"${MODFILE}" != x ]; then
|
||||
echo ""
|
||||
echo "Error: specifying both modules and --modfile is not permitted"
|
||||
echo ""
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
INPUT_MODULES="${INPUT_MODULES} $1"
|
||||
;;
|
||||
esac
|
||||
@@ -530,9 +451,6 @@ done
|
||||
# If no modules specified (blank cmd line) display help
|
||||
check_modules_specification
|
||||
|
||||
# Read the module file and normalize input in INPUT_MODULES
|
||||
read_modfile
|
||||
|
||||
# Loop through each module to release
|
||||
# Exit on error if --no-quit no specified
|
||||
process_modules
|
||||
|
||||
@@ -412,11 +412,11 @@ hidpp20drv_read_led_8071(struct ratbag_led *led, struct hidpp20drv_data* drv_dat
|
||||
struct hidpp20_profile *profile;
|
||||
struct hidpp20_led *h_led;
|
||||
struct hidpp20_rgb_device_info device_info;
|
||||
struct hidpp20_rgb_cluster_info *cluster_info;
|
||||
struct hidpp20_rgb_cluster_info cluster_info;
|
||||
int rc;
|
||||
|
||||
hidpp20_rgb_effects_get_device_info(drv_data->dev, &device_info);
|
||||
cluster_info = &drv_data->led_infos.color_leds_8071[led->index];
|
||||
cluster_info = drv_data->led_infos.color_leds_8071[led->index];
|
||||
profile = &drv_data->profiles->profiles[led->profile->index];
|
||||
h_led = &profile->leds[led->index];
|
||||
|
||||
@@ -437,7 +437,7 @@ hidpp20drv_read_led_8071(struct ratbag_led *led, struct hidpp20drv_data* drv_dat
|
||||
|
||||
/* pre-filled, only override if unknown */
|
||||
if (led->type == RATBAG_LED_TYPE_UNKNOWN)
|
||||
led->type = hidpp20_led_get_location_mapping(cluster_info->location);
|
||||
led->type = hidpp20_led_get_location_mapping(cluster_info.location);
|
||||
led->color.red = h_led->color.red;
|
||||
led->color.green = h_led->color.green;
|
||||
led->color.blue = h_led->color.blue;
|
||||
@@ -449,10 +449,10 @@ hidpp20drv_read_led_8071(struct ratbag_led *led, struct hidpp20drv_data* drv_dat
|
||||
else
|
||||
led->colordepth = RATBAG_LED_COLORDEPTH_RGB_888;
|
||||
|
||||
for (int i = 0; i < cluster_info->num_effects; i++) {
|
||||
for (int i = 0; i < cluster_info.num_effects; i++) {
|
||||
struct hidpp20_rgb_effect_info ei;
|
||||
rc = hidpp20_rgb_effects_get_effect_info(drv_data->dev,
|
||||
cluster_info->index,
|
||||
cluster_info.index,
|
||||
i, &ei);
|
||||
if (rc < 0)
|
||||
break;
|
||||
@@ -859,7 +859,8 @@ hidpp20drv_read_resolution_dpi(struct ratbag_profile *profile)
|
||||
unsigned int default_rate = 500;
|
||||
int rc;
|
||||
|
||||
if (drv_data->capabilities & HIDPP_CAP_RESOLUTION_2200) {
|
||||
if ((drv_data->capabilities & HIDPP_CAP_RESOLUTION_2200) &&
|
||||
(drv_data->capabilities & HIDPP_CAP_SWITCHABLE_RESOLUTION_2201) == 0) {
|
||||
uint16_t resolution;
|
||||
uint8_t flags;
|
||||
|
||||
@@ -928,6 +929,9 @@ hidpp20drv_update_resolution_dpi_8100(struct ratbag_resolution *resolution,
|
||||
h_profile = &drv_data->profiles->profiles[profile->index];
|
||||
h_profile->dpi[resolution->index] = dpi;
|
||||
|
||||
if (resolution->is_default)
|
||||
h_profile->default_dpi = resolution->index;
|
||||
|
||||
return RATBAG_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1302,6 +1306,11 @@ hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature)
|
||||
break;
|
||||
}
|
||||
case HIDPP_PAGE_COLOR_LED_EFFECTS: {
|
||||
/* The 8070 feauture implemented in the G602 doesn't follow the spec,
|
||||
* so we ignore it */
|
||||
if (ratbag_device_data_hidpp20_get_quirk(device->data) == HIDPP20_QUIRK_G602)
|
||||
break;
|
||||
|
||||
log_debug(ratbag, "device has color effects\n");
|
||||
drv_data->capabilities |= HIDPP_CAP_COLOR_LED_EFFECTS_8070;
|
||||
|
||||
@@ -1513,6 +1522,7 @@ hidpp20drv_init_device(struct ratbag_device *device,
|
||||
struct hidpp20drv_data *drv_data)
|
||||
{
|
||||
struct ratbag_profile *profile;
|
||||
bool active_profile = false;
|
||||
|
||||
ratbag_device_init_profiles(device,
|
||||
drv_data->num_profiles,
|
||||
@@ -1522,6 +1532,18 @@ hidpp20drv_init_device(struct ratbag_device *device,
|
||||
|
||||
ratbag_device_for_each_profile(device, profile)
|
||||
hidpp20drv_read_profile(profile);
|
||||
|
||||
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100) {
|
||||
/* Fallback to the first profile if no profile is active */
|
||||
list_for_each(profile, &device->profiles, link)
|
||||
if (profile->is_active)
|
||||
active_profile = true;
|
||||
|
||||
if (!active_profile && device->num_profiles >= 1) {
|
||||
profile = ratbag_device_get_profile(device, 0);
|
||||
profile->is_active = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1560,10 +1582,15 @@ hidpp20drv_probe(struct ratbag_device *device)
|
||||
goto err;
|
||||
}
|
||||
|
||||
dev->quirk = ratbag_device_data_hidpp20_get_quirk(device->data);
|
||||
|
||||
drv_data->dev = dev;
|
||||
|
||||
log_debug(device->ratbag, "'%s' is using protocol v%d.%d\n", ratbag_device_get_name(device), dev->proto_major, dev->proto_minor);
|
||||
|
||||
if(dev->quirk != HIDPP20_QUIRK_NONE)
|
||||
log_debug(device->ratbag, "'%s' is quirked (%s)\n", ratbag_device_get_name(device), hidpp20_get_quirk_string(dev->quirk));
|
||||
|
||||
/* add some defaults that will be overwritten by the device */
|
||||
drv_data->num_profiles = 1;
|
||||
drv_data->num_resolutions = 1;
|
||||
|
||||
23
src/hidpp.i
Normal file
23
src/hidpp.i
Normal file
@@ -0,0 +1,23 @@
|
||||
/* wrapping libratbag functions from hidpp*.h using SWIG. */
|
||||
|
||||
%module hidpp
|
||||
%{
|
||||
/* the resulting C file should be built as a python extension */
|
||||
#define SWIG_FILE_WITH_INIT
|
||||
/* Includes the header in the wrapper code */
|
||||
#include <shared.h>
|
||||
#include <hidpp-generic.h>
|
||||
#include <hidpp20.h>
|
||||
%}
|
||||
#define __attribute__(x)
|
||||
#define _Static_assert(a,b)
|
||||
|
||||
|
||||
/* Parse the header file to generate wrappers */
|
||||
%include "stdint.i"
|
||||
%include "cpointer.i"
|
||||
%pointer_functions(int, intp);
|
||||
%pointer_functions(uint8_t, uint8_tp);
|
||||
%pointer_functions(uint16_t, uint16_tp);
|
||||
%include "hidpp-generic.h"
|
||||
%include "hidpp20.h"
|
||||
@@ -833,6 +833,20 @@ hidpp10_get_current_profile(struct hidpp10_device *dev, uint8_t *current_profile
|
||||
"unable to find the profile at (%d,%d) in the directory\n",
|
||||
page, offset);
|
||||
break;
|
||||
case PROFILE_TYPE_FACTORY:
|
||||
/* Factory profile is selected and profile switching is
|
||||
* disabled. Let's switch to the first profile because the
|
||||
* factory profile doesn't help anywone */
|
||||
res = hidpp10_set_current_profile(dev, 0);
|
||||
if (res == 0) {
|
||||
hidpp_log_info(&dev->base, "switched from factory profile to 0\n");
|
||||
*current_profile = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
hidpp_log_error(&dev->base,
|
||||
"current profile is factory profile but switching to 0 failed.\n");
|
||||
break;
|
||||
default:
|
||||
hidpp_log_error(&dev->base,
|
||||
"Unexpected value: %02x\n",
|
||||
@@ -2737,8 +2751,7 @@ hidpp10_get_device_info(struct hidpp10_device *dev)
|
||||
|
||||
hidpp10_get_optical_sensor_settings(dev, &reflect);
|
||||
|
||||
hidpp10_get_current_profile(dev, ¤t_profile);
|
||||
return 0;
|
||||
return hidpp10_get_current_profile(dev, ¤t_profile);
|
||||
}
|
||||
|
||||
struct hidpp10_device*
|
||||
|
||||
@@ -48,7 +48,6 @@ hidpp20_feature_get_name(uint16_t feature)
|
||||
{
|
||||
static char numeric[8];
|
||||
const char *str;
|
||||
#define CASE_RETURN_STRING(a) case a: return #a; break
|
||||
|
||||
switch(feature)
|
||||
{
|
||||
@@ -99,11 +98,22 @@ hidpp20_sw_led_control_get_mode_string(const enum hidpp20_led_sw_ctrl_led_mode m
|
||||
str = numeric;
|
||||
break;
|
||||
}
|
||||
#undef CASE_RETURN_STRING
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
const char*
|
||||
hidpp20_get_quirk_string(enum hidpp20_quirk quirk)
|
||||
{
|
||||
switch (quirk) {
|
||||
CASE_RETURN_STRING(HIDPP20_QUIRK_NONE);
|
||||
CASE_RETURN_STRING(HIDPP20_QUIRK_G305);
|
||||
CASE_RETURN_STRING(HIDPP20_QUIRK_G602);
|
||||
}
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
static int
|
||||
hidpp20_request_command_allow_error(struct hidpp20_device *device, union hidpp20_message *msg,
|
||||
bool allow_error)
|
||||
@@ -1073,8 +1083,8 @@ hidpp20_rgb_effects_get_cluster_info(struct hidpp20_device *device,
|
||||
info->effect_index = msg.msg.parameters[1];
|
||||
|
||||
info->location = get_unaligned_be_u16(&msg.msg.parameters[2]);
|
||||
info->num_effects = get_unaligned_be_u16(&msg.msg.parameters[4]);
|
||||
info->persistency_caps = get_unaligned_be_u16(&msg.msg.parameters[6]);
|
||||
info->num_effects = msg.msg.parameters[4];
|
||||
info->persistency_caps = msg.msg.parameters[5];
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1432,6 +1442,11 @@ hidpp20_adjustable_dpi_get_dpi_list(struct hidpp20_device *device,
|
||||
.msg.parameters[0] = sensor->index,
|
||||
};
|
||||
|
||||
if (device->quirk == HIDPP20_QUIRK_G602) {
|
||||
msg.msg.parameters[0] = 1;
|
||||
i = 0;
|
||||
}
|
||||
|
||||
rc = hidpp20_request_command(device, &msg);
|
||||
if (rc)
|
||||
return rc;
|
||||
@@ -1443,6 +1458,9 @@ hidpp20_adjustable_dpi_get_dpi_list(struct hidpp20_device *device,
|
||||
get_unaligned_be_u16(&msg.msg.parameters[i]) != 0) {
|
||||
uint16_t value = get_unaligned_be_u16(&msg.msg.parameters[i]);
|
||||
|
||||
if (device->quirk == HIDPP20_QUIRK_G602 && i == 2)
|
||||
value += 0xe000;
|
||||
|
||||
if (value > 0xe000) {
|
||||
sensor->dpi_steps = value - 0xe000;
|
||||
} else {
|
||||
@@ -1472,6 +1490,9 @@ hidpp20_adjustable_dpi_get_dpi(struct hidpp20_device *device,
|
||||
.msg.parameters[0] = sensor->index,
|
||||
};
|
||||
|
||||
if (device->quirk == HIDPP20_QUIRK_G602)
|
||||
msg.msg.parameters[0] = 1;
|
||||
|
||||
rc = hidpp20_request_command(device, &msg);
|
||||
if (rc)
|
||||
return rc;
|
||||
@@ -1551,6 +1572,9 @@ int hidpp20_adjustable_dpi_set_sensor_dpi(struct hidpp20_device *device,
|
||||
.msg.parameters[0] = sensor->index,
|
||||
};
|
||||
|
||||
if (device->quirk == HIDPP20_QUIRK_G602)
|
||||
msg.msg.parameters[0] = 1;
|
||||
|
||||
set_unaligned_be_u16(&msg.msg.parameters[1], dpi);
|
||||
|
||||
feature_index = hidpp_root_get_feature_idx(device,
|
||||
@@ -1634,7 +1658,7 @@ int hidpp20_adjustable_report_rate_get_report_rate_list(struct hidpp20_device *d
|
||||
#define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G402 0x01
|
||||
#define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G303 0x02
|
||||
#define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G900 0x03
|
||||
#define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G903_HERO 0x04
|
||||
#define HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G915 0x04
|
||||
#define HIDPP20_ONBOARD_PROFILES_MACRO_TYPE_G402 0x01
|
||||
|
||||
#define HIDPP20_USER_PROFILES_G402 0x0000
|
||||
@@ -2054,7 +2078,7 @@ hidpp20_onboard_profiles_validate(struct hidpp20_device *device,
|
||||
if ((info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G402) &&
|
||||
(info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G303) &&
|
||||
(info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G900) &&
|
||||
(info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G903_HERO)) {
|
||||
(info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G915)) {
|
||||
hidpp_log_error(&device->base,
|
||||
"Profile layout not supported: 0x%02x.\n",
|
||||
info->profile_format_id);
|
||||
@@ -2602,6 +2626,15 @@ hidpp20_onboard_profiles_initialize(struct hidpp20_device *device,
|
||||
HIDPP20_USER_PROFILES_G402,
|
||||
profiles->sector_size,
|
||||
data);
|
||||
|
||||
if (rc && device->quirk != HIDPP20_QUIRK_G305) {
|
||||
/* The G305 has a bug where it throws an ERR_INVALID_ARGUMENT
|
||||
if the sector has not been written to yet. If this happens
|
||||
we will read the ROM profiles.*/
|
||||
read_userdata = false;
|
||||
goto read_profiles;
|
||||
}
|
||||
|
||||
if (rc < 0)
|
||||
return rc; // ignore_clang_sa_mem_leak
|
||||
|
||||
@@ -2635,6 +2668,7 @@ hidpp20_onboard_profiles_initialize(struct hidpp20_device *device,
|
||||
read_userdata = false;
|
||||
}
|
||||
|
||||
read_profiles:
|
||||
for (i = 0; i < profiles->num_profiles; i++) {
|
||||
if (read_userdata) {
|
||||
hidpp_log_debug(&device->base, "Parsing profile %u\n", i);
|
||||
|
||||
@@ -51,6 +51,12 @@ struct hidpp20_feature {
|
||||
uint8_t type;
|
||||
};
|
||||
|
||||
enum hidpp20_quirk {
|
||||
HIDPP20_QUIRK_NONE,
|
||||
HIDPP20_QUIRK_G305,
|
||||
HIDPP20_QUIRK_G602,
|
||||
};
|
||||
|
||||
struct hidpp20_device {
|
||||
struct hidpp_device base;
|
||||
unsigned int index;
|
||||
@@ -58,12 +64,17 @@ struct hidpp20_device {
|
||||
unsigned proto_minor;
|
||||
unsigned feature_count;
|
||||
struct hidpp20_feature *feature_list;
|
||||
enum hidpp20_quirk quirk;
|
||||
};
|
||||
|
||||
int hidpp20_request_command(struct hidpp20_device *dev, union hidpp20_message *msg);
|
||||
|
||||
#define CASE_RETURN_STRING(a) case a: return #a; break
|
||||
|
||||
const char *hidpp20_feature_get_name(uint16_t feature);
|
||||
|
||||
const char *hidpp20_get_quirk_string(enum hidpp20_quirk quirk);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* generic hidpp20 device operations */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "libratbag.h"
|
||||
#include "libratbag-private.h"
|
||||
#include "libratbag-data.h"
|
||||
#include "hidpp20.h"
|
||||
|
||||
#define GROUP_DEVICE "Device"
|
||||
|
||||
@@ -54,6 +55,7 @@ enum driver {
|
||||
|
||||
struct data_hidpp20 {
|
||||
int index;
|
||||
enum hidpp20_quirk quirk;
|
||||
};
|
||||
|
||||
struct data_hidpp10 {
|
||||
@@ -152,6 +154,7 @@ init_data_hidpp20(struct ratbag *ratbag,
|
||||
const char *group = "Driver/hidpp20";
|
||||
GError *error = NULL;
|
||||
int num;
|
||||
char *str;
|
||||
|
||||
data->hidpp20.index = -1;
|
||||
|
||||
@@ -160,6 +163,15 @@ init_data_hidpp20(struct ratbag *ratbag,
|
||||
data->hidpp20.index = num;
|
||||
if (error)
|
||||
g_error_free(error);
|
||||
|
||||
str = g_key_file_get_string(keyfile, group, "Quirk", NULL);
|
||||
data->hidpp20.quirk = HIDPP20_QUIRK_NONE;
|
||||
if (str) {
|
||||
if (streq(str, "G305"))
|
||||
data->hidpp20.quirk = HIDPP20_QUIRK_G305;
|
||||
else if(streq(str, "G602"))
|
||||
data->hidpp20.quirk = HIDPP20_QUIRK_G602;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -562,6 +574,14 @@ ratbag_device_data_hidpp20_get_index(const struct ratbag_device_data *data)
|
||||
return data->hidpp20.index;
|
||||
}
|
||||
|
||||
enum hidpp20_quirk
|
||||
ratbag_device_data_hidpp20_get_quirk(const struct ratbag_device_data *data)
|
||||
{
|
||||
assert(data->drivertype == HIDPP20);
|
||||
|
||||
return data->hidpp20.quirk;
|
||||
}
|
||||
|
||||
/* SteelSeries */
|
||||
|
||||
int
|
||||
|
||||
@@ -80,6 +80,9 @@ ratbag_device_data_hidpp10_get_led_count(const struct ratbag_device_data *data);
|
||||
int
|
||||
ratbag_device_data_hidpp20_get_index(const struct ratbag_device_data *data);
|
||||
|
||||
enum hidpp20_quirk
|
||||
ratbag_device_data_hidpp20_get_quirk(const struct ratbag_device_data *data);
|
||||
|
||||
/* SteelSeries */
|
||||
|
||||
/**
|
||||
|
||||
@@ -322,7 +322,7 @@ out:
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ratbag_test_driver(struct ratbag_device *device,
|
||||
ratbag_try_driver(struct ratbag_device *device,
|
||||
const struct input_id *dev_id,
|
||||
const char *driver_name,
|
||||
const struct ratbag_test_device *test_device)
|
||||
@@ -377,9 +377,9 @@ ratbag_driver_fallback_logitech(struct ratbag_device *device,
|
||||
if (dev_id->vendor != USB_VENDOR_ID_LOGITECH)
|
||||
return false;
|
||||
|
||||
rc = ratbag_test_driver(device, dev_id, "hidpp20", NULL);
|
||||
rc = ratbag_try_driver(device, dev_id, "hidpp20", NULL);
|
||||
if (!rc)
|
||||
rc = ratbag_test_driver(device, dev_id, "hidpp10", NULL);
|
||||
rc = ratbag_try_driver(device, dev_id, "hidpp10", NULL);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -401,7 +401,7 @@ ratbag_assign_driver(struct ratbag_device *device,
|
||||
|
||||
if (driver_name) {
|
||||
log_debug(device->ratbag, "device assigned driver %s\n", driver_name);
|
||||
rc = ratbag_test_driver(device, dev_id, driver_name, test_device);
|
||||
rc = ratbag_try_driver(device, dev_id, driver_name, test_device);
|
||||
} else {
|
||||
rc = ratbag_driver_fallback_logitech(device, dev_id);
|
||||
}
|
||||
|
||||
@@ -520,7 +520,7 @@ class RatbagdProfile(_RatbagdDBus):
|
||||
|
||||
@GObject.Property
|
||||
def is_active(self):
|
||||
"""Returns True if the profile is currenly active, false otherwise."""
|
||||
"""Returns True if the profile is currently active, false otherwise."""
|
||||
return self._active
|
||||
|
||||
def set_active(self):
|
||||
|
||||
Reference in New Issue
Block a user