Add resolution modes

The devices we're dealing with all have multiple DPIs to configure. This API
will replace the current ratbag_profile_set_resolution_dpi() and friends.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer
2015-08-27 15:34:04 +10:00
parent 6a2b4afa7b
commit 7da10cc074
7 changed files with 368 additions and 39 deletions

View File

@@ -122,19 +122,33 @@ hidpp10drv_read_profile(struct ratbag_profile *profile, unsigned int index)
struct ratbag_device *device = profile->device;
struct hidpp10drv_data *drv_data;
struct hidpp10_device *hidpp10;
uint16_t xres, yres, refresh;
struct hidpp10_profile p;
int rc;
unsigned int i;
uint16_t xres, yres;
drv_data = ratbag_get_drv_data(device);
hidpp10 = drv_data->dev;
rc = hidpp10_get_profile(hidpp10, index, &p);
if (rc)
return;
rc = hidpp10_get_current_resolution(hidpp10, &xres, &yres);
if (rc == 0)
profile->current_dpi = xres;
if (rc)
xres = 0xffff;
rc = hidpp10_get_usb_refresh_rate(hidpp10, &refresh);
if (rc == 0)
profile->report_rate = refresh;
profile->resolution.num_modes = p.num_dpi_modes;
for (i = 0; i < p.num_dpi_modes; i++) {
/* FIXME: we should expose x/y res separately */
profile->resolution.modes[i].dpi = p.dpi_modes[i].xres;
profile->resolution.modes[i].hz = p.refresh_rate;
profile->resolution.modes[i].is_active = false;
/* FIXME: active != default. p.default_dpi_mode is the
* default, we can only tick the active in the currently
* active profile */
if (profile->resolution.modes[i].dpi == xres)
profile->resolution.modes[i].is_active = true;
}
}
static int

View File

@@ -297,9 +297,13 @@ hidpp20drv_read_profile(struct ratbag_profile *profile, unsigned int index)
struct ratbag_device *device = profile->device;
int dpi;
/* FIXME */
#if 0
dpi = hidpp20drv_read_resolution_dpi(device);
if (dpi > 0)
profile->current_dpi = dpi;
#endif
hidpp20drv_read_special_key_mouse(device);
}

View File

@@ -26,6 +26,7 @@
#include <linux/input.h>
#include <stdint.h>
#include <stdbool.h>
#include "libratbag.h"
#include "libratbag-util.h"
@@ -178,6 +179,15 @@ struct ratbag_driver {
struct list link;
};
#define MAX_RESOLUTIONS 10
struct ratbag_resolution{
int refcount;
void *userdata;
unsigned int dpi; /**< resolution on dpi */
unsigned int hz; /**< report rate in Hz */
bool is_active;
};
struct ratbag_profile {
int refcount;
void *userdata;
@@ -188,8 +198,10 @@ struct ratbag_profile {
struct list buttons;
void *drv_data;
void *user_data;
int current_dpi;
int report_rate;
struct {
struct ratbag_resolution modes[MAX_RESOLUTIONS];
unsigned int num_modes;
} resolution;
};
#define BUTTON_ACTION_NONE \

View File

@@ -695,31 +695,95 @@ ratbag_device_set_active_profile(struct ratbag_profile *profile)
return rc;
}
LIBRATBAG_EXPORT int
ratbag_profile_get_resolution_dpi(const struct ratbag_profile *profile)
ratbag_profile_get_num_resolutions(struct ratbag_profile *profile)
{
assert(profile);
return profile->current_dpi;
return profile->resolution.num_modes;
}
LIBRATBAG_EXPORT struct ratbag_resolution *
ratbag_profile_get_resolution(struct ratbag_profile *profile, unsigned int idx)
{
struct ratbag_resolution *res;
int max = ratbag_profile_get_num_resolutions(profile);
if (max < 0 || idx >= (unsigned int)max)
return NULL;
res = &profile->resolution.modes[idx];
return ratbag_resolution_ref(res);
}
LIBRATBAG_EXPORT struct ratbag_resolution *
ratbag_resolution_ref(struct ratbag_resolution *resolution)
{
resolution->refcount++;
return resolution;
}
LIBRATBAG_EXPORT struct ratbag_resolution *
ratbag_resolution_unref(struct ratbag_resolution *resolution)
{
if (resolution == NULL)
return NULL;
assert(resolution->refcount > 0);
resolution->refcount--;
if (resolution->refcount > 0)
return resolution;
/* Resolution is a fixed list of structs, no freeing required */
return NULL;
}
LIBRATBAG_EXPORT int
ratbag_profile_set_resolution_dpi(struct ratbag_profile *profile, int dpi)
ratbag_resolution_set_dpi(struct ratbag_resolution *resolution,
unsigned int dpi)
{
if (!ratbag_device_has_capability(profile->device,
RATBAG_CAP_SWITCHABLE_RESOLUTION))
return -ENOTSUP;
assert(profile->device->driver->write_resolution_dpi);
return profile->device->driver->write_resolution_dpi(profile, dpi);
resolution->dpi = dpi;
/* FIXME: call into the driver */
return 0;
}
LIBRATBAG_EXPORT int
ratbag_profile_get_report_rate_hz(const struct ratbag_profile *profile)
ratbag_resolution_set_report_rate(struct ratbag_resolution *resolution,
unsigned int hz)
{
assert(profile);
return profile->report_rate;
resolution->hz = hz;
/* FIXME: call into the driver */
return 0;
}
LIBRATBAG_EXPORT int
ratbag_resolution_get_dpi(struct ratbag_resolution *resolution)
{
return resolution->dpi;
}
LIBRATBAG_EXPORT int
ratbag_resolution_get_report_rate(struct ratbag_resolution *resolution)
{
return resolution->hz;
}
LIBRATBAG_EXPORT int
ratbag_resolution_is_active(const struct ratbag_resolution *resolution)
{
return resolution->is_active;
}
LIBRATBAG_EXPORT int
ratbag_resolution_set_active(struct ratbag_resolution *resolution)
{
resolution->is_active = true;
/* FIXME: call into the driver */
return 0;
}
LIBRATBAG_EXPORT struct ratbag_button*
ratbag_profile_get_button_by_index(struct ratbag_profile *profile,
unsigned int index)
@@ -895,7 +959,6 @@ ratbag_button_unref(struct ratbag_button *button)
return NULL;
}
#define func_userdata(T) \
LIBRATBAG_EXPORT void \
T##_set_user_data(struct T *ptr, void *userdata) \
@@ -913,3 +976,4 @@ func_userdata(ratbag)
func_userdata(ratbag_device)
func_userdata(ratbag_profile)
func_userdata(ratbag_button)
func_userdata(ratbag_resolution)

View File

@@ -126,6 +126,18 @@ struct ratbag_profile;
*/
struct ratbag_button;
/**
* @ingroup resolution
* @struct ratbag_resolution
*
* Represents a resolution setting on the device. Most devices have multiple
* resolutions per profile, one of which is active at a time.
*
* This struct is refcounted, use ratbag_resolution_ref() and
* ratbag_resolution_unref().
*/
struct ratbag_resolution;
/**
* @ingroup base
* @struct ratbag_interface
@@ -416,6 +428,199 @@ ratbag_device_get_active_profile(struct ratbag_device *ratbag);
int
ratbag_device_set_active_profile(struct ratbag_profile *profile);
/**
* @ingroup profile
*
* Get the number of @ref ratbag_resolution available in this profile. A
* resolution mode is a tuple of (resolution, report rate), each mode can be
* fetched with ratbag_profile_get_resolution_by_idx().
*
* The returned value is the maximum number of modes available and thus
* identical for all profiles. However, some of the modes may not be
* configured.
*
* @param profile A previously initialized ratbag profile
*
* @return The number of profiles available.
*/
int
ratbag_profile_get_num_resolutions(struct ratbag_profile *profile);
/**
* @ingroup profile
*
* Return the resolution in DPI and the report rate in Hz for the resolution
* mode identified by the given index. The index must be between 0 and
* ratbag_profile_get_num_resolution_modes().
*
* See ratbag_profile_get_num_resolution_modes() for a description of
* resolution_modes.
*
* Profiles available but not currently configured on the device return
* success but set dpi and hz to 0.
*
* The returned struct has a refcount of at least 1, use
* ratbag_resolution_unref() to release the resources associated.
*
* @param profile A previously initialized ratbag profile
* @param idx The index of the resolution mode to get
*
* @return zero on success, non-zero otherwise. On error, dpi and hz are
* unmodified.
*/
struct ratbag_resolution *
ratbag_profile_get_resolution(struct ratbag_profile *profile, unsigned int idx);
/**
* @ingroup resolution
*
* Add a reference to the resolution. A resolution is destroyed whenever the
* reference count reaches 0. See @ref ratbag_resolution_unref.
*
* @param resolution A previously initialized valid ratbag resolution
* @return The passed ratbag resolution
*/
struct ratbag_resolution *
ratbag_resolution_ref(struct ratbag_resolution *resolution);
/**
* @ingroup resolution
*
* Dereference the ratbag resolution. After this, the resolution may have been
* destroyed, if the last reference was dereferenced. If so, the resolution is
* invalid and may not be interacted with.
*
* @param resolution A previously initialized ratbag resolution
* @return NULL if context was destroyed otherwise the passed resolution
*/
struct ratbag_resolution *
ratbag_resolution_unref(struct ratbag_resolution *resolution);
/**
* @ingroup resolution
*
* Set caller-specific data associated with this resolution. libratbag does
* not manage, look at, or modify this data. The caller must ensure the
* data is valid.
*
* @param resolution A previously initialized resolution
* @param userdata Caller-specific data passed to the various callback
* interfaces.
*/
void
ratbag_resolution_set_user_data(struct ratbag_resolution *resolution, void *userdata);
/**
* @ingroup resolution
*
* Get the caller-specific data associated with this resolution, if any.
*
* @param resolution A previously initialized ratbag resolution
* @return The caller-specific data previously assigned in
* ratbag_resolution_set_user_data().
*/
void*
ratbag_resolution_get_user_data(const struct ratbag_resolution *resolution);
/**
* @ingroup resolution
*
* Set the resolution in DPI for the resolution mode.
*
* A value of 0 for dpi disables the mode.
*
* If the resolution mode is the currently active mode and the profile is
* the currently active profile, the change takes effect immediately.
*
* @param resolution A previously initialized ratbag resolution
* @param dpi Set to the resolution in dpi, 0 to disable
*
* @return zero on success, non-zero otherwise
*/
int
ratbag_resolution_set_dpi(struct ratbag_resolution *resolution,
unsigned int dpi);
/**
* @ingroup resolution
*
* Get the resolution in DPI for the resolution mode.
*
* A value of 0 for dpi indicates the mode is disabled.
*
* @param resolution A previously initialized ratbag resolution
*
* @return zero on success, non-zero otherwise
*/
int
ratbag_resolution_get_dpi(struct ratbag_resolution *resolution);
/**
* @ingroup resolution
*
* Set the the report rate in Hz for the resolution mode.
*
* A value of 0 hz disables the mode.
*
* If the resolution mode is the currently active mode and the profile is
* the currently active profile, the change takes effect immediately.
*
* @param resolution A previously initialized ratbag resolution
* @param hz Set to the report rate in Hz, may be 0
*
* @return zero on success, non-zero otherwise
*/
int
ratbag_resolution_set_report_rate(struct ratbag_resolution *resolution,
unsigned int hz);
/**
* @ingroup resolution
*
* Get the the report rate in Hz for the resolution mode.
*
* A value of 0 hz indicates the mode is disabled.
*
* @param resolution A previously initialized ratbag resolution
*
* @return zero on success, non-zero otherwise
*/
int
ratbag_resolution_get_report_rate(struct ratbag_resolution *resolution);
/**
* @ingroup resolution
*
* Activate the given resolution mode. If the mode is not configured, this
* function returns an error and the result is undefined.
*
* If the profile is the currently active profile, the change takes effect
* immediately. Otherwise, the resolution mode will be the active mode when
* the device switches to the profile next.
*
* @param resolution A previously initialized ratbag resolution
*
* @return zero on success, non-zero otherwise
*/
int
ratbag_resolution_set_active(struct ratbag_resolution *resolution);
/**
* @ingroup resolution
*
* Check if the resolution mode is the currently active one.
*
* If the profile is the currently active profile, the mode is the one
* currently active. Otherwise, the resolution mode is the one used when
* the device switches to the profile next.
*
* @param resolution A previously initialized ratbag resolution
*
* @return Non-zero if the resolution mode is the active one, zero
* otherwise.
*/
int
ratbag_resolution_is_active(const struct ratbag_resolution *resolution);
/**
* @ingroup profile
*
@@ -423,6 +628,7 @@ ratbag_device_set_active_profile(struct ratbag_profile *profile);
* @return The current resolution in dots-per-inch.
* @retval 0 The resolution is unknown
*/
/* FIXME: remove me */
int
ratbag_profile_get_resolution_dpi(const struct ratbag_profile *profile);
@@ -439,6 +645,7 @@ ratbag_profile_get_resolution_dpi(const struct ratbag_profile *profile);
*
* @return 0 on success or -1 on failure
*/
/* FIXME: remove me */
int
ratbag_profile_set_resolution_dpi(struct ratbag_profile *profile, int dpi);
@@ -449,6 +656,7 @@ ratbag_profile_set_resolution_dpi(struct ratbag_profile *profile, int dpi);
* @return The current report rate in Hz
* @retval 0 The report rate is unknown
*/
/* FIXME: remove me */
int
ratbag_profile_get_report_rate_hz(const struct ratbag_profile *profile);
@@ -465,6 +673,7 @@ ratbag_profile_get_report_rate_hz(const struct ratbag_profile *profile);
*
* @return 0 on success or -1 on failure
*/
/* FIXME: remove me */
int
ratbag_profile_set_report_rate_hz(struct ratbag_profile *profile, int hz);

View File

@@ -33,13 +33,22 @@ global:
ratbag_log_set_handler;
ratbag_log_set_priority;
ratbag_profile_get_button_by_index;
ratbag_profile_get_report_rate_hz;
ratbag_profile_get_resolution_dpi;
ratbag_profile_get_num_resolutions;
ratbag_profile_get_resolution;
ratbag_profile_get_user_data;
ratbag_profile_set_resolution_dpi;
ratbag_profile_ref;
ratbag_profile_set_user_data;
ratbag_profile_unref;
ratbag_resolution_get_dpi;
ratbag_resolution_get_report_rate;
ratbag_resolution_get_user_data;
ratbag_resolution_is_active;
ratbag_resolution_ref;
ratbag_resolution_set_active;
ratbag_resolution_set_dpi;
ratbag_resolution_set_report_rate;
ratbag_resolution_set_user_data;
ratbag_resolution_unref;
ratbag_ref;
ratbag_set_user_data;
ratbag_unref;

View File

@@ -277,7 +277,7 @@ ratbag_cmd_info(struct ratbag *ratbag, uint32_t flags, int argc, char **argv)
struct ratbag_button *button;
char *action;
int num_profiles, num_buttons;
int i, b;
int i, j, b;
int rc = 1;
if (argc != 1) {
@@ -321,12 +321,20 @@ ratbag_cmd_info(struct ratbag *ratbag, uint32_t flags, int argc, char **argv)
int dpi, rate;
profile = ratbag_device_get_profile_by_index(device, i);
dpi = ratbag_profile_get_resolution_dpi(profile);
rate = ratbag_profile_get_report_rate_hz(profile);
printf(" Profile %d%s\n", i,
profile == active_profile ? " (active)" : "");
printf(" Resolution: %ddpi\n", dpi);
printf(" Report rate: %dhz\n", rate);
printf(" Resolutions:\n");
for (j = 0; j < ratbag_profile_get_num_resolutions(profile); j++) {
struct ratbag_resolution *res;
res = ratbag_profile_get_resolution(profile, j);
dpi = ratbag_resolution_get_dpi(res);
rate = ratbag_resolution_get_report_rate(res);
printf(" %d: %ddpi @ %dHz%s\n", i+1, dpi, rate,
ratbag_resolution_is_active(res) ? " (active)" : "");
ratbag_resolution_unref(res);
}
for (b = 0; b < num_buttons; b++) {
enum ratbag_button_type type;
@@ -705,6 +713,7 @@ ratbag_cmd_switch_dpi(struct ratbag *ratbag, uint32_t flags, int argc, char **ar
struct ratbag_profile *profile = NULL;
int rc = 1;
int dpi;
int i;
if (argc != 2) {
usage();
@@ -732,15 +741,23 @@ ratbag_cmd_switch_dpi(struct ratbag *ratbag, uint32_t flags, int argc, char **ar
goto out;
}
rc = ratbag_profile_set_resolution_dpi(profile, dpi);
if (!rc)
printf("Switched the current resolution profile of '%s' to %d dpi\n",
ratbag_device_get_name(device),
dpi);
else
error("can't seem to be able to change the dpi: %s (%d)\n",
strerror(-rc),
rc);
for (i = 0; i < ratbag_profile_get_num_resolutions(profile); i++) {
struct ratbag_resolution *res;
res = ratbag_profile_get_resolution(profile, i);
if (ratbag_resolution_is_active(res)) {
rc = ratbag_resolution_set_dpi(res, dpi);
if (!rc)
printf("Switched the current resolution profile of '%s' to %d dpi\n",
ratbag_device_get_name(device),
dpi);
else
error("can't seem to be able to change the dpi: %s (%d)\n",
strerror(-rc),
rc);
}
ratbag_resolution_unref(res);
}
out:
profile = ratbag_profile_unref(profile);