~ruther/qmk_firmware

96e2b13d1de227cdc2b918fb0292bd832d346a25 — Joel Challis 4 years ago 4c9003b
Begin to carve out platform/protocol API - Single main loop (#13843)

* Begin to carve out platform/protocol API

* Fix up after rebase
M build_keyboard.mk => build_keyboard.mk +4 -2
@@ 338,9 338,11 @@ ifneq ("$(wildcard $(KEYMAP_PATH)/config.h)","")
endif

# project specific files
SRC += $(KEYBOARD_SRC) \
SRC += \
    $(KEYBOARD_SRC) \
    $(KEYMAP_C) \
    $(QUANTUM_SRC)
    $(QUANTUM_SRC) \
    $(QUANTUM_DIR)/main.c \

# Optimize size but this may cause error "relocation truncated to fit"
#EXTRALDFLAGS = -Wl,--relax

A quantum/main.c => quantum/main.c +41 -0
@@ 0,0 1,41 @@
/* Copyright 2021 QMK
 *
 * 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 3 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 "keyboard.h"

void platform_setup(void);

void protocol_setup(void);
void protocol_init(void);
void protocol_task(void);

/** \brief Main
 *
 * FIXME: Needs doc
 */
int main(void) __attribute__((weak));
int main(void) {
    platform_setup();
    protocol_setup();

    protocol_init();

    /* Main loop */
    while (true) {
        protocol_task();
        housekeeping_task();
    }
}

M tmk_core/common.mk => tmk_core/common.mk +1 -0
@@ 12,6 12,7 @@ TMK_COMMON_SRC +=	$(COMMON_DIR)/host.c \
	$(COMMON_DIR)/report.c \
	$(COMMON_DIR)/sync_timer.c \
	$(COMMON_DIR)/usb_util.c \
	$(PLATFORM_COMMON_DIR)/platform.c \
	$(PLATFORM_COMMON_DIR)/suspend.c \
	$(PLATFORM_COMMON_DIR)/timer.c \
	$(PLATFORM_COMMON_DIR)/bootloader.c \

A tmk_core/common/arm_atsam/platform.c => tmk_core/common/arm_atsam/platform.c +21 -0
@@ 0,0 1,21 @@
/* Copyright 2021 QMK
 *
 * 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 3 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 "platform_deps.h"

void platform_setup(void) {
    // do nothing
}

A tmk_core/common/avr/platform.c => tmk_core/common/avr/platform.c +21 -0
@@ 0,0 1,21 @@
/* Copyright 2021 QMK
 *
 * 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 3 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 "platform_deps.h"

void platform_setup(void) {
    // do nothing
}

A tmk_core/common/chibios/platform.c => tmk_core/common/chibios/platform.c +22 -0
@@ 0,0 1,22 @@
/* Copyright 2021 QMK
 *
 * 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 3 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 "platform_deps.h"

void platform_setup(void) {
    halInit();
    chSysInit();
}
\ No newline at end of file

A tmk_core/common/test/platform.c => tmk_core/common/test/platform.c +21 -0
@@ 0,0 1,21 @@
/* Copyright 2021 QMK
 *
 * 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 3 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 "platform_deps.h"

void platform_setup(void) {
    // do nothing
}
\ No newline at end of file

M tmk_core/protocol/chibios.mk => tmk_core/protocol/chibios.mk +1 -1
@@ 3,7 3,7 @@ CHIBIOS_DIR = $(PROTOCOL_DIR)/chibios


SRC += $(CHIBIOS_DIR)/usb_main.c
SRC += $(CHIBIOS_DIR)/main.c
SRC += $(CHIBIOS_DIR)/chibios.c
SRC += usb_descriptor.c
SRC += $(CHIBIOS_DIR)/usb_driver.c
SRC += $(CHIBIOS_DIR)/usb_util.c

R tmk_core/protocol/chibios/main.c => tmk_core/protocol/chibios/chibios.c +29 -37
@@ 138,18 138,14 @@ void boardInit(void) {
    board_init();
}

/* Main thread
 */
int main(void) {
    /* ChibiOS/RT init */
    halInit();
    chSysInit();

void protocol_setup(void) {
    // TESTING
    // chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);

    keyboard_setup();
}

void protocol_init(void) {
    /* Init USB */
    usb_event_queue_init();
    init_usb_driver(&USB_DRIVER);


@@ 207,57 203,53 @@ int main(void) {
#endif

    print("Keyboard start.\n");
}

    /* Main loop */
    while (true) {
        usb_event_queue_task();
void protocol_task(void) {
    usb_event_queue_task();

#if !defined(NO_USB_STARTUP_CHECK)
        if (USB_DRIVER.state == USB_SUSPENDED) {
            print("[s]");
    if (USB_DRIVER.state == USB_SUSPENDED) {
        print("[s]");
#    ifdef VISUALIZER_ENABLE
            visualizer_suspend();
        visualizer_suspend();
#    endif
            while (USB_DRIVER.state == USB_SUSPENDED) {
                /* Do this in the suspended state */
        while (USB_DRIVER.state == USB_SUSPENDED) {
            /* Do this in the suspended state */
#    ifdef SERIAL_LINK_ENABLE
                serial_link_update();
            serial_link_update();
#    endif
                suspend_power_down();  // on AVR this deep sleeps for 15ms
                /* Remote wakeup */
                if (suspend_wakeup_condition()) {
                    usbWakeupHost(&USB_DRIVER);
                    restart_usb_driver(&USB_DRIVER);
                }
            suspend_power_down();  // on AVR this deep sleeps for 15ms
            /* Remote wakeup */
            if (suspend_wakeup_condition()) {
                usbWakeupHost(&USB_DRIVER);
                restart_usb_driver(&USB_DRIVER);
            }
            /* Woken up */
            // variables has been already cleared by the wakeup hook
            send_keyboard_report();
        }
        /* Woken up */
        // variables has been already cleared by the wakeup hook
        send_keyboard_report();
#    ifdef MOUSEKEY_ENABLE
            mousekey_send();
        mousekey_send();
#    endif /* MOUSEKEY_ENABLE */

#    ifdef VISUALIZER_ENABLE
            visualizer_resume();
        visualizer_resume();
#    endif
        }
    }
#endif

        keyboard_task();
    keyboard_task();
#ifdef CONSOLE_ENABLE
        console_task();
    console_task();
#endif
#ifdef MIDI_ENABLE
        midi_ep_task();
    midi_ep_task();
#endif
#ifdef VIRTSER_ENABLE
        virtser_task();
    virtser_task();
#endif
#ifdef RAW_ENABLE
        raw_hid_task();
    raw_hid_task();
#endif

        // Run housekeeping
        housekeeping_task();
    }
}

M tmk_core/protocol/lufa/lufa.c => tmk_core/protocol/lufa/lufa.c +30 -34
@@ 1033,18 1033,16 @@ static void setup_usb(void) {
    USB_Device_EnableSOFEvents();
}

/** \brief Main
 *
 * FIXME: Needs doc
 */
int main(void) __attribute__((weak));
int main(void) {
void protocol_setup(void) {
#ifdef MIDI_ENABLE
    setup_midi();
#endif

    setup_mcu();
    keyboard_setup();
}

void protocol_init(void) {
    setup_usb();
    sei();



@@ 1078,57 1076,55 @@ int main(void) {
#endif

    print("Keyboard start.\n");
    while (1) {
}

void protocol_task(void) {
#if !defined(NO_USB_STARTUP_CHECK)
        if (USB_DeviceState == DEVICE_STATE_Suspended) {
            print("[s]");
            while (USB_DeviceState == DEVICE_STATE_Suspended) {
                suspend_power_down();
                if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
                    USB_Device_SendRemoteWakeup();
                    clear_keyboard();
    if (USB_DeviceState == DEVICE_STATE_Suspended) {
        print("[s]");
        while (USB_DeviceState == DEVICE_STATE_Suspended) {
            suspend_power_down();
            if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
                USB_Device_SendRemoteWakeup();
                clear_keyboard();

#    if USB_SUSPEND_WAKEUP_DELAY > 0
                    // Some hubs, kvm switches, and monitors do
                    // weird things, with USB device state bouncing
                    // around wildly on wakeup, yielding race
                    // conditions that can corrupt the keyboard state.
                    //
                    // Pause for a while to let things settle...
                    wait_ms(USB_SUSPEND_WAKEUP_DELAY);
                // Some hubs, kvm switches, and monitors do
                // weird things, with USB device state bouncing
                // around wildly on wakeup, yielding race
                // conditions that can corrupt the keyboard state.
                //
                // Pause for a while to let things settle...
                wait_ms(USB_SUSPEND_WAKEUP_DELAY);
#    endif
                }
            }
            suspend_wakeup_init();
        }
        suspend_wakeup_init();
    }
#endif

        keyboard_task();
    keyboard_task();

#ifdef MIDI_ENABLE
        MIDI_Device_USBTask(&USB_MIDI_Interface);
    MIDI_Device_USBTask(&USB_MIDI_Interface);
#endif

#ifdef MODULE_ADAFRUIT_BLE
        adafruit_ble_task();
    adafruit_ble_task();
#endif

#ifdef VIRTSER_ENABLE
        virtser_task();
        CDC_Device_USBTask(&cdc_device);
    virtser_task();
    CDC_Device_USBTask(&cdc_device);
#endif

#ifdef RAW_ENABLE
        raw_hid_task();
    raw_hid_task();
#endif

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

        // Run housekeeping
        housekeeping_task();
    }
}

uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint16_t wIndex, const void **const DescriptorAddress) { return get_usb_descriptor(wValue, wIndex, DescriptorAddress); }

M tmk_core/protocol/vusb.mk => tmk_core/protocol/vusb.mk +1 -1
@@ 3,7 3,7 @@ VUSB_DIR = protocol/vusb
# Path to the V-USB library
VUSB_PATH = $(LIB_PATH)/vusb

SRC += $(VUSB_DIR)/main.c \
SRC += $(VUSB_DIR)/protocol.c \
	$(VUSB_DIR)/vusb.c \
	$(VUSB_DIR)/usb_util.c \
	$(VUSB_PATH)/usbdrv/usbdrv.c \

R tmk_core/protocol/vusb/main.c => tmk_core/protocol/vusb/protocol.c +44 -45
@@ 99,14 99,11 @@ static void vusb_wakeup(void) {
 */
static void setup_usb(void) { initForUsbConnectivity(); }

/** \brief Main
 *
 * FIXME: Needs doc
 */
int main(void) __attribute__((weak));
int main(void) {
uint16_t sof_timer = 0;

void protocol_setup(void) {
#if USB_COUNT_SOF
    uint16_t sof_timer = timer_read();
    sof_timer = timer_read();
#endif

#ifdef CLKPR


@@ 115,9 112,14 @@ int main(void) {
    clock_prescale_set(clock_div_1);
#endif
    keyboard_setup();
}

void protocol_init(void) {
    setup_usb();
    sei();

    keyboard_init();

    host_set_driver(vusb_driver());

    wait_ms(50);


@@ 125,55 127,52 @@ int main(void) {
#ifdef SLEEP_LED_ENABLE
    sleep_led_init();
#endif
}

    while (1) {
void protocol_task(void) {
#if USB_COUNT_SOF
        if (usbSofCount != 0) {
            usbSofCount = 0;
            sof_timer   = timer_read();
            if (vusb_suspended) {
                vusb_wakeup();
            }
        } else {
            // Suspend when no SOF in 3ms-10ms(7.1.7.4 Suspending of USB1.1)
            if (!vusb_suspended && timer_elapsed(sof_timer) > 5) {
                vusb_suspend();
            }
        }
#endif
    if (usbSofCount != 0) {
        usbSofCount = 0;
        sof_timer   = timer_read();
        if (vusb_suspended) {
            vusb_wakeup();
        }
    } else {
        // Suspend when no SOF in 3ms-10ms(7.1.7.4 Suspending of USB1.1)
        if (!vusb_suspended && timer_elapsed(sof_timer) > 5) {
            vusb_suspend();
            if (suspend_wakeup_condition()) {
                vusb_send_remote_wakeup();
            }
        } else {
            usbPoll();

            // TODO: configuration process is inconsistent. it sometime fails.
            // To prevent failing to configure NOT scan keyboard during configuration
            if (usbConfiguration && usbInterruptIsReady()) {
                keyboard_task();
            }
            vusb_transfer_keyboard();
        }
    }
#endif
    if (vusb_suspended) {
        vusb_suspend();
        if (suspend_wakeup_condition()) {
            vusb_send_remote_wakeup();
        }
    } else {
        usbPoll();

        // TODO: configuration process is inconsistent. it sometime fails.
        // To prevent failing to configure NOT scan keyboard during configuration
        if (usbConfiguration && usbInterruptIsReady()) {
            keyboard_task();
        }
        vusb_transfer_keyboard();

#ifdef RAW_ENABLE
            usbPoll();
        usbPoll();

            if (usbConfiguration && usbInterruptIsReady3()) {
                raw_hid_task();
            }
        if (usbConfiguration && usbInterruptIsReady3()) {
            raw_hid_task();
        }
#endif

#ifdef CONSOLE_ENABLE
            usbPoll();
        usbPoll();

            if (usbConfiguration && usbInterruptIsReady3()) {
                console_task();
            }
#endif

            // Run housekeeping
            housekeeping_task();
        if (usbConfiguration && usbInterruptIsReady3()) {
            console_task();
        }
#endif
    }
}