Skip to content
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

Bluetooth: AVRCP: Implement unit message reception on the AVRCP target #85917

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

makeshi
Copy link
Collaborator

@makeshi makeshi commented Feb 18, 2025

@gzh-terry Please help review it, thanks.

@@ -177,6 +177,13 @@ struct bt_avrcp_cb {
* @param rsp The response for PASS THROUGH command.
*/
void (*passthrough_rsp)(struct bt_avrcp *avrcp, struct bt_avrcp_passthrough_rsp *rsp);
/** @brief Callback function called when received unit info command
Copy link
Collaborator

Choose a reason for hiding this comment

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

Leave one line between 179 and 180 would be better :)

Copy link
Collaborator Author

@makeshi makeshi Feb 19, 2025

Choose a reason for hiding this comment

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

Thanks, I remember there was no space before in these call back function list, and I'd like to keep it consistent. :) Anyway, I'll add a space.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks, I remember there was no space before in these call back function list, and I'd like to keep it consistent. :) Anyway, I'll add a space.

Yes, I added it here #84367 :)

@@ -249,6 +256,17 @@ int bt_avrcp_get_subunit_info(struct bt_avrcp *avrcp);
int bt_avrcp_passthrough(struct bt_avrcp *avrcp, bt_avrcp_opid_t operation_id,
bt_avrcp_button_state_t state, const uint8_t *payload, uint8_t len);

/** @brief Response unit info command.
*
* Send the response unit info command when the receiver will be notified by the registered
Copy link
Collaborator

Choose a reason for hiding this comment

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

response unit info command -> unit info response

int bt_avrcp_response_unit_info(struct bt_avrcp *avrcp, struct bt_avrcp_unit_info_rsp *rsp)
{
struct net_buf *buf;
uint8_t data[5];
Copy link
Collaborator

Choose a reason for hiding this comment

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

Try to keep style consistent, e.g., use param[5].

rsp.unit_type = 0x9;
rsp.company_id = 0x001958; /*BT SIG registered Company ID*/

err = bt_avrcp_response_unit_info(avrcp, &rsp);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Caution: this is in the callback thread, and might lead to assertion in net_buf.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks, let me check it

@makeshi makeshi force-pushed the improve_br_avrcp branch 2 times, most recently from 4f7f13f to 510fc82 Compare February 20, 2025 06:45
@makeshi makeshi requested a review from gzh-terry February 20, 2025 06:58
@@ -249,6 +257,16 @@ int bt_avrcp_get_subunit_info(struct bt_avrcp *avrcp);
int bt_avrcp_passthrough(struct bt_avrcp *avrcp, bt_avrcp_opid_t operation_id,
bt_avrcp_button_state_t state, const uint8_t *payload, uint8_t len);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Set -> Send?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It's also okay to use "send". I use set because I want it to correspond to the above API bt_avrcp_get_unit_info.

Copy link
Collaborator

Choose a reason for hiding this comment

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

It's also okay to use "send". I use set because I want it to correspond to the above API bt_avrcp_get_unit_info.

I think set usualy means to provide a value and save at the local device, or set a configuration to the remote.
However, this interface is to inform the remote device, rather than a configuration.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Agree, Here using "Send" here can indeed better express the actual meaning than "Set" for this function. I'll update the comments and the function name.

gzh-terry
gzh-terry previously approved these changes Feb 20, 2025
Copy link
Collaborator

@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.

/* ToDo */
if ((avrcp_cb != NULL) && (avrcp_cb->unit_info_req != NULL)) {
avrcp_hdr = (void *)buf->data;
net_buf_pull(buf, sizeof(*avrcp_hdr));
Copy link
Contributor

Choose a reason for hiding this comment

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

The buf->len needs to be checked before pulling the net buffer.

After checking the whole receiving data path, I found an issue that the buf->len is also not checked before accessing the buf->data in function avrcp_recv.

avctp_hdr = (void *)buf->data;
net_buf_pull(buf, sizeof(*avctp_hdr));
if (buf->len < sizeof(*avrcp_hdr)) {
LOG_ERR("invalid AVRCP header received");
return -EINVAL;
}
avrcp_hdr = (void *)buf->data;
tid = BT_AVCTP_HDR_GET_TRANSACTION_LABLE(avctp_hdr);
cr = BT_AVCTP_HDR_GET_CR(avctp_hdr);
rsp = BT_AVRCP_HDR_GET_CTYPE_OR_RSP(avrcp_hdr);
subunit_id = BT_AVRCP_HDR_GET_SUBUNIT_ID(avrcp_hdr);
subunit_type = BT_AVRCP_HDR_GET_SUBUNIT_TYPE(avrcp_hdr);

@@ -253,9 +253,26 @@ static void avrcp_unit_info_handler(struct bt_avrcp *avrcp, struct net_buf *buf,
{
struct bt_avrcp_header *avrcp_hdr;
struct bt_avrcp_unit_info_rsp rsp;
bt_avrcp_subunit_type_t subunit_type;

if (cr == BT_AVCTP_CMD) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it is better to split the handler for request and response.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I will split the AVRCP code to handle with different role CT and CG.

if ((subunit_type != BT_AVRCP_SUBUNIT_TYPE_UNIT) ||
(avrcp_hdr->opcode != BT_AVRCP_OPC_UNIT_INFO)) {
LOG_ERR("Invalid unit info command");
return;
Copy link
Contributor

@lylezhu2012 lylezhu2012 Feb 21, 2025

Choose a reason for hiding this comment

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

For the command, if the command is invalid, the response should be sent internally instead of ignoring it.


if (cr == BT_AVCTP_CMD) {
/* ToDo */
if ((avrcp_cb != NULL) && (avrcp_cb->unit_info_req != NULL)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

The command handling should be controlled by the registered callback. Such as, if the command is not valid or the command is unsupported, the error response should be sent directly.

{
struct net_buf *buf;

buf = avrcp_create_unit_pdu(avrcp, BT_AVCTP_RESPONSE);
Copy link
Contributor

Choose a reason for hiding this comment

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

The TID should be same with the TID of the command.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

TID should added as all function calls and callback parameter, handled in application code side.

Copy link
Contributor

@lylezhu2012 lylezhu2012 Feb 24, 2025

Choose a reason for hiding this comment

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

But the TID cannot be set by application in your PR.

And I think if the TID need be set by application, the TID of command should also be notified to application.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

As you comments as in #85910, these is only one command is ongoing , so also need the TID sent should be same with the TID of the command.

}

/* Add additional info */
net_buf_add_u8(buf, 0x07);
Copy link
Contributor

Choose a reason for hiding this comment

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

What does the mean of 7? I think the hard code should be defined as a MICRO.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I did not find the real mean of the 7,
image
and The protocol analysis tool recognizes as the "Const byte"
image

Copy link
Collaborator

@gzh-terry gzh-terry Feb 21, 2025

Choose a reason for hiding this comment

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

Hi @makeshi @lylezhu2012

0x07 means page = 0 and extension_code = 7
page shall only be greater than 0 when the number of extended units exceeds 4, which is not possible at unit info response, where the number of extended units is 0.
extension_code is not defined currently, so all three bits are set to 1.

image

Copy link
Collaborator

Choose a reason for hiding this comment

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

UNIT INFO response generally has the same structure as SUBUNIT INFO response.

Copy link
Collaborator

@gzh-terry gzh-terry Feb 21, 2025

Choose a reason for hiding this comment

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

@makeshi can use

	FIELD_PREP(GENMASK(6, 4), AVRCP_SUBUNIT_PAGE) |
		FIELD_PREP(GENMASK(2, 0), AVRCP_SUBUNIT_EXTENSION_COED);

Which exactly is 0x7

Copy link
Contributor

Choose a reason for hiding this comment

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

Hi @makeshi @lylezhu2012

0x07 means page = 0 and extension_code = 7 page shall only be greater than 0 when the number of extended units exceeds 4, which is not possible at unit info response, where the number of extended units is 0. extension_code is not defined currently, so all three bits are set to 1.

The command is unit info instead of subunit info.
From UNIT INFO status command response format, it is a hardcode without any comments. It seams the field has not yet explained of what it means.
image

Copy link
Collaborator

Choose a reason for hiding this comment

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

Hi @makeshi @lylezhu2012
0x07 means page = 0 and extension_code = 7 page shall only be greater than 0 when the number of extended units exceeds 4, which is not possible at unit info response, where the number of extended units is 0. extension_code is not defined currently, so all three bits are set to 1.

The command is unit info instead of subunit info. From UNIT INFO status command response format, it is a hardcode without any comments. It seams the field has not yet explained of what it means. image

Then just put 0x7 is fine, to exactly match the spec.

Copy link
Member

Choose a reason for hiding this comment

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

It's good to have at least a code comment pointing out that the constant is hard-coded in the spec

/* Add additional info */
net_buf_add_u8(buf, 0x07);
/* Add Unit Type info */
net_buf_add_u8(buf, FIELD_PREP(GENMASK(7, 3), (rsp->unit_type)));
Copy link
Contributor

Choose a reason for hiding this comment

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

For AVRCP, the unit_type should be Panel, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

current , it is right, but in spec, it mentions
image
So, for the code extensibility, I also used the uint_type as a parameter not hard code for Panel

Copy link
Collaborator

Choose a reason for hiding this comment

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

@makeshi @lylezhu2012
We may consider to expose bt_avrcp_subunit_type_t (BT_AVRCP_SUBUNIT_TYPE_PANEL = 0x9) to users?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, I think we could expose it

@nashif
Copy link
Member

nashif commented Feb 21, 2025

Please set a readable and useful PR title and add more description the PR body, the PR body should be used for more details about the change and not to ask for reviews.

@makeshi makeshi changed the title Improve br avrcp Bluetooth: AVRCP: Implement unit message reception on the AVRCP target Feb 25, 2025
@makeshi makeshi force-pushed the improve_br_avrcp branch from 510fc82 to 54dd129 Compare March 4, 2025 07:18
@makeshi makeshi force-pushed the improve_br_avrcp branch from 54dd129 to e772dc6 Compare March 4, 2025 07:47
makeshi added 2 commits March 4, 2025 16:13
Add a new callback to support the situation when a unit info command is
received, and add an API to respond to the unit info command.

Signed-off-by: Make Shi <make.shi@nxp.com>
Add avrcp_unit_info_req callback function in shell and a command to set
the unit info response.

Signed-off-by: Make Shi <make.shi@nxp.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants