mirror of
https://github.com/libratbag/libratbag.git
synced 2026-11-08 07:33:53 +01:00
hidpp20: clean the button mapping code
The button mapping of the hid++ 2.0 devices is close to the one from HID++ 1.0, but not entirely (1.0 have a size of 3 while and 2.0 a size of 4). The parsing was not clean, so reuse a the same logic than hidpp10. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
This commit is contained in:
@@ -109,24 +109,28 @@ hidpp20drv_read_button_8100(struct ratbag_button *button)
|
||||
|
||||
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;
|
||||
case HIDPP20_BUTTON_HID_KEYBOARD:
|
||||
button->action.type = RATBAG_BUTTON_ACTION_TYPE_KEY;
|
||||
button->action.action.key.key = ratbag_hidraw_get_keycode_from_keyboard_usage(device,
|
||||
profile->buttons[button->index].code);
|
||||
break;
|
||||
case HIDPP20_BUTTON_HID_CONSUMER_CONTROL:
|
||||
button->action.type = RATBAG_BUTTON_ACTION_TYPE_KEY;
|
||||
button->action.action.key.key = ratbag_hidraw_get_keycode_from_consumer_usage(device,
|
||||
profile->buttons[button->index].code);
|
||||
switch (profile->buttons[button->index].any.type) {
|
||||
case HIDPP20_BUTTON_HID_TYPE:
|
||||
switch (profile->buttons[button->index].subany.subtype) {
|
||||
case HIDPP20_BUTTON_HID_TYPE_MOUSE:
|
||||
button->action.type = RATBAG_BUTTON_ACTION_TYPE_BUTTON;
|
||||
button->action.action.button = profile->buttons[button->index].button.buttons;
|
||||
break;
|
||||
case HIDPP20_BUTTON_HID_TYPE_KEYBOARD:
|
||||
button->action.type = RATBAG_BUTTON_ACTION_TYPE_KEY;
|
||||
button->action.action.key.key = ratbag_hidraw_get_keycode_from_keyboard_usage(device,
|
||||
profile->buttons[button->index].keyboard_keys.key);
|
||||
break;
|
||||
case HIDPP20_BUTTON_HID_TYPE_CONSUMER_CONTROL:
|
||||
button->action.type = RATBAG_BUTTON_ACTION_TYPE_KEY;
|
||||
button->action.action.key.key = ratbag_hidraw_get_keycode_from_consumer_usage(device,
|
||||
profile->buttons[button->index].consumer_control.consumer_control);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case HIDPP20_BUTTON_SPECIAL:
|
||||
button->action.type = RATBAG_BUTTON_ACTION_TYPE_SPECIAL;
|
||||
button->action.action.special = hidpp20_onboard_profiles_get_special(profile->buttons[button->index].code);
|
||||
button->action.action.special = hidpp20_onboard_profiles_get_special(profile->buttons[button->index].special.special);
|
||||
break;
|
||||
default:
|
||||
button->action.type = RATBAG_BUTTON_ACTION_TYPE_UNKNOWN;
|
||||
@@ -187,7 +191,7 @@ hidpp20drv_write_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;
|
||||
uint8_t code, type;
|
||||
uint8_t code, type, subtype;
|
||||
|
||||
if (!(drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100))
|
||||
return -ENOTSUP;
|
||||
@@ -196,27 +200,33 @@ hidpp20drv_write_button_8100(struct ratbag_button *button,
|
||||
|
||||
switch (action->type) {
|
||||
case RATBAG_BUTTON_ACTION_TYPE_BUTTON:
|
||||
profile->buttons[button->index].type = HIDPP20_BUTTON_HID_MOUSE;
|
||||
profile->buttons[button->index].code = action->action.button;
|
||||
profile->buttons[button->index].button.type = HIDPP20_BUTTON_HID_TYPE;
|
||||
profile->buttons[button->index].button.subtype = HIDPP20_BUTTON_HID_TYPE_MOUSE;
|
||||
profile->buttons[button->index].button.buttons = action->action.button;
|
||||
break;
|
||||
case RATBAG_BUTTON_ACTION_TYPE_KEY:
|
||||
type = HIDPP20_BUTTON_HID_KEYBOARD;
|
||||
type = HIDPP20_BUTTON_HID_TYPE;
|
||||
subtype = HIDPP20_BUTTON_HID_TYPE_KEYBOARD;
|
||||
code = ratbag_hidraw_get_keyboard_usage_from_keycode(device, action->action.key.key);
|
||||
if (code == 0) {
|
||||
type = HIDPP20_BUTTON_HID_CONSUMER_CONTROL;
|
||||
subtype = HIDPP20_BUTTON_HID_TYPE_CONSUMER_CONTROL;
|
||||
code = ratbag_hidraw_get_consumer_usage_from_keycode(device, action->action.key.key);
|
||||
if (code == 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
profile->buttons[button->index].type = type;
|
||||
profile->buttons[button->index].code = code;
|
||||
profile->buttons[button->index].subany.type = type;
|
||||
profile->buttons[button->index].subany.subtype = subtype;
|
||||
if (subtype == HIDPP20_BUTTON_HID_TYPE_KEYBOARD)
|
||||
profile->buttons[button->index].keyboard_keys.key = code;
|
||||
else
|
||||
profile->buttons[button->index].consumer_control.consumer_control = code;
|
||||
break;
|
||||
case RATBAG_BUTTON_ACTION_TYPE_SPECIAL:
|
||||
code = hidpp20_onboard_profiles_get_code_from_special(action->action.special);
|
||||
if (code == 0)
|
||||
return -EINVAL;
|
||||
profile->buttons[button->index].type = HIDPP20_BUTTON_SPECIAL;
|
||||
profile->buttons[button->index].code = code;
|
||||
profile->buttons[button->index].special.type = HIDPP20_BUTTON_SPECIAL;
|
||||
profile->buttons[button->index].special.special = code;
|
||||
break;
|
||||
case RATBAG_BUTTON_ACTION_TYPE_MACRO:
|
||||
default:
|
||||
|
||||
146
src/hidpp20.c
146
src/hidpp20.c
@@ -1256,23 +1256,6 @@ hidpp20_onboard_profiles_enable_profile(struct hidpp20_device *device,
|
||||
return hidpp20_onboard_profiles_write_page(device, 0x00, data);
|
||||
}
|
||||
|
||||
struct hidpp20_internal_button {
|
||||
uint8_t type;
|
||||
union {
|
||||
struct {
|
||||
uint8_t subtype;
|
||||
union {
|
||||
struct {
|
||||
uint8_t modifier;
|
||||
uint8_t code;
|
||||
} key;
|
||||
uint16_t button;
|
||||
} __attribute__((packed));
|
||||
} __attribute__((packed)) hid;
|
||||
uint8_t special;
|
||||
} value;
|
||||
} __attribute__((packed));
|
||||
|
||||
union hidpp20_internal_profile {
|
||||
uint8_t data[HIDPP20_PROFILE_SIZE];
|
||||
struct {
|
||||
@@ -1282,8 +1265,8 @@ union hidpp20_internal_profile {
|
||||
uint16_t dpi[7];
|
||||
uint8_t zero;
|
||||
uint8_t padding[14];
|
||||
struct hidpp20_internal_button buttons[16];
|
||||
struct hidpp20_internal_button alternate_buttons[16];
|
||||
union hidpp20_button_binding buttons[16];
|
||||
union hidpp20_button_binding alternate_buttons[16];
|
||||
union {
|
||||
char txt[16 * 3];
|
||||
uint8_t raw[16 * 3];
|
||||
@@ -1294,6 +1277,90 @@ union hidpp20_internal_profile {
|
||||
};
|
||||
_Static_assert(sizeof(union hidpp20_internal_profile) == HIDPP20_PROFILE_SIZE, "Invalid size");
|
||||
|
||||
static void
|
||||
hidpp20_buttons_to_cpu(struct hidpp20_profile *profile,
|
||||
union hidpp20_button_binding *buttons,
|
||||
unsigned int count)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
union hidpp20_button_binding *b = &buttons[i];
|
||||
union hidpp20_button_binding *button = &profile->buttons[i];
|
||||
|
||||
button->any.type = b->any.type;
|
||||
|
||||
switch (b->any.type) {
|
||||
case HIDPP20_BUTTON_HID_TYPE:
|
||||
button->subany.subtype = b->subany.subtype;
|
||||
switch (b->subany.subtype) {
|
||||
case HIDPP20_BUTTON_HID_TYPE_MOUSE:
|
||||
button->button.buttons = ffs(hidpp_be_u16_to_cpu(b->button.buttons));
|
||||
break;
|
||||
case HIDPP20_BUTTON_HID_TYPE_KEYBOARD:
|
||||
button->keyboard_keys.modifier_flags = b->keyboard_keys.modifier_flags;
|
||||
button->keyboard_keys.key = b->keyboard_keys.key;
|
||||
break;
|
||||
case HIDPP20_BUTTON_HID_TYPE_CONSUMER_CONTROL:
|
||||
button->consumer_control.consumer_control =
|
||||
hidpp_be_u16_to_cpu(b->consumer_control.consumer_control);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case HIDPP20_BUTTON_SPECIAL:
|
||||
button->special.special = b->special.special;
|
||||
break;
|
||||
case HIDPP20_BUTTON_DISABLED:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hidpp20_buttons_from_cpu(struct hidpp20_profile *profile,
|
||||
union hidpp20_button_binding *buttons,
|
||||
unsigned int count)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
union hidpp20_button_binding *button = &buttons[i];
|
||||
union hidpp20_button_binding *b = &profile->buttons[i];
|
||||
|
||||
button->any.type = b->any.type;
|
||||
|
||||
switch (b->any.type) {
|
||||
case HIDPP20_BUTTON_HID_TYPE:
|
||||
button->subany.subtype = b->subany.subtype;
|
||||
switch (b->subany.subtype) {
|
||||
case HIDPP20_BUTTON_HID_TYPE_MOUSE:
|
||||
button->button.buttons = hidpp_cpu_to_be_u16(1U << (b->button.buttons - 1));
|
||||
break;
|
||||
case HIDPP20_BUTTON_HID_TYPE_KEYBOARD:
|
||||
button->keyboard_keys.modifier_flags = b->keyboard_keys.modifier_flags;
|
||||
button->keyboard_keys.key = b->keyboard_keys.key;
|
||||
break;
|
||||
case HIDPP20_BUTTON_HID_TYPE_CONSUMER_CONTROL:
|
||||
button->consumer_control.type = HIDPP20_BUTTON_HID_TYPE;
|
||||
button->consumer_control.subtype = HIDPP20_BUTTON_HID_TYPE_CONSUMER_CONTROL;
|
||||
button->consumer_control.consumer_control =
|
||||
hidpp_cpu_to_be_u16(b->consumer_control.consumer_control);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case HIDPP20_BUTTON_SPECIAL:
|
||||
button->special.special = b->special.special;
|
||||
break;
|
||||
case HIDPP20_BUTTON_DISABLED:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int hidpp20_onboard_profiles_read(struct hidpp20_device *device,
|
||||
unsigned int index,
|
||||
struct hidpp20_profiles *profiles_list)
|
||||
@@ -1319,27 +1386,7 @@ int hidpp20_onboard_profiles_read(struct hidpp20_device *device,
|
||||
profile->dpi[i] = hidpp_get_unaligned_le_u16(&data[2 * i + 3]);
|
||||
}
|
||||
|
||||
for (i = 0; i < profiles_list->num_buttons; i++) {
|
||||
struct hidpp20_internal_button *button = &pdata.profile.buttons[i];
|
||||
|
||||
profile->buttons[i].type = button->type;
|
||||
|
||||
if (button->type == HIDPP20_BUTTON_HID) {
|
||||
profile->buttons[i].type |= button->value.hid.subtype;
|
||||
|
||||
if (profile->buttons[i].type == HIDPP20_BUTTON_HID_KEYBOARD) {
|
||||
profile->buttons[i].modifiers = button->value.hid.key.modifier;
|
||||
profile->buttons[i].code = button->value.hid.key.code;
|
||||
} else if (profile->buttons[i].type == HIDPP20_BUTTON_HID_CONSUMER_CONTROL) {
|
||||
profile->buttons[i].modifiers = button->value.hid.key.modifier;
|
||||
profile->buttons[i].code = button->value.hid.key.code;
|
||||
} else {
|
||||
profile->buttons[i].code = ffs(hidpp_be_u16_to_cpu(button->value.hid.button));
|
||||
}
|
||||
} else if (button->type == HIDPP20_BUTTON_SPECIAL) {
|
||||
profile->buttons[i].code = button->value.special;
|
||||
}
|
||||
}
|
||||
hidpp20_buttons_to_cpu(profile, pdata.profile.buttons, profiles_list->num_buttons);
|
||||
|
||||
memcpy(profile->name, pdata.profile.name.txt, sizeof(profile->name));
|
||||
/* force terminating '\0' */
|
||||
@@ -1385,24 +1432,7 @@ int hidpp20_onboard_profiles_write(struct hidpp20_device *device,
|
||||
pdata.profile.dpi[i] = hidpp_cpu_to_le_u16(profile->dpi[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < profiles_list->num_buttons; i++) {
|
||||
struct hidpp20_internal_button *button = &pdata.profile.buttons[i];
|
||||
|
||||
button->type = profile->buttons[i].type & 0xf0;
|
||||
|
||||
if (button->type == HIDPP20_BUTTON_HID) {
|
||||
button->value.hid.subtype = profile->buttons[i].type & 0x0f;
|
||||
|
||||
if (button->value.hid.subtype == HIDPP20_BUTTON_HID_KEYBOARD) {
|
||||
button->value.hid.key.modifier = profile->buttons[i].modifiers;
|
||||
button->value.hid.key.code = profile->buttons[i].code;
|
||||
} else {
|
||||
button->value.hid.button = hidpp_cpu_to_be_u16(1U << (profile->buttons[i].code - 1));
|
||||
}
|
||||
} else if (button->type == HIDPP20_BUTTON_SPECIAL) {
|
||||
button->value.special = profile->buttons[i].code;
|
||||
}
|
||||
}
|
||||
hidpp20_buttons_from_cpu(profile, pdata.profile.buttons, profiles_list->num_buttons);
|
||||
|
||||
memcpy(pdata.profile.name.txt, profile->name, sizeof(profile->name));
|
||||
|
||||
|
||||
@@ -264,14 +264,49 @@ 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_BUTTON_HID_TYPE 0x80
|
||||
#define HIDPP20_BUTTON_HID_TYPE_MOUSE 0x01
|
||||
#define HIDPP20_BUTTON_HID_TYPE_KEYBOARD 0x02
|
||||
#define HIDPP20_BUTTON_HID_TYPE_CONSUMER_CONTROL 0x03
|
||||
#define HIDPP20_BUTTON_SPECIAL 0x90
|
||||
#define HIDPP20_BUTTON_DISABLED 0xFF
|
||||
|
||||
#define HIDPP20_MODIFIER_KEY_CTRL 0x01
|
||||
#define HIDPP20_MODIFIER_KEY_SHIFT 0x02
|
||||
#define HIDPP20_MODIFIER_KEY_CTRL 0x01
|
||||
#define HIDPP20_MODIFIER_KEY_SHIFT 0x02
|
||||
|
||||
union hidpp20_button_binding {
|
||||
struct {
|
||||
uint8_t type;
|
||||
} any;
|
||||
struct {
|
||||
uint8_t type;
|
||||
uint8_t subtype;
|
||||
} subany;
|
||||
struct {
|
||||
uint8_t type; /* HIDPP20_BUTTON_HID_TYPE */
|
||||
uint8_t subtype; /* HIDPP20_BUTTON_HID_TYPE_MOUSE */
|
||||
uint16_t buttons; /* flags when internal */
|
||||
} __attribute__((packed)) button;
|
||||
struct {
|
||||
uint8_t type; /* HIDPP20_BUTTON_HID_TYPE */
|
||||
uint8_t subtype; /* HIDPP20_BUTTON_HID_TYPE_KEYBOARD */
|
||||
uint8_t modifier_flags;
|
||||
uint8_t key;
|
||||
} __attribute__((packed)) keyboard_keys;
|
||||
struct {
|
||||
uint8_t type; /* HIDPP20_BUTTON_HID_TYPE */
|
||||
uint8_t subtype; /* HIDPP20_BUTTON_HID_TYPE_CONSUMER_CONTROL */
|
||||
uint16_t consumer_control;
|
||||
} __attribute__((packed)) consumer_control;
|
||||
struct {
|
||||
uint8_t type; /* HIDPP20_BUTTON_SPECIAL */
|
||||
uint8_t special;
|
||||
} __attribute__((packed)) special;
|
||||
struct {
|
||||
uint8_t type; /* PROFILE_BUTTON_TYPE_DISABLED */
|
||||
} disabled;
|
||||
} __attribute__((packed));
|
||||
_Static_assert(sizeof(union hidpp20_button_binding) == 4, "Invalid size");
|
||||
|
||||
struct hidpp20_profile {
|
||||
uint8_t index;
|
||||
@@ -281,11 +316,7 @@ 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];
|
||||
union hidpp20_button_binding buttons[32];
|
||||
};
|
||||
|
||||
struct hidpp20_profiles {
|
||||
|
||||
Reference in New Issue
Block a user