forked from drath/libratbag
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:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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)
|
||||
|
||||
209
src/libratbag.h
209
src/libratbag.h
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user