1
0
forked from drath/libratbag

hidpp10: Parse G9 profile

This allows to read but not write profiles from the G9.

The dpi mode sturct is a little different as the mouse only supports
symetrical dpi for x/y. Given the current naming a suffix of _sym
was the best I could come up with.

The G9 profile has some additional unknown bytes compared to the
others. Unfortunately the content of them varies for the 4 first
profiles and the last. So adding a default value for the like with
the G700 is not possible. For this reason I dropped implementing
the write part for now.

Something else to address is that this mouse only has 10 buttons
compared to the usual 13 that we have in PROFILE_NUM_BUTTONS. For
now I just hardcoded it in the profile and hidpp10_get_profile.
This commit is contained in:
Thomas Hindoe Paaboel Andersen
2016-01-07 22:18:11 +01:00
parent 8ed646fd7f
commit 14ca639270
4 changed files with 63 additions and 0 deletions

View File

@@ -81,6 +81,7 @@ mouse:usb:v046dpc51a:name:*:
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
# G9x [Original]
mouse:usb:v046dpc066:name:*:

View File

@@ -520,6 +520,8 @@ hidpp10drv_probe(struct ratbag_device *device)
type = HIDPP10_PROFILE_G500;
else if (strcasecmp("G700", prop) == 0)
type = HIDPP10_PROFILE_G700;
else if (strcasecmp("G9", prop) == 0)
type = HIDPP10_PROFILE_G9;
}
prop = ratbag_device_get_udev_property(device, "RATBAG_HIDPP10_INDEX");

View File

@@ -520,6 +520,15 @@ hidpp10_get_battery_mileage(struct hidpp10_device *dev,
} \
}
struct _hidpp10_dpi_mode_8_sym {
uint8_t res;
uint8_t led1:4;
uint8_t led2:4;
uint8_t led3:4;
uint8_t led4:4;
} __attribute__((packed));
_Static_assert(sizeof(struct _hidpp10_dpi_mode_8_sym) == 3, "Invalid size");
struct _hidpp10_dpi_mode_8 {
uint8_t xres;
uint8_t yres;
@@ -617,9 +626,25 @@ struct _hidpp10_profile_700 {
} __attribute__((packed));
_Static_assert(sizeof(struct _hidpp10_profile_700) == 499, "Invalid size");
struct _hidpp10_profile_9 {
uint8_t red;
uint8_t green;
uint8_t blue;
uint8_t unknown1;
struct _hidpp10_dpi_mode_8_sym dpi_modes[PROFILE_NUM_DPI_MODES];
uint8_t default_dpi_mode;
uint8_t unknown2[2];
uint8_t usb_refresh_rate;
union _hidpp10_button_binding buttons[10];
uint8_t unknown3[3];
union _hidpp10_profile_metadata metadata;
} __attribute__((packed));
_Static_assert(sizeof(struct _hidpp10_profile_500) == 503, "Invalid size");
union _hidpp10_profile_data {
struct _hidpp10_profile_500 profile_500;
struct _hidpp10_profile_700 profile_700;
struct _hidpp10_profile_9 profile_9;
uint8_t data[HIDPP10_PAGE_SIZE];
};
_Static_assert((sizeof(union _hidpp10_profile_data) % 16) == 0, "Invalid size");
@@ -833,6 +858,28 @@ hidpp10_set_current_profile(struct hidpp10_device *dev, int16_t current_profile)
PROFILE_TYPE_INDEX);
}
static void
hidpp10_fill_dpi_modes_8_sym(struct hidpp10_device *dev,
struct hidpp10_profile *profile,
struct _hidpp10_dpi_mode_8_sym *dpi_list,
unsigned int count)
{
unsigned int i;
profile->num_dpi_modes = count;
for (i = 0; i < count; i++) {
struct _hidpp10_dpi_mode_8_sym *dpi = &dpi_list[i];
profile->dpi_modes[i].xres = hidpp10_get_dpi_value(dev, dpi->res);
profile->dpi_modes[i].yres = hidpp10_get_dpi_value(dev, dpi->res);
profile->dpi_modes[i].led[0] = dpi->led1 == 0x2;
profile->dpi_modes[i].led[1] = dpi->led2 == 0x2;
profile->dpi_modes[i].led[2] = dpi->led3 == 0x2;
profile->dpi_modes[i].led[3] = dpi->led4 == 0x2;
}
}
static void
hidpp10_fill_dpi_modes_8(struct hidpp10_device *dev,
struct hidpp10_profile *profile,
@@ -1345,6 +1392,7 @@ hidpp10_get_profile(struct hidpp10_device *dev, int8_t number, struct hidpp10_pr
union _hidpp10_profile_data *data = (union _hidpp10_profile_data *)page_data;
struct _hidpp10_profile_500 *p500 = &data->profile_500;
struct _hidpp10_profile_700 *p700 = &data->profile_700;
struct _hidpp10_profile_9 *p9 = &data->profile_9;
size_t i;
int res;
struct hidpp10_profile *profile;
@@ -1384,6 +1432,9 @@ hidpp10_get_profile(struct hidpp10_device *dev, int8_t number, struct hidpp10_pr
case HIDPP10_PROFILE_G700:
buttons = p700->buttons;
break;
case HIDPP10_PROFILE_G9:
buttons = p9->buttons;
break;
default:
hidpp_log_error(&dev->base, "This should never happen, complain to your maintainer.\n");
}
@@ -1427,6 +1478,14 @@ hidpp10_get_profile(struct hidpp10_device *dev, int8_t number, struct hidpp10_pr
hidpp10_profile_parse_names(dev, profile, number, &p700->metadata);
hidpp10_fill_buttons(dev, profile, buttons, PROFILE_NUM_BUTTONS);
break;
case HIDPP10_PROFILE_G9:
profile->default_dpi_mode = p9->default_dpi_mode;
profile->refresh_rate = p9->usb_refresh_rate ? 1000/p9->usb_refresh_rate : 0;
hidpp10_fill_dpi_modes_8_sym(dev, profile, p9->dpi_modes, PROFILE_NUM_DPI_MODES);
hidpp10_profile_parse_names(dev, profile, number, &p9->metadata);
hidpp10_fill_buttons(dev, profile, buttons, 10);
break;
default:
hidpp_log_error(&dev->base, "This should never happen, complain to your maintainer.\n");
}

View File

@@ -44,6 +44,7 @@ enum hidpp10_profile_type {
HIDPP10_PROFILE_UNKNOWN = -1,
HIDPP10_PROFILE_G500,
HIDPP10_PROFILE_G700,
HIDPP10_PROFILE_G9,
};
struct hidpp10_directory;