Newer
Older
mbed-os / connectivity / FEATURE_BLE / include / ble / internal / cordio / CordioGattServer.h
@Paul Szczeanek Paul Szczeanek on 7 Aug 2020 10 KB remove generic, TPPs, nested namespaces
/* mbed Microcontroller Library
 * Copyright (c) 2006-2020 ARM Limited
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef MBED_CORDIO_GATT_SERVER_H__
#define MBED_CORDIO_GATT_SERVER_H__

#include "CallChainOfFunctionPointersWithContext.h"

#include "ble/types/GattService.h"
#include "ble/types/GattAttribute.h"
#include "ble/types/GattServerEvents.h"
#include "ble/types/GattCallbackParamTypes.h"

#include <stddef.h>
#include "ble/types/blecommon.h"
#include "ble/Gap.h"
#include "wsf_types.h"
#include "att_api.h"
#include "SecurityManager.h"

#include "ble/BLE.h"
#include "ble/types/GattCallbackParamTypes.h"
#include "ble/internal/cordio/CordioPalSigningMonitor.h"

/*! Maximum count of characteristics that can be stored for authorisation purposes */
#define MAX_CHARACTERISTIC_AUTHORIZATION_CNT 20

/*! client characteristic configuration descriptors settings */
#define MAX_CCCD_CNT 20

namespace ble {

// fwd declaration of PalAttClient and BLE
class PalAttClient;
class BLE;

class GattServer :
    public ble::interface::GattServer,
    public PalSigningMonitor
{
    friend ble::BLE;
    friend ble::PalAttClient;
    friend PalSigningMonitor;
    friend CordioBLEInstanceBase;
    friend PalGenericAccessService;

// inherited typedefs have the wrong types so we have to redefine them
public:

    typedef FunctionPointerWithContext<const GattServer *>
        GattServerShutdownCallback_t;

    typedef CallChainOfFunctionPointersWithContext<const GattServer*>
        GattServerShutdownCallbackChain_t;
public:

    void setEventHandler(EventHandler *handler);

    ble_error_t reset(void);

    ble_error_t addService(GattService &service);

    ble_error_t read(
        GattAttribute::Handle_t attributeHandle,
        uint8_t buffer[],
        uint16_t *lengthP
    );

    ble_error_t read(
        ble::connection_handle_t connectionHandle,
        GattAttribute::Handle_t attributeHandle,
        uint8_t *buffer,
        uint16_t *lengthP
    );

    ble_error_t write(
        GattAttribute::Handle_t attributeHandle,
        const uint8_t *value,
        uint16_t size,
        bool localOnly = false
    );

    ble_error_t write(
        ble::connection_handle_t connectionHandle,
        GattAttribute::Handle_t attributeHandle,
        const uint8_t *value,
        uint16_t size,
        bool localOnly = false
    );

    ble_error_t areUpdatesEnabled(
        const GattCharacteristic &characteristic,
        bool *enabledP
    );

    ble_error_t areUpdatesEnabled(
        ble::connection_handle_t connectionHandle,
        const GattCharacteristic &characteristic,
        bool *enabledP
    );

    Gap::PreferredConnectionParams_t getPreferredConnectionParams();

    void setPreferredConnectionParams(const Gap::PreferredConnectionParams_t& params);

    bool isOnDataReadAvailable() const;

    void onDataSent(const DataSentCallback_t &callback);

    template <typename T>
    void onDataSent(T *objPtr, void (T::*memberPtr)(unsigned count));

    DataSentCallbackChain_t &onDataSent();

    void onDataWritten(const DataWrittenCallback_t &callback) {
        dataWrittenCallChain.add(callback);
    }

    template <typename T>
    void onDataWritten(
        T *objPtr,
        void (T::*memberPtr)(const GattWriteCallbackParams *context)
    ) {
        dataWrittenCallChain.add(objPtr, memberPtr);
    };

    DataWrittenCallbackChain_t &onDataWritten();

    ble_error_t onDataRead(const DataReadCallback_t &callback);

    template <typename T>
    ble_error_t onDataRead(
        T *objPtr,
        void (T::*memberPtr)(const GattReadCallbackParams *context)
    );

    DataReadCallbackChain_t &onDataRead();

    void onShutdown(const GattServerShutdownCallback_t &callback);

    template <typename T>
    void onShutdown(T *objPtr, void (T::*memberPtr)(const GattServer *));

    GattServerShutdownCallbackChain_t& onShutdown();

    void onUpdatesEnabled(EventCallback_t callback);

    void onUpdatesDisabled(EventCallback_t callback);

    void onConfirmationReceived(EventCallback_t callback);

    /* Entry points for the underlying stack to report events back to the user. */
protected:

    void handleDataWrittenEvent(const GattWriteCallbackParams *params);

    void handleDataReadEvent(const GattReadCallbackParams *params);

    void handleEvent(
        GattServerEvents::gattEvent_e type,
        GattAttribute::Handle_t attributeHandle
    );

    void handleDataSentEvent(unsigned count);

    /* ===================================================================== */
    /*                    private implementation follows                     */

#if 0 // Disabled until reworked and reintroduced to GattServer API
public:
    /**
     * @see ble::GattServer::setDeviceName
     */
    ble_error_t setDeviceName(const uint8_t *deviceName);

    /**
     * @see ble::GattServer::getDeviceName
     */
    void getDeviceName(const uint8_t*& name, uint16_t& length);

    /**
     * @see ble::GattServer::setAppearance
     */
    void setAppearance(GapAdvertisingData::Appearance appearance);

    /**
     * @see ble::GattServer::getAppearance
     */
    GapAdvertisingData::Appearance getAppearance();

#endif // Disabled until reworked and reintroduced to GattServer API

private:
    GattServer();

    GattServer(const GattServer &);
    const GattServer& operator=(const GattServer &);

    /**
     * Return the singleton of the Cordio implementation of ble::GattServer.
     */
    static GattServer &getInstance();

    /**
     * Initialize the GattServer and add mandatory services (generic access and
     * generic attribute service).
     */
    void initialize();

    void set_signing_event_handler(
        PalSigningMonitorEventHandler *signing_event_handler
    );

    EventHandler* getEventHandler();

    void add_default_services();

    static uint16_t compute_attributes_count(GattService& service);

    void insert_service_attribute(
        GattService& service,
        attsAttr_t *&attribute_it
    );

    ble_error_t insert_characteristic(
        GattCharacteristic *characteristic,
        attsAttr_t *&attribute_it
    );

    bool is_characteristic_valid(GattCharacteristic *characteristic);

    void insert_characteristic_declaration_attribute(
        GattCharacteristic *characteristic,
        attsAttr_t *&attribute_it
    );

    ble_error_t insert_characteristic_value_attribute(
        GattCharacteristic *characteristic,
        attsAttr_t *&attribute_it
    );

    ble_error_t insert_descriptor(
        GattCharacteristic *characteristic,
        GattAttribute* descriptor,
        attsAttr_t *&attribute_it,
        bool& cccd_created
    );

    ble_error_t insert_cccd(
        GattCharacteristic *characteristic,
        attsAttr_t *&attribute_it
    );

    static void cccd_cb(attsCccEvt_t *pEvt);
    static void att_cb(const attEvt_t *pEvt);
    static uint8_t atts_read_cb(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr);
    static uint8_t atts_write_cb(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr);
    static uint8_t atts_auth_cb(dmConnId_t connId, uint8_t permit, uint16_t handle);
    void add_generic_access_service();
    void add_generic_attribute_service();
    void* alloc_block(size_t block_size);
    GattCharacteristic* get_auth_char(uint16_t value_handle);
    bool get_cccd_index_by_cccd_handle(GattAttribute::Handle_t cccd_handle, uint8_t& idx) const;
    bool get_cccd_index_by_value_handle(GattAttribute::Handle_t char_handle, uint8_t& idx) const;
    bool is_update_authorized(connection_handle_t connection, GattAttribute::Handle_t value_handle);

    struct alloc_block_t {
        alloc_block_t* next;
        uint8_t data[1];
    };

    struct internal_service_t {
        attsGroup_t attGroup;
        internal_service_t *next;
    };

private:
    /**
     * Event handler provided by the application.
     */
    EventHandler *eventHandler;

    /**
     * The total number of services added to the ATT table.
     */
    uint8_t serviceCount;

    /**
     * The total number of characteristics added to the ATT table.
     */
    uint8_t characteristicCount;

    /**
     * Callchain containing all registered callback handlers for data sent
     * events.
     */
    DataSentCallbackChain_t dataSentCallChain;

    /**
     * Callchain containing all registered callback handlers for data written
     * events.
     */
    DataWrittenCallbackChain_t dataWrittenCallChain;

    /**
     * Callchain containing all registered callback handlers for data read
     * events.
     */
    DataReadCallbackChain_t dataReadCallChain;

    /**
     * Callchain containing all registered callback handlers for shutdown
     * events.
     */
    GattServerShutdownCallbackChain_t shutdownCallChain;

    /**
     * The registered callback handler for updates enabled events.
     */
    EventCallback_t updatesEnabledCallback;

    /**
     * The registered callback handler for updates disabled events.
     */
    EventCallback_t updatesDisabledCallback;

    /**
     * The registered callback handler for confirmation received events.
     */
    EventCallback_t confirmationReceivedCallback;

    PalSigningMonitorEventHandler *_signing_event_handler;

    attsCccSet_t cccds[MAX_CCCD_CNT];
    uint16_t cccd_values[MAX_CCCD_CNT];
    uint16_t cccd_handles[MAX_CCCD_CNT];
    uint8_t cccd_cnt;

    GattCharacteristic *_auth_char[MAX_CHARACTERISTIC_AUTHORIZATION_CNT];
    uint8_t _auth_char_count;

    struct {
        attsGroup_t service;
        attsAttr_t attributes[7];
        uint8_t device_name_declaration_value[5];
        uint16_t device_name_length;
        uint8_t appearance_declaration_value[5];
        uint16_t appearance;
        uint8_t ppcp_declaration_value[5];
        uint8_t ppcp[8];

        uint8_t*& device_name_value() {
            return attributes[2].pValue;
        }
    } generic_access_service;

    struct {
        attsGroup_t service;
        attsAttr_t attributes[4];
        uint8_t service_changed_declaration[5];
    } generic_attribute_service;

    internal_service_t* registered_service;
    alloc_block_t* allocated_blocks;

    uint16_t currentHandle;

    bool default_services_added;
};

} // ble

#endif /* ifndef MBED_CORDIO_GATT_SERVER_H__ */