GSeriesDev / gseries-tools

information and tools for use with the logitech gseries line of devices
17 stars 9 forks source link

Decoding G402 data dumps #3

Open dslul opened 7 years ago

dslul commented 7 years ago

I am trying to decode some information sent from the Logitech app and firmware updater, but without any luck for now...did you manage to get something for the other models? I can't figure out how the firmware updater (separate from the main app) gets the version...I am attaching a wireshark dump in plain text, maybe you can confront it with other devices (current mouse firmware version: 90.3.20). updater.txt

EDIT: I've just noticed that lsusb shows the correct firmware version (bcdDevice); however, I still cannot understand what the logitech app does. When I click on Illumination (to set the leds configuration of the mouse), it starts to send an infinite amount of packet as long as I remain in that section (even without changing a single configuration). Do you think this is an expected behaviour? It's kinda hard to reverse engineer the packets when they are covered by so much (apparently) useless information

hanetzer commented 7 years ago

@dslul honestly I don't grok wireshark dump's formatting. I've been mostly using direct usbmon dumps. If you can locate the firmware file itself inside the updater you can fairly easily grep the logs for known data.

dslul commented 7 years ago

I agree on the wireshark dumps, I ended up exporting as text file and isolating the data packets sent by the logitech application. This way I managed to find some interesting things (on the g402): when the application starts, it checks for the name of the device, the firmware version and does some sort of reset/config rewrite that is useful to fix any kind of errors that may occur during hacking; when you move to the light configuration tab, it enters some sort of "edit mode", and it continues to send packets (apparently useless) even when doing nothing. I found some quicker ways to edit these configuration on linux by sending the appropriate packets to the mouse: DPI LIGHT ON: 10 ff 05 7d 00 02 00 DPI LIGHT OFF: 10 ff 05 7d 00 04 00

These two packets work even without entering the aforementioned "edit mode".

G LOGO LED: 11ff055d01008000ff0000000000000000000000 The 9th byte represents the brightness, ff for full brightness, 00 to disable it. The 10th and 11th bytes are for blinking: leave 0000 if you don't want it to blink, otherwise put some small hex to make it blink fast (e.g. 032d) or slow (5e2f). These two instead, work only in "edit mode", using this packet: 10ff053d010000 To apply the configuration, the same packet with the 5th byte toggled is sent: 10ff053d000000

To test packets I used this https://github.com/cvuchener/g500/tree/master/src (the send-raw-request program) in conjunction with a bash script to send a batch of hex packets from a file easily:

!/bin/bash

if [ ! -f $1 ]; then echo "File not found!" exit 1 fi

while read p; do echo "Sending packet $p ...." xxd -r -p <<< "$p" | ~/Scrivania/g500/src/send-raw-request /dev/hidraw1 | xxd -g 1

sleep 1

done < $1

exit 0

opensiriusfox commented 7 years ago

I'm curious how you place meaning on this "edit mode" you describe. I'm going through a similar dig based upon the Logitech G102 and I see a number of packets that I can't place meaning on that I'd be interested to mapping to the work you're doing.

I note that the core of my dumps suggests that the G102 has a radically different configuration format than the mouse tested here. Just as a brief example, lighting information is sent twice to two different ?registers? on the mouse, with one byte setting the mode, three bytes of RGB data, with brightness information further on ranging from 0 to 0x64.

dslul commented 7 years ago

Can you upload your dumps so I can compare with mine? (One when application start and one when you enter the lightning section and modify something)

hanetzer commented 7 years ago

Another good tool is the hidapi's python binding. it offers a sort of shell you can use to interactively send and receive hid packets.

opensiriusfox commented 7 years ago

@dslul I stuck my recent dumps over here. They're currently stripped Wireshark dumps (I used tshark with a filter to remove all of the extra crap on the bus), but if there is a prefered way that you've been working with text dumps I can dump things that way.

I've personally been using the pip pcapfile library with a primitive USB layer to extract data from packets. I have some confidence as to how most of the lighting data makes it's way onto the G102, but I hadn't bothered trying to manually manipulate it. Based upon a few things in this thread I think I can start tinkering.

With regard to the version string, I think that the version is sent as a device descriptor when it's initally pluged in. In your dumps only the device name looks like it's going over the wire ("Gaming Mouse G402" Descriptor ID #2), but in my dumps I see descriptor #1 contains "Logitech", #2 "G102 Prodigy Gaming Mouse", #3 some sort of number (I think it's an encoded serial number or something), and after I start the Logitech gaming software a descriptor with index #4 containing the string "U107.01_B0013". I suspect this number corresponds to the software version.

dslul commented 7 years ago

I discovered there are some information on the protocol here https://drive.google.com/open?id=0BxbRzx7vEV7eU3VfMnRuRXktZ3M You should also take a look at hidpp: https://github.com/cvuchener/hidpp compile the project and use the tools list features, so you know better what each packet does. The so-called features of the mouse are indicated in the 3rd byte, the function in the 4th, and the rest are the parameters of the function (1st and 2nd byte are type of packet and device index respectively). Also take a look at this https://github.com/cvuchener/hidpp/issues/1 where I asked some information about the features, to see if some of your features are also present on my mouse.

cvuchener commented 7 years ago

@dsul Could you post dumps of your profile memory? I would like to see exactly how the profile structure change for different "profile format" values. libratbag treats format 1, 2, and 3 in the same way. Use hidpp20-dump-page using page parameter between 0 and 2 (since according to the description, you have 3 pages) and pipe the output with xxd -g 1 since it is binary data.

for i in {0..2}; do tools/hidpp20-dump-page /dev/hidraw1 $i | xxd -g 1; done

or if you have a doubt on the page count:

i=0; while tools/hidpp20-dump-page /dev/hidraw1 $i; do i=$((i+1)); done | xxd -g 1

For your information, the profile structure is defined in libratbag: https://github.com/libratbag/libratbag/blob/master/src/hidpp20.c#L1650

For comparison, one profile from the G502 spectrum (profile format is 2):

00000000: 01 01 00 b0 04 60 09 80 0c 00 19 00 00 ff ff ff  .....`..........
00000010: ff 00 06 00 ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000020: 80 01 00 01 80 01 00 02 80 01 00 04 80 01 00 08  ................
00000030: 80 01 00 10 90 07 ff ff 90 04 ff ff 90 03 ff ff  ................
00000040: 90 0a ff ff 90 02 ff ff 90 01 ff ff ff ff ff ff  ................
00000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000060: 80 01 00 01 80 01 00 02 80 01 00 04 80 01 00 08  ................
00000070: 80 01 00 10 90 07 ff ff 90 04 ff ff 90 03 ff ff  ................
00000080: 90 0a ff ff 90 02 ff ff 90 01 ff ff ff ff ff ff  ................
00000090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000000a0: 50 00 72 00 6f 00 66 00 69 00 6c 00 20 00 6e 00  P.r.o.f.i.l. .n.
000000b0: b0 00 20 00 31 00 00 00 00 00 00 00 00 00 00 00  .. .1...........
000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
000000d0: 03 00 00 00 00 00 1f 40 64 00 00 03 00 00 00 00  .......@d.......
000000e0: 00 1f 40 64 00 00 ff ff ff ff ff ff ff ff ff ff  ..@d............
000000f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff 14 7a  ...............z

profile_color and power_mode are not used (filled with ff), and the first two bytes of the reserved array are used for an unknown purpose.

dslul commented 7 years ago

@cvuchener here it is:

00000000: 00 01 01 00 ff ff 00 00 ff ff ff ff ff ff ff ff  ................
00000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000000a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000000b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000000c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000000d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000000e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000000f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
<repeated data because of bug>
00000000: 01 02 00 90 01 20 03 40 06 80 0c 10 0e ff ff ff  ..... .@........
00000010: ff 00 13 00 ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000020: 80 01 00 01 80 01 00 02 80 01 00 04 80 01 00 08  ................
00000030: 80 01 00 10 90 07 ff ff 90 04 ff ff 90 03 ff ff  ................
00000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000060: 80 01 00 01 80 01 00 02 80 01 00 04 80 01 00 08  ................
00000070: 80 01 00 10 90 07 ff ff 90 04 ff ff 90 03 ff ff  ................
00000080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
000000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
000000d0: 00 02 00 00 00 00 28 df 00 08 51 d3 00 08 59 d3  ......(...Q...Y.
000000e0: 00 08 05 00 00 03 00 00 00 00 3c df 00 08 67 d3  ..........<...g.
000000f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
<repeated data because of bug>
00000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
00000090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000000a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000000b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000000c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000000d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000000e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
000000f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
<repeated data because of bug>

I also tried to dump using libratbrag, but I don't understand why there is a distinction between ROM and FLASH:

FLASH: page 0x00 off 0x00:  00 01 01 00 ff ff 00 00 ff ff ff ff ff ff ff ff
FLASH: page 0x00 off 0x10:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x00 off 0x20:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x00 off 0x30:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x00 off 0x40:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x00 off 0x50:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x00 off 0x60:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x00 off 0x70:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x00 off 0x80:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x00 off 0x90:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x00 off 0xa0:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x00 off 0xb0:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x00 off 0xc0:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x00 off 0xd0:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x00 off 0xe0:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x00 off 0xf0:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x01 off 0x00:  01 02 00 90 01 20 03 40 06 80 0c 10 0e ff ff ff
FLASH: page 0x01 off 0x10:  ff 00 13 00 ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x01 off 0x20:  80 01 00 01 80 01 00 02 80 01 00 04 80 01 00 08
FLASH: page 0x01 off 0x30:  80 01 00 10 90 07 ff ff 90 04 ff ff 90 03 ff ff
FLASH: page 0x01 off 0x40:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x01 off 0x50:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x01 off 0x60:  80 01 00 01 80 01 00 02 80 01 00 04 80 01 00 08
FLASH: page 0x01 off 0x70:  80 01 00 10 90 07 ff ff 90 04 ff ff 90 03 ff ff
FLASH: page 0x01 off 0x80:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x01 off 0x90:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x01 off 0xa0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
FLASH: page 0x01 off 0xb0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
FLASH: page 0x01 off 0xc0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
FLASH: page 0x01 off 0xd0:  00 02 00 00 00 00 28 df 00 08 51 d3 00 08 59 d3
FLASH: page 0x01 off 0xe0:  00 08 05 00 00 03 00 00 00 00 3c df 00 08 67 d3
FLASH: page 0x01 off 0xf0:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x02 off 0x00:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x02 off 0x10:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x02 off 0x20:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x02 off 0x30:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x02 off 0x40:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x02 off 0x50:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x02 off 0x60:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x02 off 0x70:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x02 off 0x80:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x02 off 0x90:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x02 off 0xa0:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x02 off 0xb0:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x02 off 0xc0:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x02 off 0xd0:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x02 off 0xe0:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
FLASH: page 0x02 off 0xf0:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff

ROM  : page 0x00 off 0x00:  01 01 01 ff ff ff 00 00 00 02 00 00 00 00 00 df
ROM  : page 0x00 off 0x10:  00 08 e1 d2 00 08 15 d3 00 08 01 00 00 02 00 00
ROM  : page 0x00 off 0x20:  00 00 14 df 00 08 25 d3 00 08 2d d3 00 08 03 00
ROM  : page 0x00 off 0x30:  00 02 00 00 00 00 28 df 00 08 51 d3 00 08 59 d3
ROM  : page 0x00 off 0x40:  00 08 05 00 00 03 00 00 00 00 3c df 00 08 67 d3
ROM  : page 0x00 off 0x50:  00 08 93 d3 00 08 7d d3 00 08 c1 00 00 02 00 00
ROM  : page 0x00 off 0x60:  00 00 54 df 00 08 e5 d3 00 08 1d d4 00 08 00 13
ROM  : page 0x00 off 0x70:  00 08 00 00 00 00 68 df 00 08 e5 b3 00 08 ed b3
ROM  : page 0x00 off 0x80:  00 08 25 b4 00 08 f1 b9 00 08 35 b4 00 08 d5 bb
ROM  : page 0x00 off 0x90:  00 08 b9 b4 00 08 4d ba 00 08 01 18 60 02 00 00
ROM  : page 0x00 off 0xa0:  00 00 94 df 00 08 51 56 00 08 ad 56 00 08 02 18
ROM  : page 0x00 off 0xb0:  60 01 00 00 00 00 a8 df 00 08 63 d4 00 08 6d d4
ROM  : page 0x00 off 0xc0:  00 08 71 d4 00 08 a1 18 60 03 00 00 00 00 c0 df
ROM  : page 0x00 off 0xd0:  00 08 c1 57 00 08 cd 57 00 08 1d 58 00 08 00 1e
ROM  : page 0x00 off 0xe0:  40 02 00 00 00 00 d8 df 00 08 75 d4 00 08 83 d4
ROM  : page 0x00 off 0xf0:  00 08 b0 1e 60 03 00 00 00 00 ec df 00 08 99 d4
ROM  : page 0x01 off 0x00:  01 02 00 a4 01 48 03 3c 06 78 0c 00 00 ff ff ff
ROM  : page 0x01 off 0x10:  ff 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ROM  : page 0x01 off 0x20:  80 01 00 01 80 01 00 02 80 01 00 04 80 01 00 08
ROM  : page 0x01 off 0x30:  80 01 00 10 90 07 ff ff 90 04 ff ff 90 03 ff ff
ROM  : page 0x01 off 0x40:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ROM  : page 0x01 off 0x50:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ROM  : page 0x01 off 0x60:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ROM  : page 0x01 off 0x70:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ROM  : page 0x01 off 0x80:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ROM  : page 0x01 off 0x90:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ROM  : page 0x01 off 0xa0:  01 01 01 ff ff ff 00 00 00 02 00 00 00 00 00 df
ROM  : page 0x01 off 0xb0:  00 08 e1 d2 00 08 15 d3 00 08 01 00 00 02 00 00
ROM  : page 0x01 off 0xc0:  00 00 14 df 00 08 25 d3 00 08 2d d3 00 08 03 00
ROM  : page 0x01 off 0xd0:  00 02 00 00 00 00 28 df 00 08 51 d3 00 08 59 d3
ROM  : page 0x01 off 0xe0:  00 08 05 00 00 03 00 00 00 00 3c df 00 08 67 d3
ROM  : page 0x01 off 0xf0:  00 08 93 d3 00 08 7d d3 00 08 c1 00 00 02 00 00
cvuchener commented 7 years ago

I see I have a bug when reading data after offset 256 (0x100). I will fix that but it is okay: the profile fits in the first 256 bytes, I have the data I wanted.

Yes there is a ROM, you can use the -r option with hidpp20-dump-page to read it. It also contains profiles but I am not sure when they are used (maybe when there are errors in the flash).

PS: I edited your message to hide the useless repeated data. PS2: The bug should be fixed with this commit. There is not need to post the data again, if there is nothing interesting in the end of pages.

cvuchener commented 7 years ago

So your profile is very similar to the G502: profile_color and power_mode are not used, the first two reserved bytes (13 00) are used in flash but not in ROM. But the profile changes from 0xd0 (leds in libratbag's structure).

About the first two reserved bytes, on the G502 the three default flash profiles have 06 00, 3e 00 and 04 00, ROM profiles do not use them (ff ff).

The data from 0xd0 may be related to leds, but the format is different. Maybe you can see some similarities with the format used for effects in feature 0x1300 "LED Control".

000000d0: 00 02 00 00 00 00 28 df 00 08 51 d3 00 08 59 d3  ......(...Q...Y.
000000e0: 00 08 05 00 00 03 00 00 00 00 3c df 00 08 67 d3  ..........<...g.
dslul commented 7 years ago

The data from 0xd0 doesn't change when I make modifications to led settings, so it should not be related to them. I dumped the data sent when one resets the profile settings, it seems to rewrite completely the memory with all settings as stock and I got this (1024 bytes total with a crc checksum in the last 2 bytes calculated on 1022 bytes by using this algorithm https://github.com/libratbag/libratbag/blob/821e2798b9af80f932f18c0e2cbdad5c905d7f94/src/hidpp-generic.c#L327), instead of the 768 bytes retrieved from libratbag or your tool:

10ff0fbc000000
10ff0fcc010000
11ff0f6c00010000040000000000000000000000
11ff0f7c010200900120034006800c0000ffffff
11ff0f7cff001e00ffffffffffffffffffffffff
11ff0f7c80010001800100028001000480010008
11ff0f7c800100109007ffff9004ffff9003ffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7c80010001800100028001000480010008
11ff0f7c800100109007ffff9004ffff9003ffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7c00000000000000000000000000000000
11ff0f7c00000000000000000000000000000000
11ff0f7c00000000000000000000000000000000
11ff0f7c00020000000028df000851d3000859d3
11ff0f7c000805000003000000003cdf000867d3
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffffff
11ff0f7cffffffffffffffffffffffffffffeada
10ff0f8c000000
10ff0f4c000000

I also can't find the checksum on the dumps, but it is clearly sent by LGS.

cvuchener commented 7 years ago

instead of the 768 bytes retrieved from libratbag or your tool:

From your previous post, my tool was retrieving 1024 bytes of data, but 4 times the same first 256 bytes (because of a overflowing 8 bit offset). It should be fixed now. Please, write a bug report if it still doesn't work as expected.

libratbag should have the same problem since it uses 8 bit offsets and hard-coded page size of 256 bytes. Because the profile fits in the first 256 bytes, it works for reading the profile. But the CRC is written at the end of the first 256 bytes instead of the end of the page. That means the profiles written by libratbag on the G402 would not work. Is it the case?

cvuchener commented 7 years ago

11 ff 0f 6c 00 01 00 00 04 00 00 00 00 00 00 00 00 00 00 00

libratbag hard-code parameter byte 4 to 0x01, but your case it is 0x04. Byte 4 and 5 could be data length in big endian (0x100 = 256 bytes, 0x400 = 1024 bytes). I'll test that and fix my code.

cvuchener commented 7 years ago

I confirm that byte 4 and 5 are actually the length of the data to write. Fixed in https://github.com/cvuchener/hidpp/commit/ad5c91803c1832732725426a9b35fa9e145dd5f8

dslul commented 7 years ago

Great, now it reads 1kiB per page! Do you know why there are two pages just filled with ff (except the first 8 bytes of page 0 that are 00 01 01 00 ff ff 00 00) and also the majority of page 1, where the profile is stored? Does your g502 also have so much empty space?

I think I discovered what the first two "reserved" bytes of the profile are for: it is a number in big little endian that increases by one every time a write operation is performed.

cvuchener commented 7 years ago

Do you know why there are two pages just filled with ff (except the first 8 bytes of page 0 that are 00 01 01 00 ff ff 00 00) and also the majority of page 1, where the profile is stored? Does your g502 also have so much empty space?

The data at the start of page 0 is the profile list. It is a array with 4 bytes per profile : memory type (00: flash, 01 would be ROM), page index (01), enabled (01), the fourth byte (00) is unknown. ff ff 00 00 marks the end of the list, although I am not sure that your mouse would support a second profile.

The remaining space can be used to store macros or whatever you want. LGS usually writes macros in the first page after the profiles (page 2 for you), but they can be anywhere. On older HID++1.0 devices like the G500 or G9x, LGS used to store metadata after the profile or profile list (macro/profile names).

I think I discovered what the first two "reserved" bytes of the profile are for: it is a number in big endian that increases by one every time a write operation is performed.

You meant little endian? That would make sense: the highest number is the profile I tweaked the most.

dslul commented 7 years ago

I assume the g502 has a separate page for each profile, doesn't it? Maybe the fourth byte in the profile list is there to indicate an offset, for example in a page where one can fit four profiles (like in my case); however, lgs does not allow me to create more than one profile, but also doesn't seem to use all that space except the first 256 bytes. I will try to do this, I hope it works.

cvuchener commented 7 years ago

I had a closer look at your profile data and I have doubts that the data from 0xd0 is related to the profile. On page 1 of the ROM, the data from 0xa0 is a copy of page 0 (from the beginning), including the profile list. The data from 0xd0 to 0xef from page 1 in the flash memory is an exact copy of the ROM (so the same data as page 0 with the first 48 bytes overwritten by the name). I think the data was copied accidentally and is not actually part of the profile structure. I cannot say if page 0 of ROM is its proper place or not. I does not look like the macro format I know.

I missed some of your questions.

I assume the g502 has a separate page for each profile, doesn't it?

Yes: one profile at the beginning of each page 1, 2 and 3. Macro data begins at page 4.

Maybe the fourth byte in the profile list is there to indicate an offset

HID++1.0 devices have an offset in the profile list. But HID++2.0 (and later) uses 16 bit offset, it would not fit, except if only the most significant byte is stored. In ROM on the G502, the fourth byte is 0xff instead of 0, it does not look like an offset.