feat(remap): on-dongle button remapping over 0xF6/0xF7
16-entry source→target table in its own flash sector (-3, magic DS5\x03), identity default, 0xFF = disabled. Applied to the OUTGOING host report copy only — raw interrupt_in_data (OLED screens + PS+Mute reboot combo) stays physical. Edited via the existing 0xF6/0xF7 vendor reports with a hardened RM+version frame (no HID-descriptor change, so Windows enumeration is unaffected) plus a revision counter the host polls to confirm a write. Apply logic + button set ported from SundayMoments/DS5_Bridge (credit). scripts/remap_test.py exercises the path over /dev/hidraw without the web tool. Verified on hardware: swap applied, read back, survived reboot. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
da63e2bb72
commit
1b1944c006
+48
-3
@@ -14,6 +14,7 @@
|
||||
#include "device/usbd.h"
|
||||
#include "pico/time.h"
|
||||
#include "slots.h"
|
||||
#include "remap.h"
|
||||
#include "hardware/clocks.h"
|
||||
#include "hardware/adc.h"
|
||||
#include "hardware/vreg.h"
|
||||
@@ -86,11 +87,34 @@ bool is_pico_cmd(uint8_t report_id) {
|
||||
uint16_t pico_cmd_get(uint8_t report_id, uint8_t *buffer, uint16_t reqlen) {
|
||||
if (report_id == 0xf7) {
|
||||
printf("[HID] Receive 0xf7 getting config\n");
|
||||
if (sizeof(Config_body) > reqlen) {
|
||||
const size_t cfg_len = sizeof(Config_body);
|
||||
if (cfg_len > reqlen) {
|
||||
printf("[Config] Warning: Config_body overflow\n");
|
||||
}
|
||||
const auto len = std::min(sizeof(Config_body),static_cast<size_t>(reqlen));
|
||||
memcpy(buffer,&get_config(),len);
|
||||
const auto len = std::min(cfg_len, static_cast<size_t>(reqlen));
|
||||
memcpy(buffer, &get_config(), len);
|
||||
|
||||
// OLED Edition: append the button-remap block right after Config_body
|
||||
// when the host asked for enough room. Old clients request exactly
|
||||
// sizeof(Config_body) and never see it; new web tools read config +
|
||||
// remap in one GET (the 0xF6/0xF7 reports are 63 bytes, plenty).
|
||||
// [+0] 'R'
|
||||
// [+1] 'M'
|
||||
// [+2] protocol version (kRemapProtoVer)
|
||||
// [+3..+4] revision uint16 LE (bumps on each successful set)
|
||||
// [+5..+20] 16-byte remap table (source idx -> target idx, 0xFF=off)
|
||||
constexpr size_t kRemapBlock = 5 + kRemapCount;
|
||||
if (reqlen >= cfg_len + kRemapBlock) {
|
||||
uint8_t *p = buffer + cfg_len;
|
||||
p[0] = 'R';
|
||||
p[1] = 'M';
|
||||
p[2] = kRemapProtoVer;
|
||||
const uint16_t rev = remap_revision();
|
||||
p[3] = (uint8_t)(rev & 0xFF);
|
||||
p[4] = (uint8_t)((rev >> 8) & 0xFF);
|
||||
remap_get(p + 5);
|
||||
return cfg_len + kRemapBlock;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
if (report_id == 0xf8) {
|
||||
@@ -268,4 +292,25 @@ void pico_cmd_set(uint8_t report_id, uint8_t const *buffer, uint16_t bufsize) {
|
||||
sleep_ms(150);
|
||||
tud_connect();
|
||||
}
|
||||
// 0x10 set button-remap table (OLED Edition). Hardened framing so a stray
|
||||
// write to 0xF6 can't corrupt the map: magic 'R''M' + protocol version gate
|
||||
// before remap_set() (which itself validates each entry <16 or 0xFF=off).
|
||||
// [0] 0x10 func-id
|
||||
// [1] 'R'
|
||||
// [2] 'M'
|
||||
// [3] protocol version (must == kRemapProtoVer)
|
||||
// [4..19] 16-byte remap table
|
||||
if (buffer[0] == 0x10) {
|
||||
constexpr uint16_t kNeed = 4 + kRemapCount;
|
||||
if (bufsize < kNeed) {
|
||||
printf("[CMD] 0x10 remap-set too short (%u<%u)\n", bufsize, kNeed);
|
||||
return;
|
||||
}
|
||||
if (buffer[1] != 'R' || buffer[2] != 'M' || buffer[3] != kRemapProtoVer) {
|
||||
printf("[CMD] 0x10 remap-set bad magic/version\n");
|
||||
return;
|
||||
}
|
||||
if (remap_set(buffer + 4)) printf("[CMD] remap set ok (rev=%u)\n", remap_revision());
|
||||
else printf("[CMD] remap set rejected (invalid table)\n");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user