-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Bluetooth: Classic: AVRCP: Support vendor dependent cmd #96273
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Bluetooth: Classic: AVRCP: Support vendor dependent cmd #96273
Conversation
7251c67
to
54ff174
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only reviewed part of the codes.
sizeof(struct bt_l2cap_hdr) + | ||
sizeof(struct bt_avctp_header_start) + | ||
sizeof(struct bt_avrcp_header) + | ||
sizeof(struct bt_avrcp_avc_pdu)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From I see, the bt_avrcp_avc_pdu
is for vendor dependent msg. Is bt_avrcp_create_pdu
only for vendor dependent msg buf creation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently all bt_avrcp_avc_pdu for all AV command buffer alloc included browing buffer, the API's message is the AVRCP payload, so I need to reserve space for the maximum possible AVRCP header inside it, the sizeof(struct bt_avrcp_header) + sizeof(struct bt_avrcp_avc_pdu) is maximum possible AVRCP header.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you consider to divide bt_avrcp_avc_pdu()
into two part. On part for pass through. Another part for vendor independent?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have split two api for net_buf headrom saving
* @ref bt_avrcp_set_browsed_player_rsp. Note that the data is encoded in | ||
* big-endian format. | ||
*/ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
meaningless blank line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
* @param tid The transaction label of the request. | ||
* @param cap_id The capability ID requested. | ||
*/ | ||
void (*get_cap_req)(struct bt_avrcp_tg *tg, uint8_t tid, uint8_t cap_id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why the get_caps_rsp
uses caps
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to standardize the naming of this API so that it's easy to trace from the spec document → PDU ID → command/response buffer name → API and callback.
The reason I renamed it to caps is because of the BT_AVRCP_PDU_ID_GET_CAPS.
uint16_t received_len; /**< Length already received */ | ||
}; | ||
|
||
struct bt_avrcp_tg_tx { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my see, the struct is only used for sending the vendor dependent response, suggest to change as bt_avrcp_tg_vd_rsp_tx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
struct k_sem lock; | ||
|
||
/* TX work */ | ||
struct k_work_delayable tx_work; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my see, it is only used for the vendor dependent response. Suggest to change the name to indicate the usage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
* | ||
* @note This is an AV/C Response semantics (not an AVRCP Error Status). | ||
* When the CT-side callback reports REJECTED, the application MUST parse | ||
* the net buffer to extract the 1-octet Error Status from the PDU payload. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm trying to extend the status field. I want to append the response codes (ranging from 0x8 to 0xF) to the end of the status, starting from 0xFF bt_avrcp_rsp_t.
The response definitions will still remain as they are. pls see bt_avrcp_rsp_t
Now I'm facing a situation where a vendor-dependent Transaction Group (TG) reply requires both a response code and a status. For example, when the TG replies with an AV/C REJECTED response, it also needs to include a reason in the status.
At the same time, I feel that keeping both the response code and the status for the application might introduce redundant information, making the function somewhat awkward.
take example, if not extend the status field, we need
int bt_avrcp_tg_send_add_to_now_playing_rsp(struct bt_avrcp_tg *tg, uint8_t tid, uint8_t rsp_code, uint8_t status);
If we the status field, application only need take care the status, then stack will parse it to rsp_code and status.
detail see spec:
6.15.3 Status and error codes
The responses of AVRCP Specific Browsing Commands contain a status field to indicate success/failure
and an error status code is added to the AV/C REJECTED response if the TG rejected an AVRCP Specific AV/C command.
It is useful for CT to know why the command was rejected by the TG. Table 6.49 shows the status and error codes to
be used with both AVRCP Specific Browsing Commands and AVRCP Specific AV/C Commands.
a665fac
to
dcdbd31
Compare
a54dac2
to
08e5c63
Compare
/** @brief AVRCP Media Attribute structure */ | ||
struct bt_avrcp_media_attr { | ||
uint32_t attr_id; /**< Media attribute ID, see @ref bt_avrcp_media_attr_t */ | ||
uint16_t charset_id; /**< Character set ID, see @ref bt_avrcp_charset_t */ | ||
uint16_t attr_len; /**< Length of attribute value */ | ||
uint8_t attr_val[]; /**< Attribute value data */ | ||
} __packed; | ||
|
||
/** @brief GetElementAttributes command request structure */ | ||
struct bt_avrcp_get_element_attrs_cmd { | ||
uint8_t identifier[8]; /**< Element identifier (0x0 for currently playing) */ | ||
uint8_t num_attrs; /**< Number of attributes requested (0 = all) */ | ||
uint32_t attr_ids[]; /**< Array of requested attribute IDs */ | ||
} __packed; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/** @brief AVRCP Media Attribute structure */ | |
struct bt_avrcp_media_attr { | |
uint32_t attr_id; /**< Media attribute ID, see @ref bt_avrcp_media_attr_t */ | |
uint16_t charset_id; /**< Character set ID, see @ref bt_avrcp_charset_t */ | |
uint16_t attr_len; /**< Length of attribute value */ | |
uint8_t attr_val[]; /**< Attribute value data */ | |
} __packed; | |
/** @brief GetElementAttributes command request structure */ | |
struct bt_avrcp_get_element_attrs_cmd { | |
uint8_t identifier[8]; /**< Element identifier (0x0 for currently playing) */ | |
uint8_t num_attrs; /**< Number of attributes requested (0 = all) */ | |
uint32_t attr_ids[]; /**< Array of requested attribute IDs */ | |
} __packed; | |
/** @brief GetElementAttributes command request structure */ | |
struct bt_avrcp_get_element_attrs_cmd { | |
uint8_t identifier[8]; /**< Element identifier (0x0 for currently playing) */ | |
uint8_t num_attrs; /**< Number of attributes requested (0 = all) */ | |
uint32_t attr_ids[]; /**< Array of requested attribute IDs */ | |
} __packed | |
/** @brief AVRCP Media Attribute structure */ | |
struct bt_avrcp_media_attr { | |
uint32_t attr_id; /**< Media attribute ID, see @ref bt_avrcp_media_attr_t */ | |
uint16_t charset_id; /**< Character set ID, see @ref bt_avrcp_charset_t */ | |
uint16_t attr_len; /**< Length of attribute value */ | |
uint8_t attr_val[]; /**< Attribute value data */ | |
} __packed; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated
struct bt_avrcp_get_play_status_rsp { | ||
uint32_t song_length; /**< Total length of the song in milliseconds */ | ||
uint32_t song_position; /**< Current position in the song in milliseconds */ | ||
uint8_t play_status; /**< Play status: @ref bt_avrcp_playback_status_t*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uint8_t play_status; /**< Play status: @ref bt_avrcp_playback_status_t*/ | |
uint8_t play_status; /**< Play status: @ref bt_avrcp_playback_status_t */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated
|
||
/** @brief RegisterNotification command request */ | ||
struct bt_avrcp_register_notification_cmd { | ||
uint8_t event_id; /**< Event ID to register for */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is the event ID defined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the event ID is bt_avrcp_evt_t, but struct bt_avrcp_register_notification_cmd have been removed because it is not needed anymore
{ BT_AVRCP_PDU_ID_GET_CAPS , BT_AVRCP_CTYPE_STATUS }, | ||
{ BT_AVRCP_PDU_ID_LIST_PLAYER_APP_SETTING_ATTRS , BT_AVRCP_CTYPE_STATUS }, | ||
{ BT_AVRCP_PDU_ID_LIST_PLAYER_APP_SETTING_VALS , BT_AVRCP_CTYPE_STATUS}, | ||
{ BT_AVRCP_PDU_ID_GET_CURR_PLAYER_APP_SETTING_VAL , BT_AVRCP_CTYPE_STATUS}, | ||
{ BT_AVRCP_PDU_ID_SET_PLAYER_APP_SETTING_VAL , BT_AVRCP_CTYPE_CONTROL}, | ||
{ BT_AVRCP_PDU_ID_GET_PLAYER_APP_SETTING_ATTR_TEXT , BT_AVRCP_CTYPE_STATUS}, | ||
{ BT_AVRCP_PDU_ID_GET_PLAYER_APP_SETTING_VAL_TEXT , BT_AVRCP_CTYPE_STATUS}, | ||
{ BT_AVRCP_PDU_ID_INFORM_DISPLAYABLE_CHAR_SET , BT_AVRCP_CTYPE_CONTROL}, | ||
{ BT_AVRCP_PDU_ID_INFORM_BATT_STATUS_OF_CT , BT_AVRCP_CTYPE_CONTROL}, | ||
{ BT_AVRCP_PDU_ID_GET_ELEMENT_ATTRS , BT_AVRCP_CTYPE_STATUS}, | ||
{ BT_AVRCP_PDU_ID_GET_PLAY_STATUS , BT_AVRCP_CTYPE_STATUS}, | ||
{ BT_AVRCP_PDU_ID_REGISTER_NOTIFICATION , BT_AVRCP_CTYPE_NOTIFY}, | ||
{ BT_AVRCP_PDU_ID_SET_ABSOLUTE_VOLUME , BT_AVRCP_CTYPE_CONTROL}, | ||
{ BT_AVRCP_PDU_ID_SET_ADDRESSED_PLAYER , BT_AVRCP_CTYPE_CONTROL}, | ||
{ BT_AVRCP_PDU_ID_PLAY_ITEM , BT_AVRCP_CTYPE_CONTROL}, | ||
{ BT_AVRCP_PDU_ID_ADD_TO_NOW_PLAYING , BT_AVRCP_CTYPE_CONTROL}, | ||
{ BT_AVRCP_PDU_ID_REQ_CONTINUING_RSP , BT_AVRCP_CTYPE_CONTROL}, | ||
{ BT_AVRCP_PDU_ID_ABORT_CONTINUING_RSP , BT_AVRCP_CTYPE_CONTROL}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some lines have space before the brace, and others do not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed, and table is removed
struct avrcp_pdu_vendor_handler { | ||
bt_avrcp_pdu_id_t pdu_id; | ||
uint8_t min_len; | ||
void (*func)(struct bt_avrcp *avrcp, uint8_t tid, uint8_t result, struct net_buf *buf); | ||
}; | ||
|
||
typedef struct { | ||
uint8_t pdu_id; | ||
bt_avrcp_ctype_t cmd_type; | ||
} bt_avrcp_pdu_cmd_map_t; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you consider that these two structures can be merged into one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good suggestion, updated
BT_AVRCP_STATUS_REJECTED = 0xf8, | ||
|
||
/** Interim response. | ||
* Indicates a temporary state; typically used for @ref BT_AVRCP_CTYPE_NOTIFY | ||
* (e.g. RegisterNotification) to signal that a future CHANGED/STABLE | ||
* response will follow. | ||
*/ | ||
BT_AVRCP_STATUS_INTERIM = 0xf9, | ||
|
||
/** Changed response. | ||
* Indicates that the notified value has changed and a final result is provided. | ||
* @note AV/C Response code (not an Error Status). | ||
*/ | ||
BT_AVRCP_STATUS_CHANGED = 0xfa, | ||
|
||
/** Implemented response | ||
* - As IMPLEMENTED: used for SPECIFIC_INQUIRY and GENERAL_INQUIRY commands. | ||
* - As STABLE: used for STATUS commands to indicate a stable current state. | ||
*/ | ||
BT_AVRCP_STATUS_IMPLEMENTED = 0xfb, | ||
|
||
/** Stable response. | ||
* Alias of @ref BT_AVRCP_RSP_IMPLEMENTED for STATUS commands. | ||
*/ | ||
BT_AVRCP_STATUS_STABLE = 0xfc, | ||
|
||
/** In transition response. | ||
* The target is currently changing state (e.g., between play/pause). | ||
*/ | ||
BT_AVRCP_STATUS_IN_TRANSITION = 0xfd, | ||
|
||
/** Accepted response. | ||
* The command has been accepted and will be processed; a later response | ||
* (e.g., CHANGED/STABLE) may follow depending on the PDU. | ||
*/ | ||
BT_AVRCP_STATUS_ACCEPTED = 0xfe, | ||
|
||
/** Not implemented response. | ||
* The command/PDU is not supported by the target device. | ||
*/ | ||
BT_AVRCP_STATUS_NOT_IMPLEMENTED = 0xff, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there are four types of status,
- success -> For control, it means accepted. For status, it means stable.
- in transition -> only for status, it means TG is busy.
- not implemented -> It means the function is not implemented, such as the callback is not implemented, or the feature is not enabled.
- Any other value of
bt_avrcp_status_t
. It means it is a rejected response. The value ofbt_avrcp_status_t
is the reason.
So, I think it can be optimised with these four types of response.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
uint8_t status; | ||
|
||
switch (rsp->cap_id) { | ||
case BT_AVRCP_CAP_COMPANY_ID: | ||
expected_len = rsp->cap_cnt * BT_AVRCP_COMPANY_ID_SIZE; | ||
break; | ||
case BT_AVRCP_CAP_EVENTS_SUPPORTED: | ||
expected_len = rsp->cap_cnt; | ||
break; | ||
default: | ||
LOG_ERR("Unrecognized capability = 0x%x", rsp->cap_id); | ||
return; | ||
} | ||
status = bt_avrcp_rsp_to_status(rsp_code, BT_AVRCP_STATUS_REJECTED); | ||
|
||
if (buf->len < sizeof(*rsp) + expected_len) { | ||
LOG_ERR("Invalid capability payload length: %d", buf->len); | ||
if ((avrcp_ct_cb == NULL) || (avrcp_ct_cb->get_caps_rsp == NULL)) { | ||
return; | ||
} | ||
|
||
avrcp_ct_cb->get_caps_rsp(get_avrcp_ct(avrcp), tid, rsp); | ||
avrcp_ct_cb->get_caps_rsp(get_avrcp_ct(avrcp), tid, status, buf); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the checking of received data length is removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The previous code response parsing and net_buf length checks were handled in the stack. the patch changed moves to using net_buf the length checking and net buffer parsing logic to the application layer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it is a malformed packet, I think it should not be notified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because the common min size checking can not cover the buffer length checking here. I can move moves to using net_buf the length back to stack before notify.
if ((avrcp_tg_cb == NULL) || (avrcp_tg_cb->set_absolute_volume_req == NULL)) { | ||
error_code = BT_AVRCP_STATUS_INTERNAL_ERROR; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the error code should be not implemented
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comments for other commands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"not implemented" more reasonable, updated.
return err; | ||
} | ||
|
||
int bt_avrcp_ct_get_cap(struct bt_avrcp_ct *ct, uint8_t tid, uint8_t cap_id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the rsp callback should be checked here? Since the request is not always successful, if the get cap rsp callback is NULL, what is the purpose of the request?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comments for other commands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
buf = bt_avrcp_create_pdu(&avrcp_pool); | ||
if (buf == NULL) { | ||
LOG_ERR("Failed to allocate buffer"); | ||
return -ENOMEM; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return -ENOMEM; | |
return -ENOBUFS; |
Please check the same case in other functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
Updated the check to use buf->len to ensure the buffer contains enough data for the requested chunk size. Signed-off-by: Make Shi <[email protected]>
08e5c63
to
7f30b30
Compare
6f5302a
to
3a07ada
Compare
This patch introduces support for AVRCP vendor-dependent commands and responses, including full handling of fragmented messages. - Adds fragmentation and reassembly logic for AVRCP vendor-dependent - Introduces TX queue management using delayed work for TG - Adds support for GetCapabilities PDUs - Add new Kconfig for vendor-dependent with fragmentation support Signed-off-by: Make Shi <[email protected]>
This patch adds AVRCP notification event handling for both CT and TG roles. Also add Shell command support for testing notification registration and responses. Signed-off-by: Make Shi <[email protected]>
- Added new callback APIs in bt_avrcp_ct_cb and bt_avrcp_tg_cb - Implemented command/response handlers for CT and TG roles - Extended shell commands for testing vendor dependent commands Signed-off-by: Make Shi <[email protected]>
3a07ada
to
660cae6
Compare
|
if (net_buf_tailroom(buf) < chunk_size) { | ||
LOG_WRN("Not enough tailroom for AVCTP payload (len: %d)", chunk_size); | ||
if (buf->len < chunk_size) { | ||
LOG_WRN("AVCTP payload too short: have %d, need %d", buf->len, chunk_size); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO, this part should be before the send_fragmented_avctp
.
return -ENOBUFS; | ||
} | ||
|
||
if (AVRCP_STATUS_IS_REJECTED(status) == true) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This if
is not needed from my viewpoint, otherwise the status_buf
may not be used and released.
config BT_AVRCP_VENDOR_RX_DATA_BUF_SIZE | ||
int "AVRCP Vendor Dependent RX data buffer Size" | ||
default 1024 | ||
range 1024 $(INT16_MAX) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest to change as 512 $(INT16_MAX)
because the requestcontinue
is used when data length is bigger than 512
.
hdr->opcode = BT_AVRCP_OPC_VENDOR_DEPENDENT; | ||
|
||
err = avrcp_send(ct->avrcp, buf, BT_AVCTP_CMD, tid); | ||
if (err < 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is net_buf_unref(buf);
needed here?
goto err_rsp; | ||
} | ||
|
||
return avrcp_tg_cb->get_caps_req(get_avrcp_tg(avrcp), tid, cap_id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious: The avrcp_tg_cb->get_caps_req
doesn't have return value and process_get_caps_cmd
doesn't have return value too. Is there any building warning?
} | ||
|
||
memset(&ct->ct_notify[event_id], 0, sizeof(ct->ct_notify[0])); | ||
ct->ct_notify[event_id].cb = cb; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it needed: clear the .cb
when the event changed response is received. When registering one event that is already registered return error here.
return -ENOTSUP; | ||
} | ||
|
||
switch (status) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it needed: save the flag whether the event is registered, then return error if not registered by CT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The registered event_id should be flagged. Only registered event can be responded.
I think it is not a dedicated issue for bt_avrcp_tg_send_notification_rsp()
. For AVRCP, all responses should have the similar issue.
* first be registered using @ref bt_avrcp_notification_cb_t. | ||
*/ | ||
void (*notification_rsp)(struct bt_avrcp_ct *ct, uint8_t tid, uint8_t status, | ||
uint8_t event_id, struct bt_avrcp_event_data *data); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO, suggest to callback struct bt_avrcp_event_data *data
only through bt_avrcp_notification_cb_t
, then this callback (changed as register_notification_rsp
) only indicates the result of the registering.
* @note The callback implementation should not block or perform heavy operations. | ||
* If needed, defer processing to another thread or task. | ||
*/ | ||
typedef void(*bt_avrcp_notification_cb_t)(uint8_t event_id, struct bt_avrcp_event_data *data); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO, suggest: typedef void(*bt_avrcp_notification_cb_t)(uint8_t event_id, bool changed, struct bt_avrcp_event_data *data);
then all the event data related callback is here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comments only for first 3 commits.
if (buf->len < chunk_size) { | ||
LOG_WRN("AVCTP payload too short: have %d, need %d", buf->len, chunk_size); | ||
goto failed; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whether is the condition always false?
If user_data->sent_len
is 0 and buf->len < chunk_size
, it should be single packet. This condition is not be checked.
Or, if user_data->sent_len != 0U
, buf->len < chunk_size
should be always false since chunk_size = MIN(buf->len, max_payload_size - BT_AVCTP_HDR_SIZE_CONTINUE_END);
.
help | ||
This option enables the AVRCP profile controller function | ||
|
||
config BT_AVRCP_VENDOR_RX_DATA_BUF_SIZE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
config BT_AVRCP_VENDOR_RX_DATA_BUF_SIZE | |
config BT_AVRCP_VD_RX_SIZE |
or
config BT_AVRCP_VENDOR_RX_DATA_BUF_SIZE | |
config BT_AVRCP_VENDOR_DEPENDENT_RX_SIZE |
config BT_AVRCP_VENDOR_RX_DATA_BUF_SIZE | ||
int "AVRCP Vendor Dependent RX data buffer Size" | ||
default 1024 | ||
range 1024 $(INT16_MAX) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the minimum value 1024? I think it could be MTU of L2CAP.
struct bt_avrcp_tg_vd_rsp_tx *tx = net_buf_user_data(buf); | ||
|
||
__ASSERT(tx != NULL, "user_data is NULL in destroy callback"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the buf allocated from avrcp_vd_tx_pool
has been used to send data (the owner of the buffer is changed from AVRCP to L2CAP), the user data should not be used by AVRCP. Because the user data is dirty.
break; | ||
} | ||
|
||
*out_status = status; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the status
can be removed and pass value to *out_status
directly in switch...case
return -ENOTSUP; | ||
} | ||
|
||
switch (status) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The registered event_id should be flagged. Only registered event can be responded.
I think it is not a dedicated issue for bt_avrcp_tg_send_notification_rsp()
. For AVRCP, all responses should have the similar issue.
case BT_AVRCP_STATUS_NOT_IMPLEMENTED: | ||
rsp_code = BT_AVRCP_RSP_NOT_IMPLEMENTED; | ||
break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think if the INTERIM
has been responded, the NOT_IMPLEMENTED
should not be replied.
|
||
default: | ||
rsp_code = BT_AVRCP_RSP_REJECTED; | ||
break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tg->interim_sent[event_id]
should also be cleared if the rsp_code is rejected.
buf = bt_avrcp_create_vendor_pdu(NULL); | ||
if (buf == NULL) { | ||
LOG_ERR("Failed to allocate buffer"); | ||
return -ENOBUFS; | ||
} | ||
|
||
if (rsp_code == BT_AVRCP_RSP_REJECTED) { | ||
if (net_buf_tailroom(buf) < sizeof(status)) { | ||
LOG_ERR("Not enough space in net_buf"); | ||
net_buf_unref(buf); | ||
return -ENOMEM; | ||
} | ||
net_buf_add_u8(buf, status); | ||
} else { | ||
err = build_notification_rsp_data(event_id, data, buf); | ||
if (err < 0) { | ||
net_buf_unref(buf); | ||
return err; | ||
} | ||
} | ||
|
||
err = bt_avrcp_tg_send_vendor_rsp(tg, tid, BT_AVRCP_PDU_ID_REGISTER_NOTIFICATION, | ||
rsp_code, buf); | ||
if (err < 0) { | ||
LOG_ERR("Failed to send notification response (err: %d)", err); | ||
net_buf_unref(buf); | ||
} | ||
return err; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the INTERIM
has been sent and if there is any error when sending the 2th response, how to avoid the consistency state between CT and TG? Recover tg->interim_sent[event_id]
?
err = build_notification_rsp_data(event_id, data, buf); | ||
if (err < 0) { | ||
net_buf_unref(buf); | ||
return err; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible the buf is provided by the application? And AVRCP provides a series of auxiliary functions for packing the event data.
This patch introduces support for AVRCP vendor-dependent commands and responses, including full handling of fragmented messages.