/********************************************************************* * @fn simpleTopology_processRoleEvent * * @brief Multi role event processing function. * * @param pEvent - pointer to event structure * * @return none */ static void simpleTopology_processRoleEvent(gapMultiRoleEvent_t *pEvent) { switch (pEvent->gap.opcode) { /*case GAP_MAKE_DISCOVERABLE_DONE_EVENT: { if (gapRoleNumLinks(GAPROLE_ACTIVE_LINKS) > 0) { LCD_WRITE_STRING("Advertising", LCD_PAGE2); } else { LCD_WRITE_STRING("Advertising", LCD_PAGE2); } } break;*/ case GAP_END_DISCOVERABLE_DONE_EVENT: { if (gapRoleNumLinks(GAPROLE_AVAILABLE_LINKS) > 0) { LCD_WRITE_STRING("Ready to Advertise", LCD_PAGE2); } else { LCD_WRITE_STRING("Can't Adv : No links", LCD_PAGE2); } } break; case GAP_DEVICE_DISCOVERY_EVENT: { // discovery complete scanningStarted = FALSE; advertising_enabled = TRUE; GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &advertising_enabled, NULL); } break; default: break; } }
/********************************************************************* * @fn simpleTopology_processRoleEvent * * @brief Multi role event processing function. * * @param pEvent - pointer to event structure * * @return none */ static void simpleTopology_processRoleEvent(gapMultiRoleEvent_t *pEvent) { switch (pEvent->gap.opcode) { case GAP_DEVICE_INIT_DONE_EVENT: { maxPduSize = pEvent->initDone.dataPktLen; LCD_WRITE_STRING("Connected to 0", LCD_PAGE0); LCD_WRITE_STRING(Util_convertBdAddr2Str(pEvent->initDone.devAddr), LCD_PAGE1); LCD_WRITE_STRING("Initialized", LCD_PAGE2); DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, pEvent->initDone.devAddr); } break; case GAP_MAKE_DISCOVERABLE_DONE_EVENT: { if (gapRoleNumLinks(GAPROLE_ACTIVE_LINKS) > 0) { LCD_WRITE_STRING("Advertising", LCD_PAGE2); } else { LCD_WRITE_STRING("Advertising", LCD_PAGE2); } } break; case GAP_END_DISCOVERABLE_DONE_EVENT: { if (gapRoleNumLinks(GAPROLE_AVAILABLE_LINKS) > 0) { LCD_WRITE_STRING("Ready to Advertise", LCD_PAGE2); } else { LCD_WRITE_STRING("Can't Adv : No links", LCD_PAGE2); } } break; case GAP_DEVICE_INFO_EVENT: { // if filtering device discovery results based on service UUID if (DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE) { if (simpleTopology_findSvcUuid(SIMPLEPROFILE_SERV_UUID, pEvent->deviceInfo.pEvtData, pEvent->deviceInfo.dataLen)) { simpleTopology_addDeviceInfo(pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType); } } } break; case GAP_DEVICE_DISCOVERY_EVENT: { // discovery complete scanningStarted = FALSE; // if not filtering device discovery results based on service UUID if (DEFAULT_DEV_DISC_BY_SVC_UUID == FALSE) { // Copy results scanRes = pEvent->discCmpl.numDevs; memcpy(devList, pEvent->discCmpl.pDevList, (sizeof(gapDevRec_t) * scanRes)); } LCD_WRITE_STRING_VALUE("Devices Found", scanRes, 10, LCD_PAGE3); if (scanRes > 0) { LCD_WRITE_STRING("<- To Select", LCD_PAGE4); } // initialize scan index to last device scanIdx = scanRes; } break; case GAP_LINK_ESTABLISHED_EVENT: { if (pEvent->gap.hdr.status == SUCCESS) { LCD_WRITE_STRING("Connected!", LCD_PAGE3); LCD_WRITE_STRING_VALUE("Connected to ", gapRoleNumLinks(GAPROLE_ACTIVE_LINKS) ,10, LCD_PAGE0); //update state connecting_state = 0; //store connection handle connHandle = pEvent->linkCmpl.connectionHandle; //if we're not advertising, attempt to turn advertising back on uint8_t adv; GAPRole_GetParameter(GAPROLE_ADVERT_ENABLED, &adv, NULL); if (adv == 1) //connected and advertising { if (gapRoleNumLinks(GAPROLE_AVAILABLE_LINKS) > 0) { LCD_WRITE_STRING("Advertising", LCD_PAGE2); } else //no available links { LCD_WRITE_STRING("Can't adv: no links", LCD_PAGE2); } } else //not currently advertising { LCD_WRITE_STRING("Ready to Advertise", LCD_PAGE2); //attempt to turn advertising back o uint8_t advertEnabled = TRUE; uint8_t stat = GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &advertEnabled, NULL); if (stat == bleNoResources) //no more links { LCD_WRITE_STRING("Can't adv: no links", LCD_PAGE2); } else if (stat == SUCCESS) //turning advertising back on { LCD_WRITE_STRING("Advertising", LCD_PAGE2); } else { while(1); } } // Print last connected device LCD_WRITE_STRING("", LCD_PAGE4); LCD_WRITE_STRING(Util_convertBdAddr2Str(pEvent->linkCmpl.devAddr), LCD_PAGE5 ); // initiate service discovery Util_startClock(&startDiscClock); } else { connHandle = GAP_CONNHANDLE_INIT; discState = BLE_DISC_STATE_IDLE; LCD_WRITE_STRING("Connect Failed", LCD_PAGE4); LCD_WRITE_STRING_VALUE("Reason:", pEvent->gap.hdr.status, 10, LCD_PAGE3); } } break; case GAP_LINK_TERMINATED_EVENT: { connHandle = GAP_CONNHANDLE_INIT; discState = BLE_DISC_STATE_IDLE; uint8_t i; for (i=0; i < MAX_NUM_BLE_CONNS; i++) { if (multiConnInfo[i].gapRole_ConnectionHandle == GAPROLE_CONN_JUST_TERMINATED) { //clear screen, reset discovery info, and return to main menu multiConnInfo[i].gapRole_ConnectionHandle = INVALID_CONNHANDLE; charHdl[i] = 0; LCD_WRITE_STRING_VALUE("Connected to ", gapRoleNumLinks(GAPROLE_ACTIVE_LINKS) ,10, LCD_PAGE0); LCD_WRITE_STRING("Disconnected!", LCD_PAGE5); LCD_WRITE_STRING("Main Menu", LCD_PAGE3); LCDmenu = MAIN_MENU; } if ((gapRoleNumLinks(GAPROLE_ACTIVE_LINKS) == (MAX_NUM_BLE_CONNS-1))) //now we can advertise again { LCD_WRITE_STRING("Ready to Advertise", LCD_PAGE2); } } } break; case GAP_LINK_PARAM_UPDATE_EVENT: { LCD_WRITE_STRING_VALUE("Param Update:", pEvent->linkUpdate.status, 10, LCD_PAGE2); } break; default: break; } }
/********************************************************************* * @fn simpleTopology_processGATTMsg * * @brief Process GATT messages and events. * * @return TRUE if safe to deallocate incoming message, FALSE otherwise. */ static uint8_t simpleTopology_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, SBT_CONN_EVT_END_EVT) == SUCCESS) { // First free any pending response simpleTopology_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. LCD_WRITE_STRING_VALUE("FC Violated:", pMsg->msg.flowCtrlEvt.opcode, 10, LCD_PAGE6); } else if (pMsg->method == ATT_MTU_UPDATED_EVENT) { // MTU size updated LCD_WRITE_STRING_VALUE("MTU Size:", pMsg->msg.mtuEvt.MTU, 10, LCD_PAGE6); } //messages from GATT server if ((gapRoleNumLinks(GAPROLE_ACTIVE_LINKS) > 0)) { if ((pMsg->method == ATT_READ_RSP) || ((pMsg->method == ATT_ERROR_RSP) && (pMsg->msg.errorRsp.reqOpcode == ATT_READ_REQ))) { if (pMsg->method == ATT_ERROR_RSP) { LCD_WRITE_STRING_VALUE("Read Error", pMsg->msg.errorRsp.errCode, 10, LCD_PAGE6); } else { // After a successful read, display the read value LCD_WRITE_STRING_VALUE("Read rsp:", pMsg->msg.readRsp.pValue[0], 10, LCD_PAGE6); } } else if ((pMsg->method == ATT_WRITE_RSP) || ((pMsg->method == ATT_ERROR_RSP) && (pMsg->msg.errorRsp.reqOpcode == ATT_WRITE_REQ))) { if (pMsg->method == ATT_ERROR_RSP == ATT_ERROR_RSP) { LCD_WRITE_STRING_VALUE("Write Error", pMsg->msg.errorRsp.errCode, 10, LCD_PAGE6); } else { // After a succesful write, display the value that was written and // increment value LCD_WRITE_STRING_VALUE("Write sent:", charVal++, 10, LCD_PAGE6); } } else if (discState != BLE_DISC_STATE_IDLE) { simpleTopology_processGATTDiscEvent(pMsg); } } // else - in case a GATT message came after a connection has dropped, ignore it. // 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 simpleTopology_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 simpleTopology_handleKeys(uint8_t shift, uint8_t keys) { (void)shift; // Intentionally unreferenced parameter if (LCDmenu == MAIN_MENU) { if (keys & KEY_LEFT) //show discovery results { selectKey = DISCOVERED_DEVICES; // If discovery has occurred and a device was found if (!scanningStarted && scanRes > 0) { // Increment index of current result (with wraparound) scanIdx++; if (scanIdx >= scanRes) { scanIdx = 0; } LCD_WRITE_STRING_VALUE("Device", (scanIdx + 1), 10, LCD_PAGE3); LCD_WRITE_STRING(Util_convertBdAddr2Str(devList[scanIdx].addr), LCD_PAGE4); } return; } if (keys & KEY_UP) //Scan for devices { // Start or stop discovery if (gapRoleNumLinks(GAPROLE_AVAILABLE_LINKS) > 0) //if we can connect to another device { if (!scanningStarted) //if we're not already scanning { scanningStarted = TRUE; scanRes = 0; LCD_WRITE_STRING("Discovering...", LCD_PAGE3); LCD_WRITE_STRING("", LCD_PAGE4); LCD_WRITE_STRING("", LCD_PAGE6); GAPRole_StartDiscovery(DEFAULT_DISCOVERY_MODE, DEFAULT_DISCOVERY_ACTIVE_SCAN, DEFAULT_DISCOVERY_WHITE_LIST); } else //cancel scanning { LCD_WRITE_STRING("Discovery Cancelled", LCD_PAGE3); GAPRole_CancelDiscovery(); scanningStarted = FALSE; } } else // can't add more links at this time { LCD_WRITE_STRING("Can't scan:no links ", LCD_PAGE3); } return; } if (keys & KEY_RIGHT) // turn advertising on / off { uint8_t adv; uint8_t adv_status; GAPRole_GetParameter(GAPROLE_ADVERT_ENABLED, &adv_status, NULL); if (adv_status) //turn off { adv = FALSE; GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &adv, NULL); } else //turn on { adv = TRUE; GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &adv, NULL); } return; } if (keys & KEY_SELECT) //connect to a discovered device { if (selectKey == DISCOVERED_DEVICES) // connect to a device { uint8_t addrType; uint8_t *peerAddr; if (connecting_state == 1) // if already attempting to connect, cancel connection { GAPRole_TerminateConnection(0xFFFE); LCD_WRITE_STRING("Connecting stopped.", LCD_PAGE3); connecting_state = 0; } else //establish new connection { // if there is a scan result if (scanRes > 0) { // connect to current device in scan result peerAddr = devList[scanIdx].addr; addrType = devList[scanIdx].addrType; GAPRole_EstablishLink(DEFAULT_LINK_HIGH_DUTY_CYCLE, DEFAULT_LINK_WHITE_LIST, addrType, peerAddr); connecting_state = 1; LCD_WRITE_STRING("Connecting", LCD_PAGE3); LCD_WRITE_STRING(Util_convertBdAddr2Str(peerAddr), LCD_PAGE4); } } } else if (selectKey == CONNECTED_DEVICES) //enter the device menu { if (multiConnInfo[connIdx].gapRole_ConnectionHandle != INVALID_CONNHANDLE) { LCDmenu = DEVICE_MENU; LCD_WRITE_STRING("Device Menu", LCD_PAGE3); LCD_WRITE_STRING(Util_convertBdAddr2Str(multiConnInfo[connIdx].gapRole_devAddr), LCD_PAGE4); if (multiConnInfo[connIdx].gapRole_ConnRole == GAP_PROFILE_CENTRAL) { LCD_WRITE_STRING("Connected as Central", LCD_PAGE5); LCD_WRITE_STRING("", LCD_PAGE6); LCD_WRITE_STRING("", LCD_PAGE7); } else //PERIPHERAL { LCD_WRITE_STRING("Connected as Periph", LCD_PAGE5); LCD_WRITE_STRING("", LCD_PAGE6); LCD_WRITE_STRING("", LCD_PAGE7); } //use this connection for all functionality connHandle = multiConnInfo[connIdx].gapRole_ConnectionHandle; } else // no active connection here LCD_WRITE_STRING("No Connection here.", LCD_PAGE3); } return; } if (keys & KEY_DOWN) //browse connected devices { LCD_WRITE_STRING("Connected Device:", LCD_PAGE3); if (++connIdx >= MAX_NUM_BLE_CONNS) //increment connIdx { connIdx = 0; } if (multiConnInfo[connIdx].gapRole_ConnectionHandle != INVALID_CONNHANDLE) //if there is a connection at this index { LCD_WRITE_STRING(Util_convertBdAddr2Str(multiConnInfo[connIdx].gapRole_devAddr), LCD_PAGE4); } else { LCD_WRITE_STRING("N/A", LCD_PAGE4); } selectKey = CONNECTED_DEVICES; } return; } else if (LCDmenu == DEVICE_MENU) { if (keys & KEY_UP) //read/whrite char { if (charHdl[connIdx] != 0) { uint8_t status; // Do a read or write as long as no other read or write is in progress if (doWrite) { // Do a write attWriteReq_t req; req.pValue = GATT_bm_alloc(connHandle, ATT_WRITE_REQ, 1, NULL); if ( req.pValue != NULL ) { req.handle = charHdl[connIdx]; req.len = 1; req.pValue[0] = charVal; req.sig = 0; req.cmd = 0; status = GATT_WriteCharValue(connHandle, &req, selfEntity); if ( status != SUCCESS ) { GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ); } } } else { // Do a read attReadReq_t req; req.handle = charHdl[connIdx]; status = GATT_ReadCharValue(connHandle, &req, selfEntity); } if (status == SUCCESS) { doWrite = !doWrite; } } return; } if (keys & KEY_RIGHT) //connection update...eventually { asm("NOP"); return; } if (keys & KEY_SELECT) { GAPRole_TerminateConnection(connHandle); LCD_WRITE_STRING("Disconnecting", LCD_PAGE5); LCD_WRITE_STRING("", LCD_PAGE6); return; } if (keys & KEY_DOWN) //back to main menu { LCDmenu = MAIN_MENU; LCD_WRITE_STRING("Main Menu", LCD_PAGE3); //clear screen LCD_WRITE_STRING("", LCD_PAGE4); LCD_WRITE_STRING("", LCD_PAGE5); LCD_WRITE_STRING("", LCD_PAGE6); LCD_WRITE_STRING("", LCD_PAGE7); LCD_WRITE_STRING_VALUE("Connected to ", gapRoleNumLinks(GAPROLE_ACTIVE_LINKS) ,10, LCD_PAGE0); connIdx = 0; return; } } }
/********************************************************************* * @brief Set a GAP Role parameter. * * Public function defined in peripheral.h. */ bStatus_t GAPRole_SetParameter(uint16_t param, uint8_t len, void *pValue, uint8 connHandle) { bStatus_t ret = SUCCESS; switch (param) { case GAPROLE_IRK: if (len == KEYLEN) { VOID memcpy(gapRole_IRK, pValue, KEYLEN); } else { ret = bleInvalidRange; } break; case GAPROLE_SRK: if (len == KEYLEN) { VOID memcpy(gapRole_SRK, pValue, KEYLEN); } else { ret = bleInvalidRange; } break; case GAPROLE_SIGNCOUNTER: if (len == sizeof(uint32_t)) { gapRole_signCounter = *((uint32_t*) pValue); } else { ret = bleInvalidRange; } break; case GAPROLE_ADVERT_ENABLED: //connectable advertising if (len == sizeof(uint8_t)) { // Non-connectable advertising must be disabled. if (gapRole_AdvNonConnEnabled != TRUE) { uint8_t oldAdvEnabled = gapRole_AdvEnabled; gapRole_AdvEnabled = *((uint8_t*) pValue); if ((oldAdvEnabled) && (gapRole_AdvEnabled == FALSE)) { // Turn off advertising. //if ((gapRole_peripheralState == GAPROLE_ADVERTISING) || (gapRole_peripheralState == GAPROLE_WAITING_AFTER_TIMEOUT)) { VOID GAP_EndDiscoverable(selfEntity); //} } else if ((oldAdvEnabled == FALSE) && (gapRole_AdvEnabled)) { // Turn on advertising. if (gapRoleNumLinks(GAPROLE_AVAILABLE_LINKS)) //don't do conn adv if we don't have any avilable links { // Turn on advertising. //if ((gapRole_peripheralState == GAPROLE_STARTED) || (gapRole_peripheralState == GAPROLE_WAITING) || (gapRole_peripheralState == GAPROLE_WAITING_AFTER_TIMEOUT)) { gapRole_setEvent(START_ADVERTISING_EVT); //} //gapRole_setEvent(START_ADVERTISING_EVT); } else { return bleNoResources; // no more available links } } } else { ret = bleIncorrectMode; } } else { ret = bleInvalidRange; } break; case GAPROLE_ADV_NONCONN_ENABLED: if (len == sizeof(uint8_t)) { // Connectable advertising must be disabled. if (gapRole_AdvEnabled != TRUE) { uint8_t oldAdvEnabled = gapRole_AdvNonConnEnabled; gapRole_AdvNonConnEnabled = *((uint8_t*) pValue); if ((oldAdvEnabled) && (gapRole_AdvNonConnEnabled == FALSE)) { //if ((gapRole_peripheralState == GAPROLE_ADVERTISING_NONCONN) || (gapRole_peripheralState == GAPROLE_CONNECTED_ADV) || (gapRole_peripheralState == GAPROLE_WAITING_AFTER_TIMEOUT)) { VOID GAP_EndDiscoverable(selfEntity); //} } else if ((oldAdvEnabled == FALSE) && (gapRole_AdvNonConnEnabled)) { // Turn on advertising. //if ((gapRole_peripheralState == GAPROLE_STARTED) || (gapRole_peripheralState == GAPROLE_WAITING) || (gapRole_peripheralState == GAPROLE_CONNECTED) // || (gapRole_peripheralState == GAPROLE_WAITING_AFTER_TIMEOUT)) { gapRole_setEvent(START_ADVERTISING_EVT); //} } } else { ret = bleIncorrectMode; } } else { ret = bleInvalidRange; } break; case GAPROLE_ADVERT_OFF_TIME: if (len == sizeof(uint16_t)) { gapRole_AdvertOffTime = *((uint16_t*) pValue); } else { ret = bleInvalidRange; } break; case GAPROLE_ADVERT_DATA: if (len <= B_MAX_ADV_LEN) { VOID memset(gapRole_AdvertData, 0, B_MAX_ADV_LEN); VOID memcpy(gapRole_AdvertData, pValue, len); gapRole_AdvertDataLen = len; // Update the advertising data ret = GAP_UpdateAdvertisingData(selfEntity, TRUE, gapRole_AdvertDataLen, gapRole_AdvertData); } else { ret = bleInvalidRange; } break; case GAPROLE_SCAN_RSP_DATA: if (len <= B_MAX_ADV_LEN) { VOID memset(gapRole_ScanRspData, 0, B_MAX_ADV_LEN); VOID memcpy(gapRole_ScanRspData, pValue, len); gapRole_ScanRspDataLen = len; // Update the Response Data ret = GAP_UpdateAdvertisingData(selfEntity, FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData); } else { ret = bleInvalidRange; } break; case GAPROLE_ADV_EVENT_TYPE: if ((len == sizeof(uint8_t)) && (*((uint8_t*) pValue) <= GAP_ADTYPE_ADV_LDC_DIRECT_IND)) { gapRole_AdvEventType = *((uint8_t*) pValue); } else { ret = bleInvalidRange; } break; case GAPROLE_ADV_DIRECT_TYPE: if ((len == sizeof(uint8_t)) && (*((uint8_t*) pValue) <= ADDRMODE_PRIVATE_RESOLVE)) { gapRole_AdvDirectType = *((uint8_t*) pValue); } else { ret = bleInvalidRange; } break; case GAPROLE_ADV_DIRECT_ADDR: if (len == B_ADDR_LEN) { VOID memcpy(gapRole_AdvDirectAddr, pValue, B_ADDR_LEN); } else { ret = bleInvalidRange; } break; case GAPROLE_ADV_CHANNEL_MAP: if ((len == sizeof(uint8_t)) && (*((uint8_t*) pValue) <= 0x07)) { gapRole_AdvChanMap = *((uint8_t*) pValue); } else { ret = bleInvalidRange; } break; case GAPROLE_ADV_FILTER_POLICY: if ((len == sizeof(uint8_t)) && (*((uint8_t*) pValue) <= GAP_FILTER_POLICY_WHITE)) { gapRole_AdvFilterPolicy = *((uint8_t*) pValue); } else { ret = bleInvalidRange; } break; case GAPROLE_PARAM_UPDATE_ENABLE: if ((len == sizeof(uint8_t)) && (*((uint8_t*) pValue) <= TRUE)) { gapRole_ParamUpdateEnable = *((uint8_t*) pValue); } else { ret = bleInvalidRange; } break; case GAPROLE_MIN_CONN_INTERVAL: { uint16_t newInterval = *((uint16_t*) pValue); if (len == sizeof(uint16_t) && (newInterval >= MIN_CONN_INTERVAL) && (newInterval <= MAX_CONN_INTERVAL)) { gapRole_MinConnInterval = newInterval; } else { ret = bleInvalidRange; } } break; case GAPROLE_MAX_CONN_INTERVAL: { uint16_t newInterval = *((uint16_t*) pValue); if (len == sizeof(uint16_t) && (newInterval >= MIN_CONN_INTERVAL) && (newInterval <= MAX_CONN_INTERVAL)) { gapRole_MaxConnInterval = newInterval; } else { ret = bleInvalidRange; } } break; case GAPROLE_SLAVE_LATENCY: { uint16_t latency = *((uint16_t*) pValue); if (len == sizeof(uint16_t) && (latency < MAX_SLAVE_LATENCY)) { gapRole_SlaveLatency = latency; } else { ret = bleInvalidRange; } } break; case GAPROLE_TIMEOUT_MULTIPLIER: { uint16_t newTimeout = *((uint16_t*) pValue); if (len == sizeof(uint16_t) && (newTimeout >= MIN_TIMEOUT_MULTIPLIER) && (newTimeout <= MAX_TIMEOUT_MULTIPLIER)) { gapRole_TimeoutMultiplier = newTimeout; } else { ret = bleInvalidRange; } } break; case GAPROLE_PARAM_UPDATE_REQ: { uint8_t req = *((uint8_t*) pValue); if (len == sizeof(uint8_t) && (req == TRUE)) { // Make sure we don't send an L2CAP Connection Parameter Update Request // command within TGAP(conn_param_timeout) of an L2CAP Connection Parameter // Update Response being received. if (Util_isActive(&updateTimeoutClock) == FALSE) { // Start connection update procedure uint8 index = 0; while (index < MAX_NUM_BLE_CONNS && multiConnInfo[index].gapRole_ConnRole != GAP_PROFILE_PERIPHERAL && multiConnInfo[index].gapRole_ConnectionHandle != GAPROLE_CONN_JUST_TERMINATED) { index++; } if (index >= MAX_NUM_BLE_CONNS) { //no connection as peripheral found ret = INVALIDPARAMETER; //Util_stopClock(&startUpdateClock); } else { ret = gapRole_startConnUpdate(GAPROLE_NO_ACTION, multiConnInfo[index].gapRole_ConnectionHandle); } if (ret == SUCCESS) { // Connection update requested by app, cancel such pending procedure (if active) Util_stopClock(&startUpdateClock); } } else { ret = blePending; } } else { ret = bleInvalidRange; } } break; case GAPROLE_MAX_SCAN_RES: if (len == sizeof(uint8_t)) { gapRoleMaxScanRes = *((uint8_t*) pValue); } else { ret = bleInvalidRange; } break; default: // The param value isn't part of this profile, try the GAP. if ((param < TGAP_PARAMID_MAX) && (len == sizeof(uint16_t))) { ret = GAP_SetParamValue(param, *((uint16_t*) pValue)); } else { ret = INVALIDPARAMETER; } break; } return (ret); }