From 26fdafb881bf8b87ace7087f0923778a92711dc3 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Tue, 20 Oct 2015 17:25:59 -0400 Subject: [PATCH] hidpp20: parse the buttons mapping in the profiles Only export the actual buttons in ratbag_button for now. Signed-off-by: Benjamin Tissoires --- src/driver-hidpp20.c | 36 +++++++++++++++++++++++++++++++++++- src/hidpp20.c | 38 +++++++++++++++++++++++++++++++------- src/hidpp20.h | 14 ++++++++++++++ 3 files changed, 80 insertions(+), 8 deletions(-) diff --git a/src/driver-hidpp20.c b/src/driver-hidpp20.c index e7cb19d2..8cbd7101 100644 --- a/src/driver-hidpp20.c +++ b/src/driver-hidpp20.c @@ -64,7 +64,7 @@ struct hidpp20drv_data { }; static void -hidpp20drv_read_button(struct ratbag_button *button) +hidpp20drv_button_key_1b04_read_button(struct ratbag_button *button) { struct ratbag_device *device = button->profile->device; struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device); @@ -96,6 +96,40 @@ hidpp20drv_read_button(struct ratbag_button *button) ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_SPECIAL); } +static void +hidpp20drv_onboard_profile_8100_read_button(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; + + if (!(drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)) + return; + + profile = &drv_data->profiles->profiles[button->profile->index]; + + switch (profile->buttons[button->index].type) { + case HIDPP20_BUTTON_HID_MOUSE: + button->action.type = RATBAG_BUTTON_ACTION_TYPE_BUTTON; + button->action.action.button = profile->buttons[button->index].code; + break; + default: + button->action.type = RATBAG_BUTTON_ACTION_TYPE_UNKNOWN; + } + + ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_BUTTON); + ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_KEY); + ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_SPECIAL); + ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_MACRO); +} + +static void +hidpp20drv_read_button(struct ratbag_button *button) +{ + hidpp20drv_button_key_1b04_read_button(button); + hidpp20drv_onboard_profile_8100_read_button(button); +} + static int hidpp20drv_write_button(struct ratbag_button *button, const struct ratbag_button_action *action) diff --git a/src/hidpp20.c b/src/hidpp20.c index 2e23cc73..9de4de07 100644 --- a/src/hidpp20.c +++ b/src/hidpp20.c @@ -930,6 +930,9 @@ int hidpp20_adjustable_dpi_set_sensor_dpi(struct hidpp20_device *device, #define CMD_ONBOARD_PROFILES_GET_CURRENT_DPI_INDEX 0xb0 #define CMD_ONBOARD_PROFILES_SET_CURRENT_DPI_INDEX 0xc0 +#define HIDPP20_PROFILE_SIZE (15*16) +#define HIDPP20_BUTTON_HID 0x80 + static int hidpp20_onboard_profiles_read_memory(struct hidpp20_device *device, uint16_t page, @@ -1066,7 +1069,7 @@ int hidpp20_onboard_profiles_read(struct hidpp20_device *device, unsigned int index, struct hidpp20_profiles *profiles_list) { - uint8_t data[16] = {0}; + uint8_t data[HIDPP20_PROFILE_SIZE] = {0}; struct hidpp20_profile *profile = &profiles_list->profiles[index]; unsigned i; int rc; @@ -1074,12 +1077,14 @@ int hidpp20_onboard_profiles_read(struct hidpp20_device *device, if (index >= profiles_list->num_profiles) return -EINVAL; - rc = hidpp20_onboard_profiles_read_memory(device, - index + 1, - 0x0000, - data); - if (rc < 0) - return rc; + for (i = 0; i < HIDPP20_PROFILE_SIZE / 0x10; i++) { + rc = hidpp20_onboard_profiles_read_memory(device, + index + 1, + i * 0x10, + data + i * 0x10); + if (rc < 0) + return rc; + } profile->report_rate = 1000 / max(1, data[0]); profile->default_dpi = data[1]; @@ -1089,6 +1094,25 @@ int hidpp20_onboard_profiles_read(struct hidpp20_device *device, profile->dpi[i] = hidpp20_get_unaligned_be_u16(&data[2 * i + 3]); } + for (i = 0; i < profiles_list->num_buttons; i++) { + uint8_t *button = data + 0x20 + i * 4; + + profile->buttons[i].type = button[0]; + + if (button[0] == HIDPP20_BUTTON_HID) { + profile->buttons[i].type |= button[1]; + + if (profile->buttons[i].type == HIDPP20_BUTTON_HID_KEYBOARD) { + profile->buttons[i].modifiers = button[2]; + profile->buttons[i].code = button[3]; + } else { + profile->buttons[i].code = ffs(hidpp20_get_unaligned_u16(&button[2])); + } + } else if (button[0] == HIDPP20_BUTTON_SPECIAL) { + profile->buttons[i].code = button[1]; + } + } + return 0; } diff --git a/src/hidpp20.h b/src/hidpp20.h index d136421a..9bfab212 100644 --- a/src/hidpp20.h +++ b/src/hidpp20.h @@ -264,6 +264,15 @@ int hidpp20_adjustable_dpi_set_sensor_dpi(struct hidpp20_device *device, #define HIDPP_PAGE_ONBOARD_PROFILES 0x8100 +#define HIDPP20_BUTTON_HID_MOUSE 0x81 +#define HIDPP20_BUTTON_HID_KEYBOARD 0x82 +#define HIDPP20_BUTTON_HID_CONSUMER_CONTROL 0x83 +#define HIDPP20_BUTTON_SPECIAL 0x90 +#define HIDPP20_BUTTON_DISABLED 0xFF + +#define HIDPP20_MODIFIER_KEY_CTRL 0x01 +#define HIDPP20_MODIFIER_KEY_SHIFT 0x02 + struct hidpp20_profile { uint8_t index; uint8_t enabled; @@ -271,6 +280,11 @@ struct hidpp20_profile { unsigned default_dpi; unsigned switched_dpi; uint16_t dpi[5]; + struct { + uint8_t type; + uint8_t modifiers; + uint8_t code; + } buttons[32]; }; struct hidpp20_profiles {