Esempio n. 1
0
/**@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;
}
Esempio n. 2
0
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();
}
Esempio n. 4
0
/**@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);
}
Esempio n. 5
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;
}
Esempio n. 6
0
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();
}