mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Committer:
be_bryan
Date:
Mon Dec 11 17:54:04 2017 +0000
Revision:
0:b74591d5ab33
motor ++

Who changed what in which revision?

UserRevisionLine numberNew contents of line
be_bryan 0:b74591d5ab33 1 /*******************************************************************************
be_bryan 0:b74591d5ab33 2 * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
be_bryan 0:b74591d5ab33 3 *
be_bryan 0:b74591d5ab33 4 * Permission is hereby granted, free of charge, to any person obtaining a
be_bryan 0:b74591d5ab33 5 * copy of this software and associated documentation files (the "Software"),
be_bryan 0:b74591d5ab33 6 * to deal in the Software without restriction, including without limitation
be_bryan 0:b74591d5ab33 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
be_bryan 0:b74591d5ab33 8 * and/or sell copies of the Software, and to permit persons to whom the
be_bryan 0:b74591d5ab33 9 * Software is furnished to do so, subject to the following conditions:
be_bryan 0:b74591d5ab33 10 *
be_bryan 0:b74591d5ab33 11 * The above copyright notice and this permission notice shall be included
be_bryan 0:b74591d5ab33 12 * in all copies or substantial portions of the Software.
be_bryan 0:b74591d5ab33 13 *
be_bryan 0:b74591d5ab33 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
be_bryan 0:b74591d5ab33 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
be_bryan 0:b74591d5ab33 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
be_bryan 0:b74591d5ab33 17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
be_bryan 0:b74591d5ab33 18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
be_bryan 0:b74591d5ab33 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
be_bryan 0:b74591d5ab33 20 * OTHER DEALINGS IN THE SOFTWARE.
be_bryan 0:b74591d5ab33 21 *
be_bryan 0:b74591d5ab33 22 * Except as contained in this notice, the name of Maxim Integrated
be_bryan 0:b74591d5ab33 23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
be_bryan 0:b74591d5ab33 24 * Products, Inc. Branding Policy.
be_bryan 0:b74591d5ab33 25 *
be_bryan 0:b74591d5ab33 26 * The mere transfer of this software does not imply any licenses
be_bryan 0:b74591d5ab33 27 * of trade secrets, proprietary technology, copyrights, patents,
be_bryan 0:b74591d5ab33 28 * trademarks, maskwork rights, or any other form of intellectual
be_bryan 0:b74591d5ab33 29 * property whatsoever. Maxim Integrated Products, Inc. retains all
be_bryan 0:b74591d5ab33 30 * ownership rights.
be_bryan 0:b74591d5ab33 31 *******************************************************************************
be_bryan 0:b74591d5ab33 32 */
be_bryan 0:b74591d5ab33 33
be_bryan 0:b74591d5ab33 34 #include "MaximGattServer.h"
be_bryan 0:b74591d5ab33 35 #include "mbed.h"
be_bryan 0:b74591d5ab33 36 #include "MaximGap.h"
be_bryan 0:b74591d5ab33 37 #include "wsf_types.h"
be_bryan 0:b74591d5ab33 38 #include "att_api.h"
be_bryan 0:b74591d5ab33 39
be_bryan 0:b74591d5ab33 40 typedef struct mxmChar_s {
be_bryan 0:b74591d5ab33 41 uint16_t descLen;
be_bryan 0:b74591d5ab33 42 mxmChar_s() {}
be_bryan 0:b74591d5ab33 43 } mxmChar_t;
be_bryan 0:b74591d5ab33 44
be_bryan 0:b74591d5ab33 45 typedef struct mxmService_s mxmService_t;
be_bryan 0:b74591d5ab33 46 struct mxmService_s {
be_bryan 0:b74591d5ab33 47 uint16_t uuidLen;
be_bryan 0:b74591d5ab33 48 mxmChar_t *chars;
be_bryan 0:b74591d5ab33 49 attsGroup_t *attGroup;
be_bryan 0:b74591d5ab33 50 mxmService_t *next;
be_bryan 0:b74591d5ab33 51 mxmService_s() {}
be_bryan 0:b74591d5ab33 52 };
be_bryan 0:b74591d5ab33 53
be_bryan 0:b74591d5ab33 54 static uint16_t currentHandle = 0x20;
be_bryan 0:b74591d5ab33 55
be_bryan 0:b74591d5ab33 56 static UUID cccUUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG);
be_bryan 0:b74591d5ab33 57 static const uint16_t cccSize = sizeof(uint16_t);
be_bryan 0:b74591d5ab33 58
be_bryan 0:b74591d5ab33 59 MaximGattServer &MaximGattServer::getInstance() {
be_bryan 0:b74591d5ab33 60 static MaximGattServer m_instance;
be_bryan 0:b74591d5ab33 61 return m_instance;
be_bryan 0:b74591d5ab33 62 }
be_bryan 0:b74591d5ab33 63
be_bryan 0:b74591d5ab33 64 ble_error_t MaximGattServer::addService(GattService &service)
be_bryan 0:b74591d5ab33 65 {
be_bryan 0:b74591d5ab33 66 currentHandle = (currentHandle + 0xF) & ~0xF;
be_bryan 0:b74591d5ab33 67 uint16_t startHandle = currentHandle;
be_bryan 0:b74591d5ab33 68
be_bryan 0:b74591d5ab33 69 mxmService_t *mxmSvc = new mxmService_t;
be_bryan 0:b74591d5ab33 70
be_bryan 0:b74591d5ab33 71 // Create WiCentric attribute group
be_bryan 0:b74591d5ab33 72 mxmSvc->attGroup = new attsGroup_t;
be_bryan 0:b74591d5ab33 73
be_bryan 0:b74591d5ab33 74 // Determine the attribute list length
be_bryan 0:b74591d5ab33 75 unsigned int attListLen = 1;
be_bryan 0:b74591d5ab33 76 for (int i = 0; i < service.getCharacteristicCount(); i++) {
be_bryan 0:b74591d5ab33 77 attListLen += 2;
be_bryan 0:b74591d5ab33 78 GattCharacteristic *p_char = service.getCharacteristic(i);
be_bryan 0:b74591d5ab33 79
be_bryan 0:b74591d5ab33 80 if (p_char->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE)) {
be_bryan 0:b74591d5ab33 81 // add a CCCD
be_bryan 0:b74591d5ab33 82 attListLen++;
be_bryan 0:b74591d5ab33 83 }
be_bryan 0:b74591d5ab33 84 }
be_bryan 0:b74591d5ab33 85
be_bryan 0:b74591d5ab33 86 // Create WiCentric attribute list
be_bryan 0:b74591d5ab33 87 mxmSvc->attGroup->pAttr = (attsAttr_t*)malloc(attListLen * sizeof(attsAttr_t));;
be_bryan 0:b74591d5ab33 88 if (mxmSvc->attGroup->pAttr == NULL) {
be_bryan 0:b74591d5ab33 89 return BLE_ERROR_BUFFER_OVERFLOW;
be_bryan 0:b74591d5ab33 90 }
be_bryan 0:b74591d5ab33 91
be_bryan 0:b74591d5ab33 92 // Create characteristics
be_bryan 0:b74591d5ab33 93 mxmSvc->chars = new mxmChar_t [service.getCharacteristicCount()];
be_bryan 0:b74591d5ab33 94
be_bryan 0:b74591d5ab33 95 attsAttr_t *currAtt = mxmSvc->attGroup->pAttr;
be_bryan 0:b74591d5ab33 96
be_bryan 0:b74591d5ab33 97 /* Service */
be_bryan 0:b74591d5ab33 98 currAtt->pUuid = attPrimSvcUuid;
be_bryan 0:b74591d5ab33 99 if (service.getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) {
be_bryan 0:b74591d5ab33 100 mxmSvc->uuidLen = UUID::LENGTH_OF_LONG_UUID;
be_bryan 0:b74591d5ab33 101 } else {
be_bryan 0:b74591d5ab33 102 mxmSvc->uuidLen = sizeof(UUID::ShortUUIDBytes_t);
be_bryan 0:b74591d5ab33 103 }
be_bryan 0:b74591d5ab33 104 currAtt->pValue = (uint8_t*)malloc(mxmSvc->uuidLen);
be_bryan 0:b74591d5ab33 105 memcpy(currAtt->pValue, service.getUUID().getBaseUUID(), mxmSvc->uuidLen);
be_bryan 0:b74591d5ab33 106 currAtt->maxLen = mxmSvc->uuidLen;
be_bryan 0:b74591d5ab33 107 currAtt->pLen = &mxmSvc->uuidLen;
be_bryan 0:b74591d5ab33 108 currAtt->settings = 0;
be_bryan 0:b74591d5ab33 109 currAtt->permissions = ATTS_PERMIT_READ;
be_bryan 0:b74591d5ab33 110
be_bryan 0:b74591d5ab33 111 currAtt++;
be_bryan 0:b74591d5ab33 112
be_bryan 0:b74591d5ab33 113 /* Add characteristics to the service */
be_bryan 0:b74591d5ab33 114 for (int i = 0; i < service.getCharacteristicCount(); i++) {
be_bryan 0:b74591d5ab33 115 GattCharacteristic *p_char = service.getCharacteristic(i);
be_bryan 0:b74591d5ab33 116
be_bryan 0:b74591d5ab33 117 /* Skip any incompletely defined, read-only characteristics. */
be_bryan 0:b74591d5ab33 118 if ((p_char->getValueAttribute().getValuePtr() == NULL) &&
be_bryan 0:b74591d5ab33 119 (p_char->getValueAttribute().getLength() == 0) &&
be_bryan 0:b74591d5ab33 120 (p_char->getProperties() == GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ)) {
be_bryan 0:b74591d5ab33 121 continue;
be_bryan 0:b74591d5ab33 122 }
be_bryan 0:b74591d5ab33 123
be_bryan 0:b74591d5ab33 124 // Create Characteristic Attribute
be_bryan 0:b74591d5ab33 125 currentHandle += 2;
be_bryan 0:b74591d5ab33 126 currAtt->pUuid = attChUuid;
be_bryan 0:b74591d5ab33 127
be_bryan 0:b74591d5ab33 128 p_char->getValueAttribute().setHandle(currentHandle);
be_bryan 0:b74591d5ab33 129 mxmSvc->chars[i].descLen = 1 + sizeof(currentHandle) + p_char->getValueAttribute().getUUID().getLen();
be_bryan 0:b74591d5ab33 130 currAtt->pValue = (uint8_t*)malloc(mxmSvc->chars[i].descLen);
be_bryan 0:b74591d5ab33 131 uint8_t *pValue = currAtt->pValue;
be_bryan 0:b74591d5ab33 132 *pValue++ = p_char->getProperties();
be_bryan 0:b74591d5ab33 133 memcpy(pValue, &currentHandle, sizeof(currentHandle));
be_bryan 0:b74591d5ab33 134 pValue += sizeof(currentHandle);
be_bryan 0:b74591d5ab33 135 memcpy(pValue, p_char->getValueAttribute().getUUID().getBaseUUID(), p_char->getValueAttribute().getUUID().getLen());
be_bryan 0:b74591d5ab33 136
be_bryan 0:b74591d5ab33 137 currAtt->pLen = &mxmSvc->chars[i].descLen;
be_bryan 0:b74591d5ab33 138 currAtt->maxLen = mxmSvc->chars[i].descLen;
be_bryan 0:b74591d5ab33 139 currAtt->settings = 0;
be_bryan 0:b74591d5ab33 140 currAtt->permissions = ATTS_PERMIT_READ;
be_bryan 0:b74591d5ab33 141 currAtt++;
be_bryan 0:b74591d5ab33 142
be_bryan 0:b74591d5ab33 143 // Create Value Attribute
be_bryan 0:b74591d5ab33 144 currAtt->pUuid = p_char->getValueAttribute().getUUID().getBaseUUID();
be_bryan 0:b74591d5ab33 145 currAtt->pValue = p_char->getValueAttribute().getValuePtr();
be_bryan 0:b74591d5ab33 146 currAtt->pLen = p_char->getValueAttribute().getLengthPtr();
be_bryan 0:b74591d5ab33 147 currAtt->maxLen = p_char->getValueAttribute().getMaxLength();
be_bryan 0:b74591d5ab33 148 currAtt->settings = ATTS_SET_WRITE_CBACK | ATTS_SET_READ_CBACK;
be_bryan 0:b74591d5ab33 149 if (p_char->getValueAttribute().getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) {
be_bryan 0:b74591d5ab33 150 currAtt->settings |= ATTS_SET_UUID_128;
be_bryan 0:b74591d5ab33 151 }
be_bryan 0:b74591d5ab33 152 currAtt->permissions = 0;
be_bryan 0:b74591d5ab33 153 if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ) { currAtt->permissions |= ATTS_PERMIT_READ; }
be_bryan 0:b74591d5ab33 154 if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE) { currAtt->permissions |= ATTS_PERMIT_WRITE; }
be_bryan 0:b74591d5ab33 155 currAtt++;
be_bryan 0:b74591d5ab33 156
be_bryan 0:b74591d5ab33 157 bool cccCreated = false;
be_bryan 0:b74591d5ab33 158
be_bryan 0:b74591d5ab33 159 for (int i = 0; i < p_char->getDescriptorCount(); i++) {
be_bryan 0:b74591d5ab33 160 GattAttribute *p_att = p_char->getDescriptor(i);
be_bryan 0:b74591d5ab33 161
be_bryan 0:b74591d5ab33 162 currentHandle++;
be_bryan 0:b74591d5ab33 163
be_bryan 0:b74591d5ab33 164 currAtt->pUuid = p_att->getUUID().getBaseUUID();
be_bryan 0:b74591d5ab33 165 currAtt->pValue = p_att->getValuePtr();
be_bryan 0:b74591d5ab33 166 currAtt->pLen = p_att->getLengthPtr();
be_bryan 0:b74591d5ab33 167 currAtt->maxLen = p_att->getMaxLength();
be_bryan 0:b74591d5ab33 168 currAtt->settings = 0;
be_bryan 0:b74591d5ab33 169 currAtt->permissions = 0;
be_bryan 0:b74591d5ab33 170 if (p_att->getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) {
be_bryan 0:b74591d5ab33 171 currAtt->settings |= ATTS_SET_UUID_128;
be_bryan 0:b74591d5ab33 172 }
be_bryan 0:b74591d5ab33 173 if (p_att->getUUID() == UUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG)) {
be_bryan 0:b74591d5ab33 174 cccCreated = true;
be_bryan 0:b74591d5ab33 175 currAtt->settings |= ATTS_SET_CCC;
be_bryan 0:b74591d5ab33 176 currAtt->permissions |= ATTS_PERMIT_READ;
be_bryan 0:b74591d5ab33 177 currAtt->permissions |= ATTS_PERMIT_WRITE;
be_bryan 0:b74591d5ab33 178
be_bryan 0:b74591d5ab33 179 if (cccCnt < MAX_CCC_CNT) {
be_bryan 0:b74591d5ab33 180 cccSet[cccCnt].handle = currentHandle;
be_bryan 0:b74591d5ab33 181 cccSet[cccCnt].valueRange = 0;
be_bryan 0:b74591d5ab33 182 if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) {
be_bryan 0:b74591d5ab33 183 cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_NOTIFY;
be_bryan 0:b74591d5ab33 184 }
be_bryan 0:b74591d5ab33 185 if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) {
be_bryan 0:b74591d5ab33 186 cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_INDICATE;
be_bryan 0:b74591d5ab33 187 }
be_bryan 0:b74591d5ab33 188 cccSet[cccCnt].secLevel = DM_SEC_LEVEL_NONE;
be_bryan 0:b74591d5ab33 189 cccHandles[cccCnt] = p_char->getValueAttribute().getHandle();
be_bryan 0:b74591d5ab33 190 cccCnt++;
be_bryan 0:b74591d5ab33 191 } else {
be_bryan 0:b74591d5ab33 192 return BLE_ERROR_PARAM_OUT_OF_RANGE;
be_bryan 0:b74591d5ab33 193 }
be_bryan 0:b74591d5ab33 194 }
be_bryan 0:b74591d5ab33 195 currAtt++;
be_bryan 0:b74591d5ab33 196 }
be_bryan 0:b74591d5ab33 197
be_bryan 0:b74591d5ab33 198 if (!cccCreated && (p_char->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE))) {
be_bryan 0:b74591d5ab33 199 /* There was not a CCCD included in the descriptors, but this
be_bryan 0:b74591d5ab33 200 * characteristic is notifiable and/or indicatable. A CCCD is
be_bryan 0:b74591d5ab33 201 * required so create one now.
be_bryan 0:b74591d5ab33 202 */
be_bryan 0:b74591d5ab33 203 if (cccCnt >= MAX_CCC_CNT) {
be_bryan 0:b74591d5ab33 204 return BLE_ERROR_PARAM_OUT_OF_RANGE;
be_bryan 0:b74591d5ab33 205 }
be_bryan 0:b74591d5ab33 206
be_bryan 0:b74591d5ab33 207 currentHandle++;
be_bryan 0:b74591d5ab33 208
be_bryan 0:b74591d5ab33 209 currAtt->pUuid = cccUUID.getBaseUUID();
be_bryan 0:b74591d5ab33 210 currAtt->pValue = (uint8_t*)&cccValues[cccCnt];
be_bryan 0:b74591d5ab33 211 currAtt->pLen = (uint16_t*)&cccSize;
be_bryan 0:b74591d5ab33 212 currAtt->maxLen = sizeof(uint16_t);
be_bryan 0:b74591d5ab33 213 currAtt->settings = ATTS_SET_CCC;
be_bryan 0:b74591d5ab33 214 currAtt->permissions = (ATTS_PERMIT_READ | ATTS_PERMIT_WRITE);
be_bryan 0:b74591d5ab33 215
be_bryan 0:b74591d5ab33 216 cccSet[cccCnt].handle = currentHandle;
be_bryan 0:b74591d5ab33 217 cccSet[cccCnt].valueRange = 0;
be_bryan 0:b74591d5ab33 218 if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) {
be_bryan 0:b74591d5ab33 219 cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_NOTIFY;
be_bryan 0:b74591d5ab33 220 }
be_bryan 0:b74591d5ab33 221 if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) {
be_bryan 0:b74591d5ab33 222 cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_INDICATE;
be_bryan 0:b74591d5ab33 223 }
be_bryan 0:b74591d5ab33 224 cccSet[cccCnt].secLevel = DM_SEC_LEVEL_NONE;
be_bryan 0:b74591d5ab33 225 cccHandles[cccCnt] = p_char->getValueAttribute().getHandle();
be_bryan 0:b74591d5ab33 226
be_bryan 0:b74591d5ab33 227 cccCnt++;
be_bryan 0:b74591d5ab33 228 currAtt++;
be_bryan 0:b74591d5ab33 229 }
be_bryan 0:b74591d5ab33 230 }
be_bryan 0:b74591d5ab33 231
be_bryan 0:b74591d5ab33 232 mxmSvc->attGroup->pNext = NULL;
be_bryan 0:b74591d5ab33 233 mxmSvc->attGroup->readCback = attsReadCback;
be_bryan 0:b74591d5ab33 234 mxmSvc->attGroup->writeCback = attsWriteCback;
be_bryan 0:b74591d5ab33 235 mxmSvc->attGroup->startHandle = startHandle;
be_bryan 0:b74591d5ab33 236 mxmSvc->attGroup->endHandle = currentHandle;
be_bryan 0:b74591d5ab33 237 AttsAddGroup(mxmSvc->attGroup);
be_bryan 0:b74591d5ab33 238
be_bryan 0:b74591d5ab33 239 AttRegister(attCback);
be_bryan 0:b74591d5ab33 240 AttsCccRegister(cccCnt, (attsCccSet_t*)cccSet, cccCback);
be_bryan 0:b74591d5ab33 241
be_bryan 0:b74591d5ab33 242 return BLE_ERROR_NONE;
be_bryan 0:b74591d5ab33 243 }
be_bryan 0:b74591d5ab33 244
be_bryan 0:b74591d5ab33 245 ble_error_t MaximGattServer::read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *const lengthP)
be_bryan 0:b74591d5ab33 246 {
be_bryan 0:b74591d5ab33 247 if (AttsGetAttr(attributeHandle, lengthP, &buffer) != ATT_SUCCESS) {
be_bryan 0:b74591d5ab33 248 return BLE_ERROR_PARAM_OUT_OF_RANGE;
be_bryan 0:b74591d5ab33 249 }
be_bryan 0:b74591d5ab33 250
be_bryan 0:b74591d5ab33 251 return BLE_ERROR_NONE;
be_bryan 0:b74591d5ab33 252 }
be_bryan 0:b74591d5ab33 253
be_bryan 0:b74591d5ab33 254 ble_error_t MaximGattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP)
be_bryan 0:b74591d5ab33 255 {
be_bryan 0:b74591d5ab33 256 // Check to see if this is a CCCD
be_bryan 0:b74591d5ab33 257 uint8_t idx;
be_bryan 0:b74591d5ab33 258 for (idx = 0; idx < cccCnt; idx++) {
be_bryan 0:b74591d5ab33 259 if (attributeHandle == cccSet[idx].handle) {
be_bryan 0:b74591d5ab33 260 if (connectionHandle == DM_CONN_ID_NONE) { // CCCDs are always 16 bits
be_bryan 0:b74591d5ab33 261 return BLE_ERROR_PARAM_OUT_OF_RANGE;
be_bryan 0:b74591d5ab33 262 }
be_bryan 0:b74591d5ab33 263 *((uint16_t*)buffer) = AttsCccGet(connectionHandle, idx);
be_bryan 0:b74591d5ab33 264 *lengthP = 2; // CCCDs are always 16 bits
be_bryan 0:b74591d5ab33 265 return BLE_ERROR_NONE;
be_bryan 0:b74591d5ab33 266 }
be_bryan 0:b74591d5ab33 267 }
be_bryan 0:b74591d5ab33 268
be_bryan 0:b74591d5ab33 269 // This is not a CCCD. Use the non-connection specific update method.
be_bryan 0:b74591d5ab33 270 return read(attributeHandle, buffer, lengthP);
be_bryan 0:b74591d5ab33 271 }
be_bryan 0:b74591d5ab33 272
be_bryan 0:b74591d5ab33 273 ble_error_t MaximGattServer::write(GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly)
be_bryan 0:b74591d5ab33 274 {
be_bryan 0:b74591d5ab33 275 uint16_t connectionHandle = MaximGap::getInstance().getConnectionHandle();
be_bryan 0:b74591d5ab33 276
be_bryan 0:b74591d5ab33 277 if (AttsSetAttr(attributeHandle, len, (uint8_t*)buffer) != ATT_SUCCESS) {
be_bryan 0:b74591d5ab33 278 return BLE_ERROR_PARAM_OUT_OF_RANGE;
be_bryan 0:b74591d5ab33 279 }
be_bryan 0:b74591d5ab33 280
be_bryan 0:b74591d5ab33 281 if (!localOnly) {
be_bryan 0:b74591d5ab33 282 if (connectionHandle != DM_CONN_ID_NONE) {
be_bryan 0:b74591d5ab33 283
be_bryan 0:b74591d5ab33 284 // Check to see if this characteristic has a CCCD attribute
be_bryan 0:b74591d5ab33 285 uint8_t idx;
be_bryan 0:b74591d5ab33 286 for (idx = 0; idx < cccCnt; idx++) {
be_bryan 0:b74591d5ab33 287 if (attributeHandle == cccHandles[idx]) {
be_bryan 0:b74591d5ab33 288 break;
be_bryan 0:b74591d5ab33 289 }
be_bryan 0:b74591d5ab33 290 }
be_bryan 0:b74591d5ab33 291 if (idx < cccCnt) {
be_bryan 0:b74591d5ab33 292 // This characteristic has a CCCD attribute. Handle notifications and indications.
be_bryan 0:b74591d5ab33 293 uint16_t cccEnabled = AttsCccEnabled(connectionHandle, idx);
be_bryan 0:b74591d5ab33 294 if (cccEnabled & ATT_CLIENT_CFG_NOTIFY) {
be_bryan 0:b74591d5ab33 295 AttsHandleValueNtf(connectionHandle, attributeHandle, len, (uint8_t*)buffer);
be_bryan 0:b74591d5ab33 296 }
be_bryan 0:b74591d5ab33 297 if (cccEnabled & ATT_CLIENT_CFG_INDICATE) {
be_bryan 0:b74591d5ab33 298 AttsHandleValueInd(connectionHandle, attributeHandle, len, (uint8_t*)buffer);
be_bryan 0:b74591d5ab33 299 }
be_bryan 0:b74591d5ab33 300 }
be_bryan 0:b74591d5ab33 301 }
be_bryan 0:b74591d5ab33 302 }
be_bryan 0:b74591d5ab33 303
be_bryan 0:b74591d5ab33 304 return BLE_ERROR_NONE;
be_bryan 0:b74591d5ab33 305 }
be_bryan 0:b74591d5ab33 306
be_bryan 0:b74591d5ab33 307 ble_error_t MaximGattServer::write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly)
be_bryan 0:b74591d5ab33 308 {
be_bryan 0:b74591d5ab33 309 // Check to see if this is a CCCD
be_bryan 0:b74591d5ab33 310 uint8_t idx;
be_bryan 0:b74591d5ab33 311 for (idx = 0; idx < cccCnt; idx++) {
be_bryan 0:b74591d5ab33 312 if (attributeHandle == cccSet[idx].handle) {
be_bryan 0:b74591d5ab33 313 if ((connectionHandle == DM_CONN_ID_NONE) || (len != 2)) { // CCCDs are always 16 bits
be_bryan 0:b74591d5ab33 314 return BLE_ERROR_PARAM_OUT_OF_RANGE;
be_bryan 0:b74591d5ab33 315 }
be_bryan 0:b74591d5ab33 316 AttsCccSet(connectionHandle, idx, *((uint16_t*)buffer));
be_bryan 0:b74591d5ab33 317 return BLE_ERROR_NONE;
be_bryan 0:b74591d5ab33 318 }
be_bryan 0:b74591d5ab33 319 }
be_bryan 0:b74591d5ab33 320
be_bryan 0:b74591d5ab33 321 // This is not a CCCD. Use the non-connection specific update method.
be_bryan 0:b74591d5ab33 322 return write(attributeHandle, buffer, len, localOnly);
be_bryan 0:b74591d5ab33 323 }
be_bryan 0:b74591d5ab33 324
be_bryan 0:b74591d5ab33 325 ble_error_t MaximGattServer::areUpdatesEnabled(const GattCharacteristic &characteristic, bool *enabledP)
be_bryan 0:b74591d5ab33 326 {
be_bryan 0:b74591d5ab33 327 uint16_t connectionHandle = MaximGap::getInstance().getConnectionHandle();
be_bryan 0:b74591d5ab33 328
be_bryan 0:b74591d5ab33 329 if (connectionHandle != DM_CONN_ID_NONE) {
be_bryan 0:b74591d5ab33 330 uint8_t idx;
be_bryan 0:b74591d5ab33 331 for (idx = 0; idx < cccCnt; idx++) {
be_bryan 0:b74591d5ab33 332 if (characteristic.getValueHandle() == cccHandles[idx]) {
be_bryan 0:b74591d5ab33 333 uint16_t cccValue = AttsCccGet(connectionHandle, idx);
be_bryan 0:b74591d5ab33 334 if (cccValue & ATT_CLIENT_CFG_NOTIFY) {
be_bryan 0:b74591d5ab33 335 *enabledP = true;
be_bryan 0:b74591d5ab33 336 } else {
be_bryan 0:b74591d5ab33 337 *enabledP = false;
be_bryan 0:b74591d5ab33 338 }
be_bryan 0:b74591d5ab33 339 return BLE_ERROR_NONE;
be_bryan 0:b74591d5ab33 340 }
be_bryan 0:b74591d5ab33 341 }
be_bryan 0:b74591d5ab33 342 }
be_bryan 0:b74591d5ab33 343
be_bryan 0:b74591d5ab33 344 return BLE_ERROR_PARAM_OUT_OF_RANGE;
be_bryan 0:b74591d5ab33 345 }
be_bryan 0:b74591d5ab33 346
be_bryan 0:b74591d5ab33 347 ble_error_t MaximGattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP)
be_bryan 0:b74591d5ab33 348 {
be_bryan 0:b74591d5ab33 349 if (connectionHandle != DM_CONN_ID_NONE) {
be_bryan 0:b74591d5ab33 350 uint8_t idx;
be_bryan 0:b74591d5ab33 351 for (idx = 0; idx < cccCnt; idx++) {
be_bryan 0:b74591d5ab33 352 if (characteristic.getValueHandle() == cccHandles[idx]) {
be_bryan 0:b74591d5ab33 353 uint16_t cccValue = AttsCccGet(connectionHandle, idx);
be_bryan 0:b74591d5ab33 354 if (cccValue & ATT_CLIENT_CFG_NOTIFY) {
be_bryan 0:b74591d5ab33 355 *enabledP = true;
be_bryan 0:b74591d5ab33 356 } else {
be_bryan 0:b74591d5ab33 357 *enabledP = false;
be_bryan 0:b74591d5ab33 358 }
be_bryan 0:b74591d5ab33 359 return BLE_ERROR_NONE;
be_bryan 0:b74591d5ab33 360 }
be_bryan 0:b74591d5ab33 361 }
be_bryan 0:b74591d5ab33 362 }
be_bryan 0:b74591d5ab33 363
be_bryan 0:b74591d5ab33 364 return BLE_ERROR_PARAM_OUT_OF_RANGE;
be_bryan 0:b74591d5ab33 365 }
be_bryan 0:b74591d5ab33 366
be_bryan 0:b74591d5ab33 367 void MaximGattServer::cccCback(attsCccEvt_t *pEvt)
be_bryan 0:b74591d5ab33 368 {
be_bryan 0:b74591d5ab33 369 if (pEvt->value & (ATT_CLIENT_CFG_NOTIFY | ATT_CLIENT_CFG_INDICATE)) {
be_bryan 0:b74591d5ab33 370 getInstance().handleEvent(GattServerEvents::GATT_EVENT_UPDATES_ENABLED, pEvt->handle);
be_bryan 0:b74591d5ab33 371 } else {
be_bryan 0:b74591d5ab33 372 getInstance().handleEvent(GattServerEvents::GATT_EVENT_UPDATES_DISABLED, pEvt->handle);
be_bryan 0:b74591d5ab33 373 }
be_bryan 0:b74591d5ab33 374 }
be_bryan 0:b74591d5ab33 375
be_bryan 0:b74591d5ab33 376 void MaximGattServer::attCback(attEvt_t *pEvt)
be_bryan 0:b74591d5ab33 377 {
be_bryan 0:b74591d5ab33 378 if (pEvt->hdr.status == ATT_SUCCESS) {
be_bryan 0:b74591d5ab33 379 getInstance().handleEvent(GattServerEvents::GATT_EVENT_DATA_SENT, pEvt->handle);
be_bryan 0:b74591d5ab33 380 }
be_bryan 0:b74591d5ab33 381 }
be_bryan 0:b74591d5ab33 382
be_bryan 0:b74591d5ab33 383 uint8_t MaximGattServer::attsReadCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr)
be_bryan 0:b74591d5ab33 384 {
be_bryan 0:b74591d5ab33 385 GattReadCallbackParams cbParams = {
be_bryan 0:b74591d5ab33 386 /* .connHandle = */ connId,
be_bryan 0:b74591d5ab33 387 /* .handle = */ handle,
be_bryan 0:b74591d5ab33 388 /* .offset = */ offset,
be_bryan 0:b74591d5ab33 389 /* .len = */ *pAttr->pLen,
be_bryan 0:b74591d5ab33 390 /* .data = */ pAttr->pValue
be_bryan 0:b74591d5ab33 391 };
be_bryan 0:b74591d5ab33 392 getInstance().handleDataReadEvent(&cbParams);
be_bryan 0:b74591d5ab33 393
be_bryan 0:b74591d5ab33 394 return ATT_SUCCESS;
be_bryan 0:b74591d5ab33 395 }
be_bryan 0:b74591d5ab33 396
be_bryan 0:b74591d5ab33 397 uint8_t MaximGattServer::attsWriteCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr)
be_bryan 0:b74591d5ab33 398 {
be_bryan 0:b74591d5ab33 399 uint8_t err;
be_bryan 0:b74591d5ab33 400
be_bryan 0:b74591d5ab33 401 /* TODO: offset is not handled properly */
be_bryan 0:b74591d5ab33 402 if ((err = AttsSetAttr(handle, len, pValue)) != ATT_SUCCESS) {
be_bryan 0:b74591d5ab33 403 return err;
be_bryan 0:b74591d5ab33 404 }
be_bryan 0:b74591d5ab33 405
be_bryan 0:b74591d5ab33 406 GattWriteCallbackParams::WriteOp_t writeOp;
be_bryan 0:b74591d5ab33 407 switch (operation) {
be_bryan 0:b74591d5ab33 408 case ATT_PDU_WRITE_REQ:
be_bryan 0:b74591d5ab33 409 writeOp = GattWriteCallbackParams::OP_WRITE_REQ;
be_bryan 0:b74591d5ab33 410 break;
be_bryan 0:b74591d5ab33 411 case ATT_PDU_WRITE_CMD:
be_bryan 0:b74591d5ab33 412 writeOp = GattWriteCallbackParams::OP_WRITE_CMD;
be_bryan 0:b74591d5ab33 413 break;
be_bryan 0:b74591d5ab33 414 case ATT_PDU_SIGNED_WRITE_CMD:
be_bryan 0:b74591d5ab33 415 writeOp = GattWriteCallbackParams::OP_SIGN_WRITE_CMD;
be_bryan 0:b74591d5ab33 416 break;
be_bryan 0:b74591d5ab33 417 case ATT_PDU_PREP_WRITE_REQ:
be_bryan 0:b74591d5ab33 418 writeOp = GattWriteCallbackParams::OP_PREP_WRITE_REQ;
be_bryan 0:b74591d5ab33 419 break;
be_bryan 0:b74591d5ab33 420 case ATT_PDU_EXEC_WRITE_REQ:
be_bryan 0:b74591d5ab33 421 writeOp = GattWriteCallbackParams::OP_EXEC_WRITE_REQ_NOW;
be_bryan 0:b74591d5ab33 422 break;
be_bryan 0:b74591d5ab33 423 default:
be_bryan 0:b74591d5ab33 424 writeOp = GattWriteCallbackParams::OP_INVALID;
be_bryan 0:b74591d5ab33 425 break;
be_bryan 0:b74591d5ab33 426 }
be_bryan 0:b74591d5ab33 427
be_bryan 0:b74591d5ab33 428 GattWriteCallbackParams cbParams = {
be_bryan 0:b74591d5ab33 429 /* .connHandle = */ connId,
be_bryan 0:b74591d5ab33 430 /* .handle = */ handle,
be_bryan 0:b74591d5ab33 431 /* .writeOp = */ writeOp,
be_bryan 0:b74591d5ab33 432 /* .offset = */ offset,
be_bryan 0:b74591d5ab33 433 /* .len = */ len,
be_bryan 0:b74591d5ab33 434 /* .data = */ pValue
be_bryan 0:b74591d5ab33 435 };
be_bryan 0:b74591d5ab33 436 getInstance().handleDataWrittenEvent(&cbParams);
be_bryan 0:b74591d5ab33 437
be_bryan 0:b74591d5ab33 438 return ATT_SUCCESS;
be_bryan 0:b74591d5ab33 439 }