mirror of
https://github.com/libratbag/libratbag.git
synced 2026-11-07 23:23:52 +01:00
hidpp20: add support for 0x1b00 reprogrammable keys
As seen on the T650. Reusing most of 0x1b04 here, except this one only gives us control id, task id and flags. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
@@ -50,6 +50,7 @@
|
||||
#define HIDPP_CAP_SWITCHABLE_RESOLUTION_2201 (1 << 1)
|
||||
#define HIDPP_CAP_BUTTON_KEY_1b04 (1 << 2)
|
||||
#define HIDPP_CAP_BATTERY_LEVEL_1000 (1 << 3)
|
||||
#define HIDPP_CAP_KBD_REPROGRAMMABLE_KEYS_1b00 (1 << 4)
|
||||
|
||||
struct hidpp20drv_data {
|
||||
unsigned proto_major;
|
||||
@@ -274,6 +275,27 @@ hidpp20drv_read_special_key_mouse(struct ratbag_device *device)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
hidpp20drv_read_kbd_reprogrammable_key(struct ratbag_device *device)
|
||||
{
|
||||
struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
|
||||
int rc;
|
||||
|
||||
if (!(drv_data->capabilities & HIDPP_CAP_KBD_REPROGRAMMABLE_KEYS_1b00))
|
||||
return 0;
|
||||
|
||||
free(drv_data->controls);
|
||||
drv_data->controls = NULL;
|
||||
drv_data->num_controls = 0;
|
||||
rc = hidpp20_kbd_reprogrammable_keys_get_controls(device, &drv_data->controls);
|
||||
if (rc > 0) {
|
||||
drv_data->num_controls = rc;
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
hidpp20drv_read_profile(struct ratbag_profile *profile, unsigned int index)
|
||||
{
|
||||
@@ -338,6 +360,16 @@ hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature)
|
||||
drv_data->capabilities |= HIDPP_CAP_BATTERY_LEVEL_1000;
|
||||
break;
|
||||
}
|
||||
case HIDPP_PAGE_KBD_REPROGRAMMABLE_KEYS: {
|
||||
log_info(ratbag, "device has programmable keys/buttons\n");
|
||||
drv_data->capabilities |= HIDPP_CAP_KBD_REPROGRAMMABLE_KEYS_1b00;
|
||||
|
||||
/* we read the profile once to get the correct number of
|
||||
* supported buttons. */
|
||||
if (!hidpp20drv_read_kbd_reprogrammable_key(device))
|
||||
device->num_buttons = drv_data->num_controls;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
log_debug(device->ratbag, "unknown feature 0x%04x\n", feature);
|
||||
}
|
||||
|
||||
111
src/hidpp20.c
111
src/hidpp20.c
@@ -56,6 +56,7 @@ hidpp20_feature_get_name(uint16_t feature)
|
||||
CASE_RETURN_STRING(HIDPP_PAGE_ADJUSTABLE_DPI);
|
||||
CASE_RETURN_STRING(HIDPP_PAGE_SPECIAL_KEYS_BUTTONS);
|
||||
CASE_RETURN_STRING(HIDPP_PAGE_BATTERY_LEVEL_STATUS);
|
||||
CASE_RETURN_STRING(HIDPP_PAGE_KBD_REPROGRAMMABLE_KEYS);
|
||||
default:
|
||||
sprintf(numeric, "%#4x", feature);
|
||||
str = numeric;
|
||||
@@ -384,6 +385,116 @@ hidpp20_batterylevel_get_battery_level(struct ratbag_device *device,
|
||||
return msg.msg.parameters[2];
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 0x1b00: KBD reprogrammable keys and mouse buttons */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#define CMD_KBD_REPROGRAMMABLE_KEYS_GET_COUNT 0x00
|
||||
#define CMD_KBD_REPROGRAMMABLE_KEYS_GET_CTRL_ID_INFO 0x10
|
||||
|
||||
static int
|
||||
hidpp20_kbd_reprogrammable_keys_get_count(struct ratbag_device *device, uint8_t reg)
|
||||
{
|
||||
union hidpp20_message msg = {
|
||||
.msg.report_id = REPORT_ID_LONG,
|
||||
.msg.device_idx = 0xff,
|
||||
.msg.sub_id = reg,
|
||||
.msg.address = CMD_KBD_REPROGRAMMABLE_KEYS_GET_COUNT,
|
||||
};
|
||||
int rc;
|
||||
|
||||
rc = hidpp20_request_command(device, &msg);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return msg.msg.parameters[0];
|
||||
}
|
||||
|
||||
static int
|
||||
hidpp20_kbd_reprogrammable_keys_get_info(struct ratbag_device *device,
|
||||
uint8_t reg,
|
||||
struct hidpp20_control_id *control)
|
||||
{
|
||||
int rc;
|
||||
union hidpp20_message msg = {
|
||||
.msg.report_id = REPORT_ID_LONG,
|
||||
.msg.device_idx = 0xff,
|
||||
.msg.sub_id = reg,
|
||||
.msg.address = CMD_KBD_REPROGRAMMABLE_KEYS_GET_CTRL_ID_INFO,
|
||||
.msg.parameters[0] = control->index,
|
||||
};
|
||||
|
||||
rc = hidpp20_request_command(device, &msg);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
control->control_id = hidpp20_get_unaligned_u16(&msg.msg.parameters[0]);
|
||||
control->task_id = hidpp20_get_unaligned_u16(&msg.msg.parameters[2]);
|
||||
control->flags = msg.msg.parameters[4];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
hidpp20_kbd_reprogrammable_keys_get_controls(struct ratbag_device *device,
|
||||
struct hidpp20_control_id **controls_list)
|
||||
{
|
||||
uint8_t feature_index, feature_type, feature_version;
|
||||
struct hidpp20_control_id *c_list, *control;
|
||||
uint8_t num_controls;
|
||||
unsigned i;
|
||||
int rc;
|
||||
|
||||
rc = hidpp_root_get_feature(device,
|
||||
HIDPP_PAGE_KBD_REPROGRAMMABLE_KEYS,
|
||||
&feature_index,
|
||||
&feature_type,
|
||||
&feature_version);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = hidpp20_kbd_reprogrammable_keys_get_count(device, feature_index);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
num_controls = rc;
|
||||
if (num_controls == 0) {
|
||||
*controls_list = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
c_list = zalloc(num_controls * sizeof(struct hidpp20_control_id));
|
||||
if (!c_list)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < num_controls; i++) {
|
||||
control = &c_list[i];
|
||||
control->index = i;
|
||||
rc = hidpp20_kbd_reprogrammable_keys_get_info(device,
|
||||
feature_index,
|
||||
control);
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
/* 0x1b00 and 0x1b04 have the same control/task id mappings.
|
||||
* I hope */
|
||||
log_debug(device->ratbag,
|
||||
"control %d: cid: '%s' (%d) tid: '%s' (%d) flags: 0x%02x\n",
|
||||
control->index,
|
||||
hidpp20_1b04_get_logical_mapping_name(control->control_id),
|
||||
control->control_id,
|
||||
hidpp20_1b04_get_physical_mapping_name(control->task_id),
|
||||
control->task_id,
|
||||
control->flags);
|
||||
}
|
||||
|
||||
*controls_list = c_list;
|
||||
return num_controls;
|
||||
err:
|
||||
free(c_list);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 0x1b04: Special keys and mouse buttons */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
@@ -110,16 +110,26 @@ int hidpp20_batterylevel_get_battery_level(struct ratbag_device *device,
|
||||
uint16_t *next_level);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 0x1b04: Special keys and mouse buttons */
|
||||
/* 0x1b00: KBD reprogrammable keys and mouse buttons */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#define HIDPP_PAGE_SPECIAL_KEYS_BUTTONS 0x1b04
|
||||
#define HIDPP_PAGE_KBD_REPROGRAMMABLE_KEYS 0x1b00
|
||||
|
||||
enum hidpp2_controL_id_flags {
|
||||
HIDPP20_CONTROL_ID_FLAG_NONE = 0,
|
||||
HIDPP20_CONTROL_ID_FLAG_MOUSE_BUTTON = (1 << 0), /**< Is a mouse button */
|
||||
HIDPP20_CONTROL_ID_FLAG_FN_KEY = (1 << 1), /**< Is a fn button */
|
||||
HIDPP20_CONTROL_ID_FLAG_HOTKEY = (1 << 2), /**< Is a Hot key, not a standard kbd key */
|
||||
HIDPP20_CONTROL_ID_FLAG_FN_TOGGLE_AFFECTED = (1 << 3), /**< Fn toggle affects this key */
|
||||
HIDPP20_CONTROL_ID_FLAG_REPROGRAMMABLE = (1 << 4), /**< Key can be reprogrammed */
|
||||
};
|
||||
|
||||
struct hidpp20_control_id {
|
||||
uint8_t index;
|
||||
uint16_t control_id;
|
||||
uint16_t task_id;
|
||||
uint8_t flags;
|
||||
/* fields below are only set for 0x1b04, not for 0x1b00 */
|
||||
uint8_t position;
|
||||
uint8_t group;
|
||||
uint8_t group_mask;
|
||||
@@ -133,6 +143,15 @@ struct hidpp20_control_id {
|
||||
} reporting;
|
||||
};
|
||||
|
||||
int hidpp20_kbd_reprogrammable_keys_get_controls(struct ratbag_device *device,
|
||||
struct hidpp20_control_id **controls_list);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 0x1b04: Special keys and mouse buttons */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#define HIDPP_PAGE_SPECIAL_KEYS_BUTTONS 0x1b04
|
||||
|
||||
/**
|
||||
* allocates a list of controls that has to be freed by the caller.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user