Bluetooth: Implemented new DIS characteristics
Implemented new DIS characteristics: - UDI for medical devices - IEEE 11073-20601 Regulatory Certification Data List - System ID Also fixed buffer overflow bug when assigning too long DIS string literals Signed-off-by: Simen Eilevstjønn <simen.eilevstjonn@laerdal.com>
This commit is contained in:
parent
eb406f80bc
commit
2c64fe7f37
3 changed files with 367 additions and 71 deletions
|
@ -5090,6 +5090,16 @@ struct bt_uuid_128 {
|
|||
#define BT_UUID_GATT_SL \
|
||||
BT_UUID_DECLARE_16(BT_UUID_GATT_SL_VAL)
|
||||
|
||||
/**
|
||||
* @brief GATT Characteristic UDI for Medical Devices UUID Value
|
||||
*/
|
||||
#define BT_UUID_UDI_FOR_MEDICAL_DEVICES_VAL 0x2bff
|
||||
/**
|
||||
* @brief GATT Characteristic UDI for Medical Devices
|
||||
*/
|
||||
#define BT_UUID_UDI_FOR_MEDICAL_DEVICES \
|
||||
BT_UUID_DECLARE_16(BT_UUID_UDI_FOR_MEDICAL_DEVICES_VAL)
|
||||
|
||||
/**
|
||||
* @brief Gaming Service UUID value
|
||||
*/
|
||||
|
|
|
@ -144,4 +144,74 @@ config BT_DIS_SW_REV_STR
|
|||
help
|
||||
Enable software revision characteristic in Device Information Service.
|
||||
|
||||
config BT_DIS_UDI
|
||||
bool "DIS UDI for Medical Devices characteristic"
|
||||
help
|
||||
Enable UDI for Medical Devices characteristic in Device Information Service.
|
||||
|
||||
if BT_DIS_UDI
|
||||
config BT_DIS_UDI_LABEL_STR
|
||||
string "UDI Label"
|
||||
help
|
||||
String value matching the UDI in human readable form
|
||||
as assigned to the product by a recognized UDI Issuer.
|
||||
|
||||
config BT_DIS_UDI_DI_STR
|
||||
string "UDI Device Identifier"
|
||||
help
|
||||
A fixed portion of a UDI that identifies the labeler and the
|
||||
specific version or model of a device.
|
||||
|
||||
config BT_DIS_UDI_ISSUER_STR
|
||||
string "UDI Issuer"
|
||||
help
|
||||
OID representing the UDI Issuing Organization, such as GS1.
|
||||
|
||||
config BT_DIS_UDI_AUTHORITY_STR
|
||||
string "UDI Authority"
|
||||
help
|
||||
OID representing the regional UDI Authority, such as the US FDA.
|
||||
endif # BT_DIS_UDI
|
||||
|
||||
config BT_DIS_SYSTEM_ID
|
||||
bool "DIS System ID characteristic [experimental]"
|
||||
select EXPERIMENTAL
|
||||
help
|
||||
Enable System ID characteristic in Device Information Service.
|
||||
The System ID characteristic is used to represent an extended unique identifier (EUI) of the system
|
||||
implementing the service that contains this characteristic. This 64-bit structure is an EUI-64 which consists
|
||||
of an Organizationally Unique Identifier (OUI) concatenated with a manufacturer-defined identifier.
|
||||
|
||||
This will be transmitted as the 40 bit identifier followed by the 24-bit OUI.
|
||||
Both in little-endian format.
|
||||
|
||||
if BT_DIS_SYSTEM_ID
|
||||
config BT_DIS_SYSTEM_ID_OUI
|
||||
hex "Organizationally Unique Identifier (OUI) of the manufacturer."
|
||||
range 0 0xFFFFFF
|
||||
default 0
|
||||
help
|
||||
The OUI is a 24-bit number issued by the IEEE Registration Authority.
|
||||
System ID characteristic in Device Information Service.
|
||||
Shall contain an Organisationally Unique Identifier (OUI) followed by a manufacturer-defined indentifier unique for the device.
|
||||
|
||||
config BT_DIS_SYSTEM_ID_IDENTIFIER
|
||||
hex "Manufacturer-defined unique identifier."
|
||||
range 0 0xFFFFFFFFFF
|
||||
default 0
|
||||
help
|
||||
The manufacturer-defined unique identifier is 40 bits long.
|
||||
endif # BT_DIS_SYSTEM_ID
|
||||
|
||||
config BT_DIS_IEEE_RCDL
|
||||
bool "DIS IEEE 11073-20601 Regulatory Certification Data List characteristic"
|
||||
help
|
||||
Enable IEEE 11073-20601 Regulatory Certification Data List characteristic in Device Information Service.
|
||||
|
||||
config BT_DIS_IEEE_RCDL_STR
|
||||
string "IEEE 11073-20601 Regulatory Certification Data List"
|
||||
depends on BT_DIS_IEEE_RCDL
|
||||
help
|
||||
IEEE 11073-20601 Regulatory Certification Data List characteristic in Device Information Service string contents.
|
||||
|
||||
endif # BT_DIS
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
#include <zephyr/bluetooth/uuid.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
#include <zephyr/bluetooth/byteorder.h>
|
||||
|
||||
#define LOG_LEVEL CONFIG_BT_SERVICE_LOG_LEVEL
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(bt_dis);
|
||||
|
@ -45,105 +48,262 @@ static struct dis_pnp dis_pnp_id = {
|
|||
};
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_DIS_SETTINGS)
|
||||
static uint8_t dis_model[CONFIG_BT_DIS_STR_MAX] = CONFIG_BT_DIS_MODEL;
|
||||
static uint8_t dis_manuf[CONFIG_BT_DIS_STR_MAX] = CONFIG_BT_DIS_MANUF;
|
||||
#if defined(CONFIG_BT_DIS_SERIAL_NUMBER)
|
||||
static uint8_t dis_serial_number[CONFIG_BT_DIS_STR_MAX] =
|
||||
CONFIG_BT_DIS_SERIAL_NUMBER_STR;
|
||||
#endif
|
||||
#if defined(CONFIG_BT_DIS_FW_REV)
|
||||
static uint8_t dis_fw_rev[CONFIG_BT_DIS_STR_MAX] =
|
||||
CONFIG_BT_DIS_FW_REV_STR;
|
||||
#endif
|
||||
#if defined(CONFIG_BT_DIS_HW_REV)
|
||||
static uint8_t dis_hw_rev[CONFIG_BT_DIS_STR_MAX] =
|
||||
CONFIG_BT_DIS_HW_REV_STR;
|
||||
#endif
|
||||
#if defined(CONFIG_BT_DIS_SW_REV)
|
||||
static uint8_t dis_sw_rev[CONFIG_BT_DIS_STR_MAX] =
|
||||
CONFIG_BT_DIS_SW_REV_STR;
|
||||
#if defined(CONFIG_BT_DIS_SYSTEM_ID)
|
||||
/*
|
||||
* Casting to uint64_t since the value is at most 5 bytes, but will appear as a 32-bit literal if it
|
||||
* is less, giving a warning when right-shifting by 32.
|
||||
*/
|
||||
static uint8_t dis_system_id[8] = {BT_BYTES_LIST_LE40((uint64_t)CONFIG_BT_DIS_SYSTEM_ID_IDENTIFIER),
|
||||
BT_BYTES_LIST_LE24(CONFIG_BT_DIS_SYSTEM_ID_OUI)};
|
||||
#endif
|
||||
|
||||
#define BT_DIS_MODEL_REF dis_model
|
||||
#define BT_DIS_MANUF_REF dis_manuf
|
||||
#define BT_DIS_SERIAL_NUMBER_STR_REF dis_serial_number
|
||||
#define BT_DIS_FW_REV_STR_REF dis_fw_rev
|
||||
#define BT_DIS_HW_REV_STR_REF dis_hw_rev
|
||||
#define BT_DIS_SW_REV_STR_REF dis_sw_rev
|
||||
#if defined(CONFIG_BT_DIS_SETTINGS)
|
||||
BUILD_ASSERT(sizeof(CONFIG_BT_DIS_MODEL) <= CONFIG_BT_DIS_STR_MAX + 1);
|
||||
BUILD_ASSERT(sizeof(CONFIG_BT_DIS_MANUF) <= CONFIG_BT_DIS_STR_MAX + 1);
|
||||
static uint8_t dis_model[CONFIG_BT_DIS_STR_MAX + 1] = CONFIG_BT_DIS_MODEL;
|
||||
static uint8_t dis_manuf[CONFIG_BT_DIS_STR_MAX + 1] = CONFIG_BT_DIS_MANUF;
|
||||
#if defined(CONFIG_BT_DIS_SERIAL_NUMBER)
|
||||
BUILD_ASSERT(sizeof(CONFIG_BT_DIS_SERIAL_NUMBER_STR) <= CONFIG_BT_DIS_STR_MAX + 1);
|
||||
static uint8_t dis_serial_number[CONFIG_BT_DIS_STR_MAX + 1] = CONFIG_BT_DIS_SERIAL_NUMBER_STR;
|
||||
#endif
|
||||
#if defined(CONFIG_BT_DIS_FW_REV)
|
||||
BUILD_ASSERT(sizeof(CONFIG_BT_DIS_FW_REV_STR) <= CONFIG_BT_DIS_STR_MAX + 1);
|
||||
static uint8_t dis_fw_rev[CONFIG_BT_DIS_STR_MAX + 1] = CONFIG_BT_DIS_FW_REV_STR;
|
||||
#endif
|
||||
#if defined(CONFIG_BT_DIS_HW_REV)
|
||||
BUILD_ASSERT(sizeof(CONFIG_BT_DIS_HW_REV_STR) <= CONFIG_BT_DIS_STR_MAX + 1);
|
||||
static uint8_t dis_hw_rev[CONFIG_BT_DIS_STR_MAX + 1] = CONFIG_BT_DIS_HW_REV_STR;
|
||||
#endif
|
||||
#if defined(CONFIG_BT_DIS_SW_REV)
|
||||
BUILD_ASSERT(sizeof(CONFIG_BT_DIS_SW_REV_STR) <= CONFIG_BT_DIS_STR_MAX + 1);
|
||||
static uint8_t dis_sw_rev[CONFIG_BT_DIS_STR_MAX + 1] = CONFIG_BT_DIS_SW_REV_STR;
|
||||
#endif
|
||||
#if defined(CONFIG_BT_DIS_UDI)
|
||||
BUILD_ASSERT(sizeof(CONFIG_BT_DIS_UDI_LABEL_STR) <= CONFIG_BT_DIS_STR_MAX + 1);
|
||||
BUILD_ASSERT(sizeof(CONFIG_BT_DIS_UDI_DI_STR) <= CONFIG_BT_DIS_STR_MAX + 1);
|
||||
BUILD_ASSERT(sizeof(CONFIG_BT_DIS_UDI_ISSUER_STR) <= CONFIG_BT_DIS_STR_MAX + 1);
|
||||
BUILD_ASSERT(sizeof(CONFIG_BT_DIS_UDI_AUTHORITY_STR) <= CONFIG_BT_DIS_STR_MAX + 1);
|
||||
|
||||
static uint8_t dis_udi_label[CONFIG_BT_DIS_STR_MAX + 1] = CONFIG_BT_DIS_UDI_LABEL_STR;
|
||||
static uint8_t dis_udi_di[CONFIG_BT_DIS_STR_MAX + 1] = CONFIG_BT_DIS_UDI_DI_STR;
|
||||
static uint8_t dis_udi_issuer[CONFIG_BT_DIS_STR_MAX + 1] = CONFIG_BT_DIS_UDI_ISSUER_STR;
|
||||
static uint8_t dis_udi_authority[CONFIG_BT_DIS_STR_MAX + 1] = CONFIG_BT_DIS_UDI_AUTHORITY_STR;
|
||||
#endif
|
||||
#if defined(CONFIG_BT_DIS_IEEE_RCDL)
|
||||
BUILD_ASSERT(sizeof(CONFIG_BT_DIS_IEEE_RCDL_STR) <= CONFIG_BT_DIS_STR_MAX + 1);
|
||||
static uint8_t dis_ieee_rcdl[CONFIG_BT_DIS_STR_MAX + 1] = CONFIG_BT_DIS_IEEE_RCDL_STR;
|
||||
#endif
|
||||
|
||||
#define BT_DIS_MODEL_REF dis_model
|
||||
#define BT_DIS_MANUF_REF dis_manuf
|
||||
#define BT_DIS_SERIAL_NUMBER_STR_REF dis_serial_number
|
||||
#define BT_DIS_FW_REV_STR_REF dis_fw_rev
|
||||
#define BT_DIS_HW_REV_STR_REF dis_hw_rev
|
||||
#define BT_DIS_SW_REV_STR_REF dis_sw_rev
|
||||
#define BT_DIS_UDI_LABEL_STR_REF dis_udi_label
|
||||
#define BT_DIS_UDI_DI_STR_REF dis_udi_di
|
||||
#define BT_DIS_UDI_ISSUER_STR_REF dis_udi_issuer
|
||||
#define BT_DIS_UDI_AUTHORITY_STR_REF dis_udi_authority
|
||||
#define BT_DIS_IEEE_RCDL_STR_REF dis_ieee_rcdl
|
||||
|
||||
/*
|
||||
* When assigning too long string literals to the arrays,
|
||||
* the literals may be truncated, removing the null terminator.
|
||||
* Using strnlen to avoid sending data outside the array.
|
||||
*/
|
||||
|
||||
#else /* CONFIG_BT_DIS_SETTINGS */
|
||||
|
||||
#define BT_DIS_MODEL_REF CONFIG_BT_DIS_MODEL
|
||||
#define BT_DIS_MANUF_REF CONFIG_BT_DIS_MANUF
|
||||
#define BT_DIS_SERIAL_NUMBER_STR_REF CONFIG_BT_DIS_SERIAL_NUMBER_STR
|
||||
#define BT_DIS_FW_REV_STR_REF CONFIG_BT_DIS_FW_REV_STR
|
||||
#define BT_DIS_HW_REV_STR_REF CONFIG_BT_DIS_HW_REV_STR
|
||||
#define BT_DIS_SW_REV_STR_REF CONFIG_BT_DIS_SW_REV_STR
|
||||
#define BT_DIS_MODEL_REF CONFIG_BT_DIS_MODEL
|
||||
#define BT_DIS_MANUF_REF CONFIG_BT_DIS_MANUF
|
||||
#define BT_DIS_SERIAL_NUMBER_STR_REF CONFIG_BT_DIS_SERIAL_NUMBER_STR
|
||||
#define BT_DIS_FW_REV_STR_REF CONFIG_BT_DIS_FW_REV_STR
|
||||
#define BT_DIS_HW_REV_STR_REF CONFIG_BT_DIS_HW_REV_STR
|
||||
#define BT_DIS_SW_REV_STR_REF CONFIG_BT_DIS_SW_REV_STR
|
||||
#define BT_DIS_UDI_LABEL_STR_REF CONFIG_BT_DIS_UDI_LABEL_STR
|
||||
#define BT_DIS_UDI_DI_STR_REF CONFIG_BT_DIS_UDI_DI_STR
|
||||
#define BT_DIS_UDI_ISSUER_STR_REF CONFIG_BT_DIS_UDI_ISSUER_STR
|
||||
#define BT_DIS_UDI_AUTHORITY_STR_REF CONFIG_BT_DIS_UDI_AUTHORITY_STR
|
||||
#define BT_DIS_IEEE_RCDL_STR_REF CONFIG_BT_DIS_IEEE_RCDL_STR
|
||||
|
||||
#endif /* CONFIG_BT_DIS_SETTINGS */
|
||||
|
||||
static ssize_t read_str(struct bt_conn *conn,
|
||||
const struct bt_gatt_attr *attr, void *buf,
|
||||
uint16_t len, uint16_t offset)
|
||||
static ssize_t read_str(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
|
||||
uint16_t len, uint16_t offset)
|
||||
{
|
||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, attr->user_data,
|
||||
strlen(attr->user_data));
|
||||
}
|
||||
|
||||
#if CONFIG_BT_DIS_PNP
|
||||
static ssize_t read_pnp_id(struct bt_conn *conn,
|
||||
const struct bt_gatt_attr *attr, void *buf,
|
||||
static ssize_t read_pnp_id(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
|
||||
uint16_t len, uint16_t offset)
|
||||
{
|
||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, &dis_pnp_id,
|
||||
sizeof(dis_pnp_id));
|
||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, &dis_pnp_id, sizeof(dis_pnp_id));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_BT_DIS_SYSTEM_ID
|
||||
static ssize_t read_system_id(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
|
||||
uint16_t len, uint16_t offset)
|
||||
{
|
||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, dis_system_id,
|
||||
sizeof(dis_system_id));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_BT_DIS_UDI
|
||||
#define DIS_STR_SIZE(x) ((x[0]) != '\0' ? strlen(x) + sizeof('\0') : 0)
|
||||
#define BT_DIS_UDI_FLAG_LABEL (!!BT_DIS_UDI_LABEL_STR_REF[0])
|
||||
#define BT_DIS_UDI_FLAG_DI (!!BT_DIS_UDI_DI_STR_REF[0])
|
||||
#define BT_DIS_UDI_FLAG_ISSUER (!!BT_DIS_UDI_ISSUER_STR_REF[0])
|
||||
#define BT_DIS_UDI_FLAG_AUTHORITY (!!BT_DIS_UDI_AUTHORITY_STR_REF[0])
|
||||
#define BT_DIS_UDI_FLAGS \
|
||||
(BT_DIS_UDI_FLAG_LABEL | (BT_DIS_UDI_FLAG_DI << 1) | (BT_DIS_UDI_FLAG_ISSUER << 2) | \
|
||||
(BT_DIS_UDI_FLAG_AUTHORITY << 3))
|
||||
|
||||
/*
|
||||
* UDI for medical devices contains a flag and 4 different null-terminated strings that may have
|
||||
* unknown length. This requires its own encode method.
|
||||
*/
|
||||
static void read_udi_subval(const char *str, uint16_t val_len, char *buf, uint16_t *bytes_read,
|
||||
uint16_t *index, uint16_t len, uint16_t offset)
|
||||
{
|
||||
/* String should not be with included null-terminator if empty */
|
||||
if (val_len == sizeof('\0')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (*bytes_read == len) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (*index + val_len < offset) {
|
||||
*index += val_len;
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint16_t i = 0; i < val_len; i++) {
|
||||
if (*index >= offset && *bytes_read < len) {
|
||||
buf[*bytes_read] = str[i];
|
||||
|
||||
(*bytes_read)++;
|
||||
}
|
||||
|
||||
(*index)++;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t read_udi(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
|
||||
uint16_t len, uint16_t offset)
|
||||
{
|
||||
uint16_t bytes_read = 0;
|
||||
|
||||
char *buf_i = (char *)buf;
|
||||
|
||||
/* Flag */
|
||||
uint16_t index = sizeof(uint8_t);
|
||||
|
||||
if (offset == 0) {
|
||||
buf_i[0] = BT_DIS_UDI_FLAGS;
|
||||
bytes_read = 1U;
|
||||
}
|
||||
|
||||
read_udi_subval(BT_DIS_UDI_LABEL_STR_REF, DIS_STR_SIZE(BT_DIS_UDI_LABEL_STR_REF), buf_i,
|
||||
&bytes_read, &index, len, offset);
|
||||
read_udi_subval(BT_DIS_UDI_DI_STR_REF, DIS_STR_SIZE(BT_DIS_UDI_DI_STR_REF), buf_i,
|
||||
&bytes_read, &index, len, offset);
|
||||
read_udi_subval(BT_DIS_UDI_ISSUER_STR_REF, DIS_STR_SIZE(BT_DIS_UDI_ISSUER_STR_REF), buf_i,
|
||||
&bytes_read, &index, len, offset);
|
||||
read_udi_subval(BT_DIS_UDI_AUTHORITY_STR_REF, DIS_STR_SIZE(BT_DIS_UDI_AUTHORITY_STR_REF),
|
||||
buf_i, &bytes_read, &index, len, offset);
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Device Information Service Declaration */
|
||||
BT_GATT_SERVICE_DEFINE(dis_svc,
|
||||
BT_GATT_PRIMARY_SERVICE(BT_UUID_DIS),
|
||||
BT_GATT_SERVICE_DEFINE(
|
||||
dis_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_DIS),
|
||||
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DIS_MODEL_NUMBER,
|
||||
BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DIS_MODEL_NUMBER, BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
|
||||
read_str, NULL, BT_DIS_MODEL_REF),
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DIS_MANUFACTURER_NAME,
|
||||
BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DIS_MANUFACTURER_NAME, BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
|
||||
read_str, NULL, BT_DIS_MANUF_REF),
|
||||
#if CONFIG_BT_DIS_PNP
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DIS_PNP_ID,
|
||||
BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DIS_PNP_ID, BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
|
||||
read_pnp_id, NULL, &dis_pnp_id),
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_DIS_SERIAL_NUMBER)
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DIS_SERIAL_NUMBER,
|
||||
BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
|
||||
read_str, NULL,
|
||||
BT_DIS_SERIAL_NUMBER_STR_REF),
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DIS_SERIAL_NUMBER, BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
|
||||
read_str, NULL, BT_DIS_SERIAL_NUMBER_STR_REF),
|
||||
#endif
|
||||
#if defined(CONFIG_BT_DIS_FW_REV)
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DIS_FIRMWARE_REVISION,
|
||||
BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DIS_FIRMWARE_REVISION, BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
|
||||
read_str, NULL, BT_DIS_FW_REV_STR_REF),
|
||||
#endif
|
||||
#if defined(CONFIG_BT_DIS_HW_REV)
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DIS_HARDWARE_REVISION,
|
||||
BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DIS_HARDWARE_REVISION, BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
|
||||
read_str, NULL, BT_DIS_HW_REV_STR_REF),
|
||||
#endif
|
||||
#if defined(CONFIG_BT_DIS_SW_REV)
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DIS_SOFTWARE_REVISION,
|
||||
BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DIS_SOFTWARE_REVISION, BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
|
||||
read_str, NULL, BT_DIS_SW_REV_STR_REF),
|
||||
#endif
|
||||
#if defined(CONFIG_BT_DIS_UDI)
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_UDI_FOR_MEDICAL_DEVICES, BT_GATT_CHRC_READ,
|
||||
BT_GATT_PERM_READ, read_udi, NULL, NULL),
|
||||
#endif
|
||||
#if defined(CONFIG_BT_DIS_SYSTEM_ID)
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DIS_SYSTEM_ID, BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
|
||||
read_system_id, NULL, NULL),
|
||||
#endif
|
||||
#if defined(CONFIG_BT_DIS_IEEE_RCDL)
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_GATT_IEEE_RCDL, BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
|
||||
read_str, NULL, BT_DIS_IEEE_RCDL_STR_REF),
|
||||
#endif
|
||||
|
||||
);
|
||||
|
||||
#if defined(CONFIG_BT_DIS_SETTINGS)
|
||||
static int dis_set(const char *name, size_t len_rd,
|
||||
settings_read_cb read_cb, void *store)
|
||||
#if defined(CONFIG_BT_DIS_UDI)
|
||||
static void dis_update_udi_value(const char *new, char *old, settings_read_cb read_cb,
|
||||
const char *logkey)
|
||||
{
|
||||
/*
|
||||
* The characteristic contains 1 one-byte flag and 4-null-terminated.
|
||||
* The null-terminators are only present for strings that are in the flags.
|
||||
*/
|
||||
const size_t merged_size = sizeof(uint8_t) + DIS_STR_SIZE(BT_DIS_UDI_LABEL_STR_REF) +
|
||||
DIS_STR_SIZE(BT_DIS_UDI_DI_STR_REF) +
|
||||
DIS_STR_SIZE(BT_DIS_UDI_ISSUER_STR_REF) +
|
||||
DIS_STR_SIZE(BT_DIS_UDI_AUTHORITY_STR_REF);
|
||||
|
||||
size_t without_old = merged_size - DIS_STR_SIZE(old);
|
||||
|
||||
bool valid = BT_ATT_MAX_ATTRIBUTE_LEN >= without_old + DIS_STR_SIZE(new);
|
||||
|
||||
if (!valid) {
|
||||
LOG_ERR("Failed to set UDI %s. Not enough space. The sum of the 4 DIS UDI for "
|
||||
"Medical Devices strings may not exceed the maximum attribute length.",
|
||||
logkey);
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t len = read_cb((void *)new, (void *)old, CONFIG_BT_DIS_STR_MAX);
|
||||
|
||||
if (len < 0) {
|
||||
LOG_ERR("Failed to read UDI %s from storage (err %zd)", logkey, len);
|
||||
} else {
|
||||
old[len] = '\0';
|
||||
|
||||
LOG_DBG("UDI %s set to %s", logkey, old);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int dis_set(const char *name, size_t len_rd, settings_read_cb read_cb, void *store)
|
||||
{
|
||||
ssize_t len;
|
||||
int nlen;
|
||||
|
@ -153,8 +313,7 @@ static int dis_set(const char *name, size_t len_rd,
|
|||
if (!strncmp(name, "manuf", nlen)) {
|
||||
len = read_cb(store, &dis_manuf, sizeof(dis_manuf) - 1);
|
||||
if (len < 0) {
|
||||
LOG_ERR("Failed to read manufacturer from storage"
|
||||
" (err %zd)", len);
|
||||
LOG_ERR("Failed to read manufacturer from storage (err %zd)", len);
|
||||
} else {
|
||||
dis_manuf[len] = '\0';
|
||||
|
||||
|
@ -165,8 +324,7 @@ static int dis_set(const char *name, size_t len_rd,
|
|||
if (!strncmp(name, "model", nlen)) {
|
||||
len = read_cb(store, &dis_model, sizeof(dis_model) - 1);
|
||||
if (len < 0) {
|
||||
LOG_ERR("Failed to read model from storage"
|
||||
" (err %zd)", len);
|
||||
LOG_ERR("Failed to read model from storage (err %zd)", len);
|
||||
} else {
|
||||
dis_model[len] = '\0';
|
||||
|
||||
|
@ -176,11 +334,9 @@ static int dis_set(const char *name, size_t len_rd,
|
|||
}
|
||||
#if defined(CONFIG_BT_DIS_SERIAL_NUMBER)
|
||||
if (!strncmp(name, "serial", nlen)) {
|
||||
len = read_cb(store, &dis_serial_number,
|
||||
sizeof(dis_serial_number) - 1);
|
||||
len = read_cb(store, &dis_serial_number, sizeof(dis_serial_number) - 1);
|
||||
if (len < 0) {
|
||||
LOG_ERR("Failed to read serial number from storage"
|
||||
" (err %zd)", len);
|
||||
LOG_ERR("Failed to read serial number from storage (err %zd)", len);
|
||||
} else {
|
||||
dis_serial_number[len] = '\0';
|
||||
|
||||
|
@ -193,8 +349,7 @@ static int dis_set(const char *name, size_t len_rd,
|
|||
if (!strncmp(name, "fw", nlen)) {
|
||||
len = read_cb(store, &dis_fw_rev, sizeof(dis_fw_rev) - 1);
|
||||
if (len < 0) {
|
||||
LOG_ERR("Failed to read firmware revision from storage"
|
||||
" (err %zd)", len);
|
||||
LOG_ERR("Failed to read firmware revision from storage (err %zd)", len);
|
||||
} else {
|
||||
dis_fw_rev[len] = '\0';
|
||||
|
||||
|
@ -207,8 +362,7 @@ static int dis_set(const char *name, size_t len_rd,
|
|||
if (!strncmp(name, "hw", nlen)) {
|
||||
len = read_cb(store, &dis_hw_rev, sizeof(dis_hw_rev) - 1);
|
||||
if (len < 0) {
|
||||
LOG_ERR("Failed to read hardware revision from storage"
|
||||
" (err %zd)", len);
|
||||
LOG_ERR("Failed to read hardware revision from storage (err %zd)", len);
|
||||
} else {
|
||||
dis_hw_rev[len] = '\0';
|
||||
|
||||
|
@ -221,8 +375,7 @@ static int dis_set(const char *name, size_t len_rd,
|
|||
if (!strncmp(name, "sw", nlen)) {
|
||||
len = read_cb(store, &dis_sw_rev, sizeof(dis_sw_rev) - 1);
|
||||
if (len < 0) {
|
||||
LOG_ERR("Failed to read software revision from storage"
|
||||
" (err %zd)", len);
|
||||
LOG_ERR("Failed to read software revision from storage (err %zd)", len);
|
||||
} else {
|
||||
dis_sw_rev[len] = '\0';
|
||||
|
||||
|
@ -230,6 +383,69 @@ static int dis_set(const char *name, size_t len_rd,
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_BT_DIS_UDI)
|
||||
if (!strncmp(name, "udi_label", nlen)) {
|
||||
dis_update_udi_value(store, BT_DIS_UDI_LABEL_STR_REF, read_cb, "label");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strncmp(name, "udi_di", nlen)) {
|
||||
dis_update_udi_value(store, BT_DIS_UDI_DI_STR_REF, read_cb, "device information");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strncmp(name, "udi_issuer", nlen)) {
|
||||
dis_update_udi_value(store, BT_DIS_UDI_ISSUER_STR_REF, read_cb, "issuer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strncmp(name, "udi_authority", nlen)) {
|
||||
dis_update_udi_value(store, BT_DIS_UDI_AUTHORITY_STR_REF, read_cb, "authority");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_BT_DIS_SYSTEM_ID)
|
||||
if (!strncmp(name, "sysid_oui", nlen)) {
|
||||
uint32_t oui = 0;
|
||||
|
||||
len = read_cb(store, &oui, sizeof(oui));
|
||||
if (len < 0) {
|
||||
LOG_ERR("Failed to read System ID OUI from storage (err %zd)", len);
|
||||
} else {
|
||||
sys_put_le24(oui, &dis_system_id[5]);
|
||||
LOG_DBG("System ID OUI set to %06X", oui);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (!strncmp(name, "sysid_identifier", nlen)) {
|
||||
uint64_t identifier = 0;
|
||||
|
||||
len = read_cb(store, &identifier, sizeof(identifier));
|
||||
if (len < 0) {
|
||||
LOG_ERR("Failed to read System ID identifier from storage (err %zd)", len);
|
||||
} else {
|
||||
sys_put_le40(identifier, &dis_system_id[0]);
|
||||
LOG_DBG("System ID identifier set to %10llX", identifier);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_BT_DIS_IEEE_RCDL)
|
||||
if (!strncmp(name, "ieeercdl", nlen)) {
|
||||
len = read_cb(store, &dis_ieee_rcdl, sizeof(dis_ieee_rcdl) - 1);
|
||||
if (len < 0) {
|
||||
LOG_ERR("Failed to read IEEE 11073-20601 Regulatory Certification Data "
|
||||
"List from storage (err %zd)",
|
||||
len);
|
||||
} else {
|
||||
dis_ieee_rcdl[len] = '\0';
|
||||
|
||||
LOG_DBG("IEEE 11073-20601 Regulatory Certification Data List set to %s",
|
||||
dis_ieee_rcdl);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue