From 8f18357e4797092ecefe2786f3f2faa19bc2c28b Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Mon, 14 Dec 2015 17:26:07 +0100 Subject: [PATCH] hidpp10: properly parse metadata in profiles unknown3 in G700 is the constant string "LGS02". This string is a marker for LGS to specify that the rest of the data is the names of the profiles and macros. SetPoint doesn't set those, so they are considered as metadata. In libratbag, we will parse those properly and always set them, no matter if the user used SetPoint or not. Signed-off-by: Benjamin Tissoires --- src/hidpp10.c | 78 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 17 deletions(-) diff --git a/src/hidpp10.c b/src/hidpp10.c index 7086aabb..4b572585 100644 --- a/src/hidpp10.c +++ b/src/hidpp10.c @@ -571,6 +571,18 @@ union _hidpp10_button_binding { } __attribute__((packed)); _Static_assert(sizeof(union _hidpp10_button_binding) == 3, "Invalid size"); +union _hidpp10_profile_metadata { + struct { + uint8_t marker[5]; + uint8_t padding[420]; + } __attribute__((packed)) any; + struct { + uint8_t marker[5]; /* { 'L', 'G', 'S', '0', '2' } */ + uint16_t name[23]; + uint16_t macro_names[11][17]; + } __attribute__((packed)) lgs02; +} __attribute__((packed)); + struct _hidpp10_profile_500 { uint8_t red; uint8_t green; @@ -587,7 +599,6 @@ _Static_assert(sizeof(struct _hidpp10_profile_500) == 78, "Invalid size"); static const uint8_t _hidpp10_profile_700_unknown1[3] = { 0x80, 0x01, 0x10 }; static const uint8_t _hidpp10_profile_700_unknown2[10] = { 0x01, 0x2c, 0x02, 0x58, 0x64, 0xff, 0xbc, 0x00, 0x09, 0x31 }; -static const uint8_t _hidpp10_profile_700_unknown3[5] = { 0x4c, 0x47, 0x53, 0x30, 0x32 }; struct _hidpp10_profile_700 { struct _hidpp10_dpi_mode_8 dpi_modes[PROFILE_NUM_DPI_MODES]; @@ -596,9 +607,7 @@ struct _hidpp10_profile_700 { uint8_t usb_refresh_rate; uint8_t unknown2[10]; union _hidpp10_button_binding buttons[PROFILE_NUM_BUTTONS]; - uint8_t unknown3[5]; - uint16_t name[23]; - uint16_t macro_names[11][17]; + union _hidpp10_profile_metadata metadata; } __attribute__((packed)); _Static_assert(sizeof(struct _hidpp10_profile_700) == 499, "Invalid size"); @@ -999,6 +1008,52 @@ hidpp10_uchar8_to_uchar16(uint16_t *dst, uint8_t *src, size_t len) dst[i] = hidpp_cpu_to_le_u16(src[i]); } +static void +hidpp10_profile_parse_names(struct hidpp10_device *dev, struct hidpp10_profile *profile, + uint8_t number, + union _hidpp10_profile_metadata *metadata) +{ + unsigned i; + + if (strneq((char *)metadata->any.marker, "LGS02", 5)) { + hidpp10_uchar16_to_uchar8(profile->name, + metadata->lgs02.name, + ARRAY_LENGTH(metadata->lgs02.name)); + hidpp_log_raw(&dev->base, "profile %d is named '%s'\n", number, profile->name); + for (i = 0; i < ARRAY_LENGTH(metadata->lgs02.macro_names); i++) { + hidpp10_uchar16_to_uchar8(profile->macro_names[i], + metadata->lgs02.macro_names[i], + ARRAY_LENGTH(metadata->lgs02.macro_names[i])); + if (profile->macro_names[i][0]) + hidpp_log_raw(&dev->base, + "macro %d of profile %d is named: '%s'\n", + (unsigned)i, + number, + profile->macro_names[i]); + } + } else { + snprintf((char *)profile->name, sizeof(profile->name) - 1, "Profile %d", number + 1); + } +} + +static void +hidpp10_profile_set_names(struct hidpp10_device *dev, struct hidpp10_profile *profile, + uint8_t number, + union _hidpp10_profile_metadata *metadata) +{ + unsigned i; + + memcpy(metadata->lgs02.marker, "LGS02", sizeof(metadata->lgs02.marker)); + hidpp10_uchar8_to_uchar16(metadata->lgs02.name, + profile->name, + sizeof(metadata->lgs02.name)); + for (i = 0; i < ARRAY_LENGTH(metadata->lgs02.macro_names); i++) { + hidpp10_uchar8_to_uchar16(metadata->lgs02.macro_names[i], + profile->macro_names[i], + ARRAY_LENGTH(metadata->lgs02.macro_names[i])); + } +} + int hidpp10_get_profile(struct hidpp10_device *dev, int8_t number, struct hidpp10_profile *profile_return) { @@ -1085,13 +1140,7 @@ hidpp10_get_profile(struct hidpp10_device *dev, int8_t number, struct hidpp10_pr hidpp10_fill_dpi_modes_8(dev, profile, p700->dpi_modes, PROFILE_NUM_DPI_MODES); hidpp10_fill_buttons(dev, profile, buttons, PROFILE_NUM_BUTTONS); - hidpp10_uchar16_to_uchar8(profile->name, p700->name, ARRAY_LENGTH(p700->name)); - hidpp_log_raw(&dev->base, "profile %d is named '%s'\n", number, profile->name); - for (i = 0; i < ARRAY_LENGTH(p700->macro_names); i++) { - hidpp10_uchar16_to_uchar8(profile->macro_names[i], p700->macro_names[i], ARRAY_LENGTH(p700->macro_names[i])); - if (profile->macro_names[i][0]) - hidpp_log_raw(&dev->base, "macro %d of profile %d is named: '%s'\n", (unsigned)i, number, profile->macro_names[i]); - } + hidpp10_profile_parse_names(dev, profile, number, &p700->metadata); break; default: hidpp_log_error(&dev->base, "This should never happen, complain to your maintainer.\n"); @@ -1216,7 +1265,6 @@ hidpp10_set_profile(struct hidpp10_device *dev, int8_t number, struct hidpp10_pr struct hidpp10_directory directory[16]; /* completely random profile count */ union _hidpp10_button_binding *buttons; int count = 0; - unsigned i; uint16_t crc; uint8_t page; @@ -1262,7 +1310,6 @@ hidpp10_set_profile(struct hidpp10_device *dev, int8_t number, struct hidpp10_pr case HIDPP10_PROFILE_G700: memcpy(p700->unknown1, _hidpp10_profile_700_unknown1, sizeof(p700->unknown1)); memcpy(p700->unknown2, _hidpp10_profile_700_unknown2, sizeof(p700->unknown2)); - memcpy(p700->unknown3, _hidpp10_profile_700_unknown3, sizeof(p700->unknown3)); break; default: hidpp_log_error(&dev->base, "This should never happen, complain to your maintainer.\n"); @@ -1286,10 +1333,7 @@ hidpp10_set_profile(struct hidpp10_device *dev, int8_t number, struct hidpp10_pr hidpp10_write_dpi_modes_8(dev, profile, p700->dpi_modes, PROFILE_NUM_DPI_MODES); hidpp10_write_buttons(dev, profile, buttons, PROFILE_NUM_BUTTONS); - hidpp10_uchar8_to_uchar16(p700->name, profile->name, sizeof(p700->name)); - for (i = 0; i < ARRAY_LENGTH(p700->macro_names); i++) { - hidpp10_uchar8_to_uchar16(p700->macro_names[i], profile->macro_names[i], ARRAY_LENGTH(p700->macro_names[i])); - } + hidpp10_profile_set_names(dev, profile, number, &p700->metadata); break; default: hidpp_log_error(&dev->base, "This should never happen, complain to your maintainer.\n");