feat(protocol): 添加时间同步和主题颜色协议支持
- 添加CDC_PROTO_TYPE_LED_STATE、CDC_PROTO_TYPE_TIME_SYNC和 CDC_PROTO_TYPE_THEME_RGB协议类型定义 - 在protobuf中定义LedState、TimeSync和ThemeRgb消息结构 - 更新CdcPacketBody消息以包含新的协议类型 - 增加协议能力标志位以支持新功能
This commit is contained in:
@@ -33,6 +33,7 @@ target_sources(app PRIVATE
|
|||||||
src/led_effect/led_effect_registry.c
|
src/led_effect/led_effect_registry.c
|
||||||
src/led_effect/effects/led_effect_key_fade.c
|
src/led_effect/effects/led_effect_key_fade.c
|
||||||
src/led_strip_module.c
|
src/led_strip_module.c
|
||||||
|
src/time_sync_module.c
|
||||||
src/ui/ui_main.c
|
src/ui/ui_main.c
|
||||||
src/cdc_wrapper_module.c
|
src/cdc_wrapper_module.c
|
||||||
src/protocol_module.c
|
src/protocol_module.c
|
||||||
@@ -43,6 +44,7 @@ target_sources(app PRIVATE
|
|||||||
src/events/ble_serial_rx_event.c
|
src/events/ble_serial_rx_event.c
|
||||||
src/events/ble_serial_tx_event.c
|
src/events/ble_serial_tx_event.c
|
||||||
src/events/cdc_proto_tx_event.c
|
src/events/cdc_proto_tx_event.c
|
||||||
|
src/events/datetime_event.c
|
||||||
src/events/encoder_event.c
|
src/events/encoder_event.c
|
||||||
src/events/function_bitmap_update_event.c
|
src/events/function_bitmap_update_event.c
|
||||||
src/events/hid_led_event.c
|
src/events/hid_led_event.c
|
||||||
@@ -55,6 +57,8 @@ target_sources(app PRIVATE
|
|||||||
src/events/keyboard_hid_report_event.c
|
src/events/keyboard_hid_report_event.c
|
||||||
src/events/mode_switch_event.c
|
src/events/mode_switch_event.c
|
||||||
src/events/set_protocol_event.c
|
src/events/set_protocol_event.c
|
||||||
|
src/events/theme_rgb_update_event.c
|
||||||
|
src/events/time_sync_event.c
|
||||||
src/events/usb_cdc_rx_event.c
|
src/events/usb_cdc_rx_event.c
|
||||||
src/events/usb_cdc_tx_event.c
|
src/events/usb_cdc_tx_event.c
|
||||||
src/events/usb_device_state_event.c
|
src/events/usb_device_state_event.c
|
||||||
|
|||||||
26
inc/events/datetime_event.h
Normal file
26
inc/events/datetime_event.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef BLINKY_DATETIME_EVENT_H_
|
||||||
|
#define BLINKY_DATETIME_EVENT_H_
|
||||||
|
|
||||||
|
#include <app_event_manager.h>
|
||||||
|
#include <app_event_manager_profiler_tracer.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DATETIME_EVENT_DATE_TEXT_LEN 16
|
||||||
|
#define DATETIME_EVENT_TIME_TEXT_LEN 16
|
||||||
|
|
||||||
|
struct datetime_event {
|
||||||
|
struct app_event_header header;
|
||||||
|
char date_text[DATETIME_EVENT_DATE_TEXT_LEN];
|
||||||
|
char time_text[DATETIME_EVENT_TIME_TEXT_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
APP_EVENT_TYPE_DECLARE(datetime_event);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* BLINKY_DATETIME_EVENT_H_ */
|
||||||
24
inc/events/theme_rgb_update_event.h
Normal file
24
inc/events/theme_rgb_update_event.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef BLINKY_THEME_RGB_UPDATE_EVENT_H_
|
||||||
|
#define BLINKY_THEME_RGB_UPDATE_EVENT_H_
|
||||||
|
|
||||||
|
#include <app_event_manager.h>
|
||||||
|
#include <app_event_manager_profiler_tracer.h>
|
||||||
|
|
||||||
|
#include "theme_color.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct theme_rgb_update_event {
|
||||||
|
struct app_event_header header;
|
||||||
|
struct theme_rgb theme;
|
||||||
|
};
|
||||||
|
|
||||||
|
APP_EVENT_TYPE_DECLARE(theme_rgb_update_event);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* BLINKY_THEME_RGB_UPDATE_EVENT_H_ */
|
||||||
26
inc/events/time_sync_event.h
Normal file
26
inc/events/time_sync_event.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef BLINKY_TIME_SYNC_EVENT_H_
|
||||||
|
#define BLINKY_TIME_SYNC_EVENT_H_
|
||||||
|
|
||||||
|
#include <app_event_manager.h>
|
||||||
|
#include <app_event_manager_profiler_tracer.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct time_sync_event {
|
||||||
|
struct app_event_header header;
|
||||||
|
uint32_t version;
|
||||||
|
uint32_t flags;
|
||||||
|
int32_t timezone_min;
|
||||||
|
uint64_t utc_ms;
|
||||||
|
uint32_t accuracy_ms;
|
||||||
|
};
|
||||||
|
|
||||||
|
APP_EVENT_TYPE_DECLARE(time_sync_event);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* BLINKY_TIME_SYNC_EVENT_H_ */
|
||||||
@@ -12,6 +12,9 @@ extern "C" {
|
|||||||
#define CDC_PROTO_TYPE_HELLO_RSP 0x02U
|
#define CDC_PROTO_TYPE_HELLO_RSP 0x02U
|
||||||
#define CDC_PROTO_TYPE_BITMAP 0x10U
|
#define CDC_PROTO_TYPE_BITMAP 0x10U
|
||||||
#define CDC_PROTO_TYPE_FUNCTION_KEY_EVENT 0x20U
|
#define CDC_PROTO_TYPE_FUNCTION_KEY_EVENT 0x20U
|
||||||
|
#define CDC_PROTO_TYPE_LED_STATE 0x21U
|
||||||
|
#define CDC_PROTO_TYPE_TIME_SYNC 0x30U
|
||||||
|
#define CDC_PROTO_TYPE_THEME_RGB 0x31U
|
||||||
#define CDC_PROTO_TYPE_ACK 0x7EU
|
#define CDC_PROTO_TYPE_ACK 0x7EU
|
||||||
#define CDC_PROTO_TYPE_ERROR 0x7FU
|
#define CDC_PROTO_TYPE_ERROR 0x7FU
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,24 @@ message FunctionKeyEvent {
|
|||||||
KeyAction action = 2;
|
KeyAction action = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message LedState {
|
||||||
|
uint32 led_mask = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TimeSync {
|
||||||
|
uint32 version = 1;
|
||||||
|
uint32 flags = 2;
|
||||||
|
sint32 timezone_min = 3;
|
||||||
|
fixed64 utc_ms = 4;
|
||||||
|
fixed32 accuracy_ms = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ThemeRgb {
|
||||||
|
uint32 red = 1;
|
||||||
|
uint32 green = 2;
|
||||||
|
uint32 blue = 3;
|
||||||
|
}
|
||||||
|
|
||||||
message Ack {
|
message Ack {
|
||||||
uint32 acked_type = 1;
|
uint32 acked_type = 1;
|
||||||
}
|
}
|
||||||
@@ -50,7 +68,10 @@ message CdcPacketBody {
|
|||||||
HelloRsp hello_rsp = 2;
|
HelloRsp hello_rsp = 2;
|
||||||
Bitmap bitmap = 3;
|
Bitmap bitmap = 3;
|
||||||
FunctionKeyEvent function_key_event = 4;
|
FunctionKeyEvent function_key_event = 4;
|
||||||
Ack ack = 5;
|
LedState led_state = 5;
|
||||||
Error error = 6;
|
TimeSync time_sync = 6;
|
||||||
|
ThemeRgb theme_rgb = 7;
|
||||||
|
Ack ack = 8;
|
||||||
|
Error error = 9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,10 @@
|
|||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
|
|
||||||
#include "bat_state_event.h"
|
#include "bat_state_event.h"
|
||||||
|
#include "datetime_event.h"
|
||||||
#include "hid_led_event.h"
|
#include "hid_led_event.h"
|
||||||
#include "mode_switch_event.h"
|
#include "mode_switch_event.h"
|
||||||
|
#include "theme_rgb_update_event.h"
|
||||||
#include "theme_color.h"
|
#include "theme_color.h"
|
||||||
#include "ui/ui_main.h"
|
#include "ui/ui_main.h"
|
||||||
|
|
||||||
@@ -40,6 +42,8 @@ static struct ui_main_model ui_model = {
|
|||||||
static bool initialized;
|
static bool initialized;
|
||||||
static bool running;
|
static bool running;
|
||||||
static bool lvgl_initialized;
|
static bool lvgl_initialized;
|
||||||
|
static char date_text[DATETIME_EVENT_DATE_TEXT_LEN] = "1970/01/01";
|
||||||
|
static char time_text[DATETIME_EVENT_TIME_TEXT_LEN] = "00:00:00";
|
||||||
|
|
||||||
static int backlight_set(bool on)
|
static int backlight_set(bool on)
|
||||||
{
|
{
|
||||||
@@ -93,7 +97,7 @@ static int module_start(void)
|
|||||||
lvgl_initialized = true;
|
lvgl_initialized = true;
|
||||||
|
|
||||||
lvgl_lock();
|
lvgl_lock();
|
||||||
ui_main_init(&ui_model, "WH Mini", "Hello World");
|
ui_main_init(&ui_model, date_text, time_text);
|
||||||
lvgl_unlock();
|
lvgl_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +139,7 @@ static void refresh_ui(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
lvgl_lock();
|
lvgl_lock();
|
||||||
ui_main_refresh_all(&ui_model, "WH Mini", "Hello World");
|
ui_main_refresh_all(&ui_model, date_text, time_text);
|
||||||
lvgl_unlock();
|
lvgl_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,6 +171,28 @@ static bool app_event_handler(const struct app_event_header *aeh)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_theme_rgb_update_event(aeh)) {
|
||||||
|
const struct theme_rgb_update_event *event =
|
||||||
|
cast_theme_rgb_update_event(aeh);
|
||||||
|
|
||||||
|
ui_model.theme_color = (lv_color_t)LV_COLOR_MAKE(event->theme.r,
|
||||||
|
event->theme.g,
|
||||||
|
event->theme.b);
|
||||||
|
refresh_ui();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_datetime_event(aeh)) {
|
||||||
|
const struct datetime_event *event = cast_datetime_event(aeh);
|
||||||
|
|
||||||
|
strncpy(date_text, event->date_text, sizeof(date_text));
|
||||||
|
date_text[sizeof(date_text) - 1] = '\0';
|
||||||
|
strncpy(time_text, event->time_text, sizeof(time_text));
|
||||||
|
time_text[sizeof(time_text) - 1] = '\0';
|
||||||
|
refresh_ui();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_module_state_event(aeh)) {
|
if (is_module_state_event(aeh)) {
|
||||||
const struct module_state_event *event = cast_module_state_event(aeh);
|
const struct module_state_event *event = cast_module_state_event(aeh);
|
||||||
int err;
|
int err;
|
||||||
@@ -221,8 +247,10 @@ static bool app_event_handler(const struct app_event_header *aeh)
|
|||||||
|
|
||||||
APP_EVENT_LISTENER(MODULE, app_event_handler);
|
APP_EVENT_LISTENER(MODULE, app_event_handler);
|
||||||
APP_EVENT_SUBSCRIBE(MODULE, bat_state_event);
|
APP_EVENT_SUBSCRIBE(MODULE, bat_state_event);
|
||||||
|
APP_EVENT_SUBSCRIBE(MODULE, datetime_event);
|
||||||
APP_EVENT_SUBSCRIBE(MODULE, hid_led_event);
|
APP_EVENT_SUBSCRIBE(MODULE, hid_led_event);
|
||||||
APP_EVENT_SUBSCRIBE(MODULE, module_state_event);
|
APP_EVENT_SUBSCRIBE(MODULE, module_state_event);
|
||||||
APP_EVENT_SUBSCRIBE(MODULE, mode_switch_event);
|
APP_EVENT_SUBSCRIBE(MODULE, mode_switch_event);
|
||||||
|
APP_EVENT_SUBSCRIBE(MODULE, theme_rgb_update_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);
|
||||||
|
|||||||
27
src/events/datetime_event.c
Normal file
27
src/events/datetime_event.c
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#include "datetime_event.h"
|
||||||
|
|
||||||
|
static void log_datetime_event(const struct app_event_header *aeh)
|
||||||
|
{
|
||||||
|
const struct datetime_event *event = cast_datetime_event(aeh);
|
||||||
|
|
||||||
|
APP_EVENT_MANAGER_LOG(aeh, "date:%s time:%s",
|
||||||
|
event->date_text, event->time_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void profile_datetime_event(struct log_event_buf *buf,
|
||||||
|
const struct app_event_header *aeh)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(buf);
|
||||||
|
ARG_UNUSED(aeh);
|
||||||
|
}
|
||||||
|
|
||||||
|
APP_EVENT_INFO_DEFINE(datetime_event,
|
||||||
|
ENCODE(),
|
||||||
|
ENCODE(),
|
||||||
|
profile_datetime_event);
|
||||||
|
|
||||||
|
APP_EVENT_TYPE_DEFINE(datetime_event,
|
||||||
|
log_datetime_event,
|
||||||
|
&datetime_event_info,
|
||||||
|
APP_EVENT_FLAGS_CREATE(
|
||||||
|
APP_EVENT_TYPE_FLAGS_INIT_LOG_ENABLE));
|
||||||
34
src/events/theme_rgb_update_event.c
Normal file
34
src/events/theme_rgb_update_event.c
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#include "theme_rgb_update_event.h"
|
||||||
|
|
||||||
|
static void log_theme_rgb_update_event(const struct app_event_header *aeh)
|
||||||
|
{
|
||||||
|
const struct theme_rgb_update_event *event =
|
||||||
|
cast_theme_rgb_update_event(aeh);
|
||||||
|
|
||||||
|
APP_EVENT_MANAGER_LOG(aeh, "r:%u g:%u b:%u",
|
||||||
|
event->theme.r, event->theme.g, event->theme.b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void profile_theme_rgb_update_event(struct log_event_buf *buf,
|
||||||
|
const struct app_event_header *aeh)
|
||||||
|
{
|
||||||
|
const struct theme_rgb_update_event *event =
|
||||||
|
cast_theme_rgb_update_event(aeh);
|
||||||
|
|
||||||
|
nrf_profiler_log_encode_uint8(buf, event->theme.r);
|
||||||
|
nrf_profiler_log_encode_uint8(buf, event->theme.g);
|
||||||
|
nrf_profiler_log_encode_uint8(buf, event->theme.b);
|
||||||
|
}
|
||||||
|
|
||||||
|
APP_EVENT_INFO_DEFINE(theme_rgb_update_event,
|
||||||
|
ENCODE(NRF_PROFILER_ARG_U8,
|
||||||
|
NRF_PROFILER_ARG_U8,
|
||||||
|
NRF_PROFILER_ARG_U8),
|
||||||
|
ENCODE("r", "g", "b"),
|
||||||
|
profile_theme_rgb_update_event);
|
||||||
|
|
||||||
|
APP_EVENT_TYPE_DEFINE(theme_rgb_update_event,
|
||||||
|
log_theme_rgb_update_event,
|
||||||
|
&theme_rgb_update_event_info,
|
||||||
|
APP_EVENT_FLAGS_CREATE(
|
||||||
|
APP_EVENT_TYPE_FLAGS_INIT_LOG_ENABLE));
|
||||||
41
src/events/time_sync_event.c
Normal file
41
src/events/time_sync_event.c
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include "time_sync_event.h"
|
||||||
|
|
||||||
|
static void log_time_sync_event(const struct app_event_header *aeh)
|
||||||
|
{
|
||||||
|
const struct time_sync_event *event = cast_time_sync_event(aeh);
|
||||||
|
|
||||||
|
APP_EVENT_MANAGER_LOG(aeh,
|
||||||
|
"ver:%u flags:0x%08x tz:%d utc_ms:%llu acc:%u",
|
||||||
|
event->version,
|
||||||
|
event->flags,
|
||||||
|
event->timezone_min,
|
||||||
|
event->utc_ms,
|
||||||
|
event->accuracy_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void profile_time_sync_event(struct log_event_buf *buf,
|
||||||
|
const struct app_event_header *aeh)
|
||||||
|
{
|
||||||
|
const struct time_sync_event *event = cast_time_sync_event(aeh);
|
||||||
|
|
||||||
|
nrf_profiler_log_encode_uint32(buf, event->version);
|
||||||
|
nrf_profiler_log_encode_uint32(buf, event->flags);
|
||||||
|
nrf_profiler_log_encode_int32(buf, event->timezone_min);
|
||||||
|
nrf_profiler_log_encode_uint32(buf, (uint32_t)(event->utc_ms & 0xFFFFFFFFULL));
|
||||||
|
nrf_profiler_log_encode_uint32(buf, event->accuracy_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
APP_EVENT_INFO_DEFINE(time_sync_event,
|
||||||
|
ENCODE(NRF_PROFILER_ARG_U32,
|
||||||
|
NRF_PROFILER_ARG_U32,
|
||||||
|
NRF_PROFILER_ARG_S32,
|
||||||
|
NRF_PROFILER_ARG_U32,
|
||||||
|
NRF_PROFILER_ARG_U32),
|
||||||
|
ENCODE("version", "flags", "timezone_min", "utc_ms_lo", "accuracy_ms"),
|
||||||
|
profile_time_sync_event);
|
||||||
|
|
||||||
|
APP_EVENT_TYPE_DEFINE(time_sync_event,
|
||||||
|
log_time_sync_event,
|
||||||
|
&time_sync_event_info,
|
||||||
|
APP_EVENT_FLAGS_CREATE(
|
||||||
|
APP_EVENT_TYPE_FLAGS_INIT_LOG_ENABLE));
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "led_effect/led_effect.h"
|
#include "led_effect/led_effect.h"
|
||||||
#include "led_strip_en_event.h"
|
#include "led_strip_en_event.h"
|
||||||
|
#include "theme_rgb_update_event.h"
|
||||||
#include "theme_color.h"
|
#include "theme_color.h"
|
||||||
|
|
||||||
LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF);
|
LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF);
|
||||||
@@ -276,6 +277,21 @@ static bool handle_led_strip_en_event(const struct led_strip_en_event *event)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool handle_theme_rgb_update_event(const struct theme_rgb_update_event *event)
|
||||||
|
{
|
||||||
|
current_theme = event->theme;
|
||||||
|
|
||||||
|
if ((effect != NULL) && (effect->ops != NULL)) {
|
||||||
|
effect->ops->set_theme(effect, ¤t_theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (running && enabled && (effect != NULL) && effect->ops->is_active(effect)) {
|
||||||
|
schedule_effect_tick(K_NO_WAIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool app_event_handler(const struct app_event_header *aeh)
|
static bool app_event_handler(const struct app_event_header *aeh)
|
||||||
{
|
{
|
||||||
if (is_button_event(aeh)) {
|
if (is_button_event(aeh)) {
|
||||||
@@ -286,6 +302,10 @@ static bool app_event_handler(const struct app_event_header *aeh)
|
|||||||
return handle_led_strip_en_event(cast_led_strip_en_event(aeh));
|
return handle_led_strip_en_event(cast_led_strip_en_event(aeh));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_theme_rgb_update_event(aeh)) {
|
||||||
|
return handle_theme_rgb_update_event(cast_theme_rgb_update_event(aeh));
|
||||||
|
}
|
||||||
|
|
||||||
if (is_module_state_event(aeh)) {
|
if (is_module_state_event(aeh)) {
|
||||||
const struct module_state_event *event = cast_module_state_event(aeh);
|
const struct module_state_event *event = cast_module_state_event(aeh);
|
||||||
|
|
||||||
@@ -343,5 +363,6 @@ APP_EVENT_LISTENER(MODULE, app_event_handler);
|
|||||||
APP_EVENT_SUBSCRIBE_EARLY(MODULE, button_event);
|
APP_EVENT_SUBSCRIBE_EARLY(MODULE, button_event);
|
||||||
APP_EVENT_SUBSCRIBE(MODULE, led_strip_en_event);
|
APP_EVENT_SUBSCRIBE(MODULE, led_strip_en_event);
|
||||||
APP_EVENT_SUBSCRIBE(MODULE, module_state_event);
|
APP_EVENT_SUBSCRIBE(MODULE, module_state_event);
|
||||||
|
APP_EVENT_SUBSCRIBE(MODULE, theme_rgb_update_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);
|
||||||
|
|||||||
@@ -18,8 +18,11 @@
|
|||||||
|
|
||||||
#include <proto/device_comm.pb.h>
|
#include <proto/device_comm.pb.h>
|
||||||
|
|
||||||
|
#include "theme_rgb_update_event.h"
|
||||||
|
#include "time_sync_event.h"
|
||||||
#include "cdc_proto_tx_event.h"
|
#include "cdc_proto_tx_event.h"
|
||||||
#include "function_bitmap_update_event.h"
|
#include "function_bitmap_update_event.h"
|
||||||
|
#include "hid_led_event.h"
|
||||||
#include "key_function_event.h"
|
#include "key_function_event.h"
|
||||||
#include "protocol_module.h"
|
#include "protocol_module.h"
|
||||||
#include "usb_device_state_event.h"
|
#include "usb_device_state_event.h"
|
||||||
@@ -31,7 +34,7 @@ LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF);
|
|||||||
#define PROTOCOL_PRODUCT_ID 0x52F0U
|
#define PROTOCOL_PRODUCT_ID 0x52F0U
|
||||||
#define PROTOCOL_FIRMWARE_MAJOR 0U
|
#define PROTOCOL_FIRMWARE_MAJOR 0U
|
||||||
#define PROTOCOL_FIRMWARE_MINOR 0U
|
#define PROTOCOL_FIRMWARE_MINOR 0U
|
||||||
#define PROTOCOL_CAPABILITY_FLAGS BIT(0)
|
#define PROTOCOL_CAPABILITY_FLAGS (BIT(0) | BIT(1) | BIT(2) | BIT(3))
|
||||||
|
|
||||||
static bool initialized;
|
static bool initialized;
|
||||||
static bool running;
|
static bool running;
|
||||||
@@ -50,6 +53,12 @@ static bool type_matches_body(uint8_t type, const CdcPacketBody *body)
|
|||||||
return body->which_body == CdcPacketBody_bitmap_tag;
|
return body->which_body == CdcPacketBody_bitmap_tag;
|
||||||
case CDC_PROTO_TYPE_FUNCTION_KEY_EVENT:
|
case CDC_PROTO_TYPE_FUNCTION_KEY_EVENT:
|
||||||
return body->which_body == CdcPacketBody_function_key_event_tag;
|
return body->which_body == CdcPacketBody_function_key_event_tag;
|
||||||
|
case CDC_PROTO_TYPE_LED_STATE:
|
||||||
|
return body->which_body == CdcPacketBody_led_state_tag;
|
||||||
|
case CDC_PROTO_TYPE_TIME_SYNC:
|
||||||
|
return body->which_body == CdcPacketBody_time_sync_tag;
|
||||||
|
case CDC_PROTO_TYPE_THEME_RGB:
|
||||||
|
return body->which_body == CdcPacketBody_theme_rgb_tag;
|
||||||
case CDC_PROTO_TYPE_ACK:
|
case CDC_PROTO_TYPE_ACK:
|
||||||
return body->which_body == CdcPacketBody_ack_tag;
|
return body->which_body == CdcPacketBody_ack_tag;
|
||||||
case CDC_PROTO_TYPE_ERROR:
|
case CDC_PROTO_TYPE_ERROR:
|
||||||
@@ -152,6 +161,17 @@ static int encode_function_key_event(uint16_t usage, uint8_t action,
|
|||||||
return encode_body(&body, payload, payload_buf_size, payload_len);
|
return encode_body(&body, payload, payload_buf_size, payload_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int encode_led_state(uint32_t led_mask, uint8_t *payload,
|
||||||
|
size_t payload_buf_size, size_t *payload_len)
|
||||||
|
{
|
||||||
|
CdcPacketBody body = CdcPacketBody_init_zero;
|
||||||
|
|
||||||
|
body.which_body = CdcPacketBody_led_state_tag;
|
||||||
|
body.body.led_state.led_mask = led_mask;
|
||||||
|
|
||||||
|
return encode_body(&body, payload, payload_buf_size, payload_len);
|
||||||
|
}
|
||||||
|
|
||||||
static int submit_cdc_proto_tx_event(uint8_t type, const uint8_t *payload,
|
static int submit_cdc_proto_tx_event(uint8_t type, const uint8_t *payload,
|
||||||
size_t payload_len)
|
size_t payload_len)
|
||||||
{
|
{
|
||||||
@@ -188,6 +208,45 @@ static int submit_function_bitmap_update_event(const Bitmap *bitmap)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int submit_theme_rgb_update_event(const ThemeRgb *theme_rgb)
|
||||||
|
{
|
||||||
|
struct theme_rgb_update_event *event;
|
||||||
|
|
||||||
|
if ((theme_rgb == NULL) ||
|
||||||
|
(theme_rgb->red > 255U) ||
|
||||||
|
(theme_rgb->green > 255U) ||
|
||||||
|
(theme_rgb->blue > 255U)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
event = new_theme_rgb_update_event();
|
||||||
|
event->theme.r = (uint8_t)theme_rgb->red;
|
||||||
|
event->theme.g = (uint8_t)theme_rgb->green;
|
||||||
|
event->theme.b = (uint8_t)theme_rgb->blue;
|
||||||
|
APP_EVENT_SUBMIT(event);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int submit_time_sync_event(const TimeSync *time_sync)
|
||||||
|
{
|
||||||
|
struct time_sync_event *event;
|
||||||
|
|
||||||
|
if (time_sync == NULL) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
event = new_time_sync_event();
|
||||||
|
event->version = time_sync->version;
|
||||||
|
event->flags = time_sync->flags;
|
||||||
|
event->timezone_min = time_sync->timezone_min;
|
||||||
|
event->utc_ms = time_sync->utc_ms;
|
||||||
|
event->accuracy_ms = time_sync->accuracy_ms;
|
||||||
|
APP_EVENT_SUBMIT(event);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int encode_error_response(uint8_t req_type, ErrorCode error_code,
|
static int encode_error_response(uint8_t req_type, ErrorCode error_code,
|
||||||
uint8_t *rsp_type, uint8_t *rsp_payload,
|
uint8_t *rsp_type, uint8_t *rsp_payload,
|
||||||
size_t rsp_payload_buf_size,
|
size_t rsp_payload_buf_size,
|
||||||
@@ -339,6 +398,51 @@ int protocol_module_process_cdc_packet(uint8_t req_type,
|
|||||||
return encode_ack_response(req_type, rsp_type, rsp_payload,
|
return encode_ack_response(req_type, rsp_type, rsp_payload,
|
||||||
rsp_payload_buf_size, rsp_payload_len);
|
rsp_payload_buf_size, rsp_payload_len);
|
||||||
|
|
||||||
|
case CDC_PROTO_TYPE_TIME_SYNC:
|
||||||
|
if (!hello_done) {
|
||||||
|
return encode_error_response(req_type, ErrorCode_ERROR_CODE_NOT_READY,
|
||||||
|
rsp_type, rsp_payload,
|
||||||
|
rsp_payload_buf_size,
|
||||||
|
rsp_payload_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (body.body.time_sync.version != 1U) {
|
||||||
|
return encode_error_response(req_type, ErrorCode_ERROR_CODE_INVALID_PARAM,
|
||||||
|
rsp_type, rsp_payload,
|
||||||
|
rsp_payload_buf_size,
|
||||||
|
rsp_payload_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = submit_time_sync_event(&body.body.time_sync);
|
||||||
|
if (err) {
|
||||||
|
return encode_error_response(req_type, ErrorCode_ERROR_CODE_INVALID_PARAM,
|
||||||
|
rsp_type, rsp_payload,
|
||||||
|
rsp_payload_buf_size,
|
||||||
|
rsp_payload_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return encode_ack_response(req_type, rsp_type, rsp_payload,
|
||||||
|
rsp_payload_buf_size, rsp_payload_len);
|
||||||
|
|
||||||
|
case CDC_PROTO_TYPE_THEME_RGB:
|
||||||
|
if (!hello_done) {
|
||||||
|
return encode_error_response(req_type, ErrorCode_ERROR_CODE_NOT_READY,
|
||||||
|
rsp_type, rsp_payload,
|
||||||
|
rsp_payload_buf_size,
|
||||||
|
rsp_payload_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = submit_theme_rgb_update_event(&body.body.theme_rgb);
|
||||||
|
if (err) {
|
||||||
|
return encode_error_response(req_type, ErrorCode_ERROR_CODE_INVALID_PARAM,
|
||||||
|
rsp_type, rsp_payload,
|
||||||
|
rsp_payload_buf_size,
|
||||||
|
rsp_payload_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return encode_ack_response(req_type, rsp_type, rsp_payload,
|
||||||
|
rsp_payload_buf_size, rsp_payload_len);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_WRN("Unsupported CDC protocol type:0x%02x", req_type);
|
LOG_WRN("Unsupported CDC protocol type:0x%02x", req_type);
|
||||||
return encode_error_response(req_type, ErrorCode_ERROR_CODE_UNKNOWN_TYPE,
|
return encode_error_response(req_type, ErrorCode_ERROR_CODE_UNKNOWN_TYPE,
|
||||||
@@ -373,6 +477,30 @@ static bool handle_key_function_event(const struct key_function_event *event)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool handle_hid_led_event(const struct hid_led_event *event)
|
||||||
|
{
|
||||||
|
uint8_t payload[64];
|
||||||
|
size_t payload_len;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!running || !usb_active || !hello_done) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = encode_led_state(event->led_bm, payload, sizeof(payload), &payload_len);
|
||||||
|
if (err) {
|
||||||
|
LOG_WRN("LedState encode failed (%d)", err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = submit_cdc_proto_tx_event(CDC_PROTO_TYPE_LED_STATE, payload, payload_len);
|
||||||
|
if (err) {
|
||||||
|
LOG_WRN("LedState submit failed (%d)", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool handle_usb_device_state_event(const struct usb_device_state_event *event)
|
static bool handle_usb_device_state_event(const struct usb_device_state_event *event)
|
||||||
{
|
{
|
||||||
usb_active = (event->state == USB_DEVICE_STATE_ACTIVE);
|
usb_active = (event->state == USB_DEVICE_STATE_ACTIVE);
|
||||||
@@ -389,6 +517,10 @@ static bool app_event_handler(const struct app_event_header *aeh)
|
|||||||
return handle_key_function_event(cast_key_function_event(aeh));
|
return handle_key_function_event(cast_key_function_event(aeh));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_hid_led_event(aeh)) {
|
||||||
|
return handle_hid_led_event(cast_hid_led_event(aeh));
|
||||||
|
}
|
||||||
|
|
||||||
if (is_usb_device_state_event(aeh)) {
|
if (is_usb_device_state_event(aeh)) {
|
||||||
return handle_usb_device_state_event(cast_usb_device_state_event(aeh));
|
return handle_usb_device_state_event(cast_usb_device_state_event(aeh));
|
||||||
}
|
}
|
||||||
@@ -453,6 +585,7 @@ static bool app_event_handler(const struct app_event_header *aeh)
|
|||||||
}
|
}
|
||||||
|
|
||||||
APP_EVENT_LISTENER(MODULE, app_event_handler);
|
APP_EVENT_LISTENER(MODULE, app_event_handler);
|
||||||
|
APP_EVENT_SUBSCRIBE(MODULE, hid_led_event);
|
||||||
APP_EVENT_SUBSCRIBE(MODULE, key_function_event);
|
APP_EVENT_SUBSCRIBE(MODULE, key_function_event);
|
||||||
APP_EVENT_SUBSCRIBE(MODULE, module_state_event);
|
APP_EVENT_SUBSCRIBE(MODULE, module_state_event);
|
||||||
APP_EVENT_SUBSCRIBE(MODULE, usb_device_state_event);
|
APP_EVENT_SUBSCRIBE(MODULE, usb_device_state_event);
|
||||||
|
|||||||
186
src/time_sync_module.c
Normal file
186
src/time_sync_module.c
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <app_event_manager.h>
|
||||||
|
|
||||||
|
#define MODULE time_sync_module
|
||||||
|
#include <caf/events/module_state_event.h>
|
||||||
|
#include <caf/events/power_event.h>
|
||||||
|
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
#include <zephyr/sys/printk.h>
|
||||||
|
|
||||||
|
#include "datetime_event.h"
|
||||||
|
#include "time_sync_event.h"
|
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF);
|
||||||
|
|
||||||
|
#define TIME_SYNC_REFRESH_PERIOD K_SECONDS(1)
|
||||||
|
|
||||||
|
static struct k_work_delayable refresh_work;
|
||||||
|
static bool initialized;
|
||||||
|
static bool running;
|
||||||
|
static int32_t timezone_min;
|
||||||
|
static uint64_t utc_ms_base;
|
||||||
|
static int64_t uptime_ms_base;
|
||||||
|
|
||||||
|
static void submit_datetime_event(void)
|
||||||
|
{
|
||||||
|
struct datetime_event *event = new_datetime_event();
|
||||||
|
struct tm tm_buf;
|
||||||
|
time_t seconds;
|
||||||
|
int64_t local_ms;
|
||||||
|
|
||||||
|
local_ms = (int64_t)utc_ms_base +
|
||||||
|
(k_uptime_get() - uptime_ms_base) +
|
||||||
|
((int64_t)timezone_min * 60LL * 1000LL);
|
||||||
|
if (local_ms < 0) {
|
||||||
|
local_ms = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
seconds = (time_t)(local_ms / 1000LL);
|
||||||
|
if (gmtime_r(&seconds, &tm_buf) == NULL) {
|
||||||
|
strncpy(event->date_text, "1970/01/01", sizeof(event->date_text));
|
||||||
|
strncpy(event->time_text, "00:00:00", sizeof(event->time_text));
|
||||||
|
} else {
|
||||||
|
snprintk(event->date_text, sizeof(event->date_text),
|
||||||
|
"%04u/%02u/%02u",
|
||||||
|
(unsigned int)(tm_buf.tm_year + 1900),
|
||||||
|
(unsigned int)(tm_buf.tm_mon + 1),
|
||||||
|
(unsigned int)tm_buf.tm_mday);
|
||||||
|
snprintk(event->time_text, sizeof(event->time_text),
|
||||||
|
"%02u:%02u:%02u",
|
||||||
|
(unsigned int)tm_buf.tm_hour,
|
||||||
|
(unsigned int)tm_buf.tm_min,
|
||||||
|
(unsigned int)tm_buf.tm_sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
APP_EVENT_SUBMIT(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void refresh_work_handler(struct k_work *work)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(work);
|
||||||
|
|
||||||
|
if (!running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
submit_datetime_event();
|
||||||
|
k_work_reschedule(&refresh_work, TIME_SYNC_REFRESH_PERIOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int module_init(void)
|
||||||
|
{
|
||||||
|
timezone_min = 0;
|
||||||
|
utc_ms_base = 0U;
|
||||||
|
uptime_ms_base = k_uptime_get();
|
||||||
|
k_work_init_delayable(&refresh_work, refresh_work_handler);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int module_start(void)
|
||||||
|
{
|
||||||
|
if (running) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
running = true;
|
||||||
|
k_work_reschedule(&refresh_work, K_NO_WAIT);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void module_pause(void)
|
||||||
|
{
|
||||||
|
if (!running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_work_cancel_delayable(&refresh_work);
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool handle_time_sync_event(const struct time_sync_event *event)
|
||||||
|
{
|
||||||
|
if (event->version != 1U) {
|
||||||
|
LOG_WRN("Unexpected TimeSync version:%u", event->version);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
timezone_min = event->timezone_min;
|
||||||
|
utc_ms_base = event->utc_ms;
|
||||||
|
uptime_ms_base = k_uptime_get();
|
||||||
|
|
||||||
|
if (running) {
|
||||||
|
k_work_reschedule(&refresh_work, K_NO_WAIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool app_event_handler(const struct app_event_header *aeh)
|
||||||
|
{
|
||||||
|
if (is_time_sync_event(aeh)) {
|
||||||
|
return handle_time_sync_event(cast_time_sync_event(aeh));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_module_state_event(aeh)) {
|
||||||
|
const struct module_state_event *event = cast_module_state_event(aeh);
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) {
|
||||||
|
if (!initialized) {
|
||||||
|
err = module_init();
|
||||||
|
if (err) {
|
||||||
|
module_set_state(MODULE_STATE_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = module_start();
|
||||||
|
if (err) {
|
||||||
|
module_set_state(MODULE_STATE_ERROR);
|
||||||
|
} else {
|
||||||
|
module_set_state(MODULE_STATE_READY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_power_down_event(aeh)) {
|
||||||
|
if (initialized) {
|
||||||
|
module_pause();
|
||||||
|
module_set_state(MODULE_STATE_STANDBY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_wake_up_event(aeh)) {
|
||||||
|
if (initialized) {
|
||||||
|
int err = module_start();
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
module_set_state(MODULE_STATE_ERROR);
|
||||||
|
} else {
|
||||||
|
module_set_state(MODULE_STATE_READY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
APP_EVENT_LISTENER(MODULE, app_event_handler);
|
||||||
|
APP_EVENT_SUBSCRIBE(MODULE, module_state_event);
|
||||||
|
APP_EVENT_SUBSCRIBE(MODULE, time_sync_event);
|
||||||
|
APP_EVENT_SUBSCRIBE_EARLY(MODULE, power_down_event);
|
||||||
|
APP_EVENT_SUBSCRIBE(MODULE, wake_up_event);
|
||||||
Reference in New Issue
Block a user