~ruther/qmk_firmware

f80058d96e2f1606f648166d320cda15986ced4c — Ryan 2 years ago cbbb45c
Start Bluetooth API (#18366)

M builddefs/common_features.mk => builddefs/common_features.mk +1 -1
@@ 882,7 882,7 @@ ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
    OPT_DEFS += -DBLUETOOTH_ENABLE
    NO_USB_STARTUP_CHECK := yes
    COMMON_VPATH += $(DRIVER_PATH)/bluetooth
    SRC += outputselect.c
    SRC += outputselect.c bluetooth.c

    ifeq ($(strip $(BLUETOOTH_DRIVER)), BluefruitLE)
        OPT_DEFS += -DBLUETOOTH_BLUEFRUIT_LE -DHAL_USE_SPI=TRUE

M drivers/bluetooth/bluefruit_le.cpp => drivers/bluetooth/bluefruit_le.cpp +20 -38
@@ 5,7 5,7 @@
#include <alloca.h>
#include "debug.h"
#include "timer.h"
#include "action_util.h"
#include "gpio.h"
#include "ringbuffer.hpp"
#include <string.h>
#include "spi_master.h"


@@ 288,7 288,7 @@ static void resp_buf_wait(const char *cmd) {
    }
}

static bool ble_init(void) {
void bluefruit_le_init(void) {
    state.initialized  = false;
    state.configured   = false;
    state.is_connected = false;


@@ 307,7 307,6 @@ static bool ble_init(void) {
    wait_ms(1000); // Give it a second to initialize

    state.initialized = true;
    return state.initialized;
}

static inline uint8_t min(uint8_t a, uint8_t b) {


@@ 431,7 430,7 @@ bool bluefruit_le_is_connected(void) {
bool bluefruit_le_enable_keyboard(void) {
    char resbuf[128];

    if (!state.initialized && !ble_init()) {
    if (!state.initialized) {
        return false;
    }



@@ 613,41 612,24 @@ static bool process_queue_item(struct queue_item *item, uint16_t timeout) {
    }
}

void bluefruit_le_send_keys(uint8_t hid_modifier_mask, uint8_t *keys, uint8_t nkeys) {
void bluefruit_le_send_keyboard(report_keyboard_t *report) {
    struct queue_item item;
    bool              didWait = false;

    item.queue_type   = QTKeyReport;
    item.key.modifier = hid_modifier_mask;
    item.added        = timer_read();

    while (nkeys >= 0) {
        item.key.keys[0] = keys[0];
        item.key.keys[1] = nkeys >= 1 ? keys[1] : 0;
        item.key.keys[2] = nkeys >= 2 ? keys[2] : 0;
        item.key.keys[3] = nkeys >= 3 ? keys[3] : 0;
        item.key.keys[4] = nkeys >= 4 ? keys[4] : 0;
        item.key.keys[5] = nkeys >= 5 ? keys[5] : 0;

        if (!send_buf.enqueue(item)) {
            if (!didWait) {
                dprint("wait for buf space\n");
                didWait = true;
            }
            send_buf_send_one();
            continue;
        }

        if (nkeys <= 6) {
            return;
        }
    item.key.modifier = report->mods;
    item.key.keys[0]  = report->keys[0];
    item.key.keys[1]  = report->keys[1];
    item.key.keys[2]  = report->keys[2];
    item.key.keys[3]  = report->keys[3];
    item.key.keys[4]  = report->keys[4];
    item.key.keys[5]  = report->keys[5];

        nkeys -= 6;
        keys += 6;
    while (!send_buf.enqueue(item)) {
        send_buf_send_one();
    }
}

void bluefruit_le_send_consumer_key(uint16_t usage) {
void bluefruit_le_send_consumer(uint16_t usage) {
    struct queue_item item;

    item.queue_type = QTConsumer;


@@ 658,15 640,15 @@ void bluefruit_le_send_consumer_key(uint16_t usage) {
    }
}

void bluefruit_le_send_mouse_move(int8_t x, int8_t y, int8_t scroll, int8_t pan, uint8_t buttons) {
void bluefruit_le_send_mouse(report_mouse_t *report) {
    struct queue_item item;

    item.queue_type        = QTMouseMove;
    item.mousemove.x       = x;
    item.mousemove.y       = y;
    item.mousemove.scroll  = scroll;
    item.mousemove.pan     = pan;
    item.mousemove.buttons = buttons;
    item.mousemove.x       = report->x;
    item.mousemove.y       = report->y;
    item.mousemove.scroll  = report->v;
    item.mousemove.pan     = report->h;
    item.mousemove.buttons = report->buttons;

    while (!send_buf.enqueue(item)) {
        send_buf_send_one();

M drivers/bluetooth/bluefruit_le.h => drivers/bluetooth/bluefruit_le.h +6 -6
@@ 7,9 7,7 @@

#include <stdbool.h>
#include <stdint.h>
#include <string.h>

#include "config_common.h"
#include "report.h"

#ifdef __cplusplus
extern "C" {


@@ 26,6 24,8 @@ extern bool bluefruit_le_query_is_connected(void);
 * calling ble_task() periodically. */
extern bool bluefruit_le_is_connected(void);

extern void bluefruit_le_init(void);

/* Call this periodically to process BLE-originated things */
extern void bluefruit_le_task(void);



@@ 34,16 34,16 @@ extern void bluefruit_le_task(void);
 * this set of keys.
 * Also sends a key release indicator, so that the keys do not remain
 * held down. */
extern void bluefruit_le_send_keys(uint8_t hid_modifier_mask, uint8_t *keys, uint8_t nkeys);
extern void bluefruit_le_send_keyboard(report_keyboard_t *report);

/* Send a consumer usage.
 * (milliseconds) */
extern void bluefruit_le_send_consumer_key(uint16_t usage);
extern void bluefruit_le_send_consumer(uint16_t usage);

/* Send a mouse/wheel movement report.
 * The parameters are signed and indicate positive or negative direction
 * change. */
extern void bluefruit_le_send_mouse_move(int8_t x, int8_t y, int8_t scroll, int8_t pan, uint8_t buttons);
extern void bluefruit_le_send_mouse(report_mouse_t *report);

/* Compute battery voltage by reading an analog pin.
 * Returns the integer number of millivolts */

A drivers/bluetooth/bluetooth.c => drivers/bluetooth/bluetooth.c +62 -0
@@ 0,0 1,62 @@
/*
 * Copyright 2022
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "bluetooth.h"

#if defined(BLUETOOTH_BLUEFRUIT_LE)
#    include "bluefruit_le.h"
#elif defined(BLUETOOTH_RN42)
#    include "rn42.h"
#endif

void bluetooth_init(void) {
#if defined(BLUETOOTH_BLUEFRUIT_LE)
    bluefruit_le_init();
#elif defined(BLUETOOTH_RN42)
    rn42_init();
#endif
}

void bluetooth_task(void) {
#if defined(BLUETOOTH_BLUEFRUIT_LE)
    bluefruit_le_task();
#endif
}

void bluetooth_send_keyboard(report_keyboard_t *report) {
#if defined(BLUETOOTH_BLUEFRUIT_LE)
    bluefruit_le_send_keyboard(report);
#elif defined(BLUETOOTH_RN42)
    rn42_send_keyboard(report);
#endif
}

void bluetooth_send_mouse(report_mouse_t *report) {
#if defined(BLUETOOTH_BLUEFRUIT_LE)
    bluefruit_le_send_mouse(report);
#elif defined(BLUETOOTH_RN42)
    rn42_send_mouse(report);
#endif
}

void bluetooth_send_consumer(uint16_t usage) {
#if defined(BLUETOOTH_BLUEFRUIT_LE)
    bluefruit_le_send_consumer(usage);
#elif defined(BLUETOOTH_RN42)
    rn42_send_consumer(usage);
#endif
}

A drivers/bluetooth/bluetooth.h => drivers/bluetooth/bluetooth.h +52 -0
@@ 0,0 1,52 @@
/*
 * Copyright 2022
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <stdint.h>
#include "report.h"

/**
 * \brief Initialize the Bluetooth system.
 */
void bluetooth_init(void);

/**
 * \brief Perform housekeeping tasks.
 */
void bluetooth_task(void);

/**
 * \brief Send a keyboard report.
 * 
 * \param report The keyboard report to send.
 */
void bluetooth_send_keyboard(report_keyboard_t *report);

/**
 * \brief Send a mouse report.
 * 
 * \param report The mouse report to send.
 */
void bluetooth_send_mouse(report_mouse_t *report);

/**
 * \brief Send a consumer usage.
 * 
 * \param usage The consumer usage to send.
 */
void bluetooth_send_consumer(uint16_t usage);

M quantum/keyboard.c => quantum/keyboard.c +5 -10
@@ 106,12 106,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
#    include "split_util.h"
#endif
#ifdef BLUETOOTH_ENABLE
#    include "outputselect.h"
#    ifdef BLUETOOTH_BLUEFRUIT_LE
#        include "bluefruit_le.h"
#    elif BLUETOOTH_RN42
#        include "rn42.h"
#    endif
#    include "bluetooth.h"
#endif
#ifdef CAPS_WORD_ENABLE
#    include "caps_word.h"


@@ 411,8 406,8 @@ void keyboard_init(void) {
    // init after split init
    pointing_device_init();
#endif
#if defined(BLUETOOTH_RN42)
    rn42_init();
#ifdef BLUETOOTH_ENABLE
    bluetooth_init();
#endif

#if defined(DEBUG_MATRIX_SCAN_RATE) && defined(CONSOLE_ENABLE)


@@ 674,8 669,8 @@ void keyboard_task(void) {
    programmable_button_send();
#endif

#ifdef BLUETOOTH_BLUEFRUIT_LE
    bluefruit_le_task();
#ifdef BLUETOOTH_ENABLE
    bluetooth_task();
#endif

    led_task();

M tmk_core/protocol/host.c => tmk_core/protocol/host.c +4 -21
@@ 29,12 29,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
#endif

#ifdef BLUETOOTH_ENABLE
#    include "bluetooth.h"
#    include "outputselect.h"
#    ifdef BLUETOOTH_BLUEFRUIT_LE
#        include "bluefruit_le.h"
#    elif BLUETOOTH_RN42
#        include "rn42.h"
#    endif
#endif

#ifdef NKRO_ENABLE


@@ 78,11 74,7 @@ led_t host_keyboard_led_state(void) {
void host_keyboard_send(report_keyboard_t *report) {
#ifdef BLUETOOTH_ENABLE
    if (where_to_send() == OUTPUT_BLUETOOTH) {
#    ifdef BLUETOOTH_BLUEFRUIT_LE
        bluefruit_le_send_keys(report->mods, report->keys, sizeof(report->keys));
#    elif BLUETOOTH_RN42
        rn42_send_keyboard(report);
#    endif
        bluetooth_send_keyboard(report);
        return;
    }
#endif


@@ 116,12 108,7 @@ void host_keyboard_send(report_keyboard_t *report) {
void host_mouse_send(report_mouse_t *report) {
#ifdef BLUETOOTH_ENABLE
    if (where_to_send() == OUTPUT_BLUETOOTH) {
#    ifdef BLUETOOTH_BLUEFRUIT_LE
        // FIXME: mouse buttons
        bluefruit_le_send_mouse_move(report->x, report->y, report->v, report->h, report->buttons);
#    elif BLUETOOTH_RN42
        rn42_send_mouse(report);
#    endif
        bluetooth_send_mouse(report);
        return;
    }
#endif


@@ 152,11 139,7 @@ void host_consumer_send(uint16_t report) {

#ifdef BLUETOOTH_ENABLE
    if (where_to_send() == OUTPUT_BLUETOOTH) {
#    ifdef BLUETOOTH_BLUEFRUIT_LE
        bluefruit_le_send_consumer_key(report);
#    elif BLUETOOTH_RN42
        rn42_send_consumer(report);
#    endif
        bluetooth_send_consumer(report);
        return;
    }
#endif