From 3cf866cee7da73d564807ed116f933809b58d013 Mon Sep 17 00:00:00 2001 From: jialu Date: Fri, 22 Nov 2024 19:46:38 +0800 Subject: [PATCH] AVRCP: add avrcp metadata feature bug:v/42364 Adding AVRCP metadata feature Signed-off-by: jialu --- CMakeLists.txt | 10 ++ Makefile | 9 ++ feature/include/feature_bluetooth.h | 8 + feature/jidl/bluetooth_bt_avrcpcontrol.jidl | 27 ++++ feature/src/feature_bluetooth_callback.c | 142 ++++++++++++++++++ feature/src/feature_bluetooth_util.c | 3 + .../system_bluetooth_bt_avrcpcontrol_impl.c | 103 +++++++++++++ 7 files changed, 302 insertions(+) create mode 100644 feature/jidl/bluetooth_bt_avrcpcontrol.jidl create mode 100644 feature/src/system_bluetooth_bt_avrcpcontrol_impl.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 2fb97c7..0185bfb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -451,6 +451,12 @@ if(CONFIG_BLUETOOTH) list(APPEND CSRCS ${BLUETOOTH_DIR}/feature/src/system_bluetooth_bt_a2dpsink_impl.c) endif() + if(CONFIG_BLUETOOTH_AVRCP_CONTROL) + list(APPEND CSRCS + ${BLUETOOTH_DIR}/feature/src/system_bluetooth_bt_avrcpcontrol.c) + list(APPEND CSRCS + ${BLUETOOTH_DIR}/feature/src/system_bluetooth_bt_avrcpcontrol_impl.c) + endif() endif() nuttx_add_library(libbluetooth STATIC) @@ -519,6 +525,10 @@ if(CONFIG_BLUETOOTH) list(APPEND JIDL_PATHS ${BLUETOOTH_DIR}/feature/jdil/bluetooth_a2dpsink.jidl) endif() + if(CONFIG_BLUETOOTH_AVRCP_CONTROL) + list(APPEND JIDL_PATHS + ${BLUETOOTH_DIR}/feature/jdil/bluetooth_avrcpcontrol.jidl) + endif() nuttx_add_jidl( TARGET diff --git a/Makefile b/Makefile index 7eba697..fed4f62 100644 --- a/Makefile +++ b/Makefile @@ -343,6 +343,10 @@ ifeq ($(CONFIG_BLUETOOTH_A2DP_SINK), y) CSRCS += feature/src/system_bluetooth_bt_a2dpsink.c CSRCS += feature/src/system_bluetooth_bt_a2dpsink_impl.c endif +ifeq ($(CONFIG_BLUETOOTH_AVRCP_CONTROL), y) +CSRCS += feature/src/system_bluetooth_bt_avrcpcontrol.c +CSRCS += feature/src/system_bluetooth_bt_avrcpcontrol_impl.c +endif depend:: @python3 $(APPDIR)/frameworks/runtimes/feature/tools/jidl/jsongensource.py \ @@ -356,6 +360,11 @@ ifeq ($(CONFIG_BLUETOOTH_A2DP_SINK), y) $(APPDIR)/frameworks/connectivity/bluetooth/feature/jidl/bluetooth_bt_a2dpsink.jidl -out-dir \ $(APPDIR)/frameworks/connectivity/bluetooth/feature/src -header system_bluetooth_bt_a2dpsink.h -source system_bluetooth_bt_a2dpsink.c endif +ifeq ($(CONFIG_BLUETOOTH_AVRCP_CONTROL), y) + @python3 $(APPDIR)/frameworks/runtimes/feature/tools/jidl/jsongensource.py \ + $(APPDIR)/frameworks/connectivity/bluetooth/feature/jidl/bluetooth_bt_avrcpcontrol.jidl -out-dir \ + $(APPDIR)/frameworks/connectivity/bluetooth/feature/src -header system_bluetooth_bt_avrcpcontrol.h -source system_bluetooth_bt_avrcpcontrol.c +endif endif diff --git a/feature/include/feature_bluetooth.h b/feature/include/feature_bluetooth.h index afcc847..4ec5fa3 100644 --- a/feature/include/feature_bluetooth.h +++ b/feature/include/feature_bluetooth.h @@ -40,12 +40,14 @@ typedef enum { ON_DISCOVERY_RESULT, ON_BOND_STATE_CHANGE, A2DPSINK_ON_CONNECT_STATE_CHANGE, + AVRCPCONTROL_ELEMENT_ATTRIBUTE_CALLBACK, } feature_bluetooth_callback_t; typedef enum { FEATURE_BLUETOOTH, FEATURE_BLUETOOTH_BT, FEATURE_BLUETOOTH_A2DPSINK, + FEATURE_BLUETOOTH_AVRCPCONTROL, } feature_bluetooth_feature_type_t; typedef struct { @@ -64,6 +66,11 @@ typedef struct { FtCallbackId a2dp_sink_connection_state_cb_id; } feature_bluetooth_a2dp_sink_callbacks_t; +typedef struct { + FeatureInstanceHandle* feature_ins; + FtCallbackId avrcp_control_element_attribute_cb_id; +} feature_bluetooth_avrcp_control_callbacks_t; + typedef struct { FtCallbackId feature_callback_id; void* feature; @@ -75,6 +82,7 @@ typedef struct { bt_list_t* feature_bluetooth_callbacks; bt_list_t* feature_bluetooth_bt_callbacks; bt_list_t* feature_a2dp_sink_callbacks; + bt_list_t* feature_avrcp_control_callbacks; uint32_t created_features; } feature_bluetooth_features_info_t; diff --git a/feature/jidl/bluetooth_bt_avrcpcontrol.jidl b/feature/jidl/bluetooth_bt_avrcpcontrol.jidl new file mode 100644 index 0000000..d792e1d --- /dev/null +++ b/feature/jidl/bluetooth_bt_avrcpcontrol.jidl @@ -0,0 +1,27 @@ +module system.bluetooth.bt.avrcpcontrol@1.0 + +callback startGetElementAttributeSuccess() +callback startGetElementAttributeFail(string data, int code) +callback startGetElementAttributeComplete() +struct StartGetElementAttributeParams { + string deviceId + callback startGetElementAttributeSuccess success + callback startGetElementAttributeFail fail + callback startGetElementAttributeComplete complete +} +void startGetElementAttribute(StartGetElementAttributeParams params) + +struct attr_info_t { + int attrId + int chrSet + string text +} + +struct OnElementAttributeData { + string deviceId + int attrsCount + attr_info_t[] attrs; +} + +callback ElementAttributeCallback(OnElementAttributeData data) +property ElementAttributeCallback onElementattribute \ No newline at end of file diff --git a/feature/src/feature_bluetooth_callback.c b/feature/src/feature_bluetooth_callback.c index aea6084..54ff390 100644 --- a/feature/src/feature_bluetooth_callback.c +++ b/feature/src/feature_bluetooth_callback.c @@ -16,6 +16,7 @@ */ #include "bt_a2dp_sink.h" #include "bt_adapter.h" +#include "bt_avrcp_control.h" #include "bt_list.h" #include "feature_bluetooth.h" #include "feature_exports.h" @@ -23,6 +24,7 @@ #include "system_bluetooth.h" #include "system_bluetooth_bt.h" #include "system_bluetooth_bt_a2dpsink.h" +#include "system_bluetooth_bt_avrcpcontrol.h" #include "uv.h" #define REMOVE_CALLBACK(feature_callback, callback_type) \ @@ -85,6 +87,16 @@ static bool get_callback_a2dp_sink(void* data, void* feature_ins) return callbacks->feature_ins == feature_ins; } +static bool get_callback_avrcp_control(void* data, void* feature_ins) +{ + feature_bluetooth_avrcp_control_callbacks_t* callbacks = (feature_bluetooth_avrcp_control_callbacks_t*)data; + if (!callbacks) { + return false; + } + + return callbacks->feature_ins == feature_ins; +} + static void free_feature_callback(bt_list_t* callbacks, FeatureInstanceHandle handle, bt_list_find_cb find_func) { void* data; @@ -136,6 +148,18 @@ static void free_feature_bluetooth_a2dp_sink_node(void* node) free(feature_callback); } +static void free_feature_bluetooth_avrcp_control_node(void* node) +{ + feature_bluetooth_avrcp_control_callbacks_t* feature_callback = (feature_bluetooth_avrcp_control_callbacks_t*)node; + + if (!feature_callback) { + return; + } + + REMOVE_CALLBACK(feature_callback, avrcp_control_element_attribute_cb_id); + free(feature_callback); +} + static void on_adapter_state_changed_cb(void* cookie, bt_adapter_state_t state) { bt_instance_t* bt_ins = (bt_instance_t*)cookie; @@ -437,6 +461,92 @@ static const a2dp_sink_callbacks_t a2dp_sink_cbs = { a2dp_sink_connection_state_cb, }; +system_bluetooth_bt_avrcpcontrol_attr_info_t* get_attr_info(avrcp_element_attr_val_t* attr) +{ + system_bluetooth_bt_avrcpcontrol_attr_info_t* attr_info = system_bluetooth_bt_avrcpcontrolMallocattr_info_t(); + attr_info->attrId = attr->attr_id; + attr_info->chrSet = attr->chr_set; + attr_info->text = StringToFtString((char*)attr->text); + return attr_info; +} + +static void avrcp_control_get_element_attribute_cb(void* cookie, bt_address_t* addr, uint8_t attrs_count, avrcp_element_attr_val_t* attrs) +{ + int attr_index; + bt_instance_t* bt_ins = (bt_instance_t*)cookie; + feature_bluetooth_features_info_t* features_callbacks; + bt_list_t* callbacks; + bt_list_node_t* node; + + FEATURE_LOG_DEBUG("avrcp control element attribute cb"); + if (!bt_ins) { + return; + } + + features_callbacks = (feature_bluetooth_features_info_t*)bt_ins->context; + if (!features_callbacks) { + return; + } + + uv_mutex_lock(&features_callbacks->mutex); + callbacks = features_callbacks->feature_avrcp_control_callbacks; + if (!callbacks) { + uv_mutex_unlock(&features_callbacks->mutex); + return; + } + + node = bt_list_head(callbacks); + if (!node) { + uv_mutex_unlock(&features_callbacks->mutex); + return; + } + + while (node) { + feature_bluetooth_avrcp_control_callbacks_t* feature_callback; + system_bluetooth_bt_avrcpcontrol_OnElementAttributeData* data; + FtArray* attributes; + + char addr_str[BT_ADDR_STR_LENGTH] = { 0 }; + + feature_callback = (feature_bluetooth_avrcp_control_callbacks_t*)bt_list_node(node); + if (!feature_callback) { + break; + } + + FEATURE_LOG_DEBUG("feature:%p, callbackId:%d", feature_callback->feature_ins, feature_callback->avrcp_control_element_attribute_cb_id); + bt_addr_ba2str(addr, addr_str); + data = system_bluetooth_bt_avrcpcontrolMallocOnElementAttributeData(); + attributes = system_bluetooth_bt_avrcpcontrol_malloc_attr_info_t_struct_type_array(); + + if (!data || !attributes) { + continue; + } + + data->deviceId = StringToFtString(addr_str); + data->attrsCount = attrs_count; + attributes->_size = attrs_count; + attributes->_element = malloc(attributes->_size * sizeof(struct Attribute*)); + if (!attributes->_element) { + continue; + } + for (attr_index = 0; attr_index < attributes->_size; attr_index++) { + system_bluetooth_bt_avrcpcontrol_attr_info_t* attr_info = get_attr_info(&attrs[attr_index]); + ((system_bluetooth_bt_avrcpcontrol_attr_info_t**)attributes->_element)[attr_index] = attr_info; + } + + data->attrs = attributes; + + feature_bluetooth_post_task(feature_callback->feature_ins, feature_callback->avrcp_control_element_attribute_cb_id, data); + node = bt_list_next(callbacks, node); + } + uv_mutex_unlock(&features_callbacks->mutex); +} + +static const avrcp_control_callbacks_t avrcp_control_cbs = { + .size = sizeof(avrcp_control_cbs), + .get_element_attribute_cb = avrcp_control_get_element_attribute_cb, +}; + void feature_bluetooth_add_feature_callback(FeatureInstanceHandle handle, feature_bluetooth_feature_type_t feature_type) { bt_instance_t* bt_ins; @@ -465,6 +575,11 @@ void feature_bluetooth_add_feature_callback(FeatureInstanceHandle handle, featur case FEATURE_BLUETOOTH_A2DPSINK: add_feature_callback(features_callbacks->feature_a2dp_sink_callbacks, feature_bluetooth_a2dp_sink_callbacks_t, handle); break; +#endif +#ifdef CONFIG_BLUETOOTH_AVRCP_CONTROL + case FEATURE_BLUETOOTH_AVRCPCONTROL: + add_feature_callback(features_callbacks->feature_avrcp_control_callbacks, feature_bluetooth_avrcp_control_callbacks_t, handle); + break; #endif default: break; @@ -499,6 +614,11 @@ void feature_bluetooth_free_feature_callback(FeatureInstanceHandle handle, featu case FEATURE_BLUETOOTH_A2DPSINK: free_feature_callback(features_callbacks->feature_a2dp_sink_callbacks, handle, get_callback_a2dp_sink); break; +#endif +#ifdef CONFIG_BLUETOOTH_AVRCP_CONTROL + case FEATURE_BLUETOOTH_AVRCPCONTROL: + free_feature_callback(features_callbacks->feature_avrcp_control_callbacks, handle, get_callback_avrcp_control); + break; #endif default: break; @@ -536,6 +656,11 @@ void feature_bluetooth_set_feature_callback(FeatureInstanceHandle handle, FtCall case A2DPSINK_ON_CONNECT_STATE_CHANGE: set_feature_callback(features_callbacks->feature_a2dp_sink_callbacks, feature_bluetooth_a2dp_sink_callbacks_t, get_callback_a2dp_sink, handle, callback_id, a2dp_sink_connection_state_cb_id); break; +#endif +#ifdef CONFIG_BLUETOOTH_AVRCP_CONTROL + case AVRCPCONTROL_ELEMENT_ATTRIBUTE_CALLBACK: + set_feature_callback(features_callbacks->feature_avrcp_control_callbacks, feature_bluetooth_avrcp_control_callbacks_t, get_callback_avrcp_control, handle, callback_id, avrcp_control_element_attribute_cb_id); + break; #endif default: break; @@ -575,6 +700,11 @@ FtCallbackId feature_bluetooth_get_feature_callback(FeatureInstanceHandle handle case A2DPSINK_ON_CONNECT_STATE_CHANGE: get_feature_callback(features_callbacks->feature_a2dp_sink_callbacks, feature_bluetooth_a2dp_sink_callbacks_t, get_callback_a2dp_sink, handle, callback_id, a2dp_sink_connection_state_cb_id); break; +#endif +#ifdef CONFIG_BLUETOOTH_AVRCP_CONTROL + case AVRCPCONTROL_ELEMENT_ATTRIBUTE_CALLBACK: + get_feature_callback(features_callbacks->feature_avrcp_control_callbacks, feature_bluetooth_avrcp_control_callbacks_t, get_callback_avrcp_control, handle, callback_id, avrcp_control_element_attribute_cb_id); + break; #endif default: break; @@ -607,6 +737,11 @@ void feature_bluetooth_callback_init(bt_instance_t* bt_ins) bt_ins->a2dp_sink_cookie = bt_a2dp_sink_register_callbacks(bt_ins, &a2dp_sink_cbs); #endif +#ifdef CONFIG_BLUETOOTH_AVRCP_CONTROL + features_callbacks->feature_avrcp_control_callbacks = bt_list_new(free_feature_bluetooth_avrcp_control_node); + bt_ins->avrcp_control_cookie = bt_avrcp_control_register_callbacks(bt_ins, &avrcp_control_cbs); +#endif + bt_ins->context = features_callbacks; } @@ -629,11 +764,18 @@ void feature_bluetooth_callback_uninit(bt_instance_t* bt_ins) bt_a2dp_sink_unregister_callbacks(bt_ins, bt_ins->a2dp_sink_cookie); #endif +#ifdef CONFIG_BLUETOOTH_AVRCP_CONTROL + bt_avrcp_control_unregister_callbacks(bt_ins, bt_ins->avrcp_control_cookie); +#endif + uv_mutex_lock(&features_callbacks->mutex); bt_list_free(features_callbacks->feature_bluetooth_callbacks); bt_list_free(features_callbacks->feature_bluetooth_bt_callbacks); #ifdef CONFIG_BLUETOOTH_A2DP_SINK bt_list_free(features_callbacks->feature_a2dp_sink_callbacks); +#endif +#ifdef CONFIG_BLUETOOTH_AVRCP_CONTROL + bt_list_free(features_callbacks->feature_avrcp_control_callbacks); #endif uv_mutex_unlock(&features_callbacks->mutex); diff --git a/feature/src/feature_bluetooth_util.c b/feature/src/feature_bluetooth_util.c index e6c750b..1381177 100644 --- a/feature/src/feature_bluetooth_util.c +++ b/feature/src/feature_bluetooth_util.c @@ -77,6 +77,9 @@ void feature_bluetooth_post_task(FeatureInstanceHandle handle, FtCallbackId call char* StringToFtString(const char* str) { + if (!str) { + return NULL; + } int len = strlen(str); char* ftStr = (char*)FeatureMalloc(len + 1, FT_CHAR); strcpy(ftStr, str); diff --git a/feature/src/system_bluetooth_bt_avrcpcontrol_impl.c b/feature/src/system_bluetooth_bt_avrcpcontrol_impl.c new file mode 100644 index 0000000..78648e3 --- /dev/null +++ b/feature/src/system_bluetooth_bt_avrcpcontrol_impl.c @@ -0,0 +1,103 @@ +/* + * This file is auto-generated by jsongensource.py, Do not modify it directly! + */ + +/* + * Copyright (C) 2024 Xiaomi Corporation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "bt_avrcp_control.h" +#include "feature_bluetooth.h" +#include "system_bluetooth_bt_avrcpcontrol.h" + +#define file_tag "system_bluetooth_bt_avrcpcontrol" + +void system_bluetooth_bt_avrcpcontrol_onRegister(const char* feature_name) +{ + FEATURE_LOG_DEBUG("%s::%s()", file_tag, __FUNCTION__); +} + +void system_bluetooth_bt_avrcpcontrol_onCreate(FeatureRuntimeContext ctx, FeatureProtoHandle handle) +{ + feature_bluetooth_init_bt_ins(FEATURE_BLUETOOTH_AVRCPCONTROL, handle); + FEATURE_LOG_DEBUG("%s::%s()", file_tag, __FUNCTION__); +} + +void system_bluetooth_bt_avrcpcontrol_onRequired(FeatureRuntimeContext ctx, FeatureInstanceHandle handle) +{ + feature_bluetooth_add_feature_callback(handle, FEATURE_BLUETOOTH_AVRCPCONTROL); + FEATURE_LOG_DEBUG("%s::%s()", file_tag, __FUNCTION__); +} + +void system_bluetooth_bt_avrcpcontrol_onDetached(FeatureRuntimeContext ctx, FeatureInstanceHandle handle) +{ + feature_bluetooth_free_feature_callback(handle, FEATURE_BLUETOOTH_AVRCPCONTROL); + FEATURE_LOG_DEBUG("%s::%s()", file_tag, __FUNCTION__); +} + +void system_bluetooth_bt_avrcpcontrol_onDestroy(FeatureRuntimeContext ctx, FeatureProtoHandle handle) +{ + feature_bluetooth_uninit_bt_ins(FEATURE_BLUETOOTH_AVRCPCONTROL, handle); + FEATURE_LOG_DEBUG("%s::%s()", file_tag, __FUNCTION__); +} + +void system_bluetooth_bt_avrcpcontrol_onUnregister(const char* feature_name) +{ + FEATURE_LOG_DEBUG("%s::%s()", file_tag, __FUNCTION__); +} + +FtCallbackId system_bluetooth_bt_avrcpcontrol_get_onElementattribute(void* feature, union AppendData append_data) +{ + return feature_bluetooth_get_feature_callback(feature, AVRCPCONTROL_ELEMENT_ATTRIBUTE_CALLBACK); +} + +void system_bluetooth_bt_avrcpcontrol_set_onElementattribute(void* feature, union AppendData append_data, FtCallbackId onElementattribute) +{ + FEATURE_LOG_DEBUG("set on avrcpcontrol set element attribute callback: %p, callbackId: %d", feature, onElementattribute); + feature_bluetooth_set_feature_callback(feature, onElementattribute, AVRCPCONTROL_ELEMENT_ATTRIBUTE_CALLBACK); +} + +void system_bluetooth_bt_avrcpcontrol_wrap_startGetElementAttribute(FeatureInstanceHandle feature, union AppendData append_data, system_bluetooth_bt_avrcpcontrol_StartGetElementAttributeParams* params) +{ + bt_address_t addr; + bt_status_t status; + + if (bt_addr_str2ba(params->deviceId, &addr) < 0) { + if (!FeatureInvokeCallback(feature, params->fail, "invalid addr!", BT_STATUS_PARM_INVALID)) { + FEATURE_LOG_ERROR("invoke get element attribute fail callback failed!"); + } + goto COMPLETE_CALLBACK; + } + + status = bt_avrcp_control_get_element_attributes(feature_bluetooth_get_bt_ins(feature), &addr); + + if (status == BT_STATUS_SUCCESS) { + if (!FeatureInvokeCallback(feature, params->success)) { + FEATURE_LOG_ERROR("invoke get element attribute success failed!"); + } + } else { + if (!FeatureInvokeCallback(feature, params->fail, "get element attribute failed!", status)) { + FEATURE_LOG_ERROR("invoke get element attribute fail callback failed!"); + } + } +COMPLETE_CALLBACK: + if (!FeatureInvokeCallback(feature, params->complete)) { + FEATURE_LOG_ERROR("invoke disconnect complete callback failed!"); + } + + FeatureRemoveCallback(feature, params->success); + FeatureRemoveCallback(feature, params->fail); + FeatureRemoveCallback(feature, params->complete); +} \ No newline at end of file