uint32_t conn_mw_ble_gap_adv_data_set(uint8_t const * const p_rx_buf, uint32_t rx_buf_len, uint8_t * const p_tx_buf, uint32_t * const p_tx_buf_len) { SER_ASSERT_NOT_NULL(p_rx_buf); SER_ASSERT_NOT_NULL(p_tx_buf); SER_ASSERT_NOT_NULL(p_tx_buf_len); uint8_t data[BLE_GAP_ADV_MAX_SIZE]; uint8_t * p_data = data; uint8_t dlen = sizeof (data); uint8_t sr_data[BLE_GAP_ADV_MAX_SIZE]; uint8_t * p_sr_data = sr_data; uint8_t srdlen = sizeof (sr_data); uint32_t err_code = NRF_SUCCESS; uint32_t sd_err_code; err_code = ble_gap_adv_data_set_req_dec(p_rx_buf, rx_buf_len, &p_data, &dlen, &p_sr_data, &srdlen); SER_ASSERT(err_code == NRF_SUCCESS, err_code); sd_err_code = sd_ble_gap_adv_data_set(p_data, dlen, p_sr_data, srdlen); err_code = ble_gap_adv_data_set_rsp_enc(sd_err_code, p_tx_buf, p_tx_buf_len); SER_ASSERT(err_code == NRF_SUCCESS, err_code); return err_code; }
void app_beacon_start(void) { uint32_t err_code; uint8_t adv_pdu[ADV_DATA_LEN]; uint8_t adv_len = encode_adv_packet(&adv_pdu[0]); err_code = sd_ble_gap_adv_data_set(adv_pdu, adv_len, NULL, 0); if (err_code != NRF_SUCCESS) { if (m_beacon.error_handler != NULL) { m_beacon.error_handler(err_code); } } err_code = sd_ble_gap_adv_start(&m_beacon.adv_params); if (err_code != NRF_SUCCESS) { if (m_beacon.error_handler != NULL) { m_beacon.error_handler(err_code); } } }
uint32_t ble_advdata_set(const ble_advdata_t * p_advdata, const ble_advdata_t * p_srdata) { uint32_t err_code; uint16_t len_advdata = BLE_GAP_ADV_MAX_SIZE; uint16_t len_srdata = BLE_GAP_ADV_MAX_SIZE; uint8_t encoded_advdata[BLE_GAP_ADV_MAX_SIZE]; uint8_t encoded_srdata[BLE_GAP_ADV_MAX_SIZE]; uint8_t * p_encoded_advdata; uint8_t * p_encoded_srdata; // Encode advertising data (if supplied). if (p_advdata != NULL) { err_code = advdata_check(p_advdata); if (err_code != NRF_SUCCESS) { return err_code; } err_code = adv_data_encode(p_advdata, encoded_advdata, &len_advdata); if (err_code != NRF_SUCCESS) { return err_code; } p_encoded_advdata = encoded_advdata; } else { p_encoded_advdata = NULL; len_advdata = 0; } // Encode scan response data (if supplied). if (p_srdata != NULL) { err_code = srdata_check(p_srdata); if (err_code != NRF_SUCCESS) { return err_code; } err_code = adv_data_encode(p_srdata, encoded_srdata, &len_srdata); if (err_code != NRF_SUCCESS) { return err_code; } p_encoded_srdata = encoded_srdata; } else { p_encoded_srdata = NULL; len_srdata = 0; } // Pass encoded advertising data and/or scan response data to the stack. return sd_ble_gap_adv_data_set(p_encoded_advdata, len_advdata, p_encoded_srdata, len_srdata); }
ble_error_t nRF5xGap::setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) { /* Make sure we don't exceed the advertising payload length */ if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD) { return BLE_ERROR_BUFFER_OVERFLOW; } /* Make sure we have a payload! */ if (advData.getPayloadLen() == 0) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } /* Check the scan response payload limits */ //if ((params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED)) //{ // /* Check if we're within the upper limit */ // if (advData.getPayloadLen() > GAP_ADVERTISING_DATA_MAX_PAYLOAD) // { // return BLE_ERROR_BUFFER_OVERFLOW; // } // /* Make sure we have a payload! */ // if (advData.getPayloadLen() == 0) // { // return BLE_ERROR_PARAM_OUT_OF_RANGE; // } //} /* Send advertising data! */ ASSERT_TRUE(ERROR_NONE == sd_ble_gap_adv_data_set(advData.getPayload(), advData.getPayloadLen(), scanResponse.getPayload(), scanResponse.getPayloadLen()), BLE_ERROR_PARAM_OUT_OF_RANGE); /* Make sure the GAP Service appearance value is aligned with the *appearance from GapAdvertisingData */ ASSERT_TRUE(ERROR_NONE == sd_ble_gap_appearance_set(advData.getAppearance()), BLE_ERROR_PARAM_OUT_OF_RANGE); /* ToDo: Perform some checks on the payload, for example the Scan Response can't */ /* contains a flags AD type, etc. */ return BLE_ERROR_NONE; }
/**@brief Function for the Advertising functionality initialization. * * @details Encodes the required advertising data and passes it to the stack. * The advertising data encoded here is specific for DFU. * Setting advertising data can by done by calling @ref ble_advdata_set. */ static uint32_t advertising_init(uint8_t adv_flags) { uint32_t err_code; uint16_t len_advdata = 9; uint16_t max_device_name_length = MAX_ADV_DATA_LENGTH - len_advdata; uint16_t actual_device_name_length = max_device_name_length; uint8_t p_encoded_advdata[MAX_ADV_DATA_LENGTH]; // Encode flags. p_encoded_advdata[0] = 0x2; p_encoded_advdata[1] = BLE_GAP_AD_TYPE_FLAGS; p_encoded_advdata[2] = adv_flags; // Encode 'more available' uuid list. p_encoded_advdata[3] = 0x3; p_encoded_advdata[4] = BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE; p_encoded_advdata[5] = LSB_16(BLE_DFU_SERVICE_UUID); p_encoded_advdata[6] = MSB_16(BLE_DFU_SERVICE_UUID); // Get GAP device name and length err_code = sd_ble_gap_device_name_get(&p_encoded_advdata[9], &actual_device_name_length); if (err_code != NRF_SUCCESS) { return err_code; } // Set GAP device in advertising data. if (actual_device_name_length <= max_device_name_length) { p_encoded_advdata[7] = actual_device_name_length + 1; // (actual_length + ADV_AD_TYPE_FIELD_SIZE(1)) p_encoded_advdata[8] = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME; len_advdata += actual_device_name_length; } else { // Must use a shorter advertising name than the actual name of the device p_encoded_advdata[7] = max_device_name_length + 1; // (length + ADV_AD_TYPE_FIELD_SIZE(1)) p_encoded_advdata[8] = BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME; len_advdata = MAX_ADV_DATA_LENGTH; } return sd_ble_gap_adv_data_set(p_encoded_advdata, len_advdata, NULL, 0); }
/**@brief Function for decoding a command packet with RPC_SD_BLE_GAP_ADV_DATA_SET opcode. * * This function will decode the command, call the BLE Stack API, and also send command response * to the peer through the the transport layer. * * @param[in] p_command The encoded structure that needs to be decoded and passed on * to the BLE Stack API. * @param[in] command_len The length of the encoded command read from transport layer. * * @retval NRF_SUCCESS If the decoding of the command was successful, the SoftDevice * API was called, and the command response was sent to peer, * otherwise an error code. * @retval NRF_ERROR_INVALID_LENGTH If the content length of the packet is not conforming to the * codec specification. * * @note The NRF_ERROR_INVALID_LENGTH error code for this function represents both a SoftDevice * error and content length check error. */ static uint32_t gap_adv_data_set_handle(const uint8_t * const p_command, uint32_t command_len) { uint8_t dlen; uint8_t srdlen; const uint8_t * p_data; const uint8_t * p_sr_data; uint32_t index = 0; dlen = p_command[index++]; RPC_DECODER_LENGTH_CHECK(command_len, (index + dlen), SD_BLE_GAP_ADV_DATA_SET); p_data = &(p_command[index]); index += dlen; srdlen = p_command[index++]; RPC_DECODER_LENGTH_CHECK(command_len, (index + srdlen), SD_BLE_GAP_ADV_DATA_SET); p_sr_data = &(p_command[index]); uint32_t err_code = sd_ble_gap_adv_data_set(p_data, dlen, p_sr_data, srdlen); return ble_rpc_cmd_resp_send(SD_BLE_GAP_ADV_DATA_SET, err_code); }
bool nRF51822::broadcastCharacteristic(BLECharacteristic& characteristic) { bool success = false; for (int i = 0; i < this->_numLocalCharacteristics; i++) { struct localCharacteristicInfo* localCharacteristicInfo = &this->_localCharacteristicInfo[i]; if (localCharacteristicInfo->characteristic == &characteristic) { if (characteristic.properties() & BLEBroadcast && localCharacteristicInfo->service) { unsigned char advData[31]; unsigned char advDataLen = this->_advDataLen; // copy the existing advertisement data memcpy(advData, this->_advData, advDataLen); advDataLen += (4 + characteristic.valueLength()); if (advDataLen <= 31) { BLEUuid uuid = BLEUuid(localCharacteristicInfo->service->uuid()); advData[this->_advDataLen + 0] = 3 + characteristic.valueLength(); advData[this->_advDataLen + 1] = 0x16; memcpy(&advData[this->_advDataLen + 2], uuid.data(), 2); memcpy(&advData[this->_advDataLen + 4], characteristic.value(), characteristic.valueLength()); sd_ble_gap_adv_data_set(advData, advDataLen, NULL, 0); // update advertisement data success = true; this->_broadcastCharacteristic = &characteristic; } } break; } } return success; }
void nRF51822::begin(unsigned char advertisementDataType, unsigned char advertisementDataLength, const unsigned char* advertisementData, unsigned char scanDataType, unsigned char scanDataLength, const unsigned char* scanData, BLELocalAttribute** localAttributes, unsigned char numLocalAttributes, BLERemoteAttribute** remoteAttributes, unsigned char numRemoteAttributes) { #ifdef __RFduino__ sd_softdevice_enable(NRF_CLOCK_LFCLKSRC_SYNTH_250_PPM, NULL); #else sd_softdevice_enable(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, NULL); // sd_nvic_EnableIRQ(SWI2_IRQn); #endif #ifdef NRF51_S130 ble_enable_params_t enableParams = { .gatts_enable_params = { .service_changed = true } }; sd_ble_enable(&enableParams); #endif #ifdef NRF_51822_DEBUG ble_version_t version; sd_ble_version_get(&version); Serial.print(F("version = ")); Serial.print(version.version_number); Serial.print(F(" ")); Serial.print(version.company_id); Serial.print(F(" ")); Serial.print(version.subversion_number); Serial.println(); #endif ble_gap_conn_params_t gap_conn_params; gap_conn_params.min_conn_interval = 40; // in 1.25ms units gap_conn_params.max_conn_interval = 80; // in 1.25ms unit gap_conn_params.slave_latency = 0; gap_conn_params.conn_sup_timeout = 4000 / 10; // in 10ms unit sd_ble_gap_ppcp_set(&gap_conn_params); sd_ble_gap_tx_power_set(0); unsigned char srData[31]; unsigned char srDataLen = 0; this->_advDataLen = 0; // flags this->_advData[this->_advDataLen + 0] = 2; this->_advData[this->_advDataLen + 1] = 0x01; this->_advData[this->_advDataLen + 2] = 0x06; this->_advDataLen += 3; if (advertisementDataType && advertisementDataLength && advertisementData) { this->_advData[this->_advDataLen + 0] = advertisementDataLength + 1; this->_advData[this->_advDataLen + 1] = advertisementDataType; this->_advDataLen += 2; memcpy(&this->_advData[this->_advDataLen], advertisementData, advertisementDataLength); this->_advDataLen += advertisementDataLength; } if (scanDataType && scanDataLength && scanData) { srData[0] = scanDataLength + 1; srData[1] = scanDataType; memcpy(&srData[2], scanData, scanDataLength); srDataLen = 2 + scanDataLength; } sd_ble_gap_adv_data_set(this->_advData, this->_advDataLen, srData, srDataLen); sd_ble_gap_appearance_set(0); for (int i = 0; i < numLocalAttributes; i++) { BLELocalAttribute *localAttribute = localAttributes[i]; if (localAttribute->type() == BLETypeCharacteristic) { this->_numLocalCharacteristics++; } } this->_numLocalCharacteristics -= 3; // 0x2a00, 0x2a01, 0x2a05 this->_localCharacteristicInfo = (struct localCharacteristicInfo*)malloc(sizeof(struct localCharacteristicInfo) * this->_numLocalCharacteristics); unsigned char localCharacteristicIndex = 0; uint16_t handle = 0; BLEService *lastService = NULL; for (int i = 0; i < numLocalAttributes; i++) { BLELocalAttribute *localAttribute = localAttributes[i]; BLEUuid uuid = BLEUuid(localAttribute->uuid()); const unsigned char* uuidData = uuid.data(); unsigned char value[255]; ble_uuid_t nordicUUID; if (uuid.length() == 2) { nordicUUID.uuid = (uuidData[1] << 8) | uuidData[0]; nordicUUID.type = BLE_UUID_TYPE_BLE; } else { unsigned char uuidDataTemp[16]; memcpy(&uuidDataTemp, uuidData, sizeof(uuidDataTemp)); nordicUUID.uuid = (uuidData[13] << 8) | uuidData[12]; uuidDataTemp[13] = 0; uuidDataTemp[12] = 0; sd_ble_uuid_vs_add((ble_uuid128_t*)&uuidDataTemp, &nordicUUID.type); } if (localAttribute->type() == BLETypeService) { BLEService *service = (BLEService *)localAttribute; if (strcmp(service->uuid(), "1800") == 0 || strcmp(service->uuid(), "1801") == 0) { continue; // skip } sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &nordicUUID, &handle); lastService = service; } else if (localAttribute->type() == BLETypeCharacteristic) { BLECharacteristic *characteristic = (BLECharacteristic *)localAttribute; if (strcmp(characteristic->uuid(), "2a00") == 0) { ble_gap_conn_sec_mode_t secMode; BLE_GAP_CONN_SEC_MODE_SET_OPEN(&secMode); // no security is needed sd_ble_gap_device_name_set(&secMode, characteristic->value(), characteristic->valueLength()); } else if (strcmp(characteristic->uuid(), "2a01") == 0) { const uint16_t *appearance = (const uint16_t*)characteristic->value(); sd_ble_gap_appearance_set(*appearance); } else if (strcmp(characteristic->uuid(), "2a05") == 0) { // do nothing } else { uint8_t properties = characteristic->properties() & 0xfe; uint16_t valueLength = characteristic->valueLength(); this->_localCharacteristicInfo[localCharacteristicIndex].characteristic = characteristic; this->_localCharacteristicInfo[localCharacteristicIndex].notifySubscribed = false; this->_localCharacteristicInfo[localCharacteristicIndex].indicateSubscribed = false; this->_localCharacteristicInfo[localCharacteristicIndex].service = lastService; ble_gatts_char_md_t characteristicMetaData; ble_gatts_attr_md_t clientCharacteristicConfigurationMetaData; ble_gatts_attr_t characteristicValueAttribute; ble_gatts_attr_md_t characteristicValueAttributeMetaData; memset(&characteristicMetaData, 0, sizeof(characteristicMetaData)); memcpy(&characteristicMetaData.char_props, &properties, 1); characteristicMetaData.p_char_user_desc = NULL; characteristicMetaData.p_char_pf = NULL; characteristicMetaData.p_user_desc_md = NULL; characteristicMetaData.p_cccd_md = NULL; characteristicMetaData.p_sccd_md = NULL; if (properties & (BLENotify | BLEIndicate)) { memset(&clientCharacteristicConfigurationMetaData, 0, sizeof(clientCharacteristicConfigurationMetaData)); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&clientCharacteristicConfigurationMetaData.read_perm); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&clientCharacteristicConfigurationMetaData.write_perm); clientCharacteristicConfigurationMetaData.vloc = BLE_GATTS_VLOC_STACK; characteristicMetaData.p_cccd_md = &clientCharacteristicConfigurationMetaData; } memset(&characteristicValueAttributeMetaData, 0, sizeof(characteristicValueAttributeMetaData)); if (properties & (BLERead | BLENotify | BLEIndicate)) { if (this->_bondStore) { BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&characteristicValueAttributeMetaData.read_perm); } else { BLE_GAP_CONN_SEC_MODE_SET_OPEN(&characteristicValueAttributeMetaData.read_perm); } } if (properties & (BLEWriteWithoutResponse | BLEWrite)) { if (this->_bondStore) { BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&characteristicValueAttributeMetaData.write_perm); } else { BLE_GAP_CONN_SEC_MODE_SET_OPEN(&characteristicValueAttributeMetaData.write_perm); } } characteristicValueAttributeMetaData.vloc = BLE_GATTS_VLOC_STACK; characteristicValueAttributeMetaData.rd_auth = 0; characteristicValueAttributeMetaData.wr_auth = 0; characteristicValueAttributeMetaData.vlen = !characteristic->fixedLength(); for (int j = (i + 1); j < numLocalAttributes; j++) { localAttribute = localAttributes[j]; if (localAttribute->type() != BLETypeDescriptor) { break; } BLEDescriptor *descriptor = (BLEDescriptor *)localAttribute; if (strcmp(descriptor->uuid(), "2901") == 0) { characteristicMetaData.p_char_user_desc = (uint8_t*)descriptor->value(); characteristicMetaData.char_user_desc_max_size = descriptor->valueLength(); characteristicMetaData.char_user_desc_size = descriptor->valueLength(); } else if (strcmp(descriptor->uuid(), "2904") == 0) { characteristicMetaData.p_char_pf = (ble_gatts_char_pf_t *)descriptor->value(); } } memset(&characteristicValueAttribute, 0, sizeof(characteristicValueAttribute)); characteristicValueAttribute.p_uuid = &nordicUUID; characteristicValueAttribute.p_attr_md = &characteristicValueAttributeMetaData; characteristicValueAttribute.init_len = valueLength; characteristicValueAttribute.init_offs = 0; characteristicValueAttribute.max_len = characteristic->valueSize(); characteristicValueAttribute.p_value = NULL; sd_ble_gatts_characteristic_add(BLE_GATT_HANDLE_INVALID, &characteristicMetaData, &characteristicValueAttribute, &this->_localCharacteristicInfo[localCharacteristicIndex].handles); if (valueLength) { for (int j = 0; j < valueLength; j++) { value[j] = (*characteristic)[j]; } sd_ble_gatts_value_set(this->_localCharacteristicInfo[localCharacteristicIndex].handles.value_handle, 0, &valueLength, value); } localCharacteristicIndex++; } } else if (localAttribute->type() == BLETypeDescriptor) { BLEDescriptor *descriptor = (BLEDescriptor *)localAttribute; if (strcmp(descriptor->uuid(), "2901") == 0 || strcmp(descriptor->uuid(), "2902") == 0 || strcmp(descriptor->uuid(), "2903") == 0 || strcmp(descriptor->uuid(), "2904") == 0) { continue; // skip } uint16_t valueLength = descriptor->valueLength(); ble_gatts_attr_t descriptorAttribute; ble_gatts_attr_md_t descriptorMetaData; memset(&descriptorAttribute, 0, sizeof(descriptorAttribute)); memset(&descriptorMetaData, 0, sizeof(descriptorMetaData)); descriptorMetaData.vloc = BLE_GATTS_VLOC_STACK; descriptorMetaData.vlen = (valueLength == descriptor->valueLength()) ? 0 : 1; if (this->_bondStore) { BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&descriptorMetaData.read_perm); } else { BLE_GAP_CONN_SEC_MODE_SET_OPEN(&descriptorMetaData.read_perm); } descriptorAttribute.p_uuid = &nordicUUID; descriptorAttribute.p_attr_md = &descriptorMetaData; descriptorAttribute.init_len = valueLength; descriptorAttribute.max_len = descriptor->valueLength(); descriptorAttribute.p_value = NULL; sd_ble_gatts_descriptor_add(BLE_GATT_HANDLE_INVALID, &descriptorAttribute, &handle); if (valueLength) { for (int j = 0; j < valueLength; j++) { value[j] = (*descriptor)[j]; } sd_ble_gatts_value_set(handle, 0, &valueLength, value); } } } if ( numRemoteAttributes > 0) { numRemoteAttributes -= 2; // 0x1801, 0x2a05 } for (int i = 0; i < numRemoteAttributes; i++) { BLERemoteAttribute *remoteAttribute = remoteAttributes[i]; if (remoteAttribute->type() == BLETypeService) { this->_numRemoteServices++; } else if (remoteAttribute->type() == BLETypeCharacteristic) { this->_numRemoteCharacteristics++; } } this->_remoteServiceInfo = (struct remoteServiceInfo*)malloc(sizeof(struct remoteServiceInfo) * this->_numRemoteServices); this->_remoteCharacteristicInfo = (struct remoteCharacteristicInfo*)malloc(sizeof(struct remoteCharacteristicInfo) * this->_numRemoteCharacteristics); BLERemoteService *lastRemoteService = NULL; unsigned char remoteServiceIndex = 0; unsigned char remoteCharacteristicIndex = 0; for (int i = 0; i < numRemoteAttributes; i++) { BLERemoteAttribute *remoteAttribute = remoteAttributes[i]; BLEUuid uuid = BLEUuid(remoteAttribute->uuid()); const unsigned char* uuidData = uuid.data(); ble_uuid_t nordicUUID; if (uuid.length() == 2) { nordicUUID.uuid = (uuidData[1] << 8) | uuidData[0]; nordicUUID.type = BLE_UUID_TYPE_BLE; } else { unsigned char uuidDataTemp[16]; memcpy(&uuidDataTemp, uuidData, sizeof(uuidDataTemp)); nordicUUID.uuid = (uuidData[13] << 8) | uuidData[12]; uuidDataTemp[13] = 0; uuidDataTemp[12] = 0; sd_ble_uuid_vs_add((ble_uuid128_t*)&uuidDataTemp, &nordicUUID.type); } if (remoteAttribute->type() == BLETypeService) { this->_remoteServiceInfo[remoteServiceIndex].service = lastRemoteService = (BLERemoteService *)remoteAttribute; this->_remoteServiceInfo[remoteServiceIndex].uuid = nordicUUID; memset(&this->_remoteServiceInfo[remoteServiceIndex].handlesRange, 0, sizeof(this->_remoteServiceInfo[remoteServiceIndex].handlesRange)); remoteServiceIndex++; } else if (remoteAttribute->type() == BLETypeCharacteristic) { this->_remoteCharacteristicInfo[remoteCharacteristicIndex].characteristic = (BLERemoteCharacteristic *)remoteAttribute; this->_remoteCharacteristicInfo[remoteCharacteristicIndex].service = lastRemoteService; this->_remoteCharacteristicInfo[remoteCharacteristicIndex].uuid = nordicUUID; memset(&this->_remoteCharacteristicInfo[remoteCharacteristicIndex].properties, 0, sizeof(this->_remoteCharacteristicInfo[remoteCharacteristicIndex].properties)); this->_remoteCharacteristicInfo[remoteCharacteristicIndex].valueHandle = 0; remoteCharacteristicIndex++; } } if (this->_bondStore && this->_bondStore->hasData()) { #ifdef NRF_51822_DEBUG Serial.println(F("Restoring bond data")); #endif #ifdef NRF51_S130 this->_bondStore->getData(this->_bondData, 0, sizeof(this->_bondData)); #else this->_bondStore->getData(this->_authStatusBuffer, 0, sizeof(this->_authStatusBuffer)); #endif } this->startAdvertising(); #ifdef __RFduino__ RFduinoBLE_enabled = 1; #endif }
uint32_t eddystone_set_adv_data(uint32_t frame_index) { uint8_t *p_encoded_advdata = edstn_frames[frame_index].adv_frame; return sd_ble_gap_adv_data_set(p_encoded_advdata, edstn_frames[frame_index].adv_len, NULL, 0); }
void AdvertisingModule::NodeStateChangedHandler(discoveryState newState) { if(newState == discoveryState::BACK_OFF || newState == discoveryState::DISCOVERY_OFF){ //Activate our advertising //This is a small packet for debugging a node's state if(Config->advertiseDebugPackets){ u8 buffer[31]; memset(buffer, 0, 31); advStructureFlags* flags = (advStructureFlags*)buffer; flags->len = SIZEOF_ADV_STRUCTURE_FLAGS-1; flags->type = BLE_GAP_AD_TYPE_FLAGS; flags->flags = BLE_GAP_ADV_FLAG_LE_GENERAL_DISC_MODE | BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED; advStructureManufacturer* manufacturer = (advStructureManufacturer*)(buffer+3); manufacturer->len = 26; manufacturer->type = BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA; manufacturer->companyIdentifier = 0x24D; AdvertisingModuleDebugMessage* msg = (AdvertisingModuleDebugMessage*)(buffer+7); msg->debugPacketIdentifier = 0xDE; msg->senderId = node->persistentConfig.nodeId; msg->connLossCounter = node->persistentConfig.connectionLossCounter; for(int i=0; i<Config->meshMaxConnections; i++){ if(cm->connections[i]->handshakeDone()){ msg->partners[i] = cm->connections[i]->partnerId; msg->rssiVals[i] = cm->connections[i]->rssiAverage; msg->droppedVals[i] = cm->connections[i]->droppedPackets; } else { msg->partners[i] = 0; msg->rssiVals[i] = 0; msg->droppedVals[i] = 0; } } char strbuffer[200]; Logger::getInstance().convertBufferToHexString(buffer, 31, strbuffer, 200); logt("ADVMOD", "ADV set to %s", strbuffer); u32 err = sd_ble_gap_adv_data_set(buffer, 31, NULL, 0); if(err != NRF_SUCCESS){ logt("ADVMOD", "Debug Packet corrupt"); } AdvertisingController::SetAdvertisingState(advState::ADV_STATE_HIGH); } else if(configuration.messageCount > 0){ u32 err = sd_ble_gap_adv_data_set(configuration.messageData[0].messageData, configuration.messageData[0].messageLength, NULL, 0); if(err != NRF_SUCCESS){ logt("ADVMOD", "Adv msg corrupt"); } char buffer[200]; Logger::getInstance().convertBufferToHexString((u8*)configuration.messageData[0].messageData, 31, buffer, 200); logt("ADVMOD", "ADV set to %s", buffer); if(configuration.messageData[0].forceNonConnectable) { AdvertisingController::SetNonConnectable(); } //Now, start advertising //TODO: Use advertising parameters from config to advertise AdvertisingController::SetAdvertisingState(advState::ADV_STATE_HIGH); } } else if (newState == discoveryState::DISCOVERY) { //Do not trigger custom advertisings anymore, reset to node's advertising node->UpdateJoinMePacket(); } }
void simble_adv_start(void) { struct ble_gap_advdata advdata = { .length = 0 }; struct ble_gap_ad_flags flags = { .payload_length = 1, .type = BLE_GAP_AD_TYPE_FLAGS, .flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE, }; simble_add_advdata(&flags, &advdata); struct ble_gap_ad_name name; uint16_t namelen = sizeof(advdata); if (sd_ble_gap_device_name_get(name.name, &namelen) != NRF_SUCCESS) namelen = 0; name.type = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME; name.payload_length = namelen; simble_add_advdata(&name, &advdata); sd_ble_gap_adv_data_set(advdata.data, advdata.length, NULL, 0); ble_gap_adv_params_t adv_params = { .type = BLE_GAP_ADV_TYPE_ADV_IND, .fp = BLE_GAP_ADV_FP_ANY, .interval = 0x400, }; sd_ble_gap_adv_start(&adv_params); onboard_led(ONBOARD_LED_ON); } static void simble_srv_tx_init(void) { uint16_t srv_handle; ble_uuid_t srv_uuid = {.type = BLE_UUID_TYPE_BLE, .uuid = 0x1804}; sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &srv_uuid, &srv_handle); ble_gatts_char_handles_t chr_handles; ble_gatts_char_md_t char_meta = {.char_props = {.read = 1}}; ble_uuid_t chr_uuid = {.type = BLE_UUID_TYPE_BLE, .uuid = 0x2a07}; ble_gatts_attr_md_t chr_attr_meta = { .vloc = BLE_GATTS_VLOC_STACK, }; BLE_GAP_CONN_SEC_MODE_SET_OPEN(&chr_attr_meta.read_perm); BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&chr_attr_meta.write_perm); uint8_t tx_val = 0; ble_gatts_attr_t chr_attr = { .p_uuid = &chr_uuid, .p_attr_md = &chr_attr_meta, .init_offs = 0, .init_len = sizeof(tx_val), .max_len = sizeof(tx_val), .p_value = &tx_val, }; sd_ble_gatts_characteristic_add(srv_handle, &char_meta, &chr_attr, &chr_handles); } /* DM requires a `app_error_handler` */ void __attribute__((weak)) app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name) { app_trace_log("[simble]: err: %d, line: %d, file: %s\r\n", error_code, line_num, p_file_name); for (;;) { /* NOTHING */ } } void simble_init(const char *name) { app_trace_init(); sd_softdevice_enable(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, NULL); /* XXX assertion handler */ ble_enable_params_t ble_params = { #if defined(SD120) .gap_enable_params = { .role = BLE_GAP_ROLE_PERIPH, }, #endif .gatts_enable_params = { .service_changed = 1, }, }; sd_ble_enable(&ble_params); ble_gap_conn_sec_mode_t mode; BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&mode); sd_ble_gap_device_name_set(&mode, (const uint8_t *)name, strlen(name)); // flash storage pstorage_init(); simble_srv_tx_init(); } uint8_t simble_get_vendor_uuid_class(void) { ble_uuid128_t vendorid = {{0x13,0xb0,0xa0,0x71,0xfe,0x62,0x4c,0x01,0xaa,0x4d,0xd8,0x03,0,0,0x0b,0xd0}}; static uint8_t vendor_type = BLE_UUID_TYPE_UNKNOWN; if (vendor_type != BLE_UUID_TYPE_UNKNOWN) return (vendor_type); sd_ble_uuid_vs_add(&vendorid, &vendor_type); return (vendor_type); } void simble_srv_register(struct service_desc *s) { s->next = services; services = s; sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &s->uuid, &s->handle); for (int i = 0; i < s->char_count; ++i) { struct char_desc *c = &s->chars[i]; ble_gatts_attr_md_t cccd_md; memset(&cccd_md, 0, sizeof(cccd_md)); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm); cccd_md.vloc = BLE_GATTS_VLOC_STACK; int have_write = c->write_cb != NULL; ble_gatts_char_md_t char_meta = { .char_props = { .broadcast = 0, .read = 1, .write_wo_resp = have_write, .write = have_write, .notify = c->notify, .indicate = c->indicate, .auth_signed_wr = have_write, }, .p_char_user_desc = (uint8_t *)c->desc, .char_user_desc_size = strlen(c->desc), .char_user_desc_max_size = strlen(c->desc), .p_char_pf = c->format.format != 0 ? &c->format : NULL, .p_cccd_md = (c->notify || c->indicate) ? &cccd_md : NULL, }; ble_gatts_attr_md_t chr_attr_meta = { .vlen = 1, .vloc = BLE_GATTS_VLOC_STACK, .rd_auth = 1, .wr_auth = 1, }; BLE_GAP_CONN_SEC_MODE_SET_OPEN(&chr_attr_meta.read_perm); if (have_write) BLE_GAP_CONN_SEC_MODE_SET_OPEN(&chr_attr_meta.write_perm); else BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&chr_attr_meta.write_perm); ble_gatts_attr_t chr_attr = { .p_uuid = &c->uuid, .p_attr_md = &chr_attr_meta, .init_offs = 0, .init_len = 0, .max_len = c->length, }; sd_ble_gatts_characteristic_add(s->handle, &char_meta, &chr_attr, &c->handles); } } void simble_srv_init(struct service_desc *s, uint8_t type, uint16_t id) { *s = (struct service_desc){ .uuid = {.type = type, .uuid = id}, .char_count = 0, }; }; void simble_srv_char_add(struct service_desc *s, struct char_desc *c, uint8_t type, uint16_t id, const char *desc, uint16_t length) { *c = (struct char_desc){ .uuid = { .type = type, .uuid = id }, .desc = desc, .length = length, };