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

Implement (G)ATT on top of L2CAP #29

Open
jonas-schievink opened this issue Mar 31, 2019 · 6 comments · Fixed by #45
Open

Implement (G)ATT on top of L2CAP #29

jonas-schievink opened this issue Mar 31, 2019 · 6 comments · Fixed by #45
Labels
area: (G)ATT Code Area: Attribute Protocol or the Generic Attribute Profile built on top of ATT help wanted Call for participation: Help is requested to fix this issue status: needs code An implementation or a bugfix need to be written status: needs design Needs design work (API, communication between components, etc.) type: enhancement A new feature or an improvement for an existing one

Comments

@jonas-schievink
Copy link
Owner

jonas-schievink commented Mar 31, 2019

GATT is not it's own protocol, but means Generic Attribute Profile (even though the spec sometimes calls it Generic Attribute Protocol - I'm not making this shit up!). We have to implement whatever parts of ATT are needed by GATT.

@jonas-schievink jonas-schievink added this to the Oxidize milestone Mar 31, 2019
@jonas-schievink jonas-schievink added type: enhancement A new feature or an improvement for an existing one status: needs design Needs design work (API, communication between components, etc.) status: needs code An implementation or a bugfix need to be written area: (G)ATT Code Area: Attribute Protocol or the Generic Attribute Profile built on top of ATT labels Apr 1, 2019
@jonas-schievink jonas-schievink changed the title Implement the attribute protocol (ATT) on top of L2CAP Implement enough of (G)ATT on top of L2CAP Apr 1, 2019
@jonas-schievink
Copy link
Owner Author

A hard-coded primary service is now enumerated correctly. Next steps:

  • ATT needs to call into GATT to figure some things out because BLE is a giant protocol layering violation
  • An interface for exposing and defining Services and Characteristics needs to be created. Currently we just operate off of a slice of raw attributes. We need a better interfacing trait and possibly proc macros to make this simpler.
  • Figure out how to do notification/indication of changed attribute values

@jonas-schievink jonas-schievink removed this from the Oxidize milestone Apr 26, 2019
@jonas-schievink
Copy link
Owner Author

Removing milestone since service enumeration with one hard-coded service now works.

@jonas-schievink jonas-schievink added the help wanted Call for participation: Help is requested to fix this issue label Jun 12, 2019
@jonas-schievink jonas-schievink changed the title Implement enough of (G)ATT on top of L2CAP Implement (G)ATT on top of L2CAP Jun 13, 2019
@fmckeogh
Copy link
Collaborator

I've been using NimBLE for a few days, and think implementing a similar pattern for notifications would be a good idea, I'm going to start work on this over the next couple days and see where I get.

NimBLE ble_gap.h

NimBLE ble_gatt.h

@tl8roy
Copy link

tl8roy commented May 3, 2020

As promised may moons ago, here is an example layout that I think will work (hopefully this job is still relevant). I am not 100% certain of the actual parameters required, nor how they fit into the existing code. Hopefully you can make adjustments as required.

It also doesn't take into account Server vs Client, but I think Client is a subset of the traits and probably not much different.

struct Profile {}

trait GATTProfile {
    fn get_uuid() -> UUID;
    fn set_uuid(uuid: UUID);
    fn get_profile_type() -> ProfileType;
    fn get_profile_type(profie_type: ProfileType);
    fn add_services(attr: GATTService);
    fn get_services(uuid: UUID) -> & GATTService;
    fn get_services(service_type: Option<ServiceType>) -> Vec<& GATTService>;
}

#[GATTService("UUID","ServiceType")]
struct Service {}

trait GATTService {
    fn get_uuid() -> UUID;
    fn set_uuid(uuid: UUID);
    fn get_service_type() -> ServiceType;
    fn get_service_type(profie_type: ServiceType);
    fn add_characteristic(attr: GATTCharacteristic);
    fn get_characteristic(uuid: UUID) -> & GATTCharacteristic;
    fn get_characteristic() -> Vec<& GATTCharacteristic>;
}

#[GATTCharacteristic("UUID","Descriptor")]
struct Characteristic {
    value: [u8]
}

trait GATTCharacteristic {
    fn get_uuid() -> UUID;
    fn set_uuid(uuid: UUID);
    fn get_descriptor() -> String;
    fn set_descriptor(descriptor: String);
    fn get_value() -> [u8];
    fn set_value(value: [u8]);   
    fn notify(func: Option<FnOnce(value: [u8])>); 
    fn indicate(func: Option<FnOnce(value: [u8])>); 
}```

I can't say that I can help with the implementation, but I am happy to review any decisions.

@jonas-schievink
Copy link
Owner Author

@tl8roy Sorry, I'm not entirely sure what to make of that – we can't allocate memory, for example, and if the attributes are supposed to auto-implement the traits then they would need quite a bit more info to do so. For example the service needs to know all characteristics that are present at compile time to avoid allocations, but macros cannot access implemented traits or any values really.

The reason why I arrived at the approach described in #72 is that I don't think it will be very easy (if at all possible) to make procedural macros do the job in all cases here.

@tl8roy
Copy link

tl8roy commented May 3, 2020

Your completely correct. I should have reread everything before posting. Let me have a think and see if I can abuse macros/types some more.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: (G)ATT Code Area: Attribute Protocol or the Generic Attribute Profile built on top of ATT help wanted Call for participation: Help is requested to fix this issue status: needs code An implementation or a bugfix need to be written status: needs design Needs design work (API, communication between components, etc.) type: enhancement A new feature or an improvement for an existing one
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants