forked from drath/libratbag
Add profile implementation
Still not populated with buttons, but it's a good start. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <linux/input.h>
|
||||
#include <stdlib.h>
|
||||
@@ -30,6 +31,10 @@
|
||||
#include "libratbag-private.h"
|
||||
#include "libratbag-hidraw.h"
|
||||
|
||||
#define ETEKCITY_PROFILE_MAX 4
|
||||
|
||||
#define ETEKCITY_REPORT_ID_KEY_MAPPING 7
|
||||
|
||||
static char *
|
||||
print_key(__u8 key)
|
||||
{
|
||||
@@ -117,13 +122,44 @@ etekcity_set_config_profile(struct ratbag *ratbag, __u8 profile, __u8 type)
|
||||
return ret == sizeof(buf) ? 0 : ret;
|
||||
}
|
||||
|
||||
static void
|
||||
etekcity_read_profile(struct ratbag_profile *profile, unsigned int index)
|
||||
{
|
||||
struct ratbag *ratbag = profile->ratbag;
|
||||
int i, rc;
|
||||
__u8 buf[50];
|
||||
__u8 data;
|
||||
|
||||
assert(index <= ETEKCITY_PROFILE_MAX);
|
||||
|
||||
etekcity_set_config_profile(ratbag, index, 0x20);
|
||||
rc = ratbag_hidraw_raw_request(ratbag, ETEKCITY_REPORT_ID_KEY_MAPPING,
|
||||
buf, sizeof(buf), HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
|
||||
|
||||
if (rc < 50)
|
||||
return;
|
||||
|
||||
log_debug(ratbag->libratbag, "profile: %d %s:%d\n",
|
||||
buf[2],
|
||||
__FILE__, __LINE__);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
data = buf[3 + i * 3];
|
||||
if (data)
|
||||
log_debug(ratbag->libratbag,
|
||||
" - button%d: %s (%02x) %s:%d\n",
|
||||
i,
|
||||
print_key(data),
|
||||
data,
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
etekcity_probe(struct ratbag *ratbag, const struct ratbag_id id)
|
||||
{
|
||||
int rc, current_profile;
|
||||
int i;
|
||||
__u8 data;
|
||||
__u8 buf[256];
|
||||
int rc;
|
||||
struct ratbag_profile *profile;
|
||||
|
||||
log_debug(ratbag->libratbag, "data: %d\n", id.data);
|
||||
|
||||
@@ -136,8 +172,11 @@ etekcity_probe(struct ratbag *ratbag, const struct ratbag_id id)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rc = etekcity_current_profile(ratbag);
|
||||
if (rc < 0) {
|
||||
ratbag->num_profiles = ETEKCITY_PROFILE_MAX;
|
||||
|
||||
profile = ratbag_get_active_profile(ratbag);
|
||||
|
||||
if (!profile) {
|
||||
log_error(ratbag->libratbag,
|
||||
"Can't talk to the mouse: '%s' (%d)\n",
|
||||
strerror(-rc),
|
||||
@@ -145,32 +184,12 @@ etekcity_probe(struct ratbag *ratbag, const struct ratbag_id id)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
current_profile = rc;
|
||||
|
||||
log_info(ratbag->libratbag,
|
||||
"'%s' is in profile %d\n",
|
||||
ratbag_get_name(ratbag),
|
||||
current_profile);
|
||||
profile->index);
|
||||
|
||||
etekcity_set_config_profile(ratbag, current_profile, 0x20);
|
||||
rc = ratbag_hidraw_raw_request(ratbag, 7, buf, sizeof(buf),
|
||||
HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
|
||||
if (rc >= 40) {
|
||||
log_debug(ratbag->libratbag, "profile: %d %s:%d\n",
|
||||
buf[2],
|
||||
__FILE__, __LINE__);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
data = buf[3 + i * 3];
|
||||
if (data)
|
||||
log_debug(ratbag->libratbag,
|
||||
" - button%d: %s (%02x) %s:%d\n",
|
||||
i,
|
||||
print_key(data),
|
||||
data,
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
profile = ratbag_profile_unref(profile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -190,4 +209,6 @@ struct ratbag_driver etekcity_driver = {
|
||||
.name = "EtekCity",
|
||||
.table_ids = etekcity_table,
|
||||
.probe = etekcity_probe,
|
||||
.read_profile = etekcity_read_profile,
|
||||
.get_active_profile = etekcity_current_profile,
|
||||
};
|
||||
|
||||
@@ -49,6 +49,9 @@ struct ratbag {
|
||||
struct input_id ids;
|
||||
struct ratbag_driver *driver;
|
||||
struct libratbag *libratbag;
|
||||
|
||||
unsigned num_profiles;
|
||||
struct list profiles;
|
||||
};
|
||||
|
||||
struct ratbag_id {
|
||||
@@ -61,11 +64,20 @@ struct ratbag_driver {
|
||||
const struct ratbag_id *table_ids;
|
||||
|
||||
int (*probe)(struct ratbag *ratbag, const struct ratbag_id id);
|
||||
void (*read_profile)(struct ratbag_profile *profile, unsigned int index);
|
||||
int (*get_active_profile)(struct ratbag *ratbag);
|
||||
|
||||
/* private */
|
||||
struct list link;
|
||||
};
|
||||
|
||||
struct ratbag_profile {
|
||||
int refcount;
|
||||
struct list link;
|
||||
unsigned index;
|
||||
struct ratbag *ratbag;
|
||||
};
|
||||
|
||||
void ratbag_device_init(struct ratbag *rb, int fd);
|
||||
|
||||
void
|
||||
|
||||
@@ -194,6 +194,7 @@ ratbag_device_init(struct ratbag *rb, int fd)
|
||||
rb->evdev_fd = fd;
|
||||
rb->hidraw_fd = -1;
|
||||
rb->refcount = 1;
|
||||
list_init(&rb->profiles);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
@@ -222,10 +223,13 @@ ratbag_find_driver(struct libratbag *libratbag, struct ratbag *ratbag,
|
||||
assert(driver->probe);
|
||||
matched_id.id = *dev_id;
|
||||
matched_id.data = matching_id->data;
|
||||
ratbag->driver = driver;
|
||||
rc = driver->probe(ratbag, matched_id);
|
||||
if (rc == 0)
|
||||
return driver;
|
||||
|
||||
ratbag->driver = NULL;
|
||||
|
||||
if (rc != -ENODEV)
|
||||
return NULL;
|
||||
}
|
||||
@@ -285,8 +289,6 @@ ratbag_new_from_fd(struct libratbag *libratbag, int fd)
|
||||
goto err_udev;
|
||||
}
|
||||
|
||||
ratbag->driver = driver;
|
||||
|
||||
return ratbag;
|
||||
|
||||
err_udev:
|
||||
@@ -384,3 +386,79 @@ libratbag_unref(struct libratbag *libratbag)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct ratbag_profile *
|
||||
ratbag_create_profile(struct ratbag *ratbag, unsigned int index)
|
||||
{
|
||||
struct ratbag_profile *profile;
|
||||
|
||||
profile = zalloc(sizeof(*profile));
|
||||
if (!profile)
|
||||
return NULL;
|
||||
|
||||
profile->refcount = 1;
|
||||
profile->ratbag = ratbag;
|
||||
profile->index = index;
|
||||
|
||||
list_insert(&ratbag->profiles, &profile->link);
|
||||
|
||||
assert(ratbag->driver->read_profile);
|
||||
ratbag->driver->read_profile(profile, index);
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
LIBRATBAG_EXPORT struct ratbag_profile *
|
||||
ratbag_profile_ref(struct ratbag_profile *profile)
|
||||
{
|
||||
profile->refcount++;
|
||||
return profile;
|
||||
}
|
||||
|
||||
LIBRATBAG_EXPORT struct ratbag_profile *
|
||||
ratbag_profile_unref(struct ratbag_profile *profile)
|
||||
{
|
||||
if (profile == NULL)
|
||||
return NULL;
|
||||
|
||||
assert(profile->refcount > 0);
|
||||
profile->refcount--;
|
||||
if (profile->refcount > 0)
|
||||
return profile;
|
||||
|
||||
list_remove(&profile->link);
|
||||
free(profile);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LIBRATBAG_EXPORT struct ratbag_profile *
|
||||
ratbag_get_profile_by_index(struct ratbag *ratbag, unsigned int index)
|
||||
{
|
||||
struct ratbag_profile *profile;
|
||||
|
||||
list_for_each(profile, &ratbag->profiles, link) {
|
||||
if (profile->index == index) {
|
||||
assert(ratbag->driver->read_profile);
|
||||
ratbag->driver->read_profile(profile, index);
|
||||
return ratbag_profile_ref(profile);
|
||||
}
|
||||
}
|
||||
|
||||
return ratbag_create_profile(ratbag, index);
|
||||
}
|
||||
|
||||
LIBRATBAG_EXPORT struct ratbag_profile *
|
||||
ratbag_get_active_profile(struct ratbag *ratbag)
|
||||
{
|
||||
int current_profile;
|
||||
|
||||
assert(ratbag->driver->get_active_profile);
|
||||
current_profile = ratbag->driver->get_active_profile(ratbag);
|
||||
if (current_profile < 0) {
|
||||
errno = -current_profile;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ratbag_get_profile_by_index(ratbag, current_profile);
|
||||
}
|
||||
|
||||
@@ -5,8 +5,12 @@ global:
|
||||
libratbag_create_context;
|
||||
libratbag_ref;
|
||||
libratbag_unref;
|
||||
ratbag_get_active_profile;
|
||||
ratbag_get_name;
|
||||
ratbag_get_profile_by_index;
|
||||
ratbag_new_from_fd;
|
||||
ratbag_profile_ref;
|
||||
ratbag_profile_unref;
|
||||
ratbag_unref;
|
||||
local:
|
||||
*;
|
||||
|
||||
@@ -49,6 +49,7 @@ main(int argc, char **argv)
|
||||
{
|
||||
struct ratbag *rb;
|
||||
struct libratbag *libratbag;
|
||||
struct ratbag_profile *profile;
|
||||
char *path;
|
||||
int fd;
|
||||
int retval = 0;
|
||||
@@ -81,7 +82,10 @@ main(int argc, char **argv)
|
||||
|
||||
fprintf(stderr, "Opened '%s' (%s).\n", ratbag_get_name(rb), path);
|
||||
|
||||
profile = ratbag_get_active_profile(rb);
|
||||
|
||||
out:
|
||||
profile = ratbag_profile_unref(profile);
|
||||
rb = ratbag_unref(rb);
|
||||
libratbag_unref(libratbag);
|
||||
close(fd);
|
||||
|
||||
Reference in New Issue
Block a user