我主要按照这里所说的改了CC2640的SimpleBLEPeripheral例程:
但是修改后,没有反应,CC2640是有在广播,但是搜不到有服务的UUID,只有MAC之类的信息,请问一下各位大牛,该怎么办???
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
我主要按照这里所说的改了CC2640的SimpleBLEPeripheral例程:
但是修改后,没有反应,CC2640是有在广播,但是搜不到有服务的UUID,只有MAC之类的信息,请问一下各位大牛,该怎么办???
您可以试一下 https://e2e.ti.com/support/wireless_connectivity/bluetooth_low_energy/f/538/t/205258 给出的代码
这个他改的部分,在我贴的那个链接里也有,而且我也是这样做的,就是16bit及其操作换成128bit及其对应操作,但我改了之后就是没有UUID了,无论是128bit的还是之前的16bit都没有
/* * Filename: serial_port_service.c * * Description: This is the simple_peripheral example modified to send * data over BLE at a high throughput. * * * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/ * * * 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 "bcomdef.h" #include "OSAL.h" #include "linkdb.h" #include "att.h" #include "gatt.h" #include "gatt_uuid.h" #include "gattservapp.h" #include "gapbondmgr.h" #ifdef SDI_USE_UART #include "inc/sdi_task.h" #endif #include "serial_port_service.h" #ifdef SDI_USE_UART #include "inc/sdi_tl_uart.h" #endif #include "ti/drivers/uart/UARTCC26XX.h" #include "board.h" #include "spp_ble_server.h" /********************************************************************* * MACROS */ #define AUTO_NOTIFICATION FALSE /********************************************************************* * CONSTANTS */ #define SERVAPP_NUM_ATTR_SUPPORTED 11 gattAttribute_t SerialPortServiceAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED]; /********************************************************************* * TYPEDEFS */ typedef enum UART_STATUS_CHAR { FRAMING_ERR_BYTE, PARITY_ERR_BYTE, RF_OVERRUN_BYTE } UART_STATUS_BYTE_DEF; /*! * @brief UART config service settings * * This enumeration defines the UART config bits in Byte 2 of config. char. */ typedef enum UART_CONFIG_CHAR { UART_CONFIG_START = 0, /*!<Start bit level */ UART_CONFIG_STOP = 1, /*!< Stop bit level (must be different from start bit level)*/ UART_CONFIG_STOP_BITS = 2, /*!< Number of stop bits */ UART_CONFIG_PARITY = 3, /*!< Parity enable */ UART_CONFIG_EVEN = 4, /*!< Parity level */ UART_CONFIG_FLOW = 5 /*!< Flow control enabled */ } UART_CONFIG_BIT_DEF; /********************************************************************* * GLOBAL VARIABLES */ // Serial Port Service Profile Service UUID: 0xC0E0 CONST uint8 SerialPortServUUID[ATT_UUID_SIZE] = { TI_BASE_UUID_128(SERIALPORTSERVICE_SERV_UUID) }; // Characteristic Data UUID: 0xC0E1 CONST uint8 SerialPortServiceDataUUID[ATT_UUID_SIZE] = { TI_BASE_UUID_128(SERIALPORTSERVICE_DATA_UUID) }; // Characteristic Status UUID: 0xC0E2 CONST uint8 SerialPortServiceStatusUUID[ATT_UUID_SIZE] = { TI_BASE_UUID_128(SERIALPORTSERVICE_STATUS_UUID) }; // Characteristic Config UUID: 0xC0E3 CONST uint8 SerialPortServiceConfigUUID[ATT_UUID_SIZE] = { TI_BASE_UUID_128(SERIALPORTSERVICE_CONFIG_UUID) }; /********************************************************************* * EXTERNAL VARIABLES */ /********************************************************************* * EXTERNAL FUNCTIONS */ /********************************************************************* * LOCAL VARIABLES */ static SerialPortServiceCBs_t *SerialPortService_AppCBs = NULL; /********************************************************************* * Profile Attributes - variables */ // Serial Port Profile Service attribute static CONST gattAttrType_t SerialPortService = { ATT_UUID_SIZE, SerialPortServUUID }; // Serial Port Profile Characteristic Data Properties static uint8 SerialPortServiceDataProps = GATT_PROP_WRITE_NO_RSP | GATT_PROP_NOTIFY; // Serial Port Profile Characteristic 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 *SerialPortServiceDataConfig; // Characteristic Data Value uint8 SerialPortServiceData[SERIALPORTSERVICE_DATA_LEN] = {0,}; // Serial Port Profile Characteristic Data User Description static uint8 SerialPortServiceDataUserDesp[21] = "Data Characteristic \0"; // Serial Port Profile Characteristic Status Properties static uint8 SerialPortServiceStatusProps = GATT_PROP_READ; // Characteristic Status Value static uint8 SerialPortServiceStatus[SERIALPORTSERVICE_STATUS_LEN] = {0,0,0,0,0,0,0}; // Serial Port Profile Characteristic Status User Description static uint8 SerialPortServiceStatusUserDesp[23] = "Status Characteristic \0"; static uint32 numTxBytes = 0; //received on serial port, sent to central. since last status readout. static uint32 numRxBytes = 0; //received from central, sent on serial port. since last status readout. static uint32 numRFLinkOverRun = 0; //number of bytes lost due to overrun from serial device. static uint32 numFramingError = 0; static uint32 numParityError = 0; static UART_Params SerialPortParams; // Serial Port Profile Characteristic Config Properties static uint8 SerialPortServiceConfigProps = GATT_PROP_READ | GATT_PROP_WRITE; // Characteristic Config Value static uint8 SerialPortServiceConfig[SERIALPORTSERVICE_CONFIG_LEN] = {0x2D,0x00,02}; // Serial Port Profile Characteristic Config User Description static uint8 SerialPortServiceConfigUserDesp[23] = "Config Characteristic \0"; //Keep track of length static uint8 charDataValueLen = SERIALPORTSERVICE_DATA_LEN; /********************************************************************* * Profile Attributes - Table */ gattAttribute_t SerialPortServiceAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] = { // Serial Port Profile Service { { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */ GATT_PERMIT_READ, /* permissions */ 0, /* handle */ (uint8 *)&SerialPortService /* pValue */ }, // Characteristic Data Declaration { { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &SerialPortServiceDataProps }, // Characteristic Data Value { { ATT_UUID_SIZE, SerialPortServiceDataUUID }, GATT_PERMIT_WRITE, 0, SerialPortServiceData }, // Characteristic Data configuration { { ATT_BT_UUID_SIZE, clientCharCfgUUID }, GATT_PERMIT_READ | GATT_PERMIT_WRITE, 0, (uint8 *)&SerialPortServiceDataConfig }, // Characteristic Data User Description { { ATT_BT_UUID_SIZE, charUserDescUUID }, GATT_PERMIT_READ, 0, SerialPortServiceDataUserDesp }, // Characteristic Status Declaration { { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &SerialPortServiceStatusProps }, // Characteristic Status Value { { ATT_UUID_SIZE, SerialPortServiceStatusUUID }, GATT_PERMIT_READ, 0, //&SerialPortServiceChar3 SerialPortServiceStatus }, // Characteristic Status User Description { { ATT_BT_UUID_SIZE, charUserDescUUID }, GATT_PERMIT_READ, 0, SerialPortServiceStatusUserDesp }, // Characteristic Config Declaration { { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &SerialPortServiceConfigProps }, // Characteristic Value Config { { ATT_UUID_SIZE, SerialPortServiceConfigUUID }, GATT_PERMIT_READ | GATT_PERMIT_WRITE, 0, SerialPortServiceConfig }, // Characteristic Config User Description { { ATT_BT_UUID_SIZE, charUserDescUUID }, GATT_PERMIT_READ, 0, SerialPortServiceConfigUserDesp }, }; /********************************************************************* * LOCAL FUNCTIONS */ static bStatus_t SerialPortService_ReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint16 *pLen, uint16 offset, uint16 maxLen, uint8 method ); static bStatus_t SerialPortService_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint16 len, uint16 offset, uint8 method ); /********************************************************************* * PROFILE CALLBACKS */ // Serial Port Profile Service Callbacks CONST gattServiceCBs_t SerialPortServiceCBs = { SerialPortService_ReadAttrCB, // Read callback function pointer SerialPortService_WriteAttrCB, // Write callback function pointer NULL // Authorization callback function pointer }; /********************************************************************* * PUBLIC FUNCTIONS */ /********************************************************************* * @fn SerialPortService_AddService * * @brief Initializes the Serial Port 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 SerialPortService_AddService( uint32 services ) { uint8 status; // Allocate Client Characteristic Configuration table SerialPortServiceDataConfig = (gattCharCfg_t *)ICall_malloc( sizeof(gattCharCfg_t) * linkDBNumConns ); if ( SerialPortServiceDataConfig == NULL ) { return ( bleMemAllocError ); } // Initialize Client Characteristic Configuration attributes GATTServApp_InitCharCfg( INVALID_CONNHANDLE, SerialPortServiceDataConfig ); #if (defined(AUTO_NOTIFICATION) && (AUTO_NOTIFICATION == TRUE)) //Hardcode to enable notification in GATT table SerialPortServiceDataConfig[0].connHandle = 0x0000; SerialPortServiceDataConfig[0].value = 0x01; #endif if ( services & SERIALPORTSERVICE_SERVICE ) { // Register GATT attribute list and CBs with GATT Server App status = GATTServApp_RegisterService( SerialPortServiceAttrTbl, GATT_NUM_ATTRS( SerialPortServiceAttrTbl ), 16, &SerialPortServiceCBs ); } else { status = SUCCESS; } return ( status ); } /********************************************************************* * @fn SerialPortService_RegisterAppCBs * * @brief Registers the application callback function. Only call * this function once. * * @param callbacks - pointer to application callbacks. * * @return SUCCESS or bleAlreadyInRequestedMode */ bStatus_t SerialPortService_RegisterAppCBs( SerialPortServiceCBs_t *appCallbacks ) { if ( appCallbacks ) { SerialPortService_AppCBs = appCallbacks; return ( SUCCESS ); } else { return ( bleAlreadyInRequestedMode ); } } /********************************************************************* * @fn SerialPortService_SetParameter * * @brief Set a Serial Port 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 SerialPortService_SetParameter( uint8 param, uint8 len, void *value ) { bStatus_t ret = SUCCESS; switch ( param ) { case SERIALPORTSERVICE_CHAR_DATA: if( len <= SERIALPORTSERVICE_DATA_LEN ) { memset(SerialPortServiceData, 0, SERIALPORTSERVICE_DATA_LEN); VOID memcpy( SerialPortServiceData, value, len ); charDataValueLen = len; // See if Notification has been enabled ret = GATTServApp_ProcessCharCfg( SerialPortServiceDataConfig, SerialPortServiceData, FALSE, SerialPortServiceAttrTbl, GATT_NUM_ATTRS( SerialPortServiceAttrTbl ), INVALID_TASK_ID, SerialPortService_ReadAttrCB ); } else { ret = bleInvalidRange; } break; case SERIALPORTSERVICE_CHAR_STATUS: if ( len == SERIALPORTSERVICE_STATUS_LEN ) { VOID memcpy( SerialPortServiceStatus, value, SERIALPORTSERVICE_STATUS_LEN ); } else { ret = bleInvalidRange; } break; case SERIALPORTSERVICE_CHAR_CONFIG: if ( len == SERIALPORTSERVICE_CONFIG_LEN ) { VOID memcpy( SerialPortServiceData, value, SERIALPORTSERVICE_CONFIG_LEN ); } else { ret = bleInvalidRange; } break; default: ret = INVALIDPARAMETER; break; } return ( ret ); } /********************************************************************* * @fn SerialPortService_SetStatusTXBytes * * @brief Set a Serial Port Service 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 SerialPortService_AddStatusTXBytes( uint16 count ) { bStatus_t ret = SUCCESS; if( count ) { numTxBytes += count; SerialPortServiceStatus[6] = numTxBytes & 0x00ff; SerialPortServiceStatus[5] = (numTxBytes & 0xff00) >> 8; } else { ret = bleInvalidRange; } return ( ret ); } /********************************************************************* * @fn SerialPortService_AddStatusErrorCount * * @brief Set a Serial Port Profile parameter. * * @param errorCode - UART_Status error code * * @return bStatus_t */ bStatus_t SerialPortService_AddStatusErrorCount( UART_Status errorCode ) { bStatus_t ret = SUCCESS; switch(errorCode) { case UART_PARITY_ERROR: numParityError++; SerialPortServiceStatus[PARITY_ERR_BYTE] = numParityError; break; case UART_OVERRUN_ERROR: numRFLinkOverRun++; SerialPortServiceStatus[RF_OVERRUN_BYTE] = numRFLinkOverRun; break; case UART_FRAMING_ERROR: numFramingError++; SerialPortServiceStatus[FRAMING_ERR_BYTE] = numFramingError; break; } return ( ret ); } /********************************************************************* * @fn SerialPortService_SetStatusRXBytes * * @brief Set a Serial Port 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 SerialPortService_AddStatusRXBytes( uint16 count ) { bStatus_t ret = SUCCESS; if( count ) { numRxBytes += count; SerialPortServiceStatus[4] = numRxBytes & 0x000000ff; SerialPortServiceStatus[3] = (numRxBytes & 0x0000ff00) >> 8; } else { ret = bleInvalidRange; } return ( ret ); } /********************************************************************* * @fn SerialPortService_SetUartConfig * * @brief Set a Serial Port 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 SerialPortService_SetUartConfig( UART_Params *params ) { bStatus_t ret = SUCCESS; SerialPortParams.readMode = params->readMode; SerialPortParams.writeMode = params->writeMode; SerialPortParams.readTimeout = params->readTimeout; SerialPortParams.writeTimeout = params->writeTimeout; SerialPortParams.readCallback = params->readCallback; SerialPortParams.writeCallback = params->writeCallback; SerialPortParams.readReturnMode = params->readReturnMode; SerialPortParams.readDataMode = params->readDataMode; SerialPortParams.writeDataMode = params->writeDataMode; SerialPortParams.baudRate = params->baudRate; SerialPortParams.dataLength = params->dataLength; SerialPortParams.stopBits = params->stopBits; SerialPortParams.parityType = params->parityType; SerialPortParams.readEcho = params->readEcho; SerialPortParams.custom = params->custom; DEBUG("*****UART SETTINGS*****"); DEBUG_NEWLINE(); uint16_t count = SerialPortParams.baudRate/10; SerialPortServiceConfig[1] = count & 0x00ff; SerialPortServiceConfig[0] = (count & 0xff00) >> 8; //DEBUG("UART Baud Rate: "); //DEBUG((uint8_t*)convInt32ToText(SerialPortParams.baudRate)); DEBUG_NEWLINE(); SerialPortServiceConfig[2] &= 0xfe; //Start bit Low SerialPortServiceConfig[2] |= 0x02; //Stop bit High DEBUG("Stop bits: "); if(SerialPortParams.stopBits == UART_STOP_TWO) { SerialPortServiceConfig[2] |= 0x04; //SPB = 1, 2 stop bit DEBUG("2 stop bit"); } else { SerialPortServiceConfig[2] &= 0xfb; //SPB = 0, 1 stop bit DEBUG("1 stop bit"); } DEBUG_NEWLINE(); DEBUG("Parity: "); switch(SerialPortParams.parityType) { case UART_PAR_NONE: SerialPortServiceConfig[2] &= 0xf7; //Parity disabled DEBUG("UART_PAR_NONE"); break; case UART_PAR_EVEN: SerialPortServiceConfig[2] |= 0x08; //Parity enabled SerialPortServiceConfig[2] |= 0x10; //Even parity DEBUG("UART_PAR_EVEN"); break; case UART_PAR_ODD: SerialPortServiceConfig[2] |= 0x08; //Parity enabled SerialPortServiceConfig[2] &= 0xef; //Even parity DEBUG("UART_PAR_ODD"); break; case UART_PAR_ZERO: break; case UART_PAR_ONE: break; } DEBUG_NEWLINE(); //Hardware Flow control is not ready yet. SerialPortServiceConfig[2] &= 0xdf; return ( ret ); } /********************************************************************* * @fn SerialPortService_GetUartConfig * * @brief Get a Serial Port 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 SerialPortService_GetUartConfig( UART_Params *params ) { bStatus_t ret = SUCCESS; params->readMode = SerialPortParams.readMode; params->writeMode = SerialPortParams.writeMode; params->readTimeout = SerialPortParams.readTimeout; params->writeTimeout = SerialPortParams.writeTimeout; params->readCallback = SerialPortParams.readCallback; params->writeCallback = SerialPortParams.writeCallback; params->readReturnMode = SerialPortParams.readReturnMode; params->readDataMode = SerialPortParams.readDataMode; params->writeDataMode = SerialPortParams.writeDataMode; params->baudRate = SerialPortParams.baudRate; params->dataLength = SerialPortParams.dataLength; params->stopBits = SerialPortParams.stopBits; params->parityType = SerialPortParams.parityType; params->readEcho = SerialPortParams.readEcho; params->custom = SerialPortParams.custom; return ( ret ); } /********************************************************************* * @fn SerialPortService_GetParameter * * @brief Get a Serial Port 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 SerialPortService_GetParameter( uint8 param, void *value ) { bStatus_t ret = SUCCESS; switch ( param ) { case SERIALPORTSERVICE_CHAR_DATA: VOID memcpy( value, SerialPortServiceData, SERIALPORTSERVICE_DATA_LEN ); break; case SERIALPORTSERVICE_CHAR_STATUS: VOID memcpy( value, SerialPortServiceStatus, SERIALPORTSERVICE_STATUS_LEN ); break; case SERIALPORTSERVICE_CHAR_CONFIG: VOID memcpy( value, SerialPortServiceConfig, SERIALPORTSERVICE_CONFIG_LEN ); break; default: ret = INVALIDPARAMETER; break; } return ( ret ); } /********************************************************************* * @fn SerialPortService_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 SerialPortService_ReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint16 *pLen, uint16 offset, uint16 maxLen, uint8 method ) { bStatus_t status = SUCCESS; // If attribute permissions require authorization to read, return error if ( gattPermitAuthorRead( pAttr->permissions ) ) { // Insufficient authorization return ( ATT_ERR_INSUFFICIENT_AUTHOR ); } // 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_UUID_SIZE ) { // Get 16-bit UUID from 128-bit UUID uint16 uuid = BUILD_UINT16( pAttr->type.uuid[12], pAttr->type.uuid[13]); switch ( uuid ) { // No need for "GATT_SERVICE_UUID" or "GATT_CLIENT_CHAR_CFG_UUID" cases; // gattserverapp handles those reads // characteristics SERIALPORTSERVICE_STATUS_UUID and SERIALPORTSERVICE_CONFIG_UUID have read permissions // characteristic SERIALPORTSERVICE_DATA_UUID does not have read permissions, but because it // can be sent as a notification, it is included here case SERIALPORTSERVICE_DATA_UUID: *pLen = charDataValueLen; VOID memcpy( pValue, pAttr->pValue, charDataValueLen ); break; case SERIALPORTSERVICE_STATUS_UUID: *pLen = SERIALPORTSERVICE_STATUS_LEN; VOID memcpy( pValue, pAttr->pValue, SERIALPORTSERVICE_STATUS_LEN ); //Reset all counters numTxBytes = 0; SerialPortServiceStatus[6] = 0x00; SerialPortServiceStatus[5] = 0x00; numRxBytes = 0; SerialPortServiceStatus[4] = 0x00; SerialPortServiceStatus[3] = 0x00; numRFLinkOverRun = 0; numFramingError = 0; numParityError = 0; break; case SERIALPORTSERVICE_CONFIG_UUID: *pLen = SERIALPORTSERVICE_CONFIG_LEN; VOID memcpy( pValue, pAttr->pValue, SERIALPORTSERVICE_CONFIG_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 if( pAttr->type.len == ATT_BT_UUID_SIZE) { uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]); switch ( uuid ) { default: // Should never get here! *pLen = 0; status = ATT_ERR_ATTR_NOT_FOUND; break; } } else { //neither 16-bit UUID nor 128bit UUID *pLen = 0; status = ATT_ERR_INVALID_HANDLE; } return ( status ); } /********************************************************************* * @fn SerialPortService_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 SerialPortService_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint16 len, uint16 offset, uint8 method ) { bStatus_t status = SUCCESS; uint8 notifyApp = 0xFF; // If attribute permissions require authorization to write, return error if ( gattPermitAuthorWrite( pAttr->permissions ) ) { // Insufficient authorization return ( ATT_ERR_INSUFFICIENT_AUTHOR ); } if ( pAttr->type.len == ATT_UUID_SIZE ) { // 16-bit UUID uint16 uuid = BUILD_UINT16( pAttr->type.uuid[12], pAttr->type.uuid[13]); switch ( uuid ) { case SERIALPORTSERVICE_DATA_UUID: if ( offset == 0 ) { if ( len > SERIALPORTSERVICE_DATA_LEN ) { status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } //Write the value if ( status == SUCCESS ) { uint8 *pCurValue = (uint8 *)pAttr->pValue; //Copy/Store data to the GATT table entry memset(pCurValue, 0, SERIALPORTSERVICE_DATA_LEN); memcpy(pCurValue, pValue, len); #ifdef SDI_USE_UART //Send Data to UART SDITask_sendToUART(pCurValue, len); #else SNP_replyToHost_send(0x55, 0xFF, NULL, len, pCurValue); #endif //Toggle LED to indicate data received from client SPPBLEServer_toggleLed(Board_RLED, Board_LED_TOGGLE); if (len > 0) { SerialPortService_AddStatusRXBytes( len ); } notifyApp = SERIALPORTSERVICE_CHAR_DATA; } break; case SERIALPORTSERVICE_CONFIG_UUID: //Validate the value if ( offset == 0 ) { if ( len != SERIALPORTSERVICE_CONFIG_LEN ) { status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } //Write the value if ( status == SUCCESS ) { uint8 *pCurValue = (uint8 *)pAttr->pValue; memset(pCurValue, 0, SERIALPORTSERVICE_CONFIG_LEN); memcpy(pCurValue, pValue, len); //Configured in higher application layer notifyApp = SERIALPORTSERVICE_CHAR_CONFIG; } break; default: // Should never get here! (characteristics 2 and 4 do not have write permissions) status = ATT_ERR_ATTR_NOT_FOUND; break; } } else 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 GATT_CLIENT_CHAR_CFG_UUID: status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY ); break; default: status = ATT_ERR_ATTR_NOT_FOUND; break; } } else { //neither 16bit UUID nor 128bit UUID status = ATT_ERR_INVALID_HANDLE; } // If a charactersitic value changed then callback function to notify application of change if ( (notifyApp != 0xFF ) && SerialPortService_AppCBs && SerialPortService_AppCBs->pfnSerialPortServiceChange ) { SerialPortService_AppCBs->pfnSerialPortServiceChange( notifyApp ); } return ( status ); } /********************************************************************* *********************************************************************/