BLE shield

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 "mbed.h"
00041 #include "BlueNRGGap.h"
00042 #include "Utils.h"
00043 #include "debug.h"
00044 
00045 static uint8_t props_mask[] = {
00046   0x01,
00047   0x02,
00048   0x04,
00049   0x08,
00050   0x10,
00051   0x20,
00052   0x40,
00053   0x80
00054   };
00055 
00056 void BlueNRGGattClient::gattProcedureCompleteCB(Gap::Handle_t connectionHandle, uint8_t error_code)
00057 {
00058   if(error_code != BLE_STATUS_SUCCESS) {
00059     return;
00060   }
00061     
00062   // Service Discovery complete
00063   if(_currentState != GATT_IDLE && 
00064      _currentState != GATT_DISCOVERY_TERMINATED &&
00065        _currentState != GATT_WRITE_CHAR &&
00066          _currentState != GATT_READ_CHAR) {
00067              
00068     findServiceChars(connectionHandle);
00069   }
00070   
00071   if(_currentState == GATT_WRITE_CHAR) {
00072     BlueNRGGattClient::getInstance().processWriteResponse(&writeCBParams);
00073     _currentState = GATT_IDLE;
00074   }
00075 }
00076                                                 
00077 void BlueNRGGattClient::primaryServicesCB(Gap::Handle_t connectionHandle,
00078                                           uint8_t event_data_length,
00079                                           uint8_t attribute_data_length,
00080                                           uint8_t *attribute_data_list)
00081 {
00082   GattAttribute::Handle_t startHandle, endHandle;
00083   UUID uuid;
00084   uint8_t i, offset, numAttr;
00085   /* avoid compiler warnings about unused variables */
00086   (void)connectionHandle;
00087 
00088   numAttr = (event_data_length - 1) / attribute_data_length;
00089 
00090   offset = 0;
00091   for (i=0; i<numAttr; i++) {
00092     startHandle = attribute_data_list[offset];
00093     endHandle = attribute_data_list[offset+2];
00094 
00095     // UUID Type
00096     if (attribute_data_length == 6) {
00097       
00098       PRINTF("UUID_TYPE_16\n\r");
00099       uuid = attribute_data_list[offset+5]<<8|attribute_data_list[offset+4];
00100       PRINTF("S UUID-%X attrs[%u %u]\r\n", uuid.getShortUUID(), startHandle, endHandle);
00101       
00102     } else {
00103       
00104       PRINTF("UUID_TYPE_128\n\r");
00105       uuid.setupLong(attribute_data_list+offset+4);
00106       
00107       PRINTF("S UUID-");
00108 #ifdef DEBUG
00109       const uint8_t *longUUIDBytes = uuid.getBaseUUID();
00110       for (unsigned j = 0; j < UUID::LENGTH_OF_LONG_UUID; j++) {
00111         PRINTF("%02x", longUUIDBytes[j]);
00112       }
00113 #endif
00114       PRINTF(" attrs[%u %u]\r\n", startHandle, endHandle);
00115       
00116     }
00117     
00118     PRINTF("Setup serviceIndex = %d\n\r", _numServices);
00119     discoveredService[_numServices].setup(uuid, startHandle, endHandle);
00120     
00121     if(serviceDiscoveryCallback) {
00122       if(_matchingServiceUUID == BLE_UUID_UNKNOWN || _matchingServiceUUID == discoveredService[_numServices].getUUID()) {
00123         serviceDiscoveryCallback(&discoveredService[_numServices]);
00124       }
00125     }
00126     _numServices++;
00127 
00128     offset += attribute_data_length;
00129   }
00130 
00131   PRINTF("!!!Service Discovery complete (numAttr=%u)!!!\n\r", numAttr);
00132 
00133 }
00134 
00135 void BlueNRGGattClient::primaryServiceCB(Gap::Handle_t connectionHandle,
00136                                          uint8_t event_data_length,
00137                                          uint8_t *handles_info_list)
00138 {
00139   GattAttribute::Handle_t startHandle, endHandle;
00140   UUID uuid;
00141   uint8_t i, offset, numHandlePairs;
00142   /* avoid compiler warnings about unused variables */
00143   (void)connectionHandle;
00144 
00145   numHandlePairs = (event_data_length - 1) / 2;
00146 
00147   offset = 0;
00148   for (i=0; i<numHandlePairs; i++) {
00149     startHandle = handles_info_list[offset];
00150     endHandle = handles_info_list[offset+2];
00151 
00152     PRINTF("primaryServiceCB attrs[%u %u]\r\n", startHandle, endHandle);
00153     
00154     discoveredService[i].setup(_matchingServiceUUID, startHandle, endHandle);
00155     
00156     if(serviceDiscoveryCallback) {
00157       serviceDiscoveryCallback(&discoveredService[_numServices]);
00158     }
00159     _numServices++;
00160     
00161     offset += 4;
00162   }
00163 }
00164 
00165 void BlueNRGGattClient::serviceCharsCB(Gap::Handle_t connectionHandle,
00166                                        uint8_t event_data_length,
00167                                        uint8_t handle_value_pair_length,
00168                                        uint8_t *handle_value_pair)
00169 {
00170   // Charac Handle (2), Charac Properties(1), Charac Value Handle(2), Charac UUID(2/16)
00171 
00172   GattAttribute::Handle_t declHandle, valueHandle;
00173   UUID uuid;
00174   uint8_t i, numChar, offset;
00175 
00176   numChar = (event_data_length - 1) / handle_value_pair_length;
00177 
00178   offset = 0;
00179   for (i=0; i<numChar; i++) {
00180     // UUID Type
00181     if (handle_value_pair_length == 7) {
00182       PRINTF("Char UUID_TYPE_16\n\r");
00183       uuid = handle_value_pair[offset+6]<<8|handle_value_pair[offset+5];
00184       PRINTF("C UUID-%X\r\n", uuid.getShortUUID());
00185     } else {
00186       PRINTF("Char UUID_TYPE_128\n\r");
00187       uuid.setupLong(handle_value_pair+offset+5);
00188       PRINTF("C UUID-");
00189 #ifdef DEBUG
00190       const uint8_t *longUUIDBytes = uuid.getBaseUUID();
00191       for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
00192         PRINTF("%02X", longUUIDBytes[i]);
00193       }
00194       PRINTF("\r\n");
00195 #endif
00196     }
00197     
00198     // Properties
00199     DiscoveredCharacteristic::Properties_t p;
00200     
00201     p._broadcast = (props_mask[0] & handle_value_pair[offset+2]);
00202     p._read = (props_mask[1] & handle_value_pair[offset+2])>>1;
00203     p._writeWoResp = (props_mask[2] & handle_value_pair[offset+2])>>2;
00204     p._write = (props_mask[3] & handle_value_pair[offset+2])>>3;
00205     p._notify = (props_mask[4] & handle_value_pair[offset+2])>>4;
00206     p._indicate = (props_mask[5] & handle_value_pair[offset+2])>>5;
00207     p._authSignedWrite = (props_mask[6] & handle_value_pair[offset+2])>>6;
00208     PRINTF("p._broadcast=%d\n\r", p._broadcast);
00209     PRINTF("p._read=%d\n\r", p._read);
00210     PRINTF("p._writeWoResp=%d\n\r", p._writeWoResp);
00211     PRINTF("p._write=%d\n\r", p._write);
00212     PRINTF("p._notify=%d\n\r", p._notify);
00213     PRINTF("p._indicate=%d\n\r", p._indicate);
00214     PRINTF("p._authSignedWrite=%d\n\r", p._authSignedWrite);
00215 
00216     /*
00217     uint8_t props = handle_value_pair[offset+2];
00218     PRINTF("CHAR PROPS: %d\n\r", props);
00219     */
00220 
00221     // Handles
00222     declHandle = handle_value_pair[offset];
00223     valueHandle = handle_value_pair[offset+3];
00224 
00225     discoveredChar[_numChars].setup(this,
00226                                     connectionHandle,
00227                                     uuid,
00228                                     p,
00229                                     declHandle,
00230                                     valueHandle);
00231 
00232     if(characteristicDiscoveryCallback) {
00233       characteristicDiscoveryCallback(&discoveredChar[_numChars]);
00234     }
00235     _numChars++;
00236 
00237     offset += handle_value_pair_length;
00238   }
00239 }
00240 
00241 void BlueNRGGattClient::serviceCharByUUIDCB(Gap::Handle_t connectionHandle,
00242                                             uint8_t event_data_length,
00243                                             uint16_t attr_handle,
00244                                             uint8_t *attr_value)
00245 {
00246   // Charac Properties(1), Charac Value Handle(2), Charac UUID(2/16)
00247   GattAttribute::Handle_t declHandle, valueHandle;
00248   UUID uuid;
00249   
00250   PRINTF("serviceCharByUUIDCB\n\r");
00251   
00252   // UUID Type
00253   if (event_data_length == 7) {
00254     PRINTF("Char UUID_TYPE_16\n\r");
00255     uuid = attr_value[4]<<8|attr_value[3];
00256     PRINTF("C UUID-%X\r\n", uuid.getShortUUID());
00257   } else {
00258     PRINTF("Char UUID_TYPE_128\n\r");
00259     uuid.setupLong(attr_value+3);
00260     PRINTF("C UUID-");
00261 #ifdef DEBUG
00262     const uint8_t *longUUIDBytes = uuid.getBaseUUID();
00263     for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
00264       PRINTF("%02X", longUUIDBytes[i]);
00265     }
00266     PRINTF("\r\n");
00267 #endif
00268   }
00269 
00270   // Properties
00271   DiscoveredCharacteristic::Properties_t p;
00272   
00273   p._broadcast = (props_mask[0] & attr_value[0]);
00274   p._read = (props_mask[1] & attr_value[0])>>1;
00275   p._writeWoResp = (props_mask[2] & attr_value[0])>>2;
00276   p._write = (props_mask[3] & attr_value[0])>>3;
00277   p._notify = (props_mask[4] & attr_value[0])>>4;
00278   p._indicate = (props_mask[5] & attr_value[0])>>5;
00279   p._authSignedWrite = (props_mask[6] & attr_value[0])>>6;
00280   PRINTF("p._broadcast=%d\n\r", p._broadcast);
00281   PRINTF("p._read=%d\n\r", p._read);
00282   PRINTF("p._writeWoResp=%d\n\r", p._writeWoResp);
00283   PRINTF("p._write=%d\n\r", p._write);
00284   PRINTF("p._notify=%d\n\r", p._notify);
00285   PRINTF("p._indicate=%d\n\r", p._indicate);
00286   PRINTF("p._authSignedWrite=%d\n\r", p._authSignedWrite);
00287 
00288   /*
00289   uint8_t props = attr_value[0];
00290   PRINTF("CHAR PROPS: %d\n\r", props);
00291   */
00292 
00293   // Handles
00294   declHandle = attr_handle;
00295   valueHandle = attr_value[1];
00296 
00297   discoveredChar[_numChars].setup(this,
00298                                   connectionHandle,
00299                                   uuid,
00300                                   p,
00301                                   declHandle,
00302                                   valueHandle);
00303   
00304   if(characteristicDiscoveryCallback) {
00305     characteristicDiscoveryCallback(&discoveredChar[_numChars]);
00306   }
00307   _numChars++;
00308 }
00309 
00310 ble_error_t BlueNRGGattClient::findServiceChars(Gap::Handle_t connectionHandle)
00311 {
00312   PRINTF("findServiceChars\n\r");
00313   
00314   tBleStatus ret;
00315   uint8_t uuid_type = UUID_TYPE_16;
00316   uint8_t short_uuid[2];
00317   uint8_t *uuid = NULL;
00318   
00319   DiscoveredService *service;
00320   
00321   // We finished chars discovery for all services
00322   if(_servIndex >= _numServices) {
00323     PRINTF("!!!We finished chars discovery for all services!!!\n\r");
00324     _currentState = GATT_CHARS_DISCOVERY_COMPLETE;
00325     
00326     terminateServiceDiscovery();
00327     
00328     return BLE_ERROR_NONE;
00329   }
00330     
00331   service = &discoveredService[_servIndex];
00332   /*
00333   if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
00334     PRINTF("S UUID-%X\r\n", service->getUUID().getShortUUID());
00335   } else {
00336     PRINTF("S UUID-");
00337     const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
00338     for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
00339       PRINTF("%02X", longUUIDBytes[i]);
00340     }
00341     PRINTF("\r\n");
00342   }
00343   */
00344   
00345   PRINTF("findServiceChars (_servIndex=%d)\n\r", _servIndex);
00346   //ret = aci_gatt_disc_all_charac_of_serv(connectionHandle, service->getStartHandle(), service->getEndHandle());
00347 
00348   if(_matchingCharacteristicUUIDIn == BLE_UUID_UNKNOWN) {
00349     PRINTF("findServiceChars (BLE_UUID_UNKNOWN)\n\r");
00350     ret = aci_gatt_disc_all_charac_of_serv(connectionHandle, service->getStartHandle(), service->getEndHandle());
00351   } else {
00352     
00353     uint8_t type = _matchingCharacteristicUUIDIn.shortOrLong();
00354     
00355     if(type == UUID::UUID_TYPE_SHORT) {
00356       STORE_LE_16(short_uuid, _matchingCharacteristicUUIDIn.getShortUUID());
00357       
00358       uuid_type = UUID_TYPE_16;
00359       uuid = short_uuid;
00360       
00361       PRINTF("findServiceChars C UUID-");
00362       for(unsigned i = 0; i < 2; i++) {
00363         PRINTF("%02X", short_uuid[i]);
00364       }
00365       PRINTF("\n\r");
00366 
00367     } else if(type==UUID::UUID_TYPE_LONG) {
00368       
00369       uuid_type = UUID_TYPE_128;
00370       uuid = (unsigned char*)_matchingCharacteristicUUIDIn.getBaseUUID();
00371       
00372       PRINTF("(findServiceChars) C UUID-");
00373       for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
00374         PRINTF("%02X", uuid[i]);
00375       }
00376       PRINTF("\r\n");
00377     }
00378 
00379     ret = aci_gatt_disc_charac_by_uuid(connectionHandle,
00380                                        service->getStartHandle(),
00381                                        service->getEndHandle(),
00382                                        uuid_type,
00383                                        uuid);
00384   }
00385   
00386   if(ret == BLE_STATUS_SUCCESS) {
00387     _servIndex++;
00388   }
00389   
00390   PRINTF("findServiceChars ret=%d\n\r", ret);
00391   
00392   return BLE_ERROR_NONE;
00393 }
00394 
00395 ble_error_t BlueNRGGattClient::launchServiceDiscovery(Gap::Handle_t                               connectionHandle,
00396                                                       ServiceDiscovery::ServiceCallback_t         sc,
00397                                                       ServiceDiscovery::CharacteristicCallback_t  cc,
00398                                                       const UUID                                 &matchingServiceUUID,
00399                                                       const UUID                                 &matchingCharacteristicUUIDIn)
00400 {
00401   PRINTF("launchServiceDiscovery\n\r");
00402   
00403   tBleStatus ret;
00404   uint8_t uuid_type = UUID_TYPE_16;
00405   uint8_t short_uuid[2];
00406   uint8_t *uuid = NULL;
00407   unsigned j;
00408   
00409   _connectionHandle = connectionHandle;
00410   serviceDiscoveryCallback = sc;
00411   characteristicDiscoveryCallback = cc;
00412   _matchingServiceUUID = matchingServiceUUID;
00413   _matchingCharacteristicUUIDIn = matchingCharacteristicUUIDIn;
00414 
00415   //reset services
00416   _numServices = 0;
00417   _numChars = 0;
00418   _servIndex = 0;
00419   for(j = 0; j < BLE_TOTAL_DISCOVERED_SERVICES; j++) {
00420     discoveredService[j].setup(BLE_UUID_UNKNOWN, GattAttribute::INVALID_HANDLE, GattAttribute::INVALID_HANDLE);
00421   }
00422   
00423   if(matchingServiceUUID == BLE_UUID_UNKNOWN) {
00424     
00425     // Wildcard: search for all services
00426     ret = aci_gatt_disc_all_prim_services((uint16_t)connectionHandle);
00427     
00428   } else {
00429   
00430     uint8_t type = matchingServiceUUID.shortOrLong();
00431     //PRINTF("AddService(): Type:%d\n\r", type);
00432     
00433     if(type == UUID::UUID_TYPE_SHORT) {
00434       STORE_LE_16(short_uuid, matchingServiceUUID.getShortUUID());
00435       
00436       PRINTF("launchServiceDiscovery short_uuid=0x");
00437       for(j = 0; j < 2; j++) {
00438         PRINTF("%02X", short_uuid[j]);
00439       }
00440       PRINTF("\n\r");
00441       
00442       
00443       uuid_type = UUID_TYPE_16;
00444       uuid = short_uuid;
00445       
00446     } else if(type==UUID::UUID_TYPE_LONG) {
00447 
00448       uuid_type = UUID_TYPE_128;
00449       uuid = (unsigned char*)matchingServiceUUID.getBaseUUID();
00450       
00451       /*
00452       PRINTF("launchServiceDiscovery base_uuid=0x");
00453       for(j = 0; j < 16; j++) {
00454         PRINTF("%02X", uuid[j]);
00455       }
00456       PRINTF("\n\r");
00457       */
00458     }
00459     
00460     // search for specific service by UUID
00461     ret = aci_gatt_disc_prim_service_by_uuid((uint16_t)connectionHandle, uuid_type, uuid);
00462     //ret = aci_gatt_disc_all_prim_services((uint16_t)connectionHandle);
00463   }
00464     
00465   if(ret == BLE_STATUS_SUCCESS) {
00466     _currentState = GATT_SERVICE_DISCOVERY;
00467   }
00468   
00469   PRINTF("launchServiceDiscovery ret=%d\n\r", ret);
00470   
00471   return BLE_ERROR_NONE;
00472 }
00473 
00474 ble_error_t BlueNRGGattClient::discoverServices(Gap::Handle_t                        connectionHandle,
00475                                                 ServiceDiscovery::ServiceCallback_t  callback,
00476                                                 const UUID                          &matchingServiceUUID)
00477 {
00478   /* avoid compiler warnings about unused variables */
00479   (void)connectionHandle;
00480   (void)callback;
00481   (void)matchingServiceUUID;
00482 
00483   return BLE_ERROR_NOT_IMPLEMENTED;
00484 }
00485 
00486 ble_error_t BlueNRGGattClient::discoverServices(Gap::Handle_t                        connectionHandle,
00487                                                 ServiceDiscovery::ServiceCallback_t  callback,
00488                                                 GattAttribute::Handle_t              startHandle,
00489                                                 GattAttribute::Handle_t              endHandle)
00490 {
00491   /* avoid compiler warnings about unused variables */
00492   (void)connectionHandle;
00493   (void)callback;
00494   (void)startHandle;
00495   (void)endHandle;
00496 
00497   return BLE_ERROR_NOT_IMPLEMENTED;
00498 }
00499 
00500 bool BlueNRGGattClient::isServiceDiscoveryActive(void) const
00501 {
00502   if(_currentState == GATT_IDLE ||
00503      _currentState == GATT_DISCOVERY_TERMINATED ||
00504        _currentState == GATT_READ_CHAR ||
00505          _currentState == GATT_WRITE_CHAR ) {
00506     return false;
00507   }
00508   
00509   return true;
00510 }
00511 
00512 void BlueNRGGattClient::terminateServiceDiscovery(void)
00513 {
00514   _currentState = GATT_DISCOVERY_TERMINATED;
00515   
00516   if (terminationCallback) {
00517     terminationCallback(_connectionHandle);
00518   }
00519 }
00520 
00521 void BlueNRGGattClient::charReadCB(Gap::Handle_t connHandle,
00522                                    uint8_t event_data_length,
00523                                    uint8_t* attribute_value)
00524 {
00525   readCBParams.connHandle = connHandle;
00526   readCBParams.offset = 0;
00527   readCBParams.len = event_data_length;
00528   readCBParams.data = attribute_value;
00529 
00530   BlueNRGGattClient::getInstance().processReadResponse(&readCBParams);
00531 }
00532 
00533 ble_error_t BlueNRGGattClient::read(Gap::Handle_t connHandle, GattAttribute::Handle_t attributeHandle, uint16_t offset) const
00534 {
00535   /* avoid compiler warnings about unused variables */
00536   (void)offset;
00537 
00538   tBleStatus ret;
00539   
00540   BlueNRGGattClient *gattc = const_cast<BlueNRGGattClient*>(this);
00541   
00542   gattc->_currentState = GATT_READ_CHAR;
00543   
00544   // Save the attribute_handle not provided by evt_att_read_resp    
00545   gattc->readCBParams.handle = attributeHandle;
00546   
00547   // FIXME: We need to wait for a while before starting a read
00548   // due to BlueNRG process queue handling
00549   Clock_Wait(100);
00550 
00551   ret = aci_gatt_read_charac_val(connHandle, attributeHandle);
00552   
00553   if(ret == BLE_STATUS_SUCCESS) {
00554     return BLE_ERROR_NONE;
00555   }
00556   switch (ret) {
00557   case BLE_STATUS_BUSY:
00558     return BLE_STACK_BUSY;
00559   default:
00560     return BLE_ERROR_INVALID_STATE;
00561   }
00562 }
00563 
00564 void BlueNRGGattClient::charWritePrepareCB(Gap::Handle_t connHandle,
00565                                            uint8_t event_data_length,
00566                                            uint16_t attribute_handle,
00567                                            uint16_t offset,
00568                                            uint8_t *part_attr_value)
00569 {
00570   /* avoid compiler warnings about unused variables */
00571   (void)connHandle;
00572 
00573   // Update the write response params
00574   writeCBParams.handle = attribute_handle;
00575   writeCBParams.offset = offset;
00576   writeCBParams.len = event_data_length-4; //(?)
00577   writeCBParams.data = part_attr_value;
00578 
00579   BlueNRGGattClient::getInstance().processWriteResponse(&writeCBParams);
00580 }
00581 
00582 void BlueNRGGattClient::charWriteExecCB(Gap::Handle_t connHandle,
00583                                         uint8_t event_data_length)
00584 {
00585   /* avoid compiler warnings about unused variables */
00586   (void)event_data_length;
00587 
00588   writeCBParams.connHandle = connHandle;
00589   
00590   BlueNRGGattClient::getInstance().processWriteResponse(&writeCBParams);
00591 }
00592 
00593 ble_error_t BlueNRGGattClient::write(GattClient::WriteOp_t    cmd,
00594                                      Gap::Handle_t            connHandle,
00595                                      GattAttribute::Handle_t  attributeHandle,
00596                                      size_t                   length,
00597                                      const uint8_t           *value) const
00598 {
00599   /* avoid compiler warnings about unused variables */
00600   (void)cmd;
00601 
00602   tBleStatus ret;
00603   
00604   BlueNRGGattClient *gattc = const_cast<BlueNRGGattClient*>(this);
00605     
00606   gattc->_currentState = GATT_WRITE_CHAR;
00607   
00608   // We save the write response params (used by the callback) because
00609   // when the aci_gatt_write_charac_value() is used the only event received is the EVT_BLUE_GATT_PROCEDURE_COMPLETE
00610   gattc->writeCBParams.connHandle = connHandle;
00611   gattc->writeCBParams.writeOp = GattWriteCallbackParams::OP_WRITE_CMD;
00612   gattc->writeCBParams.handle = attributeHandle;
00613   gattc->writeCBParams.offset = 0;
00614   gattc->writeCBParams.len = length;
00615   gattc->writeCBParams.data = value;
00616   
00617   ret = aci_gatt_write_charac_value(connHandle, attributeHandle, length, const_cast<uint8_t *>(value));
00618   //ret = aci_gatt_write_charac_reliable(connHandle, attributeHandle, 0, length, const_cast<uint8_t *>(value));
00619   
00620   if (ret == BLE_STATUS_SUCCESS) {
00621     return BLE_ERROR_NONE;
00622   }
00623   switch (ret) {
00624   case BLE_STATUS_BUSY:
00625     return BLE_STACK_BUSY;
00626   default:
00627     return BLE_ERROR_INVALID_STATE;
00628   }
00629 
00630 }