Beispiel #1
0
static void
hidpp20drv_read_button_1b04(struct ratbag_button *button)
{
    struct ratbag_device *device = button->profile->device;
    struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
    struct hidpp20_control_id *control;
    const struct ratbag_button_action *action;
    uint16_t mapping;

    if (!(drv_data->capabilities & HIDPP_CAP_BUTTON_KEY_1b04))
        return;

    control = &drv_data->controls[button->index];
    mapping = control->control_id;
    if (control->reporting.divert || control->reporting.persist)
        mapping = control->reporting.remapped;
    log_raw(device->ratbag,
            " - button%d: %s (%02x) %s%s:%d\n",
            button->index,
            hidpp20_1b04_get_logical_mapping_name(mapping),
            mapping,
            control->reporting.divert || control->reporting.persist ? "(redirected) " : "",
            __FILE__, __LINE__);
    button->type = hidpp20_1b04_get_physical_mapping(control->task_id);
    action = hidpp20_1b04_get_logical_mapping(mapping);
    if (action)
        button->action = *action;

    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);
}
Beispiel #2
0
int
hidpp20_batterylevel_get_battery_level(struct ratbag_device *device,
				       uint16_t *level,
				       uint16_t *next_level)
{
	uint8_t feature_index, feature_type, feature_version;
	union hidpp20_message msg = {
		.msg.report_id = REPORT_ID_LONG,
		.msg.device_idx = 0xff,
		.msg.address = CMD_BATTERY_LEVEL_STATUS_GET_BATTERY_LEVEL_STATUS,
	};
	int rc;

	rc = hidpp_root_get_feature(device,
				    HIDPP_PAGE_BATTERY_LEVEL_STATUS,
				    &feature_index,
				    &feature_type,
				    &feature_version);
	if (rc)
		return rc;

	msg.msg.sub_id = feature_index;

	rc = hidpp20_request_command(device, &msg);
	if (rc)
		return rc;

	*level = msg.msg.parameters[0];
	*next_level = msg.msg.parameters[1];

	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));

	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_raw(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                                     */
/* -------------------------------------------------------------------------- */

#define CMD_SPECIAL_KEYS_BUTTONS_GET_COUNT		0x00
#define CMD_SPECIAL_KEYS_BUTTONS_GET_INFO		0x10
#define CMD_SPECIAL_KEYS_BUTTONS_GET_REPORTING		0x20
#define CMD_SPECIAL_KEYS_BUTTONS_SET_REPORTING		0x30

static int
hidpp20_special_keys_buttons_get_count(struct ratbag_device *device, uint8_t reg)
{
	int rc;
	union hidpp20_message msg = {
		.msg.report_id = REPORT_ID_LONG,
		.msg.device_idx = 0xff,
		.msg.sub_id = reg,
		.msg.address = CMD_SPECIAL_KEYS_BUTTONS_GET_COUNT,
	};

	rc = hidpp20_request_command(device, &msg);
	if (rc)
		return rc;

	return msg.msg.parameters[0];
}

static int
hidpp20_special_keys_buttons_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_SPECIAL_KEYS_BUTTONS_GET_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];
	control->position = msg.msg.parameters[5];
	control->group = msg.msg.parameters[6];
	control->group_mask = msg.msg.parameters[7];
	control->raw_XY = msg.msg.parameters[8] & 0x01;

	return 0;
}


static int
hidpp20_special_keys_buttons_get_reporting(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_SPECIAL_KEYS_BUTTONS_GET_REPORTING,
		.msg.parameters[0] = control->control_id >> 8,
		.msg.parameters[1] = control->control_id & 0xff,
	};

	rc = hidpp20_request_command(device, &msg);
	if (rc)
		return rc;

	control->reporting.remapped = hidpp20_get_unaligned_u16(&msg.msg.parameters[3]);
	control->reporting.raw_XY = !!(msg.msg.parameters[2] & 0x10);
	control->reporting.persist = !!(msg.msg.parameters[2] & 0x04);
	control->reporting.divert = !!(msg.msg.parameters[2] & 0x01);

	return 0;
}

int hidpp20_special_key_mouse_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_SPECIAL_KEYS_BUTTONS,
				    &feature_index,
				    &feature_type,
				    &feature_version);
	if (rc)
		return rc;

	rc = hidpp20_special_keys_buttons_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));

	for (i = 0; i < num_controls; i++) {
		control = &c_list[i];
		control->index = i;
		rc = hidpp20_special_keys_buttons_get_info(device,
							   feature_index,
							   control);
		if (rc)
			goto err;

		rc = hidpp20_special_keys_buttons_get_reporting(device,
								feature_index,
								control);
		if (rc)
			goto err;

		log_raw(device->ratbag,
			"control %d: cid: '%s' (%d) tid: '%s' (%d) flags: 0x%02x pos: %d group: %d gmask: 0x%02x raw_XY: %s\n"
			"      reporting: raw_xy: %s persist: %s divert: %s remapped: '%s' (%d)\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,
			control->position,
			control->group,
			control->group_mask,
			control->raw_XY ? "yes" : "no",
			control->reporting.raw_XY ? "yes" : "no",
			control->reporting.persist ? "yes" : "no",
			control->reporting.divert ? "yes" : "no",
			hidpp20_1b04_get_logical_mapping_name(control->reporting.remapped),
			control->reporting.remapped);
	}

	*controls_list = c_list;
	return num_controls;
err:
	free(c_list);
	return rc;
}