Skip to content

bluetooth: add HOGP device and HID host support#583

Open
chengkai15 wants to merge 898 commits into
open-vela:devfrom
chengkai15:feature/dev-hogp
Open

bluetooth: add HOGP device and HID host support#583
chengkai15 wants to merge 898 commits into
open-vela:devfrom
chengkai15:feature/dev-hogp

Conversation

@chengkai15
Copy link
Copy Markdown
Contributor

Summary

Add HID over GATT Profile (HOGP) support for both device and host roles, enabling BLE HID connectivity on the Zephyr stack.

Changes

Commit 1: HOGP Device Support

  • Implement sal_hogp_device_interface for Zephyr stack integration
  • Extend hid_device_service to support BLE (HOGP) device mode alongside classic HID
  • Add CONFIG_BLUETOOTH_HOGP_DEVICE Kconfig option (depends on CONFIG_BLUETOOTH_HID_DEVICE)

Commit 2: HID Host (HOGP Host) Support

  • Add hid_host_service profile implementation
  • Implement sal_hogp_host_interface for Zephyr stack integration
  • Add framework API (bt_hid_host) and socket IPC layer
  • Add CONFIG_BLUETOOTH_HID_HOST Kconfig option
  • Add hidh CLI tool for testing

Testing

  • HOGP Device: BLE HID device registration and report sending
  • HID Host: Connect/disconnect to BLE HID peripherals
  • HID Host: Get/set report, input report callback
  • Coexistence with classic HID device profile

Configuration

Enable HOGP device (requires HID_DEVICE)

CONFIG_BLUETOOTH_HID_DEVICE=y
CONFIG_BLUETOOTH_HOGP_DEVICE=y

Enable HID host

CONFIG_BLUETOOTH_HID_HOST=y

jialu522 and others added 30 commits December 24, 2025 14:25
bug: v/81522

When event_id == BT_AVRCP_EVT_VOLUME_CHANGED, flag = true is set only if both CONFIG_BLUETOOTH_AVRCP_ABSOLUTE_VOLUME and CONFIG_BLUETOOTH_AVRCP_CONTROL are enabled.
Otherwise in the else branch, flag = true is set only if CONFIG_BLUETOOTH_AVRCP_TARGET is enabled. All configurations are enabled, treating flag as always true, making the if (!flag) condition unreachable.

Signed-off-by: YuhengLi <liyuheng@xiaomi.com>
bug: v/81702

Fixed memory leak caused by premature return.

Signed-off-by: liuxiang18 <liuxiang18@xiaomi.com>
bug: v/80258

Rootcause: attributes in bt_sdp_discover_params may be modified by ZBlue SDP. Using const could cause a crash in some cases
Signed-off-by: YuhengLi <liyuheng@xiaomi.com>
bug: v/81752

Rootcause: audio_connect should not be called in bluetoothd task
Signed-off-by: YuhengLi <liyuheng@xiaomi.com>
bug: v/81968

Rootcause: disconnected_callback not called caused connect info not cleared in connection manager module

Signed-off-by: YuhengLi <liyuheng@xiaomi.com>
… an asynchronous API.

bug: v/81682

When priv dynamically allocates memory successfully but fails later due to other reasons before reaching the assignment ins->priv = priv;, the memory allocated to priv cannot be freed in bt_socket_async_client_deinit, leading to a resource leak.

Signed-off-by: jialu <jialu@xiaomi.com>
…se functions

bug: v/80811

Rootcause: In certain scenarios, users of `euv_pipe` must ensure all UV requests have completed execution before releasing resources. Consequently, it is necessary to notify users that `euv_pipe` has been fully released after its close operation is completed, thereby permitting subsequent operational procedures to proceed. Support for the close callback has therefore been added.

Signed-off-by: chejinxian1 <chejinxian1@xiaomi.com>
…e callback

bug: v/80808

Rootcause: In high-throughput reception scenarios, situations may arise where the `write_cb` for SPP data transmission to the application has not yet completed, yet the SPP device is released due to an abrupt disconnection, thereby preventing notification to the protocol stack that data reception has concluded.

To circumvent this issue, it is imperative to ensure all write operations are finalised before releasing the SPP device. Consequently, an `euv_pipe` close callback implementation has been introduced to guarantee that all `write_cb` operations execute successfully prior to severing the data pathway.

Signed-off-by: chejinxian1 <chejinxian1@xiaomi.com>
bug: v/74709

only open CONFIG_BLUETOOTH_AVRCP_CONTROL or CONFIG_BLUETOOTH_AVRCP_ABSOLUTE_VOLUME can build in bt_avrcp_control_notification_cb.

error: 'bt_avrcp_info_find_by_ct' undeclared (first use in this function); did you mean 'bt_avrcp_info_find_by_tg'?
 1501 |     avrcp_info = bt_list_find(bt_avrcp_conn, bt_avrcp_info_find_by_ct, ct);
      |                                              ^~~~~~~~~~~~~~~~~~~~~~~~
      |                                              bt_avrcp_info_find_by_tg

Signed-off-by: zhongzhijie1 <zhongzhijie1@xiaomi.com>
bug: v/82095

The spp_connect_handler was attempting to look up the SPP connection
by rfcomm_dlc before it was added to the connection list, causing
"SPP connection not found for rfcomm_dlc" error.

Root Cause:
The connection object wasn't in the global connection list at the
time of lookup, making spp_find_connection_by_dlc() always fail.

Fix:
Pass the spp_conn pointer directly as user_data to avoid the lookup,
and add it to the connection list after successful initialization.

Signed-off-by: zhongzhijie1 <zhongzhijie1@xiaomi.com>
bug: v/81925

Add a generic descriptor allocation path, matching alloc_characteristic() style.

Signed-off-by: zhongzhijie1 <zhongzhijie1@xiaomi.com>
bug: v/81958

Some services are marked with GATT_PROP_EXPOSED_OVER_BREDR, but current
not implement gatt over bredr. As a temporary workaround, clear
this flag when calling add_service() so the service is exposed over BLE.

Signed-off-by: zhongzhijie1 <zhongzhijie1@xiaomi.com>
bug: v/82081

`bt_le_scan.h` is a globally exposed header file. Then, Zephyr's `#include <zephyr/bluetooth/bluetooth.h>` is declared as a private inclusion of Zephyr in CMake. However, the problem is that when third-party apps use my global `bt_le_scan.h`, the CMake system doesn't know where `zephyr/bluetooth/bluetooth.h` is and throws an error. One solution is for the third-party app to also declare a private inclusion of Zephyr in CMake, but this doesn't conform to design principles. The app only needs to be concerned with my framework layer. If the app also needs to include Zephyr's header files, then the framework layer is not properly configured. Therefore, `zephyr/bluetooth/bluetooth.h` must not be explicitly included in `bt_le_scan`.

Signed-off-by: zhongzhijie1 <zhongzhijie1@xiaomi.com>
bug: v/82104

The number of gatts sal DB attributes was insufficient for miwear's needs, so it was increased to a margin of 60. Future memory optimization projects will no longer maintain static arrays.

Signed-off-by: zhongzhijie1 <zhongzhijie1@xiaomi.com>
bug: v/81701

Rootcause: dereference null.
Signed-off-by: Yuheng Li <liyuheng@xiaomi.com>
bug: v/81701

Rootcause: unnecessary malloc
Signed-off-by: YuhengLi <liyuheng@xiaomi.com>
bug: v/81924

By default, just working (no I/O) should automatically accept user confirmation, but for compatibility with the watch app, app confirmation is required.

Signed-off-by: zhongzhijie1 <zhongzhijie1@xiaomi.com>
bug: v/59050

Rootcause:When reconnect to the headset during a call, the headset will obtain the call status through the cind command. Since Vela does not have modem, the status will be error. So, get cind from Android.

Signed-off-by: zhangyuan20 <zhangyuan20@xiaomi.com>
bug: v/61170

Signed-off-by: zhangyuan20 <zhangyuan20@xiaomi.com>
bug: v/81520

In `spp_find_connection_by_sdp_param` and `spp_connect_with_uuid`, the pointer `spp_conn` was dereferenced before the NULL check. This patch ensures the pointer is validated before access to avoid potential crashes.

Signed-off-by: v-yichenxi <v-yichenxi@xiaomi.com>
bug: v/82928

Remove the redundant stack variable bd_addr, which already exists in sal_conn.

Signed-off-by: YuhengLi <liyuheng@xiaomi.com>
bug: v/82928

Rootcause: bt_sal_get_remote_address may fail

Signed-off-by: YuhengLi <liyuheng@xiaomi.com>
Signed-off-by: zhongzhijie1 <zhongzhijie1@xiaomi.com>
support.

bug: v/65087

Signed-off-by: zhongzhijie1 <zhongzhijie1@xiaomi.com>
…global database hash.

bug :v/65095

The logic is implemented in gatts_service.c to trigger hash calculation
and return the result via a registered callback, for trusted device sync and DB change tracking.

Signed-off-by: zhongzhijie1 <zhongzhijie1@xiaomi.com>
…h from adapter to profile.

bug: v/65126

Root cause:
Adapter had no generic message path to deliver events to profile services.
GATTS could not receive a request to fetch the server database hash.
Add adapter handler to forward profile_msg_t to service_manager.
Add PROFILE_EVT_GATTS_REQUEST_DB_HASH and handle it in gatts_service via process_msg.
Wire bt_sal_gatt_server_get_database_hash() call when the event is received.

Signed-off-by: zhongzhijie1 <zhongzhijie1@xiaomi.com>
bug: v/65129

Root cause:
The stack did not compute and store the server GATT database hash on initial bonding.
Peers could keep a stale GATT cache because no hash update was triggered.
When a bonded LE device is connected, send PROFILE_EVT_GATTS_REQUEST_DB_HASH.
Force hash update to start cache sync for the new bond.

Signed-off-by: zhongzhijie1 <zhongzhijie1@xiaomi.com>
bug: v/65131

There was no persistent storage for the server GATT database hash.
The system could not compare hashes after reboot and peers could keep a stale GATT cache.
Add remote_device_gatt_properties_t with 16-byte hash field.
Add save/load APIs for GATT hash cache using the uv_db backend (BT_KEY_BLEGATTHASH).

Signed-off-by: zhongzhijie1 <zhongzhijie1@xiaomi.com>
bug: v/65135

KVDB backend had no key and no save/load path for GATT server database hash.
The system could not restore the hash after reboot and cache validation failed.
Add BT_KVDB_BLEGATTDBHASH and helpers to save/load remote_device_gatt_properties_t entries.
Count and delete old hash properties before saving new data.

Signed-off-by: zhongzhijie1 <zhongzhijie1@xiaomi.com>
bug: v/65139

The device object had no field to keep the GATT database hash.
The stack could not persist and validate GATT cache state per bonded peer.
Add a 16-byte gatt_hash field under CONFIG_BLUETOOTH_GATTS_CACHE_SUPPORT.
Add get/set/delete helpers and export remote_device_gatt_properties_t data.
Add DFLAG_GATT_HASH_VALID to mark hash presence.

Signed-off-by: zhongzhijie1 <zhongzhijie1@xiaomi.com>
bug: v/88762

Add CS RAP (Ranging Application Profile) implementation including
segment reassembly, step data restoration, Mode1 size detection,
RTT and phase-based distance calculation algorithms, and le_rap
command line tool.

Signed-off-by: huangyulong3 <huangyulong3@xiaomi.com>
bug: v/88765

Add cs_rap_gattc module for RAP GATT Client operations including
RAS service discovery, feature read, real-time and on-demand data
subscription, control point write, and lost segment retrieval.

Signed-off-by: huangyulong3 <huangyulong3@xiaomi.com>
BT_LOGD("HOGP Host: bt_conn_le_create OK, conn=%p", conn);

pthread_mutex_lock(&g_mutex);
hc = alloc_conn(&req->addr, conn);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allocate this before bt_conn_le_create, because ble_connected_cb may arrive anytime after bt_conn_le_create (We usually do not make assumption on the priority of the host thread).

gzh-terry
gzh-terry previously approved these changes May 7, 2026
Copy link
Copy Markdown
Contributor

@gzh-terry gzh-terry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally fine to me now

bug: v/88240

Add null pointer and length check before memcpy in
if_gattc_on_element_read to prevent crash when stack
reports a read result with null value pointer.

Signed-off-by: liuxiang18 <liuxiang18@xiaomi.com>
liuX10 added 3 commits May 8, 2026 15:06
bug: v/88246

- Add helper to find the service declaration element from any
  characteristic or descriptor element within the same service table
- Add PTS mode check in read_value to reject cross-transport access:
  BR conn to LE-only service or LE conn to BR-only service returns 0x80

Signed-off-by: liuxiang18 <liuxiang18@xiaomi.com>
bug: v/87180

bt_sal_gatt_server_disable() only unregistered callbacks without
cleaning up server_db[] and server_svcs[] static arrays. Each
disable/enable cycle left stale attributes occupying slots, causing
attr_count to eventually reach CONFIG_GATT_SERVER_MAX_ATTRIBUTES.

- Add full resource cleanup in bt_sal_gatt_server_disable(): unregister
  all GATT services from zephyr, free SDP records, release all
  attribute user_data/uuid memory, and reset server_db/server_svcs/
  attr_count/svc_attr_count.
- Reorder if_gatts_shutdown() to call disable before freeing the
  upper-layer service list, ensuring zephyr unregister completes first.

Signed-off-by: liuxiang18 <liuxiang18@xiaomi.com>
bug: v/88246

- Add new GATT service (UUID 0xFF10) declared with
  GATT_H_PRIMARY_SERVICE_OVER_BREDR for PTS cross-transport testing
- Include TX (notify/indicate), CCCD, and RX (read/write) characteristics
- Register as service id 4 (BREDR) in gatt_server tool

Signed-off-by: liuxiang18 <liuxiang18@xiaomi.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 34 out of 34 changed files in this pull request and generated 8 comments.

Comment on lines 46 to 56
enum profile_id {
PROFILE_A2DP,
PROFILE_A2DP_SINK,
PROFILE_AVRCP_CT,
PROFILE_AVRCP_TG,
PROFILE_HFP_HF,
PROFILE_HFP_AG,
PROFILE_SPP,
PROFILE_HID_DEV,
PROFILE_HID_HOST,
PROFILE_PANU,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

Comment thread Kconfig
Comment on lines +794 to +798
bool "HID Host (Classic HIDP + HOGP)"
default n
help
Enable HID Host profile. Supports both classic Bluetooth
HID Host (HIDP) and BLE HID over GATT Profile (HOGP) Host.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

Comment thread service/profiles/hid/hid_host_service.c Outdated
Comment on lines +189 to +195
msg->report_map.data = malloc(len);
if (!msg->report_map.data) {
BT_LOGE("%s malloc report_map data failed", __func__);
free(msg);
return;
}
memcpy(msg->report_map.data, data, len);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

Comment on lines +28 to +46
void* bt_hid_host_register_callbacks(bt_instance_t* ins, const hid_host_callbacks_t* callbacks)
{
bt_message_packet_t packet;
bt_status_t status;
void* cookie;

BT_SOCKET_INS_VALID(ins, NULL);

if (ins->hidh_callbacks == NULL)
ins->hidh_callbacks = bt_callbacks_list_new(CONFIG_BLUETOOTH_MAX_REGISTER_NUM);

cookie = bt_remote_callbacks_register(ins->hidh_callbacks, ins, (void*)callbacks);
if (cookie == NULL)
return NULL;

status = bt_socket_client_sendrecv(ins, &packet, BT_HID_HOST_REGISTER_CALLBACK);
if (status != BT_STATUS_SUCCESS || packet.hidh_r.status != BT_STATUS_SUCCESS) {
bt_remote_callbacks_unregister(ins->hidh_callbacks, NULL, cookie);
return NULL;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no it only use valid mem, to keep with other func

Comment thread tools/hid_host.c
Comment on lines +265 to +276
if (slen % 2 != 0 || slen == 0)
return CMD_INVALID_PARAM;

int len = slen / 2;

if (len > (int)sizeof(data))
len = sizeof(data);

for (int i = 0; i < len; i++) {
char hex[3] = { argv[3][i * 2], argv[3][i * 2 + 1], 0 };
data[i] = strtol(hex, NULL, 16);
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not fix, just tool for debug

Comment thread tools/hid_host.c
Comment on lines +378 to +389
static int mouse_stats_cmd(void* handle, int argc, char* argv[])
{
(void)handle;

if (argc < 2)
return CMD_PARAM_NOT_ENOUGH;

if (strcmp(argv[1], "on") == 0) {
memset(&g_mouse_stats, 0, sizeof(g_mouse_stats));
g_mouse_stats.enabled = true;
g_mouse_stats.min_us = UINT32_MAX;
clock_gettime(CLOCK_MONOTONIC, &g_mouse_stats.period_start);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only one test not support many cases

Comment on lines 272 to +294
@@ -277,6 +290,8 @@ typedef struct {
hidd_set_report_callback set_report_cb;
hidd_receive_report_callback receive_report_cb;
hidd_virtual_unplug_callback virtual_unplug_cb;
hidd_mode_changed_callback mode_changed_cb;
hidd_suspend_callback suspend_cb;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused cb

pthread_mutex_unlock(&g_hogp_mutex);

if (!hconn) {
BT_LOGE("HOGP: no free connection slot");
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

@chengkai15 chengkai15 force-pushed the feature/dev-hogp branch 4 times, most recently from 10f0866 to 9059441 Compare May 8, 2026 15:17
bug: v/89553

Add HID over GATT Profile (HOGP) device role implementation on top of
the existing HID Device profile. This enables BLE HID device
functionality through the Zephyr stack adapter.

Changes:
- Add sal_hogp_device_interface for Zephyr stack integration
- Extend hid_device_service to support HOGP device mode
- Add CONFIG_BLUETOOTH_HOGP_DEVICE Kconfig option (depends on HID_DEVICE)
- Update CMakeLists.txt build configuration

Signed-off-by: Kai Cheng <chengkai@xiaomi.com>

struct {
bt_address_t addr;
} _bt_hid_host_disconnect, _bt_hid_host_suspend, _bt_hid_host_exit_suspend;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
} _bt_hid_host_disconnect, _bt_hid_host_suspend, _bt_hid_host_exit_suspend;
} _bt_hid_host_disconnect,
_bt_hid_host_suspend,
_bt_hid_host_exit_suspend;

gzh-terry
gzh-terry previously approved these changes May 9, 2026
@liujinye-sys liujinye-sys dismissed gzh-terry’s stale review May 9, 2026 06:44

The merge-base changed after approval.

bug: v/89553

Add HID Host profile with HOGP (HID over GATT) host role support,
enabling connection to BLE HID peripherals (keyboards, mice, etc.).

Changes:
- Add hid_host_service profile implementation
- Add sal_hogp_host_interface for Zephyr stack integration
- Add framework API (bt_hid_host) and socket IPC layer
- Add CONFIG_BLUETOOTH_HID_HOST Kconfig option
- Add hidh CLI tool for testing
- Update CMakeLists.txt build configuration

Signed-off-by: Kai Cheng <chengkai@xiaomi.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.