mirror of
https://github.com/google/pebble.git
synced 2026-02-11 07:57:19 -05:00
155 lines
4.2 KiB
C
155 lines
4.2 KiB
C
/*
|
|
* Copyright 2024 Google LLC
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "serial_console.h"
|
|
|
|
#include "console/dbgserial_input.h"
|
|
#include "console/pulse_protocol_impl.h"
|
|
#include "console_internal.h"
|
|
#include "prompt.h"
|
|
#include "ui_nudge.h"
|
|
|
|
#include "console/pulse_internal.h"
|
|
#include "drivers/mic.h"
|
|
#include "drivers/watchdog.h"
|
|
#include "kernel/util/stop.h"
|
|
#include "os/tick.h"
|
|
#include "system/logging.h"
|
|
#include "system/passert.h"
|
|
|
|
#include <bluetooth/bt_test.h>
|
|
|
|
SerialConsoleState s_serial_console_state = SERIAL_CONSOLE_STATE_LOGGING;
|
|
static bool s_serial_console_initialized;
|
|
|
|
static bool s_prompt_enabled = false;
|
|
|
|
static void logging_handle_character(char c, bool* should_context_switch) {
|
|
#ifdef DISABLE_PROMPT
|
|
return;
|
|
#endif
|
|
// Remember, you're in an interrupt here!
|
|
|
|
if (c == 0x3) { // CTRL-C
|
|
if (!s_prompt_enabled) {
|
|
PBL_LOG(LOG_LEVEL_DEBUG, "Ignoring prompt request, not yet ready!");
|
|
return;
|
|
}
|
|
console_switch_to_prompt();
|
|
}
|
|
}
|
|
|
|
void serial_console_init(void) {
|
|
if (s_serial_console_initialized) {
|
|
return;
|
|
}
|
|
|
|
dbgserial_register_character_callback(logging_handle_character);
|
|
|
|
s_serial_console_state = SERIAL_CONSOLE_STATE_LOGGING;
|
|
s_serial_console_initialized = true;
|
|
}
|
|
|
|
bool serial_console_is_prompt_enabled(void) {
|
|
if (!s_serial_console_initialized) {
|
|
return false;
|
|
}
|
|
|
|
return (s_serial_console_state == SERIAL_CONSOLE_STATE_PROMPT);
|
|
}
|
|
|
|
bool serial_console_is_logging_enabled(void) {
|
|
if (!s_serial_console_initialized) {
|
|
return true;
|
|
}
|
|
|
|
return s_serial_console_state == SERIAL_CONSOLE_STATE_LOGGING ||
|
|
s_serial_console_state == SERIAL_CONSOLE_STATE_PULSE;
|
|
}
|
|
|
|
void serial_console_enable_prompt(void) {
|
|
s_prompt_enabled = true;
|
|
}
|
|
|
|
void serial_console_write_log_message(const char* msg) {
|
|
while (*msg) {
|
|
dbgserial_putchar(*(msg++));
|
|
}
|
|
}
|
|
|
|
void serial_console_set_state(SerialConsoleState new_state) {
|
|
PBL_ASSERTN(s_serial_console_initialized);
|
|
PBL_ASSERTN(new_state < SERIAL_CONSOLE_NUM_STATES);
|
|
|
|
// This function is called from the USART3 IRQ, the new timer thread,
|
|
// and the system task. It thus needs a critical section.
|
|
portENTER_CRITICAL();
|
|
|
|
if (new_state == s_serial_console_state) {
|
|
portEXIT_CRITICAL();
|
|
return;
|
|
}
|
|
|
|
#if !PULSE_EVERYWHERE
|
|
if (new_state == SERIAL_CONSOLE_STATE_LOGGING) {
|
|
stop_mode_enable(InhibitorDbgSerial);
|
|
dbgserial_enable_rx_exti();
|
|
} else if (s_serial_console_state == SERIAL_CONSOLE_STATE_LOGGING) {
|
|
stop_mode_disable(InhibitorDbgSerial);
|
|
}
|
|
#endif
|
|
|
|
s_serial_console_state = new_state;
|
|
|
|
switch (s_serial_console_state) {
|
|
#if !DISABLE_PROMPT
|
|
case SERIAL_CONSOLE_STATE_PROMPT:
|
|
dbgserial_register_character_callback(prompt_handle_character);
|
|
dbgserial_set_rx_dma_enabled(false);
|
|
break;
|
|
#endif
|
|
case SERIAL_CONSOLE_STATE_LOGGING:
|
|
dbgserial_register_character_callback(logging_handle_character);
|
|
dbgserial_set_rx_dma_enabled(false);
|
|
break;
|
|
#ifdef UI_DEBUG
|
|
case SERIAL_CONSOLE_STATE_LAYER_NUDGING:
|
|
dbgserial_register_character_callback(layer_debug_nudging_handle_character);
|
|
dbgserial_set_rx_dma_enabled(false);
|
|
break;
|
|
#endif
|
|
case SERIAL_CONSOLE_STATE_HCI_PASSTHROUGH:
|
|
dbgserial_register_character_callback(bt_driver_test_handle_hci_passthrough_character);
|
|
dbgserial_set_rx_dma_enabled(false);
|
|
break;
|
|
case SERIAL_CONSOLE_STATE_PULSE:
|
|
dbgserial_register_character_callback(pulse_handle_character);
|
|
dbgserial_set_rx_dma_enabled(true);
|
|
break;
|
|
default:
|
|
WTF; // Don't know this state
|
|
}
|
|
|
|
portEXIT_CRITICAL();
|
|
}
|
|
|
|
SerialConsoleState serial_console_get_state(void) {
|
|
SerialConsoleState state = __atomic_load_n(&s_serial_console_state, __ATOMIC_RELAXED);
|
|
|
|
return state;
|
|
}
|
|
|