-
Notifications
You must be signed in to change notification settings - Fork 7.3k
Bluetooth: HCI: Use H:4 encoding for buffers #88710
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?
Conversation
This implements the first item in #88048, which was originally discussed at the recent Bluetooth WG F2F meeting. |
One positive realization I had when I worked on this change, is that actually most of our HCI drivers already internally used the H:4 encoding. This is the primary reason why the PR ends up removing about 300 lines of code. |
I get that this allows us to be partially backwards compatible, but the name of these functions is misleading now. I think the value of keeping them backwards compatible is worth more than a better name, but there may be a way so the function can be invoked multiple times: Doesn't the H4 type always land in the space |
include/zephyr/bluetooth/buf.h
Outdated
@@ -29,26 +30,19 @@ extern "C" { | |||
#endif | |||
|
|||
/** Possible types of buffers passed around the Bluetooth stack in a form of bitmask. */ | |||
enum bt_buf_type { | |||
enum __packed bt_buf_type { |
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 did not know we had packed enums. That's cool. We could potentially use these in hci_types.h
instead of plain uint8_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.
I did not know we had packed enums. That's cool. We could potentially use these in
hci_types.h
instead of plainuint8_t
.
Sounds like a good idea.
include/zephyr/bluetooth/buf.h
Outdated
* @param timeout Non-negative waiting period to obtain a buffer or one of the | ||
* special values K_NO_WAIT and K_FOREVER. | ||
* @param data Initial data to append to buffer. | ||
* @param size Initial data size. | ||
* @return A new buffer. | ||
*/ | ||
struct net_buf *bt_buf_get_tx(enum bt_buf_type type, k_timeout_t timeout, | ||
struct net_buf *bt_buf_get_tx(uint8_t type, k_timeout_t timeout, |
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.
We need to maintain some level of type information here. Either we should rename the argument to h4_type
, or seeing as the enum is packed, we keep using the enum here. I suggest adding BUILD_ASSERT(sizeof(enum bt_buf_type) == sizeof(uint8_t))
in the latter case.
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.
We need to maintain some level of type information here. Either we should rename the argument to
h4_type
, or seeing as the enum is packed, we keep using the enum here. I suggest addingBUILD_ASSERT(sizeof(enum bt_buf_type) == sizeof(uint8_t))
in the latter case.
I think it'd be nice to try to use the enum everywhere, combined with the build assert.
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 moved from uint8_t
to enum bt_buf_type
for these APIs.
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.
Thanks! Looks good!
I have a minor fix that I nack for:
The other discussions are not hard nacking.
drivers/bluetooth/hci/hci_ambiq.c
Outdated
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.
Verified sample/bluetooth/peripheral_hr worked normally on apollo4p_blue_kxr_evb and apollo3_evb with the change.
doc/releases/migration-guide-4.2.rst
Outdated
have been deprecated, but are still usable, with the exception that the latter can only be | ||
called once per buffer. |
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.
Both of the functions have the same caveat, not just the latter.
Can we be more precise here about the caveat? I think we have to mention that these function will now silently corrupt data unless the following assumptions hold.
bt_buf_get_type(buf)
has to be called exactly once beforebuf
is accessed.bt_buf_set_type(buf)
has to be called exactly once before it's handed tobt_hci_recv_t
, with no accesses tobuf
in between.
Also, this is the migration guide, not the change log, so we need to say how to migrate away from the deprecated behavior. I.e. Verifying the above assumptions and substitute calls to bt_buf_get_type
and bt_buf_set_type
with net_buf_pull_u8
and net_buf_push_u8
.
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.
bt_buf_set_type(buf) has to be called exactly once before it's handed to bt_hci_recv_t, with no accesses to buf in between.
HCI drivers don't generally use this API at all, rather they use the various buffer allocation APIs (like bt_buf_get_rx()
) which implicitly add the type prefix to the buffer. If you grep under drivers/bluetooth
you wont find a single user of it.
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.
Both of the functions have the same caveat, not just the latter.
Fixed.
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.
@alwa-nordic I did some more thinking about this, and I think hci_types.h
is a justifiable place for the packet type prefix byte. I initially felt against this, since it's different from the rest of the HCI payload, which the drivers will just proxy unmodified back-and-forth, whereas the type is something that needs to be separately handled if the underlying transport doesn't use this format. However, while I made the claim that drivers/bluetooth.h
should be the only interface that drivers should look at, I failed to consider the fact that most drivers either way have to be aware of the packet type-specific header, in order to determine the packet length, and the type-specific header (event, ACL data, etc) is part of hci_types.h
. Drivers currently also need to peek at the event definitions to make the "discardable" vs "not discardable" distinction.
So, I'll take another stab at keeping buf.h
(i.e. enum bt_buf_type
) backwards compatible. I'm still not quite comfortable with keeping "H4" in the other enumeration name, since "H:4" really is about an entire transport and not just about packet types. I'd rather just strictly document that the values defined based on those values from the transport spec. We don't even have to document it just in reference to H:4, but can say that "the possible values are are commands (1), ACL (2), SCO (3), events (4) and ISO (5) as specified in the UART and 3-Wire UART transport specs" (and extend the reference list to other transports if/when they show up in future specs with the same mapping from value to packet type). So while the documentation makes these references, I think I'd still prefer to keep the enum name generic, i.e. enum bt_hci_pkt_type
, however that could be done as a follow-up step and just use our existing H4 defines from hci_types.h
for now.
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've pushed these changes now. Doesn't look that bad, however there's some inefficiency introduced with the conversions. In some case we even have to do the conversion twice, such as for some bt_hci_raw users like the hci_uart app: For data coming from the host the app first has to convert to enum bt_buf_type
to be able to call bt_buf_get_tx()
, which in turn internally has convert back to H:4 to be able to prepend the right byte.
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.
And I've now pushed a rebased & squashed patch set. I had to simplify some parts in the commit split, since it wasn't (trivially) possible to include all changes cleanly to the original commit set (I basically recreated all commits as far as it made sense).
e2b87df
to
5484227
Compare
@andrzej-kaczmarek @sylvioalves @npal-cy @yeaissa @HoZHel @asm5878 @dchat-nordic: Could you please take a look at the HCI driver testing checklist in this PR description, and mark each driver as tested once you (or someone else with the respective HW) have tested it with this PR? Thanks! |
ca64efb
to
d105150
Compare
I checked on NXP platform using hci_nxp.c, no regression noticed. Thanks for the change @jhedberg. |
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.
@jhedberg have you seen any significant changes in memory usage with this PR?
include/zephyr/bluetooth/buf.h
Outdated
/** Direction of HCI packets */ | ||
enum bt_buf_dir { | ||
BT_BUF_IN, | ||
BT_BUF_OUT, |
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 the point of view of the host?
We could consider making the directions absolute rather than relative like we have for ISO data paths:
#define BT_HCI_DATAPATH_DIR_HOST_TO_CTLR 0x00
#define BT_HCI_DATAPATH_DIR_CTLR_TO_HOST 0x01
The same argument can be applied for the ACL and ISO IN/OUT, but if we modify one, we should probably modify all, which seems outside the scope of this PR
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 the point of view of the host?
From the point of view of BT_BUF_*_IN/OUT
values when converting from a H:4 type (which don't convey any direction info by themselves).
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 added a clarifying sentence to the docstring above the enum definition.
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.
Also worth noting that this entire public header will hopefully disappear soon, so I wouldn't put too much effort into trying to micro-optimize it :)
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.
Pull Request Overview
This PR revises the HCI packet type encoding by moving the H:4 type byte from net_buf metadata into the net_buf payload. It deprecates the bt_buf_get/set_type() APIs and removes the experimental H:4 USB transport support.
- Remove H:4 mode enums, APIs, and raw-mode functions from hci_raw.h
- Update buffer API functions in buf.h to use H:4 prefix encoding
- Modify multiple HCI transport drivers to directly use the payload’s first byte for packet type
Reviewed Changes
Copilot reviewed 52 out of 53 changed files in this pull request and generated no comments.
File | Description |
---|---|
include/zephyr/bluetooth/hci_raw.h | Removed legacy H:4 mode definitions and raw-channel APIs |
include/zephyr/bluetooth/buf.h | Updated buffer type conversion functions and deprecation of old APIs |
drivers/bluetooth/hci/* | Replaced bt_buf_get/set_type() invocations with direct payload access |
drivers/bluetooth/hci/h4.c | Removed redundant type handling before UART transmission |
Files not reviewed (1)
- doc/releases/migration-guide-4.2.rst: Language not supported
I haven't done any profiling, but I'd expect to see at least a decrease in code size (if you just look at the diffstat). On aggregate it's a big reduction in code, however it'll be spread out over many platforms (a little for each HCI driver) so any single build wont show the same magnitude as the PR as a whole. |
Encode the packet type as a H:4 payload prefix for buffers passing to & from HCI drivers. The existing bt_buf_set/get_type functions are deprecated, but kept compatible with the change, except that they can only be called once, since they modify the buffer payload. Signed-off-by: Johan Hedberg <[email protected]>
Update all HCI drivers to use the new H:4 encoding for buffers passing to/from drivers. One behavioral change that's done in favor of simplicity, is that where there's previously been switch statements that could return an error for unsupported packet types now simply pass any received packet unchanged to lower layers of the controller (or the HCI transport). Handling this is now the responsibility of the lower layers, however in practice hitting such scenarios means that there's a mismatch between configured host and controller features. Signed-off-by: Johan Hedberg <[email protected]>
Update the Bluetooth tests to assume the new H:4 encoding for data that's passing between HCI drivers and their users (normally the host stack). Signed-off-by: Johan Hedberg <[email protected]>
This non-standard feature never had any proper host side implementation (e.g. it was never upstreamed to BlueZ), and since it comes with notable maintenance overhead it's fair to just remove it. Signed-off-by: Johan Hedberg <[email protected]>
Mention the changes that have happened to the Bluetooth HCI driver interface regarding packet type encoding. Signed-off-by: Johan Hedberg <[email protected]>
The documentation for the HCI raw interface was incorrectly talking about the need to define buffer pools, when in fact the hci_raw module provides the necessary API to perform buffer allocation. Signed-off-by: Johan Hedberg <[email protected]>
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 am quite happy with how this looks now. I found a small mistake:
This PR changes the encoding of HCI packet types from net_buf metadata into the net_buf payload as a H:4 prefix byte. The
bt_buf_get/set_type()
APIs are deprecated but kept compatible with the change (i.e. they donet_buf_pull/push_u8()
internally).The PR also removes the experimental H:4 encoding support from the USB transport for several reasons:
Testing status for the drivers. Please check the box once you've tested your respective driver with this PR:
h4.c
@jhedberg /upstream CIh5.c
@jhedberg /upstream CIhci_ambiq.c
@aaronyegxhci_da1469x.c
@andrzej-kaczmarekhci_esp32.c
@sylvioalveshci_ifx_cyw208xx.c
@npal-cyhci_ifx_psoc6_bless.c
@npal-cyhci_nxp.c
@yeaissahci_silabs_siwx917.c
@jhedberghci_silabs_efr32.c
@jhedberghci_spi_st.c
@HoZHelhci_stm32wb0.c
@HoZHelhci_stm32wba.c
@asm5878ipc.c
@dchat-nordic (probably tested by upstream CI?)ipm_stm32wb.c
@asm5878spi.c
@HoZHeluserchan.c
@jhedberg /@aescolar