Compare commits

...

2 Commits

Author SHA1 Message Date
6a03df1b39 feat(events): 添加传输策略事件支持
添加了新的 transport_policy_event 事件类型,用于管理 HID
传输策略和蓝牙配置文件策略。该事件包含源模式、HID 传输策
略和蓝牙配置文件策略三个枚举值,并提供了相应的提交函数
和日志记录功能。

BREAKING CHANGE: 将原有的 mode_switch_event 替换为更具体的
transport_policy_event,相关模块需要更新以使用新的事件类
型。
2026-04-23 09:48:06 +08:00
a11f4c0110 feat(usb_cdc): 添加USB CDC ACM控制台和日志后端支持
添加zephyr,console和zephyr,log-uart设备树配置,启用UART控制台和日志功能,
同时增加第二个CDC ACM UART实例用于控制台输出。在prj.conf中启用相关配置项。

refactor(protocol): 优化协议会话状态管理并增强日志记录

引入proto_session_set函数统一管理协议会话状态转换,添加详细的日志输出来跟踪
状态变化、消息处理和传输事件,提高系统的可调试性。

feat(usb_device): 增强USB设备模块状态跟踪和日志输出

为USB栈、总线和公共状态添加命名函数,实现详细的状态转换日志记录,包括USB
连接、断开、使能等关键事件的日志输出,便于系统调试和问题排查。
2026-04-21 16:40:37 +08:00
11 changed files with 554 additions and 60 deletions

View File

@@ -60,6 +60,7 @@ target_sources(app PRIVATE
src/events/set_protocol_event.c src/events/set_protocol_event.c
src/events/theme_rgb_update_event.c src/events/theme_rgb_update_event.c
src/events/time_sync_event.c src/events/time_sync_event.c
src/events/transport_policy_event.c
src/events/usb_control_event.c src/events/usb_control_event.c
src/events/usb_state_event.c src/events/usb_state_event.c
) )

View File

@@ -16,6 +16,8 @@
zephyr,code-partition = &slot0_partition; zephyr,code-partition = &slot0_partition;
zephyr,display = &screen_lcd; zephyr,display = &screen_lcd;
zephyr,led-strip = &led_strip; zephyr,led-strip = &led_strip;
zephyr,console = &cdc_acm_uart1;
zephyr,log-uart = &log_uarts;
}; };
aliases { aliases {
@@ -25,6 +27,11 @@
backlight = &backlight; backlight = &backlight;
}; };
log_uarts: log_uarts {
compatible = "zephyr,log-uart";
uarts = <&cdc_acm_uart1>;
};
hid_kbd: hid_kbd { hid_kbd: hid_kbd {
compatible = "zephyr,hid-device"; compatible = "zephyr,hid-device";
label = "HID_KBD"; label = "HID_KBD";
@@ -260,4 +267,9 @@
compatible = "zephyr,cdc-acm-uart"; compatible = "zephyr,cdc-acm-uart";
label = "CDC_ACM_0"; label = "CDC_ACM_0";
}; };
cdc_acm_uart1: cdc_acm_uart1 {
compatible = "zephyr,cdc-acm-uart";
label = "CDC_ACM_1";
};
}; };

View File

@@ -0,0 +1,42 @@
#ifndef BLINKY_TRANSPORT_POLICY_EVENT_H_
#define BLINKY_TRANSPORT_POLICY_EVENT_H_
#include <app_event_manager.h>
#include "mode_switch_event.h"
enum hid_transport_policy {
HID_TRANSPORT_POLICY_NONE = 0,
HID_TRANSPORT_POLICY_USB,
HID_TRANSPORT_POLICY_BLE,
};
enum ble_profile_policy {
BLE_PROFILE_POLICY_NONE = 0,
BLE_PROFILE_POLICY_GENERAL,
BLE_PROFILE_POLICY_DONGLE,
};
struct transport_policy_event {
struct app_event_header header;
enum mode_switch_mode source_mode;
enum hid_transport_policy hid_transport;
enum ble_profile_policy ble_profile;
};
APP_EVENT_TYPE_DECLARE(transport_policy_event);
static inline void submit_transport_policy_event(
enum mode_switch_mode source_mode,
enum hid_transport_policy hid_transport,
enum ble_profile_policy ble_profile)
{
struct transport_policy_event *event = new_transport_policy_event();
event->source_mode = source_mode;
event->hid_transport = hid_transport;
event->ble_profile = ble_profile;
APP_EVENT_SUBMIT(event);
}
#endif /* BLINKY_TRANSPORT_POLICY_EVENT_H_ */

View File

@@ -27,12 +27,18 @@ CONFIG_NVS=y
CONFIG_HEAP_MEM_POOL_SIZE=4096 CONFIG_HEAP_MEM_POOL_SIZE=4096
CONFIG_LOG=y CONFIG_LOG=y
CONFIG_LOG_BUFFER_SIZE=16384 CONFIG_LOG_BUFFER_SIZE=16384
CONFIG_LOG_BACKEND_UART=y
CONFIG_LOG_BACKEND_SHOW_COLOR=n
CONFIG_LOG_BACKEND_RTT_OUTPUT_BUFFER_SIZE=16384 CONFIG_LOG_BACKEND_RTT_OUTPUT_BUFFER_SIZE=16384
CONFIG_ASSERT=y CONFIG_ASSERT=y
CONFIG_SEGGER_RTT_BUFFER_SIZE_UP=16384 CONFIG_SEGGER_RTT_BUFFER_SIZE_UP=16384
CONFIG_APP_EVENT_MANAGER_MAX_EVENT_CNT=64 CONFIG_APP_EVENT_MANAGER_MAX_EVENT_CNT=64
CONFIG_LED_STRIP=y CONFIG_LED_STRIP=y
CONFIG_WS2812_STRIP_SPI=y CONFIG_WS2812_STRIP_SPI=y
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
CONFIG_STDOUT_CONSOLE=y
CONFIG_PRINTK=y
# USB HID next stack # USB HID next stack
CONFIG_USB_DEVICE_STACK_NEXT=y CONFIG_USB_DEVICE_STACK_NEXT=y

View File

@@ -0,0 +1,78 @@
#include "transport_policy_event.h"
static const char *source_mode_name(enum mode_switch_mode mode)
{
switch (mode) {
case MODE_SWITCH_USB:
return "USB";
case MODE_SWITCH_BLE:
return "BLE";
case MODE_SWITCH_24G:
return "24G";
default:
return "?";
}
}
static const char *hid_transport_policy_name(enum hid_transport_policy transport)
{
switch (transport) {
case HID_TRANSPORT_POLICY_NONE:
return "none";
case HID_TRANSPORT_POLICY_USB:
return "usb";
case HID_TRANSPORT_POLICY_BLE:
return "ble";
default:
return "?";
}
}
static const char *ble_profile_policy_name(enum ble_profile_policy profile)
{
switch (profile) {
case BLE_PROFILE_POLICY_NONE:
return "none";
case BLE_PROFILE_POLICY_GENERAL:
return "general";
case BLE_PROFILE_POLICY_DONGLE:
return "dongle";
default:
return "?";
}
}
static void log_transport_policy_event(const struct app_event_header *aeh)
{
const struct transport_policy_event *event =
cast_transport_policy_event(aeh);
APP_EVENT_MANAGER_LOG(aeh, "source:%s hid:%s ble:%s",
source_mode_name(event->source_mode),
hid_transport_policy_name(event->hid_transport),
ble_profile_policy_name(event->ble_profile));
}
static void profile_transport_policy_event(struct log_event_buf *buf,
const struct app_event_header *aeh)
{
const struct transport_policy_event *event =
cast_transport_policy_event(aeh);
nrf_profiler_log_encode_uint8(buf, event->source_mode);
nrf_profiler_log_encode_uint8(buf, event->hid_transport);
nrf_profiler_log_encode_uint8(buf, event->ble_profile);
}
APP_EVENT_INFO_DEFINE(transport_policy_event,
ENCODE(NRF_PROFILER_ARG_U8, NRF_PROFILER_ARG_U8,
NRF_PROFILER_ARG_U8),
ENCODE("source_mode", "hid_transport", "ble_profile"),
profile_transport_policy_event);
APP_EVENT_TYPE_DEFINE(transport_policy_event,
log_transport_policy_event,
&transport_policy_event_info,
APP_EVENT_FLAGS_CREATE(
IF_ENABLED(CONFIG_BRIDGE_LOG_TRANSPORT_POLICY_EVENT,
(APP_EVENT_TYPE_FLAGS_INIT_LOG_ENABLE))));

View File

@@ -16,7 +16,7 @@
#include "keyboard_core.h" #include "keyboard_core.h"
#include "keyboard_hid_report_event.h" #include "keyboard_hid_report_event.h"
#include "module_lifecycle.h" #include "module_lifecycle.h"
#include "mode_switch_event.h" #include "transport_policy_event.h"
LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF); LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF);
@@ -60,7 +60,7 @@ struct hid_flowctrl_module_ctx {
uint8_t consumer_fifo_tail; uint8_t consumer_fifo_tail;
uint8_t consumer_fifo_count; uint8_t consumer_fifo_count;
struct in_flight_report in_flight[HID_SEND_CH_COUNT]; struct in_flight_report in_flight[HID_SEND_CH_COUNT];
enum mode_switch_mode current_mode; enum hid_transport_policy current_transport;
uint16_t next_sequence; uint16_t next_sequence;
}; };
@@ -107,25 +107,25 @@ static struct hid_flowctrl_module_ctx ctx = {
#define consumer_fifo_tail ctx.consumer_fifo_tail #define consumer_fifo_tail ctx.consumer_fifo_tail
#define consumer_fifo_count ctx.consumer_fifo_count #define consumer_fifo_count ctx.consumer_fifo_count
#define in_flight ctx.in_flight #define in_flight ctx.in_flight
#define current_mode ctx.current_mode #define current_transport ctx.current_transport
#define next_sequence ctx.next_sequence #define next_sequence ctx.next_sequence
#define running module_lifecycle_is_running(&ctx.lc) #define running module_lifecycle_is_running(&ctx.lc)
static bool current_mode_to_channel(enum keyboard_report_type report_type, static bool current_transport_to_channel(enum keyboard_report_type report_type,
enum hid_send_channel *channel) enum hid_send_channel *channel)
{ {
if (channel == NULL) { if (channel == NULL) {
return false; return false;
} }
switch (current_mode) { switch (current_transport) {
case MODE_SWITCH_USB: case HID_TRANSPORT_POLICY_USB:
*channel = (report_type == KEYBOARD_REPORT_TYPE_KEYS) ? *channel = (report_type == KEYBOARD_REPORT_TYPE_KEYS) ?
HID_SEND_CH_USB_KEYS : HID_SEND_CH_USB_KEYS :
HID_SEND_CH_USB_CONSUMER; HID_SEND_CH_USB_CONSUMER;
return true; return true;
case MODE_SWITCH_BLE: case HID_TRANSPORT_POLICY_BLE:
*channel = HID_SEND_CH_BLE_SHARED; *channel = HID_SEND_CH_BLE_SHARED;
return true; return true;
@@ -209,7 +209,7 @@ static void try_send_keys(void)
return; return;
} }
if (!current_mode_to_channel(KEYBOARD_REPORT_TYPE_KEYS, &channel)) { if (!current_transport_to_channel(KEYBOARD_REPORT_TYPE_KEYS, &channel)) {
return; return;
} }
@@ -238,7 +238,7 @@ static void try_send_consumer_fifo(void)
return; return;
} }
if (!current_mode_to_channel(KEYBOARD_REPORT_TYPE_CONSUMER, &channel)) { if (!current_transport_to_channel(KEYBOARD_REPORT_TYPE_CONSUMER, &channel)) {
return; return;
} }
@@ -273,7 +273,7 @@ static void try_send_consumer_latest(void)
return; return;
} }
if (!current_mode_to_channel(KEYBOARD_REPORT_TYPE_CONSUMER, &channel)) { if (!current_transport_to_channel(KEYBOARD_REPORT_TYPE_CONSUMER, &channel)) {
return; return;
} }
@@ -383,14 +383,15 @@ static bool handle_hid_report_sent_event(const struct hid_report_sent_event *eve
return false; return false;
} }
static bool handle_mode_switch_event(const struct mode_switch_event *event) static bool handle_transport_policy_event(
const struct transport_policy_event *event)
{ {
bool mode_changed = (current_mode != event->mode); bool transport_changed = (current_transport != event->hid_transport);
current_mode = event->mode; current_transport = event->hid_transport;
if (mode_changed || ((current_mode != MODE_SWITCH_USB) && if (transport_changed ||
(current_mode != MODE_SWITCH_BLE))) { (current_transport == HID_TRANSPORT_POLICY_NONE)) {
clear_pending_reports(); clear_pending_reports();
} }
@@ -401,7 +402,7 @@ static bool handle_mode_switch_event(const struct mode_switch_event *event)
static int do_init(void) static int do_init(void)
{ {
clear_pending_reports(); clear_pending_reports();
current_mode = MODE_SWITCH_USB; current_transport = HID_TRANSPORT_POLICY_USB;
memset(channel_state, 0, sizeof(channel_state)); memset(channel_state, 0, sizeof(channel_state));
channel_state[HID_SEND_CH_USB_KEYS].protocol_mode = channel_state[HID_SEND_CH_USB_KEYS].protocol_mode =
KEYBOARD_PROTOCOL_MODE_REPORT; KEYBOARD_PROTOCOL_MODE_REPORT;
@@ -451,8 +452,9 @@ static bool app_event_handler(const struct app_event_header *aeh)
cast_hid_report_sent_event(aeh)); cast_hid_report_sent_event(aeh));
} }
if (is_mode_switch_event(aeh)) { if (is_transport_policy_event(aeh)) {
return handle_mode_switch_event(cast_mode_switch_event(aeh)); return handle_transport_policy_event(
cast_transport_policy_event(aeh));
} }
if (is_module_state_event(aeh)) { if (is_module_state_event(aeh)) {
@@ -490,7 +492,7 @@ APP_EVENT_LISTENER(MODULE, app_event_handler);
APP_EVENT_SUBSCRIBE(MODULE, keyboard_hid_report_event); APP_EVENT_SUBSCRIBE(MODULE, keyboard_hid_report_event);
APP_EVENT_SUBSCRIBE(MODULE, hid_channel_state_event); APP_EVENT_SUBSCRIBE(MODULE, hid_channel_state_event);
APP_EVENT_SUBSCRIBE(MODULE, hid_report_sent_event); APP_EVENT_SUBSCRIBE(MODULE, hid_report_sent_event);
APP_EVENT_SUBSCRIBE(MODULE, mode_switch_event); APP_EVENT_SUBSCRIBE(MODULE, transport_policy_event);
APP_EVENT_SUBSCRIBE(MODULE, module_state_event); APP_EVENT_SUBSCRIBE(MODULE, module_state_event);
APP_EVENT_SUBSCRIBE_EARLY(MODULE, power_down_event); APP_EVENT_SUBSCRIBE_EARLY(MODULE, power_down_event);
APP_EVENT_SUBSCRIBE(MODULE, wake_up_event); APP_EVENT_SUBSCRIBE(MODULE, wake_up_event);

View File

@@ -20,8 +20,8 @@
#include "keyboard_core.h" #include "keyboard_core.h"
#include "keyboard_hid_report_event.h" #include "keyboard_hid_report_event.h"
#include "module_lifecycle.h" #include "module_lifecycle.h"
#include "mode_switch_event.h"
#include "set_protocol_event.h" #include "set_protocol_event.h"
#include "transport_policy_event.h"
LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF); LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF);
@@ -92,7 +92,7 @@ struct keyboard_core_module_ctx {
struct keyboard_reports_cache reports_cache; struct keyboard_reports_cache reports_cache;
uint8_t function_usage_mask[KEYBOARD_PROTOCOL_BITMAP_BYTES]; uint8_t function_usage_mask[KEYBOARD_PROTOCOL_BITMAP_BYTES];
enum keyboard_protocol_mode transport_protocol_modes[HID_TRANSPORT_COUNT]; enum keyboard_protocol_mode transport_protocol_modes[HID_TRANSPORT_COUNT];
enum mode_switch_mode current_mode; enum hid_transport_policy current_transport;
bool mode_valid; bool mode_valid;
}; };
@@ -128,18 +128,19 @@ static struct keyboard_core_module_ctx ctx = {
#define reports_cache ctx.reports_cache #define reports_cache ctx.reports_cache
#define function_usage_mask ctx.function_usage_mask #define function_usage_mask ctx.function_usage_mask
#define transport_protocol_modes ctx.transport_protocol_modes #define transport_protocol_modes ctx.transport_protocol_modes
#define current_mode ctx.current_mode #define current_transport ctx.current_transport
#define mode_valid ctx.mode_valid #define mode_valid ctx.mode_valid
#define running module_lifecycle_is_running(&ctx.lc) #define running module_lifecycle_is_running(&ctx.lc)
static bool mode_to_transport(enum mode_switch_mode mode, enum hid_transport *transport) static bool policy_to_transport(enum hid_transport_policy policy,
enum hid_transport *transport)
{ {
switch (mode) { switch (policy) {
case MODE_SWITCH_USB: case HID_TRANSPORT_POLICY_USB:
*transport = HID_TRANSPORT_USB; *transport = HID_TRANSPORT_USB;
return true; return true;
case MODE_SWITCH_BLE: case HID_TRANSPORT_POLICY_BLE:
*transport = HID_TRANSPORT_BLE; *transport = HID_TRANSPORT_BLE;
return true; return true;
@@ -152,13 +153,32 @@ static enum keyboard_protocol_mode active_protocol_mode_get(void)
{ {
enum hid_transport transport; enum hid_transport transport;
if (mode_valid && mode_to_transport(current_mode, &transport)) { if (mode_valid && policy_to_transport(current_transport, &transport)) {
return transport_protocol_modes[transport]; return transport_protocol_modes[transport];
} }
return KEYBOARD_PROTOCOL_MODE_REPORT; return KEYBOARD_PROTOCOL_MODE_REPORT;
} }
static bool transport_policy_to_mode(enum hid_transport_policy policy,
enum mode_switch_mode *mode)
{
if (mode == NULL) {
return false;
}
switch (policy) {
case HID_TRANSPORT_POLICY_USB:
*mode = MODE_SWITCH_USB;
return true;
case HID_TRANSPORT_POLICY_BLE:
*mode = MODE_SWITCH_BLE;
return true;
default:
return false;
}
}
static const struct keymap_entry *keymap_get(uint16_t key_id) static const struct keymap_entry *keymap_get(uint16_t key_id)
{ {
size_t left = 0; size_t left = 0;
@@ -341,15 +361,17 @@ static void submit_consumer_fifo_frame(uint16_t usage_id)
{ {
uint8_t report_buf[KEYBOARD_CONSUMER_REPORT_SIZE]; uint8_t report_buf[KEYBOARD_CONSUMER_REPORT_SIZE];
enum keyboard_protocol_mode protocol_mode = active_protocol_mode_get(); enum keyboard_protocol_mode protocol_mode = active_protocol_mode_get();
enum mode_switch_mode mode;
if (!running || !mode_valid || if (!running || !mode_valid ||
!transport_policy_to_mode(current_transport, &mode) ||
(protocol_mode == KEYBOARD_PROTOCOL_MODE_BOOT)) { (protocol_mode == KEYBOARD_PROTOCOL_MODE_BOOT)) {
return; return;
} }
sys_put_le16(usage_id, report_buf); sys_put_le16(usage_id, report_buf);
(void)submit_keyboard_hid_report_event( (void)submit_keyboard_hid_report_event(
current_mode, KEYBOARD_REPORT_TYPE_CONSUMER, protocol_mode, mode, KEYBOARD_REPORT_TYPE_CONSUMER, protocol_mode,
HID_QUEUE_POLICY_FIFO, report_buf, KEYBOARD_CONSUMER_REPORT_SIZE); HID_QUEUE_POLICY_FIFO, report_buf, KEYBOARD_CONSUMER_REPORT_SIZE);
} }
@@ -386,8 +408,9 @@ static void emit_keys_report(bool force)
uint8_t *cache_buf; uint8_t *cache_buf;
bool *cache_valid; bool *cache_valid;
enum keyboard_protocol_mode protocol_mode = active_protocol_mode_get(); enum keyboard_protocol_mode protocol_mode = active_protocol_mode_get();
enum mode_switch_mode mode;
if (!mode_valid) { if (!mode_valid || !transport_policy_to_mode(current_transport, &mode)) {
return; return;
} }
@@ -411,7 +434,7 @@ static void emit_keys_report(bool force)
*cache_valid = true; *cache_valid = true;
(void)submit_keyboard_hid_report_event( (void)submit_keyboard_hid_report_event(
current_mode, KEYBOARD_REPORT_TYPE_KEYS, protocol_mode, mode, KEYBOARD_REPORT_TYPE_KEYS, protocol_mode,
HID_QUEUE_POLICY_LATEST, report_buf, report_size); HID_QUEUE_POLICY_LATEST, report_buf, report_size);
} }
@@ -419,8 +442,10 @@ static void emit_consumer_report(bool force)
{ {
uint8_t report_buf[KEYBOARD_CONSUMER_REPORT_SIZE]; uint8_t report_buf[KEYBOARD_CONSUMER_REPORT_SIZE];
enum keyboard_protocol_mode protocol_mode = active_protocol_mode_get(); enum keyboard_protocol_mode protocol_mode = active_protocol_mode_get();
enum mode_switch_mode mode;
if (!mode_valid || (protocol_mode == KEYBOARD_PROTOCOL_MODE_BOOT)) { if (!mode_valid || !transport_policy_to_mode(current_transport, &mode) ||
(protocol_mode == KEYBOARD_PROTOCOL_MODE_BOOT)) {
return; return;
} }
@@ -435,7 +460,7 @@ static void emit_consumer_report(bool force)
reports_cache.consumer_valid = true; reports_cache.consumer_valid = true;
(void)submit_keyboard_hid_report_event( (void)submit_keyboard_hid_report_event(
current_mode, KEYBOARD_REPORT_TYPE_CONSUMER, protocol_mode, mode, KEYBOARD_REPORT_TYPE_CONSUMER, protocol_mode,
HID_QUEUE_POLICY_LATEST, report_buf, HID_QUEUE_POLICY_LATEST, report_buf,
KEYBOARD_CONSUMER_REPORT_SIZE); KEYBOARD_CONSUMER_REPORT_SIZE);
} }
@@ -454,15 +479,27 @@ static void emit_function_state_event(void)
(void)submit_function_bitmap_state_event(keyboard_state.pressed_usage_bitmap); (void)submit_function_bitmap_state_event(keyboard_state.pressed_usage_bitmap);
} }
static void emit_release_reports(enum mode_switch_mode mode) static void emit_release_reports(enum hid_transport_policy transport_policy)
{ {
uint8_t keys_report[KEYBOARD_NKRO_REPORT_SIZE] = { 0 }; uint8_t keys_report[KEYBOARD_NKRO_REPORT_SIZE] = { 0 };
uint8_t consumer_report[KEYBOARD_CONSUMER_REPORT_SIZE] = { 0 }; uint8_t consumer_report[KEYBOARD_CONSUMER_REPORT_SIZE] = { 0 };
enum keyboard_protocol_mode protocol_mode = active_protocol_mode_get(); enum keyboard_protocol_mode protocol_mode = active_protocol_mode_get();
enum mode_switch_mode mode;
size_t keys_report_size = size_t keys_report_size =
(protocol_mode == KEYBOARD_PROTOCOL_MODE_BOOT) ? (protocol_mode == KEYBOARD_PROTOCOL_MODE_BOOT) ?
KEYBOARD_BOOT_REPORT_SIZE : KEYBOARD_NKRO_REPORT_SIZE; KEYBOARD_BOOT_REPORT_SIZE : KEYBOARD_NKRO_REPORT_SIZE;
switch (transport_policy) {
case HID_TRANSPORT_POLICY_USB:
mode = MODE_SWITCH_USB;
break;
case HID_TRANSPORT_POLICY_BLE:
mode = MODE_SWITCH_BLE;
break;
default:
return;
}
(void)submit_keyboard_hid_report_event( (void)submit_keyboard_hid_report_event(
mode, KEYBOARD_REPORT_TYPE_KEYS, protocol_mode, mode, KEYBOARD_REPORT_TYPE_KEYS, protocol_mode,
HID_QUEUE_POLICY_LATEST, keys_report, keys_report_size); HID_QUEUE_POLICY_LATEST, keys_report, keys_report_size);
@@ -505,7 +542,7 @@ static int do_stop(void)
} }
if (mode_valid) { if (mode_valid) {
emit_release_reports(current_mode); emit_release_reports(current_transport);
} }
emit_function_state_event(); emit_function_state_event();
@@ -568,26 +605,30 @@ static bool handle_button_event(const struct button_event *event)
return false; return false;
} }
static bool handle_mode_switch_event(const struct mode_switch_event *event) static bool handle_transport_policy_event(
const struct transport_policy_event *event)
{ {
bool mode_changed; bool transport_changed;
if (!running) { if (!running) {
current_mode = event->mode; current_transport = event->hid_transport;
return false; return false;
} }
mode_changed = mode_valid && (current_mode != event->mode); transport_changed = mode_valid && (current_transport != event->hid_transport);
if (mode_changed) { if (transport_changed) {
emit_release_reports(current_mode); emit_release_reports(current_transport);
emit_function_state_event(); emit_function_state_event();
keyboard_state_clear(); keyboard_state_clear();
reports_cache_invalidate(); reports_cache_invalidate();
} }
current_mode = event->mode; current_transport = event->hid_transport;
mode_valid = true; mode_valid = (current_transport != HID_TRANSPORT_POLICY_NONE);
if (mode_valid) {
emit_all_reports(true); emit_all_reports(true);
}
return false; return false;
} }
@@ -643,7 +684,7 @@ static bool app_event_handler(const struct app_event_header *aeh)
transport_protocol_modes[event->transport] = event->protocol_mode; transport_protocol_modes[event->transport] = event->protocol_mode;
if (running && mode_valid && if (running && mode_valid &&
mode_to_transport(current_mode, &active_transport) && policy_to_transport(current_transport, &active_transport) &&
(active_transport == event->transport)) { (active_transport == event->transport)) {
reports_cache_invalidate(); reports_cache_invalidate();
emit_keys_report(true); emit_keys_report(true);
@@ -657,8 +698,9 @@ static bool app_event_handler(const struct app_event_header *aeh)
return false; return false;
} }
if (is_mode_switch_event(aeh)) { if (is_transport_policy_event(aeh)) {
return handle_mode_switch_event(cast_mode_switch_event(aeh)); return handle_transport_policy_event(
cast_transport_policy_event(aeh));
} }
if (is_module_state_event(aeh)) { if (is_module_state_event(aeh)) {
@@ -696,7 +738,7 @@ APP_EVENT_SUBSCRIBE(MODULE, button_event);
APP_EVENT_SUBSCRIBE(MODULE, encoder_event); APP_EVENT_SUBSCRIBE(MODULE, encoder_event);
APP_EVENT_SUBSCRIBE(MODULE, function_bitmap_update_event); APP_EVENT_SUBSCRIBE(MODULE, function_bitmap_update_event);
APP_EVENT_SUBSCRIBE(MODULE, set_protocol_event); APP_EVENT_SUBSCRIBE(MODULE, set_protocol_event);
APP_EVENT_SUBSCRIBE(MODULE, mode_switch_event); APP_EVENT_SUBSCRIBE(MODULE, transport_policy_event);
APP_EVENT_SUBSCRIBE(MODULE, module_state_event); APP_EVENT_SUBSCRIBE(MODULE, module_state_event);
APP_EVENT_SUBSCRIBE_EARLY(MODULE, power_down_event); APP_EVENT_SUBSCRIBE_EARLY(MODULE, power_down_event);
APP_EVENT_SUBSCRIBE(MODULE, wake_up_event); APP_EVENT_SUBSCRIBE(MODULE, wake_up_event);

View File

@@ -10,12 +10,19 @@
#include "module_lifecycle.h" #include "module_lifecycle.h"
#include "mode_switch_event.h" #include "mode_switch_event.h"
#include "transport_policy_event.h"
LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF); LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF);
struct transport_policy_state {
enum hid_transport_policy hid_transport;
enum ble_profile_policy ble_profile;
};
struct mode_policy_module_ctx { struct mode_policy_module_ctx {
struct module_lifecycle_ctx lc; struct module_lifecycle_ctx lc;
enum mode_switch_mode active_mode; enum mode_switch_mode active_mode;
struct transport_policy_state policy;
}; };
static int do_init(void); static int do_init(void);
@@ -40,8 +47,51 @@ static struct mode_policy_module_ctx ctx = {
.ops = &lifecycle_ops, .ops = &lifecycle_ops,
}, },
.active_mode = MODE_SWITCH_USB, .active_mode = MODE_SWITCH_USB,
.policy = {
.hid_transport = HID_TRANSPORT_POLICY_USB,
.ble_profile = BLE_PROFILE_POLICY_NONE,
},
}; };
static void build_policy_from_mode(enum mode_switch_mode mode,
struct transport_policy_state *policy)
{
switch (mode) {
case MODE_SWITCH_USB:
policy->hid_transport = HID_TRANSPORT_POLICY_USB;
policy->ble_profile = BLE_PROFILE_POLICY_NONE;
break;
case MODE_SWITCH_BLE:
policy->hid_transport = HID_TRANSPORT_POLICY_BLE;
policy->ble_profile = BLE_PROFILE_POLICY_GENERAL;
break;
case MODE_SWITCH_24G:
policy->hid_transport = HID_TRANSPORT_POLICY_BLE;
policy->ble_profile = BLE_PROFILE_POLICY_DONGLE;
break;
default:
policy->hid_transport = HID_TRANSPORT_POLICY_NONE;
policy->ble_profile = BLE_PROFILE_POLICY_NONE;
break;
}
}
static bool policy_equal(const struct transport_policy_state *a,
const struct transport_policy_state *b)
{
return (a->hid_transport == b->hid_transport) &&
(a->ble_profile == b->ble_profile);
}
static void broadcast_policy(void)
{
submit_transport_policy_event(ctx.active_mode, ctx.policy.hid_transport,
ctx.policy.ble_profile);
}
static void mode_policy_set_ble(bool enable) static void mode_policy_set_ble(bool enable)
{ {
if (enable) { if (enable) {
@@ -76,7 +126,7 @@ static void mode_policy_set_usb(bool enable)
} }
} }
static void apply_active_mode(void) static void apply_stack_policy(void)
{ {
switch (ctx.active_mode) { switch (ctx.active_mode) {
case MODE_SWITCH_BLE: case MODE_SWITCH_BLE:
@@ -90,7 +140,7 @@ static void apply_active_mode(void)
break; break;
case MODE_SWITCH_24G: case MODE_SWITCH_24G:
mode_policy_set_ble(false); mode_policy_set_ble(true);
mode_policy_set_usb(false); mode_policy_set_usb(false);
break; break;
@@ -111,7 +161,7 @@ static void apply_ble_mode_policy(void)
break; break;
case MODE_SWITCH_24G: case MODE_SWITCH_24G:
mode_policy_set_ble(false); mode_policy_set_ble(true);
break; break;
default: default:
@@ -139,15 +189,36 @@ static void apply_usb_mode_policy(void)
} }
} }
static void update_mode_policy(enum mode_switch_mode mode)
{
struct transport_policy_state next_policy;
bool mode_changed = (ctx.active_mode != mode);
bool policy_changed;
build_policy_from_mode(mode, &next_policy);
policy_changed = !policy_equal(&ctx.policy, &next_policy);
ctx.active_mode = mode;
ctx.policy = next_policy;
if (policy_changed || mode_changed) {
broadcast_policy();
}
apply_stack_policy();
}
static int do_init(void) static int do_init(void)
{ {
ctx.active_mode = MODE_SWITCH_USB; ctx.active_mode = MODE_SWITCH_USB;
build_policy_from_mode(ctx.active_mode, &ctx.policy);
return 0; return 0;
} }
static int do_start(void) static int do_start(void)
{ {
apply_active_mode(); broadcast_policy();
apply_stack_policy();
return 0; return 0;
} }
@@ -162,8 +233,7 @@ static bool app_event_handler(const struct app_event_header *aeh)
const struct mode_switch_event *event = cast_mode_switch_event(aeh); const struct mode_switch_event *event = cast_mode_switch_event(aeh);
if (module_lifecycle_is_running(&ctx.lc)) { if (module_lifecycle_is_running(&ctx.lc)) {
ctx.active_mode = event->mode; update_mode_policy(event->mode);
apply_active_mode();
} }
return false; return false;

View File

@@ -100,6 +100,30 @@ static const char *proto_transport_name(enum proto_transport transport)
} }
} }
static void proto_session_set(enum proto_transport transport,
enum proto_session_state new_state,
const char *reason)
{
enum proto_session_state old_state;
if (transport >= PROTO_TRANSPORT_COUNT) {
return;
}
old_state = session_state[transport];
if (old_state == new_state) {
LOG_INF("Protocol session keep transport:%s state:%s reason:%s",
proto_transport_name(transport),
proto_session_name(new_state), reason);
return;
}
session_state[transport] = new_state;
LOG_INF("Protocol session transport:%s %s -> %s reason:%s",
proto_transport_name(transport), proto_session_name(old_state),
proto_session_name(new_state), reason);
}
static int decode_body(const uint8_t *payload, size_t payload_len, static int decode_body(const uint8_t *payload, size_t payload_len,
CdcPacketBody *body) CdcPacketBody *body)
{ {
@@ -214,6 +238,8 @@ static int do_init(void)
session_state[i] = PROTO_SESSION_DOWN; session_state[i] = PROTO_SESSION_DOWN;
} }
LOG_INF("Protocol init done");
return 0; return 0;
} }
@@ -233,7 +259,8 @@ static int do_stop(void)
} }
for (size_t i = 0; i < ARRAY_SIZE(session_state); i++) { for (size_t i = 0; i < ARRAY_SIZE(session_state); i++) {
session_state[i] = PROTO_SESSION_DOWN; proto_session_set((enum proto_transport)i, PROTO_SESSION_DOWN,
"module_stop");
} }
return 0; return 0;
@@ -284,7 +311,7 @@ int protocol_module_process_message(enum proto_transport transport,
body.body.hello_req.protocol_version); body.body.hello_req.protocol_version);
} }
session_state[transport] = PROTO_SESSION_ACTIVE; proto_session_set(transport, PROTO_SESSION_ACTIVE, "hello_req");
return encode_hello_rsp(rsp_payload, rsp_payload_buf_size, rsp_payload_len); return encode_hello_rsp(rsp_payload, rsp_payload_buf_size, rsp_payload_len);
case CdcPacketBody_bitmap_tag: case CdcPacketBody_bitmap_tag:
@@ -396,6 +423,9 @@ static bool handle_proto_rx_event(const struct proto_rx_event *event)
return false; return false;
} }
LOG_INF("Protocol response ready transport:%s rsp_len:%u session:%s",
proto_transport_name(event->transport), (unsigned int)rsp_payload_len,
proto_session_name(session_state[event->transport]));
err = submit_proto_tx_event(event->transport, rsp_payload, rsp_payload_len); err = submit_proto_tx_event(event->transport, rsp_payload, rsp_payload_len);
if (err) { if (err) {
LOG_WRN("Proto TX submit failed (%d)", err); LOG_WRN("Proto TX submit failed (%d)", err);
@@ -413,11 +443,13 @@ static bool handle_proto_transport_state_event(
switch (event->state) { switch (event->state) {
case PROTO_TRANSPORT_LINK_DOWN: case PROTO_TRANSPORT_LINK_DOWN:
session_state[event->transport] = PROTO_SESSION_DOWN; proto_session_set(event->transport, PROTO_SESSION_DOWN,
"transport_link_down");
break; break;
case PROTO_TRANSPORT_LINK_READY: case PROTO_TRANSPORT_LINK_READY:
session_state[event->transport] = PROTO_SESSION_WAIT_HELLO; proto_session_set(event->transport, PROTO_SESSION_WAIT_HELLO,
"transport_link_ready");
break; break;
default: default:
@@ -441,6 +473,9 @@ static bool handle_function_bitmap_state_event(
for (enum proto_transport transport = 0; transport < PROTO_TRANSPORT_COUNT; for (enum proto_transport transport = 0; transport < PROTO_TRANSPORT_COUNT;
transport++) { transport++) {
if (session_state[transport] != PROTO_SESSION_ACTIVE) { if (session_state[transport] != PROTO_SESSION_ACTIVE) {
LOG_INF("FunctionKeyEvent skip transport:%s session:%s",
proto_transport_name(transport),
proto_session_name(session_state[transport]));
continue; continue;
} }
@@ -454,6 +489,10 @@ static bool handle_function_bitmap_state_event(
err = submit_proto_tx_event(transport, payload, payload_len); err = submit_proto_tx_event(transport, payload, payload_len);
if (err) { if (err) {
LOG_WRN("FunctionKeyEvent submit failed (%d)", err); LOG_WRN("FunctionKeyEvent submit failed (%d)", err);
} else {
LOG_INF("FunctionKeyEvent submit transport:%s len:%u",
proto_transport_name(transport),
(unsigned int)payload_len);
} }
} }
@@ -476,6 +515,9 @@ static bool handle_hid_led_event(const struct hid_led_event *event)
PROTO_TRANSPORT_BLE_NUS; PROTO_TRANSPORT_BLE_NUS;
if (session_state[transport] != PROTO_SESSION_ACTIVE) { if (session_state[transport] != PROTO_SESSION_ACTIVE) {
LOG_INF("LedState skip transport:%s session:%s led_mask:0x%02x",
proto_transport_name(transport),
proto_session_name(session_state[transport]), event->led_bm);
return false; return false;
} }
@@ -488,6 +530,10 @@ static bool handle_hid_led_event(const struct hid_led_event *event)
err = submit_proto_tx_event(transport, payload, payload_len); err = submit_proto_tx_event(transport, payload, payload_len);
if (err) { if (err) {
LOG_WRN("LedState submit failed (%d)", err); LOG_WRN("LedState submit failed (%d)", err);
} else {
LOG_INF("LedState submit transport:%s len:%u led_mask:0x%02x",
proto_transport_name(transport), (unsigned int)payload_len,
event->led_bm);
} }
return false; return false;

View File

@@ -74,7 +74,7 @@ static struct usb_cdc_ctx ctx = {
.ops = &lifecycle_ops, .ops = &lifecycle_ops,
}, },
.business = USB_CDC_BUS_OFFLINE, .business = USB_CDC_BUS_OFFLINE,
.cdc_dev = DEVICE_DT_GET_ONE(zephyr_cdc_acm_uart), .cdc_dev = DEVICE_DT_GET(DT_NODELABEL(cdc_acm_uart0)),
.usb_active = false, .usb_active = false,
.proto_rx_len = 0U, .proto_rx_len = 0U,
}; };
@@ -83,6 +83,32 @@ static struct usb_cdc_ctx ctx = {
static void validate_line_coding(void); static void validate_line_coding(void);
static const char *usb_cdc_business_state_name(enum usb_cdc_business_state state)
{
switch (state) {
case USB_CDC_BUS_OFFLINE:
return "BUS_OFFLINE";
case USB_CDC_WAIT_DTR:
return "WAIT_DTR";
case USB_CDC_SESSION_READY:
return "SESSION_READY";
default:
return "?";
}
}
static const char *proto_link_state_name(enum proto_transport_link_state state)
{
switch (state) {
case PROTO_TRANSPORT_LINK_DOWN:
return "DOWN";
case PROTO_TRANSPORT_LINK_READY:
return "READY";
default:
return "?";
}
}
static bool lifecycle_is_ready(void) static bool lifecycle_is_ready(void)
{ {
return module_lifecycle_is_running(&ctx.lc); return module_lifecycle_is_running(&ctx.lc);
@@ -128,6 +154,7 @@ static void state_reconcile(enum module_lifecycle old_lifecycle,
if ((old_lifecycle == LC_RUNNING) && if ((old_lifecycle == LC_RUNNING) &&
(old_business == USB_CDC_SESSION_READY) && (old_business == USB_CDC_SESSION_READY) &&
(new_link == PROTO_TRANSPORT_LINK_DOWN)) { (new_link == PROTO_TRANSPORT_LINK_DOWN)) {
LOG_INF("CDC reconcile: link READY -> DOWN, disable UART IO");
disable_uart_io(); disable_uart_io();
} }
@@ -135,6 +162,9 @@ static void state_reconcile(enum module_lifecycle old_lifecycle,
(new_link == PROTO_TRANSPORT_LINK_READY)) { (new_link == PROTO_TRANSPORT_LINK_READY)) {
int err; int err;
LOG_INF("CDC reconcile: link DOWN -> READY (business:%s usb_active:%u lc:%s)",
usb_cdc_business_state_name(ctx.business), ctx.usb_active,
module_lifecycle_name(ctx.lc.state));
validate_line_coding(); validate_line_coding();
err = uart_line_ctrl_set(ctx.cdc_dev, UART_LINE_CTRL_DCD, 1); err = uart_line_ctrl_set(ctx.cdc_dev, UART_LINE_CTRL_DCD, 1);
@@ -151,6 +181,11 @@ static void state_reconcile(enum module_lifecycle old_lifecycle,
} }
if (old_link != new_link) { if (old_link != new_link) {
LOG_INF("CDC link %s -> %s (business:%s usb_active:%u lc:%s)",
proto_link_state_name(old_link),
proto_link_state_name(new_link),
usb_cdc_business_state_name(ctx.business), ctx.usb_active,
module_lifecycle_name(ctx.lc.state));
submit_proto_transport_state_event(PROTO_TRANSPORT_USB_CDC, submit_proto_transport_state_event(PROTO_TRANSPORT_USB_CDC,
new_link); new_link);
} }
@@ -166,11 +201,19 @@ static void business_state_set(enum usb_cdc_business_state new_state)
} }
ctx.business = new_state; ctx.business = new_state;
LOG_INF("CDC business %s -> %s (usb_active:%u lc:%s)",
usb_cdc_business_state_name(old_business),
usb_cdc_business_state_name(ctx.business), ctx.usb_active,
module_lifecycle_name(ctx.lc.state));
state_reconcile(old_lifecycle, old_business); state_reconcile(old_lifecycle, old_business);
} }
static void business_state_sync_from_usb(void) static void business_state_sync_from_usb(void)
{ {
LOG_INF("CDC sync from USB (usb_active:%u business:%s lc:%s)",
ctx.usb_active, usb_cdc_business_state_name(ctx.business),
module_lifecycle_name(ctx.lc.state));
if (!ctx.usb_active) { if (!ctx.usb_active) {
business_state_set(USB_CDC_BUS_OFFLINE); business_state_set(USB_CDC_BUS_OFFLINE);
return; return;
@@ -188,9 +231,14 @@ static void business_state_sync_from_usb(void)
static void kick_tx(void) static void kick_tx(void)
{ {
if (transport_link_state_get() != PROTO_TRANSPORT_LINK_READY) { if (transport_link_state_get() != PROTO_TRANSPORT_LINK_READY) {
LOG_INF("CDC kick_tx skipped: link=%s business:%s usb_active:%u tx_rb:%u",
proto_link_state_name(transport_link_state_get()),
usb_cdc_business_state_name(ctx.business), ctx.usb_active,
ring_buf_size_get(&ctx.tx_ringbuf));
return; return;
} }
LOG_INF("CDC kick_tx: enable TX IRQ (tx_rb:%u)", ring_buf_size_get(&ctx.tx_ringbuf));
uart_irq_tx_enable(ctx.cdc_dev); uart_irq_tx_enable(ctx.cdc_dev);
} }
@@ -249,6 +297,9 @@ static void rx_work_handler(struct k_work *work)
return; return;
} }
LOG_INF("CDC rx_work pulled %u bytes from RX ring (proto_rx_len:%u)",
(unsigned int)len, (unsigned int)ctx.proto_rx_len);
if ((ctx.proto_rx_len + len) > sizeof(proto_rx_buf)) { if ((ctx.proto_rx_len + len) > sizeof(proto_rx_buf)) {
LOG_WRN("Drop oversized CDC protobuf message len:%u", LOG_WRN("Drop oversized CDC protobuf message len:%u",
(uint32_t)(ctx.proto_rx_len + len)); (uint32_t)(ctx.proto_rx_len + len));
@@ -269,9 +320,14 @@ static void rx_flush_work_handler(struct k_work *work)
if ((transport_link_state_get() != PROTO_TRANSPORT_LINK_READY) || if ((transport_link_state_get() != PROTO_TRANSPORT_LINK_READY) ||
(ctx.proto_rx_len == 0U)) { (ctx.proto_rx_len == 0U)) {
LOG_INF("CDC rx_flush skipped: link=%s proto_rx_len:%u business:%s",
proto_link_state_name(transport_link_state_get()),
(unsigned int)ctx.proto_rx_len,
usb_cdc_business_state_name(ctx.business));
return; return;
} }
LOG_INF("CDC rx_flush submit proto_rx len:%u", (unsigned int)ctx.proto_rx_len);
(void)submit_proto_rx_event(PROTO_TRANSPORT_USB_CDC, proto_rx_buf, (void)submit_proto_rx_event(PROTO_TRANSPORT_USB_CDC, proto_rx_buf,
ctx.proto_rx_len); ctx.proto_rx_len);
ctx.proto_rx_len = 0U; ctx.proto_rx_len = 0U;
@@ -304,6 +360,10 @@ static void cdc_interrupt_handler(const struct device *dev, void *user_data)
recv_len - (int)written); recv_len - (int)written);
} }
LOG_INF("CDC IRQ RX recv:%d written:%u rx_rb:%u",
recv_len, (unsigned int)written,
ring_buf_size_get(&ctx.rx_ringbuf));
k_work_submit(&ctx.rx_work); k_work_submit(&ctx.rx_work);
} }
} }
@@ -318,6 +378,7 @@ static void cdc_interrupt_handler(const struct device *dev, void *user_data)
irq_unlock(key); irq_unlock(key);
if (len == 0U) { if (len == 0U) {
LOG_INF("CDC IRQ TX ready but no pending data, disable TX IRQ");
uart_irq_tx_disable(dev); uart_irq_tx_disable(dev);
continue; continue;
} }
@@ -330,6 +391,10 @@ static void cdc_interrupt_handler(const struct device *dev, void *user_data)
LOG_WRN("Drop %u CDC TX bytes", LOG_WRN("Drop %u CDC TX bytes",
(unsigned int)(len - (uint32_t)sent_len)); (unsigned int)(len - (uint32_t)sent_len));
} }
LOG_INF("CDC IRQ TX requested:%u sent:%d tx_rb_remain:%u",
(unsigned int)len, sent_len,
ring_buf_size_get(&ctx.tx_ringbuf));
} }
} }
} }
@@ -348,6 +413,9 @@ static int do_init(void)
ctx.business = USB_CDC_BUS_OFFLINE; ctx.business = USB_CDC_BUS_OFFLINE;
ctx.usb_active = false; ctx.usb_active = false;
ctx.proto_rx_len = 0U; ctx.proto_rx_len = 0U;
LOG_INF("CDC init done (business:%s usb_active:%u lc:%s dev:%p)",
usb_cdc_business_state_name(ctx.business), ctx.usb_active,
module_lifecycle_name(ctx.lc.state), ctx.cdc_dev);
return 0; return 0;
} }
@@ -359,6 +427,9 @@ static int do_start(void)
static int do_stop(void) static int do_stop(void)
{ {
LOG_INF("CDC stop requested (business:%s usb_active:%u lc:%s)",
usb_cdc_business_state_name(ctx.business), ctx.usb_active,
module_lifecycle_name(ctx.lc.state));
ctx.business = USB_CDC_BUS_OFFLINE; ctx.business = USB_CDC_BUS_OFFLINE;
return 0; return 0;
} }
@@ -379,6 +450,11 @@ static int apply_lifecycle(enum module_lifecycle target)
business_state_sync_from_usb(); business_state_sync_from_usb();
} }
LOG_INF("CDC lifecycle %s -> %s done (business:%s usb_active:%u link:%s)",
module_lifecycle_name(old_lifecycle), module_lifecycle_name(target),
usb_cdc_business_state_name(ctx.business), ctx.usb_active,
proto_link_state_name(transport_link_state_get()));
return 0; return 0;
} }
@@ -391,6 +467,10 @@ static bool handle_usb_state_event(const struct usb_state_event *event)
} }
ctx.usb_active = new_usb_active; ctx.usb_active = new_usb_active;
LOG_INF("CDC usb_active -> %u from usb_state:%d (business:%s lc:%s)",
ctx.usb_active, event->state,
usb_cdc_business_state_name(ctx.business),
module_lifecycle_name(ctx.lc.state));
business_state_sync_from_usb(); business_state_sync_from_usb();
return false; return false;
@@ -404,7 +484,13 @@ static bool handle_usb_control_event(const struct usb_control_event *event)
switch (event->type) { switch (event->type) {
case USB_CONTROL_EVENT_CDC_LINE_STATE: case USB_CONTROL_EVENT_CDC_LINE_STATE:
LOG_INF("CDC control event line_state dtr:%u usb_active:%u lc:%s business:%s",
event->data.cdc_line_state.dtr, ctx.usb_active,
module_lifecycle_name(ctx.lc.state),
usb_cdc_business_state_name(ctx.business));
if (!ctx.usb_active || !lifecycle_is_ready()) { if (!ctx.usb_active || !lifecycle_is_ready()) {
LOG_INF("CDC line_state ignored: usb_active:%u lc:%s",
ctx.usb_active, module_lifecycle_name(ctx.lc.state));
return false; return false;
} }
@@ -419,6 +505,13 @@ static bool handle_usb_control_event(const struct usb_control_event *event)
return false; return false;
case USB_CONTROL_EVENT_CDC_LINE_CODING: case USB_CONTROL_EVENT_CDC_LINE_CODING:
LOG_INF("CDC control event line_coding baud:%u data:%u stop:%u parity:%u flow:%u business:%s",
event->data.cdc_line_coding.baudrate,
event->data.cdc_line_coding.data_bits,
event->data.cdc_line_coding.stop_bits,
event->data.cdc_line_coding.parity,
event->data.cdc_line_coding.flow_ctrl,
usb_cdc_business_state_name(ctx.business));
if (event->data.cdc_line_coding.baudrate != 0U) { if (event->data.cdc_line_coding.baudrate != 0U) {
LOG_INF("CDC baudrate %u", LOG_INF("CDC baudrate %u",
event->data.cdc_line_coding.baudrate); event->data.cdc_line_coding.baudrate);
@@ -459,6 +552,10 @@ static bool handle_proto_tx_event(const struct proto_tx_event *event)
} }
if (transport_link_state_get() != PROTO_TRANSPORT_LINK_READY) { if (transport_link_state_get() != PROTO_TRANSPORT_LINK_READY) {
LOG_INF("CDC proto_tx ignored len:%u link:%s business:%s usb_active:%u",
(unsigned int)event->dyndata.size,
proto_link_state_name(transport_link_state_get()),
usb_cdc_business_state_name(ctx.business), ctx.usb_active);
return false; return false;
} }
@@ -467,6 +564,10 @@ static bool handle_proto_tx_event(const struct proto_tx_event *event)
(uint32_t)event->dyndata.size); (uint32_t)event->dyndata.size);
irq_unlock(key); irq_unlock(key);
LOG_INF("CDC proto_tx queued len:%u written:%u tx_rb:%u",
(unsigned int)event->dyndata.size, (unsigned int)written,
ring_buf_size_get(&ctx.tx_ringbuf));
if (written < event->dyndata.size) { if (written < event->dyndata.size) {
LOG_WRN("Drop %zu CDC TX bytes", event->dyndata.size - written); LOG_WRN("Drop %zu CDC TX bytes", event->dyndata.size - written);
} }

View File

@@ -88,6 +88,54 @@ static struct usb_owner_ctx usb_ctx = {
.bus = USB_BUS_DISCONNECTED, .bus = USB_BUS_DISCONNECTED,
}; };
static const char *usb_stack_state_name(enum usb_stack_state state)
{
switch (state) {
case USB_STACK_UNINITIALIZED:
return "UNINITIALIZED";
case USB_STACK_READY:
return "READY";
case USB_STACK_ENABLED:
return "ENABLED";
default:
return "?";
}
}
static const char *usb_bus_state_name(enum usb_bus_state state)
{
switch (state) {
case USB_BUS_DISCONNECTED:
return "DISCONNECTED";
case USB_BUS_POWERED:
return "POWERED";
case USB_BUS_ACTIVE:
return "ACTIVE";
case USB_BUS_SUSPENDED:
return "SUSPENDED";
default:
return "?";
}
}
static const char *usb_public_state_name(enum usb_state state)
{
switch (state) {
case USB_STATE_DISABLED:
return "DISABLED";
case USB_STATE_DISCONNECTED:
return "DISCONNECTED";
case USB_STATE_POWERED:
return "POWERED";
case USB_STATE_ACTIVE:
return "ACTIVE";
case USB_STATE_SUSPENDED:
return "SUSPENDED";
default:
return "?";
}
}
static inline enum usb_state usb_public_state_get(void) static inline enum usb_state usb_public_state_get(void)
{ {
if (!module_lifecycle_is_running(&usb_ctx.lc) || if (!module_lifecycle_is_running(&usb_ctx.lc) ||
@@ -111,12 +159,21 @@ static inline enum usb_state usb_public_state_get(void)
static inline void usb_bus_set(enum usb_bus_state state) static inline void usb_bus_set(enum usb_bus_state state)
{ {
enum usb_bus_state old_state = usb_ctx.bus;
if (usb_ctx.bus == state) { if (usb_ctx.bus == state) {
return; return;
} }
usb_ctx.bus = state; usb_ctx.bus = state;
LOG_INF("USB bus %s -> %s (stack:%s lc:%s public:%s)",
usb_bus_state_name(old_state),
usb_bus_state_name(usb_ctx.bus),
usb_stack_state_name(usb_ctx.stack),
module_lifecycle_name(usb_ctx.lc.state),
usb_public_state_name(usb_public_state_get()));
if (module_lifecycle_is_initialized(&usb_ctx.lc)) { if (module_lifecycle_is_initialized(&usb_ctx.lc)) {
submit_usb_state(usb_public_state_get()); submit_usb_state(usb_public_state_get());
} }
@@ -168,6 +225,12 @@ static void usbd_msg_cb(struct usbd_context *const usbd_ctx,
{ {
ARG_UNUSED(usbd_ctx); ARG_UNUSED(usbd_ctx);
LOG_INF("USBD msg:%s status:%u dev:%p stack:%s bus:%s lc:%s",
usbd_msg_type_string(msg->type), msg->status, msg->dev,
usb_stack_state_name(usb_ctx.stack),
usb_bus_state_name(usb_ctx.bus),
module_lifecycle_name(usb_ctx.lc.state));
if (msg->type == USBD_MSG_CDC_ACM_CONTROL_LINE_STATE) { if (msg->type == USBD_MSG_CDC_ACM_CONTROL_LINE_STATE) {
uint32_t dtr = 0U; uint32_t dtr = 0U;
int err = uart_line_ctrl_get(msg->dev, UART_LINE_CTRL_DTR, &dtr); int err = uart_line_ctrl_get(msg->dev, UART_LINE_CTRL_DTR, &dtr);
@@ -175,6 +238,7 @@ static void usbd_msg_cb(struct usbd_context *const usbd_ctx,
if (err) { if (err) {
LOG_WRN("Failed to get CDC DTR (%d)", err); LOG_WRN("Failed to get CDC DTR (%d)", err);
} else { } else {
LOG_INF("CDC control line state DTR:%u dev:%p", dtr, msg->dev);
submit_usb_control_cdc_line_state_event(msg->dev, dtr != 0U); submit_usb_control_cdc_line_state_event(msg->dev, dtr != 0U);
} }
@@ -210,6 +274,8 @@ static void usbd_msg_cb(struct usbd_context *const usbd_ctx,
} }
#endif #endif
LOG_INF("CDC line coding baud:%u data:%u stop:%u parity:%u flow:%u dev:%p",
baudrate, data_bits, stop_bits, parity, flow_ctrl, msg->dev);
submit_usb_control_cdc_line_coding_event(msg->dev, baudrate, submit_usb_control_cdc_line_coding_event(msg->dev, baudrate,
data_bits, stop_bits, data_bits, stop_bits,
parity, flow_ctrl); parity, flow_ctrl);
@@ -280,6 +346,10 @@ static int do_init(void)
usb_ctx.stack = USB_STACK_UNINITIALIZED; usb_ctx.stack = USB_STACK_UNINITIALIZED;
usb_ctx.bus = USB_BUS_DISCONNECTED; usb_ctx.bus = USB_BUS_DISCONNECTED;
LOG_INF("USB init start (stack:%s bus:%s lc:%s)",
usb_stack_state_name(usb_ctx.stack),
usb_bus_state_name(usb_ctx.bus),
module_lifecycle_name(usb_ctx.lc.state));
update_power_manager_restriction(false); update_power_manager_restriction(false);
STRUCT_SECTION_FOREACH(usb_function_hook, hook) { STRUCT_SECTION_FOREACH(usb_function_hook, hook) {
@@ -313,6 +383,11 @@ static int do_init(void)
} }
usb_ctx.stack = USB_STACK_READY; usb_ctx.stack = USB_STACK_READY;
LOG_INF("USB init done (stack:%s bus:%s lc:%s public:%s)",
usb_stack_state_name(usb_ctx.stack),
usb_bus_state_name(usb_ctx.bus),
module_lifecycle_name(usb_ctx.lc.state),
usb_public_state_name(usb_public_state_get()));
return 0; return 0;
} }
@@ -321,7 +396,13 @@ static int do_start(void)
{ {
int err; int err;
LOG_INF("USB start requested (stack:%s bus:%s lc:%s)",
usb_stack_state_name(usb_ctx.stack),
usb_bus_state_name(usb_ctx.bus),
module_lifecycle_name(usb_ctx.lc.state));
if (usb_ctx.stack == USB_STACK_ENABLED) { if (usb_ctx.stack == USB_STACK_ENABLED) {
LOG_INF("USB start ignored: already enabled");
return 0; return 0;
} }
@@ -334,11 +415,15 @@ static int do_start(void)
usb_ctx.stack = USB_STACK_ENABLED; usb_ctx.stack = USB_STACK_ENABLED;
usb_ctx.bus = USB_BUS_POWERED; usb_ctx.bus = USB_BUS_POWERED;
LOG_INF("USB enabled without VBUS detect (stack:%s bus:%s)",
usb_stack_state_name(usb_ctx.stack),
usb_bus_state_name(usb_ctx.bus));
update_power_manager_restriction(true); update_power_manager_restriction(true);
return 0; return 0;
} }
if (usb_ctx.bus == USB_BUS_DISCONNECTED) { if (usb_ctx.bus == USB_BUS_DISCONNECTED) {
LOG_INF("USB start deferred: waiting for VBUS");
return 0; return 0;
} }
@@ -349,6 +434,8 @@ static int do_start(void)
} }
usb_ctx.stack = USB_STACK_ENABLED; usb_ctx.stack = USB_STACK_ENABLED;
LOG_INF("USB enabled (stack:%s bus:%s)", usb_stack_state_name(usb_ctx.stack),
usb_bus_state_name(usb_ctx.bus));
update_power_manager_restriction(true); update_power_manager_restriction(true);
return 0; return 0;
} }
@@ -357,6 +444,11 @@ static int do_stop(void)
{ {
int err; int err;
LOG_INF("USB stop requested (stack:%s bus:%s lc:%s)",
usb_stack_state_name(usb_ctx.stack),
usb_bus_state_name(usb_ctx.bus),
module_lifecycle_name(usb_ctx.lc.state));
if (usb_ctx.stack == USB_STACK_ENABLED) { if (usb_ctx.stack == USB_STACK_ENABLED) {
err = usbd_disable(&blinky_usbd); err = usbd_disable(&blinky_usbd);
if (err) { if (err) {
@@ -366,6 +458,8 @@ static int do_stop(void)
} }
usb_ctx.stack = USB_STACK_READY; usb_ctx.stack = USB_STACK_READY;
LOG_INF("USB stopped (stack:%s bus:%s)", usb_stack_state_name(usb_ctx.stack),
usb_bus_state_name(usb_ctx.bus));
update_power_manager_restriction(false); update_power_manager_restriction(false);
return 0; return 0;
} }