/**@brief Function for initializing the Advertising functionality. * * @details Encodes the required advertising data and passes it to the stack. * Also builds a structure to be passed to the stack when starting advertising. */ static void advertising_init(void) { uint32_t err_code; ble_advdata_t advdata; uint8_t flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED; ble_advdata_manuf_data_t manuf_specific_data; manuf_specific_data.company_identifier = APP_COMPANY_IDENTIFIER; #if defined(USE_UICR_FOR_MAJ_MIN_VALUES) // If USE_UICR_FOR_MAJ_MIN_VALUES is defined, the major and minor values will be read from the // UICR instead of using the default values. The major and minor values obtained from the UICR // are encoded into advertising data in big endian order (MSB First). // To set the UICR used by this example to a desired value, write to the address 0x10001080 // using the nrfjprog tool. The command to be used is as follows. // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val <your major/minor value> // For example, for a major value and minor value of 0xabcd and 0x0102 respectively, the // the following command should be used. // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val 0xabcd0102 uint16_t major_value = ((*(uint32_t *)UICR_ADDRESS) & 0xFFFF0000) >> 16; uint16_t minor_value = ((*(uint32_t *)UICR_ADDRESS) & 0x0000FFFF); uint8_t index = MAJ_VAL_OFFSET_IN_BEACON_INFO; m_beacon_info[index++] = MSB_16(major_value); m_beacon_info[index++] = LSB_16(major_value); m_beacon_info[index++] = MSB_16(minor_value); m_beacon_info[index++] = LSB_16(minor_value); #endif manuf_specific_data.data.p_data = (uint8_t *) m_beacon_info; manuf_specific_data.data.size = APP_BEACON_INFO_LENGTH; // Build and set advertising data. memset(&advdata, 0, sizeof(advdata)); advdata.name_type = BLE_ADVDATA_NO_NAME; advdata.flags = flags; advdata.p_manuf_specific_data = &manuf_specific_data; err_code = ble_advdata_set(&advdata, NULL); APP_ERROR_CHECK(err_code); // Initialize advertising parameters (used when starting advertising). memset(&m_adv_params, 0, sizeof(m_adv_params)); m_adv_params.type = BLE_GAP_ADV_TYPE_ADV_NONCONN_IND; m_adv_params.p_peer_addr = NULL; // Undirected advertisement. m_adv_params.fp = BLE_GAP_ADV_FP_ANY; m_adv_params.interval = NON_CONNECTABLE_ADV_INTERVAL; m_adv_params.timeout = APP_CFG_NON_CONN_ADV_TIMEOUT; }
uint32_t pack_uint16(uint16_t val, uint32_t buffer_len, uint8_t * const buffer, uint32_t * const p_offset) { uint32_t err_code = NRF_ERROR_DATA_SIZE; if (buffer_len > (*p_offset)) { const uint32_t available_len = buffer_len - (*p_offset); MQTT_TRC("[MQTT]: << pack_uint16 V:%04x BL:%08x, B:%p, O:%08x A:%08x\r\n", val, buffer_len, buffer, (*p_offset), available_len); if (available_len >= SIZE_OF_UINT16) { // Pack value. buffer[(*p_offset)] = MSB_16(val); buffer[(*p_offset)+1] = LSB_16(val); // Increment offset. (*p_offset) += SIZE_OF_UINT16; // Indicate success. err_code = NRF_SUCCESS; } } return err_code; }
/** * @brief @ref app_usbd_class_methods_t::feed_descriptors */ static bool nrf_dfu_trigger_feed_descriptors(app_usbd_class_descriptor_ctx_t * p_ctx, app_usbd_class_inst_t const * p_inst, uint8_t * p_buff, size_t max_size) { static app_usbd_class_iface_conf_t const * p_cur_iface = NULL; p_cur_iface = app_usbd_class_iface_get(p_inst, 0); app_usbd_nrf_dfu_trigger_t const * p_dfu = nrf_dfu_trigger_get(p_inst); APP_USBD_CLASS_DESCRIPTOR_BEGIN(p_ctx, p_buff, max_size) /* INTERFACE DESCRIPTOR */ APP_USBD_CLASS_DESCRIPTOR_WRITE(sizeof(app_usbd_descriptor_iface_t)); // bLength APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_INTERFACE); // bDescriptorType APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_iface_number_get(p_cur_iface)); // bInterfaceNumber APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bAlternateSetting APP_USBD_CLASS_DESCRIPTOR_WRITE(0); // bNumEndpoints APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_NRF_DFU_TRIGGER_CLASS); // bInterfaceClass APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_NRF_DFU_TRIGGER_SUBCLASS); // bInterfaceSubClass APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_NRF_DFU_TRIGGER_PROTOCOL_RUNTIME); // bInterfaceProtocol APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // iInterface /* FUNCTIONAL DESCRIPTOR */ APP_USBD_CLASS_DESCRIPTOR_WRITE(sizeof(app_usbd_nrf_dfu_trigger_desc_func_t)); // bFunctionLength APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_NRF_DFU_TRIGGER_CS_FUNCTIONAL); // bDescriptorType APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_NRF_DFU_TRIGGER_BIT_CAN_DNLOAD | APP_USBD_NRF_DFU_TRIGGER_BIT_WILL_DETACH); // bmAttribute APP_USBD_CLASS_DESCRIPTOR_WRITE(LSB_16(p_dfu->specific.inst.detach_timeout)); // wDetachTimeOut LSB APP_USBD_CLASS_DESCRIPTOR_WRITE(MSB_16(p_dfu->specific.inst.detach_timeout)); // wDetachTimeOut MSB APP_USBD_CLASS_DESCRIPTOR_WRITE(LSB_16(p_dfu->specific.inst.transfer_size)); // wTransferSize LSB APP_USBD_CLASS_DESCRIPTOR_WRITE(MSB_16(p_dfu->specific.inst.transfer_size)); // wTransferSize MSB APP_USBD_CLASS_DESCRIPTOR_WRITE(LSB_16(p_dfu->specific.inst.bcd_dfu)); // bcdDFUVersion LSB APP_USBD_CLASS_DESCRIPTOR_WRITE(MSB_16(p_dfu->specific.inst.bcd_dfu)); // bcdDFUVersion MSB APP_USBD_CLASS_DESCRIPTOR_END(); }
/**@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 creating a TX message for writing a CCCD. */ static uint32_t cccd_configure(uint16_t conn_handle, uint16_t handle_cccd, bool enable) { tx_message_t * p_msg; uint16_t cccd_val = enable ? BLE_GATT_HVX_NOTIFICATION : 0; p_msg = &m_tx_buffer[m_tx_insert_index++]; m_tx_insert_index &= TX_BUFFER_MASK; p_msg->req.write_req.gattc_params.handle = handle_cccd; p_msg->req.write_req.gattc_params.len = WRITE_MESSAGE_LENGTH; p_msg->req.write_req.gattc_params.p_value = p_msg->req.write_req.gattc_value; p_msg->req.write_req.gattc_params.offset = 0; p_msg->req.write_req.gattc_params.write_op = BLE_GATT_OP_WRITE_REQ; p_msg->req.write_req.gattc_value[0] = LSB_16(cccd_val); p_msg->req.write_req.gattc_value[1] = MSB_16(cccd_val); p_msg->conn_handle = conn_handle; p_msg->type = WRITE_REQ; tx_buffer_process(); return NRF_SUCCESS; }
static bool audio_feed_descriptors(app_usbd_class_descriptor_ctx_t * p_ctx, app_usbd_class_inst_t const * p_inst, uint8_t * p_buff, size_t max_size) { static uint8_t ifaces = 0; ifaces = app_usbd_class_iface_count_get(p_inst); ASSERT(ifaces == 2); app_usbd_audio_t const * p_audio = audio_get(p_inst); APP_USBD_CLASS_DESCRIPTOR_BEGIN(p_ctx, p_buff, max_size); /* CONTROL INTERFACE DESCRIPTOR */ APP_USBD_CLASS_DESCRIPTOR_WRITE(0x09); // bLength APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_INTERFACE); // bDescriptorType = Interface static app_usbd_class_iface_conf_t const * p_cur_iface = NULL; p_cur_iface = app_usbd_class_iface_get(p_inst, 0); APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_iface_number_get(p_cur_iface)); // bInterfaceNumber APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bAlternateSetting APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_iface_ep_count_get(p_cur_iface)); // bNumEndpoints APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_AUDIO_CLASS); // bInterfaceClass = Audio APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_AUDIO_SUBCLASS_AUDIOCONTROL); // bInterfaceSubclass (Audio Control) APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_AUDIO_CLASS_PROTOCOL_UNDEFINED); // bInterfaceProtocol APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // iInterface /* HEADER INTERFACE */ APP_USBD_CLASS_DESCRIPTOR_WRITE(0x09); // bLength APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_AUDIO_DESCRIPTOR_INTERFACE); // bDescriptorType = Audio Interfaces APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_AUDIO_AC_IFACE_SUBTYPE_HEADER); // bDescriptorSubtype = Header APP_USBD_CLASS_DESCRIPTOR_WRITE(LSB_16(0x0100)); // bcdADC LSB APP_USBD_CLASS_DESCRIPTOR_WRITE(MSB_16(0x0100)); // bcdADC MSB static uint16_t header_desc_len = 0; header_desc_len = 9 + audio_get_feature_descriptor_size(p_inst) + audio_get_input_descriptor_size(p_inst) + audio_get_output_descriptor_size( p_inst); APP_USBD_CLASS_DESCRIPTOR_WRITE(LSB_16(header_desc_len)); // wTotalLength LSB APP_USBD_CLASS_DESCRIPTOR_WRITE(MSB_16(header_desc_len)); // wTotalLength MSB APP_USBD_CLASS_DESCRIPTOR_WRITE(0x01); // bInCollection APP_USBD_CLASS_DESCRIPTOR_WRITE(audio_get_control_interface_number(p_inst) + 1); // baInterfaceNr(1) /* INPUT TERMINAL DESCRIPTOR */ static uint32_t cur_byte = 0; static size_t input_desc_size = 0; input_desc_size = audio_get_input_descriptor_size(p_inst); for (cur_byte = 0; cur_byte < input_desc_size; cur_byte++) { APP_USBD_CLASS_DESCRIPTOR_WRITE(audio_get_input_descriptor_data(p_inst, cur_byte)); } /* FEATURE UNIT DESCRIPTOR */ static size_t feature_desc_size = 0; feature_desc_size = audio_get_feature_descriptor_size(p_inst); for (cur_byte = 0; cur_byte < feature_desc_size; cur_byte++) { APP_USBD_CLASS_DESCRIPTOR_WRITE(audio_get_feature_descriptor_data(p_inst, cur_byte)); } /* OUTPUT TERMINAL DESCRIPTOR */ static size_t output_desc_size = 0; output_desc_size = audio_get_output_descriptor_size(p_inst); for (cur_byte = 0; cur_byte < output_desc_size; cur_byte++) { APP_USBD_CLASS_DESCRIPTOR_WRITE(audio_get_output_descriptor_data(p_inst, cur_byte)); } p_cur_iface++; /* STREAM INTERFACE DESCRIPTOR ALT 0 */ APP_USBD_CLASS_DESCRIPTOR_WRITE(0x09); // bLength APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_INTERFACE); // bDescriptorType = Interface APP_USBD_CLASS_DESCRIPTOR_WRITE(audio_get_control_interface_number(p_inst) + 1); // bInterfaceNumber APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bAlternateSetting APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bNumEndpoints APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_AUDIO_CLASS); // bInterfaceClass = Audio APP_USBD_CLASS_DESCRIPTOR_WRITE(p_audio->specific.inst.type_streaming); // bInterfaceSubclass (Audio Control) APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_AUDIO_CLASS_PROTOCOL_UNDEFINED); // bInterfaceProtocol APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // iInterface /* STREAM INTERFACE DESCRIPTOR ALT 1 */ APP_USBD_CLASS_DESCRIPTOR_WRITE(0x09); // bLength APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_INTERFACE); // bDescriptorType = Interface APP_USBD_CLASS_DESCRIPTOR_WRITE(audio_get_control_interface_number(p_inst) + 1); // bInterfaceNumber APP_USBD_CLASS_DESCRIPTOR_WRITE(0x01); // bAlternateSetting APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_iface_ep_count_get(p_cur_iface)); // bNumEndpoints APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_AUDIO_CLASS); // bInterfaceClass = Audio APP_USBD_CLASS_DESCRIPTOR_WRITE(p_audio->specific.inst.type_streaming); // bInterfaceSubclass (Audio Control) APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_AUDIO_CLASS_PROTOCOL_UNDEFINED); // bInterfaceProtocol APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // iInterface /* AudioStreaming GENERAL DESCRIPTOR */ APP_USBD_CLASS_DESCRIPTOR_WRITE(0x07); // bLength APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_AUDIO_DESCRIPTOR_INTERFACE); // bDescriptorType = Audio Interface APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_AUDIO_AS_IFACE_SUBTYPE_GENERAL); // bDescriptorSubtype = General APP_USBD_CLASS_DESCRIPTOR_WRITE(audio_get_control_interface_number(p_inst) + 1); // bTerminalLink APP_USBD_CLASS_DESCRIPTOR_WRITE(p_audio->specific.inst.delay); // bDelay APP_USBD_CLASS_DESCRIPTOR_WRITE(LSB_16(p_audio->specific.inst.format)); // wFormatTag LSB APP_USBD_CLASS_DESCRIPTOR_WRITE(MSB_16(p_audio->specific.inst.format)); // wFormatTag MSB /* FORMAT DESCRIPTOR */ static size_t format_desc_size = 0; format_desc_size = audio_get_format_descriptor_size(p_inst); for (cur_byte = 0; cur_byte < format_desc_size; cur_byte++) { APP_USBD_CLASS_DESCRIPTOR_WRITE(audio_get_format_descriptor_data(p_inst, cur_byte)); } /* ENDPOINT GENERAL DESCRIPTOR */ APP_USBD_CLASS_DESCRIPTOR_WRITE(0x07); // bLength APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_AUDIO_DESCRIPTOR_ENDPOINT); // bDescriptorType = Audio Descriptor APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_AUDIO_EP_SUBTYPE_GENERAL); // bDescriptorSubtype = EP General APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bmAttributes APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bLockDelayUnits APP_USBD_CLASS_DESCRIPTOR_WRITE(LSB_16(0x0000)); // wLockDelay LSB APP_USBD_CLASS_DESCRIPTOR_WRITE(MSB_16(0x0000)); // wLockDelay MSB /* ENDPOINT ISO DESCRIPTOR */ APP_USBD_CLASS_DESCRIPTOR_WRITE(0x09); // bLength APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_ENDPOINT); // bDescriptorType = Endpoint static app_usbd_class_ep_conf_t const * p_cur_ep = NULL; p_cur_ep = app_usbd_class_iface_ep_get(p_cur_iface, 0); APP_USBD_CLASS_DESCRIPTOR_WRITE(app_usbd_class_ep_address_get(p_cur_ep)); // bEndpointAddress APP_USBD_CLASS_DESCRIPTOR_WRITE(APP_USBD_DESCRIPTOR_EP_ATTR_TYPE_ISOCHRONOUS); // bmAttributes APP_USBD_CLASS_DESCRIPTOR_WRITE(LSB_16(p_audio->specific.inst.ep_size)); // wMaxPacketSize LSB APP_USBD_CLASS_DESCRIPTOR_WRITE(MSB_16(p_audio->specific.inst.ep_size)); // wMaxPacketSize MSB APP_USBD_CLASS_DESCRIPTOR_WRITE(0x01); // bInterval APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bRefresh APP_USBD_CLASS_DESCRIPTOR_WRITE(0x00); // bSynchAddress APP_USBD_CLASS_DESCRIPTOR_END(); }