fix(q5_max): fix RAW_EPSIZE and via_command_kb hook conflict
Two build errors: 1. RAW_EPSIZE undeclared — usb_descriptor.h is not in scope when keymap.c is compiled through Keychron's build path. Replace all uses with HID_PACKET_SIZE (= 32), now defined in hid_protocol.h. 2. via_command_kb duplicate symbol — keychron_raw_hid.c already defines via_command_kb (non-weak) so we cannot redefine it in keymap.c. Fix by adding a weak kc_raw_hid_rx_kb() extension hook to keychron_raw_hid.c (following the same pattern as kc_rgb_matrix_rx). kc_raw_hid_rx() now calls this hook from its default case instead of returning false directly. The keymap overrides kc_raw_hid_rx_kb() to handle our custom HID command range (0x40-0x7E).
This commit is contained in:
@@ -85,6 +85,11 @@ void get_firmware_version(uint8_t *data) {
|
|||||||
|
|
||||||
__attribute__((weak)) void kc_rgb_matrix_rx(uint8_t *data, uint8_t length) {}
|
__attribute__((weak)) void kc_rgb_matrix_rx(uint8_t *data, uint8_t length) {}
|
||||||
|
|
||||||
|
/* Default no-op implementation; override in keymap.c to handle custom IDs. */
|
||||||
|
__attribute__((weak)) bool kc_raw_hid_rx_kb(uint8_t *data, uint8_t length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool kc_raw_hid_rx(uint8_t *data, uint8_t length) {
|
bool kc_raw_hid_rx(uint8_t *data, uint8_t length) {
|
||||||
switch (data[0]) {
|
switch (data[0]) {
|
||||||
case KC_GET_PROTOCOL_VERSION:
|
case KC_GET_PROTOCOL_VERSION:
|
||||||
@@ -185,7 +190,7 @@ bool kc_raw_hid_rx(uint8_t *data, uint8_t length) {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
return false;
|
return kc_raw_hid_rx_kb(data, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_hid_send(data, length);
|
raw_hid_send(data, length);
|
||||||
|
|||||||
@@ -63,3 +63,17 @@ enum {
|
|||||||
REPORT_RATE_GET,
|
REPORT_RATE_GET,
|
||||||
REPORT_RATE_SET,
|
REPORT_RATE_SET,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keyboard-level Raw HID extension hook.
|
||||||
|
*
|
||||||
|
* Called by kc_raw_hid_rx() for any command ID not handled by Keychron's own
|
||||||
|
* protocol (0xA0-0xAB range). The default weak implementation returns false
|
||||||
|
* so that unrecognised commands fall through to VIA.
|
||||||
|
*
|
||||||
|
* Override this in your keymap to handle custom command IDs without
|
||||||
|
* conflicting with Keychron's via_command_kb() definition.
|
||||||
|
* Return true if the packet was fully handled (including calling
|
||||||
|
* raw_hid_send() if a reply is needed), false to let VIA process it.
|
||||||
|
*/
|
||||||
|
bool kc_raw_hid_rx_kb(uint8_t *data, uint8_t length);
|
||||||
|
|||||||
@@ -80,6 +80,14 @@
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
#define HID_APP_NAME_MAX 28u
|
#define HID_APP_NAME_MAX 28u
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Packet size
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Matches RAW_EPSIZE (QMK raw HID endpoint size = 32 bytes). Defined here
|
||||||
|
// so keymap code does not depend on usb_descriptor.h being in scope, which
|
||||||
|
// it is not when compiled through Keychron's build path.
|
||||||
|
#define HID_PACKET_SIZE 32u
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Convenience: first byte of payload as an absolute packet index
|
// Convenience: first byte of payload as an absolute packet index
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "keychron_common.h"
|
#include "keychron_common.h"
|
||||||
#include "chord_unicode.h"
|
#include "chord_unicode.h"
|
||||||
#include "raw_hid.h"
|
#include "raw_hid.h"
|
||||||
|
#include "keychron_raw_hid.h"
|
||||||
#include "hid_protocol.h"
|
#include "hid_protocol.h"
|
||||||
|
|
||||||
// Tap Dance declarations
|
// Tap Dance declarations
|
||||||
@@ -77,18 +78,20 @@ static uint8_t g_hid_brightness = 0;
|
|||||||
|
|
||||||
// Send the current layer state to the host / bridge application.
|
// Send the current layer state to the host / bridge application.
|
||||||
static void hid_send_layer_sync(uint8_t layer, uint8_t locked_mask) {
|
static void hid_send_layer_sync(uint8_t layer, uint8_t locked_mask) {
|
||||||
uint8_t data[RAW_EPSIZE] = {0};
|
uint8_t data[HID_PACKET_SIZE] = {0};
|
||||||
data[HID_OFF_CMD] = HID_CMD_LAYER_SYNC;
|
data[HID_OFF_CMD] = HID_CMD_LAYER_SYNC;
|
||||||
data[HID_OFF_SRC] = HID_DEV_Q5MAX;
|
data[HID_OFF_SRC] = HID_DEV_Q5MAX;
|
||||||
data[HID_OFF_FLAGS] = 0;
|
data[HID_OFF_FLAGS] = 0;
|
||||||
data[HID_PAYLOAD(HID_LAYER_OFF_ACTIVE)] = layer;
|
data[HID_PAYLOAD(HID_LAYER_OFF_ACTIVE)] = layer;
|
||||||
data[HID_PAYLOAD(HID_LAYER_OFF_LOCKED)] = locked_mask;
|
data[HID_PAYLOAD(HID_LAYER_OFF_LOCKED)] = locked_mask;
|
||||||
raw_hid_send(data, RAW_EPSIZE);
|
raw_hid_send(data, HID_PACKET_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle a Raw HID packet for our custom command range (0x40-0x7E).
|
// Handle a Raw HID packet for our custom command range (0x40-0x7E).
|
||||||
// Called from via_command_kb(); must call raw_hid_send() for any reply.
|
// Overrides the weak kc_raw_hid_rx_kb() hook in keychron_raw_hid.c, which is
|
||||||
bool via_command_kb(uint8_t *data, uint8_t length) {
|
// called by kc_raw_hid_rx() for any command ID not handled by Keychron's own
|
||||||
|
// protocol. Must call raw_hid_send() directly for any reply.
|
||||||
|
bool kc_raw_hid_rx_kb(uint8_t *data, uint8_t length) {
|
||||||
uint8_t cmd = data[HID_OFF_CMD];
|
uint8_t cmd = data[HID_OFF_CMD];
|
||||||
|
|
||||||
// Only intercept our custom command range; let VIA handle everything else.
|
// Only intercept our custom command range; let VIA handle everything else.
|
||||||
@@ -102,13 +105,13 @@ bool via_command_kb(uint8_t *data, uint8_t length) {
|
|||||||
case HID_CMD_LAYER_SYNC: {
|
case HID_CMD_LAYER_SYNC: {
|
||||||
if (flags & HID_FLAG_QUERY) {
|
if (flags & HID_FLAG_QUERY) {
|
||||||
// Host requests current state — reply without changing anything.
|
// Host requests current state — reply without changing anything.
|
||||||
uint8_t resp[RAW_EPSIZE] = {0};
|
uint8_t resp[HID_PACKET_SIZE] = {0};
|
||||||
resp[HID_OFF_CMD] = HID_CMD_LAYER_SYNC;
|
resp[HID_OFF_CMD] = HID_CMD_LAYER_SYNC;
|
||||||
resp[HID_OFF_SRC] = HID_DEV_Q5MAX;
|
resp[HID_OFF_SRC] = HID_DEV_Q5MAX;
|
||||||
resp[HID_OFF_FLAGS] = HID_FLAG_RESPONSE;
|
resp[HID_OFF_FLAGS] = HID_FLAG_RESPONSE;
|
||||||
resp[HID_PAYLOAD(HID_LAYER_OFF_ACTIVE)] = get_highest_layer(layer_state);
|
resp[HID_PAYLOAD(HID_LAYER_OFF_ACTIVE)] = get_highest_layer(layer_state);
|
||||||
resp[HID_PAYLOAD(HID_LAYER_OFF_LOCKED)] = (uint8_t)locked_layers;
|
resp[HID_PAYLOAD(HID_LAYER_OFF_LOCKED)] = (uint8_t)locked_layers;
|
||||||
raw_hid_send(resp, RAW_EPSIZE);
|
raw_hid_send(resp, HID_PACKET_SIZE);
|
||||||
} else {
|
} else {
|
||||||
// Host or peer keyboard is pushing a new active layer.
|
// Host or peer keyboard is pushing a new active layer.
|
||||||
uint8_t new_layer = data[HID_PAYLOAD(HID_LAYER_OFF_ACTIVE)];
|
uint8_t new_layer = data[HID_PAYLOAD(HID_LAYER_OFF_ACTIVE)];
|
||||||
|
|||||||
Reference in New Issue
Block a user