Skip to content

BLE streamlining #13365

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

Merged
merged 13 commits into from
Aug 10, 2020
Merged

BLE streamlining #13365

merged 13 commits into from
Aug 10, 2020

Conversation

paul-szczepanek-arm
Copy link
Member

@paul-szczepanek-arm paul-szczepanek-arm commented Jul 28, 2020

Summary of changes

This is a refactor of BLE that makes Cordio the official BLE stack. There are no changes from the user's perspective. The API remains the same. This is to lessen the maintenance load. Other implementations are welcome but must implement the user API directly.

The internal changes are as follows:

  • removed the generic layer which is now the direct implementation of the interface
  • removed templated implementations
  • removed nested namespaces in favour of unique names (unambiguous, do not rely on namespace context)
  • removed support for multiple instances within the BLE singleton (which was already the case, see below)

This retains the separation at the PAL level, but without the templated implementation. Alternative implementations are possible by implementing the PAL API.

In simple words:
BLE is now a singleton. All implementation are non virtual concrete classes that implement interfaces directly. Any alternative implementation will have to be switched at compile time (see mbed_lib.json).

Impact of changes

Migration actions required

There are no other known BLE implementations but any porter who has one will need to adjust their implementation of BLEInstanceBase as we no longer support multiple instances within the BLE singleton. Multiple instances of BLE are supported but must be managed by the user/porter by creating their own instance of BLE.

This is already the case. The change is that this is now enforced by the API.

Documentation

None


Pull request type

[x] Patch update (Bug fix / Target update / Docs update / Test update / Refactor)
[] Feature update (New feature / Functionality change / New API)
[] Major update (Breaking change E.g. Return code change / API behaviour change)

Test results

[] No Tests required for this change (E.g docs only update)
[] Covered by existing mbed-os tests (Greentea or Unittest)
[x] Tests / results supplied as part of this PR

Reviewers

@donatieng
@LDong-Arm

@paul-szczepanek-arm
Copy link
Member Author

This has been tested with the new pytest suite.

@mergify mergify bot added the needs: work label Jul 28, 2020
@ciarmcom ciarmcom added the release-type: patch Indentifies a PR as containing just a patch label Jul 28, 2020
@ciarmcom
Copy link
Member

@paul-szczepanek-arm, thank you for your changes.
@donatieng @LDong-Arm @ARMmbed/mbed-os-maintainers please review.

@ciarmcom ciarmcom requested review from donatieng, LDong-Arm and a team July 28, 2020 19:00
@mergify mergify bot removed the needs: review label Jul 29, 2020
Copy link
Contributor

@LDong-Arm LDong-Arm left a comment

Choose a reason for hiding this comment

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

Thanks @paul-szczepanek-arm, the structure looks good to me. Please see my comment regarding the inclusion of TARGET_CORDIO headers in generic code.

Comment on lines 49 to 53

class PalGenericAccessService;
class PalSecurityManager;
class PalGap;
class BLEInstanceBase;
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we include their headers instead? Same for other class <CLASS_NAME>; in other files.

Copy link
Member Author

Choose a reason for hiding this comment

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

can't, cyclic dependency

} // ble

using ble::impl::SecurityManager;
Copy link
Contributor

Choose a reason for hiding this comment

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

For compatibility we should add Gap, SecurityManager, etc. back to the global namespace (with using for example). Our examples and cliapp should continue to compile.

Copy link
Member Author

Choose a reason for hiding this comment

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

I thought Gap and the rest are supposed to be in ble:: namespace, looking at the old files I don't see a using ble::Gap

Examples don't compile because they were incorrectly failing to include headers and relying on the happy coincidence of other headers including what they needed, I have made the fixes but not pushed to master yet

Copy link
Member Author

Choose a reason for hiding this comment

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

I added it as a config option

} // namespace ble


#if (BLE_PAL_API_IMPLEMENTATION == 1)
#include "ble/internal/PalGapImpl.h"
Copy link
Contributor

@LDong-Arm LDong-Arm Jul 31, 2020

Choose a reason for hiding this comment

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

This file is in TARGET_CORDIO - we'd better not include it here.
How to achieve that? In non-Cordio code, just use ble::interface::PalGap where possible, and this is the point of virtual functions/interface classes. It's only a few lines' change and it worked as far as I tried.
Same for the other virtual Pal classes.

Once the generic code has no dependency on headers in TARGET_CORDIO, the headers/classes in TARGET_CORDIO can be renamed to contain "Cordio" in my opinion.

Copy link
Member Author

Choose a reason for hiding this comment

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

The point is to remove virtual calls. Alternative implementation can override this include with their implementation.

@paul-szczepanek-arm
Copy link
Member Author

@0xc0170 How do I make exceptions for astyle? this is thirdparty code that is tripping the astyle tests.

@LDong-Arm
Copy link
Contributor

@0xc0170 How do I make exceptions for astyle? this is thirdparty code that is tripping the astyle tests.

Use .astyleignore located at the root of mbed-os.

@mergify
Copy link

mergify bot commented Aug 4, 2020

This PR cannot be merged due to conflicts. Please rebase to resolve them.

@paul-szczepanek-arm
Copy link
Member Author

Thank Lingkai, anything else I should look at?

Copy link
Contributor

@LDong-Arm LDong-Arm left a comment

Choose a reason for hiding this comment

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

The structure looks very good to me. I didn't and couldn't review every single line of diff given how big it is. But since the PR mostly cuts and pastes code around, we can assume nothing is missing as ble-tests and examples continue to work (otherwise things probably wouldn't even compile...).

@@ -1,9 +1,9 @@
^BUILD
^cmsis
^connectivity/FEATURE_BLE
Copy link
Contributor

Choose a reason for hiding this comment

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

Not related to this PR - no need to fix it here:
We'd better only ignore external components (e.g. Cordio) while keeping checks on our code. If any styles don't match, the CI generates a diff we can apply without manual fixes.

Copy link
Member Author

Choose a reason for hiding this comment

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

the old check was for features/FEATURE_BLE so I figured I'd better move it as is since I don't want to get bogged down with astyle right now, we can fix this in a later PR

Comment on lines 1456 to 1460
#if (BLE_API_IMPLEMENTATION == 1)
#include "ble/internal/GapImpl.h"
#else
#error "please provide alternate BLE implementation"
#endif
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
#if (BLE_API_IMPLEMENTATION == 1)
#include "ble/internal/GapImpl.h"
#else
#error "please provide alternate BLE implementation"
#endif
#include "ble/internal/GapImpl.h"

As discussed offline, this include is okay. I guess the standardised header name can be considered part of the "porting interface", and I've seen a few other projects doing this too.

Actually the BLE_API_IMPLEMENTATION macro may not be needed. If a user doesn't want Cordio, they can simply undeclare Cordio from the Mbed config so TARGET_CORDIO isn't built, and provide their implementation with the same "ble/internal/GapImpl.h" file path.

Copy link
Member Author

Choose a reason for hiding this comment

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

yes, totally agreed, this was only to show the porting point but this can be made better in a readme somewhere

Comment on lines 5 to 14
"ble-api-implementation": {
"help": "What BLE user API implementation is used. Available options: 1 (Mbed). You may add more. See headers in include/ble/.",
"value": 1,
"macro_name": "BLE_API_IMPLEMENTATION"
},
"ble-pal-api-implementation": {
"help": "What Pal API implementation is used. Available options: 1 (Cordio). You may add more. See headers in include/ble/internal/Pal*.",
"value": 1,
"macro_name": "BLE_PAL_API_IMPLEMENTATION"
},
Copy link
Contributor

Choose a reason for hiding this comment

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

See my comment above. If impl header names are standardised, we can always assume they exist.
The TARGET_CORDIO magic name already does the switch to use Cordio (i.e. default) impl or not.

Copy link
Member Author

Choose a reason for hiding this comment

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

yep, let me remove that

Copy link
Contributor

@LDong-Arm LDong-Arm left a comment

Choose a reason for hiding this comment

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

@paul-szczepanek-arm Nitpicking over the public headers mostly. I'll approve this once these are resolved.

Comment on lines 35 to 40

/*! Maximum count of characteristics that can be stored for authorisation purposes */
#define MAX_CHARACTERISTIC_AUTHORIZATION_CNT 20

/*! client characteristic configuration descriptors settings */
#define MAX_CCCD_CNT 20
Copy link
Contributor

Choose a reason for hiding this comment

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

Duplicated from the Impl header which is a better place for those?

Suggested change
/*! Maximum count of characteristics that can be stored for authorisation purposes */
#define MAX_CHARACTERISTIC_AUTHORIZATION_CNT 20
/*! client characteristic configuration descriptors settings */
#define MAX_CCCD_CNT 20

Copy link
Member Author

Choose a reason for hiding this comment

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

they should not exist as defines at all, they should be a config - added

Comment on lines 649 to 646
Gap::PreferredConnectionParams_t getPreferredConnectionParams();

/**
* The registered callback handler for confirmation received events.
* Set preferred connection parameters.
*
* @param[in] params Preferred connection parameter values to set.
*/
EventCallback_t confirmationReceivedCallback;

private:
/* Disallow copy and assignment. */
GattServer(const GattServer &);
GattServer& operator=(const GattServer &);
void setPreferredConnectionParams(const Gap::PreferredConnectionParams_t& params);
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for adding them back - I removed them from the public API a few months (thought they were deprecated but were actually missing...), please mention them in the PR description as a new feature.

Comment on lines 924 to 932
/** For backwards compatibility. This enm is now in BLETypes.h
* @deprecated, use the enum in ble namespace */
enum Keypress_t {
KEYPRESS_STARTED, /**< Passkey entry started */
KEYPRESS_ENTERED, /**< Passkey digit entered */
KEYPRESS_ERASED, /**< Passkey digit erased */
KEYPRESS_CLEARED, /**< Passkey cleared */
KEYPRESS_COMPLETED, /**< Passkey entry completed */
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/** For backwards compatibility. This enm is now in BLETypes.h
* @deprecated, use the enum in ble namespace */
enum Keypress_t {
KEYPRESS_STARTED, /**< Passkey entry started */
KEYPRESS_ENTERED, /**< Passkey digit entered */
KEYPRESS_ERASED, /**< Passkey digit erased */
KEYPRESS_CLEARED, /**< Passkey cleared */
KEYPRESS_COMPLETED, /**< Passkey entry completed */
};
/** For backwards compatibility. This enum is now in BLETypes.h
* @deprecated, use the enum in ble namespace */
using using ble::Keypress_t;

Copy link
Member Author

Choose a reason for hiding this comment

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

I assume you meant a typedef

Copy link
Contributor

@LDong-Arm LDong-Arm left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for it! @paul-szczepanek-arm

@adbridge Could you please trigger a CI run? Thanks.
I'll also try a few things locally tomorrow, though this kind of refactoring (moving files and classes around) should be low risk, as long as things compile.

@adbridge
Copy link
Contributor

adbridge commented Aug 6, 2020

CI started

@mbed-ci
Copy link

mbed-ci commented Aug 6, 2020

Jenkins CI Test : ❌ FAILED

Build Number: 1 | 🔒 Jenkins CI Job | 🌐 Logs & Artifacts

CLICK for Detailed Summary

jobs Status
jenkins-ci/mbed-os-ci_unittests ✔️
jenkins-ci/mbed-os-ci_build-GCC_ARM
jenkins-ci/mbed-os-ci_build-ARM

@adbridge
Copy link
Contributor

adbridge commented Aug 6, 2020

@paul-szczepanek-arm looks like the failures are BLE related. For one of the failing boards I see:

[Error] pretty_printer.h@84,26: member access into incomplete type 'ble::Gap'
[Error] main.cpp@30,25: incomplete type 'ble::Gap' named in nested name specifier
[Error] main.cpp@30,30: expected class name
[Error] main.cpp@208,45: no type named 'DisconnectionCompleteEvent' in namespace 'ble'
[Error] main.cpp@217,10: no type named 'AdvertisingDataBuilder' in namespace 'ble'
[Error] main.cpp@38,19: member access into incomplete type 'ble::Gap'
[Error] main.cpp@147,35: expected ';' after expression
[Error] main.cpp@147,14: no member named 'AdvertisingParameters' in namespace 'ble'
[Error] main.cpp@147,36: use of undeclared identifier 'adv_parameters'
[Error] main.cpp@175,39: member access into incomplete type 'ble::Gap'
[Error] main.cpp@185,27: member access into incomplete type 'ble::Gap'
[Error] main.cpp@197,27: member access into incomplete type 'ble::Gap'
[Error] main.cpp@209,19: member access into incomplete type 'ble::Gap'
[ERROR] In file included from ./source/main.cpp:20:

Copy link
Contributor

@LDong-Arm LDong-Arm left a comment

Choose a reason for hiding this comment

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

Still looking into it...

@@ -21,7 +21,6 @@
#if (DEVICE_SERIAL && DEVICE_SERIAL_FC) || defined(DOXYGEN_ONLY)

#include <stdint.h>
#include "mbed.h"
Copy link
Contributor

@LDong-Arm LDong-Arm Aug 6, 2020

Choose a reason for hiding this comment

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

This is one of several causes of the CI failures.
Because this is removed, you need to

  • Include a number of headers (e.g. "drivers/InterruptIn.h")
  • Use the qualified class names (e.g. mbed::InterruptIn) instead of short one (e.g. InterruptIn), because mbed.h which we removed has a using namespace mbed.

Please keep fixing errors until

mbed test -t <TOOLCHAIN> -m CY8CKIT_062S2_43012 --compile

succeeds.

@LDong-Arm
Copy link
Contributor

LDong-Arm commented Aug 6, 2020

@paul-szczepanek-arm
Okay, there are a few things we need to resolve:

  • Missing includes and namespaced class names in COMPONENT_CYW43XXX - my see inline comments above.
  • Create an mbed_lib.json for each of COMPONENT_CYW43XXX, TARGET_CY8C63XX and TARGET_STM32WB. If we don't do this, bare metal applications will fail to compile, because "ble" isn't listed in "requires" and isn't built, but our build system will still try to build connectivity/drivers/ble/TARGET_xxx whose mbed_lib.json are missing... See this.
  • The BLE_GattServer example includes the old path #include "ble/FunctionPointerWithContext.h" - we should either update that example (just remove that line - "BLE.h" provides that already), or just move the header out of internal. Why is that in internal but CallChainOfFunctionPointersWithContext.h isn't?
  • Some examples expect BLE.h to bring in classes (e.g. Gap) without having to include one header per API (e.g. Gap.h), but it's not the case anymore in this PR. In my opinion, the expectation is reasonable - those classes are core features of BLE. (See Note below.)
  • The error log @adbridge posted means headers have dependency issues. We should reduce/simplify interdependencies a bit. (See Note below.)

Note:
To solve the last two points, I personally propose this change which includes API headers (e.g. Gap.h) into BLE.h rather than forward-declaring them, and also reduces interdependencies a bit. Please have a look and discuss.

Copy link
Contributor

@LDong-Arm LDong-Arm left a comment

Choose a reason for hiding this comment

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

Trying to dismiss the previous review

@mbed-ci
Copy link

mbed-ci commented Aug 7, 2020

Jenkins CI Test : ❌ FAILED

Build Number: 2 | 🔒 Jenkins CI Job | 🌐 Logs & Artifacts

CLICK for Detailed Summary

jobs Status
jenkins-ci/mbed-os-ci_unittests ✔️
jenkins-ci/mbed-os-ci_build-ARM
jenkins-ci/mbed-os-ci_build-GCC_ARM

@mbed-ci
Copy link

mbed-ci commented Aug 7, 2020

Jenkins CI Test : ❌ FAILED

Build Number: 3 | 🔒 Jenkins CI Job | 🌐 Logs & Artifacts

CLICK for Detailed Summary

jobs Status
jenkins-ci/mbed-os-ci_unittests ✔️
jenkins-ci/mbed-os-ci_build-ARM
jenkins-ci/mbed-os-ci_build-GCC_ARM

Copy link
Contributor

@LDong-Arm LDong-Arm left a comment

Choose a reason for hiding this comment

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

LGTM. @adbridge Could you please trigger CI again? Hopefully it'll pass this time, thanks!

@adbridge
Copy link
Contributor

adbridge commented Aug 7, 2020

CI started

@@ -111,7 +109,16 @@ class GattClient : public StaticInterface<Impl, GattClient> {
virtual void onAttMtuChange(
ble::connection_handle_t connectionHandle,
uint16_t attMtuSize
)
) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Formatting is incorrect here, for functions opening { go on their own line

@@ -117,22 +114,20 @@ class GattServer {
virtual void onAttMtuChange(
ble::connection_handle_t connectionHandle,
uint16_t attMtuSize
)
) {
Copy link
Contributor

Choose a reason for hiding this comment

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

incorrect formatting

namespace interface {
#endif // !defined(DOXYGEN_ONLY)
class SecurityManager
{
Copy link
Contributor

Choose a reason for hiding this comment

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

formatting

@@ -339,7 +325,7 @@ class SecurityManager {
* @param[in] connectionHandle connection connectionHandle
* @param[in] passkey 6 digit passkey to be displayed
*/
virtual void passkeyDisplay(ble::connection_handle_t connectionHandle, const SecurityManager::Passkey_t passkey) {
virtual void passkeyDisplay(ble::connection_handle_t connectionHandle, const Passkey_t passkey) {
Copy link
Contributor

Choose a reason for hiding this comment

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

formatting

@@ -373,7 +359,7 @@ class SecurityManager {
* @param[in] connectionHandle connection connectionHandle
* @param[in] keypress type of keypress event
*/
virtual void keypressNotification(ble::connection_handle_t connectionHandle, SecurityManager::Keypress_t keypress) {
virtual void keypressNotification(ble::connection_handle_t connectionHandle, ble::Keypress_t keypress) {
Copy link
Contributor

Choose a reason for hiding this comment

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

formatting

*
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
*/
ble_error_t setPrivateAddressTimeout(
Copy link
Contributor

Choose a reason for hiding this comment

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

why is this on multiple lines ?

/**
* @see ble::PalGattClient::when_server_message_received
*/
void when_server_message_received(
Copy link
Contributor

Choose a reason for hiding this comment

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

formatting

/**
* @see ble::PalGattClient::when_transaction_timeout
*/
void when_transaction_timeout(
Copy link
Contributor

Choose a reason for hiding this comment

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

formatting, others below here too

ble_error_t PalGattClient::get_mtu_size(
connection_handle_t connection_handle,
uint16_t& mtu_size
) {
Copy link
Contributor

Choose a reason for hiding this comment

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

formatting


ble_error_t PalGenericAccessService::get_peripheral_preferred_connection_parameters(
ble::Gap::PreferredConnectionParams_t& parameters
) {
Copy link
Contributor

Choose a reason for hiding this comment

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

formatting

@LDong-Arm
Copy link
Contributor

LDong-Arm commented Aug 7, 2020

We've always had the entire FEATURE_BLE in .astyleignore, even though much of it is our own code. If we do want to get formatting right in this PR, we should edit .astyleignore and run astyle on code owned by us.
What do you think? @adbridge @paul-szczepanek-arm

@mergify mergify bot dismissed adbridge’s stale review August 7, 2020 15:22

Pull request has been modified.

@@ -1,9 +1,10 @@
^BUILD
^cmsis
^connectivity/drivers/ble
^connectivity/FEATURE_BLE
Copy link
Contributor

@LDong-Arm LDong-Arm Aug 7, 2020

Choose a reason for hiding this comment

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

Suggested change
^connectivity/FEATURE_BLE
^connectivity/FEATURE_BLE/libraries/TARGET_CORDIO/stack
^connectivity/FEATURE_BLE/libraries/TARGET_CORDIO_LL/stack

This is what I mean - external code only. See my discussion with Paul earlier. @adbridge

Copy link
Contributor

Choose a reason for hiding this comment

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

Or can we do another PR to fix this, since this one is already pretty big?

@adbridge
Copy link
Contributor

adbridge commented Aug 7, 2020

If it's our code then we shouldn't be ignoring astyle....

@adbridge
Copy link
Contributor

adbridge commented Aug 7, 2020

Ci started

@mbed-ci
Copy link

mbed-ci commented Aug 7, 2020

Jenkins CI Test : ✔️ SUCCESS

Build Number: 4 | 🔒 Jenkins CI Job | 🌐 Logs & Artifacts

CLICK for Detailed Summary

jobs Status
jenkins-ci/mbed-os-ci_unittests ✔️
jenkins-ci/mbed-os-ci_build-ARM ✔️
jenkins-ci/mbed-os-ci_build-GCC_ARM ✔️
jenkins-ci/mbed-os-ci_dynamic-memory-usage ✔️
jenkins-ci/mbed-os-ci_cloud-client-pytest ✔️
jenkins-ci/mbed-os-ci_greentea-test ✔️

@mbed-ci
Copy link

mbed-ci commented Aug 7, 2020

Jenkins CI Test : ✔️ SUCCESS

Build Number: 5 | 🔒 Jenkins CI Job | 🌐 Logs & Artifacts

CLICK for Detailed Summary

jobs Status
jenkins-ci/mbed-os-ci_unittests ✔️
jenkins-ci/mbed-os-ci_build-ARM ✔️
jenkins-ci/mbed-os-ci_build-GCC_ARM ✔️
jenkins-ci/mbed-os-ci_dynamic-memory-usage ✔️
jenkins-ci/mbed-os-ci_greentea-test ✔️
jenkins-ci/mbed-os-ci_cloud-client-pytest ✔️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants