diff --git a/features/FEATURE_BLE/ble/GattClient.h b/features/FEATURE_BLE/ble/GattClient.h index fc60e5c840..828536ffbd 100644 --- a/features/FEATURE_BLE/ble/GattClient.h +++ b/features/FEATURE_BLE/ble/GattClient.h @@ -83,6 +83,38 @@ */ class GattClient { public: + + /** + * Definition of the general handler of GattClient related events. + */ + struct EventHandler { + /** + * Function invoked when the connections changes the ATT_MTU which controls + * the maximum size of an attribute that can be read in a single L2CAP packet + * which might be fragmented across multiple packets. + * + * @param connectionHandle The handle of the connection that changed the size. + * @param attMtuSize + */ + virtual void onAttMtuChange( + ble::connection_handle_t connectionHandle, + uint16_t attMtuSize + ) + { + } + }; + + /** + * Assign the event handler implementation that will be used by the + * module to signal events back to the application. + * + * @param handler Application implementation of an EventHandler. + */ + void setEventHandler(EventHandler *handler) + { + eventHandler = handler; + } + /** * Attribute read event handler. * @@ -635,6 +667,27 @@ public: (void) characteristic; } + /** + * Trigger MTU negotiation. This might result in a Gap event onAttMtuChange + * being called if MTU changes. + * + * @note This does not guarantee a change in MTU size. If size remains + * unchanged no event will be generated. + * + * @param connection Connection on which the MTU is to be negotiated. + * + * @return BLE_ERROR_NONE if the procedure has been launched successfully + * otherwise an appropriate error. + */ + virtual ble_error_t negotiateAttMtu( + ble::connection_handle_t connection + ) { + /* Requesting action from porter(s): override this API if this + capability is supported. */ + (void) connection; + return BLE_ERROR_NOT_IMPLEMENTED; + } + /** * Register an handler for Handle Value Notification/Indication events. * @@ -742,7 +795,7 @@ public: } protected: - GattClient() + GattClient() : eventHandler(NULL) { /* Empty */ } @@ -794,6 +847,11 @@ public: } protected: + /** + * Event handler provided by the application. + */ + EventHandler *eventHandler; + /** * Callchain containing all registered event handlers for data read * events. diff --git a/features/FEATURE_BLE/ble/GattServer.h b/features/FEATURE_BLE/ble/GattServer.h index 3b0d140392..2a1bf417ce 100644 --- a/features/FEATURE_BLE/ble/GattServer.h +++ b/features/FEATURE_BLE/ble/GattServer.h @@ -87,6 +87,38 @@ */ class GattServer { public: + + /** + * Definition of the general handler of GattServer related events. + */ + struct EventHandler { + /** + * Function invoked when the connections changes the ATT_MTU which controls + * the maximum size of an attribute that can be read in a single L2CAP packet + * which might be fragmented across multiple packets. + * + * @param connectionHandle The handle of the connection that changed the size. + * @param attMtuSize + */ + virtual void onAttMtuChange( + ble::connection_handle_t connectionHandle, + uint16_t attMtuSize + ) + { + } + }; + + /** + * Assign the event handler implementation that will be used by the + * module to signal events back to the application. + * + * @param handler Application implementation of an EventHandler. + */ + void setEventHandler(EventHandler *handler) + { + eventHandler = handler; + } + /** * Event handler invoked when the server has sent data to a client. * @@ -166,6 +198,7 @@ protected: GattServer() : serviceCount(0), characteristicCount(0), + eventHandler(NULL), dataSentCallChain(), dataWrittenCallChain(), dataReadCallChain(), @@ -778,6 +811,11 @@ public: } protected: + /** + * Event handler provided by the application. + */ + EventHandler *eventHandler; + /** * The total number of services added to the ATT table. */ diff --git a/features/FEATURE_BLE/ble/gap/Gap.h b/features/FEATURE_BLE/ble/gap/Gap.h index 98f60f4596..93d1957709 100644 --- a/features/FEATURE_BLE/ble/gap/Gap.h +++ b/features/FEATURE_BLE/ble/gap/Gap.h @@ -492,6 +492,26 @@ public: { } + /** + * Function invoked when the connections changes the maximum number of octets + * that can be sent or received by the controller in a single packet. A single + * L2CAP packet can be fragmented across many such packets. + * + * @note This only triggers if controller supports data length extension and + * negotiated data length is longer than the default 23. + * + * @param connectionHandle The handle of the connection that changed the size. + * @param txSize Number of octets we can send on this connection in a single packet. + * @param rxSize Number of octets we can receive on this connection in a single packet. + */ + virtual void onDataLengthChange( + connection_handle_t connectionHandle, + uint16_t txSize, + uint16_t rxSize + ) + { + } + protected: /** * Prevent polymorphic deletion and avoid unnecessary virtual destructor diff --git a/features/FEATURE_BLE/ble/generic/GenericGap.h b/features/FEATURE_BLE/ble/generic/GenericGap.h index b46bcb6716..be0903edc1 100644 --- a/features/FEATURE_BLE/ble/generic/GenericGap.h +++ b/features/FEATURE_BLE/ble/generic/GenericGap.h @@ -627,6 +627,12 @@ private: phy_t rx_phy ); + virtual void on_data_length_change( + connection_handle_t connection_handle, + uint16_t tx_size, + uint16_t rx_size + ); + virtual void on_phy_update_complete( pal::hci_error_code_t hci_status, Handle_t connection_handle, diff --git a/features/FEATURE_BLE/ble/generic/GenericGattClient.h b/features/FEATURE_BLE/ble/generic/GenericGattClient.h index b135535d93..3759e8f1bd 100644 --- a/features/FEATURE_BLE/ble/generic/GenericGattClient.h +++ b/features/FEATURE_BLE/ble/generic/GenericGattClient.h @@ -33,8 +33,23 @@ namespace generic { * @attention: Not part of the public interface of BLE API. */ class GenericGattClient : public GattClient, - public pal::SigningEventMonitor { + public pal::SigningEventMonitor, + public pal::GattClient::EventHandler { public: + + /** + * @see pal::GattClient::EventHandler::on_att_mtu_change + */ + virtual void on_att_mtu_change( + ble::connection_handle_t connection_handle, + uint16_t att_mtu_size + ) + { + if (eventHandler) { + eventHandler->onAttMtuChange(connection_handle, att_mtu_size); + } + } + /** * Create a GenericGattClient from a pal::GattClient */ @@ -111,6 +126,13 @@ public: const DiscoveredCharacteristic& characteristic ); + /** + * @see GattClient::negotiateAttMtu + */ + virtual ble_error_t negotiateAttMtu( + connection_handle_t connection + ); + /** * @see GattClient::reset */ @@ -121,6 +143,14 @@ public: */ virtual void set_signing_event_handler(pal::SigningEventMonitor::EventHandler *signing_event_handler); + /** + * Return the user registered event handler. + * @return User registered event handler or NULL if none is present. + */ + ::GattClient::EventHandler* getEventHandler() { + return eventHandler; + } + private: struct ProcedureControlBlock; struct DiscoveryControlBlock; diff --git a/features/FEATURE_BLE/ble/pal/PalGap.h b/features/FEATURE_BLE/ble/pal/PalGap.h index 39e06f2622..3598fdace2 100644 --- a/features/FEATURE_BLE/ble/pal/PalGap.h +++ b/features/FEATURE_BLE/ble/pal/PalGap.h @@ -44,6 +44,15 @@ struct Gap { ble::phy_t rx_phy ) = 0; + /** + * @copydoc Gap::EventHandler::onDataLengthChange + */ + virtual void on_data_length_change( + connection_handle_t connection_handle, + uint16_t tx_size, + uint16_t rx_size + ) = 0; + /** * @copydoc Gap::EventHandler::onPhyUpdateComplete */ diff --git a/features/FEATURE_BLE/ble/pal/PalGattClient.h b/features/FEATURE_BLE/ble/pal/PalGattClient.h index 2152c428f4..56d72f2b9f 100644 --- a/features/FEATURE_BLE/ble/pal/PalGattClient.h +++ b/features/FEATURE_BLE/ble/pal/PalGattClient.h @@ -55,8 +55,25 @@ namespace pal { * the class AttClientToGattClientAdapter */ class GattClient { - public: + /** + * Definition of the general handler of GattClient related events. + */ + struct EventHandler { + /** + * Function invoked when the connections changes the ATT_MTU which controls + * the maximum size of an attribute that can be read in a single L2CAP packet + * which might be fragmented across multiple packets. + * + * @param connectionHandle The handle of the connection that changed the size. + * @param attMtuSize + */ + virtual void on_att_mtu_change( + ble::connection_handle_t connection_handle, + uint16_t att_mtu_size + ) = 0; + }; + /** * Initialisation of the instance. An implementation can use this function * to initialise the subsystems needed to realize the operations of this @@ -582,8 +599,27 @@ public: _transaction_timeout_cb = cb; } + /** + * Sets the event handler that us called by the PAL porters to notify the stack of events + * which will in turn be passed onto the user application when appropriate. + * + * @param event_handler The new event handler interface implementation. + */ + void set_event_handler(EventHandler* event_handler) { + _event_handler = event_handler; + } + + /** + * Get the currently registered event handler. + * + * @return Currently registered event handler. NULL if no event handler is present. + */ + EventHandler* get_event_handler() { + return _event_handler; + } + protected: - GattClient() { } + GattClient() : _event_handler(NULL) { } virtual ~GattClient() { } @@ -621,6 +657,8 @@ protected: } private: + EventHandler* _event_handler; + /** * Callback called when the client receive a message from the server. */ diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index 4ca9b9df09..26a1cbcb01 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -860,6 +860,17 @@ void GenericGap::on_read_phy( } } +void GenericGap::on_data_length_change( + Handle_t connection_handle, + uint16_t tx_size, + uint16_t rx_size +) +{ + if (_eventHandler) { + _eventHandler->onDataLengthChange(connection_handle, tx_size, rx_size); + } +} + void GenericGap::on_phy_update_complete( pal::hci_error_code_t hci_status, Handle_t connection_handle, diff --git a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp index c89577d988..4ca3616fff 100644 --- a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp @@ -1259,6 +1259,12 @@ void GenericGattClient::terminateCharacteristicDescriptorDiscovery( } +ble_error_t GenericGattClient::negotiateAttMtu( + connection_handle_t connection +) { + return _pal_client->exchange_mtu(connection); +} + ble_error_t GenericGattClient::reset(void) { // _is_reseting prevent executions of new procedure while the instance resets. @@ -1274,7 +1280,7 @@ ble_error_t GenericGattClient::reset(void) { } void GenericGattClient::set_signing_event_handler( - EventHandler *signing_event_handler + pal::SigningEventMonitor::EventHandler *signing_event_handler ) { _signing_event_handler = signing_event_handler; } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h index a8083c3bbe..57596f121a 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h @@ -107,6 +107,13 @@ public: */ virtual generic::GenericGattClient &getGattClient(); + /** + * Get the PAL Gatt Client. + * + * @return PAL Gatt Client. + */ + pal::AttClientToGattClientAdapter &getPalGattClient(); + /** * @see BLEInstanceBase::getSecurityManager */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h index bb9da0dbe5..4979ce6249 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h @@ -62,6 +62,10 @@ public: */ static GattServer &getInstance(); + ::GattServer::EventHandler* getEventHandler() { + return eventHandler; + } + /** * Initialize the GattServer and add mandatory services (generic access and * generic attribute service). diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h index cff00fceea..f646302283 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h @@ -22,6 +22,10 @@ #include "ble/pal/SimpleAttServerMessage.h" #include "att_api.h" #include "att_defs.h" +#include "ble/pal/PalGap.h" +#include "CordioPalGap.h" +#include "PalGattClient.h" +#include "CordioBLE.h" namespace ble { namespace pal { @@ -316,44 +320,7 @@ public: /** * Callback which handle attEvt_t and forward them to on_server_event. */ - static void att_client_handler(const attEvt_t* event) - { - // all handlers are stored in a static array - static const event_handler_t handlers[] = { - &timeout_event_handler, - &event_handler, - &event_handler, - &event_handler, - &event_handler, - &event_handler, - &event_handler, - &event_handler, - &event_handler, - &event_handler, - &event_handler, - &event_handler, - &event_handler, - &event_handler, - &event_handler - }; - - // event->hdr.param: connection handle - // event->header.event: opcode from the request - // event->header.status: success or error code ... - // event->pValue: starting after opcode for response; starting after opcode + handle for server initiated responses. - // event->handle: handle for server initiated responses - - // traverse all handlers and execute them with the event in input. - // exit if an handler has handled the event. - for(size_t i = 0; i < (sizeof(handlers)/sizeof(handlers[0])); ++i) { - if (handlers[i](event)) { - return; - } - } - - // pass events not handled to the server side - ble::vendor::cordio::GattServer::getInstance().att_cb(event); - } + static void att_client_handler(const attEvt_t* event); private: /** @@ -433,25 +400,6 @@ private: } }; - /** - * Converter for an AttExchangeMTUResponse. - */ - struct ExchangeMtuResponseConverter { - static bool can_convert(const attEvt_t* event) - { - if(event->hdr.status == ATT_SUCCESS && - event->hdr.event == ATT_MTU_UPDATE_IND) { - return true; - } - return false; - } - - static AttExchangeMTUResponse convert(const attEvt_t* event) - { - return AttExchangeMTUResponse(event->mtu); - } - }; - /** * Converter for a SimpleAttFindInformationResponse. */ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp index ba57e6bb96..de6dd0bd82 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp @@ -199,13 +199,19 @@ const GattServer& BLE::getGattServer() const } generic::GenericGattClient& BLE::getGattClient() +{ + static generic::GenericGattClient gatt_client(&getPalGattClient()); + + return gatt_client; +} + +pal::AttClientToGattClientAdapter& BLE::getPalGattClient() { static pal::AttClientToGattClientAdapter pal_client( pal::vendor::cordio::CordioAttClient::get_client() ); - static generic::GenericGattClient client(&pal_client); - return client; + return pal_client; } SecurityManager& BLE::getSecurityManager() @@ -286,6 +292,20 @@ void BLE::processEvents() void BLE::device_manager_cb(dmEvt_t* dm_event) { + if (dm_event->hdr.status == HCI_SUCCESS && dm_event->hdr.event == DM_CONN_DATA_LEN_CHANGE_IND) { + // this event can only happen after a connection has been established therefore gap is present + ble::pal::Gap::EventHandler *handler; + handler = ble::pal::vendor::cordio::Gap::get_gap().get_event_handler(); + if (handler) { + handler->on_data_length_change( + dm_event->hdr.param, + dm_event->dataLenChange.maxTxOctets, + dm_event->dataLenChange.maxRxOctets + ); + } + return; + } + BLE::deviceInstance().stack_handler(0, &dm_event->hdr); } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp index 8a096aab26..f3747b0cd6 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp @@ -849,7 +849,12 @@ void GattServer::cccd_cb(attsCccEvt_t *evt) void GattServer::att_cb(const attEvt_t *evt) { - if (evt->hdr.status == ATT_SUCCESS && evt->hdr.event == ATTS_HANDLE_VALUE_CNF) { + if (evt->hdr.status == ATT_SUCCESS && evt->hdr.event == ATT_MTU_UPDATE_IND) { + ::GattServer::EventHandler *handler = getInstance().getEventHandler(); + if (handler) { + handler->onAttMtuChange(evt->hdr.param, evt->mtu); + } + } else if (evt->hdr.status == ATT_SUCCESS && evt->hdr.event == ATTS_HANDLE_VALUE_CNF) { getInstance().handleEvent(GattServerEvents::GATT_EVENT_DATA_SENT, evt->handle); } } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalAttClient.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalAttClient.cpp new file mode 100644 index 0000000000..aa0786dec1 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalAttClient.cpp @@ -0,0 +1,75 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 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. + */ + +#include "CordioPalAttClient.h" +#include "CordioBLE.h" + +namespace ble { +namespace pal { +namespace vendor { +namespace cordio { + +void CordioAttClient::att_client_handler(const attEvt_t* event) +{ + if (event->hdr.status == ATT_SUCCESS && event->hdr.event == ATT_MTU_UPDATE_IND) { + ble::vendor::cordio::BLE& ble = ble::vendor::cordio::BLE::deviceInstance(); + ble::pal::GattClient::EventHandler *handler = ble.getPalGattClient().get_event_handler(); + if (handler) { + handler->on_att_mtu_change(event->hdr.param, event->mtu); + } + } else { + // all handlers are stored in a static array + static const event_handler_t handlers[] = { + &timeout_event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler, + &event_handler + }; + + // event->hdr.param: connection handle + // event->header.event: opcode from the request + // event->header.status: success or error code ... + // event->pValue: starting after opcode for response; starting after opcode + handle for server initiated responses. + // event->handle: handle for server initiated responses + + // traverse all handlers and execute them with the event in input. + // exit if an handler has handled the event. + for(size_t i = 0; i < (sizeof(handlers)/sizeof(handlers[0])); ++i) { + if (handlers[i](event)) { + return; + } + } + } + + // pass events not handled to the server side + ble::vendor::cordio::GattServer::getInstance().att_cb(event); +} + +} // cordio +} // vendor +} // pal +} // ble diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_SOFTDEVICE/TARGET_MCU_NRF51822/source/nRF5xGattServer.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_SOFTDEVICE/TARGET_MCU_NRF51822/source/nRF5xGattServer.h index b2e5f87dea..7cd58b1cf4 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_SOFTDEVICE/TARGET_MCU_NRF51822/source/nRF5xGattServer.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_SOFTDEVICE/TARGET_MCU_NRF51822/source/nRF5xGattServer.h @@ -41,6 +41,9 @@ public: void eventCallback(void); void hwCallback(ble_evt_t *p_ble_evt); + EventHandler* getEventHandler() { + return eventHandler; + } private: const static unsigned BLE_TOTAL_CHARACTERISTICS = 20; diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_SOFTDEVICE/TARGET_NRF51/source/nRF5xGattServer.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_SOFTDEVICE/TARGET_NRF51/source/nRF5xGattServer.h index 6be90ff733..8069c8c5e9 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_SOFTDEVICE/TARGET_NRF51/source/nRF5xGattServer.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_SOFTDEVICE/TARGET_NRF51/source/nRF5xGattServer.h @@ -41,6 +41,9 @@ public: void eventCallback(void); void hwCallback(const ble_evt_t *p_ble_evt); + EventHandler* getEventHandler() { + return eventHandler; + } private: const static unsigned BLE_TOTAL_CHARACTERISTICS = 20; diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_SOFTDEVICE/TARGET_NRF52/source/btle/btle.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_SOFTDEVICE/TARGET_NRF52/source/btle/btle.cpp index 962ddef9b7..7fc6bba930 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_SOFTDEVICE/TARGET_NRF52/source/btle/btle.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_SOFTDEVICE/TARGET_NRF52/source/btle/btle.cpp @@ -26,6 +26,7 @@ #include "ble/GapEvents.h" #include "nRF5xn.h" +#include #ifdef S110 #define IS_LEGACY_DEVICE_MANAGER_ENABLED 1 @@ -334,24 +335,25 @@ void btle_handler(const ble_evt_t *p_ble_evt) #if (NRF_SD_BLE_API_VERSION >= 5) #ifndef S140 // Handle PHY upgrade request - case BLE_GAP_EVT_PHY_UPDATE_REQUEST: + case BLE_GAP_EVT_PHY_UPDATE_REQUEST: { gap.on_phy_update_request( p_ble_evt->evt.gap_evt.conn_handle, p_ble_evt->evt.gap_evt.params.phy_update_request ); break; + } #endif - case BLE_GAP_EVT_PHY_UPDATE: + case BLE_GAP_EVT_PHY_UPDATE: { gap.on_phy_update( p_ble_evt->evt.gap_evt.conn_handle, p_ble_evt->evt.gap_evt.params.phy_update ); break; + } - // Handle Data length negotiation request - case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: - { - ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt; + // Handle Data length negotiation request + case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: { + ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt; uint8_t const data_length_peer = p_gap_evt->params.data_length_update_request.peer_params.max_tx_octets; @@ -360,23 +362,70 @@ void btle_handler(const ble_evt_t *p_ble_evt) data_length_peer ); - ble_gap_data_length_params_t const dlp = - { - /* max_rx_octets */ data_length, - /* max_tx_octets */ data_length + ble_gap_data_length_params_t const dlp = { + /* max_rx_octets */data_length, + /* max_tx_octets */data_length }; ASSERT_STATUS_RET_VOID(sd_ble_gap_data_length_update(p_gap_evt->conn_handle, &dlp, NULL)); - break; + break; } - // Handle MTU exchange request - case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: - { - // Respond with the server MTU - uint16_t conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; + // Handle Data length negotiation result + case BLE_GAP_EVT_DATA_LENGTH_UPDATE: { + /* inform user application */ + if (gap._eventHandler) { + Gap::Handle_t connection = p_ble_evt->evt.gap_evt.conn_handle; + const ble_gap_evt_data_length_update_t &update = + p_ble_evt->evt.gap_evt.params.data_length_update; + + gap._eventHandler->onDataLengthChange( + connection, + update.effective_params.max_tx_octets, + update.effective_params.max_rx_octets + ); + } + break; + } + + case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: { + /* Respond with the server MTU */ + uint16_t conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; ASSERT_STATUS_RET_VOID(sd_ble_gatts_exchange_mtu_reply(conn_handle, NRF_SDH_BLE_GATT_MAX_MTU_SIZE)); - break; + + /* inform user application */ + if (gap._eventHandler) { + Gap::Handle_t connection = p_ble_evt->evt.gap_evt.conn_handle; + const ble_gatts_evt_exchange_mtu_request_t &update = + p_ble_evt->evt.gatts_evt.params.exchange_mtu_request; + + nRF5xGattServer &gatt_server = (nRF5xGattServer&) ble.getGattServer(); + if (gatt_server.getEventHandler()) { + gatt_server.getEventHandler()->onAttMtuChange( + connection, + std::min(NRF_SDH_BLE_GATT_MAX_MTU_SIZE, (int)(update.client_rx_mtu)) + ); + } + } + break; + } + + case BLE_GATTC_EVT_EXCHANGE_MTU_RSP: { + /* inform user application */ + if (gap._eventHandler) { + Gap::Handle_t connection = p_ble_evt->evt.gap_evt.conn_handle; + const ble_gattc_evt_exchange_mtu_rsp_t &update = + p_ble_evt->evt.gattc_evt.params.exchange_mtu_rsp; + + nRF5xGattClient &gatt_client = (nRF5xGattClient&) ble.getGattClient(); + if (gatt_client.get_event_handler()) { + gatt_client.get_event_handler()->on_att_mtu_change( + connection, + std::min(NRF_SDH_BLE_GATT_MAX_MTU_SIZE, (int)(update.server_rx_mtu)) + ); + } + } + break; } #endif case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: { diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_SOFTDEVICE/TARGET_NRF52/source/nRF5xGattServer.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_SOFTDEVICE/TARGET_NRF52/source/nRF5xGattServer.h index 253c2d1446..270a211ac2 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_SOFTDEVICE/TARGET_NRF52/source/nRF5xGattServer.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NORDIC_SOFTDEVICE/TARGET_NRF52/source/nRF5xGattServer.h @@ -41,6 +41,9 @@ public: void eventCallback(void); void hwCallback(const ble_evt_t *p_ble_evt); + EventHandler* getEventHandler() { + return eventHandler; + } private: const static unsigned BLE_TOTAL_CHARACTERISTICS = NRF_SDH_BLE_TOTAL_CHARACTERISTICS;