Add firmware GATT protocol module
This commit is contained in:
178
src/modules/ble_gatt_proto_module.c
Normal file
178
src/modules/ble_gatt_proto_module.c
Normal 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);
|
||||
Reference in New Issue
Block a user