/********************************************************************* * @fn SimplePropBeacon_freeAttRsp * * @brief Free ATT response message. * * @param status - response transmit status * * @return none */ static void SimplePropBeacon_freeAttRsp(uint8_t status) { // See if there's a pending ATT response message if (pAttRsp != NULL) { // See if the response was sent out successfully if (status == SUCCESS) { Display_print1(dispHandle, 5, 0, "Rsp sent retry: %d", rspTxRetry); } else { // Free response payload GATT_bm_free(&pAttRsp->msg, pAttRsp->method); Display_print1(dispHandle, 5, 0, "Rsp retry failed: %d", rspTxRetry); } // Free response message ICall_freeMsg(pAttRsp); // Reset our globals pAttRsp = NULL; rspTxRetry = 0; } }
/********************************************************************* * @fn SimpleBLEPeripheral_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 SimpleBLEPeripheral_processCharValueChangeEvt(uint8_t paramID) { #ifndef FEATURE_OAD_ONCHIP uint8_t newValue; switch(paramID) { case SIMPLEPROFILE_CHAR1: SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR1, &newValue); Display_print1(dispHandle, 4, 0, "Char 1: %d", (uint16_t)newValue); break; case SIMPLEPROFILE_CHAR3: SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR3, &newValue); Display_print1(dispHandle, 4, 0, "Char 3: %d", (uint16_t)newValue); break; default: // should not reach here! break; } #endif //!FEATURE_OAD_ONCHIP }
/********************************************************************* * @fn SimplePropBeacon_sendAttRsp * * @brief Send a pending ATT response message. * * @param none * * @return none */ static void SimplePropBeacon_sendAttRsp(void) { // See if there's a pending ATT Response to be transmitted if (pAttRsp != NULL) { uint8_t status; // Increment retransmission count rspTxRetry++; // Try to retransmit ATT response till either we're successful or // the ATT Client times out (after 30s) and drops the connection. status = GATT_SendRsp(pAttRsp->connHandle, pAttRsp->method, &(pAttRsp->msg)); if ((status != blePending) && (status != MSG_BUFFER_NOT_AVAIL)) { // Disable connection event end notice HCI_EXT_ConnEventNoticeCmd(pAttRsp->connHandle, selfEntity, 0); // We're done with the response message SimplePropBeacon_freeAttRsp(status); } else { // Continue retrying Display_print1(dispHandle, 5, 0, "Rsp send retry:", rspTxRetry); } } }
/********************************************************************* * @fn SimpleBLECentral_processRoleEvent * * @brief Central role event processing function. * * @param pEvent - pointer to event structure * * @return none */ static void SimpleBLEPeripheralObserver_processRoleEvent(gapPeripheralObserverRoleEvent_t *pEvent) { switch (pEvent->gap.opcode) { case GAP_DEVICE_INFO_EVENT: { //Print scan response data otherwise advertising data if(pEvent->deviceInfo.eventType == GAP_ADRPT_SCAN_RSP) { Display_print1(dispHandle, 4, 0, "Scan Response Addr: %s", Util_convertBdAddr2Str(pEvent->deviceInfo.addr)); Display_print1(dispHandle, 5, 0, "Scan Response Data: %s", Util_convertBytes2Str(pEvent->deviceInfo.pEvtData, pEvent->deviceInfo.dataLen)); } else { deviceInfoCnt++; Display_print2(dispHandle, 6, 0, "Advertising Addr: %s Advertising Type: %s", Util_convertBdAddr2Str(pEvent->deviceInfo.addr), AdvTypeStrings[pEvent->deviceInfo.eventType]); Display_print1(dispHandle, 7, 0, "Advertising Data: %s", Util_convertBytes2Str(pEvent->deviceInfo.pEvtData, pEvent->deviceInfo.dataLen)); } ICall_free(pEvent->deviceInfo.pEvtData); ICall_free(pEvent); } break; case GAP_DEVICE_DISCOVERY_EVENT: { // discovery complete scanningStarted = FALSE; deviceInfoCnt = 0; //Display_print0(dispHandle, 7, 0, "GAP_DEVICE_DISC_EVENT"); Display_print1(dispHandle, 5, 0, "Devices discovered: %d", pEvent->discCmpl.numDevs); Display_print0(dispHandle, 4, 0, "Scanning Off"); ICall_free(pEvent->discCmpl.pDevList); ICall_free(pEvent); } break; default: break; } }
/********************************************************************* * @fn SimplePropBeacon_processGATTMsg * * @brief Process GATT messages and events. * * @return TRUE if safe to deallocate incoming message, FALSE otherwise. */ static uint8_t SimplePropBeacon_processGATTMsg(gattMsgEvent_t *pMsg) { // See if GATT server was unable to transmit an ATT response if (pMsg->hdr.status == blePending) { // No HCI buffer was available. Let's try to retransmit the response // on the next connection event. if (HCI_EXT_ConnEventNoticeCmd(pMsg->connHandle, selfEntity, SPB_CONN_EVT_END_EVT) == SUCCESS) { // First free any pending response SimplePropBeacon_freeAttRsp(FAILURE); // Hold on to the response message for retransmission pAttRsp = pMsg; // Don't free the response message yet return (FALSE); } } else if (pMsg->method == ATT_FLOW_CTRL_VIOLATED_EVENT) { // ATT request-response or indication-confirmation flow control is // violated. All subsequent ATT requests or indications will be dropped. // The app is informed in case it wants to drop the connection. // Display the opcode of the message that caused the violation. Display_print1(dispHandle, 5, 0, "FC Violated:", pMsg->msg.flowCtrlEvt.opcode); } else if (pMsg->method == ATT_MTU_UPDATED_EVENT) { // MTU size updated Display_print1(dispHandle, 5, 0, "FC Violated:", pMsg->msg.mtuEvt.MTU); } // Free message payload. Needed only for ATT Protocol messages GATT_bm_free(&pMsg->msg, pMsg->method); // It's safe to free the incoming message return (TRUE); }
/********************************************************************* * @fn SimpleBLECentral_handleKeys * * @brief Handles all key events for this device. * * @param shift - true if in shift/alt. * @param keys - bit field for key events. Valid entries: * HAL_KEY_SW_2 * HAL_KEY_SW_1 * * @return none */ static void SimpleBLEPeripheral_handleKeys(uint8_t shift, uint8_t keys) { (void)shift; // Intentionally unreferenced parameter if (keys & KEY_RIGHT) { uint8 status; if(scanningStarted == TRUE) { status = GAPObserverRole_CancelDiscovery(); if(status == SUCCESS) { scanningStarted = FALSE; Display_print0(dispHandle, 4, 0, "Scanning Off"); } else { Display_print0(dispHandle, 4, 0, "Scanning Off Fail"); } } return; } if (keys & KEY_LEFT) { uint8 status; //Start scanning if not already scanning if((scanningStarted == FALSE)) { status = GAPObserverRole_StartDiscovery(DEFAULT_DISCOVERY_MODE, DEFAULT_DISCOVERY_ACTIVE_SCAN, DEFAULT_DISCOVERY_WHITE_LIST); if(status == SUCCESS) { scanningStarted = TRUE; Display_print0(dispHandle, 4, 0, "Scanning On"); } else { Display_print1(dispHandle, 4, 0, "Scanning failed: %d", status); } } return; } }
/******************************************************************************* * @fn SensorTagDisplay_showBatteryLevel * * @brief Display the battery voltage in millivolts * * @param none * * @return none */ void SensorTagDisplay_showBatteryLevel(void) { if (AONBatMonNewBatteryMeasureReady()) { uint32_t batt; // Battery monitor (bit 10:8 - integer, but 7:0 fraction) batt = AONBatMonBatteryVoltageGet(); batt = (batt * 125) >> 5; Display_print1(handle, 10, 1, "Batt: %d mV", batt); } }
/********************************************************************* * @fn SimplePropBeacon_processStateChangeEvt * * @brief Process a pending GAP Role state change event. * * @param newState - new state * * @return None. */ static void SimplePropBeacon_processStateChangeEvt(gaprole_States_t newState) { switch ( newState ) { case GAPROLE_STARTED: { uint8_t ownAddress[B_ADDR_LEN]; uint8_t systemId[DEVINFO_SYSTEM_ID_LEN]; GAPRole_GetParameter(GAPROLE_BD_ADDR, ownAddress); // use 6 bytes of device address for 8 bytes of system ID value systemId[0] = ownAddress[0]; systemId[1] = ownAddress[1]; systemId[2] = ownAddress[2]; // set middle bytes to zero systemId[4] = 0x00; systemId[3] = 0x00; // shift three bytes up systemId[7] = ownAddress[5]; systemId[6] = ownAddress[4]; systemId[5] = ownAddress[3]; DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId); // Display device address Display_print0(dispHandle, 1, 0, Util_convertBdAddr2Str(ownAddress)); Display_print0(dispHandle, 2, 0, "Initialized"); // Start advertising SimplePropBeacon_startRegularAdv(); } break; case GAPROLE_ADVERTISING: Display_print0(dispHandle, 2, 0, "Config Mode"); break; case GAPROLE_ADVERTISING_NONCONN: { SimplePropBeacon_freeAttRsp(bleNotConnected); Display_print0(dispHandle, 2, 0, "Advertising Proprietary Beacon"); Display_print0(dispHandle, 3, 0, ""); break; } case GAPROLE_CONNECTED: { linkDBInfo_t linkInfo; uint8_t numActive = 0; numActive = linkDB_NumActive(); // Use numActive to determine the connection handle of the last // connection if ( linkDB_GetInfo( numActive - 1, &linkInfo ) == SUCCESS ) { Display_print1(dispHandle, 2, 0, "Num Conns: %d", (uint16_t)numActive); Display_print0(dispHandle, 3, 0, Util_convertBdAddr2Str(linkInfo.addr)); } else { uint8_t peerAddress[B_ADDR_LEN]; GAPRole_GetParameter(GAPROLE_CONN_BD_ADDR, peerAddress); Display_print0(dispHandle, 2, 0, "Connected"); Display_print0(dispHandle, 3, 0, Util_convertBdAddr2Str(peerAddress)); } } break; case GAPROLE_WAITING: case GAPROLE_WAITING_AFTER_TIMEOUT: SimplePropBeacon_freeAttRsp(bleNotConnected); SimplePropBeacon_startRegularAdv(); break; case GAPROLE_ERROR: Display_print0(dispHandle, 2, 0, "Error"); break; default: Display_clearLine(dispHandle, 2); break; } }
/********************************************************************* * @fn DualImageConcept_init * * @brief Called during initialization and contains application * specific initialization (ie. hardware initialization/setup, * table initialization, power up notification, etc), and * profile initialization/setup. * * @param None. * * @return None. */ static void DualImageConcept_init(void) { // For CC1350LP Set DIO1 High for 2.4 GHz Radio usage. // Set DIO30 High to power radio. // ****************************************************************** // 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, &sem); // Hard code the BD Address till CC2650 board gets its own IEEE address uint8 bdAddress[B_ADDR_LEN] = { 0x1C, 0xCD, 0xD1, 0x1C, 0xCD, 0xD1 }; HCI_EXT_SetBDADDRCmd(bdAddress); // Set device's Sleep Clock Accuracy //HCI_EXT_SetSCACmd(40); // Create an RTOS queue for message from profile to be sent to app. appMsgQueue = Util_constructQueue(&appMsg); Board_initKeys(DualImageConcept_keyChangeHandler); dispHandle = Display_open(Display_Type_LCD, NULL); // Setup the GAP GAP_SetParamValue(TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL); // Setup the GAP Peripheral Role Profile { // For all hardware platforms, device starts advertising upon initialization uint8_t initialAdvertEnable = TRUE; // 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 uint16_t advertOffTime = 0; uint8_t enableUpdateRequest = DEFAULT_ENABLE_UPDATE_REQUEST; uint16_t desiredMinInterval = DEFAULT_DESIRED_MIN_CONN_INTERVAL; uint16_t desiredMaxInterval = DEFAULT_DESIRED_MAX_CONN_INTERVAL; uint16_t desiredSlaveLatency = DEFAULT_DESIRED_SLAVE_LATENCY; uint16_t desiredConnTimeout = DEFAULT_DESIRED_CONN_TIMEOUT; // Set the GAP Role Parameters GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initialAdvertEnable); GAPRole_SetParameter(GAPROLE_ADVERT_OFF_TIME, sizeof(uint16_t), &advertOffTime); GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData), scanRspData); GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData); GAPRole_SetParameter(GAPROLE_PARAM_UPDATE_ENABLE, sizeof(uint8_t), &enableUpdateRequest); GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16_t), &desiredMinInterval); GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16_t), &desiredMaxInterval); GAPRole_SetParameter(GAPROLE_SLAVE_LATENCY, sizeof(uint16_t), &desiredSlaveLatency); GAPRole_SetParameter(GAPROLE_TIMEOUT_MULTIPLIER, sizeof(uint16_t), &desiredConnTimeout); } // Set the GAP Characteristics GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName); // Set advertising interval { 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); } // Initialize GATT attributes GGS_AddService(GATT_ALL_SERVICES); // GAP GATTServApp_AddService(GATT_ALL_SERVICES); // GATT attributes // Start the Device VOID GAPRole_StartDevice(&DualImageConcept_gapRoleCBs); Display_print0(dispHandle, 0, 0, "CC1350 BLE Image A"); // Check for shared data osal_snv_read(0x80, sizeof(uint8_t), &sharedData); // Write the shared data to the LCD. Display_print1(dispHandle, 6, 0, "Shared Data: %d", sharedData); }
/********************************************************************* * @fn SimpleBLEPeripheral_processStateChangeEvt * * @brief Process a pending GAP Role state change event. * * @param newState - new state * * @return None. */ static void SimpleBLEPeripheral_processStateChangeEvt(gaprole_States_t newState) { #ifdef PLUS_BROADCASTER static bool firstConnFlag = false; #endif // PLUS_BROADCASTER switch ( newState ) { case GAPROLE_STARTED: { uint8_t ownAddress[B_ADDR_LEN]; uint8_t systemId[DEVINFO_SYSTEM_ID_LEN]; GAPRole_GetParameter(GAPROLE_BD_ADDR, ownAddress); // use 6 bytes of device address for 8 bytes of system ID value systemId[0] = ownAddress[0]; systemId[1] = ownAddress[1]; systemId[2] = ownAddress[2]; // set middle bytes to zero systemId[4] = 0x00; systemId[3] = 0x00; // shift three bytes up systemId[7] = ownAddress[5]; systemId[6] = ownAddress[4]; systemId[5] = ownAddress[3]; DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId); // Display device address Display_print0(dispHandle, 1, 0, Util_convertBdAddr2Str(ownAddress)); Display_print0(dispHandle, 2, 0, "Initialized"); } break; case GAPROLE_ADVERTISING: Display_print0(dispHandle, 2, 0, "Advertising"); break; #ifdef PLUS_BROADCASTER /* After a connection is dropped a device in PLUS_BROADCASTER will continue * sending non-connectable advertisements and shall sending this change of * state to the application. These are then disabled here so that sending * connectable advertisements can resume. */ case GAPROLE_ADVERTISING_NONCONN: { uint8_t advertEnabled = FALSE; // Disable non-connectable advertising. GAPRole_SetParameter(GAPROLE_ADV_NONCONN_ENABLED, sizeof(uint8_t), &advertEnabled); advertEnabled = TRUE; // Enabled connectable advertising. GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &advertEnabled); // Reset flag for next connection. firstConnFlag = false; SimpleBLEPeripheral_freeAttRsp(bleNotConnected); } break; #endif //PLUS_BROADCASTER case GAPROLE_CONNECTED: { linkDBInfo_t linkInfo; uint8_t numActive = 0; Util_startClock(&periodicClock); numActive = linkDB_NumActive(); // Use numActive to determine the connection handle of the last // connection if ( linkDB_GetInfo( numActive - 1, &linkInfo ) == SUCCESS ) { Display_print1(dispHandle, 2, 0, "Num Conns: %d", (uint16_t)numActive); Display_print0(dispHandle, 3, 0, Util_convertBdAddr2Str(linkInfo.addr)); } else { uint8_t peerAddress[B_ADDR_LEN]; GAPRole_GetParameter(GAPROLE_CONN_BD_ADDR, peerAddress); Display_print0(dispHandle, 2, 0, "Connected"); Display_print0(dispHandle, 3, 0, Util_convertBdAddr2Str(peerAddress)); } #ifdef PLUS_BROADCASTER // Only turn advertising on for this state when we first connect // otherwise, when we go from connected_advertising back to this state // we will be turning advertising back on. if (firstConnFlag == false) { uint8_t advertEnabled = FALSE; // Turn on Advertising // Disable connectable advertising. GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &advertEnabled); // Set to true for non-connectabel advertising. advertEnabled = TRUE; // Enable non-connectable advertising. GAPRole_SetParameter(GAPROLE_ADV_NONCONN_ENABLED, sizeof(uint8_t), &advertEnabled); firstConnFlag = true; } #endif // PLUS_BROADCASTER } break; case GAPROLE_CONNECTED_ADV: Display_print0(dispHandle, 2, 0, "Connected Advertising"); break; case GAPROLE_WAITING: Util_stopClock(&periodicClock); SimpleBLEPeripheral_freeAttRsp(bleNotConnected); Display_print0(dispHandle, 2, 0, "Disconnected"); // Clear remaining lines Display_clearLines(dispHandle, 3, 5); break; case GAPROLE_WAITING_AFTER_TIMEOUT: SimpleBLEPeripheral_freeAttRsp(bleNotConnected); Display_print0(dispHandle, 2, 0, "Timed Out"); // Clear remaining lines Display_clearLines(dispHandle, 3, 5); #ifdef PLUS_BROADCASTER // Reset flag for next connection. firstConnFlag = false; #endif //#ifdef (PLUS_BROADCASTER) break; case GAPROLE_ERROR: Display_print0(dispHandle, 2, 0, "Error"); break; default: Display_clearLine(dispHandle, 2); break; } // Update the state //gapProfileState = newState; }