Add firmware GATT protocol module

This commit is contained in:
2026-04-11 13:00:04 +08:00
parent 9ba44586b3
commit 30f1af1a8c
2 changed files with 204 additions and 0 deletions

View File

@@ -0,0 +1,178 @@
#include <zephyr/bluetooth/gatt.h>
#include <app_event_manager.h>
#define MODULE ble_gatt_proto
#include <caf/events/module_state_event.h>
#include "function_key_event.h"
#include "keyboard_led_event.h"
#include "keyboard_proto.h"
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF);
#define BT_UUID_KEYBOARD_PROTO_SERVICE_VAL \
BT_UUID_128_ENCODE(0x0b7f6000, 0x38d2, 0x4f62, 0x8f6f, 0x36c4fd73a110)
#define BT_UUID_KEYBOARD_PROTO_RX_VAL \
BT_UUID_128_ENCODE(0x0b7f6001, 0x38d2, 0x4f62, 0x8f6f, 0x36c4fd73a110)
#define BT_UUID_KEYBOARD_PROTO_TX_VAL \
BT_UUID_128_ENCODE(0x0b7f6002, 0x38d2, 0x4f62, 0x8f6f, 0x36c4fd73a110)
#define BT_UUID_KEYBOARD_PROTO_SERVICE \
BT_UUID_DECLARE_128(BT_UUID_KEYBOARD_PROTO_SERVICE_VAL)
#define BT_UUID_KEYBOARD_PROTO_RX \
BT_UUID_DECLARE_128(BT_UUID_KEYBOARD_PROTO_RX_VAL)
#define BT_UUID_KEYBOARD_PROTO_TX \
BT_UUID_DECLARE_128(BT_UUID_KEYBOARD_PROTO_TX_VAL)
struct ble_gatt_proto_ctx {
bool ready;
bool notify_enabled;
};
static struct ble_gatt_proto_ctx g_ble_proto;
static void ble_gatt_proto_ccc_changed(
const struct bt_gatt_attr *attr,
uint16_t value)
{
ARG_UNUSED(attr);
g_ble_proto.notify_enabled = (value == BT_GATT_CCC_NOTIFY);
}
static ssize_t ble_gatt_proto_rx_write(
struct bt_conn *conn,
const struct bt_gatt_attr *attr,
const void *buf,
uint16_t len,
uint16_t offset,
uint8_t flags)
{
struct keyboard_cdc_CdcPacketBody body;
ARG_UNUSED(conn);
ARG_UNUSED(attr);
ARG_UNUSED(flags);
if (!g_ble_proto.ready) {
return BT_GATT_ERR(BT_ATT_ERR_UNLIKELY);
}
if (offset != 0U) {
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
}
if (!keyboard_proto_decode_body(buf, len, &body)) {
return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED);
}
(void)keyboard_proto_handle_host_body(
&body,
KEYBOARD_PROTO_TRANSPORT_GATT,
ble_gatt_proto_send_body,
NULL);
return len;
}
BT_GATT_SERVICE_DEFINE(
keyboard_proto_svc,
BT_GATT_PRIMARY_SERVICE(BT_UUID_KEYBOARD_PROTO_SERVICE),
BT_GATT_CHARACTERISTIC(BT_UUID_KEYBOARD_PROTO_RX,
BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP,
BT_GATT_PERM_WRITE,
NULL,
ble_gatt_proto_rx_write,
NULL),
BT_GATT_CHARACTERISTIC(BT_UUID_KEYBOARD_PROTO_TX,
BT_GATT_CHRC_NOTIFY,
BT_GATT_PERM_NONE,
NULL,
NULL,
NULL),
BT_GATT_CCC(ble_gatt_proto_ccc_changed,
BT_GATT_PERM_READ | BT_GATT_PERM_WRITE));
static bool ble_gatt_proto_send_body(
const struct keyboard_cdc_CdcPacketBody *body,
void *user_data)
{
uint8_t buffer[KEYBOARD_PROTO_MAX_BODY_SIZE];
size_t size = 0U;
ARG_UNUSED(user_data);
if (!g_ble_proto.ready || !g_ble_proto.notify_enabled) {
return false;
}
if (!keyboard_proto_encode_body(body, buffer, sizeof(buffer), &size)) {
return false;
}
return bt_gatt_notify(NULL, &keyboard_proto_svc.attrs[4], buffer, size) == 0;
}
static bool handle_module_state_event(const struct module_state_event *event)
{
if (!check_state(event, MODULE_ID(main), MODULE_STATE_READY)) {
return false;
}
g_ble_proto.ready = true;
module_set_state(MODULE_STATE_READY);
return false;
}
static bool handle_function_key_event(const struct function_key_event *event)
{
struct keyboard_cdc_CdcPacketBody body;
if (!keyboard_proto_build_function_key_event_body(event->usage,
event->pressed,
&body)) {
return false;
}
(void)ble_gatt_proto_send_body(&body, NULL);
return false;
}
static bool handle_keyboard_led_event(const struct keyboard_led_event *event)
{
struct keyboard_cdc_CdcPacketBody body;
if (!keyboard_proto_build_led_state_body(
keyboard_led_event_get_mask(event),
&body)) {
return false;
}
(void)ble_gatt_proto_send_body(&body, NULL);
return false;
}
static bool app_event_handler(const struct app_event_header *aeh)
{
if (is_module_state_event(aeh)) {
return handle_module_state_event(cast_module_state_event(aeh));
}
if (is_function_key_event(aeh)) {
return handle_function_key_event(cast_function_key_event(aeh));
}
if (is_keyboard_led_event(aeh)) {
return handle_keyboard_led_event(cast_keyboard_led_event(aeh));
}
__ASSERT_NO_MSG(false);
return false;
}
APP_EVENT_LISTENER(MODULE, app_event_handler);
APP_EVENT_SUBSCRIBE(MODULE, module_state_event);
APP_EVENT_SUBSCRIBE(MODULE, function_key_event);
APP_EVENT_SUBSCRIBE(MODULE, keyboard_led_event);