Skip to content

Commit

Permalink
Service Builder: Descriptor discovery working
Browse files Browse the repository at this point in the history
Aggregate work:

* Add free_lists to service_builder

* Loosen up ble::gatt:attrbute types to deal with discovered properties.
  * gatt::characteristic, gatt::descriptor, gatt::service
    all get default ctors and are no longer const only
    data members. This way their uuids, types and associations
    can be changed as services are discovered.

    Add attribute_type::undefined for creating objects
    which do not yet know their attribute type.

* Add service_container::find_service_handle_assoc()

* Issue #21: overloaded non-const member functions should call const members

* Add service_builder::discovery_iterator

* nordic_ble_gattc_operations.cc
  add debug log messages to each call

* Add external directory for 3rd party source and libraries.
  Has its own Makefile
  Executes download of Nordic SDK, googletest.
  Unzips/de-archive the compressed file format.
  For Nordic's SDK, execute nordic/sdk-modifiled/replace_sdk_files.

* Implement unit tests within googletest
  Issue #6

* Add unit tests for service and characteristics classes
  Issue #5

* Add version info for BLE central, peripheral
  Version information consists of a version
  string built from a git tag (TBD) and the
  4 left-hand bytes of the git sha1 (implemented).
  The version info struct is located at the top
  of FLASH in the section .version_info.

* Device Information Service (DIS)
  Updated. Uses Nordic NRF_FICR->DEVICEADDR
  to create a unique 8-byte serial number.

* Segger RTT buffer allocations provided by application

  Issue #30
  Previously #define nonsense inside the header
  segger/segger_rtt_conf.h

  Now the application allocates the buffer and passes
  it in to the Segger RTT module.

* Change namespace write_data -> io
* Add io::output_stream* logger::get_output_stream()

* Move discovery_iterator into service_container

* Fix broken unit tests test_vwritef, test_write_data
  • Loading branch information
natersoz committed Mar 17, 2019
1 parent 33e97eb commit cee3cef
Show file tree
Hide file tree
Showing 131 changed files with 9,287 additions and 8,179 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
_build
.segger_sn
external/downloads
external/nRF5_SDK_15.2.0_9412b96
external/googletest*
15 changes: 9 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,35 @@ else
MAKE_JOBS :=
endif

sub_make_files = $(shell find . -maxdepth 2 -name Makefile -not -wholename ./Makefile)
#sub_make_files += $(shell find ./nordic/tests -maxdepth 2 -name Makefile -not -wholename ./Makefile)
sub_make_files = $(shell find . -maxdepth 2 -name Makefile -not \( -wholename ./Makefile -or -wholename ./external/Makefile \))
sub_make_dirs = $(patsubst %/Makefile,%,$(sub_make_files))

.PHONY: all relink clean info
.PHONY: all relink clean mrproper info

all:
make -C external
@for make_dir in $(sub_make_dirs); do \
printf "make -C $$make_dir: $@\n"; \
make -C $$make_dir $@ $(MAKE_JOBS); \
done
make -C nordic/tests $@
make -C nordic/tests $@

relink:
@for make_dir in $(sub_make_dirs); do \
printf "make -C $$make_dir: $@\n"; \
make -C $$make_dir $@ $(MAKE_JOBS); \
done
make -C nordic/tests $@
make -C nordic/tests $@

clean:
@for make_dir in $(sub_make_dirs); do \
printf "make -C $$make_dir: $@\n"; \
make -C $$make_dir $@; \
done
make -C nordic/tests $@
make -C nordic/tests $@

mrproper:
make -C external $@

info:
@printf "sub_make_files = $(sub_make_files)\n"
Expand Down
7 changes: 7 additions & 0 deletions ble/att.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include <type_traits>
#include <cstdint>
#include <utility>

namespace ble
{
Expand Down Expand Up @@ -41,6 +42,12 @@ static constexpr uint16_t const handle_minimum = 0x0001u;
static constexpr uint16_t const handle_maximum = UINT16_MAX;
/** @} */

/**
* An BLE ATT handle range is inclusive of the first and second members within
* the pair.
*/
using handle_range = std::pair<uint16_t, uint16_t>;

/**
* @typedef ble::att::length_t
* Define an attribute lenth type similar to std::size_t but for use with BLE.
Expand Down
8 changes: 7 additions & 1 deletion ble/ble.vpj
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,12 @@
<F N="gap_connection_negotiation_state.cc"/>
<F N="gatt_attribute.cc"/>
<F N="gatt_characteristic.cc"/>
<F N="gatt_declaration.cc"/>
<F N="gatt_enum_types_strings.cc"/>
<F N="gatt_service.cc"/>
<F N="gatt_service_container.cc"/>
<F N="gatt_service_discovery_iterator.cc"/>
<F N="gatt_write_ostream.cc"/>
<F N="gattc_service_builder.cc"/>
<F N="gatts_event_observer.cc"/>
<F N="ltv_encode.cc"/>
Expand Down Expand Up @@ -336,11 +340,13 @@
<F N="gatt_characteristic.h"/>
<F N="gatt_declaration.h"/>
<F N="gatt_descriptors.h"/>
<F N="gatt_enum_types.h"/>
<F N="gatt_enum_types_strings.h"/>
<F N="gatt_format.h"/>
<F N="gatt_service.h"/>
<F N="gatt_service_container.h"/>
<F N="gatt_service_include.h"/>
<F N="gatt_uuids.h"/>
<F N="gatt_write_ostream.h"/>
<F N="gattc_discovery_observer.h"/>
<F N="gattc_event_observer.h"/>
<F N="gattc_operations.h"/>
Expand Down
12 changes: 7 additions & 5 deletions ble/gatt_attribute.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ ble::att::length_t attribute::write(ble::att::op_code write_type,
ble::att::length_t length,
void const* data)
{
(void) write_type;

uint8_t *data_dst = reinterpret_cast<uint8_t*>(this->data_pointer());
ASSERT(data_dst);

Expand All @@ -45,15 +47,15 @@ ble::att::length_t attribute::write(ble::att::op_code write_type,

data_end = std::min(data_end, data_max);

std::ptrdiff_t const length = data_end - data_dst;
if (length > 0)
std::ptrdiff_t const dest_length = data_end - data_dst;
if (dest_length > 0)
{
memcpy(data_dst, data, length);
return static_cast<att::length_t>(length);
memcpy(data_dst, data, dest_length);
return static_cast<att::length_t>(dest_length);
}
else
{
logger::instance().warn("attribute::write: %d", length);
logger::instance().warn("attribute::write: %d", dest_length);
return 0u;
}
}
Expand Down
9 changes: 2 additions & 7 deletions ble/gatt_attribute.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,12 @@ struct attribute
attribute& operator=(attribute const&) = delete;
attribute& operator=(attribute&&) = delete;

attribute(attribute_type attr_type, uint16_t prop_bits) :
attribute(ble::gatt::attribute_type attr_type, uint16_t prop_bits) :
decl(attr_type, prop_bits)
{
}

attribute(uint32_t uuid_32, attribute_type attr_type, uint16_t prop_bits) :
decl(attr_type, prop_bits)
{
}

declaration decl;
ble::gatt::declaration decl;

/**
* Write data to the attribute. The base implementation behavior is
Expand Down
22 changes: 16 additions & 6 deletions ble/gatt_characteristic.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

#include "ble/gatt_attribute.h"
#include "ble/gatt_descriptors.h"
#include "ble/gatt_uuids.h"
#include "ble/gatt_enum_types.h"
#include "ble/gatt_format.h"

#include <cstdint>
Expand All @@ -27,37 +27,47 @@ struct characteristic: public attribute
{
virtual ~characteristic() override = default;

characteristic() = delete;
characteristic(characteristic const&) = delete;
characteristic(characteristic &&) = delete;
characteristic& operator=(characteristic const&) = delete;
characteristic& operator=(characteristic&&) = delete;

characteristic(att::uuid att_uuid, uint16_t prop_bits) :
/** A characteristic which is uninitialized. The uuid is zero filled */
characteristic() :
attribute(attribute_type::characteristic, 0u),
uuid(),
service_(nullptr)
{
}

/** A characteristic created by standard uuid. */
characteristic(att::uuid const& att_uuid, uint16_t prop_bits) :
attribute(attribute_type::characteristic, prop_bits),
uuid(att_uuid),
service_(nullptr)
{
}

/** A characteristic create by a 16-bit or 32-bit value. */
characteristic(uint32_t uuid_32, uint16_t prop_bits) :
attribute(attribute_type::characteristic, prop_bits),
uuid(uuid_32),
service_(nullptr)
{
}

characteristic(characteristics uuid_char, uint16_t prop_bits) :
/** A standard Bluetooth SIG characteristic. */
characteristic(characteristic_type uuid_ble_sig, uint16_t prop_bits) :
attribute(attribute_type::characteristic, prop_bits),
uuid(static_cast<uint16_t>(uuid_char)),
uuid(static_cast<uint16_t>(uuid_ble_sig)),
service_(nullptr)
{
}

ble::gatt::service const* service() const { return this->service_; }
ble::gatt::service* service() { return this->service_; }

void descriptor_add(characteristic_base_descriptor &descriptor) {
void descriptor_add(descriptor_base &descriptor) {
this->descriptor_list.push_back(descriptor);
}

Expand Down
84 changes: 84 additions & 0 deletions ble/gatt_declaration.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* @file ble/gatt_declaration.cc
* @copyright (c) 2018, natersoz. Distributed under the Apache 2.0 license.
*/

#include "gatt_declaration.h"
#include "int_to_string.h"
#include "std_error.h"

namespace ble
{
namespace gatt
{

std::to_chars_result properties::to_chars(char *begin, char *end) const
{
if (end - begin < 6)
{
return std::to_chars_result{begin, std::errc::value_too_large};
}

*begin++ = '0';
*begin++ = 'x';

uint16_t const props = this->get();
std::size_t const count = int_to_hex(begin, end - begin, props, 4u);
begin += count;

if (end - begin < 10) // We need 10 more characters to complete
{ // the conversion.
return std::to_chars_result {begin, std::errc::value_too_large};
}

*begin++ = ' ';

uint16_t const all_write_types =
ble::gatt::properties::write_without_response |
ble::gatt::properties::write |
ble::gatt::properties::write_with_signature |
ble::gatt::properties::write_reliable |
ble::gatt::properties::write_aux ;

*begin++ = ((props & ble::gatt::properties::broadcast)? 'b' : '-');
*begin++ = ((props & ble::gatt::properties::read)? 'r' : '-');
*begin++ = ((props & all_write_types)? 'w' : '-');
*begin++ = ((props & ble::gatt::properties::notify)? 'n' : '-');
*begin++ = ((props & ble::gatt::properties::indicate)? 'i' : '-');

if (props & ble::gatt::properties::write_without_response) { *begin++ = 'N'; }
if (props & ble::gatt::properties::write_with_signature) { *begin++ = 'S'; }
if (props & ble::gatt::properties::write_reliable) { *begin++ = 'R'; }
if (props & ble::gatt::properties::write_aux) { *begin++ = 'A'; }

// If there is room, write the null terminator.
if (end - begin > 1) { *begin++ = 0; }

return std::to_chars_result {begin, errc_success};
}

std::to_chars_result declaration::to_chars(char *begin, char *end) const
{
using signed_size_t = std::make_signed<std::size_t>::type;
if (end - begin < static_cast<signed_size_t>(conversion_length))
{
return std::to_chars_result{begin, std::errc::value_too_large};
}

char const type_prefix[] = "type: 0x";
memcpy(begin, type_prefix, sizeof(type_prefix));
begin += std::size(type_prefix) - 1u; // Overwrite null terminator.

uint16_t const attr_type = static_cast<uint16_t>(this->attribute_type);
std::size_t const count = int_to_hex(begin, end - begin, attr_type, 4u);
begin += count;

char const properties_prefix[] = " props: ";
memcpy(begin, properties_prefix, sizeof(properties_prefix));
begin += std::size(properties_prefix) - 1u; // Overwrite null terminator.
return this->properties.to_chars(begin, end);
}

} // namespace gatt
} // namespace ble

36 changes: 33 additions & 3 deletions ble/gatt_declaration.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@

#include "ble/uuid.h"
#include "ble/att.h"
#include "ble/gatt_uuids.h"
#include "ble/gatt_enum_types.h"
#include "charconv.h" /// @todo Issue 17

#include <cstdint>
#include <cstddef>

namespace ble
{
Expand Down Expand Up @@ -75,10 +77,24 @@ struct properties

bool is_writable() const { return this->get() & write; }
bool is_readable() const { return this->get() & read; }
bool is_read_write() const { return this->is_readable() && this->is_writable(); }
bool is_read_write() const { return this->is_readable() &&
this->is_writable(); }

uint8_t bits;
uint8_t bits_ext;

/**
* Convert properties to a string.
* The conversion form is: "0x0000 brwniNSRA"
* (17 bytes including the null terminator).
*
* @param begin The buffer into which the conversion will take place.
* @param end One past the valid buffer size; i.e. begin + length.
*
* @return std::to_chars_result The conversion result
*/
std::to_chars_result to_chars(char *begin, char *end) const;
static constexpr size_t const conversion_length = 17u;
};

/**
Expand Down Expand Up @@ -107,7 +123,21 @@ struct declaration

struct properties properties;
uint16_t handle;
enum attribute_type const attribute_type;
ble::gatt::attribute_type attribute_type;

/**
* Convert ble::gatt::declaration to a string.
* The conversion form is: "type: 0x0000 props: ", gatt::properties
* 13 + properties::conversion_length, includes null terminator.
*
* @param begin The buffer into which the conversion will take place.
* @param end One past the valid buffer size; i.e. begin + length.
*
* @return std::to_chars_result The conversion result
*/
std::to_chars_result to_chars(char *begin, char *end) const;
static constexpr size_t const conversion_length = 20u +
properties::conversion_length;
};

} // namespace gatt
Expand Down
Loading

0 comments on commit cee3cef

Please sign in to comment.