Other Parts Discussed in Thread: SIMPLELINK-CC2640R2-SDK,
Tool/software: Code Composer Studio
Hello All,
I am working on SIMPLELINK-CC2640R2-SDK_3.10.00.15
Currently i am working on ble cc2640r2f launchpad.
Below i have attached my code that receive data ,store data and send/.write same data to uart.
But facing issue when write or read data to/from external flash, the data getting duplicate or over written on other data when writing on uart.
In this multi role project i will receive the sensor data from 2 or more BLE module periodically in simplegattprofile.c file then will store/write data in external flash and the read it and then written on uart.
But in below code duplication and loss is found.
So please help me out to solve this issue or provide your valuable suggestion.
Here my code and the function that i am using....
@file multi_role.c
// How often to perform periodic event (in msec)
int READ_PERIOD = 149;
int WRITE_UART = 79;
#define flashbufsize 5000
#define extbuffer 0x61000
uint8_t simple1handle = 45;//34;
uint8_t simple3handle = 51;//40;
void write_to_flash(uint8_t *buf,int buf_size)
{
if(writecount>=flashbufsize)
{
n=0;
writecount=0;
readcount=0;
ExtFlash_open();
ExtFlash_erase(extbuffer,flashbufsize*5);
ExtFlash_close();
}
ExtFlash_open();
writereturn = ExtFlash_write(extbuffer+(writecount*buf_size),buf_size,buf);
DELAY_MS(10);
ExtFlash_close();
writecount++;
n++;
}
void read_from_flash(uint8_t *buf,int buf_size)
{
if(readcount<writecount)
{
ExtFlash_open();
readreturn = ExtFlash_read(extbuffer+(readcount*buf_size),buf_size,buf);
//DELAY_MS(10);
ExtFlash_close();
readcount++;
}
}
static void readCallback(UART_Handle uart, void *rxBuf, size_t size)
{
//rxBytes = UART_read(uart, startaddress, wantedRxBytes);
return;
}
static void writeCallback(UART_Handle uart, void *rxBuf, size_t size)
{
return;
}
static void multi_role_init(void)
{
// ******************************************************************
// N0 STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp
// ******************************************************************
// Register the current thread as an ICall dispatcher application
// so that the application can send and receive messages.
ICall_registerApp(&selfEntity, &syncEvent);
PIN_setOutputValue(hGpioPin, Board_RLED, Board_LED_ON);
DELAY_MS(100);
PIN_setOutputValue(hGpioPin, Board_RLED, Board_LED_OFF);
DELAY_MS(100);
PIN_setOutputValue(hGpioPin, Board_RLED, Board_LED_ON);
DELAY_MS(100);
PIN_setOutputValue(hGpioPin, Board_RLED, Board_LED_OFF);
DELAY_MS(100);
PIN_setOutputValue(hGpioPin, Board_RLED, Board_LED_ON);
DELAY_MS(100);
PIN_setOutputValue(hGpioPin, Board_RLED, Board_LED_OFF);
// Create an RTOS queue for message from profile to be sent to app.
appMsgQueue = Util_constructQueue(&appMsg);
init_whatch();
// Create one-shot clocks for internal periodic events.
Util_constructClock(&read_clock, multi_role_clockHandler,
READ_PERIOD, 0, false,READ_UART_DATA_EVT);
Util_constructClock(&buffer_clock, multi_role_clockHandler,
SEND_PERIOD, 0, false,SEND_BUFFER_DATA);
Util_constructClock(&write_uart_clock, multi_role_clockHandler,
WRITE_UART, 0, false,UART_WRITE_EVT);
Util_constructClock(&ack_clock, multi_role_clockHandler,
ACK_PERIOD, 0, false, ACK_TIMEOUT_EVT);
Util_constructClock(&reset_clock, multi_role_clockHandler,
RESET_PERIOD, 0, false,RESET_EVT);
Util_constructClock(&time_rqt_clock, multi_role_clockHandler,
TIME_RQT_PERIOD, 0, false,TIME_RQT_EVT);
//Util_constructClock(&signal_clock, multi_role_clockHandler,
//SIGNAL_PERIOD, 0, false,SIGNAL_EVT );
Util_constructClock(&ble_stat_clock, multi_role_clockHandler,
BLE_STAT_PERIOD, 0, false,BLE_STAT_EVT);
HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_5_DBM);
// Setup the GAP
{
// Set advertising interval the same for all scenarios
uint16_t advInt = DEFAULT_ADVERTISING_INTERVAL;
GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MIN, advInt);
GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MAX, advInt);
GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, advInt);
GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, advInt);
GAP_SetParamValue(TGAP_CONN_ADV_INT_MIN, advInt);
GAP_SetParamValue(TGAP_CONN_ADV_INT_MAX, advInt);
// Set scan duration
GAP_SetParamValue(TGAP_GEN_DISC_SCAN, DEFAULT_SCAN_DURATION);
// Scan interval and window the same for all scenarios
GAP_SetParamValue(TGAP_CONN_SCAN_INT, DEFAULT_SCAN_INT);
GAP_SetParamValue(TGAP_CONN_SCAN_WIND, DEFAULT_SCAN_WIND);
GAP_SetParamValue(TGAP_CONN_HIGH_SCAN_INT, DEFAULT_SCAN_INT);
GAP_SetParamValue(TGAP_CONN_HIGH_SCAN_WIND, DEFAULT_SCAN_WIND);
GAP_SetParamValue(TGAP_GEN_DISC_SCAN_INT, DEFAULT_SCAN_INT);
GAP_SetParamValue(TGAP_GEN_DISC_SCAN_WIND, DEFAULT_SCAN_WIND);
GAP_SetParamValue(TGAP_LIM_DISC_SCAN_INT, DEFAULT_SCAN_INT);
GAP_SetParamValue(TGAP_LIM_DISC_SCAN_WIND, DEFAULT_SCAN_WIND);
GAP_SetParamValue(TGAP_CONN_EST_SCAN_INT, DEFAULT_SCAN_INT);
GAP_SetParamValue(TGAP_CONN_EST_SCAN_WIND, DEFAULT_SCAN_WIND);
// Set connection parameters
GAP_SetParamValue(TGAP_CONN_EST_INT_MIN, 8);
GAP_SetParamValue(TGAP_CONN_EST_INT_MAX, DEFAULT_CONN_INT);
GAP_SetParamValue(TGAP_CONN_EST_SUPERV_TIMEOUT, DEFAULT_CONN_TIMEOUT);
GAP_SetParamValue(TGAP_CONN_EST_LATENCY, DEFAULT_CONN_LATENCY);
// Register to receive GAP and HCI messages
GAP_RegisterForMsgs(selfEntity);
}
// Setup the GAP Role Profile
{
/*--------PERIPHERAL-------------*/
uint8_t initialAdvertEnable = TRUE;
uint16_t advertOffTime = 0;
// device starts advertising upon initialization
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
&initialAdvertEnable, NULL);
// By setting this to zero, the device will go into the waiting state after
// being discoverable for 30.72 second, and will not being advertising again
// until the enabler is set back to TRUE
GAPRole_SetParameter(GAPROLE_ADVERT_OFF_TIME, sizeof(uint16_t),
&advertOffTime, NULL);
// Set scan response data
GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData1),
scanRspData1, NULL);
// Set advertising data
GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData, NULL);
// set max amount of scan responses
uint8_t scanRes = DEFAULT_MAX_SCAN_RES;
// Set the max amount of scan responses
GAPRole_SetParameter(GAPROLE_MAX_SCAN_RES, sizeof(uint8_t),
&scanRes, NULL);
// Start the GAPRole and negotiate max number of connections
VOID GAPRole_StartDevice(&multi_role_gapRoleCBs, &maxNumBleConns);
// Allocate memory for index to connection handle map
if (connHandleMap = ICall_malloc(sizeof(connHandleMapEntry_t) * maxNumBleConns))
{
// Init index to connection handle map
for (uint8_t i = 0; i < maxNumBleConns; i++)
{
connHandleMap[i].connHandle = INVALID_CONNHANDLE;
}
}
// Allocate memory for per connection discovery information
if (discInfo = ICall_malloc(sizeof(discInfo_t) * maxNumBleConns))
{
// Init index to connection handle map to 0's
for (uint8_t i = 0; i < maxNumBleConns; i++)
{
discInfo[i].charHdl = 0;
discInfo[i].discState = BLE_DISC_STATE_IDLE;
discInfo[i].svcEndHdl = 0;
discInfo[i].svcStartHdl = 0;
}
}
}
//oad
// Open the OAD module and add the OAD service to the application
if(OAD_SUCCESS != OAD_open(OAD_DEFAULT_INACTIVITY_TIME))
{
/*
* OAD cannot be opened, steps must be taken in the application to
* handle this gracefully, this can mean an error, assert,
* or print statement.
*/
}
else
{
// Register the OAD callback with the application
OAD_register(&multi_role_oadCBs);
}
// GATT
{
// Set the GAP Characteristics
GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);
// Initialize GATT Server Services
GGS_AddService(GATT_ALL_SERVICES); // GAP
GATTServApp_AddService(GATT_ALL_SERVICES); // GATT attributes
DevInfo_AddService(); // Device Information Service
SimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile
// Register callback with SimpleGATTprofile
SimpleProfile_RegisterAppCBs(&multi_role_simpleProfileCBs);
/*-----------------CLIENT------------------*/
// Initialize GATT Client
VOID GATT_InitClient();
// Register for GATT local events and ATT Responses pending for transmission
GATT_RegisterForMsgs(selfEntity);
// Register to receive incoming ATT Indications/Notifications
GATT_RegisterForInd(selfEntity);
}
count_store();
#if !defined (USE_LL_CONN_PARAM_UPDATE)
// Get the currently set local supported LE features
// The HCI will generate an HCI event that will get received in the main
// loop
HCI_LE_ReadLocalSupportedFeaturesCmd();
#endif // !defined (USE_LL_CONN_PARAM_UPDATE)
Util_startClock(&time_rqt_clock);
Util_startClock(&read_clock);
}
void DataSend(uint8* dataToSend,uint8 size,uint8_t chandle)
{
ack_data_counter++;
attPrepareWriteReq_t req;
req.pValue = GATT_bm_alloc(connHandleMap[cindex].connHandle, ATT_WRITE_REQ, size, NULL);
if ( req.pValue != NULL )
{
req.handle = chandle;
req.offset = 0;
req.len = size;
memcpy(req.pValue, dataToSend,size);
status = GATT_WriteLongCharValue(connHandleMap[cindex].connHandle, &req, selfEntity);
if ( status != SUCCESS )
GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
}
}
// UART Parameters
void UART_parameter(void)
{
/* Create a UART with data processing off. */
UART_Params_init(&uartParams);
uartParams.readMode = UART_MODE_CALLBACK;
uartParams.writeMode = UART_MODE_BLOCKING;
uartParams.writeDataMode = UART_DATA_BINARY;
uartParams.readDataMode = UART_DATA_BINARY;
uartParams.readCallback = readCallback;
uartParams.writeCallback = writeCallback;
uartParams.readReturnMode = UART_RETURN_FULL;
uartParams.readEcho = UART_ECHO_OFF;
uartParams.dataLength = UART_LEN_8;
uartParams.stopBits = UART_STOP_ONE;
uartParams.parityType = UART_PAR_NONE;
uartParams.baudRate = 115200;
// startaddress = &rxBuf[0];
}
/*********************************************************************
* @fn multi_role_processRoleEvent
*
* @brief Multi role event processing function.
*
* @param pEvent - pointer to event structure
*
* @return none
*/
static void multi_role_processRoleEvent(gapMultiRoleEvent_t *pEvent)
{
switch (pEvent->gap.opcode)
{
// Connection has been established
case GAP_LINK_ESTABLISHED_EVENT:
{
scan_count=0;
// If succesfully established
if (pEvent->gap.hdr.status == SUCCESS)
{
ix=0;
jx=0;
device_connected=1;
Util_startClock(&reset_clock);
PIN_setOutputValue(hGpioPin, Board_GLED, Board_LED_ON);
// Add index-to-connHandle mapping entry and update menus
cindex = multi_role_addMappingEntry(pEvent->linkCmpl.connectionHandle, pEvent->linkCmpl.devAddr);
memcpy(connected_device_address,pEvent->linkCmpl.devAddr,GATEWAY_DATA);
connRole=pEvent->linkCmpl.connRole;
if(connRole == GAP_PROFILE_CENTRAL)
{
ack_data_counter++; ///-----------------------------------------------------------
ptr=&coin_buffer[ix][0];
memcpy(packet_to_send,ptr,COIN_DATA);
DataSend(packet_to_send,COIN_DATA,simple3handle);
if (status!=SUCCESS)
{
disconnect_and_update_buffer(ix);
}
else if (status==SUCCESS)
{
Util_startClock(&ack_clock);
}
if(packet_to_send[1]==0x45 && buffer_counter==1)
buffer_counter=0;
//}
}
}
}
break;
}
/*********************************************************************
* @fn multi_role_processCharValueChangeEvt
*
* @brief Process a pending Simple Profile characteristic value change
* event.
*
* @param paramID - parameter ID of the value that was changed.
*
* @return None.
*/
static void multi_role_processCharValueChangeEvt(uint8_t paramID)
{
// Print new value depending on which characteristic was updated
switch(paramID)
{
case SIMPLEPROFILE_CHAR1:
if(connRole==GAP_PROFILE_PERIPHERAL)
{
ack_packet[0]=ack;
ack_packet[1]=++jx;
DataSend(ack_packet,2,simple1handle);
time_total=UTC_getClock();
if(time_total>=86400)
{
UTC_setClock(0);
time_hr=0;
time_min=0;
time_sec=0;
}
else if(time_total>86400)
{
time_remainder=time_total-86400;
UTC_setClock(time_remainder);
time_hr=time_remainder/3600;
time_remainder_dup=time_remainder%3600;
time_min=time_remainder_dup/60;
time_sec=time_remainder_dup%60;
}
else
{
time_hr=time_total/3600;
time_total_dup=time_total%3600;
time_min=time_total_dup/60;
time_sec=time_total_dup%60;
}
utc_time_data[0]=coindata[0];
utc_time_data[1]=coindata[1];
utc_time_data[2]=coindata[2];
utc_time_data[3]=coindata[3];
utc_time_data[4]=time_hr;
utc_time_data[5]=time_min;
utc_time_data[6]=time_sec;
if((first_data==1)||((coindata[0]!=last_received_packet[0] || coindata[0]==last_received_packet[0]) && coindata[4]!=last_received_packet[4])||(coindata[0]!=last_received_packet[0] && coindata[4]==last_received_packet[4]))
{
if(coindata[0]!=0 && coindata[1]!=0)
{
write_to_flash(&utc_time_data[0],UART_WRITE_SIZE);
memcpy(last_received_packet,coindata,COIN_DATA);
}
if(first_data==1)
first_data=0;
}
/* memcpy(in_data_buffer[in_data_count],coindata,COIN_DATA);
in_data_count++;*/
}
break;
}
void write_on_uart(void)
{
read_from_flash(&extdata[0],UART_WRITE_SIZE);
DELAY_MS(10);
converttoascii();
onuart[0] = BLEADDRESS_ASCII[0];
onuart[1] = BLEADDRESS_ASCII[1];
onuart[2] = BLEADDRESS_ASCII[2];
onuart[3] = BLEADDRESS_ASCII[3];
onuart[4] = BLEADDRESS_ASCII[4];
onuart[5] = BLEADDRESS_ASCII[5];
onuart[6] = BLEADDRESS_ASCII[6];
onuart[7] = BLEADDRESS_ASCII[7];
onuart[8] = BLEADDRESS_ASCII[8];
onuart[9] = BLEADDRESS_ASCII[9];
onuart[10] = BLEADDRESS_ASCII[10];
onuart[11] = BLEADDRESS_ASCII[11];
onuart[12] = uartdata[0];
onuart[13] = uartdata[1];
onuart[14] = uartdata[2];
onuart[15] = uartdata[3];
onuart[16] = uartdata[4];
onuart[17] = uartdata[5];
onuart[18] = uartdata[6];
onuart[19] = uartdata[7];
onuart[20] = uartdata[8];
onuart[21] = uartdata[9];
onuart[22] = uartdata[10];
onuart[23] = uartdata[11];
onuart[24] = uartdata[12];
onuart[25] = uartdata[13];
onuart[26] = '\n';
UART_write(uart,onuart,sizeof(onuart));
}
/****************************************************************************** @file simple_gatt_profile.c @brief This file contains the Simple GATT profile sample GATT service profile for use with the BLE sample application. Group: WCS, BTS Target Device: cc2640r2 ****************************************************************************** Copyright (c) 2010-2019, Texas Instruments Incorporated All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Texas Instruments Incorporated nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ****************************************************************************** *****************************************************************************/ /********************************************************************* * INCLUDES */ #include <string.h> #include <icall.h> #include "util.h" /* This Header file contains all BLE API and icall structure definition */ #include "icall_ble_api.h" #include "simple_gatt_profile.h" /********************************************************************* * MACROS */ /********************************************************************* * CONSTANTS */ #define SERVAPP_NUM_ATTR_SUPPORTED 17 extern uint8_t ack_packet[2]; /********************************************************************* * TYPEDEFS */ /********************************************************************* * GLOBAL VARIABLES */ // Simple GATT Profile Service UUID: 0xFFF0 CONST uint8 simpleProfileServUUID[ATT_BT_UUID_SIZE] = { LO_UINT16(SIMPLEPROFILE_SERV_UUID), HI_UINT16(SIMPLEPROFILE_SERV_UUID) }; // Characteristic 1 UUID: 0xFFF1 CONST uint8 simpleProfilechar1UUID[ATT_BT_UUID_SIZE] = { LO_UINT16(SIMPLEPROFILE_CHAR1_UUID), HI_UINT16(SIMPLEPROFILE_CHAR1_UUID) }; // Characteristic 2 UUID: 0xFFF2 CONST uint8 simpleProfilechar2UUID[ATT_BT_UUID_SIZE] = { LO_UINT16(SIMPLEPROFILE_CHAR2_UUID), HI_UINT16(SIMPLEPROFILE_CHAR2_UUID) }; // Characteristic 3 UUID: 0xFFF3 CONST uint8 simpleProfilechar3UUID[ATT_BT_UUID_SIZE] = { LO_UINT16(SIMPLEPROFILE_CHAR3_UUID), HI_UINT16(SIMPLEPROFILE_CHAR3_UUID) }; // Characteristic 4 UUID: 0xFFF4 CONST uint8 simpleProfilechar4UUID[ATT_BT_UUID_SIZE] = { LO_UINT16(SIMPLEPROFILE_CHAR4_UUID), HI_UINT16(SIMPLEPROFILE_CHAR4_UUID) }; // Characteristic 5 UUID: 0xFFF5 CONST uint8 simpleProfilechar5UUID[ATT_BT_UUID_SIZE] = { LO_UINT16(SIMPLEPROFILE_CHAR5_UUID), HI_UINT16(SIMPLEPROFILE_CHAR5_UUID) }; /********************************************************************* * EXTERNAL VARIABLES */ /********************************************************************* * EXTERNAL FUNCTIONS */ /********************************************************************* * LOCAL VARIABLES */ static simpleProfileCBs_t *simpleProfile_AppCBs = NULL; /********************************************************************* * Profile Attributes - variables */ // Simple Profile Service attribute static CONST gattAttrType_t simpleProfileService = { ATT_BT_UUID_SIZE, simpleProfileServUUID }; // Simple Profile Characteristic 1 Properties static uint8 simpleProfileChar1Props = GATT_PROP_READ | GATT_PROP_WRITE | GATT_PROP_NOTIFY; // Characteristic 1 Value uint8 simpleProfileChar1[COIN_DATA] = {0}; // Simple Profile Characteristic 1 User Description static uint8 simpleProfileChar1UserDesp[17] = "Characteristic 1"; // Simple Profile Characteristic 2 Properties static uint8 simpleProfileChar2Props = GATT_PROP_READ; // Characteristic 2 Value static uint8 simpleProfileChar2 = 0; // Simple Profile Characteristic 2 User Description static uint8 simpleProfileChar2UserDesp[17] = "Characteristic 2"; // Simple Profile Characteristic 3 Properties static uint8 simpleProfileChar3Props = GATT_PROP_WRITE; // Characteristic 3 Value static uint8 simpleProfileChar3[COIN_DATA] = {0}; // Simple Profile Characteristic 3 User Description static uint8 simpleProfileChar3UserDesp[17] = "Characteristic 3"; // Simple Profile Characteristic 4 Properties static uint8 simpleProfileChar4Props = GATT_PROP_NOTIFY; // Characteristic 4 Value static uint8 simpleProfileChar4 = 0; // Simple Profile Characteristic 4 Configuration Each client has its own // instantiation of the Client Characteristic Configuration. Reads of the // Client Characteristic Configuration only shows the configuration for // that client and writes only affect the configuration of that client. static gattCharCfg_t *simpleProfileChar4Config; // Simple Profile Characteristic 4 User Description static uint8 simpleProfileChar4UserDesp[17] = "Characteristic 4"; // Simple Profile Characteristic 5 Properties static uint8 simpleProfileChar5Props = GATT_PROP_READ; // Characteristic 5 Value static uint8 simpleProfileChar5[SIMPLEPROFILE_CHAR5_LEN] = { 0, 0, 0, 0, 0 }; // Simple Profile Characteristic 5 User Description static uint8 simpleProfileChar5UserDesp[17] = "Characteristic 5"; /********************************************************************* * Profile Attributes - Table */ static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] = { // Simple Profile Service { { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */ GATT_PERMIT_READ, /* permissions */ 0, /* handle */ (uint8 *)&simpleProfileService /* pValue */ }, // Characteristic 1 Declaration { { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &simpleProfileChar1Props }, // Characteristic Value 1 { { ATT_BT_UUID_SIZE, simpleProfilechar1UUID }, GATT_PERMIT_READ | GATT_PERMIT_WRITE, 0, &simpleProfileChar1[0] }, // Characteristic 1 User Description { { ATT_BT_UUID_SIZE, charUserDescUUID }, GATT_PERMIT_READ, 0, simpleProfileChar1UserDesp }, // Characteristic 2 Declaration { { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &simpleProfileChar2Props }, // Characteristic Value 2 { { ATT_BT_UUID_SIZE, simpleProfilechar2UUID }, GATT_PERMIT_READ, 0, &simpleProfileChar2 }, // Characteristic 2 User Description { { ATT_BT_UUID_SIZE, charUserDescUUID }, GATT_PERMIT_READ, 0, simpleProfileChar2UserDesp }, // Characteristic 3 Declaration { { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &simpleProfileChar3Props }, // Characteristic Value 3 { { ATT_BT_UUID_SIZE, simpleProfilechar3UUID }, GATT_PERMIT_WRITE, 0, &simpleProfileChar3[0] }, // Characteristic 3 User Description { { ATT_BT_UUID_SIZE, charUserDescUUID }, GATT_PERMIT_READ, 0, simpleProfileChar3UserDesp }, // Characteristic 4 Declaration { { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &simpleProfileChar4Props }, // Characteristic Value 4 { { ATT_BT_UUID_SIZE, simpleProfilechar4UUID }, 0, 0, &simpleProfileChar4 }, // Characteristic 4 configuration { { ATT_BT_UUID_SIZE, clientCharCfgUUID }, GATT_PERMIT_READ | GATT_PERMIT_WRITE, 0, (uint8 *)&simpleProfileChar4Config }, // Characteristic 4 User Description { { ATT_BT_UUID_SIZE, charUserDescUUID }, GATT_PERMIT_READ, 0, simpleProfileChar4UserDesp }, // Characteristic 5 Declaration { { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &simpleProfileChar5Props }, // Characteristic Value 5 { { ATT_BT_UUID_SIZE, simpleProfilechar5UUID }, GATT_PERMIT_AUTHEN_READ, 0, simpleProfileChar5 }, // Characteristic 5 User Description { { ATT_BT_UUID_SIZE, charUserDescUUID }, GATT_PERMIT_READ, 0, simpleProfileChar5UserDesp }, }; /********************************************************************* * LOCAL FUNCTIONS */ static bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr, uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method); static bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr, uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method); /********************************************************************* * PROFILE CALLBACKS */ // Simple Profile Service Callbacks // Note: When an operation on a characteristic requires authorization and // pfnAuthorizeAttrCB is not defined for that characteristic's service, the // Stack will report a status of ATT_ERR_UNLIKELY to the client. When an // operation on a characteristic requires authorization the Stack will call // pfnAuthorizeAttrCB to check a client's authorization prior to calling // pfnReadAttrCB or pfnWriteAttrCB, so no checks for authorization need to be // made within these functions. CONST gattServiceCBs_t simpleProfileCBs = { simpleProfile_ReadAttrCB, // Read callback function pointer simpleProfile_WriteAttrCB, // Write callback function pointer NULL // Authorization callback function pointer }; /********************************************************************* * PUBLIC FUNCTIONS */ /********************************************************************* * @fn SimpleProfile_AddService * * @brief Initializes the Simple Profile service by registering * GATT attributes with the GATT server. * * @param services - services to add. This is a bit map and can * contain more than one service. * * @return Success or Failure */ bStatus_t SimpleProfile_AddService( uint32 services ) { uint8 status; // Allocate Client Characteristic Configuration table simpleProfileChar4Config = (gattCharCfg_t *)ICall_malloc( sizeof(gattCharCfg_t) * linkDBNumConns ); if ( simpleProfileChar4Config == NULL ) { return ( bleMemAllocError ); } // Initialize Client Characteristic Configuration attributes GATTServApp_InitCharCfg( INVALID_CONNHANDLE, simpleProfileChar4Config ); if ( services & SIMPLEPROFILE_SERVICE ) { // Register GATT attribute list and CBs with GATT Server App status = GATTServApp_RegisterService( simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ), GATT_MAX_ENCRYPT_KEY_SIZE, &simpleProfileCBs ); } else { status = SUCCESS; } return ( status ); } /********************************************************************* * @fn SimpleProfile_RegisterAppCBs * * @brief Registers the application callback function. Only call * this function once. * * @param callbacks - pointer to application callbacks. * * @return SUCCESS or bleAlreadyInRequestedMode */ bStatus_t SimpleProfile_RegisterAppCBs( simpleProfileCBs_t *appCallbacks ) { if ( appCallbacks ) { simpleProfile_AppCBs = appCallbacks; return ( SUCCESS ); } else { return ( bleAlreadyInRequestedMode ); } } /********************************************************************* * @fn SimpleProfile_SetParameter * * @brief Set a Simple Profile parameter. * * @param param - Profile parameter ID * @param len - length of data to write * @param value - pointer to data to write. This is dependent on * the parameter ID and WILL be cast to the appropriate * data type (example: data type of uint16 will be cast to * uint16 pointer). * * @return bStatus_t */ bStatus_t SimpleProfile_SetParameter( uint8 param, uint8 len, void *value ) { bStatus_t ret = SUCCESS; switch ( param ) { case SIMPLEPROFILE_CHAR1: if ( len <= COIN_DATA ) { memcpy(simpleProfileChar1,value,COIN_DATA); } else { ret = bleInvalidRange; } break; case SIMPLEPROFILE_CHAR2: if ( len == sizeof ( uint8 ) ) { simpleProfileChar2 = *((uint8*)value); } else { ret = bleInvalidRange; } break; case SIMPLEPROFILE_CHAR3: if ( len <= COIN_DATA ) { memcpy(simpleProfileChar3,value,COIN_DATA); } else { ret = bleInvalidRange; } break; case SIMPLEPROFILE_CHAR4: if ( len == sizeof ( uint8 ) ) { simpleProfileChar4 = *((uint8*)value); // See if Notification has been enabled GATTServApp_ProcessCharCfg( simpleProfileChar4Config, &simpleProfileChar4, FALSE, simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ), INVALID_TASK_ID, simpleProfile_ReadAttrCB ); } else { ret = bleInvalidRange; } break; case SIMPLEPROFILE_CHAR5: if ( len == SIMPLEPROFILE_CHAR5_LEN ) { VOID memcpy( simpleProfileChar5, value, SIMPLEPROFILE_CHAR5_LEN ); } else { ret = bleInvalidRange; } break; default: ret = INVALIDPARAMETER; break; } return ( ret ); } /********************************************************************* * @fn SimpleProfile_GetParameter * * @brief Get a Simple Profile parameter. * * @param param - Profile parameter ID * @param value - pointer to data to put. This is dependent on * the parameter ID and WILL be cast to the appropriate * data type (example: data type of uint16 will be cast to * uint16 pointer). * * @return bStatus_t */ bStatus_t SimpleProfile_GetParameter( uint8 param, void *value ) { bStatus_t ret = SUCCESS; switch ( param ) { case SIMPLEPROFILE_CHAR1: memcpy(value,simpleProfileChar1,COIN_DATA); break; case SIMPLEPROFILE_CHAR2: *((uint8*)value) = simpleProfileChar2; break; case SIMPLEPROFILE_CHAR3: memcpy(value,simpleProfileChar3,COIN_DATA); break; case SIMPLEPROFILE_CHAR4: *((uint8*)value) = simpleProfileChar4; break; case SIMPLEPROFILE_CHAR5: VOID memcpy( value, simpleProfileChar5, SIMPLEPROFILE_CHAR5_LEN ); break; default: ret = INVALIDPARAMETER; break; } return ( ret ); } /********************************************************************* * @fn simpleProfile_ReadAttrCB * * @brief Read an attribute. * * @param connHandle - connection message was received on * @param pAttr - pointer to attribute * @param pValue - pointer to data to be read * @param pLen - length of data to be read * @param offset - offset of the first octet to be read * @param maxLen - maximum length of data to be read * @param method - type of read message * * @return SUCCESS, blePending or Failure */ static bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr, uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method) { bStatus_t status = SUCCESS; // Make sure it's not a blob operation (no attributes in the profile are long) if ( offset > 0 ) { return ( ATT_ERR_ATTR_NOT_LONG ); } if ( pAttr->type.len == ATT_BT_UUID_SIZE ) { // 16-bit UUID uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]); switch ( uuid ) { // No need for "GATT_SERVICE_UUID" or "GATT_CLIENT_CHAR_CFG_UUID" cases; // gattserverapp handles those reads // characteristics 1 and 2 have read permissions // characteritisc 3 does not have read permissions; therefore it is not // included here // characteristic 4 does not have read permissions, but because it // can be sent as a notification, it is included here case SIMPLEPROFILE_CHAR1_UUID: case SIMPLEPROFILE_CHAR2_UUID: case SIMPLEPROFILE_CHAR4_UUID: *pLen = 1; pValue[0] = *pAttr->pValue; break; case SIMPLEPROFILE_CHAR5_UUID: *pLen = SIMPLEPROFILE_CHAR5_LEN; VOID memcpy( pValue, pAttr->pValue, SIMPLEPROFILE_CHAR5_LEN ); break; default: // Should never get here! (characteristics 3 and 4 do not have read permissions) *pLen = 0; status = ATT_ERR_ATTR_NOT_FOUND; break; } } else { // 128-bit UUID *pLen = 0; status = ATT_ERR_INVALID_HANDLE; } return ( status ); } /********************************************************************* * @fn simpleProfile_WriteAttrCB * * @brief Validate attribute data prior to a write operation * * @param connHandle - connection message was received on * @param pAttr - pointer to attribute * @param pValue - pointer to data to be written * @param len - length of data * @param offset - offset of the first octet to be written * @param method - type of write message * * @return SUCCESS, blePending or Failure */ static bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr, uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method) { bStatus_t status = SUCCESS; uint8 notifyApp = 0xFF; if ( pAttr->type.len == ATT_BT_UUID_SIZE ) { // 16-bit UUID uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]); switch ( uuid ) { case SIMPLEPROFILE_CHAR1_UUID: if ( offset == 0 ) { if ( len < COIN_DATA ) { status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } //Write the value if ( status == SUCCESS) { memcpy( simpleProfileChar1, pValue, COIN_DATA); memcpy( coindata, simpleProfileChar1, COIN_DATA); notifyApp = SIMPLEPROFILE_CHAR1; /*memcpy( coindata, pValue, COIN_DATA); memcpy( profile_data_buffer[profile_data_count], pValue, COIN_DATA); profile_data_count++; simple_pro_counter++;*/ } break; case SIMPLEPROFILE_CHAR3_UUID: if ( offset == 0 ) { if ( len > COIN_DATA ) { status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } //Write the value if ( status == SUCCESS ) { if(len == COIN_DATA) { memcpy( simpleProfileChar3, pValue, COIN_DATA); memcpy( coindata, simpleProfileChar3, COIN_DATA); notifyApp = SIMPLEPROFILE_CHAR3; } else if (len == 2) { memcpy(ack_packet,pValue,2); notifyApp = SIMPLEPROFILE_CHAR3; } } break; case GATT_CLIENT_CHAR_CFG_UUID: status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY ); break; default: // Should never get here! (characteristics 2 and 4 do not have write permissions) status = ATT_ERR_ATTR_NOT_FOUND; break; } } else { // 128-bit UUID status = ATT_ERR_INVALID_HANDLE; } // If a characteristic value changed then callback function to notify application of change if ( (notifyApp != 0xFF ) && simpleProfile_AppCBs && simpleProfile_AppCBs->pfnSimpleProfileChange ) { simpleProfile_AppCBs->pfnSimpleProfileChange( notifyApp ); } return ( status ); }
Waiting for your response.
Thanks and Regards,
Rohit