uint32_t conn_mw_ble_gatts_service_changed(uint8_t const * const p_rx_buf, uint32_t rx_buf_len, uint8_t * const p_tx_buf, uint32_t * const p_tx_buf_len) { SER_ASSERT_NOT_NULL(p_rx_buf); SER_ASSERT_NOT_NULL(p_tx_buf); SER_ASSERT_NOT_NULL(p_tx_buf_len); uint16_t conn_handle; uint16_t start_handle; uint16_t end_handle; uint32_t err_code = NRF_SUCCESS; uint32_t sd_err_code; err_code = ble_gatts_service_changed_req_dec(p_rx_buf, rx_buf_len, &conn_handle, &start_handle, &end_handle); SER_ASSERT(err_code == NRF_SUCCESS, err_code); sd_err_code = sd_ble_gatts_service_changed(conn_handle, start_handle, end_handle); err_code = ble_gatts_service_changed_rsp_enc(sd_err_code, p_tx_buf, p_tx_buf_len); SER_ASSERT(err_code == NRF_SUCCESS, err_code); return err_code; }
/**@brief Function updating Service Changed CCCD and indicate a service change to peer. * * @details This function will verify the CCCD setting provided with \ref m_ble_peer_data and * update the system attributes accordingly. If Service Change CCCD is set to indicate * then a service change indication will be send to the peer. * * @retval NRF_INVALID_STATE if no connection has been established to a central. * @return Any error code returned by SoftDevice function calls. */ static uint32_t service_change_indicate() { uint32_t err_code; if (m_conn_handle == BLE_CONN_HANDLE_INVALID) { return NRF_ERROR_INVALID_STATE; } if (m_ble_peer_data_valid) { err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, m_ble_peer_data.sys_serv_attr, sizeof(m_ble_peer_data.sys_serv_attr), BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS); if (err_code != NRF_SUCCESS) { return err_code; } err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS); if (err_code != NRF_SUCCESS) { return err_code; } err_code = sd_ble_gatts_service_changed(m_conn_handle, DFU_SERVICE_HANDLE, BLE_HANDLE_MAX); if ((err_code == BLE_ERROR_INVALID_CONN_HANDLE) || (err_code == NRF_ERROR_INVALID_STATE) || (err_code == BLE_ERROR_NO_TX_BUFFERS)) { // Those errors can be expected when sending trying to send Service Changed Indication // if the CCCD is not set to indicate. Thus set the returning error code to success. err_code = NRF_SUCCESS; } } else { err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0); } return err_code; }
/** * Callback when a BLE SYS_ATTR_MISSING. */ static void bleSysAttrMissingCallback(const GattSysAttrMissingCallbackParams *params) { int complete = 0; deviceID = 255; dm_handle_t dm_handle = {0,0,0,0}; int ret = dm_handle_get(params->connHandle, &dm_handle); if (ret == 0) deviceID = dm_handle.device_id; if(manager->storage != NULL && deviceID < MICROBIT_BLE_MAXIMUM_BONDS) { ManagedString key("bleSysAttrs"); KeyValuePair* bleSysAttrs = manager->storage->get(key); BLESysAttributeStore attribStore; BLESysAttribute attrib; if(bleSysAttrs != NULL) { //restore our sysAttrStore memcpy(&attribStore, bleSysAttrs->value, sizeof(BLESysAttributeStore)); delete bleSysAttrs; attrib = attribStore.sys_attrs[deviceID]; ret = sd_ble_gatts_sys_attr_set(params->connHandle, attrib.sys_attr, sizeof(attrib.sys_attr), BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS); complete = 1; if(ret == 0) ret = sd_ble_gatts_service_changed(params->connHandle, 0x000c, 0xffff); } } if (!complete) sd_ble_gatts_sys_attr_set(params->connHandle, NULL, 0, 0); }
/** * Callback when a BLE GATT connect occurs. */ static void bleConnectionCallback(const Gap::ConnectionCallbackParams_t *reason) { // configure the stack to hold on to CPU during critical timing events. // mbed-classic performs __disabe_irq calls in its timers, which can cause MIC failures // on secure BLE channels. ble_common_opt_radio_cpu_mutex_t opt; opt.enable = 1; sd_ble_opt_set(BLE_COMMON_OPT_RADIO_CPU_MUTEX, (const ble_opt_t *)&opt); // Ensure that there's no stale, cached information in the client... invalidate all characteristics. uint16_t len = 8; // Configure the ServiceChanged characteristic to receive service changed indications // TODO: This is really a workaround as we can't maintain persistent state on the micro:bit across USB // reprogramming flashes.... yet. uint8_t data[] = {0x0B,0x00,0x02,0x00,0x02,0x00,0xB8,0x46}; sd_ble_gatts_sys_attr_set(reason->handle, data, len, BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS); sd_ble_gatts_service_changed(reason->handle, 0x000c, 0xffff); }
/**@brief Function for loading application-specific context after establishing a secure connection. * * @details This function will load the application context and check if the ATT table is marked as * changed. If the ATT table is marked as changed, a Service Changed Indication * is sent to the peer if the Service Changed CCCD is set to indicate. * * @param[in] p_handle The Device Manager handle that identifies the connection for which the context * should be loaded. */ static void app_context_load(dm_handle_t const * p_handle) { uint32_t err_code; static uint32_t context_data; dm_application_context_t context; context.len = sizeof(context_data); context.p_data = (uint8_t *)&context_data; err_code = dm_application_context_get(p_handle, &context); if (err_code == NRF_SUCCESS) { // Send Service Changed Indication if ATT table has changed. if ((context_data & (DFU_APP_ATT_TABLE_CHANGED << DFU_APP_ATT_TABLE_POS)) != 0) { err_code = sd_ble_gatts_service_changed(m_conn_handle, APP_SERVICE_HANDLE_START, BLE_HANDLE_MAX); if ((err_code != NRF_SUCCESS) && (err_code != BLE_ERROR_INVALID_CONN_HANDLE) && (err_code != NRF_ERROR_INVALID_STATE) && (err_code != BLE_ERROR_NO_TX_PACKETS) && (err_code != NRF_ERROR_BUSY) && (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)) { APP_ERROR_HANDLER(err_code); } } err_code = dm_application_context_delete(p_handle); APP_ERROR_CHECK(err_code); } else if (err_code == DM_NO_APP_CONTEXT) { // No context available. Ignore. } else { APP_ERROR_HANDLER(err_code); } }