Пример #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);
}
Пример #2
0
static int
hidpp20drv_20_probe(struct ratbag_device *device)
{
    struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
    struct hidpp20_device *dev = drv_data->dev;
    struct hidpp20_feature *feature_list = dev->feature_list;
    unsigned int i;
    int rc;

    log_raw(device->ratbag,
            "'%s' has %d features\n",
            ratbag_device_get_name(device),
            dev->feature_count);

    for (i = 0; i < dev->feature_count; i++) {
        log_raw(device->ratbag, "Init feature %s (0x%04x) \n",
                hidpp20_feature_get_name(feature_list[i].feature),
                feature_list[i].feature);
        rc = hidpp20drv_init_feature(device, feature_list[i].feature);
        if (rc < 0)
            return rc;
    }

    return 0;

}
Пример #3
0
static int
hidpp20drv_read_resolution_dpi_2201(struct ratbag_device *device)
{
    struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
    struct ratbag *ratbag = device->ratbag;
    int rc;

    free(drv_data->sensors);
    drv_data->sensors = NULL;
    drv_data->num_sensors = 0;
    rc = hidpp20_adjustable_dpi_get_sensors(drv_data->dev, &drv_data->sensors);
    if (rc < 0) {
        log_error(ratbag,
                  "Error while requesting resolution: %s (%d)\n",
                  strerror(-rc), rc);
        return rc;
    } else if (rc == 0) {
        log_error(ratbag, "Error, no compatible sensors found.\n");
        return -ENODEV;
    }
    log_debug(ratbag,
              "device is at %d dpi (variable between %d and %d).\n",
              drv_data->sensors[0].dpi,
              drv_data->sensors[0].dpi_min,
              drv_data->sensors[0].dpi_max);

    drv_data->num_sensors = rc;
    drv_data->num_resolutions = drv_data->num_sensors;

    return 0;
}
Пример #4
0
static void
test_read_profile(struct ratbag_profile *profile, unsigned int index)
{
	struct ratbag_test_device *d = ratbag_get_drv_data(profile->device);
	struct ratbag_test_profile *p;
	struct ratbag_test_resolution *r;
	unsigned int i;

	assert(index < d->num_profiles);

	p = &d->profiles[index];
	profile->resolution.num_modes = p->num_resolutions;
	for (i = 0; i < p->num_resolutions; i++) {
		struct ratbag_resolution *res;

		r = &p->resolutions[i];
		res = ratbag_resolution_init(profile, i, r->xres, r->yres, r->hz);
		res->is_active = r->active;
		res->is_default = r->dflt;
		res->capabilities = r->caps;
		res->hz = r->hz;
		assert(res);
	}

	profile->is_active = p->active;
	profile->is_default = p->dflt;
}
Пример #5
0
static int
hidpp20drv_write_button_1b04(struct ratbag_button *button,
                             const struct ratbag_button_action *action)
{
    struct ratbag_device *device = button->profile->device;
    struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
    struct hidpp20_control_id *control;
    uint16_t mapping;
    int rc;

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

    control = &drv_data->controls[button->index];
    mapping = hidpp20_1b04_get_logical_control_id(action);
    if (!mapping)
        return -EINVAL;

    control->reporting.divert = 1;
    control->reporting.remapped = mapping;
    control->reporting.updated = 1;

    rc = hidpp20_special_key_mouse_set_control(drv_data->dev, control);
    if (rc == ERR_INVALID_ADDRESS)
        return -EINVAL;

    if (rc)
        log_error(device->ratbag,
                  "Error while writing profile: '%s' (%d)\n",
                  strerror(-rc),
                  rc);

    return rc;
}
Пример #6
0
static int
test_write_profile(struct ratbag_profile *profile)
{
	/* check if the device is still valid */
	assert(ratbag_get_drv_data(profile->device) != NULL);
	return 0;
}
Пример #7
0
static void
test_remove(struct ratbag_device *device)
{
	struct ratbag_test_device *d = ratbag_get_drv_data(device);

	/* remove must be called only once */
	assert(d != NULL);
	if (d->destroyed)
		d->destroyed(device, d->destroyed_data);
	ratbag_set_drv_data(device, NULL);
}
Пример #8
0
static int
hidpp20drv_write_button_8100(struct ratbag_button *button,
                             const struct ratbag_button_action *action)
{
    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, subtype;

    if (!(drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100))
        return -ENOTSUP;

    profile = &drv_data->profiles->profiles[button->profile->index];

    switch (action->type) {
    case RATBAG_BUTTON_ACTION_TYPE_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_TYPE;
        subtype = HIDPP20_BUTTON_HID_TYPE_KEYBOARD;
        code = ratbag_hidraw_get_keyboard_usage_from_keycode(device, action->action.key.key);
        if (code == 0) {
            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].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].special.type = HIDPP20_BUTTON_SPECIAL;
        profile->buttons[button->index].special.special = code;
        break;
    case RATBAG_BUTTON_ACTION_TYPE_MACRO:
    default:
        return -ENOTSUP;
    }

    return hidpp20_onboard_profiles_write(drv_data->dev, button->profile->index, drv_data->profiles);
}
Пример #9
0
static void
hidpp20drv_read_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;
    int rc;

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

    profile = &drv_data->profiles->profiles[button->profile->index];

    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].special.special);
        break;
    case HIDPP20_BUTTON_MACRO:
        rc = hidpp20drv_read_macro_8100(button, profile, &profile->buttons[button->index]);
        if (rc)
            button->action.type = RATBAG_BUTTON_ACTION_TYPE_NONE;
        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);
}
Пример #10
0
static void
hidpp20drv_read_profile(struct ratbag_profile *profile, unsigned int index)
{
    struct ratbag_device *device = profile->device;
    struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);

    if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)
        return hidpp20drv_read_profile_8100(profile, index);

    hidpp20drv_read_resolution_dpi(profile);
    hidpp20drv_read_special_key_mouse(device);

    profile->is_active = (index == 0);
}
Пример #11
0
static int
hidpp20drv_write_button(struct ratbag_button *button,
                        const struct ratbag_button_action *action)
{
    struct ratbag_device *device = button->profile->device;
    struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);

    if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)
        return hidpp20drv_write_button_8100(button, action);

    if (drv_data->capabilities & HIDPP_CAP_BUTTON_KEY_1b04)
        return hidpp20drv_write_button_1b04(button, action);

    return -ENOTSUP;
}
Пример #12
0
static int
hidpp20drv_current_profile(struct ratbag_device *device)
{
    struct hidpp20drv_data *drv_data = ratbag_get_drv_data((struct ratbag_device *)device);
    int rc;

    if (!(drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100))
        return 0;

    rc = hidpp20_onboard_profiles_get_current_profile(drv_data->dev);
    if (rc < 0)
        return rc;

    return rc - 1;
}
Пример #13
0
static int
hidpp20drv_read_onboard_profile(struct ratbag_device *device, unsigned index)
{
    struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
    int rc;

    if (!(drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100))
        return 0;

    rc = hidpp20_onboard_profiles_read(drv_data->dev, index, drv_data->profiles);
    if (rc < 0)
        return rc;

    return 0;
}
Пример #14
0
static int
hidpp20drv_write_resolution_dpi(struct ratbag_resolution *resolution,
                                int dpi_x, int dpi_y)
{
    struct ratbag_profile *profile = resolution->profile;
    struct ratbag_device *device = profile->device;
    struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
    struct hidpp20_sensor *sensor;
    int rc, i;
    int dpi = dpi_x; /* dpi_x == dpi_y if we don't have the individual resolution cap */

    if (drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100)
        return hidpp20drv_write_resolution_dpi_8100(resolution, dpi_x, dpi_y);

    if (!(drv_data->capabilities & HIDPP_CAP_SWITCHABLE_RESOLUTION_2201))
        return -ENOTSUP;

    if (!drv_data->num_sensors)
        return -ENOTSUP;

    /* just for clarity, we use the first available sensor only */
    sensor = &drv_data->sensors[0];

    /* validate that the sensor accepts the given DPI */
    rc = -EINVAL;
    if (dpi < sensor->dpi_min || dpi > sensor->dpi_max)
        goto out;
    if (sensor->dpi_steps) {
        for (i = sensor->dpi_min; i < dpi; i += sensor->dpi_steps) {
        }
        if (i != dpi)
            goto out;
    } else {
        i = 0;
        while (sensor->dpi_list[i]) {
            if (sensor->dpi_list[i] == dpi)
                break;
        }
        if (sensor->dpi_list[i] != dpi)
            goto out;
    }

    rc = hidpp20_adjustable_dpi_set_sensor_dpi(drv_data->dev, sensor, dpi);

out:
    return rc;
}
Пример #15
0
static int
hidpp20drv_read_resolution_dpi(struct ratbag_profile *profile)
{
    struct ratbag_device *device = profile->device;
    struct ratbag *ratbag = device->ratbag;
    struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
    struct ratbag_resolution *res;
    int rc;
    unsigned int i;

    if (drv_data->capabilities & HIDPP_CAP_RESOLUTION_2200) {
        uint16_t resolution;
        uint8_t flags;

        rc = hidpp20_mousepointer_get_mousepointer_info(drv_data->dev, &resolution, &flags);
        if (rc) {
            log_error(ratbag,
                      "Error while requesting resolution: %s (%d)\n",
                      strerror(-rc), rc);
            return rc;
        }

        return 0;
    }

    if (drv_data->capabilities & HIDPP_CAP_SWITCHABLE_RESOLUTION_2201) {
        rc = hidpp20drv_read_resolution_dpi_2201(device);
        if (rc < 0)
            return rc;
        for (i = 0; i < profile->resolution.num_modes; i++) {
            int dpi = drv_data->sensors[i].dpi;
            /* FIXME: retrieve the refresh rate */
            res = ratbag_resolution_init(profile, i, dpi, dpi, 0);

            /* FIXME: we mark all resolutions as active because
             * they are from different sensors */
            res->is_active = true;
        }

        return 0;
    }

    return 0;
}
Пример #16
0
static void
hidpp20drv_remove(struct ratbag_device *device)
{
    struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
    struct hidpp20_device *dev = drv_data->dev;

    if (!device)
        return;

    ratbag_close_hidraw(device);

    if (drv_data->profiles)
        hidpp20_onboard_profiles_destroy(dev, drv_data->profiles);
    free(drv_data->controls);
    free(drv_data->sensors);
    if (drv_data->dev)
        hidpp20_device_destroy(drv_data->dev);
    free(drv_data);
}
Пример #17
0
static int
hidpp20drv_write_resolution_dpi_8100(struct ratbag_resolution *resolution,
                                     int dpi_x, int dpi_y)
{
    struct ratbag_profile *profile = resolution->profile;
    struct ratbag_device *device = profile->device;
    struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
    struct hidpp20_profile *h_profile;
    unsigned int index;
    int dpi = dpi_x; /* dpi_x == dpi_y if we don't have the individual resolution cap */

    /* retrieve which resolution is asked to be changed */
    index = resolution - profile->resolution.modes;

    h_profile = &drv_data->profiles->profiles[profile->index];
    h_profile->dpi[index] = dpi;

    return hidpp20_onboard_profiles_write(drv_data->dev, profile->index, drv_data->profiles);
}
Пример #18
0
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(drv_data->dev, &drv_data->controls);
    if (rc > 0) {
        drv_data->num_controls = rc;
        rc = 0;
    }

    return rc;
}
Пример #19
0
static int
hidpp20drv_read_special_key_mouse(struct ratbag_device *device)
{
    struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
    int rc;

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

    free(drv_data->controls);
    drv_data->controls = NULL;
    drv_data->num_controls = 0;
    rc = hidpp20_special_key_mouse_get_controls(drv_data->dev, &drv_data->controls);
    if (rc > 0) {
        drv_data->num_controls = rc;
        rc = 0;
    }

    return rc;
}
Пример #20
0
static int
hidpp20drv_set_current_profile(struct ratbag_device *device, unsigned int index)
{
    struct hidpp20drv_data *drv_data = ratbag_get_drv_data((struct ratbag_device *)device);
    struct hidpp20_profile *h_profile;
    int rc;

    if (!(drv_data->capabilities & HIDPP_CAP_ONBOARD_PROFILES_8100))
        return 0;

    if (index >= drv_data->num_profiles)
        return -EINVAL;

    h_profile = &drv_data->profiles->profiles[index];
    if (!h_profile->enabled) {
        rc = hidpp20_onboard_profiles_write(drv_data->dev, index, drv_data->profiles);
        if (rc)
            return rc;
    }

    return hidpp20_onboard_profiles_set_current_profile(drv_data->dev, index);
}
Пример #21
0
static void
hidpp20drv_read_profile_8100(struct ratbag_profile *profile, unsigned int index)
{
    struct ratbag_device *device = profile->device;
    struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
    struct ratbag_resolution *res;
    struct hidpp20_profile *p;
    unsigned i, dpi = 0;

    hidpp20drv_read_onboard_profile(device, profile->index);

    profile->is_active = false;
    if ((int)index == hidpp20drv_current_profile(device))
        profile->is_active = true;

    /* retrieve the resolution through 220X as the profile doesn't has it */
    if (profile->is_active)
        hidpp20drv_read_resolution_dpi(profile);

    dpi = ratbag_resolution_get_dpi(profile->resolution.modes);

    p = &drv_data->profiles->profiles[index];

    for (i = 0; i < profile->resolution.num_modes; i++) {
        res = ratbag_resolution_init(profile, i,
                                     p->dpi[i],
                                     p->dpi[i],
                                     p->report_rate);

        if (profile->is_active &&
                res->dpi_x == dpi)
            res->is_active = true;
        if (i == p->default_dpi)
            res->is_default = true;
    }
}
Пример #22
0
static int
hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature)
{
    struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device);
    struct ratbag *ratbag = device->ratbag;
    int rc;
    uint8_t feature_index, feature_type, feature_version;

    rc = hidpp_root_get_feature(drv_data->dev,
                                feature,
                                &feature_index,
                                &feature_type,
                                &feature_version);

    switch (feature) {
    case HIDPP_PAGE_ROOT:
    case HIDPP_PAGE_FEATURE_SET:
        /* these features are mandatory and already handled */
        break;
    case HIDPP_PAGE_MOUSE_POINTER_BASIC: {
        drv_data->capabilities |= HIDPP_CAP_RESOLUTION_2200;
        break;
    }
    case HIDPP_PAGE_ADJUSTABLE_DPI: {
        log_debug(ratbag, "device has adjustable dpi\n");
        /* we read the profile once to get the correct number of
         * supported resolutions. */
        rc = hidpp20drv_read_resolution_dpi_2201(device);
        if (rc < 0)
            return 0; /* this is not a hard failure */
        ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_SWITCHABLE_RESOLUTION);
        drv_data->capabilities |= HIDPP_CAP_SWITCHABLE_RESOLUTION_2201;
        break;
    }
    case HIDPP_PAGE_SPECIAL_KEYS_BUTTONS: {
        log_debug(ratbag, "device has programmable keys/buttons\n");
        drv_data->capabilities |= HIDPP_CAP_BUTTON_KEY_1b04;
        ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_KEY);
        /* we read the profile once to get the correct number of
         * supported buttons. */
        if (!hidpp20drv_read_special_key_mouse(device))
            device->num_buttons = drv_data->num_controls;
        break;
    }
    case HIDPP_PAGE_BATTERY_LEVEL_STATUS: {
        uint16_t level, next_level;
        enum hidpp20_battery_status status;

        rc = hidpp20_batterylevel_get_battery_level(drv_data->dev, &level, &next_level);
        if (rc < 0)
            return rc;
        status = rc;

        log_debug(ratbag, "device battery level is %d%% (next %d%%), status %d \n",
                  level, next_level, status);

        drv_data->capabilities |= HIDPP_CAP_BATTERY_LEVEL_1000;
        break;
    }
    case HIDPP_PAGE_KBD_REPROGRAMMABLE_KEYS: {
        log_debug(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;
    }
    case HIDPP_PAGE_ADJUSTABLE_REPORT_RATE: {
        log_debug(ratbag, "device has adjustable report rate\n");
        break;
    }
    case HIDPP_PAGE_COLOR_LED_EFFECTS: {
        log_debug(ratbag, "device has color effects\n");
        break;
    }
    case HIDPP_PAGE_ONBOARD_PROFILES: {
        log_debug(ratbag, "device has onboard profiles\n");
        drv_data->capabilities |= HIDPP_CAP_ONBOARD_PROFILES_8100;

        rc = hidpp20_onboard_profiles_allocate(drv_data->dev, &drv_data->profiles);
        if (rc < 0)
            return rc;

        drv_data->num_profiles = drv_data->profiles->num_profiles;
        drv_data->num_resolutions = drv_data->profiles->num_modes;
        drv_data->num_buttons = drv_data->profiles->num_buttons;

        break;
    }
    case HIDPP_PAGE_MOUSE_BUTTON_SPY: {
        log_debug(ratbag, "device has configurable mouse button spy\n");
        break;
    }
    default:
        log_raw(device->ratbag, "unknown feature 0x%04x\n", feature);
    }
    return 0;
}