forked from drath/libratbag
Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
821e2798b9 | ||
|
|
3a0dc8f8a5 | ||
|
|
f75152f074 | ||
|
|
f72c96914b | ||
|
|
23036eec08 | ||
|
|
045a46aa9d | ||
|
|
01876023bb | ||
|
|
e2ae29efdc | ||
|
|
f67389c017 | ||
|
|
20a57b76a8 | ||
|
|
d54d77c395 | ||
|
|
a8897ca8ca | ||
|
|
4e62a3bdd9 | ||
|
|
d8a60eca94 | ||
|
|
9aa2120c7d | ||
|
|
f7e3f51b54 | ||
|
|
aef7b3e9bb | ||
|
|
21d0219809 | ||
|
|
3cf59af3e9 | ||
|
|
28438e638b | ||
|
|
c1bf3be48e | ||
|
|
27293a22df | ||
|
|
fc07672983 | ||
|
|
c14a0ca2a1 | ||
|
|
64037febdc | ||
|
|
fd10ebbc87 | ||
|
|
91eefb9a3f | ||
|
|
1da0180e0f | ||
|
|
22abddc9d4 | ||
|
|
e912f56c26 | ||
|
|
a715679f1f | ||
|
|
55673442f1 | ||
|
|
b6294d4f93 | ||
|
|
40112e6061 | ||
|
|
0785bf138d | ||
|
|
e18e25d685 | ||
|
|
85fdea19c2 | ||
|
|
792b6c28df | ||
|
|
5c68164d48 | ||
|
|
b1d99a744b | ||
|
|
9f544cbe1c | ||
|
|
ad06d29140 | ||
|
|
c12cb66824 | ||
|
|
c476cd0654 | ||
|
|
98315343b0 | ||
|
|
eb6787181d | ||
|
|
f7d9ca63e2 |
@@ -7,6 +7,13 @@ libratbag is a configuration library for gaming mice. It provides a generic
|
||||
way to access the various features exposed by these mice and abstracts away
|
||||
hardware-specific and kernel-specific quirks.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
API documentation is available here:
|
||||
|
||||
http://libratbag.github.io/libratbag/
|
||||
|
||||
Architecture
|
||||
------------
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
AC_PREREQ([2.64])
|
||||
|
||||
m4_define([libratbag_major_version], [0])
|
||||
m4_define([libratbag_minor_version], [4])
|
||||
m4_define([libratbag_minor_version], [5])
|
||||
m4_define([libratbag_micro_version], [0])
|
||||
m4_define([libratbag_version],
|
||||
[libratbag_major_version.libratbag_minor_version.libratbag_micro_version])
|
||||
@@ -30,8 +30,8 @@ AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
|
||||
# b) If interfaces have been changed or added, but binary compatibility has
|
||||
# been preserved, change to C+1:0:A+1
|
||||
# c) If the interface is the same as the previous version, change to C:R+1:A
|
||||
LIBRATBAG_LT_VERSION=3:0:0
|
||||
LIBLUR_LT_VERSION=3:0:0
|
||||
LIBRATBAG_LT_VERSION=3:1:0
|
||||
LIBLUR_LT_VERSION=3:1:0
|
||||
AC_SUBST(LIBRATBAG_LT_VERSION)
|
||||
AC_SUBST(LIBLUR_LT_VERSION)
|
||||
|
||||
@@ -62,7 +62,7 @@ AC_ARG_WITH(udev-base-dir, AS_HELP_STRING([--with-udev-base-dir=DIR], [where ude
|
||||
if test -n "$with_udev_base_dir" ; then
|
||||
UDEV_BASE_DIR="$with_udev_base_dir"
|
||||
else
|
||||
UDEV_BASE_DIR="/usr/lib/udev"
|
||||
UDEV_BASE_DIR="$prefix/lib/udev"
|
||||
fi
|
||||
AC_SUBST(UDEV_BASE_DIR)
|
||||
|
||||
|
||||
@@ -108,11 +108,16 @@ mouse:usb:v046dpc24e:name:*:
|
||||
RATBAG_HIDPP10_DPI=0:8200@50
|
||||
RATBAG_HIDPP10_PROFILE=G500
|
||||
|
||||
# G502 over USB
|
||||
# G502 Proteus Core over USB
|
||||
mouse:usb:v046dpc07d:name:*:
|
||||
RATBAG_DRIVER=hidpp20
|
||||
RATBAG_SVG=logitech-g502.svg
|
||||
|
||||
# G502 Proteus Spectrum over USB
|
||||
mouse:usb:v046dpc332:name:*:
|
||||
RATBAG_DRIVER=hidpp20
|
||||
RATBAG_SVG=logitech-g502.svg
|
||||
|
||||
# G700 over USB
|
||||
mouse:usb:v046dpc06b:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
@@ -127,6 +132,21 @@ mouse:usb:v046dpc531:name:*:
|
||||
RATBAG_HIDPP10_PROFILE=G700
|
||||
RATBAG_HIDPP10_INDEX=1
|
||||
|
||||
# G700s over USB
|
||||
mouse:usb:v046dpc07c:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_SVG=logitech-g700.svg
|
||||
RATBAG_HIDPP10_DPI=0:8200@50
|
||||
RATBAG_HIDPP10_PROFILE=G700
|
||||
|
||||
# G700s over wireless USB
|
||||
mouse:usb:v046dpc531:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_SVG=logitech-g700.svg
|
||||
RATBAG_HIDPP10_DPI=0:8200@50
|
||||
RATBAG_HIDPP10_PROFILE=G700
|
||||
RATBAG_HIDPP10_INDEX=1
|
||||
|
||||
# MX Master over unifying
|
||||
mouse:usb:v046dp4041:name:*:
|
||||
# MX Master over bluetooth
|
||||
@@ -146,6 +166,20 @@ mouse:usb:v046dp400a:name:*:
|
||||
mouse:usb:v046dpc080:name:*:
|
||||
RATBAG_DRIVER=hidpp20
|
||||
|
||||
# Wireless Touchpad (Unifying)
|
||||
mouse:usb:v046dp4011:name:*:
|
||||
RATBAG_DRIVER=hidpp20
|
||||
|
||||
# G602 over wireless USB
|
||||
mouse:usb:v046dpc537:name:*:
|
||||
RATBAG_HIDPP20_INDEX=1
|
||||
|
||||
# G900 over wireless USB
|
||||
mouse:usb:v046dpc539:name:*:
|
||||
RATBAG_DRIVER=hidpp20
|
||||
RATBAG_HIDPP20_INDEX=1
|
||||
|
||||
|
||||
##########################################
|
||||
# Roccat
|
||||
##########################################
|
||||
|
||||
@@ -19,7 +19,8 @@ libratbag_la_SOURCES = \
|
||||
libratbag-hidraw.h \
|
||||
libratbag-private.h \
|
||||
libratbag-test.c \
|
||||
libratbag-test.h
|
||||
libratbag-test.h \
|
||||
usb-ids.h
|
||||
|
||||
libratbag_la_LIBADD = \
|
||||
libhidpp.la \
|
||||
@@ -66,7 +67,8 @@ libhidpp_la_SOURCES = \
|
||||
hidpp10.h \
|
||||
hidpp10.c \
|
||||
hidpp20.h \
|
||||
hidpp20.c
|
||||
hidpp20.c \
|
||||
usb-ids.h
|
||||
libhidpp_la_LDFLAGS = -lm
|
||||
libutil_la_SOURCES = \
|
||||
libratbag-util.c \
|
||||
|
||||
@@ -636,13 +636,8 @@ etekcity_probe(struct ratbag_device *device)
|
||||
int active_idx;
|
||||
|
||||
rc = ratbag_open_hidraw(device);
|
||||
if (rc) {
|
||||
log_error(device->ratbag,
|
||||
"Can't open corresponding hidraw node: '%s' (%d)\n",
|
||||
strerror(-rc),
|
||||
rc);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (!ratbag_hidraw_has_report(device, ETEKCITY_REPORT_ID_KEY_MAPPING)) {
|
||||
ratbag_close_hidraw(device);
|
||||
@@ -670,8 +665,8 @@ etekcity_probe(struct ratbag_device *device)
|
||||
if (active_idx < 0) {
|
||||
log_error(device->ratbag,
|
||||
"Can't talk to the mouse: '%s' (%d)\n",
|
||||
strerror(-rc),
|
||||
rc);
|
||||
strerror(-active_idx),
|
||||
active_idx);
|
||||
rc = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -35,8 +35,6 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define USB_VENDOR_ID_LOGITECH 0x046d
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
@@ -45,6 +43,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "hidpp10.h"
|
||||
#include "usb-ids.h"
|
||||
|
||||
#include "libratbag-private.h"
|
||||
#include "libratbag-hidraw.h"
|
||||
@@ -504,16 +503,8 @@ hidpp10drv_probe(struct ratbag_device *device)
|
||||
int nread = 0;
|
||||
|
||||
rc = ratbag_find_hidraw(device, hidpp10drv_test_hidraw);
|
||||
if (rc == -ENODEV) {
|
||||
return rc;
|
||||
} else if (rc) {
|
||||
log_error(device->ratbag,
|
||||
"Can't open corresponding hidraw node: '%s' (%d)\n",
|
||||
strerror(-rc),
|
||||
rc);
|
||||
rc = -ENODEV;
|
||||
if (rc)
|
||||
goto err;
|
||||
}
|
||||
|
||||
drv_data = zalloc(sizeof(*drv_data));
|
||||
hidpp_device_init(&base, device->hidraw.fd);
|
||||
|
||||
@@ -117,7 +117,7 @@ hidpp20drv_read_macro_key_8100(struct ratbag_device *device, union hidpp20_macro
|
||||
return ratbag_hidraw_get_keycode_from_keyboard_usage(device, macro->key.key);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
hidpp20drv_read_macro_8100(struct ratbag_button *button,
|
||||
struct hidpp20_profile *profile,
|
||||
union hidpp20_button_binding *binding)
|
||||
@@ -130,6 +130,9 @@ hidpp20drv_read_macro_8100(struct ratbag_button *button,
|
||||
|
||||
macro = profile->macros[binding->macro.page];
|
||||
|
||||
if (!macro)
|
||||
return -EINVAL;
|
||||
|
||||
i = 0;
|
||||
|
||||
m = ratbag_button_macro_new("macro");
|
||||
@@ -175,6 +178,8 @@ hidpp20drv_read_macro_8100(struct ratbag_button *button,
|
||||
|
||||
ratbag_button_copy_macro(button, m);
|
||||
ratbag_button_macro_unref(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -183,6 +188,7 @@ hidpp20drv_read_button_8100(struct ratbag_button *button)
|
||||
struct ratbag_device *device = button->profile->device;
|
||||
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
|
||||
struct hidpp20_profile *profile;
|
||||
int rc;
|
||||
|
||||
if (!(drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100))
|
||||
return;
|
||||
@@ -213,7 +219,9 @@ hidpp20drv_read_button_8100(struct ratbag_button *button)
|
||||
button->action.action.special = hidpp20_onboard_profiles_get_special(profile->buttons[button->index].special.special);
|
||||
break;
|
||||
case HIDPP20_BUTTON_MACRO:
|
||||
hidpp20drv_read_macro_8100(button, profile, &profile->buttons[button->index]);
|
||||
rc = hidpp20drv_read_macro_8100(button, profile, &profile->buttons[button->index]);
|
||||
if (rc)
|
||||
button->action.type = RATBAG_BUTTON_ACTION_TYPE_NONE;
|
||||
break;
|
||||
default:
|
||||
button->action.type = RATBAG_BUTTON_ACTION_TYPE_UNKNOWN;
|
||||
@@ -584,7 +592,7 @@ hidpp20drv_read_profile_8100(struct ratbag_profile *profile, unsigned int index)
|
||||
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
|
||||
struct ratbag_resolution *res;
|
||||
struct hidpp20_profile *p;
|
||||
unsigned i, dpi;
|
||||
unsigned i, dpi = 0;
|
||||
|
||||
hidpp20drv_read_onboard_profile(device, profile->index);
|
||||
|
||||
@@ -592,6 +600,10 @@ hidpp20drv_read_profile_8100(struct ratbag_profile *profile, unsigned int index)
|
||||
if ((int)index == hidpp20drv_current_profile(device))
|
||||
profile->is_active = true;
|
||||
|
||||
/* retrieve the resolution through 220X as the profile doesn't has it */
|
||||
if (profile->is_active)
|
||||
hidpp20drv_read_resolution_dpi(profile);
|
||||
|
||||
dpi = ratbag_resolution_get_dpi(profile->resolution.modes);
|
||||
|
||||
p = &drv_data->profiles->profiles[index];
|
||||
@@ -656,13 +668,13 @@ hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature)
|
||||
}
|
||||
case HIDPP_PAGE_ADJUSTABLE_DPI: {
|
||||
log_debug(ratbag, "device has adjustable dpi\n");
|
||||
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_SWITCHABLE_RESOLUTION);
|
||||
drv_data->capabilities |= HIDPP_CAP_SWITCHABLE_RESOLUTION_2201;
|
||||
/* we read the profile once to get the correct number of
|
||||
* supported resolutions. */
|
||||
rc = hidpp20drv_read_resolution_dpi_2201(device);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
return 0; /* this is not a hard failure */
|
||||
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_SWITCHABLE_RESOLUTION);
|
||||
drv_data->capabilities |= HIDPP_CAP_SWITCHABLE_RESOLUTION_2201;
|
||||
break;
|
||||
}
|
||||
case HIDPP_PAGE_SPECIAL_KEYS_BUTTONS: {
|
||||
@@ -773,6 +785,26 @@ hidpp20_log(void *userdata, enum hidpp_log_priority priority, const char *format
|
||||
log_msg_va(device->ratbag, priority, format, args);
|
||||
}
|
||||
|
||||
static void
|
||||
hidpp20drv_remove(struct ratbag_device *device)
|
||||
{
|
||||
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
|
||||
struct hidpp20_device *dev = drv_data->dev;
|
||||
|
||||
if (!device)
|
||||
return;
|
||||
|
||||
ratbag_close_hidraw(device);
|
||||
|
||||
if (drv_data->profiles)
|
||||
hidpp20_onboard_profiles_destroy(dev, drv_data->profiles);
|
||||
free(drv_data->controls);
|
||||
free(drv_data->sensors);
|
||||
if (drv_data->dev)
|
||||
hidpp20_device_destroy(drv_data->dev);
|
||||
free(drv_data);
|
||||
}
|
||||
|
||||
static int
|
||||
hidpp20drv_probe(struct ratbag_device *device)
|
||||
{
|
||||
@@ -780,28 +812,41 @@ hidpp20drv_probe(struct ratbag_device *device)
|
||||
struct hidpp20drv_data *drv_data;
|
||||
struct hidpp_device base;
|
||||
struct hidpp20_device *dev;
|
||||
const char *prop;
|
||||
int device_idx = HIDPP_RECEIVER_IDX;
|
||||
int nread = 0;
|
||||
|
||||
rc = ratbag_find_hidraw(device, hidpp20drv_test_hidraw);
|
||||
if (rc == -ENODEV) {
|
||||
if (rc)
|
||||
return rc;
|
||||
} else if (rc) {
|
||||
log_error(device->ratbag,
|
||||
"Can't open corresponding hidraw node: '%s' (%d)\n",
|
||||
strerror(-rc),
|
||||
rc);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
drv_data = zalloc(sizeof(*drv_data));
|
||||
ratbag_set_drv_data(device, drv_data);
|
||||
hidpp_device_init(&base, device->hidraw.fd);
|
||||
hidpp_device_set_log_handler(&base, hidpp20_log, HIDPP_LOG_PRIORITY_RAW, device);
|
||||
|
||||
dev = hidpp20_device_new(&base, HIDPP_RECEIVER_IDX);
|
||||
prop = ratbag_device_get_udev_property(device, "RATBAG_HIDPP20_INDEX");
|
||||
if (prop) {
|
||||
sscanf(prop, "%d%n", &device_idx, &nread);
|
||||
if (!nread || (prop[nread]) != '\0' || device_idx < 0) {
|
||||
log_error(device->ratbag,
|
||||
"Error parsing RATBAG_HIDPP20_INDEX: '%s' for %s\n",
|
||||
prop,
|
||||
device->name);
|
||||
device_idx = HIDPP_RECEIVER_IDX;
|
||||
}
|
||||
}
|
||||
|
||||
/* In the general case, we can treat all devices as wired devices
|
||||
* here. If we talk to the correct hidraw device the kernel adjusts
|
||||
* the device index for us, so even for unifying receiver devices
|
||||
* we can just use 0xff as device index.
|
||||
*
|
||||
* If there is a special need like for G900, we can pass a
|
||||
* udev prop RATBAG_HIDPP20_INDEX.
|
||||
*/
|
||||
dev = hidpp20_device_new(&base, device_idx);
|
||||
if (!dev) {
|
||||
log_error(device->ratbag,
|
||||
"Failed to get HID++2.0 device for %s\n",
|
||||
device->name);
|
||||
rc = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
@@ -815,11 +860,9 @@ hidpp20drv_probe(struct ratbag_device *device)
|
||||
drv_data->num_resolutions = 1;
|
||||
drv_data->num_buttons = 8;
|
||||
|
||||
if (dev->proto_major >= 2) {
|
||||
rc = hidpp20drv_20_probe(device);
|
||||
if (rc)
|
||||
goto err;
|
||||
}
|
||||
rc = hidpp20drv_20_probe(device);
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
ratbag_device_init_profiles(device,
|
||||
drv_data->num_profiles,
|
||||
@@ -828,27 +871,10 @@ hidpp20drv_probe(struct ratbag_device *device)
|
||||
|
||||
return rc;
|
||||
err:
|
||||
free(drv_data);
|
||||
ratbag_set_drv_data(device, NULL);
|
||||
hidpp20drv_remove(device);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
hidpp20drv_remove(struct ratbag_device *device)
|
||||
{
|
||||
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
|
||||
struct hidpp20_device *dev = drv_data->dev;
|
||||
|
||||
ratbag_close_hidraw(device);
|
||||
|
||||
if (drv_data->profiles)
|
||||
hidpp20_onboard_profiles_destroy(dev, drv_data->profiles);
|
||||
free(drv_data->controls);
|
||||
free(drv_data->sensors);
|
||||
hidpp20_device_destroy(drv_data->dev);
|
||||
free(drv_data);
|
||||
}
|
||||
|
||||
struct ratbag_driver hidpp20_driver = {
|
||||
.name = "Logitech HID++2.0",
|
||||
.id = "hidpp20",
|
||||
|
||||
@@ -780,13 +780,8 @@ roccat_probe(struct ratbag_device *device)
|
||||
int active_idx;
|
||||
|
||||
rc = ratbag_open_hidraw(device);
|
||||
if (rc) {
|
||||
log_error(device->ratbag,
|
||||
"Can't open corresponding hidraw node: '%s' (%d)\n",
|
||||
strerror(-rc),
|
||||
rc);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (!ratbag_hidraw_has_report(device, ROCCAT_REPORT_ID_KEY_MAPPING)) {
|
||||
ratbag_close_hidraw(device);
|
||||
@@ -808,8 +803,8 @@ roccat_probe(struct ratbag_device *device)
|
||||
if (active_idx < 0) {
|
||||
log_error(device->ratbag,
|
||||
"Can't talk to the mouse: '%s' (%d)\n",
|
||||
strerror(-rc),
|
||||
rc);
|
||||
strerror(-active_idx),
|
||||
active_idx);
|
||||
rc = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -200,4 +200,10 @@ hidpp_cpu_to_le_u16(uint16_t data)
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
hidpp_get_unaligned_be_u32(uint8_t *buf)
|
||||
{
|
||||
return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
|
||||
}
|
||||
|
||||
#endif /* HIDPP_GENERIC_H */
|
||||
|
||||
@@ -2555,8 +2555,7 @@ hidpp10_get_extended_pairing_information(struct hidpp10_device *dev,
|
||||
if (res)
|
||||
return -1;
|
||||
|
||||
*serial = hidpp_get_unaligned_be_u16(&info.msg.string[2]) << 16;
|
||||
*serial |= hidpp_get_unaligned_be_u16(&info.msg.string[4]);
|
||||
*serial = hidpp_get_unaligned_be_u32(&info.msg.string[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -863,8 +863,9 @@ int hidpp20_adjustable_dpi_get_sensors(struct hidpp20_device *device,
|
||||
*sensors_list = s_list;
|
||||
return num_sensors;
|
||||
err:
|
||||
num_sensors = 0;
|
||||
free(s_list);
|
||||
return rc;
|
||||
return rc > 0 ? -EPROTO : rc;
|
||||
}
|
||||
|
||||
int hidpp20_adjustable_dpi_set_sensor_dpi(struct hidpp20_device *device,
|
||||
@@ -929,6 +930,7 @@ int hidpp20_adjustable_dpi_set_sensor_dpi(struct hidpp20_device *device,
|
||||
#define HIDPP20_ONBOARD_PROFILES_MEMORY_TYPE_G402 0x01
|
||||
#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_MACRO_TYPE_G402 0x01
|
||||
|
||||
struct hidpp20_onboard_profiles_info {
|
||||
@@ -1242,7 +1244,8 @@ hidpp20_onboard_profiles_initialize(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_G303) &&
|
||||
(info->profile_format_id != HIDPP20_ONBOARD_PROFILES_PROFILE_TYPE_G900)) {
|
||||
hidpp_log_error(&device->base,
|
||||
"Profile layout not supported: 0x%02x.\n",
|
||||
info->profile_format_id);
|
||||
@@ -1283,10 +1286,11 @@ hidpp20_onboard_profiles_initialize(struct hidpp20_device *device,
|
||||
info->profile_count * sizeof(struct hidpp20_profile));
|
||||
|
||||
profiles->num_profiles = info->profile_count;
|
||||
profiles->num_rom_profiles = info->profile_count_oob;
|
||||
profiles->num_buttons = msg.msg.parameters[5] <= 16 ? msg.msg.parameters[5] : 16;
|
||||
profiles->num_modes = HIDPP20_DPI_COUNT;
|
||||
profiles->has_g_shift = (info->mechanical_layout & 0x03) == 2;
|
||||
profiles->has_dpi_shift = (info->mechanical_layout & 0x0c) == 2;
|
||||
profiles->has_dpi_shift = ((info->mechanical_layout & 0x0c) >> 2) == 2;
|
||||
switch(info->various_info & 0x07) {
|
||||
case 1:
|
||||
profiles->corded = 1;
|
||||
@@ -1300,8 +1304,6 @@ hidpp20_onboard_profiles_initialize(struct hidpp20_device *device,
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
*profiles_list = profiles;
|
||||
|
||||
return 0;
|
||||
@@ -1467,13 +1469,29 @@ hidpp20_onboard_profiles_parse_macro(struct hidpp20_device *device,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
hidpp20_onboard_profiles_compute_dict_size(struct hidpp20_device *device,
|
||||
struct hidpp20_profiles *profiles)
|
||||
{
|
||||
unsigned p, num_offset;
|
||||
|
||||
num_offset = 0;
|
||||
p = profiles->num_profiles;
|
||||
while (p) {
|
||||
p >>= 2;
|
||||
num_offset += 16;
|
||||
}
|
||||
|
||||
return num_offset;
|
||||
}
|
||||
|
||||
int
|
||||
hidpp20_onboard_profiles_allocate(struct hidpp20_device *device,
|
||||
struct hidpp20_profiles **profiles_list)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned i, offset, num_offset;
|
||||
int rc;
|
||||
uint8_t data[16] = {0};
|
||||
uint8_t data[HIDPP20_PAGE_SIZE] = {0};
|
||||
struct hidpp20_profiles *profiles = NULL;
|
||||
|
||||
rc = hidpp20_onboard_profiles_initialize(device,
|
||||
@@ -1483,16 +1501,21 @@ hidpp20_onboard_profiles_allocate(struct hidpp20_device *device,
|
||||
|
||||
assert(profiles);
|
||||
|
||||
rc = hidpp20_onboard_profiles_read_memory(device,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
data);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
num_offset = hidpp20_onboard_profiles_compute_dict_size(device,
|
||||
profiles);
|
||||
|
||||
for (offset = 0; offset < num_offset; offset += 16) {
|
||||
rc = hidpp20_onboard_profiles_read_memory(device,
|
||||
0x00,
|
||||
0x00,
|
||||
offset,
|
||||
data + offset);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
for (i = 0; i < profiles->num_profiles; i++) {
|
||||
uint8_t *d = data + 4 * i;
|
||||
uint8_t *d = data + offset + 4 * i;
|
||||
|
||||
if (d[0] == 0xFF && d[1] == 0xFF)
|
||||
break;
|
||||
@@ -1532,7 +1555,8 @@ hidpp20_onboard_profiles_destroy(struct hidpp20_device *device,
|
||||
static int
|
||||
hidpp20_onboard_profiles_find_and_read_profile(struct hidpp20_device *device,
|
||||
unsigned int index,
|
||||
uint8_t *data)
|
||||
uint8_t *data,
|
||||
unsigned int num_rom_profiles)
|
||||
{
|
||||
int rc;
|
||||
unsigned i;
|
||||
@@ -1565,13 +1589,19 @@ hidpp20_onboard_profiles_find_and_read_profile(struct hidpp20_device *device,
|
||||
}
|
||||
|
||||
/* something went wrong, the mouse is using the factory profile in ROM */
|
||||
if (num_rom_profiles == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (index >= num_rom_profiles)
|
||||
index = num_rom_profiles - 1;
|
||||
|
||||
for (i = 0; i < HIDPP20_PROFILE_SIZE / 0x10; i++) {
|
||||
rc = hidpp20_onboard_profiles_read_memory(device,
|
||||
1,
|
||||
index + 1,
|
||||
i * 0x10,
|
||||
data + i * 0x10);
|
||||
if (rc < 0)
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1592,7 +1622,7 @@ hidpp20_onboard_profiles_enable_profile(struct hidpp20_device *device,
|
||||
profiles_list->profiles[index].index = index + 1;
|
||||
profiles_list->profiles[index].enabled = 0x01;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
for (i = 0; i < profiles_list->num_profiles; i++) {
|
||||
data[buffer_index++] = 0x00;
|
||||
data[buffer_index++] = i + 1;
|
||||
data[buffer_index++] = profiles_list->profiles[i].enabled;
|
||||
@@ -1607,7 +1637,11 @@ hidpp20_onboard_profiles_enable_profile(struct hidpp20_device *device,
|
||||
|
||||
memset(data + buffer_index, 0xff, sizeof(data) - buffer_index);
|
||||
|
||||
hidpp_log_buf_error(&device->base, "dictionary: ", data, 16);
|
||||
hidpp_log_buf_debug(&device->base,
|
||||
"dictionary: ",
|
||||
data,
|
||||
hidpp20_onboard_profiles_compute_dict_size(device,
|
||||
profiles_list));
|
||||
|
||||
return hidpp20_onboard_profiles_write_page(device, 0x00, data);
|
||||
}
|
||||
@@ -1760,8 +1794,11 @@ int hidpp20_onboard_profiles_read(struct hidpp20_device *device,
|
||||
if (index >= profiles_list->num_profiles)
|
||||
return -EINVAL;
|
||||
|
||||
rc = hidpp20_onboard_profiles_find_and_read_profile(device, index, data);
|
||||
if (rc < 0)
|
||||
rc = hidpp20_onboard_profiles_find_and_read_profile(device,
|
||||
index,
|
||||
data,
|
||||
profiles_list->num_rom_profiles);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
profile->report_rate = 1000 / max(1, pdata.profile.report_rate);
|
||||
@@ -1802,7 +1839,10 @@ int hidpp20_onboard_profiles_write(struct hidpp20_device *device,
|
||||
if (index >= profiles_list->num_profiles)
|
||||
return -EINVAL;
|
||||
|
||||
rc = hidpp20_onboard_profiles_find_and_read_profile(device, index, data);
|
||||
rc = hidpp20_onboard_profiles_find_and_read_profile(device,
|
||||
index,
|
||||
data,
|
||||
profiles_list->num_rom_profiles);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
@@ -1845,8 +1885,9 @@ static const enum ratbag_button_action_special hidpp20_profiles_specials[] = {
|
||||
[0x09] = RATBAG_BUTTON_ACTION_SPECIAL_INVALID,
|
||||
[0x0a] = RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_CYCLE_UP,
|
||||
[0x0b] = RATBAG_BUTTON_ACTION_SPECIAL_SECOND_MODE,
|
||||
[0x0c] = RATBAG_BUTTON_ACTION_SPECIAL_BATTERY_LEVEL,
|
||||
|
||||
[0x0c ... 0xff] = RATBAG_BUTTON_ACTION_SPECIAL_INVALID,
|
||||
[0x0d ... 0xff] = RATBAG_BUTTON_ACTION_SPECIAL_INVALID,
|
||||
};
|
||||
|
||||
enum ratbag_button_action_special
|
||||
@@ -1892,6 +1933,9 @@ hidpp20_device_new(const struct hidpp_device *base, unsigned int idx)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (dev->proto_major < 2)
|
||||
goto err;
|
||||
|
||||
rc = hidpp20_feature_set_get(dev);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
|
||||
@@ -362,6 +362,7 @@ struct hidpp20_profile {
|
||||
|
||||
struct hidpp20_profiles {
|
||||
uint8_t num_profiles;
|
||||
uint8_t num_rom_profiles;
|
||||
uint8_t num_buttons;
|
||||
uint8_t num_modes;
|
||||
uint8_t has_g_shift;
|
||||
|
||||
@@ -30,13 +30,13 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/hidraw.h>
|
||||
|
||||
#include "usb-ids.h"
|
||||
#include "hidpp10.h"
|
||||
#include "libratbag-util.h"
|
||||
#include "liblur.h"
|
||||
|
||||
#define _EXPORT_ __attribute__ ((visibility("default")))
|
||||
#define MAX_DEVICES 6
|
||||
#define VENDOR_ID_LOGITECH 0x046d
|
||||
|
||||
struct lur_receiver {
|
||||
int refcount;
|
||||
@@ -113,7 +113,7 @@ lur_device_disconnect(struct lur_device *dev)
|
||||
_EXPORT_ int
|
||||
lur_is_receiver(uint16_t vid, uint16_t pid)
|
||||
{
|
||||
return (vid == VENDOR_ID_LOGITECH && (pid == 0xc52b || pid == 0xc532));
|
||||
return (vid == USB_VENDOR_ID_LOGITECH && (pid == 0xc52b || pid == 0xc532));
|
||||
}
|
||||
|
||||
static bool
|
||||
@@ -232,7 +232,7 @@ lur_receiver_enumerate(struct lur_receiver *lur,
|
||||
lur_receiver_ref(lur);
|
||||
dev->refcount = 1;
|
||||
dev->name = strdup_safe(name);
|
||||
dev->vid = VENDOR_ID_LOGITECH;
|
||||
dev->vid = USB_VENDOR_ID_LOGITECH;
|
||||
dev->pid = wpid;
|
||||
dev->type = type;
|
||||
dev->serial = serial;
|
||||
|
||||
@@ -1417,14 +1417,12 @@ ratbag_find_hidraw_node(struct ratbag_device *device,
|
||||
goto skip;
|
||||
|
||||
matched = match(device);
|
||||
if (matched == 1) {
|
||||
rc = 0;
|
||||
rc = matched ? 0 : -ENODEV;
|
||||
if (matched == 1)
|
||||
goto out;
|
||||
}
|
||||
|
||||
skip:
|
||||
ratbag_close_hidraw(device);
|
||||
rc = -ENODEV;
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "usb-ids.h"
|
||||
#include "libratbag-private.h"
|
||||
#include "libratbag-util.h"
|
||||
|
||||
@@ -283,23 +284,15 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool
|
||||
ratbag_assign_driver(struct ratbag_device *device,
|
||||
const struct input_id *dev_id,
|
||||
struct ratbag_test_device *test_device)
|
||||
static inline bool
|
||||
ratbag_test_driver(struct ratbag_device *device,
|
||||
const struct input_id *dev_id,
|
||||
const char *driver_name,
|
||||
struct ratbag_test_device *test_device)
|
||||
{
|
||||
struct ratbag *ratbag = device->ratbag;
|
||||
struct ratbag_driver *driver;
|
||||
int rc;
|
||||
const char *driver_name;
|
||||
|
||||
if (!test_device) {
|
||||
driver_name = udev_prop_value(device->udev_device, "RATBAG_DRIVER");
|
||||
if (!driver_name)
|
||||
return false;
|
||||
} else {
|
||||
driver_name = "test_driver";
|
||||
}
|
||||
|
||||
list_for_each(driver, &ratbag->drivers, link) {
|
||||
if (streq(driver->id, driver_name)) {
|
||||
@@ -311,7 +304,7 @@ ratbag_assign_driver(struct ratbag_device *device,
|
||||
if (!device->driver) {
|
||||
log_error(ratbag, "%s: driver '%s' does not exist\n",
|
||||
device->name, driver_name);
|
||||
return false;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (test_device)
|
||||
@@ -320,21 +313,64 @@ ratbag_assign_driver(struct ratbag_device *device,
|
||||
rc = device->driver->probe(device);
|
||||
if (rc == 0) {
|
||||
if (!ratbag_sanity_check_device(device)) {
|
||||
return false;
|
||||
goto error;
|
||||
} else {
|
||||
log_debug(ratbag, "driver match found: %s\n", driver->name);
|
||||
log_debug(ratbag,
|
||||
"driver match found: %s\n",
|
||||
device->driver->name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc != -ENODEV)
|
||||
log_error(ratbag, "%s: error opening hidraw node (%s)\n",
|
||||
device->name, strerror(-rc));
|
||||
|
||||
error:
|
||||
device->driver = NULL;
|
||||
|
||||
if (rc == -ENODEV)
|
||||
log_error(ratbag, "%s: no hidraw device found\n", device->name);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ratbag_driver_fallback_logitech(struct ratbag_device *device,
|
||||
const struct input_id *dev_id)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (dev_id->vendor != USB_VENDOR_ID_LOGITECH)
|
||||
return false;
|
||||
|
||||
rc = ratbag_test_driver(device, dev_id, "hidpp20", NULL);
|
||||
if (!rc)
|
||||
rc = ratbag_test_driver(device, dev_id, "hidpp10", NULL);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool
|
||||
ratbag_assign_driver(struct ratbag_device *device,
|
||||
const struct input_id *dev_id,
|
||||
struct ratbag_test_device *test_device)
|
||||
{
|
||||
bool rc;
|
||||
const char *driver_name;
|
||||
|
||||
if (!test_device) {
|
||||
driver_name = udev_prop_value(device->udev_device, "RATBAG_DRIVER");
|
||||
} else {
|
||||
driver_name = "test_driver";
|
||||
}
|
||||
|
||||
if (driver_name) {
|
||||
rc = ratbag_test_driver(device, dev_id, driver_name, test_device);
|
||||
} else {
|
||||
rc = ratbag_driver_fallback_logitech(device, dev_id);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline char*
|
||||
get_device_name(struct udev_device *device)
|
||||
{
|
||||
@@ -382,6 +418,9 @@ ratbag_device_new_from_udev_device(struct ratbag *ratbag,
|
||||
assert(udev_device != NULL);
|
||||
assert(device_out != NULL);
|
||||
|
||||
if (udev_prop_value(udev_device, "ID_INPUT_MOUSE") == NULL)
|
||||
goto out_err;
|
||||
|
||||
if (get_product_id(udev_device, &id) != 0)
|
||||
goto out_err;
|
||||
|
||||
|
||||
29
src/usb-ids.h
Normal file
29
src/usb-ids.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright © 2016 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef USB_IDS_H
|
||||
#define USB_IDS_H
|
||||
|
||||
#define USB_VENDOR_ID_LOGITECH 0x046d
|
||||
|
||||
#endif
|
||||
|
||||
@@ -111,6 +111,8 @@ main(int argc, char **argv)
|
||||
|
||||
hidpp_device_init(&base, fd);
|
||||
dev = hidpp20_device_new(&base, 0xff);
|
||||
if (!dev)
|
||||
error(1, 0, "Failed to open %s as a HID++ 2.0 device", path);
|
||||
|
||||
if (argc == 2)
|
||||
rc = dump_everything(dev);
|
||||
|
||||
@@ -243,7 +243,7 @@ main(int argc, char **argv)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
index = atoi(argv[3]);
|
||||
index = atoi(argv[2]);
|
||||
disconnect_device(receiver, index);
|
||||
} else {
|
||||
usage();
|
||||
|
||||
Reference in New Issue
Block a user