~ruther/qmk_firmware

ab8c5013c856bfa23289d7892be1c2bee808b542 — Ryan 2 years ago 7b31c18
BIOI G60/Morgan65: use custom Bluetooth driver (#20897)

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

    ifeq ($(strip $(BLUETOOTH_DRIVER)), BluefruitLE)
        OPT_DEFS += -DBLUETOOTH_BLUEFRUIT_LE -DHAL_USE_SPI=TRUE
        SRC += $(DRIVER_PATH)/bluetooth/bluetooth.c
        SRC += $(DRIVER_PATH)/bluetooth/bluefruit_le.cpp
        QUANTUM_LIB_SRC += analog.c
        QUANTUM_LIB_SRC += spi_master.c


@@ 917,6 918,7 @@ ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)

    ifeq ($(strip $(BLUETOOTH_DRIVER)), RN42)
        OPT_DEFS += -DBLUETOOTH_RN42 -DHAL_USE_SERIAL=TRUE
        SRC += $(DRIVER_PATH)/bluetooth/bluetooth.c
        SRC += $(DRIVER_PATH)/bluetooth/rn42.c
        QUANTUM_LIB_SRC += uart.c
    endif

M data/schemas/keyboard.jsonschema => data/schemas/keyboard.jsonschema +1 -1
@@ 146,7 146,7 @@
            "properties": {
                "driver": {
                    "type": "string",
                    "enum": ["BluefruitLE", "RN42"]
                    "enum": ["BluefruitLE", "RN42", "custom"]
                }
            }
        },

M keyboards/bioi/ble.c => keyboards/bioi/ble.c +25 -62
@@ 12,35 12,17 @@ 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 <avr/pgmspace.h>
#include "report.h"
#include "host.h"
#include "host_driver.h"
#include "keyboard.h"
#include "action.h"
#include "led.h"

#include "sendchar.h"
#include "debug.h"
#ifdef SLEEP_LED_ENABLE
#include "sleep_led.h"
#endif
#include "suspend.h"

#include "usb_descriptor.h"
#include "lufa.h"
#include "quantum.h"
#include <util/atomic.h>

#include "print.h"

#include "bluetooth.h"
#include "ble.h"
#include "usart.h"
#include "progmem.h"
#include "wait.h"
#include "debug.h"
#include "usb_descriptor.h"
#include "report.h"

keyboard_config_t ble_config;

static uint8_t bluefruit_keyboard_leds = 0;

static void bluefruit_serial_send(uint8_t);

void send_str(const char *str)


@@ 89,30 71,13 @@ static void bluefruit_serial_send(uint8_t data)
    serial_send(data);
}

/*------------------------------------------------------------------*
 * Host driver
 *------------------------------------------------------------------*/

static uint8_t keyboard_leds(void);
static void send_keyboard(report_keyboard_t *report);
static void send_mouse(report_mouse_t *report);
static void send_extra(report_extra_t *report);

host_driver_t bluefruit_driver = {
    keyboard_leds,
    send_keyboard,
    send_mouse,
    send_extra
};

host_driver_t null_driver = {};

static uint8_t keyboard_leds(void)
{
    return bluefruit_keyboard_leds;
void bluetooth_init(void) {
    usart_init();
}

static void send_keyboard(report_keyboard_t *report)
void bluetooth_task(void) {}

void bluetooth_send_keyboard(report_keyboard_t *report)
{
#ifdef BLUEFRUIT_TRACE_SERIAL
    bluefruit_trace_header();


@@ 136,7 101,7 @@ static void send_keyboard(report_keyboard_t *report)
#endif
}

static void send_mouse(report_mouse_t *report)
void bluetooth_send_mouse(report_mouse_t *report)
{
#ifdef BLUEFRUIT_TRACE_SERIAL
    bluefruit_trace_header();


@@ 177,27 142,25 @@ static void send_mouse(report_mouse_t *report)
#define CONSUMER2BLUEFRUIT(usage) \
    (usage == AUDIO_MUTE ? 0x00e2 : (usage == AUDIO_VOL_UP ? 0x00e9 : (usage == AUDIO_VOL_DOWN ? 0x00ea : (usage == TRANSPORT_NEXT_TRACK ? 0x00b5 : (usage == TRANSPORT_PREV_TRACK ? 0x00b6 : (usage == TRANSPORT_STOP ? 0x00b7 : (usage == TRANSPORT_STOP_EJECT ? 0x00b8 : (usage == TRANSPORT_PLAY_PAUSE ? 0x00b1 : (usage == AL_CC_CONFIG ? 0x0183 : (usage == AL_EMAIL ? 0x018c : (usage == AL_CALCULATOR ? 0x0192 : (usage == AL_LOCAL_BROWSER ? 0x0196 : (usage == AC_SEARCH ? 0x021f : (usage == AC_HOME ? 0x0223 : (usage == AC_BACK ? 0x0224 : (usage == AC_FORWARD ? 0x0225 : (usage == AC_STOP ? 0x0226 : (usage == AC_REFRESH ? 0x0227 : (usage == AC_BOOKMARKS ? 0x022a : 0)))))))))))))))))))

static void send_extra(report_extra_t *report)
void bluetooth_send_consumer(uint16_t usage)
{
    if (report->report_id == REPORT_ID_CONSUMER) {
        uint16_t bitmap = CONSUMER2BLUEFRUIT(report->usage);
    uint16_t bitmap = CONSUMER2BLUEFRUIT(usage);

#ifdef BLUEFRUIT_TRACE_SERIAL
        dprintf("\nData: ");
        debug_hex16(data);
        dprintf("; bitmap: ");
        debug_hex16(bitmap);
        dprintf("\n");
        bluefruit_trace_header();
    dprintf("\nData: ");
    debug_hex16(data);
    dprintf("; bitmap: ");
    debug_hex16(bitmap);
    dprintf("\n");
    bluefruit_trace_header();
#endif
        send_str(PSTR("AT+BLEHIDCONTROLKEY=0x"));
        send_bytes((bitmap >> 8) & 0xFF);
        send_bytes(bitmap & 0xFF);
        send_str(PSTR("\r\n"));
    send_str(PSTR("AT+BLEHIDCONTROLKEY=0x"));
    send_bytes((bitmap >> 8) & 0xFF);
    send_bytes(bitmap & 0xFF);
    send_str(PSTR("\r\n"));
#ifdef BLUEFRUIT_TRACE_SERIAL
        bluefruit_trace_footer();
    bluefruit_trace_footer();
#endif
    }
}

void usart_init(void)

M keyboards/bioi/ble.h => keyboards/bioi/ble.h +0 -6
@@ 15,9 15,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once

#include <stdbool.h>
#include "host_driver.h"
#include "host.h"


typedef union {
  uint32_t raw;


@@ 28,9 25,6 @@ typedef union {

extern keyboard_config_t ble_config;

extern host_driver_t bluefruit_driver;
extern host_driver_t null_driver;

void send_str(const char *str);
void usart_init(void);
void module_reset(void);

M keyboards/bioi/g60/rules.mk => keyboards/bioi/g60/rules.mk +7 -8
@@ 1,14 1,6 @@
# Processor frequency
F_CPU = 8000000

SRC += usart.c \
       ble.c \
       main.c

OPT_DEFS += -DPROTOCOL_BLE
OPT_DEFS += -DUART_RX1_BUFFER_SIZE=16 -DUART_TX1_BUFFER_SIZE=16
OPT_DEFS += -DUSART1_ENABLED

# Build Options
#   change yes to no to disable
#


@@ 22,5 14,12 @@ BACKLIGHT_ENABLE = yes      # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = yes       # Enable keyboard RGB underglow
AUDIO_ENABLE = no           # Audio output
LTO_ENABLE = yes            # Reduce firmware size
BLUETOOTH_ENABLE = yes
BLUETOOTH_DRIVER = custom

VIA_ENABLE = yes            # VIA support should be enabled here due to the main() loop will be compiled first.

SRC += usart.c ble.c

OPT_DEFS += -DUART_RX1_BUFFER_SIZE=16 -DUART_TX1_BUFFER_SIZE=16
OPT_DEFS += -DUSART1_ENABLED

D keyboards/bioi/main.c => keyboards/bioi/main.c +0 -388
@@ 1,388 0,0 @@
/*
Copyright 2019 Basic I/O Instruments(Scott Wei) <scot.wei@gmail.com>
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 <avr/pgmspace.h>
#include <util/delay.h>

#include "report.h"
#include "host.h"
#include "host_driver.h"
#include "keyboard.h"
#include "action.h"
#include "led.h"
#include "sendchar.h"
#include "debug.h"
#include "print.h"
#ifdef SLEEP_LED_ENABLE
#include "sleep_led.h"
#endif
#include "suspend.h"

#include "usb_descriptor.h"
#include "lufa.h"
#include "quantum.h"
#include <util/atomic.h>

#ifdef NKRO_ENABLE
#include "keycode_config.h"

extern keymap_config_t keymap_config;
#endif

#ifdef AUDIO_ENABLE
#include <audio.h>
#endif

#ifdef BLUETOOTH_ENABLE
#ifdef BLUETOOTH_BLUEFRUIT_LE
#include "bluefruit_le.h"
#else
#include "bluetooth.h"
#endif
#endif

#ifdef VIRTSER_ENABLE
#include "virtser.h"
#endif

#if defined(RGBLIGHT_ENABLE)
#include "rgblight.h"
#endif

#ifdef MIDI_ENABLE
#include "qmk_midi.h"
#endif

#ifdef RAW_ENABLE
#include "raw_hid.h"
#endif

#include "ble.h"
#include "usart.h"

#include <avr/power.h>
#include <avr/sleep.h>

bool force_usb = false; //Reserved for FORCE USB Mode function.
bool force_ble = false; //Reserved for FORCE USB Mode function.

bool usb_connected = false;
bool ble_enabled = false;

uint32_t kb_idle_timer = 0;

bool usb_state_sent = false;

uint8_t USB_DeviceLastState = 0;

#ifdef RAW_ENABLE
/** \brief Raw HID Task
 *
 * FIXME: Needs doc
 */
static void raw_hid_task(void)
{
    // Create a temporary buffer to hold the read in data from the host
    uint8_t data[RAW_EPSIZE];
    bool data_read = false;

    // Device must be connected and configured for the task to run
    if (USB_DeviceState != DEVICE_STATE_Configured)
        return;

    Endpoint_SelectEndpoint(RAW_OUT_EPNUM);

    // Check to see if a packet has been sent from the host
    if (Endpoint_IsOUTReceived())
    {
        // Check to see if the packet contains data
        if (Endpoint_IsReadWriteAllowed())
        {
            /* Read data */
            Endpoint_Read_Stream_LE(data, sizeof(data), NULL);
            data_read = true;
        }

        // Finalize the stream transfer to receive the last packet
        Endpoint_ClearOUT();

        if (data_read)
        {
            raw_hid_receive(data, sizeof(data));
        }
    }
}
#endif

static void setup_mcu(void)
{
    /* Disable watchdog if enabled by bootloader/fuses */
    MCUSR &= ~(1 << WDRF);
    wdt_disable();

    CLKPR = (1 << CLKPCE);
    CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
}

static void setup_usb(void)
{
    // Leonardo needs. Without this USB device is not recognized.
    USB_Disable();

    USB_Init();

    // for Console_Task
    USB_Device_EnableSOFEvents();
    print_set_sendchar(sendchar);
}

void power_saving(void)
{
    power_adc_disable();
    power_usart0_disable();
    power_spi_disable();
    power_twi_disable();

    USBCON |= (1 << FRZCLK); // Freeze the USB Clock
    PLLCSR &= ~(1 << PLLE);  // Disable the USB Clock (PPL)
    USBCON &= ~(1 << USBE);
}

void power_recover(void)
{

    USBCON |= (1 << USBE);
    PLLCSR |= (1 << PLLE);    // Resume the USB Clock (PPL)
    USBCON &= ~(1 << FRZCLK); // Resume the USB Clock

    power_adc_enable();
    power_usart0_enable();
    power_spi_enable();
    power_twi_enable();
}

void ble_task_init(void)
{
    kb_idle_timer = timer_read32();  //Mark current time, reserved for further usage;
}

void ble_task(void)
{

    if (USB_DeviceLastState != USB_DeviceState)
    {
        usb_state_sent = false;
#ifdef BLE_DEBUG
        send_str(PSTR("USB State Changed\r\n"));
        if (USB_DeviceState == DEVICE_STATE_Unattached)
        {
            send_str(PSTR("USB State Unattached\r\n"));
        }
#endif
        if (USB_DeviceState == DEVICE_STATE_Powered)
        {
#ifdef BLE_DEBUG
            send_str(PSTR("USB State Powered\r\n"));
#endif
            power_recover();
            host_set_driver(&null_driver);
        }
#ifdef BLE_DEBUG
        if ((USB_DeviceState == DEVICE_STATE_Default))
        {
            send_str(PSTR("USB State Default\r\n"));
        }
        if ((USB_DeviceState == DEVICE_STATE_Addressed))
        {
            send_str(PSTR("USB State Addressed\r\n"));
        }
        if (USB_DeviceState == DEVICE_STATE_Configured)
        {
            send_str(PSTR("USB State Configured\r\n"));
        }
        if (USB_DeviceState > DEVICE_STATE_Unattached)
        {
        }
        else
        {
            //
        }
#endif
    }
    else
    {
#ifdef BLE_DEBUG
        if (!usb_state_sent)
        {
            if (USB_DeviceState == DEVICE_STATE_Unattached)
            {
                send_str(PSTR("USB State Stopped at Unattached\r\n"));
            }
            if (USB_DeviceState == DEVICE_STATE_Powered)
            {
                send_str(PSTR("USB State Stopped at Powered\r\n"));
            }
            if ((USB_DeviceState == DEVICE_STATE_Default))
            {
                send_str(PSTR("USB State Stopped at Default\r\n"));
            }
            if ((USB_DeviceState == DEVICE_STATE_Addressed))
            {
                send_str(PSTR("USB State Stopped at Addressed\r\n"));
            }
            if (USB_DeviceState == DEVICE_STATE_Configured)
            {
                send_str(PSTR("USB State Stopped at Configured\r\n"));
            }
        }
#endif
        if (USB_DeviceState == DEVICE_STATE_Unattached)
        {
            if (host_get_driver() && host_get_driver() != &bluefruit_driver)
            {
#ifdef BLE_DEBUG
                send_str(PSTR("USB State stopped at Unattached\r\n"));
#endif
                ble_task_init();

                force_usb = 0;
                usb_connected = 0;

                //Reinit USB to prepare for next connection.
                USB_Init();
                USB_Detach();
                USB_Attach();

#ifdef BLE_DEBUG
                send_str(PSTR("Loading &bluefruit_driver\r\n"));
#endif
                host_set_driver(&bluefruit_driver);
                clear_keyboard();
                power_saving();
            }
            else
            {
                //Do nothing if USB is unattached and the driver is &bluefruit_driver
            }
        }
        if (USB_DeviceState == DEVICE_STATE_Configured)
        {
            if (host_get_driver() && host_get_driver() != &lufa_driver)
            {
#ifdef BLE_DEBUG
                send_str(PSTR("USB State stopped at Configured\r\n"));
#endif
                power_recover();

                usb_connected = 1;
                ble_enabled = 0;
#ifdef BLE_DEBUG
                send_str(PSTR("Loading &lufa_driver\r\n"));
#endif
                host_set_driver(&lufa_driver);
                clear_keyboard();
            }
            else
            {
                //Do nothing if the driver is &lufa_driver
            }
        }

        usb_state_sent = true;
    }

    USB_DeviceLastState = USB_DeviceState;
}

// Use a custom main() function because the task logic is different from the common one.
int main(void)
{
#ifdef MIDI_ENABLE
    setup_midi();
#endif

    setup_mcu();

    keyboard_setup();

    setup_usb();
    sei();

#if defined(BLUETOOTH_RN42)
    serial_init();
#endif

    /* wait for USB startup to get ready for debug output */
    uint8_t timeout = 255; // timeout when USB is not available(Bluetooth)
    while (timeout-- && USB_DeviceState != DEVICE_STATE_Configured)
    {
        wait_ms(4);
#if defined(INTERRUPT_CONTROL_ENDPOINT)
        ;
#else
        USB_USBTask();
#endif
    }

    print("\nUSB init\n");

    keyboard_init();
    host_set_driver(&lufa_driver);

    backlight_disable();
    //host_set_driver(&lufa_driver);
    print("Keyboard initialized.\n");

    //Init Hardware UART
    usart_init();

#ifdef BLE_DEBUG
    send_str(PSTR("Keyboard has been setup up\r\n"));

    if (usb_connected)
    {
        send_str(PSTR("usb_connected=1\r\n"));
    }
    else
    {
        send_str(PSTR("usb_connected=0\r\n"));
    }
#endif

#ifdef SLEEP_LED_ENABLE
    sleep_led_init();
#endif

#ifdef VIRTSER_ENABLE
    virtser_init();
#endif

    while (1)
    {
        ble_task();
        keyboard_task();

#ifdef RAW_ENABLE
        raw_hid_task();
#endif

#if defined(RGBLIGHT_ENABLE)
        rgblight_task();
#endif

#if !defined(INTERRUPT_CONTROL_ENDPOINT)
        USB_USBTask();
#endif
    }
}

M keyboards/bioi/morgan65/rules.mk => keyboards/bioi/morgan65/rules.mk +7 -8
@@ 1,14 1,6 @@
# Processor frequency
F_CPU = 8000000

SRC += usart.c \
       ble.c \
       main.c

OPT_DEFS += -DPROTOCOL_BLE
OPT_DEFS += -DUART_RX1_BUFFER_SIZE=16 -DUART_TX1_BUFFER_SIZE=16
OPT_DEFS += -DUSART1_ENABLED

# Build Options
#   change yes to no to disable
#


@@ 22,5 14,12 @@ BACKLIGHT_ENABLE = yes      # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = yes       # Enable keyboard RGB underglow
AUDIO_ENABLE = no           # Audio output
LTO_ENABLE = yes            # Reduce firmware size
BLUETOOTH_ENABLE = yes
BLUETOOTH_DRIVER = custom

VIA_ENABLE = yes            # VIA support should be enabled here due to the main() loop will be compiled first.

SRC += usart.c ble.c

OPT_DEFS += -DUART_RX1_BUFFER_SIZE=16 -DUART_TX1_BUFFER_SIZE=16
OPT_DEFS += -DUSART1_ENABLED