WILLIAN MATTOS / X_NUCLEO_IDB0XA1

Dependents:   BLE_HeartRate_IDB0XA1

Fork of X_NUCLEO_IDB0XA1 by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BlueNRGGattClient.cpp Source File

BlueNRGGattClient.cpp

Go to the documentation of this file.
00001 /* mbed Microcontroller Library
00002 * Copyright (c) 2006-2013 ARM Limited
00003 *
00004 * Licensed under the Apache License, Version 2.0 (the "License");
00005 * you may not use this file except in compliance with the License.
00006 * You may obtain a copy of the License at
00007 *
00008 *     http://www.apache.org/licenses/LICENSE-2.0
00009 *
00010 * Unless required by applicable law or agreed to in writing, software
00011 * distributed under the License is distributed on an "AS IS" BASIS,
00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 * See the License for the specific language governing permissions and
00014 * limitations under the License.
00015 */
00016 /**
00017   ******************************************************************************
00018   * @file    BlueNRGGattServer.cpp 
00019   * @author  STMicroelectronics
00020   * @brief   Implementation of BlueNRG BLE_API GattServer Class
00021   ******************************************************************************
00022   * @copy
00023   *
00024   * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
00025   * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
00026   * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
00027   * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
00028   * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
00029   * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
00030   *
00031   * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
00032   */ 
00033  
00034 /** @defgroup BlueNRGGATTClient
00035  *  @brief BlueNRG BLE_API GattClient Adaptation
00036  *  @{
00037  */
00038  
00039 #include "BlueNRGGattClient.h"
00040 #include "BlueNRGGap.h"
00041 #include "Utils.h"
00042 #include "debug.h"
00043 
00044 static uint8_t props_mask[] = {
00045   0x01,
00046   0x02,
00047   0x04,
00048   0x08,
00049   0x10,
00050   0x20,
00051   0x40,
00052   0x80
00053   };
00054 
00055 void BlueNRGGattClient::gattProcedureCompleteCB(Gap::Handle_t connectionHandle, uint8_t error_code)
00056 {
00057   if(error_code != BLE_STATUS_SUCCESS) {
00058     _currentState = GATT_IDLE;
00059     return;
00060   }
00061     
00062   // Service Discovery complete
00063 /*
00064   if(_currentState != GATT_IDLE && 
00065      _currentState != GATT_DISCOVERY_TERMINATED &&
00066      _currentState != GATT_WRITE_CHAR &&
00067      _currentState != GATT_READ_CHAR) {
00068 */
00069   if(_currentState == GATT_SERVICE_DISCOVERY) {
00070     findServiceChars(connectionHandle);
00071   }
00072 
00073   if(_currentState == GATT_CHAR_DESC_DISCOVERY) {
00074     _currentState = GATT_IDLE;
00075   }
00076 
00077   // Read complete
00078   if(_currentState == GATT_READ_CHAR) {
00079     _currentState = GATT_IDLE;
00080   }
00081 
00082   // Write complete
00083   if(_currentState == GATT_WRITE_CHAR) {
00084     BlueNRGGattClient::getInstance().processWriteResponse(&writeCBParams);
00085     _currentState = GATT_IDLE;
00086   }
00087 }
00088                                                 
00089 void BlueNRGGattClient::primaryServicesCB(Gap::Handle_t connectionHandle,
00090                                           uint8_t event_data_length,
00091                                           uint8_t attribute_data_length,
00092                                           uint8_t *attribute_data_list)
00093 {
00094   GattAttribute::Handle_t startHandle, endHandle;
00095   UUID uuid;
00096   uint8_t i, offset, numAttr;
00097   /* avoid compiler warnings about unused variables */
00098   (void)connectionHandle;
00099 
00100   numAttr = (event_data_length - 1) / attribute_data_length;
00101 
00102   offset = 0;
00103   for (i=0; i<numAttr; i++) {
00104     startHandle = attribute_data_list[offset];
00105     endHandle = attribute_data_list[offset+2];
00106 
00107     // UUID Type
00108     if (attribute_data_length == 6) {
00109       
00110       PRINTF("UUID_TYPE_16\n\r");
00111       uuid = attribute_data_list[offset+5]<<8|attribute_data_list[offset+4];
00112       PRINTF("S UUID-%X attrs[%u %u]\r\n", uuid.getShortUUID(), startHandle, endHandle);
00113       
00114     } else {
00115       
00116       PRINTF("UUID_TYPE_128\n\r");
00117       uuid.setupLong(attribute_data_list+offset+4, UUID::LSB);
00118 
00119 #ifdef DEBUG
00120       PRINTF("S UUID-");
00121       const uint8_t *longUUIDBytes = uuid.getBaseUUID();
00122       for (unsigned j = 0; j < UUID::LENGTH_OF_LONG_UUID; j++) {
00123         PRINTF("%02x", longUUIDBytes[j]);
00124       }
00125 #endif
00126       PRINTF(" attrs[%u %u]\r\n", startHandle, endHandle);
00127       
00128     }
00129     
00130     PRINTF("Setup serviceIndex = %d\n\r", _numServices);
00131     discoveredService[_numServices].setup(uuid, startHandle, endHandle);
00132     
00133     if(serviceDiscoveryCallback) {
00134       if(_matchingServiceUUID == BLE_UUID_UNKNOWN || _matchingServiceUUID == discoveredService[_numServices].getUUID()) {
00135         serviceDiscoveryCallback(&discoveredService[_numServices]);
00136       }
00137     }
00138     _numServices++;
00139 
00140     offset += attribute_data_length;
00141   }
00142 
00143   PRINTF("!!!Service Discovery complete (numAttr=%u)!!!\n\r", numAttr);
00144 
00145 }
00146 
00147 void BlueNRGGattClient::primaryServiceCB(Gap::Handle_t connectionHandle,
00148                                          uint8_t event_data_length,
00149                                          uint8_t *handles_info_list)
00150 {
00151   GattAttribute::Handle_t startHandle, endHandle;
00152   UUID uuid;
00153   uint8_t i, offset, numHandlePairs;
00154   /* avoid compiler warnings about unused variables */
00155   (void)connectionHandle;
00156 
00157   numHandlePairs = (event_data_length - 1) / 2;
00158 
00159   offset = 0;
00160   for (i=0; i<numHandlePairs; i++) {
00161     startHandle = handles_info_list[offset];
00162     endHandle = handles_info_list[offset+2];
00163 
00164     PRINTF("primaryServiceCB attrs[%u %u]\r\n", startHandle, endHandle);
00165 
00166 
00167     if (_matchingServiceUUID.shortOrLong() == UUID::UUID_TYPE_SHORT) {
00168         PRINTF("S UUID-%x attrs[%u %u]\r\n", _matchingServiceUUID.getShortUUID(), startHandle, endHandle);
00169         uuid = _matchingServiceUUID.getShortUUID();
00170     } else {
00171 #ifdef DEBUG
00172         PRINTF("S UUID-");
00173         const uint8_t *longUUIDBytes = _matchingServiceUUID.getBaseUUID();
00174         for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
00175             PRINTF("%02x", longUUIDBytes[i]);
00176         }
00177 #endif
00178         PRINTF(" attrs[%u %u]\r\n", startHandle, endHandle);
00179         uuid.setupLong(_matchingServiceUUID.getBaseUUID(), UUID::MSB);
00180     }
00181 
00182     discoveredService[i].setup(uuid, startHandle, endHandle);
00183     
00184     if(serviceDiscoveryCallback) {
00185       serviceDiscoveryCallback(&discoveredService[_numServices]);
00186     }
00187     _numServices++;
00188     
00189     offset += 4;
00190   }
00191 }
00192 
00193 void BlueNRGGattClient::serviceCharsCB(Gap::Handle_t connectionHandle,
00194                                        uint8_t event_data_length,
00195                                        uint8_t handle_value_pair_length,
00196                                        uint8_t *handle_value_pair)
00197 {
00198   // Charac Handle (2), Charac Properties(1), Charac Value Handle(2), Charac UUID(2/16)
00199 
00200   GattAttribute::Handle_t declHandle, valueHandle, lastHandle;
00201   UUID uuid;
00202   uint8_t i, numChar, offset;
00203 
00204   numChar = (event_data_length - 1) / handle_value_pair_length;
00205 
00206   PRINTF("event_data_length=%d handle_value_pair_length=%d numChar=%d\n\r", event_data_length, handle_value_pair_length, numChar);
00207 
00208   offset = 0;
00209   for (i=0; i<numChar; i++) {
00210     // UUID Type
00211     if (handle_value_pair_length == 7) {
00212       PRINTF("Char UUID_TYPE_16\n\r");
00213       uuid = handle_value_pair[offset+6]<<8|handle_value_pair[offset+5];
00214       PRINTF("C UUID-%X\r\n", uuid.getShortUUID());
00215     } else {
00216       PRINTF("Char UUID_TYPE_128\n\r");
00217       uuid.setupLong(handle_value_pair+offset+5, UUID::LSB);
00218 #ifdef DEBUG
00219       PRINTF("C UUID-");
00220       const uint8_t *longUUIDBytes = uuid.getBaseUUID();
00221       for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
00222         PRINTF("%02X", longUUIDBytes[i]);
00223       }
00224       PRINTF("\r\n");
00225 #endif
00226     }
00227     
00228     // Properties
00229     DiscoveredCharacteristic::Properties_t p;
00230     
00231     p._broadcast = (props_mask[0] & handle_value_pair[offset+2]);
00232     p._read = (props_mask[1] & handle_value_pair[offset+2])>>1;
00233     p._writeWoResp = (props_mask[2] & handle_value_pair[offset+2])>>2;
00234     p._write = (props_mask[3] & handle_value_pair[offset+2])>>3;
00235     p._notify = (props_mask[4] & handle_value_pair[offset+2])>>4;
00236     p._indicate = (props_mask[5] & handle_value_pair[offset+2])>>5;
00237     p._authSignedWrite = (props_mask[6] & handle_value_pair[offset+2])>>6;
00238     PRINTF("p._broadcast=%d\n\r", p._broadcast);
00239     PRINTF("p._read=%d\n\r", p._read);
00240     PRINTF("p._writeWoResp=%d\n\r", p._writeWoResp);
00241     PRINTF("p._write=%d\n\r", p._write);
00242     PRINTF("p._notify=%d\n\r", p._notify);
00243     PRINTF("p._indicate=%d\n\r", p._indicate);
00244     PRINTF("p._authSignedWrite=%d\n\r", p._authSignedWrite);
00245 
00246     /*
00247     uint8_t props = handle_value_pair[offset+2];
00248     PRINTF("CHAR PROPS: %d\n\r", props);
00249     */
00250 
00251     // Handles
00252     declHandle = handle_value_pair[offset];
00253     valueHandle = handle_value_pair[offset+3];
00254     lastHandle = valueHandle+1;
00255     PRINTF("declHandle: %u valueHandle=%u lastHandle=%u\n\r", declHandle, valueHandle, lastHandle);
00256 
00257     discoveredChar[_numChars].setup(this,
00258                                     connectionHandle,
00259                                     uuid,
00260                                     p,
00261                                     declHandle,
00262                                     valueHandle,
00263                                     lastHandle);
00264 
00265     if(characteristicDiscoveryCallback) {
00266       characteristicDiscoveryCallback(&discoveredChar[_numChars]);
00267     }
00268     _numChars++;
00269 
00270     offset += handle_value_pair_length;
00271   }
00272 }
00273 
00274 void BlueNRGGattClient::serviceCharByUUIDCB(Gap::Handle_t connectionHandle,
00275                                             uint8_t event_data_length,
00276                                             uint16_t attr_handle,
00277                                             uint8_t *attr_value)
00278 {
00279   // Charac Properties(1), Charac Value Handle(2), Charac UUID(2/16)
00280   GattAttribute::Handle_t declHandle, valueHandle, lastHandle;
00281   UUID uuid;
00282   
00283   PRINTF("serviceCharByUUIDCB\n\r");
00284   
00285   // UUID Type
00286   if (event_data_length == 7) {
00287     PRINTF("Char UUID_TYPE_16\n\r");
00288     uuid = attr_value[4]<<8|attr_value[3];
00289     PRINTF("C UUID-%X\r\n", uuid.getShortUUID());
00290   } else {
00291     PRINTF("Char UUID_TYPE_128\n\r");
00292     uuid.setupLong(attr_value+3, UUID::LSB);
00293 #ifdef DEBUG
00294     PRINTF("C UUID-");
00295     const uint8_t *longUUIDBytes = uuid.getBaseUUID();
00296     for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
00297       PRINTF("%02X", longUUIDBytes[i]);
00298     }
00299     PRINTF("\r\n");
00300 #endif
00301   }
00302 
00303   // Properties
00304   DiscoveredCharacteristic::Properties_t p;
00305   
00306   p._broadcast = (props_mask[0] & attr_value[0]);
00307   p._read = (props_mask[1] & attr_value[0])>>1;
00308   p._writeWoResp = (props_mask[2] & attr_value[0])>>2;
00309   p._write = (props_mask[3] & attr_value[0])>>3;
00310   p._notify = (props_mask[4] & attr_value[0])>>4;
00311   p._indicate = (props_mask[5] & attr_value[0])>>5;
00312   p._authSignedWrite = (props_mask[6] & attr_value[0])>>6;
00313   PRINTF("p._broadcast=%d\n\r", p._broadcast);
00314   PRINTF("p._read=%d\n\r", p._read);
00315   PRINTF("p._writeWoResp=%d\n\r", p._writeWoResp);
00316   PRINTF("p._write=%d\n\r", p._write);
00317   PRINTF("p._notify=%d\n\r", p._notify);
00318   PRINTF("p._indicate=%d\n\r", p._indicate);
00319   PRINTF("p._authSignedWrite=%d\n\r", p._authSignedWrite);
00320 
00321   /*
00322   uint8_t props = attr_value[0];
00323   PRINTF("CHAR PROPS: %d\n\r", props);
00324   */
00325 
00326   // Handles
00327   declHandle = attr_handle;
00328   valueHandle = attr_value[1];
00329   lastHandle = valueHandle+1;
00330 
00331   discoveredChar[_numChars].setup(this,
00332                                   connectionHandle,
00333                                   uuid,
00334                                   p,
00335                                   declHandle,
00336                                   valueHandle,
00337                                   lastHandle);
00338   
00339   if(characteristicDiscoveryCallback) {
00340     characteristicDiscoveryCallback(&discoveredChar[_numChars]);
00341   }
00342   _numChars++;
00343 }
00344 
00345 ble_error_t BlueNRGGattClient::findServiceChars(Gap::Handle_t connectionHandle)
00346 {
00347   PRINTF("findServiceChars\n\r");
00348   
00349   tBleStatus ret;
00350   uint8_t uuid_type = UUID_TYPE_16;
00351   uint8_t short_uuid[2];
00352   uint8_t *uuid = NULL;
00353   
00354   DiscoveredService *service;
00355   
00356   // We finished chars discovery for all services
00357   if(_servIndex >= _numServices) {
00358     PRINTF("!!!We finished chars discovery for all services!!!\n\r");
00359     //_currentState = GATT_CHARS_DISCOVERY_COMPLETE;
00360     
00361     terminateServiceDiscovery();
00362     
00363     return BLE_ERROR_NONE;
00364   }
00365     
00366   service = &discoveredService[_servIndex];
00367   /*
00368   if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
00369     PRINTF("S UUID-%X\r\n", service->getUUID().getShortUUID());
00370   } else {
00371     PRINTF("S UUID-");
00372     const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
00373     for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
00374       PRINTF("%02X", longUUIDBytes[i]);
00375     }
00376     PRINTF("\r\n");
00377   }
00378   */
00379   
00380   PRINTF("findServiceChars (_servIndex=%d)\n\r", _servIndex);
00381   //ret = aci_gatt_disc_all_charac_of_serv(connectionHandle, service->getStartHandle(), service->getEndHandle());
00382 
00383   if(_matchingCharacteristicUUIDIn == BLE_UUID_UNKNOWN) {
00384     PRINTF("findServiceChars (BLE_UUID_UNKNOWN)\n\r");
00385     ret = aci_gatt_disc_all_charac_of_serv(connectionHandle, service->getStartHandle(), service->getEndHandle());
00386   } else {
00387     
00388     uint8_t type = _matchingCharacteristicUUIDIn.shortOrLong();
00389     
00390     if(type == UUID::UUID_TYPE_SHORT) {
00391       STORE_LE_16(short_uuid, _matchingCharacteristicUUIDIn.getShortUUID());
00392       
00393       uuid_type = UUID_TYPE_16;
00394       uuid = short_uuid;
00395 #ifdef DEBUG
00396       PRINTF("findServiceChars C UUID-");
00397       for(unsigned i = 0; i < 2; i++) {
00398         PRINTF("%02X", short_uuid[i]);
00399       }
00400       PRINTF("\n\r");
00401 #endif
00402     } else if(type==UUID::UUID_TYPE_LONG) {
00403       
00404       uuid_type = UUID_TYPE_128;
00405       uuid = (unsigned char*)_matchingCharacteristicUUIDIn.getBaseUUID();
00406 #ifdef DEBUG
00407       PRINTF("(findServiceChars) C UUID-");
00408       for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
00409         PRINTF("%02X", uuid[i]);
00410       }
00411       PRINTF("\r\n");
00412 #endif
00413     }
00414 
00415     ret = aci_gatt_disc_charac_by_uuid(connectionHandle,
00416                                        service->getStartHandle(),
00417                                        service->getEndHandle(),
00418                                        uuid_type,
00419                                        uuid);
00420   }
00421   
00422   if(ret == BLE_STATUS_SUCCESS) {
00423     _servIndex++;
00424   }
00425   
00426   PRINTF("findServiceChars ret=%d\n\r", ret);
00427   
00428   return BLE_ERROR_NONE;
00429 }
00430 
00431 ble_error_t BlueNRGGattClient::launchServiceDiscovery(Gap::Handle_t                               connectionHandle,
00432                                                       ServiceDiscovery::ServiceCallback_t         sc,
00433                                                       ServiceDiscovery::CharacteristicCallback_t  cc,
00434                                                       const UUID                                 &matchingServiceUUID,
00435                                                       const UUID                                 &matchingCharacteristicUUIDIn)
00436 {
00437   PRINTF("launchServiceDiscovery\n\r");
00438   
00439   tBleStatus ret;
00440   uint8_t uuid_type = UUID_TYPE_16;
00441   uint8_t short_uuid[2];
00442   uint8_t *uuid = NULL;
00443   unsigned j;
00444 
00445   if(isServiceDiscoveryActive()) {
00446     return BLE_ERROR_OPERATION_NOT_PERMITTED;
00447   }
00448 
00449   if(!sc && !cc) {
00450     // nothing to do
00451     PRINTF("launchServiceDiscovery: nothing to do\n\r");
00452     return BLE_ERROR_NONE;
00453   }
00454 
00455   _connectionHandle = connectionHandle;
00456   serviceDiscoveryCallback = sc;
00457   characteristicDiscoveryCallback = cc;
00458   _matchingServiceUUID = matchingServiceUUID;
00459   _matchingCharacteristicUUIDIn = matchingCharacteristicUUIDIn;
00460 
00461   //reset services
00462   _numServices = 0;
00463   _numChars = 0;
00464   _servIndex = 0;
00465   for(j = 0; j < BLE_TOTAL_DISCOVERED_SERVICES; j++) {
00466     discoveredService[j].setup(BLE_UUID_UNKNOWN, GattAttribute::INVALID_HANDLE, GattAttribute::INVALID_HANDLE);
00467   }
00468   
00469   if(matchingServiceUUID == BLE_UUID_UNKNOWN) {
00470     
00471     // Wildcard: search for all services
00472     ret = aci_gatt_disc_all_prim_services((uint16_t)connectionHandle);
00473     
00474   } else {
00475   
00476     uint8_t type = matchingServiceUUID.shortOrLong();
00477     //PRINTF("AddService(): Type:%d\n\r", type);
00478     
00479     if(type == UUID::UUID_TYPE_SHORT) {
00480       STORE_LE_16(short_uuid, matchingServiceUUID.getShortUUID());
00481 #ifdef DEBUG
00482       PRINTF("launchServiceDiscovery short_uuid=0x");
00483       for(j = 0; j < 2; j++) {
00484         PRINTF("%02X", short_uuid[j]);
00485       }
00486       PRINTF("\n\r");
00487 #endif
00488       
00489       uuid_type = UUID_TYPE_16;
00490       uuid = short_uuid;
00491       
00492     } else if(type==UUID::UUID_TYPE_LONG) {
00493 
00494       uuid_type = UUID_TYPE_128;
00495       uuid = (unsigned char*)matchingServiceUUID.getBaseUUID();
00496 
00497 #ifdef DEBUG
00498       PRINTF("launchServiceDiscovery base_uuid=0x");
00499       for(j = 0; j < 16; j++) {
00500         PRINTF("%02X", uuid[j]);
00501       }
00502       PRINTF("\n\r");
00503 #endif
00504     }
00505     
00506     // search for specific service by UUID
00507     ret = aci_gatt_disc_prim_service_by_uuid((uint16_t)connectionHandle, uuid_type, uuid);
00508     //ret = aci_gatt_disc_all_prim_services((uint16_t)connectionHandle);
00509   }
00510     
00511   if(ret == BLE_STATUS_SUCCESS) {
00512     _currentState = GATT_SERVICE_DISCOVERY;
00513   }
00514   
00515   PRINTF("launchServiceDiscovery ret=%d\n\r", ret);
00516   
00517   return BLE_ERROR_NONE;
00518 }
00519 
00520 ble_error_t BlueNRGGattClient::discoverServices(Gap::Handle_t                        connectionHandle,
00521                                                 ServiceDiscovery::ServiceCallback_t  callback,
00522                                                 const UUID                          &matchingServiceUUID)
00523 {
00524   /* avoid compiler warnings about unused variables */
00525   (void)connectionHandle;
00526   (void)callback;
00527   (void)matchingServiceUUID;
00528 
00529   return BLE_ERROR_NOT_IMPLEMENTED;
00530 }
00531 
00532 ble_error_t BlueNRGGattClient::discoverServices(Gap::Handle_t                        connectionHandle,
00533                                                 ServiceDiscovery::ServiceCallback_t  callback,
00534                                                 GattAttribute::Handle_t              startHandle,
00535                                                 GattAttribute::Handle_t              endHandle)
00536 {
00537   /* avoid compiler warnings about unused variables */
00538   (void)connectionHandle;
00539   (void)callback;
00540   (void)startHandle;
00541   (void)endHandle;
00542 
00543   return BLE_ERROR_NOT_IMPLEMENTED;
00544 }
00545 
00546 bool BlueNRGGattClient::isServiceDiscoveryActive(void) const
00547 {
00548   if(_currentState == GATT_SERVICE_DISCOVERY) {
00549     return true;
00550   }
00551 
00552   return false;
00553 /*
00554   if(_currentState == GATT_IDLE ||
00555      _currentState == GATT_DISCOVERY_TERMINATED ||
00556        _currentState == GATT_READ_CHAR ||
00557          _currentState == GATT_WRITE_CHAR ) {
00558     return false;
00559   }
00560   
00561   return true;
00562 */
00563 }
00564 
00565 void BlueNRGGattClient::terminateServiceDiscovery(void)
00566 {
00567   _currentState = GATT_IDLE;//GATT_DISCOVERY_TERMINATED;
00568   
00569   if (terminationCallback) {
00570     terminationCallback(_connectionHandle);
00571   }
00572 }
00573 
00574 void BlueNRGGattClient::charReadCB(Gap::Handle_t connHandle,
00575                                    uint8_t event_data_length,
00576                                    uint8_t* attribute_value)
00577 {
00578   readCBParams.connHandle = connHandle;
00579   readCBParams.offset = 0;
00580   readCBParams.len = event_data_length;
00581   readCBParams.data = attribute_value;
00582 
00583   BlueNRGGattClient::getInstance().processReadResponse(&readCBParams);
00584 }
00585 
00586 ble_error_t BlueNRGGattClient::read(Gap::Handle_t connHandle, GattAttribute::Handle_t attributeHandle, uint16_t offset) const
00587 {
00588   /* avoid compiler warnings about unused variables */
00589   (void)offset;
00590 
00591   tBleStatus ret;
00592   
00593   BlueNRGGattClient *gattc = const_cast<BlueNRGGattClient*>(this);
00594   
00595   // Save the attribute_handle not provided by evt_att_read_resp    
00596   gattc->readCBParams.handle = attributeHandle;
00597   
00598   // FIXME: We need to wait for a while before starting a read
00599   // due to BlueNRG process queue handling
00600   Clock_Wait(100);
00601 
00602   ret = aci_gatt_read_charac_val(connHandle, attributeHandle);
00603   
00604   if(ret == BLE_STATUS_SUCCESS) {
00605     gattc->_currentState = GATT_READ_CHAR;
00606     return BLE_ERROR_NONE;
00607   }
00608   switch (ret) {
00609   case BLE_STATUS_BUSY:
00610     return BLE_STACK_BUSY;
00611   default:
00612     return BLE_ERROR_INVALID_STATE;
00613   }
00614 }
00615 
00616 void BlueNRGGattClient::charWritePrepareCB(Gap::Handle_t connHandle,
00617                                            uint8_t event_data_length,
00618                                            uint16_t attribute_handle,
00619                                            uint16_t offset,
00620                                            uint8_t *part_attr_value)
00621 {
00622   /* avoid compiler warnings about unused variables */
00623   (void)connHandle;
00624 
00625   // Update the write response params
00626   writeCBParams.handle = attribute_handle;
00627   writeCBParams.offset = offset;
00628   writeCBParams.len = event_data_length-4; //(?)
00629   writeCBParams.data = part_attr_value;
00630 
00631   BlueNRGGattClient::getInstance().processWriteResponse(&writeCBParams);
00632 }
00633 
00634 void BlueNRGGattClient::charWriteExecCB(Gap::Handle_t connHandle,
00635                                         uint8_t event_data_length)
00636 {
00637   /* avoid compiler warnings about unused variables */
00638   (void)event_data_length;
00639 
00640   writeCBParams.connHandle = connHandle;
00641   
00642   BlueNRGGattClient::getInstance().processWriteResponse(&writeCBParams);
00643 }
00644 
00645 ble_error_t BlueNRGGattClient::write(GattClient::WriteOp_t    cmd,
00646                                      Gap::Handle_t            connHandle,
00647                                      GattAttribute::Handle_t  attributeHandle,
00648                                      size_t                   length,
00649                                      const uint8_t           *value) const
00650 {
00651   /* avoid compiler warnings about unused variables */
00652   (void)cmd;
00653 
00654   tBleStatus ret;
00655   
00656   BlueNRGGattClient *gattc = const_cast<BlueNRGGattClient*>(this);
00657   
00658   // We save the write response params (used by the callback) because
00659   // when the aci_gatt_write_charac_value() is used the only event received is the EVT_BLUE_GATT_PROCEDURE_COMPLETE
00660   gattc->writeCBParams.connHandle = connHandle;
00661   gattc->writeCBParams.writeOp = GattWriteCallbackParams::OP_WRITE_CMD;
00662   gattc->writeCBParams.handle = attributeHandle;
00663   gattc->writeCBParams.offset = 0;
00664   gattc->writeCBParams.len = length;
00665   gattc->writeCBParams.data = value;
00666   
00667   ret = aci_gatt_write_charac_value(connHandle, attributeHandle, length, const_cast<uint8_t *>(value));
00668   //ret = aci_gatt_write_charac_reliable(connHandle, attributeHandle, 0, length, const_cast<uint8_t *>(value));
00669   
00670   if (ret == BLE_STATUS_SUCCESS) {
00671     gattc->_currentState = GATT_WRITE_CHAR;
00672     return BLE_ERROR_NONE;
00673   }
00674   switch (ret) {
00675   case BLE_STATUS_BUSY:
00676     return BLE_STACK_BUSY;
00677   default:
00678     return BLE_ERROR_INVALID_STATE;
00679   }
00680 
00681 }
00682 
00683 void BlueNRGGattClient::discAllCharacDescCB(Gap::Handle_t connHandle,
00684                                             uint8_t event_data_length,
00685                                             uint8_t format,
00686                                             uint8_t *handle_uuid_pair) {
00687   GattAttribute::Handle_t attHandle;
00688   UUID uuid;
00689   uint8_t i, numCharacDesc, offset, handle_uuid_length;
00690 
00691   handle_uuid_length = 4; //Handle + UUID_16
00692   if (format == 2)
00693     handle_uuid_length = 18; //Handle + UUID_128
00694 
00695   numCharacDesc = (event_data_length - 1) / handle_uuid_length;
00696   
00697   offset = 0;
00698 
00699   for (i=0; i<numCharacDesc; i++) {
00700     attHandle = handle_uuid_pair[offset];
00701 
00702     // UUID Type
00703     if (handle_uuid_length == 4) {
00704       
00705       PRINTF("UUID_TYPE_16\n\r");
00706       uuid = handle_uuid_pair[offset+3]<<8|handle_uuid_pair[offset+2];
00707       PRINTF("D UUID-%X attHandle=%u\r\n", uuid.getShortUUID(), attHandle);
00708       
00709     } else {
00710       
00711       PRINTF("UUID_TYPE_128\n\r");
00712       uuid.setupLong(handle_uuid_pair+offset+2, UUID::LSB);
00713 #ifdef DEBUG
00714       PRINTF("D UUID-");
00715       const uint8_t *longUUIDBytes = uuid.getBaseUUID();
00716       for (unsigned j = 0; j < UUID::LENGTH_OF_LONG_UUID; j++) {
00717         PRINTF("%02x", longUUIDBytes[j]);
00718       }
00719 #endif
00720      }
00721 
00722      if(charDescDiscoveryCallback != NULL) {
00723        CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t params = {
00724                                  _characteristic,
00725                                  DiscoveredCharacteristicDescriptor(
00726                                    _characteristic.getGattClient(),
00727                                    connHandle,
00728                                    attHandle,
00729                                    uuid
00730                                  )
00731        };
00732        charDescDiscoveryCallback(&params);
00733      }
00734 
00735     _numCharDesc++;
00736 
00737     offset += handle_uuid_length;
00738   }
00739 
00740   if(charDescTerminationCallback != NULL) {
00741      CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = {
00742                                _characteristic,
00743                                BLE_ERROR_NONE
00744      };
00745      charDescTerminationCallback(&params);
00746    }
00747 
00748 }
00749 
00750 ble_error_t BlueNRGGattClient::discoverCharacteristicDescriptors(
00751         const DiscoveredCharacteristic& characteristic,
00752         const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
00753         const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback) {
00754 
00755   tBleStatus ret;
00756 
00757   if(_currentState != GATT_IDLE) {
00758     return BLE_ERROR_OPERATION_NOT_PERMITTED;
00759   }
00760 
00761   charDescDiscoveryCallback = discoveryCallback;
00762   charDescTerminationCallback = terminationCallback;
00763 
00764   Gap::Handle_t connHandle = characteristic.getConnectionHandle();
00765   GattAttribute::Handle_t valueHandle = characteristic.getValueHandle();
00766   GattAttribute::Handle_t lastHandle = characteristic.getLastHandle();
00767 
00768   PRINTF("Starting aci_gatt_disc_all_charac_descriptors...\n\r");
00769   ret = aci_gatt_disc_all_charac_descriptors(connHandle, valueHandle, lastHandle);
00770 
00771   if (ret == BLE_STATUS_SUCCESS) {
00772     _currentState = GATT_CHAR_DESC_DISCOVERY;
00773     _characteristic = characteristic;
00774     return BLE_ERROR_NONE;
00775   }
00776   switch (ret) {
00777   case BLE_STATUS_INVALID_PARAMS:
00778     return BLE_ERROR_INVALID_PARAM;
00779   default:
00780     return BLE_ERROR_OPERATION_NOT_PERMITTED;
00781   }
00782 }
00783 
00784 /**************************************************************************/
00785 /*!
00786     @brief  Clear BlueNRGGattServer's state.
00787 
00788     @returns    ble_error_t
00789 
00790     @retval     BLE_ERROR_NONE
00791                 Everything executed properly
00792 */
00793 /**************************************************************************/
00794 ble_error_t BlueNRGGattClient::reset(void) {
00795   /* Clear all state that is from the parent, including private members */
00796   if (GattClient::reset() != BLE_ERROR_NONE) {
00797     return BLE_ERROR_INVALID_STATE;
00798   }
00799 
00800   _currentState = GATT_IDLE;
00801   _matchingServiceUUID = BLE_UUID_UNKNOWN;
00802   _matchingCharacteristicUUIDIn = BLE_UUID_UNKNOWN;
00803 
00804   _numServices = 0;
00805   _servIndex = 0;
00806   _numChars = 0;
00807   _numCharDesc = 0;
00808 
00809   /* Clear class members */
00810   memset(discoveredService, 0, sizeof(discoveredService));
00811   memset(discoveredChar, 0, sizeof(discoveredChar));
00812 
00813   return BLE_ERROR_NONE;
00814 }
00815