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: has: Ensure that notifications are sent #61980

Merged
merged 14 commits into from
Oct 20, 2023

Conversation

MariuszSkamra
Copy link
Collaborator

@MariuszSkamra MariuszSkamra commented Aug 28, 2023

This ensures active preset index, HAS features and partially control point notifications are sent.
The code retries sending notifications in case of lack of available buffers.
Partially addresses #57454

@MariuszSkamra MariuszSkamra force-pushed the has_notify_retry branch 3 times, most recently from b884dd3 to 085952f Compare August 31, 2023 11:44
@MariuszSkamra MariuszSkamra changed the title Bluetooth: has: Retry sending notification on error Bluetooth: has: Ensure that notifications are sent Sep 6, 2023
@MariuszSkamra MariuszSkamra marked this pull request as ready for review September 6, 2023 07:10
subsys/bluetooth/audio/has.c Show resolved Hide resolved
subsys/bluetooth/audio/has.c Outdated Show resolved Hide resolved
tests/bsim/bluetooth/audio/src/common.c Outdated Show resolved Hide resolved
tests/bsim/bluetooth/audio/src/has_client_test.c Outdated Show resolved Hide resolved
tests/bsim/bluetooth/audio/src/has_client_test.c Outdated Show resolved Hide resolved
subsys/bluetooth/audio/has.c Outdated Show resolved Hide resolved
subsys/bluetooth/audio/has.c Outdated Show resolved Hide resolved
subsys/bluetooth/audio/has.c Outdated Show resolved Hide resolved
subsys/bluetooth/audio/has.c Outdated Show resolved Hide resolved
subsys/bluetooth/audio/has.c Show resolved Hide resolved
subsys/bluetooth/audio/has.c Outdated Show resolved Hide resolved
subsys/bluetooth/audio/has.c Show resolved Hide resolved
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why are we mostly re-implementing the HAS client again here?

Couldn't we reuse a lot of the code from the actual implementation?

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 HAS client unsubscribes from the notifications on disconnection, I cannot use it for offline behavior test cases

Copy link
Collaborator

Choose a reason for hiding this comment

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

As HAS client unsubscribes from the notifications on disconnection, I cannot use it for offline behavior test cases

Wouldn't it be easier to implement support for bonding in the client, than reimplementing a new HAS client that supports that? This just seems like much more effort than fixing the missing feature from the current HAS client :)

But can be done in a separate PR.

tests/bsim/bluetooth/audio/src/has_client_test.c Outdated Show resolved Hide resolved
tests/bsim/bluetooth/audio/test_scripts/has_offline.sh Outdated Show resolved Hide resolved
@@ -589,7 +687,7 @@ static int bt_has_cp_generic_update(struct has_client *client, const struct has_
preset_changed_prepare(&buf, BT_HAS_CHANGE_ID_GENERIC_UPDATE, is_last);

generic_update = net_buf_simple_add(&buf, sizeof(*generic_update));
generic_update->prev_index = get_prev_preset_index(preset);
generic_update->prev_index = preset_get_prev_index(preset);
Copy link
Contributor

Choose a reason for hiding this comment

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

This will provide a wrapped index. The first item in the list has to have a prevIndex of 0.

@MariuszSkamra
Copy link
Collaborator Author

MariuszSkamra commented Oct 12, 2023

Fixed preset list notifications after reconnection if the tail of the preset list have changed (the las one preset have been removed).

In such case:

/* The last preset known to the client has been removed.
 * As we do not hold the information about the deleted presets, we need to use
 * Generic Update procedure to:
 *   1. Notify the presets that have been removed in range
 *      (PrevIndex = current_preset_last, Index=previous_preset_last)
 *   2. Notify deletion of preset Index=previous_preset_last.
 */

@MariuszSkamra MariuszSkamra force-pushed the has_notify_retry branch 3 times, most recently from 6efa790 to bc400b9 Compare October 12, 2023 22:19
subsys/bluetooth/audio/has.c Outdated Show resolved Hide resolved
subsys/bluetooth/audio/has.c Outdated Show resolved Hide resolved
subsys/bluetooth/audio/has.c Outdated Show resolved Hide resolved
subsys/bluetooth/audio/has.c Outdated Show resolved Hide resolved
subsys/bluetooth/audio/has.c Outdated Show resolved Hide resolved
This fixes testing and clearing features flag.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
This fixes code indentation.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
This removes revering the features value back to previous state if work
submission failes. Even if it fails it indicates an internal sysworkq
issue, so even retry won't help. The client can read the features value
anyway, thus it's sane to just log an error in such case.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
This fixes missing setting of FLAG_CONTROL_POINT_NOTIFY flag that
indicate whether submit control_point_work. In case the there are more
indications/notifications to sent (is_last flag is unset), the
FLAG_CONTROL_POINT_NOTIFY shall be set to resubmit control_point_work.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
This moves common code to set_preset_availability function to be called
from bt_has_preset_available and bt_has_preset_unavailable.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
Verify that a HAS Server IUT sends changed characteristic notifications
or indications when the Lower Tester reconnects.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
Defer sending the features, active index, preset list and preset read
response to sysworkq and retry sending in case failed due to buffers not
available at the moment.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
This refactors the preset list to use sys_slist API. There have been
various issues seen while iterating presets, thus it's more save to use
well-defined and tested sys_slist API.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
Some of the data shall be persistent across connections to bonded
clients. This includes notidication state flags that are used to
determine whether notify bonded client after reconnection.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
This fixes sending proper Preset List notifications after
reconnection. The issue was observed when the last preset
known to the client has been removed.
As we do not hold the information about the deleted presets,
we need to use Generic Update procedure to:
 1. Notify the presets that have been removed in range
    (PrevIndex = current_preset_last, Index=previous_preset_last)
 2. Notify deletion of preset Index=previous_preset_last.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
This fixes missing memset of parameters used for indications and/or
notifications.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
@MariuszSkamra MariuszSkamra force-pushed the has_notify_retry branch 2 times, most recently from b2b7135 to 85d80f3 Compare October 18, 2023 13:12
@MariuszSkamra MariuszSkamra marked this pull request as ready for review October 18, 2023 13:14
@@ -9,6 +9,7 @@ menuconfig BT_HAS
select EXPERIMENTAL
select UTF8
select BT_GATT_DYNAMIC_DB
select BT_GATT_AUTO_UPDATE_MTU
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is an interesting addition.

We've seen issues with Android, where Android (as the central) did not properly update the MTU on connection, which mean that some notifications sent by us (as peripheral) could not be done, due to MTU not matching the requirements from e.g. BAP.

HOWEVER
BT_GATT_AUTO_UPDATE_MTU depends on BT_GATT_CLIENT, which may not always be the case here for BT_HAS. So I don't think we should add select BT_GATT_AUTO_UPDATE_MTU here, but maybe we need to wait with the notifications until the MTU has been exchanged?

This is, btw, a general issue with all the LE Audio service implementations, where we cannot assume that the MTU has been exchanged when we are the server (and not can we expect it to do it ourself, if we are not the client).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is an interesting addition.

We've seen issues with Android, where Android (as the central) did not properly update the MTU on connection, which mean that some notifications sent by us (as peripheral) could not be done, due to MTU not matching the requirements from e.g. BAP.

Can you elaborate? Was the MTU requested too small?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, we've seen issues where we try to send notifications on reconnect of size e.g. 30 (assuming that the MTU is 64 as mandated by e.g. the BAP spec), because the phone did not request an update to the MTU before our first notification. I think it would make sense for all services in profiles that depend on BAP (CAP, TMAP, HAP, etc.) wait with sending notifications on reconnect until after the GATT MTU has been exchanged (at least the ones where it may be larger than the initial MTU of 23).

I think that we should probably add select BT_GATT_AUTO_UPDATE_MTU to any profile enabled where we act as the GATT client (e.g. BT_HAS_CLIENT), but we should not enable it for profiles where we are the GATT server (e.g. BT_HAS), as we cannot be sure that BT_GATT_CLIENT is enabled.

I am unsure what happens if a Kconfig selects another Kconfig without satisfying the dependencies.

Copy link
Collaborator Author

@MariuszSkamra MariuszSkamra Oct 19, 2023

Choose a reason for hiding this comment

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

Yes, we've seen issues where we try to send notifications on reconnect of size e.g. 30 (assuming that the MTU is 64 as mandated by e.g. the BAP spec), because the phone did not request an update to the MTU before our first notification. I think it would make sense for all services in profiles that depend on BAP (CAP, TMAP, HAP, etc.) wait with sending notifications on reconnect until after the GATT MTU has been exchanged (at least the ones where it may be larger than the initial MTU of 23).

I would say it's not phone's fault that the server wants to send the notification that does not fit MTU.
On the other hand the server does not know when the client is ready to receive the notifications (e.g. the profiles or some application is ready).
As there is no dedicated L2CAP channel PSM the client connects to, but ATT which is available right after connection this causes issues like that IMO.

I think that we should probably add select BT_GATT_AUTO_UPDATE_MTU to any profile enabled where we act as the GATT client (e.g. BT_HAS_CLIENT), but we should not enable it for profiles where we are the GATT server (e.g. BT_HAS), as we cannot be sure that BT_GATT_CLIENT is enabled.

BT_HAS_CLIENT selects BT_GATT_AUTO_UPDATE_MTU already. For profiles that are written on top of GATT Server I think that we should truncate the notifications, and apply some timeout waiting tor ATT exchange.

BTW, it would be helpful if we could have a function that will return true/false to know whether MTU was or was not already exchanged.

Like in HAS case in security_changed callback, I would like to check whether I still need to wait for MTU to be exchanged or it was exchanged already but the MTU stayed at 23 bytes

Copy link
Collaborator

Choose a reason for hiding this comment

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

BTW, it would be helpful if we could have a function that will return true/false to know whether MTU was or was not already exchanged.

We have bt_gatt_get_mtu, and I guess you could simply do bool mtu_exchanged = bt_gatt_get_mtu() == BT_ATT_DEFAULT_LE_MTU

Copy link
Collaborator Author

@MariuszSkamra MariuszSkamra Oct 19, 2023

Choose a reason for hiding this comment

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

This won't work, because if bt_gatt_get_mtu returns 23, it means either the MTU was not exchanged, or it was exchanged and is 23. So one does not know whether it may still expect MTU Exchange or not

Copy link
Collaborator

Choose a reason for hiding this comment

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

Good point.

IIRC the bt_gatt_cb.att_mtu_updated is even called on connection (bt_att_connected calls att_chan_mtu_updated), so we can't even use the callback.

I'll raise a GH issue for this.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I've created #64175 and #64172

subsys/bluetooth/audio/has_internal.h Outdated Show resolved Hide resolved
This will truncate ATT notifications/indications if exceed ATT MTU size.
It is up to the client to exchange MTU.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
This makes use of bt_conn_get_info function to access the conn address.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
This adds more logs for debugging purposes.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
@carlescufi carlescufi merged commit 49e7030 into zephyrproject-rtos:main Oct 20, 2023
21 checks passed
@MariuszSkamra MariuszSkamra deleted the has_notify_retry branch October 20, 2023 13:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

6 participants