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:
@@ -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:*:
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ enum hidpp10_profile_type {
|
||||
HIDPP10_PROFILE_UNKNOWN = -1,
|
||||
HIDPP10_PROFILE_G500,
|
||||
HIDPP10_PROFILE_G700,
|
||||
HIDPP10_PROFILE_G9,
|
||||
};
|
||||
|
||||
struct hidpp10_directory;
|
||||
|
||||
Reference in New Issue
Block a user