Repository: pwr-Solaar/Solaar

Issue:
Can't disable onboard profiles anymore on G502 lightspeed wireless
**Information**

- Solaar version: `1.1.11-182-g1eb1d4b1`
- Distribution: ArchLinux
- Kernel version (ex. `uname -srmo`): `Linux 6.8.1-zen1-1-zen x86_64 GNU/Linux`
- Output of `solaar show`:

<details>

```
solaar version 1.1.11-182-g1eb1d4b1

Lightspeed Receiver
  Device path  : /dev/hidraw4
  USB id       : 046d:C539
  Serial       : 7D7E9CF7
  C Pending    : ff
    Firmware   : 39.06.B0040
    Bootloader : 02.09
    Other      : AA.BE
  Has 1 paired device(s) out of a maximum of 1.
  Notifications: wireless, software present (0x000900)
  Device activity counters: (empty)
```
</details>

- Contents of `~/.config/solaar/config.yaml` (or `~/.config/solaar/config.json` if `~/.config/solaar/config.yaml` not present):

<details>

```yaml
- 1.1.11-182-g1eb1d4b1
- _NAME: G502 Gaming Mouse
  _absent: [hi-res-scroll, lowres-scroll-mode, scroll-ratchet, smart-shift, thumb-scroll-invert, thumb-scroll-mode, report_rate_extended, pointer_speed,
    dpi_extended, speed-change, backlight, backlight_level, backlight_duration_hands_out, backlight_duration_hands_in, backlight_duration_powered, backlight-timed,
    rgb_control, rgb_zone_, brightness_control, per-key-lighting, fn-swap, reprogrammable-keys, persistent-remappable-keys, divert-keys, disable-keyboard-keys,
    crown-smooth, divert-crown, divert-gkeys, m-key-leds, mr-key-led, multiplatform, change-host, gesture2-gestures, gesture2-divert, gesture2-params, sidetone,
    equalizer, adc_power_management]
  _battery: 4097
  _modelId: 407FC08D0000
  _sensitive: {onboard_profiles: true}
  _serial: CAFEFCF4
  _unitId: CAFEFCF4
  _wpid: 407F
  dpi: 1200
  hires-scroll-mode: false
  hires-smooth-invert: false
  hires-smooth-resolution: true
  led_control: 0
  onboard_profiles: 2
  report_rate: 1
```
</details>


- Errors or warrnings from Solaar:
<!-- Under normal operation Solaar keeps a log of warning and error messages in ~/.tmp
while it is running as a file starting with 'Solaar'.
If this file is not available or does not have useful information you can
run Solaar as `solaar -dd`, after killing any running Solaar processes to
have Solaar log informational, warning, and error messages to stdout. -->

```
2024-04-14 21:20:40,065,065    ERROR [ReceiverListener:hidraw4] logitech_receiver.base: (21) device 1 error on feature request {0B29}: 2 = invalid argument
2024-04-14 21:20:40,066,066  WARNING [ReceiverListener:hidraw4] logitech_receiver.settings: report_rate: error applying 1 so ignore it (<Device(1,407F,G502 Gaming Mouse,CAFEFCF4)>): FeatureCallError({'number': 1, 'request': 2857, 'error': 2, 'params': b'\x01'})
```

**Describe the bug**

After upgrading to Solaar 1.1.11 from 1.1.10, I no longer see the "Onboard Profiles" setting and I can't disable onboard profiles anymore.

I did a bit of digging in the code to figure out why the option wasn't shown at all
It seems that the first `chunk = device.feature_request(FEATURE.ONBOARD_PROFILES, 0x50, 0, 0, 0, i)` call (i = 0) returns `b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'`

<details><summary>solaar -ddd profiles 502</summary>

```
2024-04-14 21:31:13,908,908    DEBUG [MainThread] hidapi.udev: Starting dbus enumeration
2024-04-14 21:31:13,914,914    DEBUG [MainThread] hidapi.udev: Dbus event add Device('/sys/devices/pci0000:00/0000:00:14.0/usb1/1-11/1-11:1.0/0003:046D:C539.0003/hidraw/hidraw2')
2024-04-14 21:31:14,025,025    DEBUG [MainThread] hidapi.udev: Dbus event add Device('/sys/devices/pci0000:00/0000:00:14.0/usb1/1-11/1-11:1.1/0003:046D:C539.0004/hidraw/hidraw3')
2024-04-14 21:31:14,032,032    DEBUG [MainThread] hidapi.udev: Dbus event add Device('/sys/devices/pci0000:00/0000:00:14.0/usb1/1-11/1-11:1.2/0003:046D:C539.0005/0003:046D:407F.0009/hidraw/hidraw8')
2024-04-14 21:31:14,032,032    DEBUG [MainThread] hidapi.udev: Dbus event add Device('/sys/devices/pci0000:00/0000:00:14.0/usb1/1-11/1-11:1.2/0003:046D:C539.0005/hidraw/hidraw4')
2024-04-14 21:31:14,033,033     INFO [MainThread] hidapi.udev: Found device /dev/hidraw4 BID 0003 VID 0000046D PID 0000C539 HID++ True True USB 2 2
2024-04-14 21:31:14,034,034     INFO [MainThread] hidapi.udev: OPEN PATH /dev/hidraw4
2024-04-14 21:31:14,034,034     INFO [MainThread] logitech_receiver.base: New lock 13
2024-04-14 21:31:14,034,034    DEBUG [MainThread] logitech_receiver.base: (13) <= w[10 FF 83B5 030000]
2024-04-14 21:31:14,035,035    DEBUG [MainThread] logitech_receiver.base: (13) => r[11 FF 83B5 037D7E9CF70101070000000000000000]
2024-04-14 21:31:14,036,036    DEBUG [MainThread] logitech_receiver.base: (13) <= w[10 FF 8003 FF0000]
2024-04-14 21:31:14,037,037    DEBUG [MainThread] logitech_receiver.base: (13) => r[10 01 410C 327F40]
2024-04-14 21:31:14,037,037    DEBUG [MainThread] logitech_receiver.base: (13) => r[10 FF 8002 000000]
2024-04-14 21:31:14,038,038    DEBUG [MainThread] logitech_receiver.base: (13) => r[10 FF 8003 000000]
2024-04-14 21:31:14,038,038    DEBUG [MainThread] solaar.cli: [/dev/hidraw4] => <LightspeedReceiver(/dev/hidraw4,13)>
2024-04-14 21:31:14,039,039    DEBUG [MainThread] hidapi.udev: Dbus event add Device('/sys/devices/pci0000:00/0000:00:14.0/usb1/1-12/1-12.1/1-12.1:1.0/0003:1050:0407.0010/hidraw/hidraw5')
2024-04-14 21:31:14,041,041     INFO [MainThread] hidapi.udev: Report Descriptor not processed for DEVICE /dev/hidraw5 BID 0003 VID 00001050 PID 00000407: Expecting 8 usages but got 1
2024-04-14 21:31:14,041,041    DEBUG [MainThread] hidapi.udev: Dbus event add Device('/sys/devices/pci0000:00/0000:00:14.0/usb1/1-12/1-12.1/1-12.1:1.1/0003:1050:0407.0011/hidraw/hidraw6')
2024-04-14 21:31:14,042,042     INFO [MainThread] hidapi.udev: Report Descriptor not processed for DEVICE /dev/hidraw6 BID 0003 VID 00001050 PID 00000407: Expecting 64 usages but got 1
2024-04-14 21:31:14,042,042    DEBUG [MainThread] hidapi.udev: Dbus event add Device('/sys/devices/pci0000:00/0000:00:14.0/usb1/1-12/1-12.3/1-12.3:1.3/0003:03F0:018B.0008/hidraw/hidraw7')
2024-04-14 21:31:14,043,043     INFO [MainThread] hidapi.udev: Report Descriptor not processed for DEVICE /dev/hidraw7 BID 0003 VID 000003F0 PID 0000018B: unpack requires a buffer of 2 bytes
2024-04-14 21:31:14,044,044    DEBUG [MainThread] hidapi.udev: Dbus event add Device('/sys/devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.0/0003:046D:C31C.0001/hidraw/hidraw0')
2024-04-14 21:31:14,049,049    DEBUG [MainThread] hidapi.udev: Dbus event add Device('/sys/devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.1/0003:046D:C31C.0002/hidraw/hidraw1')
2024-04-14 21:31:14,050,050    DEBUG [MainThread] logitech_receiver.base: (13) <= w[10 FF 8102 000000]
2024-04-14 21:31:14,051,051    DEBUG [MainThread] logitech_receiver.base: (13) => r[10 FF 8102 000100]
2024-04-14 21:31:14,052,052    DEBUG [MainThread] logitech_receiver.base: (13) <= w[10 FF 8102 000000]
2024-04-14 21:31:14,052,052    DEBUG [MainThread] logitech_receiver.base: (13) => r[10 FF 8102 000100]
2024-04-14 21:31:14,053,053    DEBUG [MainThread] logitech_receiver.base: (13) <= w[10 FF 83B5 200000]
2024-04-14 21:31:14,054,054    DEBUG [MainThread] logitech_receiver.base: (13) => r[11 FF 83B5 200708407F0C0102B300000000000000]
2024-04-14 21:31:14,055,055    DEBUG [MainThread] logitech_receiver.base: (13) <= w[10 FF 83B5 300000]
2024-04-14 21:31:14,056,056    DEBUG [MainThread] logitech_receiver.base: (13) => r[11 FF 83B5 30CAFEFCF40E00200001000000000000]
2024-04-14 21:31:14,066,066     INFO [MainThread] hidapi.udev: OPEN PATH /dev/hidraw8
2024-04-14 21:31:14,066,066    DEBUG [MainThread] logitech_receiver.base: (13) <= w[10 FF 83B5 400000]
2024-04-14 21:31:14,067,067    DEBUG [MainThread] logitech_receiver.base: (13) => r[11 FF 83B5 40044735303200000000000000000000]
2024-04-14 21:31:14,068,068     INFO [MainThread] logitech_receiver.receiver: <LightspeedReceiver(/dev/hidraw4,13)>: found new device 1 (407F)
2024-04-14 21:31:14,068,068    DEBUG [MainThread] logitech_receiver.base: (14) pinging device 1
2024-04-14 21:31:14,068,068     INFO [MainThread] logitech_receiver.base: New lock 14
2024-04-14 21:31:14,068,068    DEBUG [MainThread] logitech_receiver.base: (14) <= w[10 01 001E 000087]
2024-04-14 21:31:14,074,074    DEBUG [MainThread] logitech_receiver.base: (14) => r[11 01 0001 04000000000000000000000000000000]
2024-04-14 21:31:14,077,077    DEBUG [MainThread] logitech_receiver.base: (14) => r[11 01 001E 04028700000000000000000000000000]
2024-04-14 21:31:14,078,078    DEBUG [MainThread] logitech_receiver.base: (14) <= w[11 01 000E 00010000000000000000000000000000]
2024-04-14 21:31:14,086,086    DEBUG [MainThread] logitech_receiver.base: (14) => r[11 01 0001 1D000000000000000000000000000000]
2024-04-14 21:31:14,089,089    DEBUG [MainThread] logitech_receiver.base: (14) => r[11 01 000E 01000100000000000000000000000000]
2024-04-14 21:31:14,090,090    DEBUG [MainThread] logitech_receiver.base: (14) <= w[11 01 010F 00000000000000000000000000000000]
2024-04-14 21:31:14,099,099    DEBUG [MainThread] logitech_receiver.base: (14) => r[11 01 0601 0ECD0000000000000000000000000000]
2024-04-14 21:31:14,101,101    DEBUG [MainThread] logitech_receiver.base: (14) => r[11 01 010F 1D000000000000000000000000000000]
2024-04-14 21:31:14,102,102    DEBUG [MainThread] logitech_receiver.base: (14) <= w[11 01 000F 81000000000000000000000000000000]
2024-04-14 21:31:14,110,110    DEBUG [MainThread] logitech_receiver.base: (14) => r[11 01 0001 1D000000000000000000000000000000]
2024-04-14 21:31:14,113,113    DEBUG [MainThread] logitech_receiver.base: (14) => r[11 01 000F 09000000000000000000000000000000]
2024-04-14 21:31:14,114,114    DEBUG [MainThread] logitech_receiver.base: (14) <= w[11 01 090B 00000000000000000000000000000000]
2024-04-14 21:31:14,123,123    DEBUG [MainThread] logitech_receiver.base: (14) => r[11 01 1D21 02000000000000000000000000000000]
2024-04-14 21:31:14,125,125    DEBUG [MainThread] logitech_receiver.base: (14) => r[11 01 090B 01030105010B1000FF0A040000000000]
2024-04-14 21:31:14,125,125    DEBUG [MainThread] logitech_receiver.base: (14) <= w[11 01 095C 00000000000000000000000000000000]
2024-04-14 21:31:14,135,135    DEBUG [MainThread] logitech_receiver.base: (14) => r[11 01 0001 1D000000000000000000000000000000]
2024-04-14 21:31:14,138,138    DEBUG [MainThread] logitech_receiver.base: (14) => r[11 01 095C FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF]
#Dumping profiles from G502 Gaming Mouse
!OnboardProfiles
buttons: 11
count: 5
gbuttons: 11
name: G502 Gaming Mouse
profiles: {}
sectors: 16
size: 255
version: 3
```
</details>

I'm thinking maybe I have no modifiable profiles and just the read-only ones?
In an attempt to enumerate "rom" profiles, I changed the `get_profile_headers` function to the following (just a guess how it "could" work, I haven't reverse engineered anything):
```python
    def get_profile_headers(cls, device):
        headers = []

        for s in (0x00, 0x01):
            i = 0
            while True:
                chunk = device.feature_request(FEATURE.ONBOARD_PROFILES, 0x50, s, 0, 0, i * 4)
                print(f'{s=} {i=} {chunk=}')
                i += 1
                if chunk[0:4] == b"\x00\x00\x00\x00" or chunk[0:2] == b"\xff\xff":
                    break
                sector, enabled = _unpack("!HB", chunk[0:3])
                headers.append((sector, enabled))

        return headers
```
Now I get this (also added log in read_sector):

<details open><summary>solaar profiles 502 (with patch)</summary>

```
s=0 i=0 chunk=b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
s=1 i=0 chunk=b'\x01\x01\x01\xff\xff\xff\x90d\x03\x00\xa4d\x03\x00\xc0d'
s=1 i=1 chunk=b'\xff\xff\x90d\x03\x00\xa4d\x03\x00\xc0d\x03\x00\xccd'
read_sector(sector=257, s=255) = b'\x01\x01\x00\x90\x01 \x03@\x06\x80\x0c\x00\x19\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x01\x00\x01\x80\x01\x00\x02\x80\x01\x00\x04\x80\x01\x00\x08\x80\x01\x00\x10\x90\x07\x00\x00\x90\x04\x00\x00\x90\x03\x00\x00\x90\x0c\x00\x00\x90\x02\x00\x00\x90\x01\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x03\x00\x00\x00\x00\x00\x1f@\x00\x00\x00\x03\x00\x00\x00\x00\x00\x1f@\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
#Dumping profiles from G502 Gaming Mouse
!OnboardProfiles
buttons: 11
count: 5
gbuttons: 11
name: G502 Gaming Mouse
profiles:
  1: !OnboardProfile
    angle_snap: 0
    blue: 255
    buttons:
    - !Button {behavior: 8, type: 1, value: 1}
    - !Button {behavior: 8, type: 1, value: 2}
    - !Button {behavior: 8, type: 1, value: 4}
    - !Button {behavior: 8, type: 1, value: 8}
    - !Button {behavior: 8, type: 1, value: 16}
    - !Button {behavior: 9, data: 0, value: 7}
    - !Button {behavior: 9, data: 0, value: 4}
    - !Button {behavior: 9, data: 0, value: 3}
    - !Button {behavior: 9, data: 0, value: 12}
    - !Button {behavior: 9, data: 0, value: 2}
    - !Button {behavior: 9, data: 0, value: 1}
    enabled: 1
    gbuttons:
    - !Button {behavior: 15, bytes: !!binary "/////w==\n"}
    - !Button {behavior: 15, bytes: !!binary "/////w==\n"}
    - !Button {behavior: 15, bytes: !!binary "/////w==\n"}
    - !Button {behavior: 15, bytes: !!binary "/////w==\n"}
    - !Button {behavior: 15, bytes: !!binary "/////w==\n"}
    - !Button {behavior: 15, bytes: !!binary "/////w==\n"}
    - !Button {behavior: 15, bytes: !!binary "/////w==\n"}
    - !Button {behavior: 15, bytes: !!binary "/////w==\n"}
    - !Button {behavior: 15, bytes: !!binary "/////w==\n"}
    - !Button {behavior: 15, bytes: !!binary "/////w==\n"}
    - !Button {behavior: 15, bytes: !!binary "/////w==\n"}
    green: 255
    lighting:
    - !LEDEffectSetting {ID: 3, intensity: 0, period: 8000}
    - !LEDEffectSetting {ID: 3, intensity: 0, period: 8000}
    - !LEDEffectSetting {ID: null, bytes: !!binary "//////////////8=\n"}
    - !LEDEffectSetting {ID: null, bytes: !!binary "//////////////8=\n"}
    name: ''
    po_timeout: 65535
    power_mode: 255
    ps_timeout: 65535
    red: 255
    report_rate: 1
    reserved: !!binary |
      //////////8=
    resolution_default_index: 1
    resolution_shift_index: 0
    resolutions:
    - 400
    - 800
    - 1600
    - 3200
    - 6400
    sector: 257
    write_count: 65535
sectors: 16
size: 255
version: 3
```

</details>

As you can see, the result is just one ROM profile, I'm not sure if all of the data makes sense (you tell me) but at least the resolutions are correct

I tried to see if I could switch between the any other profile by changing `OnboardProfiles.validator_class.build` in `settings_templates.py` to be able to select every possible profile:
```python
    class validator_class(_ChoicesV):
        @classmethod
        def build(cls, setting_class, device):
            return cls(choices=setting_class.choices_universe, byte_count=2)
```

The result is that I can switch between "Disabled" and "Read-Only Profile 1", but for any other value the devices responds with an "invalid argument" error

I'm not sure if I have corrupted profiles or the mouse doesn't support switching profiles like that and only has an on-off switch? Perhaps you know more about this.

If it's expected behavior, then I suppose there should just be a switch between "Enabled" and "Disabled" as this was the case in the previous version?

In any case, let me know if I can help with any data dump

At some point I might boot into Windows and see what I can do with the Logitech software


Discussion:

Resolving patch:
diff --git a/lib/logitech_receiver/hidpp20.py b/lib/logitech_receiver/hidpp20.py
--- a/lib/logitech_receiver/hidpp20.py
+++ b/lib/logitech_receiver/hidpp20.py
@@ -1247,7 +1247,7 @@ def get_profile_headers(cls, device):
         headers = []
         chunk = device.feature_request(FEATURE.ONBOARD_PROFILES, 0x50, 0, 0, 0, i)
         s = 0x00
-        if chunk[0:4] == b"\x00\x00\x00\x00":  # look in ROM instead
+        if chunk[0:4] == b"\x00\x00\x00\x00" or chunk[0:4] == b"\xFF\xFF\xFF\xFF":  # look in ROM instead
             chunk = device.feature_request(FEATURE.ONBOARD_PROFILES, 0x50, 0x01, 0, 0, i)
             s = 0x01
         while chunk[0:2] != b"\xff\xff":
diff --git a/lib/logitech_receiver/receiver.py b/lib/logitech_receiver/receiver.py
--- a/lib/logitech_receiver/receiver.py
+++ b/lib/logitech_receiver/receiver.py
@@ -17,6 +17,7 @@
 
 import errno as _errno
 import logging
+import time
 
 from dataclasses import dataclass
 from typing import Optional
@@ -209,6 +210,7 @@ def register_new_device(self, number, notification=None):
         assert notification is None or notification.sub_id == 0x41
 
         try:
+            time.sleep(0.05)  # let receiver settle
             info = self.device_pairing_information(number)
             if notification is not None:
                 online, _e, nwpid, nkind = self.notification_information(number, notification)


Test patch:
diff --git a/tests/logitech_receiver/hidpp.py b/tests/logitech_receiver/hidpp.py
--- a/tests/logitech_receiver/hidpp.py
+++ b/tests/logitech_receiver/hidpp.py
@@ -299,6 +299,28 @@ def adjust_responses_index(index, responses):  # change index-4 responses to ind
     Response("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 0x0950, "010100E0"),
     Response("FFFFFFFFFFFFFFFFFFFFFFFFFF7C81AB", 0x0950, "010100EE"),
 ]
+responses_profiles_rom_2 = [  # OnboardProfile in ROM
+    Response("0104010101020100FE0200", 0x0900),
+    Response("FFFFFFFF", 0x0950, "00000000"),
+    Response("010101FF", 0x0950, "01000000"),
+    Response("FFFFFFFF", 0x0950, "01000004"),
+    Response("01010290018003000700140028FFFFFF", 0x0950, "01010000"),
+    Response("FFFF0000000000000000000000000000", 0x0950, "01010010"),
+    Response("8000FFFF900aFF00800204548000FFFF", 0x0950, "01010020"),
+    Response("900aFF00800204548000FFFF900aFF00", 0x0950, "01010030"),
+    Response("800204548000FFFF900aFF0080020454", 0x0950, "01010040"),
+    Response("8000FFFF900aFF00800204548000FFFF", 0x0950, "01010050"),
+    Response("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 0x0950, "01010060"),
+    Response("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 0x0950, "01010070"),
+    Response("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 0x0950, "01010080"),
+    Response("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 0x0950, "01010090"),
+    Response("54004500370000000000000000000000", 0x0950, "010100A0"),
+    Response("00000000000000000000000000000000", 0x0950, "010100B0"),
+    Response("00000000000000000000000000000000", 0x0950, "010100C0"),
+    Response("0A01020300500407000000FFFFFFFFFF", 0x0950, "010100D0"),
+    Response("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 0x0950, "010100E0"),
+    Response("FFFFFFFFFFFFFFFFFFFFFFFFFF7C81AB", 0x0950, "010100EE"),
+]
 
 complex_responses_1 = [  # COLOR_LED_EFFECTS
     Response(4.2, 0x0010),  # ping
diff --git a/tests/logitech_receiver/test_hidpp20_complex.py b/tests/logitech_receiver/test_hidpp20_complex.py
--- a/tests/logitech_receiver/test_hidpp20_complex.py
+++ b/tests/logitech_receiver/test_hidpp20_complex.py
@@ -775,6 +775,25 @@ def test_button_bytes(hex, behavior, sector, address, typ, val, modifiers, data,
     "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
     "FFFFFFFFFFFFFFFFFFFFFFFFFF27C9"
 )
+hex3 = (
+    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+    "FFFFFFFFFFFFFFFFFFFFFFFFFF2307"
+)
 
 
 @pytest.mark.parametrize(
@@ -782,6 +801,7 @@ def test_button_bytes(hex, behavior, sector, address, typ, val, modifiers, data,
     [
         (hex1, "TE7", 2, 1, 16, 0, [0x0190, 0x0380, 0x0700, 0x1400, 0x2800], "8000FFFF", "0A01020300500407000000"),
         (hex2, "", 2, 1, 16, 0, [0x0190, 0x0380, 0x0700, 0x1400, 0x2800], "8000FFFF", "0A01020300500407000000"),
+        (hex3, "", 2, 1, 16, 0, [0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF], "FFFFFFFF", "FFFFFFFFFFFFFFFFFFFFFF"),
     ],
 )
 def test_OnboardProfile_bytes(hex, name, sector, enabled, buttons, gbuttons, resolutions, button, lighting):
@@ -802,6 +822,7 @@ def test_OnboardProfile_bytes(hex, name, sector, enabled, buttons, gbuttons, res
     [
         (hidpp.responses_profiles, "ONB", 1, 2, 2, 1, 254),
         (hidpp.responses_profiles_rom, "ONB", 1, 2, 2, 1, 254),
+        (hidpp.responses_profiles_rom_2, "ONB", 1, 2, 2, 1, 254),
     ],
 )
 def test_OnboardProfiles_device(responses, name, count, buttons, gbuttons, sectors, size):