feat(keyboard): 添加蓝牙HID支持和电池状态事件
- 添加BLE相关模块:ble_adv_ctrl_module、ble_adv_uuid16、ble_bas_module、 ble_hid_module - 新增电池状态事件(bat_state_event)用于监控电池电量、充电状态 - 在多个事件中添加HID_TRANSPORT_BLE支持,包括hid_led_event、 set_protocol_event等 - 更新配置文件prj.conf以启用蓝牙功能、HID服务和设置系统 - 修改电池模块以计算并报告电池SOC百分比 - 集成CAF设置加载器以管理蓝牙配对信息
This commit is contained in:
@@ -46,12 +46,18 @@ struct hid_transport_state_data {
|
||||
|
||||
struct in_flight_report {
|
||||
bool active;
|
||||
enum hid_transport transport;
|
||||
enum keyboard_report_type report_type;
|
||||
uint16_t sequence;
|
||||
};
|
||||
|
||||
static struct hid_transport_state_data usb_state = {
|
||||
.protocol_mode = KEYBOARD_PROTOCOL_MODE_REPORT,
|
||||
static struct hid_transport_state_data transport_state[HID_TRANSPORT_COUNT] = {
|
||||
[HID_TRANSPORT_USB] = {
|
||||
.protocol_mode = KEYBOARD_PROTOCOL_MODE_REPORT,
|
||||
},
|
||||
[HID_TRANSPORT_BLE] = {
|
||||
.protocol_mode = KEYBOARD_PROTOCOL_MODE_REPORT,
|
||||
},
|
||||
};
|
||||
static struct pending_report pending_keys;
|
||||
static struct pending_report pending_consumer_latest;
|
||||
@@ -65,6 +71,22 @@ static uint16_t next_sequence;
|
||||
static bool initialized;
|
||||
static bool running;
|
||||
|
||||
static bool mode_to_transport(enum mode_switch_mode mode, enum hid_transport *transport)
|
||||
{
|
||||
switch (mode) {
|
||||
case MODE_SWITCH_USB:
|
||||
*transport = HID_TRANSPORT_USB;
|
||||
return true;
|
||||
|
||||
case MODE_SWITCH_BLE:
|
||||
*transport = HID_TRANSPORT_BLE;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_pending_reports(void)
|
||||
{
|
||||
memset(&pending_keys, 0, sizeof(pending_keys));
|
||||
@@ -111,30 +133,41 @@ static bool consumer_fifo_pop(struct queued_report *entry)
|
||||
|
||||
static bool transport_can_send_report(enum keyboard_report_type report_type)
|
||||
{
|
||||
if ((current_mode != MODE_SWITCH_USB) || !usb_state.ready || in_flight.active) {
|
||||
enum hid_transport transport;
|
||||
struct hid_transport_state_data *state;
|
||||
|
||||
if (!mode_to_transport(current_mode, &transport) || in_flight.active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
state = &transport_state[transport];
|
||||
|
||||
if (!state->ready) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (report_type == KEYBOARD_REPORT_TYPE_KEYS) {
|
||||
return usb_state.keys_ready;
|
||||
return state->keys_ready;
|
||||
}
|
||||
|
||||
return usb_state.consumer_ready;
|
||||
return state->consumer_ready;
|
||||
}
|
||||
|
||||
static void submit_hid_tx_report_event(enum keyboard_report_type report_type,
|
||||
static void submit_hid_tx_report_event(enum hid_transport transport,
|
||||
enum keyboard_report_type report_type,
|
||||
enum keyboard_protocol_mode protocol_mode,
|
||||
const uint8_t *data, size_t size)
|
||||
{
|
||||
struct hid_tx_report_event *event = new_hid_tx_report_event(size);
|
||||
|
||||
event->transport = HID_TRANSPORT_USB;
|
||||
event->transport = transport;
|
||||
event->report_type = report_type;
|
||||
event->protocol_mode = protocol_mode;
|
||||
event->sequence = next_sequence++;
|
||||
memcpy(event->dyndata.data, data, size);
|
||||
|
||||
in_flight.active = true;
|
||||
in_flight.transport = transport;
|
||||
in_flight.report_type = report_type;
|
||||
in_flight.sequence = event->sequence;
|
||||
|
||||
@@ -144,17 +177,26 @@ static void submit_hid_tx_report_event(enum keyboard_report_type report_type,
|
||||
static void try_send_next(void)
|
||||
{
|
||||
struct queued_report queued;
|
||||
enum hid_transport transport;
|
||||
struct hid_transport_state_data *state;
|
||||
|
||||
if (!running || in_flight.active || (current_mode != MODE_SWITCH_USB) || !usb_state.ready) {
|
||||
if (!running || in_flight.active || !mode_to_transport(current_mode, &transport)) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = &transport_state[transport];
|
||||
|
||||
if (!state->ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pending_keys.valid && transport_can_send_report(KEYBOARD_REPORT_TYPE_KEYS)) {
|
||||
if (pending_keys.protocol_mode != usb_state.protocol_mode) {
|
||||
if (pending_keys.protocol_mode != state->protocol_mode) {
|
||||
LOG_WRN("Drop stale keys report after protocol change");
|
||||
pending_keys.valid = false;
|
||||
} else {
|
||||
submit_hid_tx_report_event(pending_keys.report_type,
|
||||
submit_hid_tx_report_event(transport,
|
||||
pending_keys.report_type,
|
||||
pending_keys.protocol_mode,
|
||||
pending_keys.data,
|
||||
pending_keys.size);
|
||||
@@ -166,26 +208,38 @@ static void try_send_next(void)
|
||||
if ((consumer_fifo_count > 0U) &&
|
||||
transport_can_send_report(KEYBOARD_REPORT_TYPE_CONSUMER) &&
|
||||
consumer_fifo_pop(&queued)) {
|
||||
submit_hid_tx_report_event(queued.report_type,
|
||||
queued.protocol_mode,
|
||||
queued.data,
|
||||
queued.size);
|
||||
return;
|
||||
if (queued.protocol_mode != state->protocol_mode) {
|
||||
LOG_WRN("Drop stale consumer report after protocol change");
|
||||
} else {
|
||||
submit_hid_tx_report_event(transport,
|
||||
queued.report_type,
|
||||
queued.protocol_mode,
|
||||
queued.data,
|
||||
queued.size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (pending_consumer_latest.valid &&
|
||||
transport_can_send_report(KEYBOARD_REPORT_TYPE_CONSUMER)) {
|
||||
submit_hid_tx_report_event(pending_consumer_latest.report_type,
|
||||
pending_consumer_latest.protocol_mode,
|
||||
pending_consumer_latest.data,
|
||||
pending_consumer_latest.size);
|
||||
pending_consumer_latest.valid = false;
|
||||
if (pending_consumer_latest.protocol_mode != state->protocol_mode) {
|
||||
LOG_WRN("Drop stale latest consumer report after protocol change");
|
||||
pending_consumer_latest.valid = false;
|
||||
} else {
|
||||
submit_hid_tx_report_event(transport,
|
||||
pending_consumer_latest.report_type,
|
||||
pending_consumer_latest.protocol_mode,
|
||||
pending_consumer_latest.data,
|
||||
pending_consumer_latest.size);
|
||||
pending_consumer_latest.valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool handle_keyboard_hid_report_event(const struct keyboard_hid_report_event *event)
|
||||
{
|
||||
if (!running || (event->mode != MODE_SWITCH_USB)) {
|
||||
if (!running ||
|
||||
((event->mode != MODE_SWITCH_USB) && (event->mode != MODE_SWITCH_BLE))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -215,20 +269,35 @@ static bool handle_keyboard_hid_report_event(const struct keyboard_hid_report_ev
|
||||
|
||||
static bool handle_hid_transport_state_event(const struct hid_transport_state_event *event)
|
||||
{
|
||||
if (event->transport != HID_TRANSPORT_USB) {
|
||||
enum hid_transport active_transport;
|
||||
struct hid_transport_state_data *state;
|
||||
|
||||
if (event->transport >= HID_TRANSPORT_COUNT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
usb_state.ready = event->ready;
|
||||
usb_state.keys_ready = event->keys_ready;
|
||||
usb_state.consumer_ready = event->consumer_ready;
|
||||
state = &transport_state[event->transport];
|
||||
|
||||
if (usb_state.protocol_mode != event->protocol_mode) {
|
||||
usb_state.protocol_mode = event->protocol_mode;
|
||||
pending_keys.valid = false;
|
||||
state->ready = event->ready;
|
||||
state->keys_ready = event->keys_ready;
|
||||
state->consumer_ready = event->consumer_ready;
|
||||
|
||||
if (state->protocol_mode != event->protocol_mode) {
|
||||
state->protocol_mode = event->protocol_mode;
|
||||
|
||||
if (mode_to_transport(current_mode, &active_transport) &&
|
||||
(active_transport == event->transport)) {
|
||||
pending_keys.valid = false;
|
||||
pending_consumer_latest.valid = false;
|
||||
consumer_fifo_head = 0U;
|
||||
consumer_fifo_tail = 0U;
|
||||
consumer_fifo_count = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
if (!usb_state.ready) {
|
||||
if (!state->ready &&
|
||||
mode_to_transport(current_mode, &active_transport) &&
|
||||
(active_transport == event->transport)) {
|
||||
consumer_fifo_head = 0U;
|
||||
consumer_fifo_tail = 0U;
|
||||
consumer_fifo_count = 0U;
|
||||
@@ -241,7 +310,7 @@ static bool handle_hid_transport_state_event(const struct hid_transport_state_ev
|
||||
|
||||
static bool handle_hid_report_sent_event(const struct hid_report_sent_event *event)
|
||||
{
|
||||
if ((event->transport != HID_TRANSPORT_USB) || !in_flight.active) {
|
||||
if (!in_flight.active || (event->transport != in_flight.transport)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -263,9 +332,12 @@ static bool handle_hid_report_sent_event(const struct hid_report_sent_event *eve
|
||||
|
||||
static bool handle_mode_switch_event(const struct mode_switch_event *event)
|
||||
{
|
||||
bool mode_changed = (current_mode != event->mode);
|
||||
|
||||
current_mode = event->mode;
|
||||
|
||||
if (current_mode != MODE_SWITCH_USB) {
|
||||
if (mode_changed || ((current_mode != MODE_SWITCH_USB) &&
|
||||
(current_mode != MODE_SWITCH_BLE))) {
|
||||
clear_pending_reports();
|
||||
}
|
||||
|
||||
@@ -277,10 +349,16 @@ static int module_init(void)
|
||||
{
|
||||
clear_pending_reports();
|
||||
current_mode = MODE_SWITCH_USB;
|
||||
usb_state.ready = false;
|
||||
usb_state.keys_ready = false;
|
||||
usb_state.consumer_ready = false;
|
||||
usb_state.protocol_mode = KEYBOARD_PROTOCOL_MODE_REPORT;
|
||||
transport_state[HID_TRANSPORT_USB].ready = false;
|
||||
transport_state[HID_TRANSPORT_USB].keys_ready = false;
|
||||
transport_state[HID_TRANSPORT_USB].consumer_ready = false;
|
||||
transport_state[HID_TRANSPORT_USB].protocol_mode =
|
||||
KEYBOARD_PROTOCOL_MODE_REPORT;
|
||||
transport_state[HID_TRANSPORT_BLE].ready = false;
|
||||
transport_state[HID_TRANSPORT_BLE].keys_ready = false;
|
||||
transport_state[HID_TRANSPORT_BLE].consumer_ready = false;
|
||||
transport_state[HID_TRANSPORT_BLE].protocol_mode =
|
||||
KEYBOARD_PROTOCOL_MODE_REPORT;
|
||||
next_sequence = 1U;
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user