diff --git a/components/bt/host/bluedroid/api/esp_avrc_api.c b/components/bt/host/bluedroid/api/esp_avrc_api.c index 125bfff111..50b5fd78d3 100644 --- a/components/bt/host/bluedroid/api/esp_avrc_api.c +++ b/components/bt/host/bluedroid/api/esp_avrc_api.c @@ -232,6 +232,31 @@ esp_err_t esp_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code, uint8_t return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; } +esp_err_t esp_avrc_ct_send_get_play_status_cmd(uint8_t tl) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (tl > ESP_AVRC_TRANS_LABEL_MAX) { + return ESP_ERR_INVALID_ARG; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_AVRC_CT; + msg.act = BTC_AVRC_STATUS_API_SND_GET_PLAY_STATUS_EVT; + + btc_avrc_args_t arg; + memset(&arg, 0, sizeof(btc_avrc_args_t)); + + arg.get_play_status_cmd.tl = tl; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_args_t), NULL, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + #if BTC_AV_CA_INCLUDED esp_err_t esp_avrc_ct_cover_art_connect(uint16_t mtu) diff --git a/components/bt/host/bluedroid/api/include/api/esp_avrc_api.h b/components/bt/host/bluedroid/api/include/api/esp_avrc_api.h index 1c1e34ab2a..ddf59d081a 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_avrc_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_avrc_api.h @@ -323,6 +323,15 @@ typedef union { int attr_length; /*!< attribute character length */ } meta_rsp; /*!< metadata attributes response */ + /** + * @brief ESP_AVRC_CT_PLAY_STATUS_RSP_EVT + */ + struct avrc_ct_get_play_status_rsp_param { + uint32_t song_length; /*!< total length of the playing song in milliseconds */ + uint32_t song_position; /*!< current position of the playing song in milliseconds elapsed */ + esp_avrc_playback_stat_t play_status; /*!< current status of playing */ + } play_status_rsp; /*!< get play status command response */ + /** * @brief ESP_AVRC_CT_CHANGE_NOTIFY_EVT */ @@ -586,6 +595,18 @@ esp_err_t esp_avrc_ct_send_metadata_cmd(uint8_t tl, uint8_t attr_mask); */ esp_err_t esp_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code, uint8_t key_state); +/** + * @brief Send get play status command to AVRCP target. This function should be called after + * ESP_AVRC_CT_CONNECTION_STATE_EVT is received and AVRCP connection is established. + * + * @param[in] tl : transaction label, 0 to 15, consecutive commands should use different values. + * + * @return + * - ESP_OK: success + * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + */ +esp_err_t esp_avrc_ct_send_get_play_status_cmd(uint8_t tl); /** * @brief Register application callbacks to AVRCP target module. This function should be diff --git a/components/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c b/components/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c index a783d5e350..d03795babd 100644 --- a/components/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c +++ b/components/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c @@ -700,6 +700,18 @@ static void handle_rc_set_absolute_volume_rsp(tAVRC_SET_VOLUME_RSP *rsp) btc_avrc_ct_cb_to_app(ESP_AVRC_CT_SET_ABSOLUTE_VOLUME_RSP_EVT, ¶m); } +static void handle_rc_get_play_status_rsp(tAVRC_GET_PLAY_STATUS_RSP *rsp) +{ + esp_avrc_ct_cb_param_t param; + memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t)); + + param.play_status_rsp.song_length = rsp->song_len; + param.play_status_rsp.song_position = rsp->song_pos; + param.play_status_rsp.play_status = rsp->play_status; + + btc_avrc_ct_cb_to_app(ESP_AVRC_CT_PLAY_STATUS_RSP_EVT, ¶m); +} + /*************************************************************************** * Function handle_rc_metamsg_cmd * @@ -898,6 +910,9 @@ static void handle_rc_metamsg_rsp (tBTA_AV_META_MSG *p_meta_msg) handle_rc_set_absolute_volume_rsp(&avrc_response.volume); } break; + case AVRC_PDU_GET_PLAY_STATUS: + handle_rc_get_play_status_rsp(&avrc_response.get_play_status); + break; default: BTC_TRACE_WARNING("%s: unhandled meta rsp: pdu 0x%x", __FUNCTION__, avrc_response.rsp.pdu); } @@ -1333,6 +1348,38 @@ static bt_status_t btc_avrc_ct_send_metadata_cmd (uint8_t tl, uint8_t attr_mask) return status; } +static bt_status_t btc_avrc_ct_send_get_play_status_cmd(uint8_t tl) +{ + tAVRC_STS status = BT_STATUS_UNSUPPORTED; + +#if (AVRC_METADATA_INCLUDED == TRUE) + CHECK_ESP_RC_CONNECTED; + + tAVRC_COMMAND avrc_cmd = {0}; + BT_HDR *p_msg = NULL; + + avrc_cmd.get_play_status.opcode = AVRC_OP_VENDOR; + avrc_cmd.get_play_status.status = AVRC_STS_NO_ERROR; + avrc_cmd.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS; + + if (btc_rc_cb.rc_features & BTA_AV_FEAT_METADATA) { + status = AVRC_BldCommand(&avrc_cmd, &p_msg); + if (status == AVRC_STS_NO_ERROR) { + BTA_AvMetaCmd(btc_rc_cb.rc_handle, tl, AVRC_CMD_STATUS, p_msg); + status = BT_STATUS_SUCCESS; + } + } else { + status = BT_STATUS_FAIL; + BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__); + } + +#else + BTC_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__); +#endif + + return status; +} + static bt_status_t btc_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code, uint8_t key_state) { tAVRC_STS status = BT_STATUS_UNSUPPORTED; @@ -1550,6 +1597,10 @@ void btc_avrc_ct_call_handler(btc_msg_t *msg) btc_avrc_ct_send_metadata_cmd(arg->md_cmd.tl, arg->md_cmd.attr_mask); break; } + case BTC_AVRC_STATUS_API_SND_GET_PLAY_STATUS_EVT: { + btc_avrc_ct_send_get_play_status_cmd(arg->get_play_status_cmd.tl); + break; + } case BTC_AVRC_STATUS_API_SND_GET_RN_CAPS_EVT: { btc_avrc_ct_send_get_rn_caps_cmd(arg->get_caps_cmd.tl); break; diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_avrc.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_avrc.h index a78a7af1db..98178ee608 100644 --- a/components/bt/host/bluedroid/btc/profile/std/include/btc_avrc.h +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_avrc.h @@ -37,6 +37,7 @@ typedef enum { BTC_AVRC_STATUS_API_SND_META_EVT, BTC_AVRC_STATUS_API_SND_PLAY_STATUS_EVT, BTC_AVRC_STATUS_API_SND_GET_RN_CAPS_EVT, + BTC_AVRC_STATUS_API_SND_GET_PLAY_STATUS_EVT, BTC_AVRC_NOTIFY_API_SND_REG_NOTIFY_EVT, BTC_AVRC_CTRL_API_SND_SET_PLAYER_SETTING_EVT, BTC_AVRC_CTRL_API_SND_SET_ABSOLUTE_VOLUME_EVT, @@ -76,6 +77,10 @@ typedef struct { uint8_t tl; } get_caps_cmd_t; +typedef struct { + uint8_t tl; +} get_play_status_cmd_t; + #define BTC_AVRC_MIN_VOLUME 0x00 #define BTC_AVRC_MAX_VOLUME 0x7f @@ -113,6 +118,7 @@ typedef union { rn_cmd_t rn_cmd; ps_cmd_t ps_cmd; get_caps_cmd_t get_caps_cmd; + get_play_status_cmd_t get_play_status_cmd; set_abs_vol_cmd_t set_abs_vol_cmd; #if BTC_AV_CA_INCLUDED ca_conn_t ca_conn; diff --git a/components/bt/host/bluedroid/common/include/common/bt_target.h b/components/bt/host/bluedroid/common/include/common/bt_target.h index 3142335694..c7dff7606d 100644 --- a/components/bt/host/bluedroid/common/include/common/bt_target.h +++ b/components/bt/host/bluedroid/common/include/common/bt_target.h @@ -956,7 +956,7 @@ /* The number of security records for services. 32 AS Default*/ #ifndef BTM_SEC_MAX_SERVICE_RECORDS -#define BTM_SEC_MAX_SERVICE_RECORDS 8 // 32 +#define BTM_SEC_MAX_SERVICE_RECORDS 32 #endif /* If True, force a retrieval of remote device name for each bond in case it's changed */ diff --git a/components/bt/host/bluedroid/stack/avrc/avrc_bld_ct.c b/components/bt/host/bluedroid/stack/avrc/avrc_bld_ct.c index 1810687066..279313d4c6 100644 --- a/components/bt/host/bluedroid/stack/avrc/avrc_bld_ct.c +++ b/components/bt/host/bluedroid/stack/avrc/avrc_bld_ct.c @@ -50,7 +50,7 @@ static tAVRC_STS avrc_bld_next_cmd (tAVRC_NEXT_CMD *p_cmd, BT_HDR *p_pkt) p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start + 2; /* pdu + rsvd */ - /* add fixed lenth 1 - pdu_id (1) */ + /* add fixed length 1 - pdu_id (1) */ UINT16_TO_BE_STREAM(p_data, 1); UINT8_TO_BE_STREAM(p_data, p_cmd->target_pdu); p_pkt->len = (p_data - p_start); @@ -81,7 +81,7 @@ static tAVRC_STS avrc_bld_set_abs_volume_cmd (tAVRC_SET_VOLUME_CMD *p_cmd, BT_HD /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start + 2; /* pdu + rsvd */ - /* add fixed lenth 1 - volume (1) */ + /* add fixed length 1 - volume (1) */ UINT16_TO_BE_STREAM(p_data, 1); UINT8_TO_BE_STREAM(p_data, (AVRC_MAX_VOLUME & p_cmd->volume)); p_pkt->len = (p_data - p_start); @@ -163,7 +163,7 @@ static BT_HDR *avrc_bld_init_cmd_buffer(tAVRC_COMMAND *p_cmd) /* reserved 0, packet_type 0 */ UINT8_TO_BE_STREAM(p_data, 0); /* continue to the next "case to add length */ - /* add fixed lenth - 0 */ + /* add fixed length - 0 */ UINT16_TO_BE_STREAM(p_data, 0); break; } @@ -237,6 +237,20 @@ static tAVRC_STS avrc_bld_get_element_attr_cmd (tAVRC_GET_ELEM_ATTRS_CMD *p_cmd, return AVRC_STS_NO_ERROR; } +static tAVRC_STS avrc_bld_get_play_status_cmd(tAVRC_CMD *p_cmd, BT_HDR *p_pkt) +{ + UINT8 *p_data, *p_start; + + AVRC_TRACE_API("avrc_bld_get_play_status"); + /* get the existing length */ + p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; + p_data = p_start + 2; /* pdu + rsvd */ + /* add parameter length 0 */ + UINT16_TO_BE_STREAM(p_data, 0); + p_pkt->len = (p_data - p_start); + return AVRC_STS_NO_ERROR; +} + static tAVRC_STS avrc_bld_get_caps_cmd(tAVRC_GET_CAPS_CMD *p_cmd, BT_HDR *p_pkt) { UINT8 *p_data, *p_start; @@ -309,6 +323,10 @@ tAVRC_STS AVRC_BldCommand( tAVRC_COMMAND *p_cmd, BT_HDR **pp_pkt) status = avrc_bld_get_element_attr_cmd(&p_cmd->get_elem_attrs, p_pkt); break; + case AVRC_PDU_GET_PLAY_STATUS: /* 0x30 */ + status = avrc_bld_get_play_status_cmd(&p_cmd->get_play_status, p_pkt); + break; + case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */ status = avrc_bld_register_change_notfn(p_cmd->reg_notif.event_id, p_cmd->reg_notif.param, p_pkt); break; diff --git a/components/bt/host/bluedroid/stack/avrc/avrc_pars_ct.c b/components/bt/host/bluedroid/stack/avrc/avrc_pars_ct.c index f185e7b569..72f2651397 100644 --- a/components/bt/host/bluedroid/stack/avrc/avrc_pars_ct.c +++ b/components/bt/host/bluedroid/stack/avrc/avrc_pars_ct.c @@ -113,6 +113,19 @@ static tAVRC_STS avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR *p_msg, tAVRC_RESPONSE *p } } break; + case AVRC_PDU_GET_PLAY_STATUS: + if (p_msg->hdr.ctype == AVRC_RSP_IMPL_STBL) { + BE_STREAM_TO_UINT32(p_result->get_play_status.song_len, p); + BE_STREAM_TO_UINT32(p_result->get_play_status.song_pos, p); + BE_STREAM_TO_UINT8(p_result->get_play_status.play_status, p); + } + else { + /* got error response */ + p_result->get_play_status.song_len = 0; + p_result->get_play_status.song_pos = 0; + p_result->get_play_status.play_status = AVRC_PLAYSTATE_ERROR; + } + break; default: status = AVRC_STS_BAD_CMD; break; diff --git a/components/bt/host/bluedroid/stack/goep/goepc_api.c b/components/bt/host/bluedroid/stack/goep/goepc_api.c index 350e80c9c2..06be8f59cb 100644 --- a/components/bt/host/bluedroid/stack/goep/goepc_api.c +++ b/components/bt/host/bluedroid/stack/goep/goepc_api.c @@ -359,7 +359,7 @@ UINT16 GOEPC_RequestAddHeader(UINT16 handle, UINT8 header_id, const UINT8 *data, break; } - if ((data == NULL) ^ (data_len == 0)) { + if ((data == NULL && data_len != 0) || (data != NULL && data_len == 0)) { ret = GOEP_INVALID_PARAM; break; } diff --git a/components/bt/host/bluedroid/stack/obex/obex_api.c b/components/bt/host/bluedroid/stack/obex/obex_api.c index 8851a0f81a..0ebf14bf6d 100644 --- a/components/bt/host/bluedroid/stack/obex/obex_api.c +++ b/components/bt/host/bluedroid/stack/obex/obex_api.c @@ -491,7 +491,7 @@ UINT16 OBEX_AppendHeaderRaw(BT_HDR *pkt, UINT8 header_id, const UINT8 *data, UIN return OBEX_INVALID_PARAM; } - if ((data == NULL) ^ (data_len == 0)) { + if ((data == NULL && data_len != 0) || (data != NULL && data_len == 0)) { return OBEX_INVALID_PARAM; }