Skip to content
This repository has been archived by the owner on May 18, 2022. It is now read-only.

Basic writeable connection attributes + attribute permissions #171

Merged

Conversation

noloerino
Copy link
Contributor

This PR adds basic support for the GATT WriteReq (write w/ response) and WriteCommand (write w/o response) commands, permissions on attributes, and a demo that exposes a writeable attribute that toggles an LED. See also #146.

I tested the demo on a NRF52832DK board, and it seems to work as expected. No rush for reviewing this by the way; I don't need this feature any time soon, I just happened to have some spare time over the holidays.

Notes:

  • This implementation lazily creates the attribute responsible for storing writeable data; it should also be possible to store an owned Attribute directly, but may be a little bit inelegant because of possibly differing sizes of the underlying byte buffer.
  • Because the group_end function of AttributeProvider needs to return Option<&Attribute>, we can't directly return a lazily-generated attribute. The demo circumvents this by adding a static dummy attribute to end the characteristic and service groups.
  • I replaced the AttrValue trait defined in Use a trait for representing attribute values #166 with AsRef<[u8]> because it became impossible for an Attribute to own its underlying data because the trait cannot be implemented for [u8; N]. I think this can be circumvented by passing a slice to a lazily produced Attribute. If anyone feels strongly enough about leaving the AttrValue trait in, then I can try to work around it.

The following related features are not yet implemented:

  • Signed writes (SignedWriteCommand)
  • Queued writes (PrepareWriteReq and ExecuteWriteReq; these would require some means of storing queued data that would take a little more design thinking)
  • Callbacks on write_attribute for added flexibility (see Writeable attributes & attribute permissions #146)
  • Returning an error if a ReadReq is made on an attribute that does not have readable permission (see comment in diff)

@@ -197,10 +203,17 @@ impl<A: AttributeProvider> AttributeServer<A> {
self.attrs.for_attrs_in_range(
HandleRange::new(*handle, *handle),
|_provider, attr| {
let value = if writer.space_left() < attr.value.as_slice().len() {
&attr.value.as_slice()[..writer.space_left()]
// FIXME return if attribute is not readable
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This callback can't return the proper error type with the current API design due (see comment).

@jonas-schievink
Copy link
Owner

This looks pretty good so far, thanks!

One think I'd like to see is to get the new demo merged into the old one. That way there's less code to deal with, and it should be fine to have both writeable and readable attributes in that demo.

@noloerino
Copy link
Contributor Author

Sure thing. Should I include both the LED and the battery service attributes?

@jonas-schievink
Copy link
Owner

Yeah that should be fine

demos/nrf52-demo/src/attrs.rs Outdated Show resolved Hide resolved
AttPdu::WriteCommand { handle, value } => {
// WriteCommand shouldn't respond to the client even on failure
if self.attrs.attr_access_permissions(*handle).is_writeable() {
self.attrs.write_attr(*handle, value.as_ref()).unwrap();
Copy link
Owner

Choose a reason for hiding this comment

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

I think crashing is not the right course of action here. Can you instead log any error via log::error! and continue?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed, and did the same for handling write requests as well. I noticed that in the original code, errors in handling ReadReq and ExchangeMtuReq are also unwrapped - should I change that as well while I'm at it?

Copy link
Owner

Choose a reason for hiding this comment

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

Not necessary for this PR, but feel free to file a followup PR if you want. I'll go ahead and merge this now, thanks!

demos/nrf52-demo/Cargo.toml Outdated Show resolved Hide resolved
@jonas-schievink jonas-schievink merged commit a2a8c94 into jonas-schievink:master Jan 11, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants