Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions keyboards/annepro2/annepro2.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ static const SerialConfig ble_uart_config = {
static uint8_t led_mcu_wakeup[11] = {0x7b, 0x10, 0x43, 0x10, 0x03, 0x00, 0x00, 0x7d, 0x02, 0x01, 0x02};

ble_capslock_t ble_capslock = {._dummy = {0}, .caps_lock = false};
static uint8_t ble_rx_buffer[sizeof(ble_capslock)];
static uint8_t ble_rx_offset;

#ifdef RGB_MATRIX_ENABLE
static uint8_t led_enabled = 1;
Expand Down Expand Up @@ -115,10 +117,20 @@ void keyboard_post_init_kb(void) {
}

void matrix_scan_kb(void) {
// if there's stuff on the ble serial buffer
// read it into the capslock struct
annepro2_ble_task();

/*
* BLE RX framing is not decoded yet. Drain one byte at a time so a short
* UART read cannot block matrix scanning for the old 10 ms timeout.
*/
while (!sdGetWouldBlock(&SD1)) {
sdReadTimeout(&SD1, (uint8_t *)&ble_capslock, sizeof(ble_capslock_t), 10);
ble_rx_buffer[ble_rx_offset++] = (uint8_t)sdGet(&SD1);
if (ble_rx_offset == sizeof(ble_capslock)) {
ble_rx_offset = 0;
for (uint8_t i = 0; i < sizeof(ble_capslock); i++) {
((uint8_t *)&ble_capslock)[i] = ble_rx_buffer[i];
}
}
}

/* While there's data from LED keyboard sent - read it. */
Expand Down Expand Up @@ -283,7 +295,9 @@ bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
}
return true;
#endif

case KC_AP2_IAP:
bootloader_jump();
return true;
default:
break;
}
Expand Down
1 change: 1 addition & 0 deletions keyboards/annepro2/annepro2.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ enum AP2KeyCodes {
KC_AP_RGB_VAD,
KC_AP_RGB_TOG,
KC_AP_RGB_MOD,
KC_AP2_IAP,
};
109 changes: 82 additions & 27 deletions keyboards/annepro2/annepro2_ble.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "host.h"
#include "host_driver.h"
#include "report.h"
#include "timer.h"

/* -------------------- Static Function Prototypes -------------------------- */
static uint8_t ap2_ble_leds(void);
Expand All @@ -29,36 +30,43 @@ static void ap2_ble_keyboard(report_keyboard_t *report);

static void ap2_ble_swtich_ble_driver(void);

#ifndef ANNEPRO2_BLE_CONNECT_GUARD_MS
# define ANNEPRO2_BLE_CONNECT_GUARD_MS 200
#endif

/* -------------------- Static Local Variables ------------------------------ */
static host_driver_t ap2_ble_driver = {
ap2_ble_leds, ap2_ble_keyboard, NULL, ap2_ble_mouse, ap2_ble_extra
};

static uint8_t ble_mcu_wakeup[11] = {0x7b, 0x12, 0x53, 0x00, 0x03, 0x00, 0x01, 0x7d, 0x02, 0x01, 0x02};
static const uint8_t ble_mcu_wakeup[11] = {0x7b, 0x12, 0x53, 0x00, 0x03, 0x00, 0x01, 0x7d, 0x02, 0x01, 0x02};

static uint8_t ble_mcu_start_broadcast[10] = {
static const uint8_t ble_mcu_start_broadcast[10] = {
0x7b, 0x12, 0x53, 0x00, 0x03, 0x00, 0x00, 0x7d, 0x40, 0x01, // Broadcast ID[0-3]
};

static uint8_t ble_mcu_connect[10] = {
static const uint8_t ble_mcu_connect[10] = {
0x7b, 0x12, 0x53, 0x00, 0x03, 0x00, 0x00, 0x7d, 0x40, 0x04, // Connect ID [0-3]
};

static uint8_t ble_mcu_send_report[10] = {
static const uint8_t ble_mcu_send_report[10] = {
0x7b, 0x12, 0x53, 0x00, 0x0A, 0x00, 0x00, 0x7d, 0x10, 0x04,
};

static uint8_t ble_mcu_send_consumer_report[10] = {
static const uint8_t ble_mcu_send_consumer_report[10] = {
0x7b, 0x12, 0x53, 0x00, 0x06, 0x00, 0x00, 0x7d, 0x10, 0x08,
};

static uint8_t ble_mcu_unpair[10] = {
static const uint8_t ble_mcu_unpair[10] = {
0x7b, 0x12, 0x53, 0x00, 0x02, 0x00, 0x00, 0x7d, 0x40, 0x05,
};

static uint8_t ble_mcu_bootload[11] = {0x7b, 0x10, 0x51, 0x10, 0x03, 0x00, 0x00, 0x7d, 0x02, 0x01, 0x01};
static const uint8_t ble_mcu_bootload[11] = {0x7b, 0x10, 0x51, 0x10, 0x03, 0x00, 0x00, 0x7d, 0x02, 0x01, 0x01};

static host_driver_t *last_host_driver = NULL;
static int8_t last_broadcast = -1;
static bool ble_connect_pending;
static uint32_t ble_connect_started_at;
#ifdef NKRO_ENABLE
static bool lastNkroStatus = false;
#endif // NKRO_ENABLE
Expand All @@ -73,28 +81,56 @@ void annepro2_ble_broadcast(uint8_t port) {
if (port > 3) {
port = 3;
}
// sdPut(&SD1, 0x00);
sdWrite(&SD1, ble_mcu_start_broadcast, sizeof(ble_mcu_start_broadcast));
sdPut(&SD1, port);
sdPut(&SD1, 0x00);
static int lastBroadcast = -1;
if (lastBroadcast == port) {
const bool reconnect = last_broadcast == (int8_t)port;
uint8_t frame[sizeof(ble_mcu_start_broadcast) + 2];

if (!reconnect) {
/* Do not keep sending HID reports to a previously selected slot. */
annepro2_ble_disconnect();
}

for (uint8_t i = 0; i < sizeof(ble_mcu_start_broadcast); i++) {
frame[i] = ble_mcu_start_broadcast[i];
}
frame[sizeof(ble_mcu_start_broadcast)] = port;
frame[sizeof(ble_mcu_start_broadcast) + 1] = 0x00;
sdWrite(&SD1, frame, sizeof(frame));

if (reconnect) {
annepro2_ble_connect(port);
}
lastBroadcast = port;
last_broadcast = port;
}

void annepro2_ble_connect(uint8_t port) {
if (port > 3) {
port = 3;
}
sdWrite(&SD1, ble_mcu_connect, sizeof(ble_mcu_connect));
sdPut(&SD1, port);
sdPut(&SD1, 0x00);
ap2_ble_swtich_ble_driver();
uint8_t frame[sizeof(ble_mcu_connect) + 2];

/* A reconnect must not let stale reports enter the newly selected slot. */
annepro2_ble_disconnect();

for (uint8_t i = 0; i < sizeof(ble_mcu_connect); i++) {
frame[i] = ble_mcu_connect[i];
}
frame[sizeof(ble_mcu_connect)] = port;
frame[sizeof(ble_mcu_connect) + 1] = 0x00;
sdWrite(&SD1, frame, sizeof(frame));

/*
* The BLE firmware's connect-complete indication is not decoded yet.
* Keep QMK on its previous host driver briefly so the command reaches the
* module before it can receive HID reports; this is not a link-state ACK.
*/
ble_connect_started_at = timer_read32();
ble_connect_pending = true;
}

void annepro2_ble_disconnect(void) {
ble_connect_pending = false;
last_broadcast = -1;

/* Skip if the driver is already enabled */
if (host_get_driver() != &ap2_ble_driver) {
return;
Expand All @@ -108,8 +144,17 @@ void annepro2_ble_disconnect(void) {
}

void annepro2_ble_unpair(void) {
// sdPut(&SD1, 0x0);
sdWrite(&SD1, ble_mcu_unpair, sizeof(ble_mcu_unpair));
annepro2_ble_disconnect();
}

void annepro2_ble_task(void) {
if (!ble_connect_pending || timer_elapsed32(ble_connect_started_at) < ANNEPRO2_BLE_CONNECT_GUARD_MS) {
return;
}

ble_connect_pending = false;
ap2_ble_swtich_ble_driver();
}

/* ------------------- Static Function Implementation ----------------------- */
Expand Down Expand Up @@ -153,19 +198,29 @@ static inline uint16_t CONSUMER2AP2(uint16_t usage) {

static void ap2_ble_extra(report_extra_t *report) {
if (report->report_id == REPORT_ID_CONSUMER) {
sdPut(&SD1, 0x0);
sdWrite(&SD1, ble_mcu_send_consumer_report, sizeof(ble_mcu_send_consumer_report));
sdPut(&SD1, CONSUMER2AP2(report->usage));
static const uint8_t dummy[3] = {0};
sdWrite(&SD1, dummy, sizeof(dummy));
uint8_t frame[1 + sizeof(ble_mcu_send_consumer_report) + 4] = {0};

frame[0] = 0x00;
for (uint8_t i = 0; i < sizeof(ble_mcu_send_consumer_report); i++) {
frame[i + 1] = ble_mcu_send_consumer_report[i];
}
frame[sizeof(ble_mcu_send_consumer_report) + 1] = CONSUMER2AP2(report->usage);
sdWrite(&SD1, frame, sizeof(frame));
}
}

/*!
* @brief Send keyboard HID report for Bluetooth driver
*/
static void ap2_ble_keyboard(report_keyboard_t *report) {
sdPut(&SD1, 0x0);
sdWrite(&SD1, ble_mcu_send_report, sizeof(ble_mcu_send_report));
sdWrite(&SD1, (uint8_t *)report, KEYBOARD_REPORT_SIZE);
uint8_t frame[1 + sizeof(ble_mcu_send_report) + KEYBOARD_REPORT_SIZE];

frame[0] = 0x00;
for (uint8_t i = 0; i < sizeof(ble_mcu_send_report); i++) {
frame[i + 1] = ble_mcu_send_report[i];
}
for (uint8_t i = 0; i < KEYBOARD_REPORT_SIZE; i++) {
frame[sizeof(ble_mcu_send_report) + 1 + i] = ((const uint8_t *)report)[i];
}
sdWrite(&SD1, frame, sizeof(frame));
}
3 changes: 3 additions & 0 deletions keyboards/annepro2/annepro2_ble.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ void annepro2_ble_broadcast(uint8_t port);
void annepro2_ble_connect(uint8_t port);
void annepro2_ble_disconnect(void);
void annepro2_ble_unpair(void);

/* Run from the keyboard scan loop to finish a requested BLE driver change. */
void annepro2_ble_task(void);