diff --git a/nimble/host/include/host/ble_gatt.h b/nimble/host/include/host/ble_gatt.h index 3e59e3467..fedfabb27 100644 --- a/nimble/host/include/host/ble_gatt.h +++ b/nimble/host/include/host/ble_gatt.h @@ -66,6 +66,8 @@ struct ble_hs_cfg; /** GATT Client Characteristic Configuration descriptor 16-bit UUID. */ #define BLE_GATT_DSC_CLT_CFG_UUID16 0x2902 +#define BLE_GATT_DSC_CLT_PRE_FMT16 0x2904 +#define BLE_GATT_DSC_CLT_AGG_FMT16 0x2905 /** @} */ @@ -186,6 +188,203 @@ struct ble_hs_cfg; #define BLE_GATT_SVC_TYPE_SECONDARY 2 /** @} */ +/** + * Client Presentation Format + * GATT Format Types + * Ref: Assigned Numbers Specification + */ +#define BLE_GATT_CHR_FORMAT_BOOLEAN 0x01 +#define BLE_GATT_CHR_FORMAT_UINT2 0x02 +#define BLE_GATT_CHR_FORMAT_UINT4 0x03 +#define BLE_GATT_CHR_FORMAT_UINT8 0x04 +#define BLE_GATT_CHR_FORMAT_UINT12 0x05 +#define BLE_GATT_CHR_FORMAT_UINT16 0x06 +#define BLE_GATT_CHR_FORMAT_UINT24 0x07 +#define BLE_GATT_CHR_FORMAT_UINT32 0x08 +#define BLE_GATT_CHR_FORMAT_UINT48 0x09 +#define BLE_GATT_CHR_FORMAT_UINT64 0x0A +#define BLE_GATT_CHR_FORMAT_UINT128 0x0B +#define BLE_GATT_CHR_FORMAT_SINT8 0x0C +#define BLE_GATT_CHR_FORMAT_SINT12 0x0D +#define BLE_GATT_CHR_FORMAT_SINT16 0x0E +#define BLE_GATT_CHR_FORMAT_SINT24 0x0F +#define BLE_GATT_CHR_FORMAT_SINT32 0x10 +#define BLE_GATT_CHR_FORMAT_SINT48 0x11 +#define BLE_GATT_CHR_FORMAT_SINT64 0x12 +#define BLE_GATT_CHR_FORMAT_SINT128 0x13 +#define BLE_GATT_CHR_FORMAT_FLOAT32 0x14 +#define BLE_GATT_CHR_FORMAT_FLOAT64 0x15 +#define BLE_GATT_CHR_FORMAT_MEDFLOAT16 0x16 +#define BLE_GATT_CHR_FORMAT_MEDFLOAT32 0x17 +#define BLE_GATT_CHR_FORMAT_UINT16_2 0x18 +#define BLE_GATT_CHR_FORMAT_UTF8S 0x19 +#define BLE_GATT_CHR_FORMAT_UTF16S 0x1A +#define BLE_GATT_CHR_FORMAT_STRUCT 0x1B +#define BLE_GATT_CHR_FORMAT_MEDASN1 0x1C + +/** + * Client Presentation Format + * GATT Unit UUIDs + * Ref: Assigned Numbers Specification + */ +#define BLE_GATT_CHR_UNIT_UNITLESS 0x2700 /* Unitless */ +#define BLE_GATT_CHR_UNIT_METRE 0x2701 /* Length */ +#define BLE_GATT_CHR_UNIT_KILOGRAM 0x2702 /* Mass */ +#define BLE_GATT_CHR_UNIT_SECOND 0x2703 /* Time */ +#define BLE_GATT_CHR_UNIT_AMPERE 0x2704 /* Electric Current */ +#define BLE_GATT_CHR_UNIT_KELVIN 0x2705 /* Thermodynamic Temperature */ +#define BLE_GATT_CHR_UNIT_MOLE 0x2706 /* Amount Of Substance */ +#define BLE_GATT_CHR_UNIT_CANDELA 0x2707 /* Luminous Intensity */ +#define BLE_GATT_CHR_UNIT_SQUARE_METRES 0x2710 /* Area */ +#define BLE_GATT_CHR_UNIT_CUBIC_METRES 0x2711 /* Volume */ +#define BLE_GATT_CHR_UNIT_METRES_PER_SECOND 0x2712 /* Velocity */ +#define BLE_GATT_CHR_UNIT_METRES_PER_SECOND_SQUARED 0x2713 /* Acceleration */ +#define BLE_GATT_CHR_UNIT_RECIPROCAL_METRE 0x2714 /* Wavenumber */ +#define BLE_GATT_CHR_UNIT_KILOGRAM_PER_CUBIC_METRE_DENSITY 0x2715 /* Density */ +#define BLE_GATT_CHR_UNIT_KILOGRAM_PER_SQUARE_METRE 0x2716 /* Surface Density */ +#define BLE_GATT_CHR_UNIT_CUBIC_METRE_PER_KILOGRAM 0x2717 /* Specific Volume */ +#define BLE_GATT_CHR_UNIT_AMPERE_PER_SQUARE_METRE 0x2718 /* Current Density */ +#define BLE_GATT_CHR_UNIT_AMPERE_PER_METRE 0x2719 /* Magnetic Field Strength */ +#define BLE_GATT_CHR_UNIT_MOLE_PER_CUBIC_METRE 0x271A /* Amount Concentration */ +#define BLE_GATT_CHR_UNIT_KILOGRAM_PER_CUBIC_METRE_MASS_CONC 0x271B /* Mass Concentration */ +#define BLE_GATT_CHR_UNIT_CANDELA_PER_SQUARE_METRE 0x271C /* Luminance */ +#define BLE_GATT_CHR_UNIT_REFRACTIVE_INDEX 0x271D /* Refractive Index */ +#define BLE_GATT_CHR_UNIT_RELATIVE_PERMEABILITY 0x271E /* Relative Permeability */ +#define BLE_GATT_CHR_UNIT_RADIAN 0x2720 /* Plane Angle */ +#define BLE_GATT_CHR_UNIT_STERADIAN 0x2721 /* Solid Angle */ +#define BLE_GATT_CHR_UNIT_HERTZ 0x2722 /* Frequency */ +#define BLE_GATT_CHR_UNIT_NEWTON 0x2723 /* Force */ +#define BLE_GATT_CHR_UNIT_PASCAL 0x2724 /* Pressure */ +#define BLE_GATT_CHR_UNIT_JOULE 0x2725 /* Energy */ +#define BLE_GATT_CHR_UNIT_WATT 0x2726 /* Power */ +#define BLE_GATT_CHR_UNIT_COULOMB 0x2727 /* Electric Charge */ +#define BLE_GATT_CHR_UNIT_VOLT 0x2728 /* Electric Potential Difference */ +#define BLE_GATT_CHR_UNIT_FARAD 0x2729 /* Capacitance */ +#define BLE_GATT_CHR_UNIT_OHM 0x272A /* Electric Resistance */ +#define BLE_GATT_CHR_UNIT_SIEMENS 0x272B /* Electric Conductance */ +#define BLE_GATT_CHR_UNIT_WEBER 0x272C /* Magnetic Flux */ +#define BLE_GATT_CHR_UNIT_TESLA 0x272D /* Magnetic Flux Density */ +#define BLE_GATT_CHR_UNIT_HENRY 0x272E /* Inductance */ +#define BLE_GATT_CHR_UNIT_DEGREE_CELSIUS 0x272F /* celsius Temperature */ +#define BLE_GATT_CHR_UNIT_LUMEN 0x2730 /* Luminous Flux */ +#define BLE_GATT_CHR_UNIT_LUX 0x2731 /* Illuminance */ +#define BLE_GATT_CHR_UNIT_BECQUEREL 0x2732 /* Activity Referred To A Radionuclide */ +#define BLE_GATT_CHR_UNIT_GRAY 0x2733 /* Absorbed Dose */ +#define BLE_GATT_CHR_UNIT_SIEVERT 0x2734 /* Dose Equivalent */ +#define BLE_GATT_CHR_UNIT_KATAL 0x2735 /* Catalytic Activity */ +#define BLE_GATT_CHR_UNIT_PASCAL_SECOND 0x2740 /* Dynamic Viscosity */ +#define BLE_GATT_CHR_UNIT_NEWTON_METRE 0x2741 /* Moment Of Force */ +#define BLE_GATT_CHR_UNIT_NEWTON_PER_METRE 0x2742 /* Surface Tension */ +#define BLE_GATT_CHR_UNIT_RADIAN_PER_SECOND 0x2743 /* Angular Velocity */ +#define BLE_GATT_CHR_UNIT_RADIAN_PER_SECOND_SQUARED 0x2744 /* Angular Acceleration */ +#define BLE_GATT_CHR_UNIT_WATT_PER_SQUARE_METRE_HEAT 0x2745 /* Heat Flux Density */ +#define BLE_GATT_CHR_UNIT_JOULE_PER_KELVIN 0x2746 /* Heat Capacity */ +#define BLE_GATT_CHR_UNIT_JOULE_PER_KILOGRAM_KELVIN 0x2747 /* Specific Heat Capacity */ +#define BLE_GATT_CHR_UNIT_JOULE_PER_KILOGRAM 0x2748 /* Specific Energy */ +#define BLE_GATT_CHR_UNIT_WATT_PER_METRE_KELVIN 0x2749 /* Thermal Conductivity */ +#define BLE_GATT_CHR_UNIT_JOULE_PER_CUBIC_METRE 0x274A /* Energy Density */ +#define BLE_GATT_CHR_UNIT_VOLT_PER_METRE 0x274B /* Electric Field Strength */ +#define BLE_GATT_CHR_UNIT_COULOMB_PER_CUBIC_METRE 0x274C /* Electric Charge Density */ +#define BLE_GATT_CHR_UNIT_COULOMB_PER_SQUARE_METRE_CHARGE 0x274D /* Surface Charge Density */ +#define BLE_GATT_CHR_UNIT_COULOMB_PER_SQUARE_METRE_FLUX 0x274E /* Electric Flux Density */ +#define BLE_GATT_CHR_UNIT_FARAD_PER_METRE 0x274F /* Permittivity */ +#define BLE_GATT_CHR_UNIT_HENRY_PER_METRE 0x2750 /* Permeability */ +#define BLE_GATT_CHR_UNIT_JOULE_PER_MOLE 0x2751 /* Molar Energy */ +#define BLE_GATT_CHR_UNIT_JOULE_PER_MOLE_KELVIN 0x2752 /* Molar Entropy */ +#define BLE_GATT_CHR_UNIT_COULOMB_PER_KILOGRAM 0x2753 /* Exposure */ +#define BLE_GATT_CHR_UNIT_GRAY_PER_SECOND 0x2754 /* Absorbed Dose Rate */ +#define BLE_GATT_CHR_UNIT_WATT_PER_STERADIAN 0x2755 /* Radiant Intensity */ +#define BLE_GATT_CHR_UNIT_WATT_PER_SQUARE_METRE_STERADIAN 0x2756 /* Radiance */ +#define BLE_GATT_CHR_UNIT_KATAL_PER_CUBIC_METRE 0x2757 /* Catalytic Activity Concentration */ +#define BLE_GATT_CHR_UNIT_MINUTE 0x2760 /* Time */ +#define BLE_GATT_CHR_UNIT_HOUR 0x2761 /* Time */ +#define BLE_GATT_CHR_UNIT_DAY 0x2762 /* Time */ +#define BLE_GATT_CHR_UNIT_DEGREE 0x2763 /* Plane Angle */ +#define BLE_GATT_CHR_UNIT_MINUTE_ANGLE 0x2764 /* Plane Angle */ +#define BLE_GATT_CHR_UNIT_SECOND_ANGLE 0x2765 /* Plane Angle */ +#define BLE_GATT_CHR_UNIT_HECTARE 0x2766 /* Area */ +#define BLE_GATT_CHR_UNIT_LITRE 0x2767 /* Volume */ +#define BLE_GATT_CHR_UNIT_TONNE 0x2768 /* Mass */ +#define BLE_GATT_CHR_UNIT_BAR 0x2780 /* Pressure */ +#define BLE_GATT_CHR_UNIT_MILLIMETRE_OF_MERCURY 0x2781 /* Pressure */ +#define BLE_GATT_CHR_UNIT_ANGSTROM 0x2782 /* Length */ +#define BLE_GATT_CHR_UNIT_NAUTICAL_MILE 0x2783 /* Length */ +#define BLE_GATT_CHR_UNIT_BARN 0x2784 /* Area */ +#define BLE_GATT_CHR_UNIT_KNOT 0x2785 /* Velocity */ +#define BLE_GATT_CHR_UNIT_NEPER 0x2786 /* Logarithmic Radio Quantity */ +#define BLE_GATT_CHR_UNIT_BEL 0x2787 /* Logarithmic Radio Quantity */ +#define BLE_GATT_CHR_UNIT_YARD 0x27A0 /* Length */ +#define BLE_GATT_CHR_UNIT_PARSEC 0x27A1 /* Length */ +#define BLE_GATT_CHR_UNIT_INCH 0x27A2 /* Length */ +#define BLE_GATT_CHR_UNIT_FOOT 0x27A3 /* Length */ +#define BLE_GATT_CHR_UNIT_MILE 0x27A4 /* Length */ +#define BLE_GATT_CHR_UNIT_POUND_FORCE_PER_SQUARE_INCH 0x27A5 /* Pressure */ +#define BLE_GATT_CHR_UNIT_KILOMETRE_PER_HOUR 0x27A6 /* Velocity */ +#define BLE_GATT_CHR_UNIT_MILE_PER_HOUR 0x27A7 /* Velocity */ +#define BLE_GATT_CHR_UNIT_REVOLUTION_PER_MINUTE 0x27A8 /* Angular Velocity */ +#define BLE_GATT_CHR_UNIT_GRAM_CALORIE 0x27A9 /* Energy */ +#define BLE_GATT_CHR_UNIT_KILOGRAM_CALORIE 0x27AA /* Energy */ +#define BLE_GATT_CHR_UNIT_KILOWATT_HOUR 0x27AB /* Energy */ +#define BLE_GATT_CHR_UNIT_DEGREE_FAHRENHEIT 0x27AC /* Thermodynamic Temperature */ +#define BLE_GATT_CHR_UNIT_PERCENTAGE 0x27AD /* Percentage */ +#define BLE_GATT_CHR_UNIT_PER_MILLE 0x27AE /* Per Mille */ +#define BLE_GATT_CHR_UNIT_BEATS_PER_MINUTE 0x27AF /* Period */ +#define BLE_GATT_CHR_UNIT_AMPERE_HOURS 0x27B0 /* Electric Charge */ +#define BLE_GATT_CHR_UNIT_MILLIGRAM_PER_DECILITRE 0x27B1 /* Mass Density */ +#define BLE_GATT_CHR_UNIT_MILLIMOLE_PER_LITRE 0x27B2 /* Mass Density */ +#define BLE_GATT_CHR_UNIT_YEAR 0x27B3 /* Time */ +#define BLE_GATT_CHR_UNIT_MONTH 0x27B4 /* Time */ +#define BLE_GATT_CHR_UNIT_COUNT_PER_CUBIC_METRE 0x27B5 /* Concentration */ +#define BLE_GATT_CHR_UNIT_WATT_PER_SQUARE_METRE_IRRADIANCE 0x27B6 /* Irradiance */ +#define BLE_GATT_CHR_UNIT_PER_KILOGRAM_PER_MINUTE 0x27B7 /* Milliliter */ +#define BLE_GATT_CHR_UNIT_POUND 0x27B8 /* Mass */ +#define BLE_GATT_CHR_UNIT_METABOLIC_EQUIVALENT 0x27B9 /* Metabolic Equivalent */ +#define BLE_GATT_CHR_UNIT_PER_MINUTE_STEP 0x27BA /* Step */ +#define BLE_GATT_CHR_UNIT_PER_MINUTE_STROKE 0x27BC /* Stroke */ +#define BLE_GATT_CHR_UNIT_KILOMETRE_PER_MINUTE 0x27BD /* Pace */ +#define BLE_GATT_CHR_UNIT_LUMEN_PER_WATT 0x27BE /* Luminous Efficacy */ +#define BLE_GATT_CHR_UNIT_LUMEN_HOUR 0x27BF /* Luminous Energy */ +#define BLE_GATT_CHR_UNIT_LUX_HOUR 0x27C0 /* Luminous Exposure */ +#define BLE_GATT_CHR_UNIT_GRAM_PER_SECOND 0x27C1 /* Mass Flow */ +#define BLE_GATT_CHR_UNIT_LITRE_PER_SECOND 0x27C2 /* Volume Flow */ +#define BLE_GATT_CHR_UNIT_DECIBEL 0x27C3 /* Sound Pressure */ +#define BLE_GATT_CHR_UNIT_PARTS_PER_MILLION 0x27C4 /* Concentration */ +#define BLE_GATT_CHR_UNIT_PARTS_PER_BILLION 0x27C5 /* Concentration */ +#define BLE_GATT_CHR_UNIT_MILLIGRAM_PER_DECILITRE_PER_MINUTE 0x27C6 /* Mass Density Rate */ +#define BLE_GATT_CHR_UNIT_KILOVOLT_AMPERE_HOUR 0x27C7 /* Electrical Apparent Energy */ +#define BLE_GATT_CHR_UNIT_VOLT_AMPERE 0x27C8 /* Electrical Apparent Power */ + +/** + * Client Presentation Format + * GATT Name Space + * Ref: Assigned Numbers Specification + */ +#define BLE_GATT_CHR_NAMESPACE_BT_SIG 0x01 + +/** + * Client Presentation Format + * GATT Description for Name Space BT_SIG + * Ref: Assigned Numbers Specification + */ +#define BLE_GATT_CHR_BT_SIG_DESC_UNKNOWN 0x0000 +/** 0x0001 - 0x00FF represent themselves. See Ref for more info */ +#define BLE_GATT_CHR_BT_SIG_DESC_FRONT 0x0100 +#define BLE_GATT_CHR_BT_SIG_DESC_BACK 0x0101 +#define BLE_GATT_CHR_BT_SIG_DESC_TOP 0x0102 +#define BLE_GATT_CHR_BT_SIG_DESC_BOTTOM 0x0103 +#define BLE_GATT_CHR_BT_SIG_DESC_UPPER 0x0104 +#define BLE_GATT_CHR_BT_SIG_DESC_LOWER 0x0105 +#define BLE_GATT_CHR_BT_SIG_DESC_MAIN 0x0106 +#define BLE_GATT_CHR_BT_SIG_DESC_BACKUP 0x0107 +#define BLE_GATT_CHR_BT_SIG_DESC_AUXILIARY 0x0108 +#define BLE_GATT_CHR_BT_SIG_DESC_SUPPLEMENTARY 0x0109 +#define BLE_GATT_CHR_BT_SIG_DESC_FLASH 0x010A +#define BLE_GATT_CHR_BT_SIG_DESC_INSIDE 0x010B +#define BLE_GATT_CHR_BT_SIG_DESC_OUTSIDE 0x010C +#define BLE_GATT_CHR_BT_SIG_DESC_LEFT 0x010D +#define BLE_GATT_CHR_BT_SIG_DESC_RIGHT 0x010E +#define BLE_GATT_CHR_BT_SIG_DESC_INTERNAL 0x010F +#define BLE_GATT_CHR_BT_SIG_DESC_EXTERNAL 0x0110 /*** @client. */ /** Represents a GATT error. */ @@ -752,6 +951,9 @@ struct ble_gatt_chr_def { * attribute handle. */ uint16_t *val_handle; + + /** Client Presentation Format Descriptors */ + struct ble_gatt_cpfd *cpfd; }; /** Represents the definition of a GATT service. */ @@ -805,6 +1007,40 @@ struct ble_gatt_dsc_def { void *arg; }; +/** + * Client Presentation Format Descriptor + * Defines the format of the Characteristic Value. + * + * +-------------+------------+ + * | Field Name | Value Size | + * +-------------+------------+ + * | Format | 1 octet | + * | Exponent | 1 octet | + * | Unit | 2 octets | + * | Name Space | 1 octet | + * | Description | 2 octets | + * +-------------+------------+ + */ +struct ble_gatt_cpfd { + /** + * Format of the value of this characteristic. e.g. UINT32 + * Cannot be 0x00. 0x00 represents CPFD array is ended. + */ + uint8_t format; + + /** Exponent field. Multiplies the value to 10^exponent. Type: sint8 */ + int8_t exponent; + + /** The unit of this characteristic. e.g. meters per second */ + uint16_t unit; + + /** The name space of the description. */ + uint8_t namespace; + + /** The description of this characteristic. Depends on name space. */ + uint16_t description; +}; + /** * Context for an access to a GATT characteristic or descriptor. When a client * reads or writes a locally registered characteristic or descriptor, an diff --git a/nimble/host/src/ble_gatt_priv.h b/nimble/host/src/ble_gatt_priv.h index 9a7b32bbc..d4c2bdd24 100644 --- a/nimble/host/src/ble_gatt_priv.h +++ b/nimble/host/src/ble_gatt_priv.h @@ -193,6 +193,18 @@ struct ble_gatt_resources { */ uint16_t cccds; + /** + * Number of client presentation format descriptors. Each of + * these also contributes to the total descriptor count. + */ + uint16_t cpfds; + + /** + * Number of aggregate presentation foramt descriptors. Each of + * these also contributes to the total descriptor count. + */ + uint16_t cafds; + /** Total number of ATT attributes. */ uint16_t attrs; }; diff --git a/nimble/host/src/ble_gatts.c b/nimble/host/src/ble_gatts.c index 0df5a353a..4643fe29c 100644 --- a/nimble/host/src/ble_gatts.c +++ b/nimble/host/src/ble_gatts.c @@ -59,6 +59,10 @@ static const ble_uuid_t *uuid_chr = BLE_UUID16_DECLARE(BLE_ATT_UUID_CHARACTERISTIC); static const ble_uuid_t *uuid_ccc = BLE_UUID16_DECLARE(BLE_GATT_DSC_CLT_CFG_UUID16); +static const ble_uuid_t *uuid_cpf = + BLE_UUID16_DECLARE(BLE_GATT_DSC_CLT_PRE_FMT16); +static const ble_uuid_t *uuid_caf = + BLE_UUID16_DECLARE(BLE_GATT_DSC_CLT_AGG_FMT16); static const struct ble_gatt_svc_def **ble_gatts_svc_defs; static int ble_gatts_num_svc_defs; @@ -736,6 +740,33 @@ ble_gatts_register_dsc(const struct ble_gatt_svc_def *svc, } +static int +ble_gatts_cpfd_is_sane(const struct ble_gatt_cpfd *cpfd) +{ + /** As per Assigned Numbers Specification (2023-09-07) */ + if ((cpfd->format < 0x01) || (cpfd->format > 0x1C)) { + return 0; + } + + if ((cpfd->unit < 0x2700) || + ((cpfd->unit > 0x2707) && (cpfd->unit < 0x2710)) || + (cpfd->unit == 0x271F) || + ((cpfd->unit > 0x2735) && (cpfd->unit < 0x2740)) || + ((cpfd->unit > 0x2757) && (cpfd->unit < 0x2760)) || + ((cpfd->unit > 0x2768) && (cpfd->unit < 0x2780)) || + ((cpfd->unit > 0x2787) && (cpfd->unit < 0x27A0)) || + (cpfd->unit == 0x27BB) || + (cpfd->unit > 0x27C8)) { + return 0; + } + + if ((cpfd->namespace == BLE_GATT_CHR_NAMESPACE_BT_SIG) && (cpfd->description > 0x0110)) { + return 0; + } + + return 1; +} + #if MYNEWT_VAL(BLE_DYNAMIC_SERVICE) static struct ble_gatts_clt_cfg * ble_gatts_clt_cfg_find(struct ble_gatts_clt_cfg_list *ble_gatts_clt_cfgs, @@ -980,6 +1011,110 @@ ble_gatts_register_clt_cfg_dsc(uint16_t *att_handle) return 0; } +static int +ble_gatts_cafd_access(uint16_t conn_handle, uint16_t attr_handle, + uint8_t op, uint16_t offset, struct os_mbuf **om, + void *arg) +{ + struct ble_att_svr_entry * cpfd_entry; + uint16_t handle; + int rc; + + BLE_HS_DBG_ASSERT(op == BLE_ATT_ACCESS_OP_READ); + + STATS_INC(ble_gatts_stats, dsc_reads); + + cpfd_entry = arg; + + /** + * All the Client Presentation Format Descriptors of this characteristic + * are registered just before the Client Aggregate Format Descriptor. + * The handle of the first one is retrieved from arg. + */ + rc = 0; + for (handle = cpfd_entry->ha_handle_id; handle < attr_handle; handle++) { + rc += os_mbuf_append(*om, &handle, sizeof(handle)); + } + + return ((rc == 0) ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES); +} + +static int +ble_gatts_cpfd_access(uint16_t conn_handle, uint16_t attr_handle, + uint8_t op, uint16_t offset, struct os_mbuf **om, + void *arg) +{ + struct ble_gatt_cpfd * cpfd; + int rc; + + BLE_HS_DBG_ASSERT(op == BLE_ATT_ACCESS_OP_READ); + + STATS_INC(ble_gatts_stats, dsc_reads); + + cpfd = arg; + + rc = 0; + rc += os_mbuf_append(*om, &(cpfd->format), sizeof(cpfd->format)); + rc += os_mbuf_append(*om, &(cpfd->exponent), sizeof(cpfd->exponent)); + rc += os_mbuf_append(*om, &(cpfd->unit), sizeof(cpfd->unit)); + rc += os_mbuf_append(*om, &(cpfd->namespace), sizeof(cpfd->namespace)); + rc += os_mbuf_append(*om, &(cpfd->description), sizeof(cpfd->description)); + + return ((rc == 0) ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES); +} + +static int +ble_gatts_register_cpfds(const struct ble_gatt_cpfd *cpfds) +{ + int idx; + int rc; + uint16_t first_cpfd_handle; + struct ble_att_svr_entry * first_cpfd_entry; + + if (cpfds == NULL) { + /** No Client Presentation Format Descriptors to add */ + return 0; + } + + for (idx = 0; cpfds[idx].format != 0; idx++) { + rc = ble_att_svr_register(uuid_cpf, BLE_ATT_F_READ, 0, &first_cpfd_handle, + ble_gatts_cpfd_access, (void *)(cpfds + idx)); + if (rc != 0) { + return rc; + } + + STATS_INC(ble_gatts_stats, dscs); + } + + /** + * Client Aggregate Format Descriptor required if + * more than one CPFDs are registered for the same characteristic + */ + if (idx > 1) { + first_cpfd_handle -= (idx - 1); + first_cpfd_entry = ble_att_svr_find_by_handle(first_cpfd_handle); + if (first_cpfd_entry == NULL) { + return BLE_HS_ENOENT; + } + + /** + * The First CPFD entry will contain it's handle, + * Using that and the handle of this descriptor we can + * find the handles all CPFDs. + */ + rc = ble_att_svr_register(uuid_caf, BLE_ATT_F_READ, 0, NULL, + ble_gatts_cafd_access, (void *)(first_cpfd_entry)); + if (rc != 0) { + return rc; + } + + STATS_INC(ble_gatts_stats, dscs); + } + + return 0; +} + + static int ble_gatts_register_chr(const struct ble_gatt_svc_def *svc, const struct ble_gatt_chr_def *chr, @@ -1048,6 +1183,12 @@ ble_gatts_register_chr(const struct ble_gatt_svc_def *svc, BLE_HS_DBG_ASSERT(dsc_handle == def_handle + 2); } + /* Register each Client Presentation Format Descriptor. */ + rc = ble_gatts_register_cpfds(chr->cpfd); + if (rc != 0) { + return rc; + } + /* Register each descriptor. */ if (chr->descriptors != NULL) { for (dsc = chr->descriptors; dsc->uuid != NULL; dsc++) { @@ -1306,6 +1447,7 @@ ble_gatts_clt_cfg_size(void) } #endif + /** * Handles GATT server clean up for a terminated connection: * o Informs the application that the peer is no longer subscribed to any @@ -2880,6 +3022,7 @@ ble_gatts_count_resources(const struct ble_gatt_svc_def *svcs, int i; int c; int d; + int pf; for (s = 0; svcs[s].type != BLE_GATT_SVC_TYPE_END; s++) { svc = svcs + s; @@ -2954,6 +3097,31 @@ ble_gatts_count_resources(const struct ble_gatt_svc_def *svcs, res->attrs++; } } + + if (chr->cpfd != NULL) { + for (pf = 0; chr->cpfd[pf].format != 0; pf++) { + if (!ble_gatts_cpfd_is_sane(chr->cpfd + pf)) { + BLE_HS_DBG_ASSERT(0); + return BLE_HS_EINVAL; + } + + /** Each CPFD requires: + * o 1 descriptor + * o 1 CPFD + * o 1 attribute + */ + res->dscs++; + res->cpfds++; + res->attrs++; + } + + /** If more than one CPFD is present for a characteristic, one CAFD is required. */ + if (pf > 1) { + res->cafds++; + res->dscs++; + res->attrs++; + } + } } } }