Caching the advertising data and the scan response.

Fork of MaximBLE by Maxim Integrated

Committer:
enginerd
Date:
Thu Mar 03 14:13:21 2016 +0000
Revision:
0:b562096246b3
Child:
1:4e764337d5c5
Initial commit of Maxim Integrated Bluetooth LE Library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
enginerd 0:b562096246b3 1 /*******************************************************************************
enginerd 0:b562096246b3 2 * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
enginerd 0:b562096246b3 3 *
enginerd 0:b562096246b3 4 * Permission is hereby granted, free of charge, to any person obtaining a
enginerd 0:b562096246b3 5 * copy of this software and associated documentation files (the "Software"),
enginerd 0:b562096246b3 6 * to deal in the Software without restriction, including without limitation
enginerd 0:b562096246b3 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
enginerd 0:b562096246b3 8 * and/or sell copies of the Software, and to permit persons to whom the
enginerd 0:b562096246b3 9 * Software is furnished to do so, subject to the following conditions:
enginerd 0:b562096246b3 10 *
enginerd 0:b562096246b3 11 * The above copyright notice and this permission notice shall be included
enginerd 0:b562096246b3 12 * in all copies or substantial portions of the Software.
enginerd 0:b562096246b3 13 *
enginerd 0:b562096246b3 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
enginerd 0:b562096246b3 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
enginerd 0:b562096246b3 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
enginerd 0:b562096246b3 17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
enginerd 0:b562096246b3 18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
enginerd 0:b562096246b3 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
enginerd 0:b562096246b3 20 * OTHER DEALINGS IN THE SOFTWARE.
enginerd 0:b562096246b3 21 *
enginerd 0:b562096246b3 22 * Except as contained in this notice, the name of Maxim Integrated
enginerd 0:b562096246b3 23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
enginerd 0:b562096246b3 24 * Products, Inc. Branding Policy.
enginerd 0:b562096246b3 25 *
enginerd 0:b562096246b3 26 * The mere transfer of this software does not imply any licenses
enginerd 0:b562096246b3 27 * of trade secrets, proprietary technology, copyrights, patents,
enginerd 0:b562096246b3 28 * trademarks, maskwork rights, or any other form of intellectual
enginerd 0:b562096246b3 29 * property whatsoever. Maxim Integrated Products, Inc. retains all
enginerd 0:b562096246b3 30 * ownership rights.
enginerd 0:b562096246b3 31 *******************************************************************************
enginerd 0:b562096246b3 32 */
enginerd 0:b562096246b3 33
enginerd 0:b562096246b3 34 #include "MaximGap.h"
enginerd 0:b562096246b3 35 #include "mbed.h"
enginerd 0:b562096246b3 36 #include "hci_vs.h"
enginerd 0:b562096246b3 37
enginerd 0:b562096246b3 38 MaximGap &MaximGap::getInstance() {
enginerd 0:b562096246b3 39 static MaximGap m_instance;
enginerd 0:b562096246b3 40 return m_instance;
enginerd 0:b562096246b3 41 }
enginerd 0:b562096246b3 42
enginerd 0:b562096246b3 43 ble_error_t MaximGap::setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse)
enginerd 0:b562096246b3 44 {
enginerd 0:b562096246b3 45 /* Make sure we don't exceed the advertising payload length */
enginerd 0:b562096246b3 46 if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD) {
enginerd 0:b562096246b3 47 return BLE_ERROR_BUFFER_OVERFLOW;
enginerd 0:b562096246b3 48 }
enginerd 0:b562096246b3 49
enginerd 0:b562096246b3 50 /* Make sure we have a payload! */
enginerd 0:b562096246b3 51 if (advData.getPayloadLen() == 0) {
enginerd 0:b562096246b3 52 return BLE_ERROR_PARAM_OUT_OF_RANGE;
enginerd 0:b562096246b3 53 }
enginerd 0:b562096246b3 54
enginerd 0:b562096246b3 55 /* set advertising and scan response data for discoverable mode */
enginerd 0:b562096246b3 56 DmAdvSetData(DM_DATA_LOC_ADV, advData.getPayloadLen(), (uint8_t*)advData.getPayload());
enginerd 0:b562096246b3 57 DmAdvSetData(DM_DATA_LOC_SCAN, scanResponse.getPayloadLen(), (uint8_t*)scanResponse.getPayload());
enginerd 0:b562096246b3 58
enginerd 0:b562096246b3 59 return BLE_ERROR_NONE;
enginerd 0:b562096246b3 60 }
enginerd 0:b562096246b3 61
enginerd 0:b562096246b3 62 ble_error_t MaximGap::startAdvertising(const GapAdvertisingParams &params)
enginerd 0:b562096246b3 63 {
enginerd 0:b562096246b3 64 /* Make sure we support the advertising type */
enginerd 0:b562096246b3 65 if (params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) {
enginerd 0:b562096246b3 66 /* ToDo: This requires a proper security implementation, etc. */
enginerd 0:b562096246b3 67 return BLE_ERROR_NOT_IMPLEMENTED;
enginerd 0:b562096246b3 68 }
enginerd 0:b562096246b3 69
enginerd 0:b562096246b3 70 /* Check interval range */
enginerd 0:b562096246b3 71 if (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED) {
enginerd 0:b562096246b3 72 /* Min delay is slightly longer for unconnectable devices */
enginerd 0:b562096246b3 73 if ((params.getInterval() < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN_NONCON) ||
enginerd 0:b562096246b3 74 (params.getInterval() > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) {
enginerd 0:b562096246b3 75 return BLE_ERROR_PARAM_OUT_OF_RANGE;
enginerd 0:b562096246b3 76 }
enginerd 0:b562096246b3 77 } else {
enginerd 0:b562096246b3 78 if ((params.getInterval() < GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MIN) ||
enginerd 0:b562096246b3 79 (params.getInterval() > GapAdvertisingParams::GAP_ADV_PARAMS_INTERVAL_MAX)) {
enginerd 0:b562096246b3 80 return BLE_ERROR_PARAM_OUT_OF_RANGE;
enginerd 0:b562096246b3 81 }
enginerd 0:b562096246b3 82 }
enginerd 0:b562096246b3 83
enginerd 0:b562096246b3 84 /* Check timeout is zero for Connectable Directed */
enginerd 0:b562096246b3 85 if ((params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) && (params.getTimeout() != 0)) {
enginerd 0:b562096246b3 86 /* Timeout must be 0 with this type, although we'll never get here */
enginerd 0:b562096246b3 87 /* since this isn't implemented yet anyway */
enginerd 0:b562096246b3 88 return BLE_ERROR_PARAM_OUT_OF_RANGE;
enginerd 0:b562096246b3 89 }
enginerd 0:b562096246b3 90
enginerd 0:b562096246b3 91 /* Check timeout for other advertising types */
enginerd 0:b562096246b3 92 if ((params.getAdvertisingType() != GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) &&
enginerd 0:b562096246b3 93 (params.getTimeout() > GapAdvertisingParams::GAP_ADV_PARAMS_TIMEOUT_MAX)) {
enginerd 0:b562096246b3 94 return BLE_ERROR_PARAM_OUT_OF_RANGE;
enginerd 0:b562096246b3 95 }
enginerd 0:b562096246b3 96
enginerd 0:b562096246b3 97 DmAdvSetInterval(params.getInterval(), params.getInterval());
enginerd 0:b562096246b3 98 DmAdvStart(params.getAdvertisingType(), params.getTimeout());
enginerd 0:b562096246b3 99
enginerd 0:b562096246b3 100 state.advertising = 1;
enginerd 0:b562096246b3 101
enginerd 0:b562096246b3 102 return BLE_ERROR_NONE;
enginerd 0:b562096246b3 103 }
enginerd 0:b562096246b3 104
enginerd 0:b562096246b3 105 ble_error_t MaximGap::stopAdvertising(void)
enginerd 0:b562096246b3 106 {
enginerd 0:b562096246b3 107 DmAdvStop();
enginerd 0:b562096246b3 108
enginerd 0:b562096246b3 109 state.advertising = 0;
enginerd 0:b562096246b3 110
enginerd 0:b562096246b3 111 return BLE_ERROR_NONE;
enginerd 0:b562096246b3 112 }
enginerd 0:b562096246b3 113
enginerd 0:b562096246b3 114 void MaximGap::advertisingStopped(void)
enginerd 0:b562096246b3 115 {
enginerd 0:b562096246b3 116 /* If advertising stopped due to a call to stopAdvertising(), state.advertising will
enginerd 0:b562096246b3 117 * be '0.' Otherwise, advertising must have stopped due to a timeout
enginerd 0:b562096246b3 118 */
enginerd 0:b562096246b3 119 if (state.advertising) {
enginerd 0:b562096246b3 120 processTimeoutEvent(Gap::TIMEOUT_SRC_ADVERTISING);
enginerd 0:b562096246b3 121 }
enginerd 0:b562096246b3 122 }
enginerd 0:b562096246b3 123
enginerd 0:b562096246b3 124 ble_error_t MaximGap::disconnect(DisconnectionReason_t reason)
enginerd 0:b562096246b3 125 {
enginerd 0:b562096246b3 126 DmConnClose(DM_CLIENT_ID_APP, m_connectionHandle, reason);
enginerd 0:b562096246b3 127
enginerd 0:b562096246b3 128 state.advertising = 0;
enginerd 0:b562096246b3 129 state.connected = 0;
enginerd 0:b562096246b3 130
enginerd 0:b562096246b3 131 return BLE_ERROR_NONE;
enginerd 0:b562096246b3 132 }
enginerd 0:b562096246b3 133
enginerd 0:b562096246b3 134 ble_error_t MaximGap::disconnect(Handle_t connectionHandle, DisconnectionReason_t reason)
enginerd 0:b562096246b3 135 {
enginerd 0:b562096246b3 136 DmConnClose(DM_CLIENT_ID_APP, connectionHandle, reason);
enginerd 0:b562096246b3 137
enginerd 0:b562096246b3 138 state.advertising = 0;
enginerd 0:b562096246b3 139 state.connected = 0;
enginerd 0:b562096246b3 140
enginerd 0:b562096246b3 141 return BLE_ERROR_NONE;
enginerd 0:b562096246b3 142 }
enginerd 0:b562096246b3 143
enginerd 0:b562096246b3 144 ble_error_t MaximGap::getPreferredConnectionParams(ConnectionParams_t *params)
enginerd 0:b562096246b3 145 {
enginerd 0:b562096246b3 146 return BLE_ERROR_NOT_IMPLEMENTED;
enginerd 0:b562096246b3 147 }
enginerd 0:b562096246b3 148
enginerd 0:b562096246b3 149 ble_error_t MaximGap::setPreferredConnectionParams(const ConnectionParams_t *params)
enginerd 0:b562096246b3 150 {
enginerd 0:b562096246b3 151 return BLE_ERROR_NOT_IMPLEMENTED;
enginerd 0:b562096246b3 152 }
enginerd 0:b562096246b3 153
enginerd 0:b562096246b3 154 ble_error_t MaximGap::updateConnectionParams(Handle_t handle, const ConnectionParams_t *newParams)
enginerd 0:b562096246b3 155 {
enginerd 0:b562096246b3 156 if (DmConnCheckIdle(handle) != 0) {
enginerd 0:b562096246b3 157 return BLE_STACK_BUSY;
enginerd 0:b562096246b3 158 }
enginerd 0:b562096246b3 159
enginerd 0:b562096246b3 160 hciConnSpec_t connSpec;
enginerd 0:b562096246b3 161 connSpec.connIntervalMin = newParams->minConnectionInterval;
enginerd 0:b562096246b3 162 connSpec.connIntervalMax = newParams->maxConnectionInterval;
enginerd 0:b562096246b3 163 connSpec.connLatency = newParams->slaveLatency;
enginerd 0:b562096246b3 164 connSpec.supTimeout = newParams->connectionSupervisionTimeout;
enginerd 0:b562096246b3 165 DmConnUpdate(handle, &connSpec);
enginerd 0:b562096246b3 166
enginerd 0:b562096246b3 167 return BLE_ERROR_NONE;
enginerd 0:b562096246b3 168 }
enginerd 0:b562096246b3 169
enginerd 0:b562096246b3 170 ble_error_t MaximGap::startRadioScan(const GapScanningParams &scanningParams)
enginerd 0:b562096246b3 171 {
enginerd 0:b562096246b3 172 DmScanSetInterval(scanningParams.getInterval(), scanningParams.getWindow());
enginerd 0:b562096246b3 173
enginerd 0:b562096246b3 174 uint8_t scanType = scanningParams.getActiveScanning() ? DM_SCAN_TYPE_ACTIVE : DM_SCAN_TYPE_PASSIVE;
enginerd 0:b562096246b3 175 uint32_t duration = (uint32_t)scanningParams.getTimeout() * 1000;
enginerd 0:b562096246b3 176 if (duration > 0xFFFF) {
enginerd 0:b562096246b3 177 // saturate to 16-bits
enginerd 0:b562096246b3 178 duration = 0xFFFF;
enginerd 0:b562096246b3 179 }
enginerd 0:b562096246b3 180
enginerd 0:b562096246b3 181 DmScanStart(DM_DISC_MODE_NONE, scanType, TRUE, duration);
enginerd 0:b562096246b3 182
enginerd 0:b562096246b3 183 return BLE_ERROR_NONE;
enginerd 0:b562096246b3 184 }
enginerd 0:b562096246b3 185
enginerd 0:b562096246b3 186 ble_error_t MaximGap::stopScan(void)
enginerd 0:b562096246b3 187 {
enginerd 0:b562096246b3 188 DmScanStop();
enginerd 0:b562096246b3 189 return BLE_ERROR_NONE;
enginerd 0:b562096246b3 190 }
enginerd 0:b562096246b3 191
enginerd 0:b562096246b3 192 void MaximGap::setConnectionHandle(uint16_t connectionHandle)
enginerd 0:b562096246b3 193 {
enginerd 0:b562096246b3 194 m_connectionHandle = connectionHandle;
enginerd 0:b562096246b3 195 }
enginerd 0:b562096246b3 196
enginerd 0:b562096246b3 197 uint16_t MaximGap::getConnectionHandle(void)
enginerd 0:b562096246b3 198 {
enginerd 0:b562096246b3 199 return m_connectionHandle;
enginerd 0:b562096246b3 200 }
enginerd 0:b562096246b3 201
enginerd 0:b562096246b3 202 ble_error_t MaximGap::setAddress(AddressType_t type, const Address_t address)
enginerd 0:b562096246b3 203 {
enginerd 0:b562096246b3 204 if ((type != ADDR_TYPE_PUBLIC) && (type != ADDR_TYPE_RANDOM_STATIC)) {
enginerd 0:b562096246b3 205 return BLE_ERROR_PARAM_OUT_OF_RANGE;
enginerd 0:b562096246b3 206 }
enginerd 0:b562096246b3 207
enginerd 0:b562096246b3 208 m_type = type;
enginerd 0:b562096246b3 209 HciVsSetPublicAddr((uint8_t*)address);
enginerd 0:b562096246b3 210
enginerd 0:b562096246b3 211 return BLE_ERROR_NONE;
enginerd 0:b562096246b3 212 }
enginerd 0:b562096246b3 213
enginerd 0:b562096246b3 214 ble_error_t MaximGap::getAddress(AddressType_t *typeP, Address_t address)
enginerd 0:b562096246b3 215 {
enginerd 0:b562096246b3 216 *typeP = m_type;
enginerd 0:b562096246b3 217 BdaCpy(address, HciGetBdAddr());
enginerd 0:b562096246b3 218 return BLE_ERROR_NONE;
enginerd 0:b562096246b3 219 }
enginerd 0:b562096246b3 220
enginerd 0:b562096246b3 221 ble_error_t MaximGap::setDeviceName(const uint8_t *deviceName)
enginerd 0:b562096246b3 222 {
enginerd 0:b562096246b3 223 return BLE_ERROR_NOT_IMPLEMENTED;
enginerd 0:b562096246b3 224 }
enginerd 0:b562096246b3 225
enginerd 0:b562096246b3 226 ble_error_t MaximGap::getDeviceName(uint8_t *deviceName, unsigned *lengthP)
enginerd 0:b562096246b3 227 {
enginerd 0:b562096246b3 228 return BLE_ERROR_NOT_IMPLEMENTED;
enginerd 0:b562096246b3 229 }
enginerd 0:b562096246b3 230
enginerd 0:b562096246b3 231 ble_error_t MaximGap::setAppearance(GapAdvertisingData::Appearance appearance)
enginerd 0:b562096246b3 232 {
enginerd 0:b562096246b3 233 return BLE_ERROR_NOT_IMPLEMENTED;
enginerd 0:b562096246b3 234 }
enginerd 0:b562096246b3 235
enginerd 0:b562096246b3 236 ble_error_t MaximGap::getAppearance(GapAdvertisingData::Appearance *appearanceP)
enginerd 0:b562096246b3 237 {
enginerd 0:b562096246b3 238 return BLE_ERROR_NOT_IMPLEMENTED;
enginerd 0:b562096246b3 239 }
enginerd 0:b562096246b3 240
enginerd 0:b562096246b3 241 ble_error_t MaximGap::setTxPower(int8_t txPower)
enginerd 0:b562096246b3 242 {
enginerd 0:b562096246b3 243 HciVsSetTxPower(txPower);
enginerd 0:b562096246b3 244 return BLE_ERROR_NONE;
enginerd 0:b562096246b3 245 }
enginerd 0:b562096246b3 246
enginerd 0:b562096246b3 247 void MaximGap::getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP)
enginerd 0:b562096246b3 248 {
enginerd 0:b562096246b3 249 static const int8_t permittedTxValues[] = {
enginerd 0:b562096246b3 250 -18, -15, -12, -9, -6, -3, 0, 3
enginerd 0:b562096246b3 251 };
enginerd 0:b562096246b3 252
enginerd 0:b562096246b3 253 *valueArrayPP = permittedTxValues;
enginerd 0:b562096246b3 254 *countP = sizeof(permittedTxValues) / sizeof(int8_t);
enginerd 0:b562096246b3 255 }