forked from drath/libratbag
hidpp10: correctly retrieve the profile directory and use it
We need to read the directory and the profiles only once. Nothing tells us how many profiles are supported, so use the specifications from Logitech website, and add a hwdb entry for those. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
This commit is contained in:
committed by
Peter Hutterer
parent
98fb63e2e3
commit
2c799eca30
@@ -69,31 +69,41 @@ mouse:usb:v046dpc041:name:*:
|
||||
RATBAG_HIDPP10_DPI_LIST=400;800;1600;2000
|
||||
|
||||
# G5 2007
|
||||
# http://support.logitech.com/en_us/product/g5-laser-mouse-product/specs
|
||||
mouse:usb:v046dpc049:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_HIDPP10_DPI_LIST=400;800;1600;2000
|
||||
RATBAG_HIDPP10_PROFILE_COUNT=1
|
||||
|
||||
# G7
|
||||
# http://support.logitech.com/en_us/product/g7-laser-cordless-mouse/specs
|
||||
mouse:usb:v046dpc51a:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_HIDPP10_PROFILE_COUNT=1
|
||||
|
||||
# G9
|
||||
# http://support.logitech.com/en_us/product/g9-laser-mouse/specs
|
||||
mouse:usb:v046dpc048:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_HIDPP10_DPI_LIST=0;200;400;600;800;1000;1200;1400;1600;1800;2000;2200;2400;2600;2800;3000;3200
|
||||
RATBAG_HIDPP10_PROFILE=G9
|
||||
RATBAG_HIDPP10_PROFILE_COUNT=5
|
||||
|
||||
# G9x [Original]
|
||||
# http://support.logitech.com/en_us/product/g9x-laser-mouse/specs
|
||||
mouse:usb:v046dpc066:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_HIDPP10_DPI=0:5700@23.53
|
||||
RATBAG_HIDPP10_PROFILE=G500
|
||||
RATBAG_HIDPP10_PROFILE_COUNT=5
|
||||
|
||||
# G9x [Call of Duty MW3 Edition]
|
||||
# http://support.logitech.com/en_us/product/laser-mouse-g9x/specs
|
||||
mouse:usb:v046dpc249:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_HIDPP10_DPI=0:5700@23.53
|
||||
RATBAG_HIDPP10_PROFILE=G500
|
||||
RATBAG_HIDPP10_PROFILE_COUNT=5
|
||||
|
||||
# G300
|
||||
mouse:usb:v046dpc246:name:*:
|
||||
@@ -106,18 +116,22 @@ mouse:usb:v046dpc082:name:*:
|
||||
RATBAG_SVG=logitech-g403.svg
|
||||
|
||||
# G500
|
||||
# http://support.logitech.com/en_us/product/gaming-mouse-g500/specs
|
||||
mouse:usb:v046dpc068:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_SVG=logitech-g500.svg
|
||||
RATBAG_HIDPP10_DPI=0:5700@23.53
|
||||
RATBAG_HIDPP10_PROFILE=G500
|
||||
RATBAG_HIDPP10_PROFILE_COUNT=1
|
||||
|
||||
# G500s
|
||||
# http://support.logitech.com/en_us/product/g500s-laser-gaming-mouse/specs
|
||||
mouse:usb:v046dpc24e:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_SVG=logitech-g500s.svg
|
||||
RATBAG_HIDPP10_DPI=0:8200@50
|
||||
RATBAG_HIDPP10_PROFILE=G500
|
||||
RATBAG_HIDPP10_PROFILE_COUNT=1
|
||||
|
||||
# G502 Proteus Core over USB
|
||||
mouse:usb:v046dpc07d:name:*:
|
||||
@@ -130,33 +144,41 @@ mouse:usb:v046dpc332:name:*:
|
||||
RATBAG_SVG=logitech-g502.svg
|
||||
|
||||
# G700 over USB
|
||||
# http://support.logitech.com/en_us/product/wireless-gaming-mouse-g700/specs
|
||||
mouse:usb:v046dpc06b:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_SVG=logitech-g700.svg
|
||||
RATBAG_HIDPP10_DPI=0:5700@23.53
|
||||
RATBAG_HIDPP10_PROFILE=G700
|
||||
RATBAG_HIDPP10_PROFILE_COUNT=5
|
||||
|
||||
# G700 over wireless USB
|
||||
# http://support.logitech.com/en_us/product/wireless-gaming-mouse-g700/specs
|
||||
mouse:usb:v046dpc531:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_HIDPP10_DPI=0:5700@23.53
|
||||
RATBAG_HIDPP10_PROFILE=G700
|
||||
RATBAG_HIDPP10_INDEX=1
|
||||
RATBAG_HIDPP10_PROFILE_COUNT=5
|
||||
|
||||
# G700s over USB
|
||||
# http://support.logitech.com/en_us/product/g700s-rechargable-wireless-gaming-mouse/specs
|
||||
mouse:usb:v046dpc07c:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_SVG=logitech-g700.svg
|
||||
RATBAG_HIDPP10_DPI=0:8200@50
|
||||
RATBAG_HIDPP10_PROFILE=G700
|
||||
RATBAG_HIDPP10_PROFILE_COUNT=5
|
||||
|
||||
# G700s over wireless USB
|
||||
# http://support.logitech.com/en_us/product/g700s-rechargable-wireless-gaming-mouse/specs
|
||||
mouse:usb:v046dpc531:name:*:
|
||||
RATBAG_DRIVER=hidpp10
|
||||
RATBAG_SVG=logitech-g700.svg
|
||||
RATBAG_HIDPP10_DPI=0:8200@50
|
||||
RATBAG_HIDPP10_PROFILE=G700
|
||||
RATBAG_HIDPP10_INDEX=1
|
||||
RATBAG_HIDPP10_PROFILE_COUNT=5
|
||||
|
||||
# MX Master over unifying
|
||||
mouse:usb:v046dp4041:name:*:
|
||||
|
||||
@@ -356,12 +356,12 @@ 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;
|
||||
struct hidpp10_profile p;
|
||||
struct hidpp10_profile p = {0};
|
||||
struct ratbag_resolution *res;
|
||||
int rc;
|
||||
unsigned int i;
|
||||
uint16_t xres, yres;
|
||||
int8_t idx;
|
||||
uint8_t idx;
|
||||
|
||||
drv_data = ratbag_get_drv_data(device);
|
||||
hidpp10 = drv_data->dev;
|
||||
@@ -369,6 +369,8 @@ hidpp10drv_read_profile(struct ratbag_profile *profile, unsigned int index)
|
||||
if (rc)
|
||||
return;
|
||||
|
||||
profile->is_enabled = p.enabled;
|
||||
|
||||
rc = hidpp10_get_current_profile(hidpp10, &idx);
|
||||
if (rc == 0 && (unsigned int)idx == profile->index)
|
||||
profile->is_active = true;
|
||||
@@ -458,24 +460,23 @@ static int
|
||||
hidpp10drv_fill_from_profile(struct ratbag_device *device, struct hidpp10_device *dev)
|
||||
{
|
||||
int rc;
|
||||
struct hidpp10_profile profile;
|
||||
struct hidpp10_directory directory[16];
|
||||
int count;
|
||||
|
||||
count = hidpp10_get_profile_directory(dev, directory, ARRAY_LENGTH(directory));
|
||||
if (count < 0)
|
||||
return count;
|
||||
struct hidpp10_profile profile = {0};
|
||||
unsigned int i;
|
||||
|
||||
/* We don't know the HID++1.0 requests to query for buttons, etc.
|
||||
* Simply get the first profile and fill the device information in
|
||||
* from that.
|
||||
* Simply get the first enabled profile and fill in the device
|
||||
* information from that.
|
||||
*/
|
||||
rc = hidpp10_get_profile(dev, 0, &profile);
|
||||
if (rc)
|
||||
return rc;
|
||||
for (i = 0; i < dev->profile_count; i++) {
|
||||
rc = hidpp10_get_profile(dev, i, &profile);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (profile.enabled)
|
||||
break;
|
||||
}
|
||||
|
||||
ratbag_device_init_profiles(device,
|
||||
count,
|
||||
dev->profile_count,
|
||||
profile.num_dpi_modes,
|
||||
profile.num_buttons,
|
||||
profile.num_leds);
|
||||
@@ -483,6 +484,7 @@ hidpp10drv_fill_from_profile(struct ratbag_device *device, struct hidpp10_device
|
||||
if (dev->profile_type != HIDPP10_PROFILE_UNKNOWN) {
|
||||
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_PROFILE);
|
||||
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_SWITCHABLE_PROFILE);
|
||||
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_DISABLE_PROFILE);
|
||||
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON);
|
||||
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_KEY);
|
||||
ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_MACROS);
|
||||
@@ -516,6 +518,7 @@ hidpp10drv_probe(struct ratbag_device *device)
|
||||
const char *prop;
|
||||
int device_idx = HIDPP_WIRED_DEVICE_IDX;
|
||||
int nread = 0;
|
||||
unsigned int profile_count = 1;
|
||||
|
||||
rc = ratbag_find_hidraw(device, hidpp10drv_test_hidraw);
|
||||
if (rc)
|
||||
@@ -533,6 +536,10 @@ hidpp10drv_probe(struct ratbag_device *device)
|
||||
type = HIDPP10_PROFILE_G700;
|
||||
else if (strcasecmp("G9", prop) == 0)
|
||||
type = HIDPP10_PROFILE_G9;
|
||||
|
||||
prop = ratbag_device_get_udev_property(device, "RATBAG_HIDPP10_PROFILE_COUNT");
|
||||
if (prop)
|
||||
profile_count = atoi(prop);
|
||||
}
|
||||
|
||||
prop = ratbag_device_get_udev_property(device, "RATBAG_HIDPP10_INDEX");
|
||||
@@ -554,7 +561,7 @@ hidpp10drv_probe(struct ratbag_device *device)
|
||||
* If there is a special need like for G700(s), we can pass a
|
||||
* udev prop RATBAG_HIDPP10_INDEX.
|
||||
*/
|
||||
dev = hidpp10_device_new(&base, device_idx, type);
|
||||
dev = hidpp10_device_new(&base, device_idx, type, profile_count);
|
||||
|
||||
if (!dev) {
|
||||
log_error(device->ratbag,
|
||||
@@ -592,6 +599,10 @@ hidpp10drv_probe(struct ratbag_device *device)
|
||||
device->name);
|
||||
}
|
||||
|
||||
rc = hidpp10_device_read_profiles(dev);
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
drv_data->dev = dev;
|
||||
ratbag_set_drv_data(device, drv_data);
|
||||
|
||||
|
||||
194
src/hidpp10.c
194
src/hidpp10.c
@@ -163,9 +163,6 @@ hidpp10_build_dpi_table_from_list(struct hidpp10_device *dev,
|
||||
if (index != count)
|
||||
goto err;
|
||||
|
||||
/* mark the state as invalid */
|
||||
dev->profile_count = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
@@ -203,9 +200,6 @@ hidpp10_build_dpi_table_from_dpi_info(struct hidpp10_device *dev,
|
||||
dev->dpi_table[i].dpi = round((min + step * i) / 25.0f) * 25;
|
||||
}
|
||||
|
||||
/* mark the state as invalid */
|
||||
dev->profile_count = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -720,31 +714,20 @@ hidpp10_get_dpi_value(struct hidpp10_device *dev, uint8_t raw_value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
hidpp10_get_profile_directory(struct hidpp10_device *dev,
|
||||
struct hidpp10_directory *out,
|
||||
size_t nelems)
|
||||
static int
|
||||
hidpp10_read_profile_directory(struct hidpp10_device *dev)
|
||||
{
|
||||
unsigned int i;
|
||||
int res;
|
||||
uint8_t bytes[HIDPP10_PAGE_SIZE] = { 0 };
|
||||
struct hidpp10_directory *directory = (struct hidpp10_directory *)bytes;
|
||||
size_t count;
|
||||
unsigned int count;
|
||||
|
||||
if (dev->profile_type == HIDPP10_PROFILE_UNKNOWN) {
|
||||
hidpp_log_debug(&dev->base, "no profile type given\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dev->profile_directory) {
|
||||
count = 0;
|
||||
while (dev->profile_directory[count].page) {
|
||||
count++;
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
hidpp_log_raw(&dev->base, "Fetching the profiles' directory\n");
|
||||
|
||||
res = hidpp10_read_page(dev, 0x01, bytes);
|
||||
@@ -752,46 +735,29 @@ hidpp10_get_profile_directory(struct hidpp10_device *dev,
|
||||
return res;
|
||||
|
||||
count = 0;
|
||||
/* assume 16 profiles max */
|
||||
for (i = 0; i < 16; i++) {
|
||||
for (i = 0; i < dev->profile_count; i++) {
|
||||
if (directory[i].page == 0xFF)
|
||||
break;
|
||||
dev->profiles[i].page = directory[i].page;
|
||||
dev->profiles[i].offset = directory[i].offset;
|
||||
dev->profiles[i].enabled = true;
|
||||
count++;
|
||||
}
|
||||
|
||||
dev->profile_directory = zalloc((count + 1) * sizeof(struct hidpp10_directory));
|
||||
memcpy(dev->profile_directory, directory, count * sizeof(struct hidpp10_directory));
|
||||
|
||||
out:
|
||||
if (dev->profile_count != count) {
|
||||
if (dev->profiles)
|
||||
free(dev->profiles);
|
||||
dev->profiles = zalloc(count * sizeof(struct hidpp10_profile));
|
||||
dev->profile_count = count;
|
||||
}
|
||||
count = min(count, nelems);
|
||||
memcpy(out, dev->profile_directory, count * sizeof(out[0]));
|
||||
for (i = count; i < dev->profile_count; i++)
|
||||
dev->profiles[i].enabled = false;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int
|
||||
hidpp10_get_current_profile(struct hidpp10_device *dev, int8_t *current_profile)
|
||||
hidpp10_get_current_profile(struct hidpp10_device *dev, uint8_t *current_profile)
|
||||
{
|
||||
unsigned idx = dev->index;
|
||||
union hidpp10_message profile = CMD_PROFILE(idx, GET_REGISTER_REQ);
|
||||
int res;
|
||||
unsigned i;
|
||||
int8_t type, page, offset;
|
||||
struct hidpp10_directory directory[16]; /* completely random profile count */
|
||||
int count = 0;
|
||||
|
||||
hidpp_log_raw(&dev->base, "Fetching the profiles' directory\n");
|
||||
|
||||
count = hidpp10_get_profile_directory(dev, directory,
|
||||
ARRAY_LENGTH(directory));
|
||||
if (count < 0)
|
||||
return count;
|
||||
uint8_t type, page, offset;
|
||||
|
||||
hidpp_log_raw(&dev->base, "Fetching current profile\n");
|
||||
|
||||
@@ -806,14 +772,14 @@ hidpp10_get_current_profile(struct hidpp10_device *dev, int8_t *current_profile)
|
||||
*current_profile = page;
|
||||
/* If the profile exceeds the directory length, default to
|
||||
* the first */
|
||||
if (*current_profile > count)
|
||||
if (*current_profile > dev->profile_count)
|
||||
*current_profile = 0;
|
||||
return 0;
|
||||
case PROFILE_TYPE_ADDRESS:
|
||||
offset = profile.msg.parameters[2];
|
||||
for (i = 0; i < ARRAY_LENGTH(directory) && directory[i].page < 32; i++) {
|
||||
if (page == directory[i].page &&
|
||||
offset == directory[i].offset) {
|
||||
for (i = 0; i < dev->profile_count; i++) {
|
||||
if (page == dev->profiles[i].page &&
|
||||
offset == dev->profiles[i].offset) {
|
||||
*current_profile = i;
|
||||
return 0;
|
||||
}
|
||||
@@ -833,21 +799,12 @@ hidpp10_get_current_profile(struct hidpp10_device *dev, int8_t *current_profile)
|
||||
|
||||
static int
|
||||
hidpp10_set_internal_current_profile(struct hidpp10_device *dev,
|
||||
int16_t current_profile,
|
||||
uint16_t current_profile,
|
||||
uint8_t profile_type)
|
||||
{
|
||||
unsigned idx = dev->index;
|
||||
union hidpp10_message profile = CMD_PROFILE(idx, SET_REGISTER_REQ);
|
||||
int8_t page, offset;
|
||||
struct hidpp10_directory directory[16]; /* completely random profile count */
|
||||
int count = 0;
|
||||
|
||||
hidpp_log_raw(&dev->base, "Fetching the profiles' directory\n");
|
||||
|
||||
count = hidpp10_get_profile_directory(dev, directory,
|
||||
ARRAY_LENGTH(directory));
|
||||
if (count < 0)
|
||||
return count;
|
||||
|
||||
hidpp_log_raw(&dev->base, "Setting current profile\n");
|
||||
|
||||
@@ -855,7 +812,7 @@ hidpp10_set_internal_current_profile(struct hidpp10_device *dev,
|
||||
|
||||
switch (profile_type) {
|
||||
case PROFILE_TYPE_INDEX:
|
||||
if (current_profile > count)
|
||||
if (current_profile > dev->profile_count)
|
||||
return -EINVAL;
|
||||
profile.msg.parameters[1] = current_profile & 0xFF;
|
||||
break;
|
||||
@@ -878,7 +835,7 @@ hidpp10_set_internal_current_profile(struct hidpp10_device *dev,
|
||||
}
|
||||
|
||||
int
|
||||
hidpp10_set_current_profile(struct hidpp10_device *dev, int16_t current_profile)
|
||||
hidpp10_set_current_profile(struct hidpp10_device *dev, uint16_t current_profile)
|
||||
{
|
||||
return hidpp10_set_internal_current_profile(dev,
|
||||
current_profile,
|
||||
@@ -1431,8 +1388,8 @@ hidpp10_profile_set_names(struct hidpp10_device *dev, struct hidpp10_profile *pr
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
hidpp10_get_profile(struct hidpp10_device *dev, int8_t number, struct hidpp10_profile *profile_return)
|
||||
static int
|
||||
hidpp10_read_profile(struct hidpp10_device *dev, uint8_t number)
|
||||
{
|
||||
uint8_t page_data[HIDPP10_PAGE_SIZE];
|
||||
union _hidpp10_profile_data *data = (union _hidpp10_profile_data *)page_data;
|
||||
@@ -1442,9 +1399,7 @@ hidpp10_get_profile(struct hidpp10_device *dev, int8_t number, struct hidpp10_pr
|
||||
size_t i;
|
||||
int res;
|
||||
struct hidpp10_profile *profile;
|
||||
struct hidpp10_directory directory[16]; /* completely random profile count */
|
||||
union _hidpp10_button_binding *buttons;
|
||||
int count = 0;
|
||||
uint8_t page;
|
||||
|
||||
/* Page 0 is RAM
|
||||
@@ -1458,19 +1413,18 @@ hidpp10_get_profile(struct hidpp10_device *dev, int8_t number, struct hidpp10_pr
|
||||
|
||||
hidpp_log_raw(&dev->base, "Fetching profile %d\n", number);
|
||||
|
||||
count = hidpp10_get_profile_directory(dev, directory,
|
||||
ARRAY_LENGTH(directory));
|
||||
if (count < 0)
|
||||
return count;
|
||||
|
||||
if (count == 0 || dev->profile_type == HIDPP10_PROFILE_UNKNOWN)
|
||||
if (dev->profile_type == HIDPP10_PROFILE_UNKNOWN)
|
||||
return -ENOTSUP;
|
||||
|
||||
if (number >= count) {
|
||||
hidpp_log_error(&dev->base, "Profile number %d not in the directory.\n", number);
|
||||
if (number >= dev->profile_count) {
|
||||
hidpp_log_error(&dev->base, "Profile number %d is not supported.\n", number);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
profile = &dev->profiles[number];
|
||||
if (!profile->enabled)
|
||||
return 0;
|
||||
|
||||
switch (dev->profile_type) {
|
||||
case HIDPP10_PROFILE_G500:
|
||||
buttons = p500->buttons;
|
||||
@@ -1486,10 +1440,8 @@ hidpp10_get_profile(struct hidpp10_device *dev, int8_t number, struct hidpp10_pr
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
profile = &dev->profiles[number];
|
||||
if (!profile->initialized) {
|
||||
|
||||
page = directory[number].page;
|
||||
page = profile->page;
|
||||
res = hidpp10_read_page(dev, page, page_data);
|
||||
if (res == -EILSEQ) {
|
||||
/*
|
||||
@@ -1597,8 +1549,21 @@ hidpp10_get_profile(struct hidpp10_device *dev, int8_t number, struct hidpp10_pr
|
||||
}
|
||||
}
|
||||
|
||||
*profile_return = *profile;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
hidpp10_get_profile(struct hidpp10_device *dev, uint8_t number, struct hidpp10_profile *profile_return)
|
||||
{
|
||||
if (dev->profile_type == HIDPP10_PROFILE_UNKNOWN)
|
||||
return -ENOTSUP;
|
||||
|
||||
if (number >= dev->profile_count) {
|
||||
hidpp_log_error(&dev->base, "Profile number %d is not supported.\n", number);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*profile_return = dev->profiles[number];
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1648,7 +1613,7 @@ hidpp10_onboard_profiles_get_code_from_special(enum ratbag_button_action_special
|
||||
}
|
||||
|
||||
int
|
||||
hidpp10_set_profile(struct hidpp10_device *dev, int8_t number, struct hidpp10_profile *profile)
|
||||
hidpp10_set_profile(struct hidpp10_device *dev, uint8_t number, struct hidpp10_profile *profile)
|
||||
{
|
||||
uint8_t page_data[HIDPP10_PAGE_SIZE];
|
||||
union _hidpp10_profile_data *data = (union _hidpp10_profile_data *)page_data;
|
||||
@@ -1656,27 +1621,24 @@ hidpp10_set_profile(struct hidpp10_device *dev, int8_t number, struct hidpp10_pr
|
||||
struct _hidpp10_profile_700 *p700 = &data->profile_700;
|
||||
struct _hidpp10_profile_9 *p9 = &data->profile_9;
|
||||
int res;
|
||||
struct hidpp10_directory directory[16]; /* completely random profile count */
|
||||
union _hidpp10_button_binding *buttons;
|
||||
int count = 0;
|
||||
uint16_t crc;
|
||||
uint8_t page;
|
||||
|
||||
hidpp_log_raw(&dev->base, "Fetching profile %d\n", number);
|
||||
|
||||
count = hidpp10_get_profile_directory(dev, directory,
|
||||
ARRAY_LENGTH(directory));
|
||||
if (count < 0)
|
||||
return count;
|
||||
|
||||
if (count == 0 || dev->profile_type == HIDPP10_PROFILE_UNKNOWN)
|
||||
if (dev->profile_type == HIDPP10_PROFILE_UNKNOWN)
|
||||
return -ENOTSUP;
|
||||
|
||||
if (number >= count) {
|
||||
hidpp_log_error(&dev->base, "Profile number %d not in the directory.\n", number);
|
||||
if (number >= dev->profile_count) {
|
||||
hidpp_log_error(&dev->base, "Profile number %d is incorrect.\n", number);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* we do not support not enabled profiles just now */
|
||||
if (!profile->page)
|
||||
return -ENOTSUP;
|
||||
|
||||
memset(page_data, 0xff, sizeof(page_data));
|
||||
|
||||
switch (dev->profile_type) {
|
||||
@@ -1702,7 +1664,7 @@ hidpp10_set_profile(struct hidpp10_device *dev, int8_t number, struct hidpp10_pr
|
||||
case HIDPP10_PROFILE_G9:
|
||||
/* we do not know the actual values of the remaining field right now
|
||||
* so pre-fill with the current data */
|
||||
res = hidpp10_read_page(dev, directory[number].page, page_data);
|
||||
res = hidpp10_read_page(dev, profile->page, page_data);
|
||||
if (res)
|
||||
return res;
|
||||
break;
|
||||
@@ -1779,7 +1741,7 @@ hidpp10_set_profile(struct hidpp10_device *dev, int8_t number, struct hidpp10_pr
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
page = directory[number].page;
|
||||
page = profile->page;
|
||||
/* according to the spec, a profile can have an offset.
|
||||
* For all the devices we know, they all start at 0x0000 */
|
||||
res = hidpp10_erase_memory(dev, page);
|
||||
@@ -1811,6 +1773,7 @@ hidpp10_set_profile(struct hidpp10_device *dev, int8_t number, struct hidpp10_pr
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
dev->profiles[number] = *profile;
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2655,14 +2618,10 @@ hidpp10_get_device_info(struct hidpp10_device *dev)
|
||||
{
|
||||
uint32_t feature_mask, notifications;
|
||||
uint8_t reflect;
|
||||
int i;
|
||||
uint16_t xres, yres;
|
||||
uint16_t refresh_rate;
|
||||
enum hidpp10_led_status led[6];
|
||||
int8_t current_profile;
|
||||
struct hidpp10_profile profiles[HIDPP10_NUM_PROFILES];
|
||||
int count;
|
||||
struct hidpp10_directory directory[16];
|
||||
uint8_t current_profile;
|
||||
|
||||
hidpp10_get_individual_features(dev, &feature_mask);
|
||||
hidpp10_get_hidpp_notifications(dev, ¬ifications);
|
||||
@@ -2674,18 +2633,14 @@ hidpp10_get_device_info(struct hidpp10_device *dev)
|
||||
hidpp10_get_optical_sensor_settings(dev, &reflect);
|
||||
|
||||
hidpp10_get_current_profile(dev, ¤t_profile);
|
||||
|
||||
count = hidpp10_get_profile_directory(dev, directory,
|
||||
ARRAY_LENGTH(directory));
|
||||
for (i = 0; i < count && i < HIDPP10_NUM_PROFILES; i++)
|
||||
hidpp10_get_profile(dev, i, &profiles[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct hidpp10_device*
|
||||
hidpp10_device_new(const struct hidpp_device *base, int idx,
|
||||
enum hidpp10_profile_type type)
|
||||
hidpp10_device_new(const struct hidpp_device *base,
|
||||
int idx,
|
||||
enum hidpp10_profile_type type,
|
||||
unsigned int profile_count)
|
||||
{
|
||||
struct hidpp10_device *dev;
|
||||
|
||||
@@ -2694,6 +2649,8 @@ hidpp10_device_new(const struct hidpp_device *base, int idx,
|
||||
dev->index = idx;
|
||||
dev->base = *base;
|
||||
dev->profile_type = type;
|
||||
dev->profile_count = profile_count;
|
||||
dev->profiles = zalloc(dev->profile_count * sizeof(struct hidpp10_profile));
|
||||
|
||||
if (hidpp10_get_device_info(dev) != 0) {
|
||||
hidpp10_device_destroy(dev);
|
||||
@@ -2703,6 +2660,19 @@ hidpp10_device_new(const struct hidpp_device *base, int idx,
|
||||
return dev;
|
||||
}
|
||||
|
||||
int
|
||||
hidpp10_device_read_profiles(struct hidpp10_device *dev)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
hidpp10_read_profile_directory(dev);
|
||||
|
||||
for (i = 0; i < dev->profile_count && i < HIDPP10_NUM_PROFILES; i++)
|
||||
hidpp10_read_profile(dev, i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
hidpp10_device_destroy(struct hidpp10_device *dev)
|
||||
{
|
||||
@@ -2711,19 +2681,15 @@ hidpp10_device_destroy(struct hidpp10_device *dev)
|
||||
|
||||
if (dev->dpi_table)
|
||||
free(dev->dpi_table);
|
||||
if (dev->profile_directory)
|
||||
free(dev->profile_directory);
|
||||
if (dev->profiles) {
|
||||
for (i = 0; i < dev->profile_count; i++) {
|
||||
ARRAY_FOR_EACH(dev->profiles[i].macros, macro) {
|
||||
if (*macro) {
|
||||
free(*macro);
|
||||
*macro = NULL;
|
||||
}
|
||||
for (i = 0; i < dev->profile_count; i++) {
|
||||
ARRAY_FOR_EACH(dev->profiles[i].macros, macro) {
|
||||
if (*macro) {
|
||||
free(*macro);
|
||||
*macro = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
free(dev->profiles);
|
||||
}
|
||||
|
||||
free(dev->profiles);
|
||||
free(dev);
|
||||
}
|
||||
|
||||
@@ -59,15 +59,19 @@ struct hidpp10_device {
|
||||
unsigned index;
|
||||
uint8_t dpi_count;
|
||||
struct hidpp10_dpi_mapping *dpi_table;
|
||||
struct hidpp10_directory *profile_directory; /* must be null terminated */
|
||||
enum hidpp10_profile_type profile_type;
|
||||
struct hidpp10_profile *profiles;
|
||||
unsigned int profile_count;
|
||||
};
|
||||
|
||||
struct hidpp10_device*
|
||||
hidpp10_device_new(const struct hidpp_device *base, int idx,
|
||||
enum hidpp10_profile_type type);
|
||||
hidpp10_device_new(const struct hidpp_device *base,
|
||||
int idx,
|
||||
enum hidpp10_profile_type type,
|
||||
unsigned int profile_count);
|
||||
|
||||
int
|
||||
hidpp10_device_read_profiles(struct hidpp10_device *dev);
|
||||
|
||||
void
|
||||
hidpp10_device_destroy(struct hidpp10_device *dev);
|
||||
@@ -463,6 +467,8 @@ union hidpp10_macro_data {
|
||||
_Static_assert(sizeof(union hidpp10_macro_data) == 5, "Invalid size");
|
||||
|
||||
struct hidpp10_profile {
|
||||
uint8_t page;
|
||||
uint8_t offset;
|
||||
struct {
|
||||
uint16_t xres;
|
||||
uint16_t yres;
|
||||
@@ -512,6 +518,7 @@ struct hidpp10_profile {
|
||||
size_t num_leds;
|
||||
|
||||
unsigned int initialized;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
struct hidpp10_directory {
|
||||
@@ -521,22 +528,17 @@ struct hidpp10_directory {
|
||||
} __attribute__((packed));
|
||||
|
||||
int
|
||||
hidpp10_get_profile_directory(struct hidpp10_device *dev,
|
||||
struct hidpp10_directory *out,
|
||||
size_t nelems);
|
||||
hidpp10_get_current_profile(struct hidpp10_device *dev, uint8_t *current_profile);
|
||||
|
||||
int
|
||||
hidpp10_get_current_profile(struct hidpp10_device *dev, int8_t *current_profile);
|
||||
hidpp10_set_current_profile(struct hidpp10_device *dev, uint16_t current_profile);
|
||||
|
||||
int
|
||||
hidpp10_set_current_profile(struct hidpp10_device *dev, int16_t current_profile);
|
||||
|
||||
int
|
||||
hidpp10_get_profile(struct hidpp10_device *dev, int8_t number,
|
||||
hidpp10_get_profile(struct hidpp10_device *dev, uint8_t number,
|
||||
struct hidpp10_profile *profile);
|
||||
|
||||
int
|
||||
hidpp10_set_profile(struct hidpp10_device *dev, int8_t number,
|
||||
hidpp10_set_profile(struct hidpp10_device *dev, uint8_t number,
|
||||
struct hidpp10_profile *profile);
|
||||
|
||||
enum ratbag_button_action_special
|
||||
|
||||
@@ -146,7 +146,7 @@ hidpp10_init(int fd)
|
||||
hidpp_device_init(&base, fd);
|
||||
|
||||
return hidpp10_device_new(&base, HIDPP_RECEIVER_IDX,
|
||||
HIDPP10_PROFILE_UNKNOWN);
|
||||
HIDPP10_PROFILE_UNKNOWN, 1);
|
||||
}
|
||||
|
||||
_EXPORT_ int
|
||||
@@ -201,8 +201,7 @@ lur_receiver_enumerate(struct lur_receiver *lur,
|
||||
uint32_t serial;
|
||||
bool is_new_device = true;
|
||||
|
||||
d = hidpp10_device_new(&base, i,
|
||||
HIDPP10_PROFILE_UNKNOWN);
|
||||
d = hidpp10_device_new(&base, i, HIDPP10_PROFILE_UNKNOWN, 1);
|
||||
if (!d)
|
||||
continue;
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ main(int argc, char **argv)
|
||||
error(1, errno, "Failed to open path %s", path);
|
||||
|
||||
hidpp_device_init(&base, fd);
|
||||
dev = hidpp10_device_new(&base, HIDPP_WIRED_DEVICE_IDX, HIDPP10_PROFILE_UNKNOWN);
|
||||
dev = hidpp10_device_new(&base, HIDPP_WIRED_DEVICE_IDX, HIDPP10_PROFILE_UNKNOWN, 5);
|
||||
|
||||
if (argc == 2)
|
||||
rc = dump_all_pages(dev);
|
||||
|
||||
Reference in New Issue
Block a user