From 774678e2e0ec94aad753a335b63274b235367131 Mon Sep 17 00:00:00 2001 From: jialu Date: Tue, 5 Nov 2024 16:08:37 +0800 Subject: [PATCH 1/2] HFP: Adding vendor specific AT command process for AG bug: v/52444 In order to implement the PTT function of headphone control, it is necessary to add the process of AG send and receive vendor specific AT commands. Signed-off-by: jialu --- framework/api/bt_hfp_ag.c | 7 ++ framework/include/bluetooth.h | 4 + framework/include/bt_hfp.h | 1 + framework/include/bt_hfp_ag.h | 23 ++++++ framework/socket/bt_hfp_ag.c | 17 ++++ .../ipc/socket/include/bt_message_hfp_ag.h | 18 +++++ service/ipc/socket/src/bt_socket_hfp_ag.c | 34 ++++++++ service/profiles/hfp_ag/hfp_ag_service.c | 22 ++++++ .../profiles/hfp_ag/hfp_ag_state_machine.c | 78 +++++++++++++++++-- service/profiles/include/hfp_ag_event.h | 1 + service/profiles/include/hfp_ag_service.h | 2 + 11 files changed, 199 insertions(+), 8 deletions(-) diff --git a/framework/api/bt_hfp_ag.c b/framework/api/bt_hfp_ag.c index 5e98b042..1d796124 100644 --- a/framework/api/bt_hfp_ag.c +++ b/framework/api/bt_hfp_ag.c @@ -150,4 +150,11 @@ bt_status_t BTSYMBOLS(bt_hfp_ag_send_at_command)(bt_instance_t* ins, bt_address_ hfp_ag_interface_t* profile = get_profile_service(); return profile->send_at_command(addr, at_command); +} + +bt_status_t BTSYMBOLS(bt_hfp_ag_send_vendor_specific_at_command)(bt_instance_t* ins, bt_address_t* addr, const char* command, const char* value) +{ + hfp_ag_interface_t* profile = get_profile_service(); + + return profile->send_vendor_specific_at_command(addr, command, value); } \ No newline at end of file diff --git a/framework/include/bluetooth.h b/framework/include/bluetooth.h index 6cc613ca..87ca634c 100644 --- a/framework/include/bluetooth.h +++ b/framework/include/bluetooth.h @@ -340,6 +340,10 @@ typedef struct { #else #define BT_DEV_NAME_MAX_LEN (64) #endif + +#define BLUETOOTH_COMPANY_ID_XIAOMI 0x038F +#define BLUETOOTH_COMPANY_ID_GOOGLE 0x00E0 + #define BT_LOC_NAME_MAX_LEN BT_DEV_NAME_MAX_LEN #define BT_REM_NAME_MAX_LEN BT_DEV_NAME_MAX_LEN diff --git a/framework/include/bt_hfp.h b/framework/include/bt_hfp.h index 81c70fbf..21b07483 100644 --- a/framework/include/bt_hfp.h +++ b/framework/include/bt_hfp.h @@ -33,6 +33,7 @@ extern "C" { Also defined as BTA_HF_CLIENT_AT_MAX_LEN (512) at Android */ #define HFP_AT_LEN_MAX 512 #define HFP_CALL_LIST_MAX 4 +#define HFP_COMPANY_PREFIX_LEN_MAX 10 typedef enum { HFP_AUDIO_STATE_DISCONNECTED, diff --git a/framework/include/bt_hfp_ag.h b/framework/include/bt_hfp_ag.h index c099a784..89512a04 100644 --- a/framework/include/bt_hfp_ag.h +++ b/framework/include/bt_hfp_ag.h @@ -132,6 +132,17 @@ typedef void (*hfp_ag_dial_call_callback)(void* cookie, bt_address_t* addr, cons */ typedef void (*hfp_ag_at_cmd_received_callback)(void* cookie, bt_address_t* addr, const char* at_command); +/** + * @brief HFP vendor specific AT command received callback + * + * @param cookie - callback cookie. + * @param command - The prefix of the AT command. + * @param company_id - Bluetooth company ID. + * @param value - AT command value. + * @param addr - address of peer HF device. + */ +typedef void (*hfp_ag_vend_spec_at_cmd_received_callback)(void* cookie, bt_address_t* addr, const char* command, uint16_t company_id, const char* value); + /** * @brief HFP AG callback structure * @@ -149,6 +160,7 @@ typedef struct hfp_ag_hangup_call_callback hangup_call_cb; hfp_ag_dial_call_callback dial_call_cb; hfp_ag_at_cmd_received_callback at_cmd_cb; + hfp_ag_vend_spec_at_cmd_received_callback vender_specific_at_cmd_cb; } hfp_ag_callbacks_t; /** @@ -323,6 +335,17 @@ bt_status_t BTSYMBOLS(bt_hfp_ag_volume_control)(bt_instance_t* ins, bt_address_t * @return bt_status_t - BT_STATUS_SUCCESS on success, a negated errno value on failure. */ bt_status_t BTSYMBOLS(bt_hfp_ag_send_at_command)(bt_instance_t* ins, bt_address_t* addr, const char* at_command); + +/** + * @brief Send vendor specific AT Command + * + * @param ins - bluetooth client instance. + * @param addr - address of peer HF device. + * @param command - the prefix of the AT command to be send. + * @param value - the value of the AT command to be send. + * @return bt_status_t - BT_STATUS_SUCCESS on success, a negated errno value on failure. + */ +bt_status_t BTSYMBOLS(bt_hfp_ag_send_vendor_specific_at_command)(bt_instance_t* ins, bt_address_t* addr, const char* command, const char* value); #ifdef __cplusplus } #endif diff --git a/framework/socket/bt_hfp_ag.c b/framework/socket/bt_hfp_ag.c index 2eb98212..505ffacd 100644 --- a/framework/socket/bt_hfp_ag.c +++ b/framework/socket/bt_hfp_ag.c @@ -326,3 +326,20 @@ bt_status_t bt_hfp_ag_send_at_command(bt_instance_t* ins, bt_address_t* addr, co return packet.hfp_ag_r.status; } + +bt_status_t bt_hfp_ag_send_vendor_specific_at_command(bt_instance_t* ins, bt_address_t* addr, const char* command, const char* value) +{ + bt_message_packet_t packet; + bt_status_t status; + + BT_SOCKET_INS_VALID(ins, BT_STATUS_PARM_INVALID); + + memcpy(&packet.hfp_ag_pl._bt_hfp_ag_send_vendor_specific_at_cmd.addr, addr, sizeof(bt_address_t)); + strlcpy(packet.hfp_ag_pl._bt_hfp_ag_send_vendor_specific_at_cmd.cmd, command, sizeof(packet.hfp_ag_pl._bt_hfp_ag_send_vendor_specific_at_cmd.cmd)); + strlcpy(packet.hfp_ag_pl._bt_hfp_ag_send_vendor_specific_at_cmd.value, value, sizeof(packet.hfp_ag_pl._bt_hfp_ag_send_vendor_specific_at_cmd.value)); + status = bt_socket_client_sendrecv(ins, &packet, BT_HFP_AG_SEND_VENDOR_SPECIFIC_AT_COMMAND); + if (status != BT_STATUS_SUCCESS) + return status; + + return packet.hfp_ag_r.status; +} \ No newline at end of file diff --git a/service/ipc/socket/include/bt_message_hfp_ag.h b/service/ipc/socket/include/bt_message_hfp_ag.h index 3dc4eea5..23737093 100644 --- a/service/ipc/socket/include/bt_message_hfp_ag.h +++ b/service/ipc/socket/include/bt_message_hfp_ag.h @@ -33,6 +33,7 @@ BT_HFP_AG_MESSAGE_START, BT_HFP_AG_NOTIFY_DEVICE_STATUS, BT_HFP_AG_VOLUME_CONTROL, BT_HFP_AG_SEND_AT_COMMAND, + BT_HFP_AG_SEND_VENDOR_SPECIFIC_AT_COMMAND, BT_HFP_AG_MESSAGE_END, #endif @@ -48,6 +49,7 @@ BT_HFP_AG_MESSAGE_START, BT_HFP_AG_ON_HANGUP_CALL, BT_HFP_AG_ON_DIAL_CALL, BT_HFP_AG_ON_AT_COMMAND_RECEIVED, + BT_HFP_AG_ON_VENDOR_SPECIFIC_AT_COMMAND_RECEIVED, BT_HFP_AG_CALLBACK_END, #endif @@ -113,6 +115,14 @@ BT_HFP_AG_MESSAGE_START, uint8_t pad[2]; char cmd[HFP_AT_LEN_MAX + 1]; } _bt_hfp_ag_send_at_cmd; + + struct { + bt_address_t addr; + uint8_t pad[2]; + char cmd[HFP_COMPANY_PREFIX_LEN_MAX + 1]; + uint8_t pad1[(HFP_COMPANY_PREFIX_LEN_MAX + 1 + 3) / 4 * 4 - (HFP_COMPANY_PREFIX_LEN_MAX + 1)]; + char value[HFP_AT_LEN_MAX + 1]; + } _bt_hfp_ag_send_vendor_specific_at_cmd; } bt_message_hfp_ag_t; typedef union { @@ -159,6 +169,14 @@ BT_HFP_AG_MESSAGE_START, uint8_t pad[2]; char cmd[HFP_AT_LEN_MAX + 1]; } _on_at_cmd_received; + + struct { + bt_address_t addr; + uint16_t company_id; + char command[HFP_COMPANY_PREFIX_LEN_MAX + 1]; + uint8_t pad1[(HFP_COMPANY_PREFIX_LEN_MAX + 1 + 3) / 4 * 4 - (HFP_COMPANY_PREFIX_LEN_MAX + 1)]; + char value[HFP_AT_LEN_MAX + 1]; + } _on_vend_spec_at_cmd_received; } bt_message_hfp_ag_callbacks_t; #ifdef __cplusplus diff --git a/service/ipc/socket/src/bt_socket_hfp_ag.c b/service/ipc/socket/src/bt_socket_hfp_ag.c index 5ab72fe1..568506a2 100644 --- a/service/ipc/socket/src/bt_socket_hfp_ag.c +++ b/service/ipc/socket/src/bt_socket_hfp_ag.c @@ -173,6 +173,25 @@ static void on_at_cmd_received_cb(void* cookie, bt_address_t* addr, const char* bt_socket_server_send(ins, &packet, BT_HFP_AG_ON_AT_COMMAND_RECEIVED); } +static void on_vendor_specific_at_cmd_received_cb(void* cookie, bt_address_t* addr, const char* command, uint16_t company_id, const char* value) +{ + bt_message_packet_t packet = { 0 }; + bt_instance_t* ins = cookie; + + memcpy(&packet.hfp_ag_cb._on_vend_spec_at_cmd_received.addr, addr, sizeof(bt_address_t)); + if (command != NULL) + strlcpy(packet.hfp_ag_cb._on_vend_spec_at_cmd_received.command, command, + sizeof(packet.hfp_ag_cb._on_vend_spec_at_cmd_received.command)); + + packet.hfp_ag_cb._on_vend_spec_at_cmd_received.company_id = company_id; + + if (value != NULL) + strlcpy(packet.hfp_ag_cb._on_vend_spec_at_cmd_received.value, value, + sizeof(packet.hfp_ag_cb._on_vend_spec_at_cmd_received.value)); + + bt_socket_server_send(ins, &packet, BT_HFP_AG_ON_VENDOR_SPECIFIC_AT_COMMAND_RECEIVED); +} + const static hfp_ag_callbacks_t g_hfp_ag_socket_cbs = { .connection_state_cb = on_connection_state_changed_cb, .audio_state_cb = on_audio_state_changed_cb, @@ -184,6 +203,7 @@ const static hfp_ag_callbacks_t g_hfp_ag_socket_cbs = { .hangup_call_cb = on_hangup_call_cb, .dial_call_cb = on_dial_call_cb, .at_cmd_cb = on_at_cmd_received_cb, + .vender_specific_at_cmd_cb = on_vendor_specific_at_cmd_received_cb, }; /**************************************************************************** @@ -297,6 +317,12 @@ void bt_socket_server_hfp_ag_process(service_poll_t* poll, int fd, &packet->hfp_ag_pl._bt_hfp_ag_send_at_cmd.addr, packet->hfp_ag_pl._bt_hfp_ag_send_at_cmd.cmd); break; + case BT_HFP_AG_SEND_VENDOR_SPECIFIC_AT_COMMAND: + packet->hfp_ag_r.status = BTSYMBOLS(bt_hfp_ag_send_vendor_specific_at_command)(ins, + &packet->hfp_ag_pl._bt_hfp_ag_send_vendor_specific_at_cmd.addr, + packet->hfp_ag_pl._bt_hfp_ag_send_vendor_specific_at_cmd.cmd, + packet->hfp_ag_pl._bt_hfp_ag_send_vendor_specific_at_cmd.value); + break; default: break; } @@ -365,6 +391,14 @@ int bt_socket_client_hfp_ag_callback(service_poll_t* poll, &packet->hfp_ag_cb._on_at_cmd_received.addr, packet->hfp_ag_cb._on_at_cmd_received.cmd); break; + case BT_HFP_AG_ON_VENDOR_SPECIFIC_AT_COMMAND_RECEIVED: + CALLBACK_FOREACH(CBLIST, hfp_ag_callbacks_t, + vender_specific_at_cmd_cb, + &packet->hfp_ag_cb._on_vend_spec_at_cmd_received.addr, + packet->hfp_ag_cb._on_vend_spec_at_cmd_received.command, + packet->hfp_ag_cb._on_vend_spec_at_cmd_received.company_id, + packet->hfp_ag_cb._on_vend_spec_at_cmd_received.value); + break; default: return BT_STATUS_PARM_INVALID; } diff --git a/service/profiles/hfp_ag/hfp_ag_service.c b/service/profiles/hfp_ag/hfp_ag_service.c index 5f192cb4..f988af26 100644 --- a/service/profiles/hfp_ag/hfp_ag_service.c +++ b/service/profiles/hfp_ag/hfp_ag_service.c @@ -662,6 +662,21 @@ bt_status_t hfp_ag_send_at_command(bt_address_t* addr, const char* at_command) return hfp_ag_send_message(msg); } +bt_status_t hfp_ag_send_vendor_specific_at_command(bt_address_t* addr, const char* command, const char* value) +{ + if (!command || !value) + return BT_STATUS_PARM_INVALID; + + hfp_ag_msg_t* msg = hfp_ag_msg_new(AG_SEND_VENDOR_SPECIFIC_AT_COMMAND, addr); + if (!msg) + return BT_STATUS_NOMEM; + + AG_MSG_ADD_STR(msg, 1, command, strlen(command)); + AG_MSG_ADD_STR(msg, 2, value, strlen(value)); + + return hfp_ag_send_message(msg); +} + static const hfp_ag_interface_t agInterface = { .size = sizeof(agInterface), .register_callbacks = hfp_ag_register_callbacks, @@ -682,6 +697,7 @@ static const hfp_ag_interface_t agInterface = { .volume_control = hfp_ag_volume_control, .dial_response = hfp_ag_dial_result, .send_at_command = hfp_ag_send_at_command, + .send_vendor_specific_at_command = hfp_ag_send_vendor_specific_at_command, }; static const void* get_ag_profile_interface(void) @@ -752,6 +768,12 @@ void ag_service_notify_cmd_received(bt_address_t* addr, const char* at_cmd) AG_CALLBACK_FOREACH(g_ag_service.callbacks, at_cmd_cb, addr, at_cmd); } +void ag_service_notify_vendor_specific_cmd(bt_address_t* addr, const char* command, uint16_t company_id, const char* value) +{ + BT_LOGD("%s, command:%s, value:%s", __func__, command, value); + AG_CALLBACK_FOREACH(g_ag_service.callbacks, vender_specific_at_cmd_cb, addr, command, company_id, value); +} + void hfp_ag_on_connection_state_changed(bt_address_t* addr, profile_connection_state_t state, profile_connection_reason_t reason, uint32_t remote_features) { diff --git a/service/profiles/hfp_ag/hfp_ag_state_machine.c b/service/profiles/hfp_ag/hfp_ag_state_machine.c index 20a35092..b86c3c51 100644 --- a/service/profiles/hfp_ag/hfp_ag_state_machine.c +++ b/service/profiles/hfp_ag/hfp_ag_state_machine.c @@ -21,6 +21,7 @@ #include #include "audio_control.h" +#include "bluetooth.h" #include "bt_addr.h" #include "bt_device.h" #include "bt_hfp_ag.h" @@ -65,6 +66,16 @@ typedef struct _ag_state_machine { service_timer_t* retry_timer; } ag_state_machine_t; +typedef struct vendor_specific_at_prefix { + char* at_prefix; + uint16_t company_id; +} vendor_specific_at_prefix_t; + +static const vendor_specific_at_prefix_t company_id_map[] = { + { "+XIAOMI", BLUETOOTH_COMPANY_ID_XIAOMI }, + { "+ANDROID", BLUETOOTH_COMPANY_ID_GOOGLE }, +}; + #define AG_TIMEOUT 10000 #define AG_OFFLOAD_TIMEOUT 500 #define AG_STM_DEBUG 1 @@ -200,6 +211,7 @@ static const char* stack_event_to_string(hfp_ag_event_t event) CASE_RETURN_STR(AG_SET_INBAND_RING_ENABLE) CASE_RETURN_STR(AG_DIALING_RESULT) CASE_RETURN_STR(AG_SEND_AT_COMMAND) + CASE_RETURN_STR(AG_SEND_VENDOR_SPECIFIC_AT_COMMAND) CASE_RETURN_STR(AG_STARTUP) CASE_RETURN_STR(AG_SHUTDOWN) CASE_RETURN_STR(AG_CONNECT_TIMEOUT) @@ -427,6 +439,56 @@ static void ag_retry_callback(service_timer_t* timer, void* data) agsm->retry_timer = NULL; } +static void process_vendor_specific_at(bt_address_t* addr, const char* at_string) +{ + uint8_t company_id_index; + uint16_t company_id; + size_t prefix_size; + char command[HFP_COMPANY_PREFIX_LEN_MAX + 1] = { 0 }; + const char* value; + const vendor_specific_at_prefix_t* prefix; + + if (!at_string) + return; + + for (company_id_index = 0; company_id_index < ARRAY_SIZE(company_id_map); company_id_index++) { + prefix = &company_id_map[company_id_index]; + prefix_size = strlen(prefix->at_prefix); + if (strlen(at_string) <= prefix_size + 3 /* "AT" and "=" */) { + continue; + } + if (strncmp(at_string + 2 /* "AT" */, prefix->at_prefix, prefix_size)) { + continue; + } + value = at_string + strlen(prefix->at_prefix) + 3; /* The value is the string after "AT+XIAOMI=" */ + if (value[0] == '\r' || value[0] == '\n') { + break; + } + strlcpy(command, prefix->at_prefix, sizeof(command)); + company_id = prefix->company_id; + + BT_LOGD("%s, command:%s, company_id:0x%04X, value:%s", __FUNCTION__, command, company_id, value); + ag_service_notify_vendor_specific_cmd(addr, command, company_id, value); + bt_sal_hfp_ag_send_at_cmd(addr, "\r\nOK\r\n", sizeof("\r\nOK\r\n")); + return; + } + BT_LOGD("unknown AT command:%s", at_string); + bt_sal_hfp_ag_error_response(addr, HFP_ATCMD_RESULT_CMEERR_OPERATION_NOTSUPPORTED); +} + +static void hfp_ag_send_vendor_specific_at_cmd(bt_address_t* addr, const char* command, const char* value) { + char at_command[HFP_AT_LEN_MAX+1] = "\r\n"; + if (!command || !value) + return; + + strlcat(at_command, command, sizeof(at_command)); + strlcat(at_command, ": ", sizeof(at_command)); + strlcat(at_command, value, sizeof(at_command)); + strlcat(at_command, "\r\n", sizeof(at_command)); + BT_LOGD("%s, command:%s, value:%s", __FUNCTION__, command, value); + bt_sal_hfp_ag_send_at_cmd(addr, at_command, strlen(at_command)); +} + static bool connecting_process_event(state_machine_t* sm, uint32_t event, void* p_data) { ag_state_machine_t* agsm = (ag_state_machine_t*)sm; @@ -446,6 +508,9 @@ static bool connecting_process_event(state_machine_t* sm, uint32_t event, void* case AG_SEND_AT_COMMAND: bt_sal_hfp_ag_send_at_cmd(&agsm->addr, data->string1, strlen(data->string1)); break; + case AG_SEND_VENDOR_SPECIFIC_AT_COMMAND: + hfp_ag_send_vendor_specific_at_cmd(&agsm->addr, data->string1, data->string2); + break; case AG_STACK_EVENT_CONNECTION_STATE_CHANGED: { profile_connection_state_t state = data->valueint1; profile_connection_reason_t reason = data->valueint2; @@ -482,11 +547,7 @@ static bool connecting_process_event(state_machine_t* sm, uint32_t event, void* process_cind_request(agsm); break; case AG_STACK_EVENT_AT_COMMAND: - if (hfp_ag_get_local_features() & HFP_FEAT_AG_UNKNOWN_AT_CMD) { - ag_service_notify_cmd_received(&agsm->addr, data->string1); - } else { - bt_sal_hfp_ag_error_response(&agsm->addr, HFP_ATCMD_RESULT_CMEERR_OPERATION_NOTSUPPORTED); - } + process_vendor_specific_at(&agsm->addr, data->string1); break; case AG_OFFLOAD_START_REQ: audio_ctrl_send_control_event(PROFILE_HFP_AG, AUDIO_CTRL_EVT_START_FAIL); @@ -617,6 +678,9 @@ static bool default_process_event(state_machine_t* sm, uint32_t event, void* p_d case AG_SEND_AT_COMMAND: bt_sal_hfp_ag_send_at_cmd(&agsm->addr, data->string1, strlen(data->string1)); break; + case AG_SEND_VENDOR_SPECIFIC_AT_COMMAND: + hfp_ag_send_vendor_specific_at_cmd(&agsm->addr, data->string1, data->string2); + break; case AG_DIALING_RESULT: if (agsm->dial_out_timer) { service_loop_cancel_timer(agsm->dial_out_timer); @@ -706,10 +770,8 @@ static bool default_process_event(state_machine_t* sm, uint32_t event, void* p_d if (at_cmd_check_test(&agsm->addr, at_cmd)) { break; - } else if (hfp_ag_get_local_features() & HFP_FEAT_AG_UNKNOWN_AT_CMD) { - ag_service_notify_cmd_received(&agsm->addr, at_cmd); } else { - bt_sal_hfp_ag_error_response(&agsm->addr, HFP_ATCMD_RESULT_CMEERR_OPERATION_NOTSUPPORTED); + process_vendor_specific_at(&agsm->addr, at_cmd); } } break; case AG_STACK_EVENT_SEND_DTMF: diff --git a/service/profiles/include/hfp_ag_event.h b/service/profiles/include/hfp_ag_event.h index 8e893442..740ec7ad 100644 --- a/service/profiles/include/hfp_ag_event.h +++ b/service/profiles/include/hfp_ag_event.h @@ -49,6 +49,7 @@ typedef enum { AG_START_VIRTUAL_CALL = 13, AG_STOP_VIRTUAL_CALL = 14, AG_SEND_AT_COMMAND = 18, + AG_SEND_VENDOR_SPECIFIC_AT_COMMAND, AG_STARTUP = 20, AG_SHUTDOWN = 21, AG_CONNECT_TIMEOUT = 25, diff --git a/service/profiles/include/hfp_ag_service.h b/service/profiles/include/hfp_ag_service.h index a4cecc2c..7a4b2f9b 100644 --- a/service/profiles/include/hfp_ag_service.h +++ b/service/profiles/include/hfp_ag_service.h @@ -83,6 +83,7 @@ void ag_service_notify_call_rejected(bt_address_t* addr); void ag_service_notify_call_hangup(bt_address_t* addr); void ag_service_notify_call_dial(bt_address_t* addr, const char* number); void ag_service_notify_cmd_received(bt_address_t* addr, const char* at_cmd); +void ag_service_notify_vendor_specific_cmd(bt_address_t* addr, const char* command, uint16_t company_id, const char* value); /* * telephony @@ -124,6 +125,7 @@ typedef struct ag_interface { bt_status_t (*volume_control)(bt_address_t* addr, hfp_volume_type_t type, uint8_t volume); bt_status_t (*dial_response)(uint8_t result); bt_status_t (*send_at_command)(bt_address_t* addr, const char* at_command); + bt_status_t (*send_vendor_specific_at_command)(bt_address_t* addr, const char* command, const char* value); } hfp_ag_interface_t; /* From 258760fb7fc4537be82f45141fdac80fb2795987 Mon Sep 17 00:00:00 2001 From: jialu Date: Wed, 8 Jan 2025 20:17:09 +0800 Subject: [PATCH 2/2] Bluetooth: Fix memory leak. bug: v/51671 Rootcause: When open transport fails, the memory of transport is not released, leading to memory leakage. Signed-off-by: jialu --- service/profiles/audio_interface/audio_control.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/profiles/audio_interface/audio_control.c b/service/profiles/audio_interface/audio_control.c index 2adaa954..eec7c4fd 100644 --- a/service/profiles/audio_interface/audio_control.c +++ b/service/profiles/audio_interface/audio_control.c @@ -251,7 +251,7 @@ void audio_ctrl_cleanup(uint8_t profile_id) case PROFILE_HFP_AG: case PROFILE_HFP_HF: if (g_audio_ctrl_transport) { - audio_transport_close(g_audio_ctrl_transport, CONFIG_BLUETOOTH_AUDIO_TRANS_ID_HFP_CTRL); + audio_transport_close(g_audio_ctrl_transport, AUDIO_TRANS_CH_ID_ALL); } break; default: