mirror of
https://github.com/libratbag/libratbag.git
synced 2026-11-07 15:14:38 +01:00
sinowealth: add support for reading button bindings
This commit is contained in:
committed by
Ilya guterman
parent
e9dff40258
commit
45a8fd9ec3
@@ -35,6 +35,7 @@ enum sinowealth_command_id {
|
||||
SINOWEALTH_CMD_FIRMWARE_VERSION = 0x1,
|
||||
SINOWEALTH_CMD_PROFILE = 0x2,
|
||||
SINOWEALTH_CMD_GET_CONFIG = 0x11,
|
||||
SINOWEALTH_CMD_GET_BUTTONS = 0x12,
|
||||
SINOWEALTH_CMD_DEBOUNCE = 0x1a,
|
||||
/* Only works on devices that use CONFIG_LONG report ID. */
|
||||
SINOWEALTH_CMD_LONG_ANGLESNAPPING_AND_LOD = 0x1b,
|
||||
@@ -339,6 +340,7 @@ struct sinowealth_data {
|
||||
/* Cached profile index. This might be incorrect if profile index was changed by another program while we are running. */
|
||||
unsigned int current_profile_index;
|
||||
unsigned int led_count;
|
||||
struct sinowealth_button_report buttons[SINOWEALTH_NUM_PROFILES];
|
||||
struct sinowealth_config_report configs[SINOWEALTH_NUM_PROFILES];
|
||||
};
|
||||
|
||||
@@ -870,6 +872,38 @@ sinowealth_print_long_lod_and_anglesnapping(struct ratbag_device *device)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read button configuration data from the mouse and save it in drv_data.
|
||||
*
|
||||
* @return 0 on success or an error code.
|
||||
*/
|
||||
static int
|
||||
sinowealth_read_raw_buttons(struct ratbag_device *device)
|
||||
{
|
||||
/* TODO: analogous to @ref sinowealth_read_raw_config. */
|
||||
|
||||
int rc = 0;
|
||||
|
||||
struct sinowealth_data *drv_data = device->drv_data;
|
||||
struct sinowealth_button_report *buttons1 = &drv_data->buttons[0];
|
||||
|
||||
const unsigned char config_report_id = drv_data->is_long ? SINOWEALTH_REPORT_ID_CONFIG_LONG : SINOWEALTH_REPORT_ID_CONFIG;
|
||||
|
||||
uint8_t cmd1[SINOWEALTH_CMD_SIZE] = { SINOWEALTH_REPORT_ID_CMD, SINOWEALTH_CMD_GET_BUTTONS };
|
||||
rc = ratbag_hidraw_set_feature_report(device, SINOWEALTH_REPORT_ID_CMD, cmd1, sizeof(cmd1));
|
||||
if (rc != sizeof(cmd1)) {
|
||||
log_error(device->ratbag, "Error while sending read config command: %d\n", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = ratbag_hidraw_get_feature_report(device, config_report_id, (uint8_t*)buttons1, SINOWEALTH_CONFIG_REPORT_SIZE);
|
||||
if (rc != SINOWEALTH_BUTTON_SIZE) {
|
||||
log_error(device->ratbag, "Could not read device button configuration: %d\n", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read configuration data from the mouse and save it in drv_data.
|
||||
*
|
||||
* @return 0 on success or an error code.
|
||||
@@ -1001,6 +1035,96 @@ sinowealth_update_profile_from_config(struct ratbag_profile *profile)
|
||||
profile->is_active = profile->index == drv_data->current_profile_index;
|
||||
}
|
||||
|
||||
static void
|
||||
sinowealth_update_profile_from_buttons(struct ratbag_profile *profile)
|
||||
{
|
||||
struct ratbag_device *device = profile->device;
|
||||
struct sinowealth_data *drv_data = device->drv_data;
|
||||
struct sinowealth_button_report *buf = &drv_data->buttons[profile->index];
|
||||
struct ratbag_button *button = NULL;
|
||||
struct sinowealth_button_data button_data;
|
||||
int rc = 0;
|
||||
|
||||
ratbag_profile_for_each_button(profile, button) {
|
||||
button_data = buf->buttons[button->index];
|
||||
|
||||
const struct ratbag_button_action *action = sinowealth_raw_to_button_action(&button_data);
|
||||
/* Match was found in the map, continue. */
|
||||
if (action != NULL) {
|
||||
button->action.action = action->action;
|
||||
button->action.type = action->type;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Explicitly fall back to type `UNKNOWN` as `NONE` is the default. */
|
||||
button->action.type = RATBAG_BUTTON_ACTION_TYPE_UNKNOWN;
|
||||
|
||||
switch (button_data.type) {
|
||||
case SINOWEALTH_BUTTON_TYPE_KEY: {
|
||||
unsigned int modifiers = 0;
|
||||
if (button_data.key.modifiers & SINOWEALTH_BUTTON_KEY_MODIFIER_LEFTCTRL)
|
||||
modifiers |= MODIFIER_LEFTCTRL;
|
||||
if (button_data.key.modifiers & SINOWEALTH_BUTTON_KEY_MODIFIER_LEFTSHIFT)
|
||||
modifiers |= MODIFIER_LEFTSHIFT;
|
||||
if (button_data.key.modifiers & SINOWEALTH_BUTTON_KEY_MODIFIER_LEFTALT)
|
||||
modifiers |= MODIFIER_LEFTALT;
|
||||
if (button_data.key.modifiers & SINOWEALTH_BUTTON_KEY_MODIFIER_LEFTMETA)
|
||||
modifiers |= MODIFIER_LEFTMETA;
|
||||
|
||||
const unsigned int key = ratbag_hidraw_get_keycode_from_keyboard_usage(device, button_data.key.key);
|
||||
|
||||
rc = ratbag_button_macro_new_from_keycode(button, key, modifiers);
|
||||
if (rc < 0) {
|
||||
log_error(device->ratbag, "Error while reading button %d\n", button->index);
|
||||
button->action.type = RATBAG_BUTTON_ACTION_TYPE_UNKNOWN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SINOWEALTH_BUTTON_TYPE_REPEATED: {
|
||||
/* NOTE: We do not support such button actions yet. */
|
||||
|
||||
const uint8_t button_index = button_data.repeated_button.index;
|
||||
const uint8_t repeat_delay = button_data.repeated_button.delay;
|
||||
const uint8_t repeat_count = button_data.repeated_button.count;
|
||||
|
||||
log_debug(device->ratbag, "Read repeating button %u: %#x %#x %#x\n", button->index, button_index, repeat_delay, repeat_count);
|
||||
break;
|
||||
}
|
||||
case SINOWEALTH_BUTTON_TYPE_DPI_LOCK: {
|
||||
/* NOTE: We do not support such button actions yet. */
|
||||
|
||||
const unsigned int dpi = button_data.dpi_lock.dpi * 100;
|
||||
|
||||
log_debug(device->ratbag, "Read button %u locks DPI on %u\n", button->index, dpi);
|
||||
break;
|
||||
}
|
||||
case SINOWEALTH_BUTTON_TYPE_MACRO: {
|
||||
const uint8_t macro_index = button_data.macro.index;
|
||||
const uint8_t mode = button_data.macro.mode;
|
||||
const uint8_t option = button_data.macro.option;
|
||||
|
||||
log_debug(device->ratbag, "Read button %u activates macro %u: %#x %#x\n", button->index, macro_index, mode, option);
|
||||
|
||||
/* There is no known way to read a macro blob, so create a dummy
|
||||
* macro event, so that the button action displays as a macro.
|
||||
*/
|
||||
|
||||
const int key = 0; /* Dummy. */
|
||||
const int modifiers = 0; /* Dummy. */
|
||||
rc = ratbag_button_macro_new_from_keycode(button, key, modifiers);
|
||||
if (rc < 0) {
|
||||
log_error(device->ratbag, "Could not make a dummy macro: %d\n", rc);
|
||||
button->action.type = RATBAG_BUTTON_ACTION_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
log_debug(device->ratbag, "Read button %u can't be determined: %#x %#x %#x %#x\n", button->index, button_data.type, button_data.data[0], button_data.data[1], button_data.data[2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Initialize profiles for device `device`.
|
||||
*
|
||||
* @return 0 on success or an error code.
|
||||
@@ -1030,6 +1154,10 @@ sinowealth_init_profile(struct ratbag_device *device)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = sinowealth_read_raw_buttons(device);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (strncmp(fw_version, "V102", 4) == 0) {
|
||||
log_info(device->ratbag, "Found a Glorious Model O (old firmware) or a Glorious Model D\n");
|
||||
|
||||
@@ -1208,6 +1336,7 @@ sinowealth_probe(struct ratbag_device *device)
|
||||
|
||||
ratbag_device_for_each_profile(device, profile) {
|
||||
sinowealth_update_profile_from_config(profile);
|
||||
sinowealth_update_profile_from_buttons(profile);
|
||||
}
|
||||
|
||||
rc = sinowealth_get_active_profile(device);
|
||||
|
||||
Reference in New Issue
Block a user