Compare commits

...

21 Commits
v0.8 ... v0.9

Author SHA1 Message Date
Benjamin Tissoires
7da53c61cf meson.build: libratbag 0.9
- convert Logitech devices to the commit API (those compatible)
- fixes for ratbag-command regarding LEDs (still few caveats left)
- some coverity fixes
- a brand new lur-command man page

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2017-06-06 15:26:37 +02:00
Benjamin Tissoires
714c0d5330 hidpp20: reset the LEDs before writing to it
We somehow now know how to write effects.
No need to carry around some left overs from previous configurations.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2017-06-06 15:03:47 +02:00
Benjamin Tissoires
dc92abb5e5 tools: replace tabs by spaces in ratbag-command usage
It's a mix of tabs and spaces. Let's use spaces to keep the formatting.

And move "switch-etekcity" back to the end, it's a special case.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2017-06-06 15:03:47 +02:00
Benjamin Tissoires
b0c515b59d tools: allow to set more than one setting for the LEDs
Or we will take the defaults that are not intuitive (like white color
when setting to on).

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2017-06-06 15:03:47 +02:00
Benjamin Tissoires
8e6c13832e hidpp20: led: document the internal structure and match the documentation
Shouldn't change the behavior, but this allows adding the other effects
found in the documentation.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2017-06-06 15:03:47 +02:00
Benjamin Tissoires
e33f655f61 hidpp20: do not waste memory
Currently we only support mice with 2 LEDs in the profile. No need
to have 32 placeholders.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2017-06-06 15:03:47 +02:00
Benjamin Tissoires
8e8b7b0611 hidpp20: make sure we read/write correct endianness to the device
rate is big endian, so we need to convert it.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2017-06-06 15:03:47 +02:00
Benjamin Tissoires
d28f2f0123 hidpp20: keep function names consistent
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2017-06-06 15:03:47 +02:00
Benjamin Tissoires
a8eea870f5 hidpp20: make sure we check all modes in the switch statement
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2017-06-06 15:03:47 +02:00
Benjamin Tissoires
7e12e45311 hidpp20-drv: no need to use doubles
We are using a uint in the end, so better have proper order in the
multiplications/divisions than using doubles.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2017-06-06 15:03:47 +02:00
Benjamin Tissoires
b31c1d5ff3 tools: ratbag-command: have only one function to dump the LED settings
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2017-06-06 15:03:47 +02:00
Benjamin Tissoires
f6949458b7 tools: make led a first class citizen of ratbag-command
Allows to follow the usage message: we do not need to provide the
currently active profile.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2017-06-06 15:03:47 +02:00
Benjamin Tissoires
15dd6b4f2b hidpp20: color effects, fix endianness
We are receiving big endian, thus the weird power of two locations.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2017-06-06 15:03:47 +02:00
Stephen Kitt
7afd59149c Add lur-command manpage
This is copied from the Debian package.

Signed-off-by: Stephen Kitt <steve@sk2.org>
2017-05-30 14:11:48 +10:00
Stephen Kitt
a47f506293 Fix ratbag-command manpage
* Description capitalisation
* Grammar
* Hyphen encoding
* --version

Signed-off-by: Stephen Kitt <steve@sk2.org>
2017-05-30 14:11:48 +10:00
Benjamin Tissoires
f243abb65c release.sh: remove unreachable test now that we switched to meson
and I must say, why would you not run this script in the current
directory.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2017-05-29 17:29:12 +10:00
Benjamin Tissoires
a4b177436d hidpp20: take into account sectors on 16bits
First part of fixing #122.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2017-05-29 10:33:33 +10:00
Benjamin Tissoires
8367569236 hidpp10: fix coverity issue
profile->dpi_modes[i].led[] is an array of boolean.
Given that the callers (hidpp10_fill_dpi_modes_*()) already are doing the
comparison against 0x02, I guess this is just copy/paste error.

Fixes #152

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2017-05-29 10:32:08 +10:00
Benjamin Tissoires
5bbb2b28ea hidpp20drv: switch to the commit API
I do not like duplicating ratbag_old_write_profile() into each driver,
but, heh.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2017-05-29 09:15:07 +10:00
bentiss
2b92ab6dd6 hidpp20drv: fix segfault with G502 (#163)
When using the G502 without RGB LEDs, the feature 8070 is not here.
And this segfaults :)

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2017-05-24 11:52:56 +03:00
Christian Kellner
c05c3dcaa3 tools: consistently call led mode "breathing"
Rename "breath" in the help text and reporting for the led mode to
"breathing". The actual command to set the mode was already called
that way.

Signed-off-by: Christian Kellner <christian@kellner.me>
2017-05-24 09:05:15 +10:00
11 changed files with 390 additions and 231 deletions

View File

@@ -1,5 +1,5 @@
project('libratbag', 'c', 'cpp',
version : '0.8.0',
version : '0.9.0',
license : 'MIT/Expat',
default_options : [ 'c_std=gnu99', 'warning_level=2' ])
@@ -14,10 +14,10 @@ libratbag_version = meson.project_version().split('.')
# 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_so_c=4
libratbag_so_r=2
libratbag_so_r=3
libratbag_so_a=0
liblur_so_c=3
liblur_so_r=2
liblur_so_r=3
liblur_so_a=0
# convert to sonames
@@ -256,6 +256,14 @@ executable('lur-command',
install : true,
)
man_lur_command = configure_file (
input: 'tools/lur-command.man',
output: 'lur-command.1',
configuration: man_config,
install : true,
install_dir : join_paths(get_option('mandir'), 'man1')
)
#### hwdb ####
udev_dir = get_option('udev-dir')
if udev_dir == ''

View File

@@ -288,39 +288,6 @@ process_module() {
return 1
fi
# Change directory to be in the git build directory (could be out-of-source)
# More than one can be found when distcheck has run and failed
configNum=`find . -name config.status -type f | wc -l | sed 's:^ *::'`
if [ $? -ne 0 ]; then
echo "Error: failed to locate config.status."
echo "Has the module been configured?"
return 1
fi
if [ x"$configNum" = x0 ]; then
echo "Error: failed to locate config.status, has the module been configured?"
return 1
fi
if [ x"$configNum" != x1 ]; then
echo "Error: more than one config.status file was found,"
echo " clean-up previously failed attempts at distcheck"
return 1
fi
status_file=`find . -name config.status -type f`
if [ $? -ne 0 ]; then
echo "Error: failed to locate config.status."
echo "Has the module been configured?"
return 1
fi
build_dir=`dirname $status_file`
cd $build_dir
if [ $? -ne 0 ]; then
echo "Error: failed to cd to $MODULE_RPATH/$build_dir."
cd $top_src
return 1
fi
# ----- Now in the git module *build* directory ----- #
# Check for uncommitted/queued changes.
check_local_changes
if [ $? -ne 0 ]; then

View File

@@ -253,7 +253,7 @@ hidpp20drv_read_led(struct ratbag_led *led)
struct hidpp20_color_led_zone_info *led_info;
struct hidpp20_led *h_led;
if (!(drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100))
if (!(drv_data->capabilities & HIDPP_CAP_COLOR_LED_EFFECTS_8070))
return;
led_info = &drv_data->led_infos[led->index];
@@ -278,8 +278,8 @@ hidpp20drv_read_led(struct ratbag_led *led)
led->color.red = h_led->color.red;
led->color.green = h_led->color.green;
led->color.blue = h_led->color.blue;
led->hz = h_led->rate;
led->brightness = h_led->brightness * 255.0 / 100;
led->hz = h_led->period; /* FIXME: should be ceil(1000.0 / h_led->period), but that would be very small */
led->brightness = h_led->brightness * 255 / 100;
}
static int
@@ -318,8 +318,8 @@ hidpp20drv_write_button_1b04(struct ratbag_button *button,
}
static int
hidpp20drv_write_button_8100(struct ratbag_button *button,
const struct ratbag_button_action *action)
hidpp20drv_update_button_8100(struct ratbag_button *button,
const struct ratbag_button_action *action)
{
struct ratbag_device *device = button->profile->device;
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
@@ -370,14 +370,14 @@ hidpp20drv_write_button_8100(struct ratbag_button *button,
}
static int
hidpp20drv_write_button(struct ratbag_button *button,
hidpp20drv_update_button(struct ratbag_button *button,
const struct ratbag_button_action *action)
{
struct ratbag_device *device = button->profile->device;
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)
return hidpp20drv_write_button_8100(button, action);
return hidpp20drv_update_button_8100(button, action);
if (drv_data->capabilities & HIDPP_CAP_BUTTON_KEY_1b04)
return hidpp20drv_write_button_1b04(button, action);
@@ -386,10 +386,7 @@ hidpp20drv_write_button(struct ratbag_button *button,
}
static int
hidpp20drv_write_led(struct ratbag_led *led,
enum ratbag_led_mode mode,
struct ratbag_color color, unsigned int hz,
unsigned int brightness)
hidpp20drv_update_led(struct ratbag_led *led)
{
struct ratbag_profile *profile = led->profile;
struct ratbag_device *device = profile->device;
@@ -407,7 +404,7 @@ hidpp20drv_write_led(struct ratbag_led *led,
if (!h_led)
return -EINVAL;
switch (mode) {
switch (led->mode) {
case RATBAG_LED_ON:
h_led->mode = HIDPP20_LED_ON;
break;
@@ -421,14 +418,13 @@ hidpp20drv_write_led(struct ratbag_led *led,
h_led->mode = HIDPP20_LED_OFF;
break;
}
h_led->color.red = color.red;
h_led->color.green = color.green;
h_led->color.blue = color.blue;
h_led->rate = hz;
h_led->brightness = brightness / 255.0 * 100;
h_led->color.red = led->color.red;
h_led->color.green = led->color.green;
h_led->color.blue = led->color.blue;
h_led->period = led->hz; /* FIXME: should be 1000 / led->hz, but that would be very small */
h_led->brightness = led->brightness * 100 / 255;
return hidpp20_onboard_profiles_write(drv_data->dev, profile->index,
drv_data->profiles);
return RATBAG_SUCCESS;
}
static int
@@ -548,8 +544,8 @@ hidpp20drv_read_resolution_dpi(struct ratbag_profile *profile)
}
static int
hidpp20drv_write_resolution_dpi_8100(struct ratbag_resolution *resolution,
int dpi_x, int dpi_y)
hidpp20drv_update_resolution_dpi_8100(struct ratbag_resolution *resolution,
int dpi_x, int dpi_y)
{
struct ratbag_profile *profile = resolution->profile;
struct ratbag_device *device = profile->device;
@@ -564,12 +560,12 @@ hidpp20drv_write_resolution_dpi_8100(struct ratbag_resolution *resolution,
h_profile = &drv_data->profiles->profiles[profile->index];
h_profile->dpi[index] = dpi;
return hidpp20_onboard_profiles_write(drv_data->dev, profile->index, drv_data->profiles);
return RATBAG_SUCCESS;
}
static int
hidpp20drv_write_resolution_dpi(struct ratbag_resolution *resolution,
int dpi_x, int dpi_y)
hidpp20drv_update_resolution_dpi(struct ratbag_resolution *resolution,
int dpi_x, int dpi_y)
{
struct ratbag_profile *profile = resolution->profile;
struct ratbag_device *device = profile->device;
@@ -579,7 +575,7 @@ hidpp20drv_write_resolution_dpi(struct ratbag_resolution *resolution,
int dpi = dpi_x; /* dpi_x == dpi_y if we don't have the individual resolution cap */
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)
return hidpp20drv_write_resolution_dpi_8100(resolution, dpi_x, dpi_y);
return hidpp20drv_update_resolution_dpi_8100(resolution, dpi_x, dpi_y);
if (!(drv_data->capabilities & HIDPP_CAP_SWITCHABLE_RESOLUTION_2201))
return -ENOTSUP;
@@ -748,12 +744,6 @@ hidpp20drv_read_profile(struct ratbag_profile *profile, unsigned int index)
profile->is_active = (index == 0);
}
static int
hidpp20drv_write_profile(struct ratbag_profile *profile)
{
return 0;
}
static int
hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature)
{
@@ -865,6 +855,60 @@ hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature)
return 0;
}
static int
hidpp20_commit(struct ratbag_device *device)
{
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
struct ratbag_profile *profile;
struct ratbag_button *button;
struct ratbag_led *led;
struct ratbag_resolution *resolution;
int rc;
unsigned int i;
list_for_each(profile, &device->profiles, link) {
if (!profile->dirty)
continue;
for (i = 0; i < profile->resolution.num_modes; i++) {
resolution = &profile->resolution.modes[i];
rc = hidpp20drv_update_resolution_dpi(resolution,
resolution->dpi_x,
resolution->dpi_y);
if (rc)
return RATBAG_ERROR_DEVICE;
}
list_for_each(button, &profile->buttons, link) {
struct ratbag_button_action action = button->action;
if (!button->dirty)
continue;
rc = hidpp20drv_update_button(button, &action);
if (rc)
return RATBAG_ERROR_DEVICE;
}
list_for_each(led, &profile->leds, link) {
if (!led->dirty)
continue;
rc = hidpp20drv_update_led(led);
if (rc)
return RATBAG_ERROR_DEVICE;
}
if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)
hidpp20_onboard_profiles_write(drv_data->dev,
profile->index,
drv_data->profiles);
}
return RATBAG_SUCCESS;
}
static int
hidpp20drv_20_probe(struct ratbag_device *device)
{
@@ -1006,12 +1050,9 @@ struct ratbag_driver hidpp20_driver = {
.id = "hidpp20",
.probe = hidpp20drv_probe,
.remove = hidpp20drv_remove,
.commit = hidpp20_commit,
.read_profile = hidpp20drv_read_profile,
.write_profile = hidpp20drv_write_profile,
.set_active_profile = hidpp20drv_set_current_profile,
.read_button = hidpp20drv_read_button,
.read_led = hidpp20drv_read_led,
.write_button = hidpp20drv_write_button,
.write_resolution_dpi = hidpp20drv_write_resolution_dpi,
.write_led = hidpp20drv_write_led,
};

View File

@@ -149,8 +149,8 @@ struct hidpp20_8070_location_mapping {
static const struct hidpp20_8070_location_mapping hidpp20_8070_location_mapping[] = {
LED_LOC_MAPPING(0, "None", RATBAG_LED_TYPE_UNKNOWN),
LED_LOC_MAPPING(256, "Logo LED", RATBAG_LED_TYPE_LOGO),
LED_LOC_MAPPING(512, "Side LED", RATBAG_LED_TYPE_SIDE),
LED_LOC_MAPPING(1, "Logo LED", RATBAG_LED_TYPE_LOGO),
LED_LOC_MAPPING(2, "Side LED", RATBAG_LED_TYPE_SIDE),
};
const struct ratbag_button_action *

View File

@@ -1525,10 +1525,10 @@ hidpp10_get_profile(struct hidpp10_device *dev, int8_t number, struct hidpp10_pr
profile->dpi_modes[i].yres);
hidpp_log_raw(&dev->base,
"LED status: 1:%s 2:%s 3:%s 4:%s\n",
(profile->dpi_modes[i].led[0] & 0x2) ? "on" : "off",
(profile->dpi_modes[i].led[1] & 0x2) ? "on" : "off",
(profile->dpi_modes[i].led[2] & 0x2) ? "on" : "off",
(profile->dpi_modes[i].led[3] & 0x2) ? "on" : "off");
profile->dpi_modes[i].led[0] ? "on" : "off",
profile->dpi_modes[i].led[1] ? "on" : "off",
profile->dpi_modes[i].led[2] ? "on" : "off",
profile->dpi_modes[i].led[3] ? "on" : "off");
}
hidpp_log_raw(&dev->base, "Angle correction: %d\n", profile->angle_correction);
hidpp_log_raw(&dev->base, "Default DPI mode: %d\n", profile->default_dpi_mode);

View File

@@ -555,7 +555,7 @@ hidpp20_color_led_effects_get_zone_info(struct hidpp20_device *device,
return rc;
msg_info = (struct hidpp20_color_led_zone_info *)msg.msg.parameters;
info->location = msg_info->location;
info->location = hidpp_be_u16_to_cpu(msg_info->location);
info->num_effects = msg_info->num_effects;
info->persistency_caps = msg_info->persistency_caps;
@@ -1064,7 +1064,7 @@ int
hidpp20_onboard_profiles_read_memory(struct hidpp20_device *device,
uint8_t read_rom,
uint8_t page,
uint8_t section,
uint16_t section,
uint8_t result[16])
{
uint8_t feature_index;
@@ -1075,13 +1075,13 @@ hidpp20_onboard_profiles_read_memory(struct hidpp20_device *device,
.msg.address = CMD_ONBOARD_PROFILES_MEMORY_READ,
.msg.parameters[0] = read_rom,
.msg.parameters[1] = page,
.msg.parameters[2] = 0,
.msg.parameters[3] = section,
};
if (read_rom > 1)
return -EINVAL;
hidpp_set_unaligned_be_u16(&msg.msg.parameters[2], section);
feature_index = hidpp_root_get_feature_idx(device,
HIDPP_PAGE_ONBOARD_PROFILES);
if (feature_index == 0)
@@ -1101,8 +1101,9 @@ hidpp20_onboard_profiles_read_memory(struct hidpp20_device *device,
static int
hidpp20_onboard_profiles_write_start(struct hidpp20_device *device,
uint8_t page,
uint8_t section)
uint16_t page,
uint16_t section,
uint16_t size)
{
uint8_t feature_index;
int rc;
@@ -1110,13 +1111,12 @@ hidpp20_onboard_profiles_write_start(struct hidpp20_device *device,
.msg.report_id = REPORT_ID_LONG,
.msg.device_idx = device->index,
.msg.address = CMD_ONBOARD_PROFILES_MEMORY_ADDR_WRITE,
.msg.parameters[0] = 0x00,
.msg.parameters[1] = page,
.msg.parameters[2] = 0,
.msg.parameters[3] = section,
.msg.parameters[4] = 0x01,
};
hidpp_set_unaligned_be_u16(&msg.msg.parameters[0], page);
hidpp_set_unaligned_be_u16(&msg.msg.parameters[2], section);
hidpp_set_unaligned_be_u16(&msg.msg.parameters[4], size);
feature_index = hidpp_root_get_feature_idx(device,
HIDPP_PAGE_ONBOARD_PROFILES);
if (feature_index == 0)
@@ -1158,8 +1158,8 @@ hidpp20_onboard_profiles_write_end(struct hidpp20_device *device)
static int
hidpp20_onboard_profiles_write_data(struct hidpp20_device *device,
uint8_t page,
uint8_t section,
uint16_t page,
uint16_t section,
uint8_t *data,
size_t len)
{
@@ -1179,7 +1179,10 @@ hidpp20_onboard_profiles_write_data(struct hidpp20_device *device,
msg.msg.sub_id = feature_index;
rc = hidpp20_onboard_profiles_write_start(device, page, section);
rc = hidpp20_onboard_profiles_write_start(device,
page,
section,
HIDPP20_PAGE_SIZE);
if (rc)
return rc;
@@ -1205,7 +1208,7 @@ hidpp20_onboard_profiles_write_data(struct hidpp20_device *device,
static int
hidpp20_onboard_profiles_write_page(struct hidpp20_device *device,
uint8_t page,
uint16_t page,
uint8_t data[HIDPP20_PAGE_SIZE])
{
uint16_t crc;
@@ -1756,7 +1759,7 @@ hidpp20_onboard_profiles_enable_profile(struct hidpp20_device *device,
hidpp20_onboard_profiles_compute_dict_size(device,
profiles_list));
return hidpp20_onboard_profiles_write_page(device, 0x00, data);
return hidpp20_onboard_profiles_write_page(device, 0x0000, data);
}
union hidpp20_internal_profile {
@@ -1890,26 +1893,36 @@ hidpp20_buttons_from_cpu(struct hidpp20_profile *profile,
}
static void
hidpp20_onboard_profile_read_led(struct hidpp20_led *led,
struct hidpp20_internal_led internal_led)
hidpp20_onboard_profiles_read_led(struct hidpp20_led *led,
struct hidpp20_internal_led internal_led)
{
uint16_t rate = 0;
uint16_t period = 0;
uint8_t brightness = 0;
switch (internal_led.mode) {
led->mode = (enum hidpp20_led_mode)internal_led.mode;
switch (led->mode) {
case HIDPP20_LED_CYCLE:
rate = internal_led.effect.cycle.rate;
brightness = internal_led.effect.cycle.brightness;
period = hidpp_be_u16_to_cpu(internal_led.effect.cycle.period_or_speed);
brightness = internal_led.effect.cycle.intensity;
if (brightness == 0)
brightness = 100;
break;
case HIDPP20_LED_BREATHING:
rate = internal_led.effect.breath.rate;
brightness = internal_led.effect.breath.brightness;
period = hidpp_be_u16_to_cpu(internal_led.effect.breath.period_or_speed);
brightness = internal_led.effect.breath.intensity;
if (brightness == 0)
brightness = 100;
led->color = internal_led.effect.breath.color;
break;
case HIDPP20_LED_ON:
led->color = internal_led.effect.fixed.color;
break;
case HIDPP20_LED_OFF:
break;
}
led->mode = (enum hidpp20_led_mode)internal_led.mode;
led->color = internal_led.color;
led->rate = rate;
led->period = period;
led->brightness = brightness;
}
@@ -1942,7 +1955,7 @@ int hidpp20_onboard_profiles_read(struct hidpp20_device *device,
}
for (i = 0; i < profiles_list->num_leds; i++)
hidpp20_onboard_profile_read_led(&profile->leds[i], pdata.profile.leds[i]);
hidpp20_onboard_profiles_read_led(&profile->leds[i], pdata.profile.leds[i]);
hidpp20_buttons_to_cpu(device, profile, pdata.profile.buttons, profiles_list->num_buttons);
@@ -1962,27 +1975,40 @@ int hidpp20_onboard_profiles_read(struct hidpp20_device *device,
}
static void
hidpp20_onboard_write_profile_led(struct hidpp20_internal_led *internal_led,
struct hidpp20_led *led)
hidpp20_onboard_profiles_write_led(struct hidpp20_internal_led *internal_led,
struct hidpp20_led *led)
{
uint16_t rate = led->rate;
uint16_t period = led->period;
uint8_t brightness = led->brightness;
memset(internal_led, 0, sizeof(*internal_led));
internal_led->mode = (uint8_t)led->mode;
internal_led->color.red = led->color.red;
internal_led->color.blue = led->color.blue;
internal_led->color.green = led->color.green;
switch (led->mode) {
case HIDPP20_LED_CYCLE:
internal_led->effect.cycle.rate = rate;
internal_led->effect.cycle.brightness = brightness;
internal_led->effect.cycle.period_or_speed = hidpp_cpu_to_be_u16(period);
if (brightness < 100)
internal_led->effect.cycle.intensity = brightness;
else
internal_led->effect.cycle.intensity = 0;
break;
case HIDPP20_LED_BREATHING:
internal_led->effect.breath.rate = rate;
internal_led->effect.breath.brightness = brightness;
internal_led->effect.breath.color.red = led->color.red;
internal_led->effect.breath.color.blue = led->color.blue;
internal_led->effect.breath.color.green = led->color.green;
internal_led->effect.breath.period_or_speed = hidpp_cpu_to_be_u16(period);
if (brightness < 100)
internal_led->effect.breath.intensity = brightness;
else
internal_led->effect.breath.intensity = 0;
break;
case HIDPP20_LED_ON:
internal_led->effect.fixed.color.red = led->color.red;
internal_led->effect.fixed.color.blue = led->color.blue;
internal_led->effect.fixed.color.green = led->color.green;
internal_led->effect.fixed.effect = 0;
break;
case HIDPP20_LED_OFF:
break;
}
@@ -2021,7 +2047,7 @@ int hidpp20_onboard_profiles_write(struct hidpp20_device *device,
}
for (i = 0; i < profiles_list->num_leds; i++)
hidpp20_onboard_write_profile_led(&pdata.profile.leds[i], &profile->leds[i]);
hidpp20_onboard_profiles_write_led(&pdata.profile.leds[i], &profile->leds[i]);
hidpp20_buttons_from_cpu(profile, pdata.profile.buttons, profiles_list->num_buttons);

View File

@@ -116,13 +116,6 @@ enum hidpp20_battery_status {
BATTERY_STATUS_INVALID,
};
enum hidpp20_led_mode {
HIDPP20_LED_OFF = 0x00,
HIDPP20_LED_ON = 0x01,
HIDPP20_LED_CYCLE = 0x03,
HIDPP20_LED_BREATHING = 0x0a,
};
/**
* Retrieves the battery level status.
*
@@ -389,26 +382,46 @@ enum hidpp20_led_type {
HIDPP20_LED_SIDE,
};
enum hidpp20_led_mode {
HIDPP20_LED_OFF = 0x00,
HIDPP20_LED_ON = 0x01,
HIDPP20_LED_CYCLE = 0x03,
HIDPP20_LED_BREATHING = 0x0a,
};
enum hidpp20_led_waveform {
HIDPP20_LED_WF_DEFAULT = 0x00,
HIDPP20_LED_WF_SINE = 0x01,
HIDPP20_LED_WF_SQUARE = 0x02,
HIDPP20_LED_WF_TRIANGLE = 0x03,
HIDPP20_LED_WF_SAWTOOTH = 0x04,
HIDPP20_LED_WF_SHARKFIN = 0x05,
HIDPP20_LED_WF_EXPONENTIAL = 0x06,
};
struct hidpp20_internal_led {
uint8_t mode; /* 00 - off; 01 - on; 03 - cycle; 0a - breath */
struct hidpp20_color color;
uint8_t mode; /* enum hidpp20_led_mode */
union {
struct hidpp20_led_fixed {
struct hidpp20_color color;
uint8_t effect;
} __attribute__((packed)) fixed;
struct hidpp20_led_cycle {
uint16_t pad_1;
uint16_t rate; /* 16000 - 20000Hz */
uint8_t brightness; /* 0 - 100 percent */
uint16_t pad_2;
uint8_t unused[5];
uint16_t period_or_speed; /* period in ms, speed is device dependent */
uint8_t intensity; /* 1 - 100 percent, 0 means 100 */
} __attribute__((packed)) cycle;
struct hidpp20_led_breath {
uint16_t rate;
uint8_t pad_1;
uint8_t brightness;
uint8_t pad_2;
uint16_t pad_3;
struct hidpp20_color color;
uint16_t period_or_speed; /* period in ms, speed is device dependent */
uint8_t waveform; /* enum hidpp20_led_waveform */
uint8_t intensity; /* 1 - 100 percent, 0 means 100 */
} __attribute__((packed)) breath;
uint8_t padding[10];
} __attribute__((packed)) effect;
};
_Static_assert(sizeof(struct hidpp20_led_cycle) == 7, "Invalid size");
_Static_assert(sizeof(struct hidpp20_led_fixed) == 4, "Invalid size");
_Static_assert(sizeof(struct hidpp20_led_cycle) == 8, "Invalid size");
_Static_assert(sizeof(struct hidpp20_led_breath) == 7, "Invalid size");
_Static_assert(sizeof(struct hidpp20_internal_led) == 11, "Invalid size");
@@ -417,7 +430,7 @@ typedef uint8_t percent_t;
struct hidpp20_led {
enum hidpp20_led_mode mode;
struct hidpp20_color color;
uint16_t rate;
uint16_t period;
percent_t brightness;
};
@@ -462,7 +475,7 @@ struct hidpp20_profile {
uint16_t dpi[HIDPP20_DPI_COUNT];
union hidpp20_button_binding buttons[32];
union hidpp20_macro_data *macros[32];
struct hidpp20_led leds[32];
struct hidpp20_led leds[HIDPP20_LED_COUNT];
};
struct hidpp20_profiles {
@@ -533,7 +546,7 @@ int
hidpp20_onboard_profiles_read_memory(struct hidpp20_device *device,
uint8_t read_rom,
uint8_t page,
uint8_t section,
uint16_t section,
uint8_t result[16]);
/* -------------------------------------------------------------------------- */

49
tools/lur-command.man Normal file
View File

@@ -0,0 +1,49 @@
.TH lur\-command 1 "@version@" lur\-command
.SH NAME
lur\-command \- list, pair and unpair Logitech Unifying devices
.SH SYNOPSIS
.B lur\-command find
.br
.B lur\-command list
.RI < device >
.br
.B lur\-command open
.RI < device >
.br
.B lur\-command close
.RI < device >
.br
.B lur\-command disconnect
.RI < index "> <" device >
.SH DESCRIPTION
.SS Common options
.TP
.BR \-h
displays a short help message.
.SS Listing receivers
.TP
.B find
lists all identified receivers on the system (scanning
.BI /dev/hidraw n
devices).
.SS Listing connected devices
.TP
.BR list " <" \fIdevice\fP >
lists the devices connected to the given receiver device.
.SS Pairing devices
.TP
.BR open " <" \fIdevice\fP >
opens the given receiver for pairing, for 30s.
.SS Closing a receiver
.TP
.BR close " <" \fIdevice\fP >
closes the given receiver, if it is currently open for pairing.
.SS Disconnecting a device
.TP
.BR disconnect " <" \fIindex\fP "> <" \fIdevice\fP >
disconnects the device matching the given index from the given
receiver. The index is as determined by the
.B list
command.
.SH SEE ALSO
.BR ratbag\-command (1)

View File

@@ -93,74 +93,74 @@ usage(void)
"Query or change a device's settings:\n"
"\n"
"Options:\n"
" --verbose Print debugging output\n"
" --verbose=raw Print debugging output with protocol output.\n"
" --help Print this help.\n"
" --verbose Print debugging output\n"
" --verbose=raw Print debugging output with protocol output.\n"
" --help Print this help.\n"
"\n"
"General Commands:\n"
" list List supported devices (does not take a device argument)\n"
" list List supported devices (does not take a device argument)\n"
"\n"
"Device Commands:\n"
" info Print information about a device \n"
" info Print information about a device \n"
"\n"
"Profile Commands:\n"
" profile active get Print the currently active profile\n"
" profile active set N Set profile N as to the active profile\n"
" profile active get Print the currently active profile\n"
" profile active set N Set profile N as to the active profile\n"
" profile enable N Enable profile N\n"
" profile disable N Disable profile N\n"
" profile N {COMMAND} Use profile N for COMMAND\n"
" profile N {COMMAND} Use profile N for COMMAND\n"
"\n"
"Resolution Commands\n"
" Resolution commands work on the given profile, or on the\n"
" active profile if none is given.\n"
"\n"
" resolution active get Print the currently active resolution\n"
" resolution active set N Set resolution N as the active resolution\n"
" resolution N {COMMAND} Use resolution N for COMMAND\n"
" resolution active get Print the currently active resolution\n"
" resolution active set N Set resolution N as the active resolution\n"
" resolution N {COMMAND} Use resolution N for COMMAND\n"
"\n"
"DPI Commands:\n"
" DPI commands work on the given profile and resolution, or on the\n"
" active resolution of the active profile if none are given.\n"
"\n"
" dpi get Print the dpi value\n"
" dpi set N Set the dpi value to N\n"
" rate get Print the report rate in Hz\n"
" rate set N Set the report rate in N Hz\n"
" dpi get Print the dpi value\n"
" dpi set N Set the dpi value to N\n"
" rate get Print the report rate in Hz\n"
" rate set N Set the report rate in N Hz\n"
"\n"
"Button Commands:\n"
" Button commands work on the given profile, or on the\n"
" active profile if none is given.\n"
"\n"
" button count Print the number of buttons\n"
" button N action get Print the button action\n"
" button N action set button B Set the button action to button B\n"
" button N action set special S Set the button action to special action S\n"
" button N action set macro ... Set the button action to the given macro \n"
" button count Print the number of buttons\n"
" button N action get Print the button action\n"
" button N action set button B Set the button action to button B\n"
" button N action set special S Set the button action to special action S\n"
" button N action set macro ... Set the button action to the given macro \n"
"\n"
" Macro syntax:\n"
" A macro is a series of key events or waiting periods.\n"
" Keys must be specified in linux/input.h key names.\n"
" KEY_A Press and release 'a'\n"
" +KEY_A Press 'a'\n"
" -KEY_A Release 'a'\n"
" t300 Wait 300ms\n"
"\n"
"Special Commands:\n"
"These commands are for testing purposes and may be removed without notice\n"
"\n"
" switch-etekcity Switch the Etekcity mouse active profile\n"
" A macro is a series of key events or waiting periods.\n"
" Keys must be specified in linux/input.h key names.\n"
" KEY_A Press and release 'a'\n"
" +KEY_A Press 'a'\n"
" -KEY_A Release 'a'\n"
" t300 Wait 300ms\n"
"\n"
"LED Commands:\n"
" LED commands work on the given profile, or on the\n"
" active profile if none is given.\n"
"\n"
" led N {COMMAND}\n"
" get print the LED properties\n"
" set {COMMAND} sets LED properties\n"
" mode [on|off|cycle|breath] sets LED mode\n"
" color COLOR sets LED's color in hex format\n"
" rate N sets LED's effect rate in Hz\n"
" brightness N sets LED's effect brightness\n"
" get print the LED properties\n"
" set {COMMAND} ... sets LED properties (one or more)\n"
" mode [on|off|cycle|breathing] sets LED mode\n"
" color COLOR sets LED's color in hex format\n"
" rate N sets LED's effect rate in Hz\n"
" brightness N sets LED's effect brightness\n"
"\n"
"Special Commands:\n"
"These commands are for testing purposes and may be removed without notice\n"
"\n"
" switch-etekcity Switch the Etekcity mouse active profile\n"
"\n"
"Examples:\n"
" %s profile active get\n"
@@ -173,10 +173,10 @@ usage(void)
" %s profile 0 led 0 set rate 20\n"
"\n"
"Exit codes:\n"
" 0 Success\n"
" 1 Unsupported feature or index out of available range\n"
" 2 Commandline arguments are invalid\n"
" 3 Invalid device or a command failed on the device\n"
" 0 Success\n"
" 1 Unsupported feature or index out of available range\n"
" 2 Commandline arguments are invalid\n"
" 3 Invalid device or a command failed on the device\n"
"\n",
program_invocation_short_name,
program_invocation_short_name,
@@ -273,7 +273,7 @@ fill_options(struct ratbag *ratbag,
struct ratbag_button *button = options->button;
int rc;
if ((flags & (FLAG_NEED_DEVICE|FLAG_NEED_PROFILE|FLAG_NEED_RESOLUTION)) &&
if ((flags & (FLAG_NEED_DEVICE|FLAG_NEED_PROFILE|FLAG_NEED_RESOLUTION|FLAG_NEED_LED)) &&
device == NULL) {
rc = ratbag_cmd_device_from_arg(ratbag, argc, argv,
&device);
@@ -282,7 +282,7 @@ fill_options(struct ratbag *ratbag,
options->device = device;
}
if ((flags & (FLAG_NEED_PROFILE|FLAG_NEED_RESOLUTION)) &&
if ((flags & (FLAG_NEED_PROFILE|FLAG_NEED_RESOLUTION|FLAG_NEED_LED)) &&
profile == NULL) {
profile = ratbag_cmd_get_active_profile(device);
if (!profile)
@@ -336,6 +336,55 @@ run_subcommand(const char *command,
return ERR_USAGE;
}
static int
ratbag_printf_led(struct ratbag_led *led, const char *prefix_format, ...)
{
va_list arg;
enum ratbag_led_mode mode;
struct ratbag_color color;
int hz;
int brightness;
enum ratbag_led_type type;
type = ratbag_led_get_type(led);
mode = ratbag_led_get_mode(led);
color = ratbag_led_get_color(led);
hz = ratbag_led_get_effect_rate(led);
brightness = ratbag_led_get_brightness(led);
va_start(arg, prefix_format);
vprintf(prefix_format, arg);
va_end(arg);
switch (mode) {
case RATBAG_LED_OFF:
printf("type: %s, mode: %s\n",
led_type_to_str(type),
led_mode_to_str(mode));
break;
case RATBAG_LED_ON:
printf("type: %s, mode: %s, color: %02x%02x%02x\n",
led_type_to_str(type),
led_mode_to_str(mode),
color.red, color.green, color.blue);
break;
case RATBAG_LED_CYCLE:
printf("type: %s, mode: %s, rate: %d, brightness: %d\n",
led_type_to_str(type),
led_mode_to_str(mode),
hz, brightness);
break;
case RATBAG_LED_BREATHING:
printf("type: %s, mode: %s, color: %02x%02x%02x, rate: %d, brightness: %d\n",
led_type_to_str(type),
led_mode_to_str(mode),
color.red, color.green, color.blue,
hz, brightness);
break;
}
return SUCCESS;
}
static int
ratbag_cmd_info(const struct ratbag_cmd *cmd,
struct ratbag *ratbag,
@@ -349,7 +398,6 @@ ratbag_cmd_info(const struct ratbag_cmd *cmd,
char *action;
int num_profiles, num_buttons, num_leds;
int b, l;
struct ratbag_color color;
device = options->device;
@@ -430,16 +478,7 @@ ratbag_cmd_info(const struct ratbag_cmd *cmd,
for (l = 0; l < num_leds; l++) {
led = ratbag_profile_get_led(profile, l);
color = ratbag_led_get_color(led);
printf(" LED: %d type %s mode %s color %02x%02x%02x rate %d brightness: %d\n",
l,
led_type_to_str(ratbag_led_get_type(led)),
led_mode_to_str(ratbag_led_get_mode(led)),
color.red, color.green, color.blue,
ratbag_led_get_effect_rate(led),
ratbag_led_get_brightness(led));
ratbag_printf_led(led, " LED: %d ", l);
led = ratbag_led_unref(led);
}
@@ -1502,14 +1541,23 @@ ratbag_cmd_led_set_brightness(const struct ratbag_cmd *cmd,
if (rc != 0)
return ERR_DEVICE;
return SUCCESS;
if (argc == 1)
return SUCCESS;
return run_subcommand(argv[1], cmd, ratbag, options,
argc - 1, argv + 1);
}
static const struct ratbag_cmd cmd_led_set_color;
static const struct ratbag_cmd cmd_led_set_effect_rate;
static const struct ratbag_cmd cmd_led_set_brightness = {
.name = "brightness",
.cmd = ratbag_cmd_led_set_brightness,
.flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE | FLAG_NEED_LED,
.subcommands = {
&cmd_led_set_color,
&cmd_led_set_effect_rate,
NULL,
},
};
@@ -1539,7 +1587,11 @@ ratbag_cmd_led_set_effect_rate(const struct ratbag_cmd *cmd,
if (rc != 0)
return ERR_DEVICE;
return SUCCESS;
if (argc == 1)
return SUCCESS;
return run_subcommand(argv[1], cmd, ratbag, options,
argc - 1, argv + 1);
}
static const struct ratbag_cmd cmd_led_set_effect_rate = {
@@ -1547,6 +1599,8 @@ static const struct ratbag_cmd cmd_led_set_effect_rate = {
.cmd = ratbag_cmd_led_set_effect_rate,
.flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE | FLAG_NEED_LED,
.subcommands = {
&cmd_led_set_color,
&cmd_led_set_brightness,
NULL,
},
};
@@ -1578,7 +1632,11 @@ ratbag_cmd_led_set_color(const struct ratbag_cmd *cmd,
if (rc != 0)
return ERR_DEVICE;
return SUCCESS;
if (argc == 1)
return SUCCESS;
return run_subcommand(argv[1], cmd, ratbag, options,
argc - 1, argv + 1);
}
static const struct ratbag_cmd cmd_led_set_color = {
@@ -1586,6 +1644,8 @@ static const struct ratbag_cmd cmd_led_set_color = {
.cmd = ratbag_cmd_led_set_color,
.flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE | FLAG_NEED_LED,
.subcommands = {
&cmd_led_set_effect_rate,
&cmd_led_set_brightness,
NULL,
},
};
@@ -1642,7 +1702,11 @@ ratbag_cmd_led_set_mode(const struct ratbag_cmd *cmd,
if (rc != 0)
return ERR_DEVICE;
return SUCCESS;
if (argc == 1)
return SUCCESS;
return run_subcommand(argv[1], cmd, ratbag, options,
argc - 1, argv + 1);
}
static const struct ratbag_cmd cmd_led_set_mode = {
@@ -1650,6 +1714,9 @@ static const struct ratbag_cmd cmd_led_set_mode = {
.cmd = ratbag_cmd_led_set_mode,
.flags = FLAG_NEED_DEVICE | FLAG_NEED_PROFILE | FLAG_NEED_LED,
.subcommands = {
&cmd_led_set_color,
&cmd_led_set_effect_rate,
&cmd_led_set_brightness,
NULL,
},
};
@@ -1686,25 +1753,9 @@ ratbag_cmd_led_get(const struct ratbag_cmd *cmd,
struct ratbag_cmd_options *options,
int argc, char **argv)
{
struct ratbag_led *led;
enum ratbag_led_mode mode;
struct ratbag_color color;
int hz;
int brightness;
enum ratbag_led_type type;
struct ratbag_led *led = options->led;
led = options->led;
type = ratbag_led_get_type(led);
mode = ratbag_led_get_mode(led);
color = ratbag_led_get_color(led);
hz = ratbag_led_get_effect_rate(led);
brightness = ratbag_led_get_brightness(led);
printf("type: %s, mode: %s, color: %02x%02x%02x, rate: %d, brightness: %d\n",
led_type_to_str(type),
led_mode_to_str(mode),
color.red, color.green, color.blue,
hz, brightness);
ratbag_printf_led(led, "");
return SUCCESS;
}
@@ -2019,6 +2070,7 @@ static const struct ratbag_cmd top_level_commands = {
&cmd_profile,
&cmd_resolution_dpi,
&cmd_resolution_rate,
&cmd_led,
NULL,
},
};

View File

@@ -1,26 +1,29 @@
.TH RATBAG_COMMAND "1" "@version@"
.SH NAME
ratbag-command \- Query or change a device's settings
ratbag\-command \- query or change a device's settings
.SH SYNOPSIS
.B ratbag-command [OPTIONS] {COMMAND} ... /path/to/device
.B ratbag\-command [OPTIONS] {COMMAND} ... /path/to/device
.SH DESCRIPTION
.PP
The
.I ratbag-commandq
tool query or change a device's settings.
.I ratbag\-command
tool queries or changes a device's settings.
.PP
This tool usually needs to be run as root to have access to the
/dev/input/eventX nodes.
.SH OPTIONS
.TP 8
.B --verbose
Print debugging output
.B \-\-verbose
Print debugging output.
.TP 8
.B --verbose=raw
.B \-\-verbose=raw
Print debugging output with protocol output. No guarantees are given regarding
the output format when this flag is on.
.TP 8
.B --help
.B \-\-version
Print the tool's version.
.TP 8
.B \-\-help
Print the help.
.SH General Commands
.TP 8
@@ -98,7 +101,7 @@ Press and release 'a'
.B +KEY_A
Press 'a'
.TP 8
.B -KEY_A
.B \-KEY_A
Release 'a'
.TP 8
.B t300
@@ -107,19 +110,19 @@ Wait 300ms
.SH Special Commands
These commands are for testing purposes and may be removed without notice
.TP 8
.B switch-etekcity
.B switch\-etekcity
Switch the Etekcity mouse active profile
.SH Examples
.TP 8
ratbag-command profile active get
ratbag\-command profile active get
.TP 8
ratbag-command profile 0 resolution active set 4
ratbag\-command profile 0 resolution active set 4
.TP 8
ratbag-command profile 0 resolution 1 dpi get
ratbag\-command profile 0 resolution 1 dpi get
.TP 8
ratbag-command resolution 4 rate get
ratbag\-command resolution 4 rate get
.TP 8
ratbag-command dpi set 800
ratbag\-command dpi set 800
.SH Exit codes
.TP 8
.B 0
@@ -136,6 +139,6 @@ Invalid device or a command failed on the device
.SH NOTES
.PP
There is currently no guarantees that the output format of
.B ratbag-command
.B ratbag\-command
will not change in the future. There should be some stability with the commands
mentioned in this man page, but do not expect it to stay the same.

View File

@@ -83,7 +83,7 @@ led_mode_to_str(enum ratbag_led_mode mode)
str = "cycle";
break;
case RATBAG_LED_BREATHING:
str = "breath";
str = "breathing";
break;
}