//============================================================================//
// This is where we initialize our services and register them with the stack.
//
// The services that we create are:
//
// 1) Custom Service
// 2) Battery Service
// 3) Device Information Service
// 4) DFU Service (if enabled via macro)
static void services_init(void)
{
    uint32_t       err_code;
    ble_bas_init_t bas_init;
    ble_dis_init_t dis_init;

	//--------------------------------------------------------------------------
    // Set up the Custom Service
    err_code = CS_Init(&_cs);
    APP_ERROR_CHECK(err_code);
	//--------------------------------------------------------------------------
    // Initialize Battery Service.
    memset(&bas_init, 0, sizeof(bas_init));
	//--------------------------------------------------------------------------
    // Here the sec level for the Battery Service can be changed/increased.
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.cccd_write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&bas_init.battery_level_char_attr_md.write_perm);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_report_read_perm);

    bas_init.evt_handler          = NULL;
    bas_init.support_notification = true;
    bas_init.p_report_ref         = NULL;
    bas_init.initial_batt_level   = 100;

    err_code = ble_bas_init(&_bas, &bas_init);
    APP_ERROR_CHECK(err_code);
	//--------------------------------------------------------------------------
    // Initialize Device Information Service.
    memset(&dis_init, 0, sizeof(dis_init));

    ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, (char *)MANUFACTURER_NAME);
	ble_srv_ascii_to_utf8(&dis_init.model_num_str, (char *)MODEL_NUMBER);
	ble_srv_ascii_to_utf8(&dis_init.serial_num_str, (char *)SERIAL_NUMBER);
	ble_srv_ascii_to_utf8(&dis_init.hw_rev_str, (char *)HARDWARE_REVISION);
	ble_srv_ascii_to_utf8(&dis_init.fw_rev_str, (char *)FIRMWARE_REVISION);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&dis_init.dis_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&dis_init.dis_attr_md.write_perm);

    err_code = ble_dis_init(&dis_init);
    APP_ERROR_CHECK(err_code);

#ifdef BLE_DFU_APP_SUPPORT
    /** @snippet [DFU BLE Service initialization] */
    ble_dfu_init_t dfus_init;

    // Initialize the Device Firmware Update Service.
    memset(&dfus_init, 0, sizeof(dfus_init));

    dfus_init.evt_handler   = dfu_app_on_dfu_evt;
    dfus_init.error_handler = NULL;
    dfus_init.evt_handler   = dfu_app_on_dfu_evt;
    dfus_init.revision      = DFU_REVISION;

    err_code = ble_dfu_init(&_dfus, &dfus_init);
    APP_ERROR_CHECK(err_code);

    dfu_app_reset_prepare_set(reset_prepare);
    dfu_app_dm_appl_instance_set(_app_handle);
    /** @snippet [DFU BLE Service initialization] */
#endif // BLE_DFU_APP_SUPPORT
}
/**@brief Function for initializing services that will be used by the application.
 *
 * @details Initialize the Heart Rate, Battery and Device Information services.
 */
static void services_init(void)
{
    uint32_t       err_code;
    ble_hrs_init_t hrs_init;
    ble_bas_init_t bas_init;
    ble_dis_init_t dis_init;
    uint8_t        body_sensor_location;

    // Initialize Heart Rate Service.
    body_sensor_location = BLE_HRS_BODY_SENSOR_LOCATION_FINGER;

    memset(&hrs_init, 0, sizeof(hrs_init));

    hrs_init.evt_handler                 = NULL;
    hrs_init.is_sensor_contact_supported = true;
    hrs_init.p_body_sensor_location      = &body_sensor_location;

    // Here the sec level for the Heart Rate Service can be changed/increased.
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&hrs_init.hrs_hrm_attr_md.cccd_write_perm);
		//***************MODIFIED
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&hrs_init.hrs_hrm_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&hrs_init.hrs_hrm_attr_md.write_perm);
		//*********************
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&hrs_init.hrs_bsl_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hrs_init.hrs_bsl_attr_md.write_perm);

    err_code = ble_hrs_init(&m_hrs, &hrs_init);
    APP_ERROR_CHECK(err_code);

    // Initialize Battery Service.
    memset(&bas_init, 0, sizeof(bas_init));

    // Here the sec level for the Battery Service can be changed/increased.
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.cccd_write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&bas_init.battery_level_char_attr_md.write_perm);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_report_read_perm);

    bas_init.evt_handler          = NULL;
    bas_init.support_notification = true;
    bas_init.p_report_ref         = NULL;
    bas_init.initial_batt_level   = 100;

    err_code = ble_bas_init(&m_bas, &bas_init);
    APP_ERROR_CHECK(err_code);

    // Initialize Device Information Service.
    memset(&dis_init, 0, sizeof(dis_init));

    ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, (char *)MANUFACTURER_NAME);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&dis_init.dis_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&dis_init.dis_attr_md.write_perm);

    err_code = ble_dis_init(&dis_init);
    APP_ERROR_CHECK(err_code);
    
#ifdef BLE_DFU_APP_SUPPORT    
    /** @snippet [DFU BLE Service initialization] */
    ble_dfu_init_t   dfus_init;

    // Initialize the Device Firmware Update Service.
    memset(&dfus_init, 0, sizeof(dfus_init));

    dfus_init.evt_handler    = dfu_app_on_dfu_evt;
    dfus_init.error_handler  = NULL; //service_error_handler - Not used as only the switch from app to DFU mode is required and not full dfu service.

    err_code = ble_dfu_init(&m_dfus, &dfus_init);
    APP_ERROR_CHECK(err_code);
    
    dfu_app_reset_prepare_set(reset_prepare);
    /** @snippet [DFU BLE Service initialization] */
#endif // BLE_DFU_APP_SUPPORT    
}
Пример #3
0
/*
 *  Function for adding the Temperature characteristic.
 */
static uint32_t temperature_char_add(ble_temp_t * p_temp)
{
    ble_gatts_char_md_t  char_md;
    ble_gatts_attr_md_t  cccd_md;
    ble_gatts_attr_t     attr_char_value;
    ble_uuid_t           ble_uuid;
    ble_gatts_attr_md_t  attr_md;
    ble_gatts_char_pf_t  char_pf;
    ble_gatts_attr_md_t  desc_md;

    static const uint8_t user_desc[] = "Temperature";

    // Setup CCCD attribute
    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;

    memset(&char_pf, 0, sizeof(char_pf));
    char_pf.format = BLE_GATT_CPF_FORMAT_UTF8S;

    // Setup User Description attribute
    memset(&desc_md, 0, sizeof(desc_md));
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.read_perm);
    desc_md.vloc = BLE_GATTS_VLOC_STACK;

    // Temp Service Characterstic
    memset(&char_md, 0, sizeof(char_md));
    char_md.char_props.read         = 1;
    char_md.char_props.notify       = 1;
    char_md.p_char_user_desc        = (uint8_t*) &user_desc;
    char_md.char_user_desc_size     = sizeof(user_desc);
    char_md.char_user_desc_max_size = sizeof(user_desc);
    char_md.p_char_pf               = &char_pf;
    char_md.p_user_desc_md          = &desc_md;
    char_md.p_cccd_md               = &cccd_md;
    char_md.p_sccd_md               = NULL;

    ble_uuid.type = p_temp->uuid_type;
    ble_uuid.uuid = TEMP_UUID_TEMPERATURE_CHAR;

    memset(&attr_md, 0, sizeof(attr_md));
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.write_perm);
    attr_md.vloc       = BLE_GATTS_VLOC_STACK;
    attr_md.rd_auth    = 0;
    attr_md.wr_auth    = 0;
    attr_md.vlen       = 0;

    memset(&attr_char_value, 0, sizeof(attr_char_value));
    attr_char_value.p_uuid       = &ble_uuid;
    attr_char_value.p_attr_md    = &attr_md;
    attr_char_value.init_len     = sizeof(uint16_t);
    attr_char_value.init_offs    = 0;
    attr_char_value.max_len      = sizeof(uint16_t);
    attr_char_value.p_value      = NULL;

    return sd_ble_gatts_characteristic_add(p_temp->service_handle, 
                                           &char_md,
                                           &attr_char_value,
                                           &p_temp->temperature_char_handles);
}
Пример #4
0
uint32_t ble_sc_ctrlpt_init(ble_sc_ctrlpt_t            * p_sc_ctrlpt,
                            const ble_cs_ctrlpt_init_t * p_sc_ctrlpt_init)
{
    ble_gatts_char_md_t char_md;
    ble_gatts_attr_md_t cccd_md;
    ble_gatts_attr_t    attr_char_value;
    ble_uuid_t          ble_uuid;
    ble_gatts_attr_md_t attr_md;

    p_sc_ctrlpt->conn_handle      = BLE_CONN_HANDLE_INVALID;
    p_sc_ctrlpt->procedure_status = BLE_SCPT_NO_PROC_IN_PROGRESS;

    p_sc_ctrlpt->size_list_supported_locations = p_sc_ctrlpt_init->size_list_supported_locations;

    if ((p_sc_ctrlpt_init->size_list_supported_locations != 0) &&
        (p_sc_ctrlpt_init->list_supported_locations != NULL))
    {
        memcpy(p_sc_ctrlpt->list_supported_locations,
               p_sc_ctrlpt_init->list_supported_locations,
               p_sc_ctrlpt->size_list_supported_locations * sizeof(ble_sensor_location_t));
    }

    p_sc_ctrlpt->service_handle         = p_sc_ctrlpt_init->service_handle;
    p_sc_ctrlpt->evt_handler            = p_sc_ctrlpt_init->evt_handler;
    p_sc_ctrlpt->supported_functions    = p_sc_ctrlpt_init->supported_functions;
    p_sc_ctrlpt->sensor_location_handle = p_sc_ctrlpt_init->sensor_location_handle;
    p_sc_ctrlpt->error_handler          = p_sc_ctrlpt_init->error_handler;

    memset(&cccd_md, 0, sizeof(cccd_md));

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
    cccd_md.write_perm = p_sc_ctrlpt_init->sc_ctrlpt_attr_md.cccd_write_perm;
    cccd_md.vloc       = BLE_GATTS_VLOC_STACK;

    memset(&char_md, 0, sizeof(char_md));

    char_md.char_props.indicate = 1;
    char_md.char_props.write    = 1;
    char_md.p_char_user_desc    = NULL;
    char_md.p_char_pf           = NULL;
    char_md.p_user_desc_md      = NULL;
    char_md.p_cccd_md           = &cccd_md;
    char_md.p_sccd_md           = NULL;

    BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_SC_CTRLPT_CHAR);

    memset(&attr_md, 0, sizeof(attr_md));

    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.read_perm);
    attr_md.write_perm = p_sc_ctrlpt_init->sc_ctrlpt_attr_md.write_perm;
    attr_md.vloc       = BLE_GATTS_VLOC_STACK;
    attr_md.rd_auth    = 0;
    attr_md.wr_auth    = 1;
    attr_md.vlen       = 1;

    memset(&attr_char_value, 0, sizeof(attr_char_value));

    attr_char_value.p_uuid    = &ble_uuid;
    attr_char_value.p_attr_md = &attr_md;
    attr_char_value.init_len  = 0;
    attr_char_value.init_offs = 0;
    attr_char_value.max_len   = BLE_SC_CTRLPT_MAX_LEN;
    attr_char_value.p_value   = 0;

    return sd_ble_gatts_characteristic_add(p_sc_ctrlpt->service_handle,
                                           &char_md,
                                           &attr_char_value,
                                           &p_sc_ctrlpt->sc_ctrlpt_handles);
}
Пример #5
0
static uint32_t ble_stack_init(bool init_softdevice)
{
    uint32_t         err_code;
    nrf_clock_lf_cfg_t clock_lf_cfg = {
            .source        = NRF_CLOCK_LF_SRC_RC,
            .rc_ctiv       = 16, // recommended for nRF52
            .rc_temp_ctiv  = 2,  // recommended for nRF52
            .xtal_accuracy = 0};

    if (init_softdevice)
    {
        err_code = nrf_dfu_mbr_init_sd();
        VERIFY_SUCCESS(err_code);
    }

    NRF_LOG_INFO("vector table: 0x%08x\r\n", BOOTLOADER_START_ADDR);
    err_code = sd_softdevice_vector_table_base_set(BOOTLOADER_START_ADDR);
    VERIFY_SUCCESS(err_code);

    SOFTDEVICE_HANDLER_APPSH_INIT(&clock_lf_cfg, true);

    ble_enable_params_t ble_enable_params;
    // Only one connection as a central is used when performing dfu.
    err_code = softdevice_enable_get_default_config(1, 1, &ble_enable_params);
    VERIFY_SUCCESS(err_code);

#if (NRF_SD_BLE_API_VERSION == 3)
    ble_enable_params.gatt_enable_params.att_mtu = NRF_BLE_MAX_MTU_SIZE;
#endif    
    
    // Enable BLE stack.
    err_code = softdevice_enable(&ble_enable_params);
    return err_code;
}


/**@brief       Function for adding DFU Packet characteristic to the BLE Stack.
 *
 * @param[in]   p_dfu DFU Service structure.
 *
 * @return      NRF_SUCCESS on success. Otherwise an error code.
 */
static uint32_t dfu_pkt_char_add(ble_dfu_t * const p_dfu)
{
    ble_gatts_char_md_t char_md             = {{0}};
    ble_gatts_attr_t    attr_char_value     = {0};
    ble_gatts_attr_md_t attr_md             = {{0}};
    ble_uuid_t          char_uuid;

    char_md.char_props.write_wo_resp = 1;

    char_uuid.type = p_dfu->uuid_type;
    char_uuid.uuid = BLE_DFU_PKT_CHAR_UUID;

    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);

    attr_md.vloc    = BLE_GATTS_VLOC_STACK;
    attr_md.vlen    = 1;

    attr_char_value.p_uuid    = &char_uuid;
    attr_char_value.p_attr_md = &attr_md;
    attr_char_value.max_len   = MAX_DFU_PKT_LEN;
    attr_char_value.p_value   = NULL;

    return sd_ble_gatts_characteristic_add(p_dfu->service_handle,
                                           &char_md,
                                           &attr_char_value,
                                           &p_dfu->dfu_pkt_handles);
}
Пример #6
0
/**@brief Initialize services that will be used by the application.
 *
 * @details Initialize the Location and Navigation, Battery and Device Information services.
 */
static void services_init(void)
{
    uint32_t       err_code;
    ble_lns_init_t lns_init;
    ble_bas_init_t bas_init;
    ble_dis_init_t dis_init;

    memset(&lns_init, 0, sizeof(lns_init));

    lns_init.evt_handler        = on_lns_evt;
    lns_init.lncp_evt_handler   = on_ln_ctrlpt_evt;
    lns_init.error_handler      = lns_error_handler;

    lns_init.is_position_quality_present = true;
    lns_init.is_control_point_present    = true;
    lns_init.is_navigation_present       = true;

    lns_init.available_features     = BLE_LNS_FEATURE_INSTANT_SPEED_SUPPORTED                 |
                                      BLE_LNS_FEATURE_TOTAL_DISTANCE_SUPPORTED                |
                                      BLE_LNS_FEATURE_LOCATION_SUPPORTED                      |
                                      BLE_LNS_FEATURE_ELEVATION_SUPPORTED                     |
                                      BLE_LNS_FEATURE_HEADING_SUPPORTED                       |
                                      BLE_LNS_FEATURE_ROLLING_TIME_SUPPORTED                  |
                                      BLE_LNS_FEATURE_UTC_TIME_SUPPORTED                      |
                                      BLE_LNS_FEATURE_REMAINING_DISTANCE_SUPPORTED            |
                                      BLE_LNS_FEATURE_REMAINING_VERT_DISTANCE_SUPPORTED       |
                                      BLE_LNS_FEATURE_EST_TIME_OF_ARRIVAL_SUPPORTED           |
                                      BLE_LNS_FEATURE_NUM_SATS_IN_SOLUTION_SUPPORTED          |
                                      BLE_LNS_FEATURE_NUM_SATS_IN_VIEW_SUPPORTED              |
                                      BLE_LNS_FEATURE_TIME_TO_FIRST_FIX_SUPPORTED             |
                                      BLE_LNS_FEATURE_EST_HORZ_POS_ERROR_SUPPORTED            |
                                      BLE_LNS_FEATURE_EST_VERT_POS_ERROR_SUPPORTED            |
                                      BLE_LNS_FEATURE_HORZ_DILUTION_OF_PRECISION_SUPPORTED    |
                                      BLE_LNS_FEATURE_VERT_DILUTION_OF_PRECISION_SUPPORTED    |
                                      BLE_LNS_FEATURE_LOC_AND_SPEED_CONTENT_MASKING_SUPPORTED |
                                      BLE_LNS_FEATURE_FIX_RATE_SETTING_SUPPORTED              |
                                      BLE_LNS_FEATURE_ELEVATION_SETTING_SUPPORTED             |
                                      BLE_LNS_FEATURE_POSITION_STATUS_SUPPORTED;


    m_sim_location_speed   = initial_lns_location_speed;
    m_sim_position_quality = initial_lns_pos_quality;
    m_sim_navigation       = initial_lns_navigation;

    lns_init.p_location_speed   = &m_sim_location_speed;
    lns_init.p_position_quality = &m_sim_position_quality;
    lns_init.p_navigation       = &m_sim_navigation;

    lns_init.loc_nav_feature_security_req_read_perm  = SEC_OPEN;
    lns_init.loc_speed_security_req_cccd_write_perm  = SEC_OPEN;
    lns_init.position_quality_security_req_read_perm = SEC_OPEN;
    lns_init.navigation_security_req_cccd_write_perm = SEC_OPEN;
    lns_init.ctrl_point_security_req_write_perm      = SEC_OPEN;
    lns_init.ctrl_point_security_req_cccd_write_perm = SEC_OPEN;

    err_code = ble_lns_init(&m_lns, &lns_init);
    APP_ERROR_CHECK(err_code);

    ble_lns_route_t route1 = {.route_name = "Route one"};
    err_code = ble_lns_add_route(&m_lns, &route1);

    ble_lns_route_t route2 = {.route_name = "Route two"};
    err_code = ble_lns_add_route(&m_lns, &route2);

    // Initialize Battery Service
    memset(&bas_init, 0, sizeof(bas_init));

    // Here the sec level for the Battery Service can be changed/increased.
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.cccd_write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&bas_init.battery_level_char_attr_md.write_perm);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_report_read_perm);

    bas_init.evt_handler          = NULL;
    bas_init.support_notification = true;
    bas_init.p_report_ref         = NULL;
    bas_init.initial_batt_level   = 100;

    err_code = ble_bas_init(&m_bas, &bas_init);
    APP_ERROR_CHECK(err_code);

    // Initialize Device Information Service
    memset(&dis_init, 0, sizeof(dis_init));

    ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, MANUFACTURER_NAME);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&dis_init.dis_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&dis_init.dis_attr_md.write_perm);

    err_code = ble_dis_init(&dis_init);
    APP_ERROR_CHECK(err_code);
}


/**@brief Initialize the simulators.
 */
static void sim_init(void)
{
    // battery simulation
    m_battery_sim_cfg.min          = MIN_BATTERY_LEVEL;
    m_battery_sim_cfg.max          = MAX_BATTERY_LEVEL;
    m_battery_sim_cfg.incr         = BATTERY_LEVEL_INCREMENT;
    m_battery_sim_cfg.start_at_max = true;

    sensorsim_init(&m_battery_sim_state, &m_battery_sim_cfg);
}


/**@brief Start application timers.
 */
static void application_timers_start(void)
{
    uint32_t err_code;

    // Start application timers
    err_code = app_timer_start(m_battery_timer_id, BATTERY_LEVEL_MEAS_INTERVAL, NULL);
    APP_ERROR_CHECK(err_code);

    err_code = app_timer_start(m_loc_and_nav_timer_id, LOC_AND_NAV_DATA_INTERVAL, NULL);
    APP_ERROR_CHECK(err_code);
}
Пример #7
0
/**@brief Function for initializing services that will be used by the application.
 *
 * @details Initialize the Heart Rate, Battery and Device Information services.
 */
static void services_init(void)
{
		uint32_t       err_code;
		
		ble_bas_init_t 	bas_init;
		ble_dis_init_t 	dis_init;
		
		// Initialize Battery Service.
    memset(&bas_init, 0, sizeof(bas_init));

    // Here the sec level for the Battery Service can be changed/increased.
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.cccd_write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&bas_init.battery_level_char_attr_md.write_perm);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_report_read_perm);

    bas_init.evt_handler          = NULL;
    bas_init.support_notification = true;
    bas_init.p_report_ref         = NULL;
    bas_init.initial_batt_level   = 100;

    err_code = ble_bas_init(&m_bas, &bas_init);
    if (err_code == NRF_SUCCESS)
			debug_printf("Battery service initialised!\r\n");
		else
		{
			debug_printf("Error with initialising battery service.\r\n");
			APP_ERROR_CHECK(err_code);
		}

    // Initialize Device Information Service.
    memset(&dis_init, 0, sizeof(dis_init));

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&dis_init.dis_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&dis_init.dis_attr_md.write_perm);

    err_code = ble_dis_init(&dis_init);
    if (err_code == NRF_SUCCESS)
			debug_printf("Device Information service initialised!\r\n");
		else
		{
			debug_printf("Error with initialising device information service.\r\n");
			APP_ERROR_CHECK(err_code);
		}		
		
		// Initialize CCH custom Service.
		cch_service_init(&m_cch_service);
		
		#ifdef BLE_DFU_APP_SUPPORT
    /** @snippet [DFU BLE Service initialization] */
    ble_dfu_init_t   dfus_init;

    // Initialize the Device Firmware Update Service.
    memset(&dfus_init, 0, sizeof(dfus_init));

    dfus_init.evt_handler   = dfu_app_on_dfu_evt;
    dfus_init.error_handler = NULL;
    dfus_init.evt_handler   = dfu_app_on_dfu_evt;
    dfus_init.revision      = DFU_REVISION;

    err_code = ble_dfu_init(&m_dfus, &dfus_init);
    APP_ERROR_CHECK(err_code);

    dfu_app_reset_prepare_set(reset_prepare);
    dfu_app_dm_appl_instance_set(m_app_handle);
    /** @snippet [DFU BLE Service initialization] */
#endif // BLE_DFU_APP_SUPPORT
}
Пример #8
0
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,
        };
static uint32_t ach_report_char_add(const uint8_t uuid_type)
{
    // Report characteristic
    ble_gatts_char_md_t char_md;
    ble_gatts_attr_md_t cccd_md;
    ble_gatts_attr_md_t attr_md;

    ble_uuid_t          char_uuid;
    ble_gatts_attr_t    attr_char_value;


    // Controlpoint characteristic
    ble_gatts_char_md_t char_ctrlpt_md;
    ble_gatts_attr_md_t cccd_ctrlpt_md;
    ble_gatts_attr_md_t attr_ctrlpt_md;

    ble_uuid_t          char_ctrlpt_uuid;
    ble_gatts_attr_t    attr_char_ctrlpt_value;


    memset(&cccd_md, 0, sizeof(cccd_md));

    cccd_md.vloc = BLE_GATTS_VLOC_STACK;
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);

    memset(&char_md, 0, sizeof(char_md));

    char_md.char_props.read   = 1;
    char_md.char_props.notify = 1;
    char_md.p_char_user_desc  = NULL;
    char_md.p_char_pf         = NULL;
    char_md.p_user_desc_md    = NULL;
    char_md.p_cccd_md         = &cccd_md;
    char_md.p_sccd_md         = NULL;

    char_uuid.type = uuid_type;
    char_uuid.uuid = LOCAL_CHAR_UUID;

    memset(&attr_md, 0, sizeof(attr_md));

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.write_perm);

    attr_md.vloc    = BLE_GATTS_VLOC_STACK;
    attr_md.rd_auth = 0;
    attr_md.wr_auth = 0;
    attr_md.vlen    = 0;

    memset(&attr_char_value, 0, sizeof(attr_char_value));
//lint --e{545}     
    memset(&m_char_value, 0, APP_REPORT_CHAR_LEN);

    attr_char_value.p_uuid    = &char_uuid;
    attr_char_value.p_attr_md = &attr_md;
    attr_char_value.init_len  = APP_REPORT_CHAR_LEN;
    attr_char_value.init_offs = 0;
    attr_char_value.max_len   = APP_REPORT_CHAR_LEN;
    attr_char_value.p_value   = m_char_value;

    uint32_t err_code;
    err_code = sd_ble_gatts_characteristic_add(m_service_handle,
                                               &char_md,
                                               &attr_char_value,
                                               &m_char_handles);

    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    memset(&cccd_ctrlpt_md, 0, sizeof(cccd_ctrlpt_md));

    cccd_ctrlpt_md.vloc = BLE_GATTS_VLOC_STACK;
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_ctrlpt_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_ctrlpt_md.write_perm);

    memset(&char_ctrlpt_md, 0, sizeof(char_ctrlpt_md));

    char_ctrlpt_md.char_props.notify   = 1;
    char_ctrlpt_md.char_props.write    = 1;
    char_ctrlpt_md.p_char_user_desc    = NULL;
    char_ctrlpt_md.p_char_pf           = NULL;
    char_ctrlpt_md.p_user_desc_md      = NULL;
    char_ctrlpt_md.p_cccd_md           = &cccd_ctrlpt_md;
    char_ctrlpt_md.p_sccd_md           = NULL;

    char_ctrlpt_uuid.type = uuid_type;
    char_ctrlpt_uuid.uuid = LOCAL_CHAR_CTRLPT_UUID;

    memset(&attr_ctrlpt_md, 0, sizeof(attr_ctrlpt_md));

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_ctrlpt_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_ctrlpt_md.write_perm);

    attr_ctrlpt_md.vloc    = BLE_GATTS_VLOC_STACK;
    attr_ctrlpt_md.rd_auth = 0;
    attr_ctrlpt_md.wr_auth = 1;
    attr_ctrlpt_md.vlen    = 0;

    memset(&attr_char_ctrlpt_value, 0, sizeof(attr_char_ctrlpt_value));
//lint --e{545}     
    memset(&m_char_ctrlpt_value, 0, APP_CTRLPT_CHAR_LEN);

    attr_char_ctrlpt_value.p_uuid    = &char_ctrlpt_uuid;
    attr_char_ctrlpt_value.p_attr_md = &attr_ctrlpt_md;
    attr_char_ctrlpt_value.init_len  = APP_CTRLPT_CHAR_LEN;
    attr_char_ctrlpt_value.init_offs = 0;
    attr_char_ctrlpt_value.max_len   = APP_CTRLPT_CHAR_LEN;
    attr_char_ctrlpt_value.p_value   = m_char_ctrlpt_value;

    err_code = sd_ble_gatts_characteristic_add(m_service_handle,
                                               &char_ctrlpt_md,
                                               &attr_char_ctrlpt_value,
                                               &m_char_ctrlpt_handles);

    return err_code;
}
Пример #10
0
/**@brief Function for adding the accel Level characteristic.
 *
 * @param[in]   p_acc        accel Service structure.
 * @param[in]   p_acc_init   Information needed to initialize the service.
 *
 * @return      NRF_SUCCESS on success, otherwise an error code.
 */
static uint32_t accel_level_char_add(ble_acc_t * p_acc, const ble_acc_init_t * p_acc_init)
{
    uint32_t            err_code;
    ble_gatts_char_md_t char_md;
    ble_gatts_attr_md_t cccd_md;
    ble_gatts_attr_t    attr_char_value;
    // ble_gatts_attr_t    attr_char_value_2;
    ble_uuid_t          ble_uuid;
    ble_gatts_attr_md_t attr_md;
    // ble_gatts_attr_md_t attr_md_2;
    ble_gatts_attr_md_t user_desc_md;
    ble_gatts_char_pf_t  accel_pf;
    uint8_t             initial_accel_level;
    uint8_t             encoded_report_ref[BLE_SRV_ENCODED_REPORT_REF_LEN];
    uint8_t             init_len;
    uint8_t             user_desc[] = "ACCEL";

    // Add accel Level characteristic
    if (p_acc->is_notification_supported)
    {
        memset(&cccd_md, 0, sizeof(cccd_md));

        // According to acc_SPEC_V10, the read operation on cccd should be possible without
        // authentication.
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
        cccd_md.write_perm = p_acc_init->accel_level_char_attr_md.cccd_write_perm;
        cccd_md.vloc       = BLE_GATTS_VLOC_STACK;
    }

    memset(&user_desc_md, 0, sizeof(user_desc_md));
    
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&user_desc_md.read_perm);
    // BLE_GAP_CONN_SEC_MODE_SET_OPEN(&user_desc_md.write_perm);
    user_desc_md.vloc = BLE_GATTS_VLOC_STACK;

    memset(&accel_pf, 0, sizeof(accel_pf));
    accel_pf.format    = BLE_GATT_CPF_FORMAT_UINT16;
    accel_pf.exponent  = 0;
    accel_pf.unit      = 0x2713; //acceleration data

    memset(&char_md, 0, sizeof(char_md));

    char_md.char_props.read   = 1;
    char_md.char_props.write  = 1;
    char_md.char_props.notify = (p_acc->is_notification_supported) ? 1 : 0;
    char_md.p_char_user_desc  = user_desc;
    char_md.char_user_desc_max_size = 6;
    char_md.char_user_desc_size = 6;
    char_md.p_char_pf         = &accel_pf;
    char_md.p_user_desc_md    = &user_desc_md;
    char_md.p_cccd_md         = (p_acc->is_notification_supported) ? &cccd_md : NULL;
    char_md.p_sccd_md         = NULL;

    //adds the acce id to the softdevice stack, puts a reference to where it is
    //into acc_uuid_type
    ble_uuid.type = p_acc->uuid_type;
    ble_uuid.uuid = BLE_UUID_TYPE_VENDOR_BEGIN;

    memset(&attr_md, 0, sizeof(attr_md));

    attr_md.read_perm  = p_acc_init->accel_level_char_attr_md.read_perm;
    attr_md.write_perm = p_acc_init->accel_level_char_attr_md.write_perm;
    attr_md.vloc       = BLE_GATTS_VLOC_STACK;
    attr_md.rd_auth    = 0;
    attr_md.wr_auth    = 0;
    attr_md.vlen       = 0;

    initial_accel_level = p_acc_init->initial_batt_level;

    memset(&attr_char_value, 0, sizeof(attr_char_value));

    attr_char_value.p_uuid    = &ble_uuid;
    attr_char_value.p_attr_md = &attr_md;
    attr_char_value.init_len  = sizeof(uint16_t);
    attr_char_value.init_offs = 0;
    attr_char_value.max_len   = sizeof(uint16_t);
    attr_char_value.p_value   = &initial_accel_level;

    err_code = sd_ble_gatts_characteristic_add(p_acc->service_handle, &char_md,
                                               &attr_char_value,
                                               &p_acc->accel_level_handles);

    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    if (p_acc_init->p_report_ref != NULL)
    {
        // Add Report Reference descriptor
        BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_REPORT_REF_DESCR);

        memset(&attr_md, 0, sizeof(attr_md));

        attr_md.read_perm = p_acc_init->accel_level_report_read_perm;
        BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.write_perm);

        attr_md.vloc    = BLE_GATTS_VLOC_STACK;
        attr_md.rd_auth = 0;
        attr_md.wr_auth = 0;
        attr_md.vlen    = 0;
        
        init_len = ble_srv_report_ref_encode(encoded_report_ref, p_acc_init->p_report_ref);
        
        memset(&attr_char_value, 0, sizeof(attr_char_value));

        attr_char_value.p_uuid    = &ble_uuid;
        attr_char_value.p_attr_md = &attr_md;
        attr_char_value.init_len  = init_len;
        attr_char_value.init_offs = 0;
        attr_char_value.max_len   = attr_char_value.init_len;
        attr_char_value.p_value   = encoded_report_ref;

        err_code = sd_ble_gatts_descriptor_add(p_acc->accel_level_handles.value_handle,
                                               &attr_char_value,
                                               &p_acc->report_ref_handle);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    }
    else
    {
        p_acc->report_ref_handle = BLE_GATT_HANDLE_INVALID;
    }

    return NRF_SUCCESS;
}
Пример #11
0
/**@brief Function for initializing services that will be used by the application.
 *
 * @details Initialize the Running Speed and Cadence, Battery and Device Information services.
 */
static void services_init(void)
{
    uint32_t        err_code;
	ble_hts_init_t   hts_init;
    ble_rscs_init_t rscs_init;
    ble_bas_init_t  bas_init;
    ble_dis_init_t  dis_init;
	
	// Initialize Health Thermometer Service
    memset(&hts_init, 0, sizeof(hts_init));

    hts_init.evt_handler                 = on_hts_evt;
    hts_init.temp_type_as_characteristic = 0;
    hts_init.temp_type                   = BLE_HTS_TEMP_TYPE_BODY;

    // Here the sec level for the Health Thermometer Service can be changed/increased.
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hts_init.hts_meas_attr_md.cccd_write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hts_init.hts_meas_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hts_init.hts_meas_attr_md.write_perm);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&hts_init.hts_temp_type_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hts_init.hts_temp_type_attr_md.write_perm);

    err_code = ble_hts_init(&m_hts, &hts_init);
    APP_ERROR_CHECK(err_code);

    // Initialize Running Speed and Cadence Service

    memset(&rscs_init, 0, sizeof(rscs_init));

    rscs_init.evt_handler = NULL;
    rscs_init.feature     = BLE_RSCS_FEATURE_INSTANT_STRIDE_LEN_BIT|
								BLE_RSCS_FEATURE_TOTAL_DISTANCE_BIT|			//
									BLE_RSCS_FEATURE_WALKING_OR_RUNNING_STATUS_BIT;

    // Here the sec level for the Running Speed and Cadence Service can be changed/increased.
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&rscs_init.rsc_meas_attr_md.cccd_write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&rscs_init.rsc_meas_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&rscs_init.rsc_meas_attr_md.write_perm);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&rscs_init.rsc_feature_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&rscs_init.rsc_feature_attr_md.write_perm);

    err_code = ble_rscs_init(&m_rscs, &rscs_init);
    APP_ERROR_CHECK(err_code);

    // Initialize Battery Service.
    memset(&bas_init, 0, sizeof(bas_init));

    // Here the sec level for the Battery Service can be changed/increased.
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.cccd_write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&bas_init.battery_level_char_attr_md.write_perm);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_report_read_perm);

    bas_init.evt_handler          = NULL;
    bas_init.support_notification = true;
    bas_init.p_report_ref         = NULL;
    bas_init.initial_batt_level   = 100;

    err_code = ble_bas_init(&m_bas, &bas_init);
    APP_ERROR_CHECK(err_code);

    // Initialize Device Information Service.
    memset(&dis_init, 0, sizeof(dis_init));

    ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, MANUFACTURER_NAME);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&dis_init.dis_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&dis_init.dis_attr_md.write_perm);

    err_code = ble_dis_init(&dis_init);
    APP_ERROR_CHECK(err_code);
}
Пример #12
0
/**@brief Function for initializing services that will be used by the application.
 *
 * @details Initialize the Running Speed and Cadence, Battery and Device Information services.
 */
static void services_init(void)
{
    uint32_t           err_code;
    ble_rscs_init_t    rscs_init;
    ble_bas_init_t     bas_init;
    ble_dis_init_t     dis_init;


    // Initialize Running Speed and Cadence Service

    memset(&rscs_init, 0, sizeof(rscs_init));

    rscs_init.evt_handler = NULL;
    rscs_init.feature     = BLE_RSCS_FEATURE_INSTANT_STRIDE_LEN_BIT |
                            BLE_RSCS_FEATURE_WALKING_OR_RUNNING_STATUS_BIT;

    rscs_init.initial_rcm.is_inst_stride_len_present = true;
    rscs_init.initial_rcm.is_total_distance_present  = false;
    rscs_init.initial_rcm.is_running                 = false;
    rscs_init.initial_rcm.inst_stride_length         = 0;

    // Here the sec level for the Running Speed and Cadence Service can be changed/increased.
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&rscs_init.rsc_meas_attr_md.cccd_write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&rscs_init.rsc_meas_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&rscs_init.rsc_meas_attr_md.write_perm);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&rscs_init.rsc_feature_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&rscs_init.rsc_feature_attr_md.write_perm);

    err_code = ble_rscs_init(&m_rscs, &rscs_init);
    APP_ERROR_CHECK(err_code);

    // Initialize Battery Service.
    memset(&bas_init, 0, sizeof(bas_init));

    // Here the sec level for the Battery Service can be changed/increased.
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.cccd_write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&bas_init.battery_level_char_attr_md.write_perm);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_report_read_perm);

    bas_init.evt_handler          = NULL;
    bas_init.support_notification = true;
    bas_init.p_report_ref         = NULL;
    bas_init.initial_batt_level   = 100;

    err_code = ble_bas_init(&m_bas, &bas_init);
    APP_ERROR_CHECK(err_code);

    // Initialize Device Information Service.
    memset(&dis_init, 0, sizeof(dis_init));

    ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, MANUFACTURER_NAME);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&dis_init.dis_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&dis_init.dis_attr_md.write_perm);

    err_code = ble_dis_init(&dis_init);
    APP_ERROR_CHECK(err_code);
}
Пример #13
0
/**@brief Function for adding Report Map characteristics.
 *
 * @param[in]   p_hids        HID Service structure.
 * @param[in]   p_hids_init   Service initialization structure.
 *
 * @return      NRF_SUCCESS on success, otherwise an error code.
 */
static uint32_t rep_map_char_add(ble_hids_t * p_hids, const ble_hids_init_t * p_hids_init)
{
    uint32_t            err_code;
    ble_gatts_char_md_t char_md;
    ble_gatts_attr_t    attr_char_value;
    ble_uuid_t          ble_uuid;
    ble_gatts_attr_md_t attr_md;

    // Add Report Map characteristic
    memset(&char_md, 0, sizeof(char_md));

    char_md.char_props.read  = 1;
    char_md.p_char_user_desc = NULL;
    char_md.p_char_pf        = NULL;
    char_md.p_user_desc_md   = NULL;
    char_md.p_cccd_md        = NULL;
    char_md.p_sccd_md        = NULL;

    BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_REPORT_MAP_CHAR);

    memset(&attr_md, 0, sizeof(attr_md));

    attr_md.read_perm  = p_hids_init->rep_map.security_mode.read_perm;
    attr_md.write_perm = p_hids_init->rep_map.security_mode.write_perm;
    attr_md.vloc       = BLE_GATTS_VLOC_STACK;
    attr_md.rd_auth    = 0;
    attr_md.wr_auth    = 0;
    attr_md.vlen       = 1;

    memset(&attr_char_value, 0, sizeof(attr_char_value));

    attr_char_value.p_uuid    = &ble_uuid;
    attr_char_value.p_attr_md = &attr_md;
    attr_char_value.init_len  = p_hids_init->rep_map.data_len;
    attr_char_value.init_offs = 0;
    attr_char_value.max_len   = p_hids_init->rep_map.data_len;
    attr_char_value.p_value   = p_hids_init->rep_map.p_data;

    err_code = sd_ble_gatts_characteristic_add(p_hids->service_handle,
                                               &char_md,
                                               &attr_char_value,
                                               &p_hids->rep_map_handles);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    if (p_hids_init->rep_map.ext_rep_ref_num != 0 && p_hids_init->rep_map.p_ext_rep_ref == NULL)
    {
        return NRF_ERROR_INVALID_PARAM;
    }
    for (int i = 0; i < p_hids_init->rep_map.ext_rep_ref_num; ++i)
    {
        uint8_t encoded_rep_ref[sizeof(ble_uuid128_t)];
        uint8_t encoded_rep_ref_len;

        // Add External Report Reference descriptor
        BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_EXTERNAL_REPORT_REF_DESCR);

        memset(&attr_md, 0, sizeof(attr_md));

        BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.read_perm);
        BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.write_perm);

        attr_md.vloc    = BLE_GATTS_VLOC_STACK;
        attr_md.rd_auth = 0;
        attr_md.wr_auth = 0;
        attr_md.vlen    = 0;

        err_code = sd_ble_uuid_encode(&p_hids_init->rep_map.p_ext_rep_ref[i],
                                      &encoded_rep_ref_len,
                                      encoded_rep_ref);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }

        memset(&attr_char_value, 0, sizeof(attr_char_value));

        attr_char_value.p_uuid    = &ble_uuid;
        attr_char_value.p_attr_md = &attr_md;
        attr_char_value.init_len  = encoded_rep_ref_len;
        attr_char_value.init_offs = 0;
        attr_char_value.max_len   = attr_char_value.init_len;
        attr_char_value.p_value   = encoded_rep_ref;

        err_code = sd_ble_gatts_descriptor_add(p_hids->rep_map_handles.value_handle,
                                               &attr_char_value,
                                               &p_hids->rep_map_ext_rep_ref_handle);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    }

    return NRF_SUCCESS;
}
Пример #14
0
/**@brief Function for adding characteristic to Eddystone service.
 *
 * @param[in] p_escs       Eddystone Configuration Service structure.
 * @param[in] p_escs_init  Information needed to initialize the service.
 * @param[in] p_char_init  Information needed to initialize the characteristic.
 *
 * @return NRF_SUCCESS on success, otherwise an error code.
 */
static uint32_t char_add(const char_init_t        * p_char_init,
                         nrf_ble_escs_t           * p_escs,
                         void                     * p_value,
                         ble_gatts_char_handles_t * p_handles)
{
    uint32_t err_code;
    ble_gatts_char_md_t char_md;
    ble_gatts_attr_t    attr_char_value;
    ble_uuid_t          ble_uuid;
    ble_gatts_attr_md_t attr_md;

    VERIFY_PARAM_NOT_NULL(p_char_init);
    VERIFY_PARAM_NOT_NULL(p_escs);
    VERIFY_PARAM_NOT_NULL(p_value);
    VERIFY_PARAM_NOT_NULL(p_handles);

    memset(&char_md, 0, sizeof(char_md));
    memset(&attr_char_value, 0, sizeof(attr_char_value));
    memset(&ble_uuid, 0, sizeof(ble_uuid));
    memset(&attr_md, 0, sizeof(attr_md));

    if(p_char_init->read)
    {
        char_md.char_props.read  = 1;
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
    }

    else
    {
        BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.read_perm);
    }

    if(p_char_init->write)
    {
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
        char_md.char_props.write  = 1;
    }

    else
    {
        BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.write_perm);
    }

    ble_uuid.type = p_escs->uuid_type;
    ble_uuid.uuid = p_char_init->uuid;

    attr_md.vloc    = p_char_init->vloc;
    attr_md.rd_auth = p_char_init->rd_auth;
    attr_md.wr_auth = p_char_init->wr_auth;
    attr_md.vlen    = p_char_init->vlen;

    attr_char_value.p_uuid    = &ble_uuid;
    attr_char_value.p_attr_md = &attr_md;
    attr_char_value.init_len  = p_char_init->init_len;
    attr_char_value.p_value   = p_value;
    attr_char_value.max_len   = p_char_init->max_len;

    err_code = sd_ble_gatts_characteristic_add(p_escs->service_handle,
                                               &char_md,
                                               &attr_char_value,
                                               p_handles);

    if(err_code == NRF_SUCCESS)
    {
        ASSERT(m_handle_to_uuid_map_idx < BLE_ESCS_NUMBER_OF_CHARACTERISTICS);
        m_handle_to_uuid_map[m_handle_to_uuid_map_idx].val_handle = p_handles->value_handle;
        m_handle_to_uuid_map[m_handle_to_uuid_map_idx].uuid = p_char_init->uuid;
        m_handle_to_uuid_map_idx++;
    }

    return err_code;
}
Пример #15
0
/**@brief Function for initializing services that will be used by the application.
 *
 * @details Initialize the Cycling Speed and Cadence, Battery and Device Information services.
 */
static void services_init(void)
{
    uint32_t        err_code;
    ble_cscs_init_t cscs_init;
    ble_bas_init_t  bas_init;
    ble_dis_init_t  dis_init;
    ble_sensor_location_t sensor_location;

    // Initialize Cycling Speed and Cadence Service.
    memset(&cscs_init, 0, sizeof(cscs_init));

    cscs_init.evt_handler = NULL;
    cscs_init.feature     = BLE_CSCS_FEATURE_WHEEL_REV_BIT | BLE_CSCS_FEATURE_CRANK_REV_BIT | BLE_CSCS_FEATURE_MULTIPLE_SENSORS_BIT;

    // Here the sec level for the Cycling Speed and Cadence Service can be changed/increased.
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cscs_init.csc_meas_attr_md.cccd_write_perm);    // for the measurement characteristic, only the CCCD write permission can be set by the application, others are mandated by service specification
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cscs_init.csc_feature_attr_md.read_perm);       // for the feature characteristic, only the read permission can be set by the application, others are mandated by service specification
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cscs_init.csc_ctrlpt_attr_md.write_perm);       // for the SC control point characteristic, only the write permission and CCCD write can be set by the application, others are mandated by service specification
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cscs_init.csc_ctrlpt_attr_md.cccd_write_perm);  // for the SC control point characteristic, only the write permission and CCCD write can be set by the application, others are mandated by service specification

    cscs_init.ctrplt_supported_functions    = BLE_SRV_SC_CTRLPT_CUM_VAL_OP_SUPPORTED
            |BLE_SRV_SC_CTRLPT_SENSOR_LOCATIONS_OP_SUPPORTED
            |BLE_SRV_SC_CTRLPT_START_CALIB_OP_SUPPORTED;
    cscs_init.ctrlpt_evt_handler            = sc_ctrlpt_event_handler;
    cscs_init.list_supported_locations      = supported_locations;
    cscs_init.size_list_supported_locations = sizeof(supported_locations) / sizeof(ble_sensor_location_t);

    sensor_location           = BLE_SENSOR_LOCATION_FRONT_WHEEL;                    // initializes the sensor location to add the sensor location characteristic.
    cscs_init.sensor_location = &sensor_location;
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cscs_init.csc_sensor_loc_attr_md.read_perm);    // for the sensor location characteristic, only the read permission can be set by the application, others are mendated by service specification

    err_code = ble_cscs_init(&m_cscs, &cscs_init);
    APP_ERROR_CHECK(err_code);

    // Initialize Battery Service.
    memset(&bas_init, 0, sizeof(bas_init));

    // Here the sec level for the Battery Service can be changed/increased.
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.cccd_write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_char_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&bas_init.battery_level_char_attr_md.write_perm);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&bas_init.battery_level_report_read_perm);

    bas_init.evt_handler          = NULL;
    bas_init.support_notification = true;
    bas_init.p_report_ref         = NULL;
    bas_init.initial_batt_level   = 100;

    err_code = ble_bas_init(&m_bas, &bas_init);
    APP_ERROR_CHECK(err_code);

    // Initialize Device Information Service.
    memset(&dis_init, 0, sizeof(dis_init));

    ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, MANUFACTURER_NAME);

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&dis_init.dis_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&dis_init.dis_attr_md.write_perm);

    err_code = ble_dis_init(&dis_init);
    APP_ERROR_CHECK(err_code);
}
Пример #16
0
/**@brief Initialize HID Service.
 */
static void hids_init(void)
{
    uint32_t                   err_code;
    ble_hids_init_t            hids_init_obj;
    ble_hids_inp_rep_init_t    input_report_array[1];
    ble_hids_inp_rep_init_t  * p_input_report;
    ble_hids_outp_rep_init_t   output_report_array[1];
    ble_hids_outp_rep_init_t * p_output_report;
    uint8_t                    hid_info_flags;

    static uint8_t report_map_data[] =
    {
        0x05, 0x01,                 // Usage Page (Generic Desktop)
        0x09, 0x06,                 // Usage (Keyboard)
        0xA1, 0x01,                 // Collection (Application)
        0x05, 0x07,                 //     Usage Page (Key Codes)
        0x19, 0xe0,                 //     Usage Minimum (224)
        0x29, 0xe7,                 //     Usage Maximum (231)
        0x15, 0x00,                 //     Logical Minimum (0)
        0x25, 0x01,                 //     Logical Maximum (1)
        0x75, 0x01,                 //     Report Size (1)
        0x95, 0x08,                 //     Report Count (8)
        0x81, 0x02,                 //     Input (Data, Variable, Absolute)
    
        0x95, 0x01,                 //     Report Count (1)
        0x75, 0x08,                 //     Report Size (8)
        0x81, 0x01,                 //     Input (Constant) reserved byte(1)
    
        0x95, 0x05,                 //     Report Count (5)
        0x75, 0x01,                 //     Report Size (1)
        0x05, 0x08,                 //     Usage Page (Page# for LEDs)
        0x19, 0x01,                 //     Usage Minimum (1)
        0x29, 0x05,                 //     Usage Maximum (5)
        0x91, 0x02,                 //     Output (Data, Variable, Absolute), Led report
        0x95, 0x01,                 //     Report Count (1)
        0x75, 0x03,                 //     Report Size (3)
        0x91, 0x01,                 //     Output (Data, Variable, Absolute), Led report padding
    
        0x95, 0x06,                 //     Report Count (6)
        0x75, 0x08,                 //     Report Size (8)
        0x15, 0x00,                 //     Logical Minimum (0)
        0x25, 0x65,                 //     Logical Maximum (101)
        0x05, 0x07,                 //     Usage Page (Key codes)
        0x19, 0x00,                 //     Usage Minimum (0)
        0x29, 0x65,                 //     Usage Maximum (101)
        0x81, 0x00,                 //     Input (Data, Array) Key array(6 bytes)
    
        0x09, 0x05,                 //     Usage (Vendor Defined)
        0x15, 0x00,                 //     Logical Minimum (0)
        0x26, 0xFF, 0x00,           //     Logical Maximum (255)
        0x75, 0x08,                 //     Report Count (2)
        0x95, 0x02,                 //     Report Size (8 bit)
        0xB1, 0x02,                 //     Feature (Data, Variable, Absolute)

        0xC0                        // End Collection (Application)    
    };

    // Initialize HID Service
    p_input_report                      = &input_report_array[INPUT_REPORT_KEYS_INDEX];
    p_input_report->max_len             = INPUT_REPORT_KEYS_MAX_LEN;
    p_input_report->rep_ref.report_id   = INPUT_REP_REF_ID;
    p_input_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_INPUT;
    
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.cccd_write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.write_perm);

    p_output_report                      = &output_report_array[OUTPUT_REPORT_INDEX];
    p_output_report->max_len             = OUTPUT_REPORT_MAX_LEN;
    p_output_report->rep_ref.report_id   = OUTPUT_REP_REF_ID;
    p_output_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_OUTPUT;
    
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_output_report->security_mode.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_output_report->security_mode.write_perm);

    hid_info_flags = HID_INFO_FLAG_REMOTE_WAKE_MSK | HID_INFO_FLAG_NORMALLY_CONNECTABLE_MSK;

    memset(&hids_init_obj, 0, sizeof(hids_init_obj));

    hids_init_obj.evt_handler                    = on_hids_evt;
    hids_init_obj.error_handler                  = service_error_handler;
    hids_init_obj.is_kb                          = true;
    hids_init_obj.is_mouse                       = false;
    hids_init_obj.inp_rep_count                  = 1;
    hids_init_obj.p_inp_rep_array                = input_report_array;
    hids_init_obj.outp_rep_count                 = 1;
    hids_init_obj.p_outp_rep_array               = output_report_array;
    hids_init_obj.feature_rep_count              = 0;
    hids_init_obj.p_feature_rep_array            = NULL;
    hids_init_obj.rep_map.data_len               = sizeof(report_map_data);
    hids_init_obj.rep_map.p_data                 = report_map_data;
    hids_init_obj.hid_information.bcd_hid        = BASE_USB_HID_SPEC_VERSION;
    hids_init_obj.hid_information.b_country_code = 0;
    hids_init_obj.hid_information.flags          = hid_info_flags;
    hids_init_obj.included_services_count        = 0;
    hids_init_obj.p_included_services_array      = NULL;

    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.rep_map.security_mode.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hids_init_obj.rep_map.security_mode.write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.hid_information.security_mode.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hids_init_obj.hid_information.security_mode.write_perm);

    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.security_mode_boot_kb_inp_rep.cccd_write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.security_mode_boot_kb_inp_rep.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hids_init_obj.security_mode_boot_kb_inp_rep.write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.security_mode_boot_kb_outp_rep.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.security_mode_boot_kb_outp_rep.write_perm);

    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.security_mode_protocol.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.security_mode_protocol.write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hids_init_obj.security_mode_ctrl_point.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.security_mode_ctrl_point.write_perm);

    err_code = ble_hids_init(&m_hids, &hids_init_obj);
    APP_ERROR_CHECK(err_code);
}
Пример #17
0
/**@brief Function for adding the Battery Level characteristic.
 *
 * @param[in]   p_bas        Battery Service structure.
 * @param[in]   p_bas_init   Information needed to initialize the service.
 *
 * @return      NRF_SUCCESS on success, otherwise an error code.
 */
static uint32_t battery_level_char_add(ble_bas_t * p_bas, const ble_bas_init_t * p_bas_init)
{
    uint32_t            err_code;
    ble_gatts_char_md_t char_md;
    ble_gatts_attr_md_t cccd_md;
    ble_gatts_attr_t    attr_char_value;
    ble_uuid_t          ble_uuid;
    ble_gatts_attr_md_t attr_md;
    uint8_t             initial_battery_level;
    uint8_t             encoded_report_ref[BLE_SRV_ENCODED_REPORT_REF_LEN];
    uint8_t             init_len;
    
    // Add Battery Level characteristic
    if (p_bas->is_notification_supported)
    {
        memset(&cccd_md, 0, sizeof(cccd_md));
    
        // According to BAS_SPEC_V10, the read operation on cccd should be possible without
        // authentication.
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
        cccd_md.write_perm = p_bas_init->battery_level_char_attr_md.cccd_write_perm;
        cccd_md.vloc = BLE_GATTS_VLOC_STACK;
    }
    
    memset(&char_md, 0, sizeof(char_md));
    
    char_md.char_props.read   = 1;
    char_md.char_props.notify = (p_bas->is_notification_supported) ? 1 : 0;
    char_md.p_char_user_desc  = NULL;
    char_md.p_char_pf         = NULL;
    char_md.p_user_desc_md    = NULL;
    char_md.p_cccd_md         = (p_bas->is_notification_supported) ? &cccd_md : NULL;
    char_md.p_sccd_md         = NULL;
    
    BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_BATTERY_LEVEL_CHAR);
    
    memset(&attr_md, 0, sizeof(attr_md));

    attr_md.read_perm  = p_bas_init->battery_level_char_attr_md.read_perm;
    attr_md.write_perm = p_bas_init->battery_level_char_attr_md.write_perm;
    attr_md.vloc       = BLE_GATTS_VLOC_STACK;
    attr_md.rd_auth    = 0;
    attr_md.wr_auth    = 0;
    attr_md.vlen       = 0;
    
    initial_battery_level = p_bas_init->initial_batt_level;
    
    memset(&attr_char_value, 0, sizeof(attr_char_value));

    attr_char_value.p_uuid       = &ble_uuid;
    attr_char_value.p_attr_md    = &attr_md;
    attr_char_value.init_len     = sizeof(uint8_t);
    attr_char_value.init_offs    = 0;
    attr_char_value.max_len      = sizeof(uint8_t);
    attr_char_value.p_value      = &initial_battery_level;
    
    err_code = sd_ble_gatts_characteristic_add(p_bas->service_handle, &char_md,
                                               &attr_char_value,
                                               &p_bas->battery_level_handles);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }
    
    if (p_bas_init->p_report_ref != NULL)
    {
        // Add Report Reference descriptor
        BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_REPORT_REF_DESCR);
        
        memset(&attr_md, 0, sizeof(attr_md));

        attr_md.read_perm = p_bas_init->battery_level_report_read_perm;
        BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.write_perm);

        attr_md.vloc       = BLE_GATTS_VLOC_STACK;
        attr_md.rd_auth    = 0;
        attr_md.wr_auth    = 0;
        attr_md.vlen       = 0;
        
        init_len = ble_srv_report_ref_encode(encoded_report_ref, p_bas_init->p_report_ref);
        
        memset(&attr_char_value, 0, sizeof(attr_char_value));

        attr_char_value.p_uuid       = &ble_uuid;
        attr_char_value.p_attr_md    = &attr_md;
        attr_char_value.init_len     = init_len;
        attr_char_value.init_offs    = 0;
        attr_char_value.max_len      = attr_char_value.init_len;
        attr_char_value.p_value      = encoded_report_ref;
        
        err_code = sd_ble_gatts_descriptor_add(p_bas->battery_level_handles.value_handle,
                                               &attr_char_value,
                                               &p_bas->report_ref_handle);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    }
    else
    {
        p_bas->report_ref_handle = BLE_GATT_HANDLE_INVALID;
    }
    
    return NRF_SUCCESS;
}
Пример #18
0
/**@brief Function for adding the Ambient Service values characteristic.
 *
 * @param[in]   p_amb        Ambient Service Service structure.
 * @param[in]   p_amb_init   Information needed to initialize the service.
 *
 * @return      NRF_SUCCESS on success, otherwise an error code.
 */
static uint32_t sensors_char_add(ble_ambient_t * p_amb, const ble_ambient_init_t * p_amb_init){
	uint32_t   err_code = NRF_SUCCESS;
	
    ble_gatts_attr_md_t cccd_md;

    ble_gatts_char_md_t char_md;
    ble_gatts_attr_t    attr_char;
    
    ble_gatts_attr_md_t attr_md_no_write;
    ble_gatts_attr_md_t attr_md_read_write;

#if TEMP_ENABLED || PR_ENABLED || HUM_ENABLED || LUM_ENABLED || HUMSOLO_ENABLED
    ble_uuid_t          ble_char_uuid;
#endif

    // Add Ambient Service values characteristics
    if (p_amb->is_notification_supported)
    {
        memset(&cccd_md, 0, sizeof(cccd_md));

        // According to BAS_SPEC_V10, the read operation on cccd should be possible without
        // authentication. Always set cccd to OPEN!
        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;
    }

    memset(&char_md, 0, sizeof(char_md));
	
	//Set characteristic metadata, use same for similar characteristics
    char_md.char_props.read   = 1;
    char_md.char_props.notify = (p_amb->is_notification_supported) ? 1 : 0;
    char_md.char_props.write  = 0;
    char_md.char_props.write_wo_resp = 0;
    char_md.p_char_user_desc  = NULL;
    char_md.p_char_pf         = NULL;
    char_md.p_user_desc_md    = NULL;
    char_md.p_cccd_md         = (p_amb->is_notification_supported) ? &cccd_md : NULL;
    char_md.p_sccd_md         = NULL;
	char_md.char_ext_props.wr_aux = 0;

	
	//Set atribute metadata for sensor values
    memset(&attr_md_no_write, 0, sizeof(attr_md_no_write));
	
	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md_no_write.read_perm); //can read
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md_no_write.write_perm); //can't write
    attr_md_no_write.vloc       = BLE_GATTS_VLOC_STACK;
    attr_md_no_write.rd_auth    = 0;
    attr_md_no_write.wr_auth    = 0;
    attr_md_no_write.vlen       = 1;
	
	//Set atribute metadata for configuration 
	memset(&attr_md_read_write, 0, sizeof(attr_md_read_write));
	
	BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md_read_write.read_perm); //can read
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md_read_write.write_perm); //can write
    attr_md_read_write.vloc       = BLE_GATTS_VLOC_STACK;
    attr_md_read_write.rd_auth    = 0;
    attr_md_read_write.wr_auth    = 0;
    attr_md_read_write.vlen       = 0;	
	
    memset(&attr_char, 0, sizeof(attr_char));
	

    ///***************** TEMP ***********************/
	#if TEMP_ENABLED
	//Set atributes struct
	ble_char_uuid.type = p_amb->uuid_type;
	ble_char_uuid.uuid = AMBIENT_UUID_TEMP_CHAR;
	
    attr_char.p_uuid    = &ble_char_uuid;
    attr_char.p_attr_md = &attr_md_no_write;
    attr_char.init_len  = AMB_TEMP_MAX_PACKET_VALUE;
    attr_char.init_offs = 0;
    attr_char.max_len   = AMB_TEMP_MAX_PACKET_VALUE;
    attr_char.p_value   = p_amb->temp_value;

    char_md.char_props.write  = 0;
	char_md.char_props.write_wo_resp = 0;

    //Add temp characteristic 
    err_code = sd_ble_gatts_characteristic_add(p_amb->service_handle, &char_md,
                                    &attr_char, &p_amb->temp_handles);

    if(err_code != NRF_SUCCESS)
		return err_code;

    //Set atributes struct
	ble_char_uuid.type = p_amb->uuid_type;
	ble_char_uuid.uuid = AMBIENT_UUID_TEMP_CONFIG_CHAR;

	attr_char.p_uuid    = &ble_char_uuid;
	attr_char.p_attr_md = &attr_md_read_write;
	attr_char.init_len  = sizeof(uint8_t);
	attr_char.init_offs = 0;
	attr_char.max_len   = sizeof(uint8_t);
	attr_char.p_value   = &(p_amb->temp_configuration);

	char_md.char_props.write  = 1;
	char_md.char_props.write_wo_resp = 1;

	//Add temp configuration characteristic
	err_code = sd_ble_gatts_characteristic_add(p_amb->service_handle, &char_md,
									&attr_char, &p_amb->temp_configuration_handles);

	if(err_code != NRF_SUCCESS)
		return err_code;
	#endif

	///***************** PR ***********************/
	#if PR_ENABLED
	//Set atributes struct
	ble_char_uuid.type = p_amb->uuid_type;
	ble_char_uuid.uuid = AMBIENT_UUID_PR_CHAR;

	attr_char.p_uuid    = &ble_char_uuid;
	attr_char.p_attr_md = &attr_md_no_write;
	attr_char.init_len  = AMB_PR_MAX_PACKET_VALUE;
	attr_char.init_offs = 0;
	attr_char.max_len   = AMB_PR_MAX_PACKET_VALUE;
	attr_char.p_value   = p_amb->pr_value;

	char_md.char_props.write  = 0;
	char_md.char_props.write_wo_resp = 0;

	//Add pressure characteristic
	err_code = sd_ble_gatts_characteristic_add(p_amb->service_handle, &char_md,
									&attr_char, &p_amb->pr_handles);

	if(err_code != NRF_SUCCESS)
		return err_code;

	//Set atributes struct
	ble_char_uuid.type = p_amb->uuid_type;
	ble_char_uuid.uuid = AMBIENT_UUID_PR_CONFIG_CHAR;

	attr_char.p_uuid    = &ble_char_uuid;
	attr_char.p_attr_md = &attr_md_read_write;
	attr_char.init_len  = sizeof(uint8_t);
	attr_char.init_offs = 0;
	attr_char.max_len   = sizeof(uint8_t);
	attr_char.p_value   = &(p_amb->pr_configuration);

	char_md.char_props.write  = 1;
	char_md.char_props.write_wo_resp = 1;

	//Add temp configuration characteristic
	err_code = sd_ble_gatts_characteristic_add(p_amb->service_handle, &char_md,
									&attr_char, &p_amb->pr_configuration_handles);

	if(err_code != NRF_SUCCESS)
		return err_code;
	#endif

	///***************** HUM ***********************/
	#if HUM_ENABLED
	//Set atributes struct
	ble_char_uuid.type = p_amb->uuid_type;
	ble_char_uuid.uuid = AMBIENT_UUID_HUM_CHAR;

	attr_char.p_uuid    = &ble_char_uuid;
	attr_char.p_attr_md = &attr_md_no_write;
	attr_char.init_len  = AMB_HUM_MAX_PACKET_VALUE;
	attr_char.init_offs = 0;
	attr_char.max_len   = AMB_HUM_MAX_PACKET_VALUE;
	attr_char.p_value   = p_amb->hum_value;

	char_md.char_props.write  = 0;
	char_md.char_props.write_wo_resp = 0;

	//Add pressure characteristic
	err_code = sd_ble_gatts_characteristic_add(p_amb->service_handle, &char_md,
									&attr_char, &p_amb->hum_handles);

	if(err_code != NRF_SUCCESS)
		return err_code;

	//Set atributes struct
	ble_char_uuid.type = p_amb->uuid_type;
	ble_char_uuid.uuid = AMBIENT_UUID_HUM_CONFIG_CHAR;

	attr_char.p_uuid    = &ble_char_uuid;
	attr_char.p_attr_md = &attr_md_read_write;
	attr_char.init_len  = sizeof(uint8_t);
	attr_char.init_offs = 0;
	attr_char.max_len   = sizeof(uint8_t);
	attr_char.p_value   = &(p_amb->hum_configuration);

	char_md.char_props.write  = 1;
	char_md.char_props.write_wo_resp = 1;

	//Add temp configuration characteristic
	err_code = sd_ble_gatts_characteristic_add(p_amb->service_handle, &char_md,
									&attr_char, &p_amb->hum_configuration_handles);

	if(err_code != NRF_SUCCESS)
		return err_code;
	#endif

	///***************** HUMSOLO ***********************/
	#if HUMSOLO_ENABLED
	//Set atributes struct
	ble_char_uuid.type = p_amb->uuid_type;
	ble_char_uuid.uuid = AMBIENT_UUID_HUMSOLO_CHAR;

	attr_char.p_uuid    = &ble_char_uuid;
	attr_char.p_attr_md = &attr_md_no_write;
	attr_char.init_len  = AMB_HUMSOLO_MAX_PACKET_VALUE;
	attr_char.init_offs = 0;
	attr_char.max_len   = AMB_HUMSOLO_MAX_PACKET_VALUE;
	attr_char.p_value   = p_amb->humsolo_value;

	char_md.char_props.write  = 0;
	char_md.char_props.write_wo_resp = 0;

	//Add pressure characteristic
	err_code = sd_ble_gatts_characteristic_add(p_amb->service_handle, &char_md,
									&attr_char, &p_amb->humsolo_handles);

	if(err_code != NRF_SUCCESS)
		return err_code;

	//Set atributes struct
	ble_char_uuid.type = p_amb->uuid_type;
	ble_char_uuid.uuid = AMBIENT_UUID_HUMSOLO_CONFIG_CHAR;

	attr_char.p_uuid    = &ble_char_uuid;
	attr_char.p_attr_md = &attr_md_read_write;
	attr_char.init_len  = sizeof(uint8_t);
	attr_char.init_offs = 0;
	attr_char.max_len   = sizeof(uint8_t);
	attr_char.p_value   = &(p_amb->humsolo_configuration);

	char_md.char_props.write  = 1;
	char_md.char_props.write_wo_resp = 1;

	//Add temp configuration characteristic
	err_code = sd_ble_gatts_characteristic_add(p_amb->service_handle, &char_md,
									&attr_char, &p_amb->humsolo_configuration_handles);

	if(err_code != NRF_SUCCESS)
		return err_code;
	#endif

	///***************** LUM ***********************/
	#if LUM_ENABLED
	//Set atributes struct
	ble_char_uuid.type = p_amb->uuid_type;
	ble_char_uuid.uuid = AMBIENT_UUID_LUM_CHAR;

	attr_char.p_uuid    = &ble_char_uuid;
	attr_char.p_attr_md = &attr_md_no_write;
	attr_char.init_len  = AMB_LUM_MAX_PACKET_VALUE;
	attr_char.init_offs = 0;
	attr_char.max_len   = AMB_LUM_MAX_PACKET_VALUE;
	attr_char.p_value   = p_amb->lum_value;

	char_md.char_props.write  = 0;
	char_md.char_props.write_wo_resp = 0;

	//Add luminosity characteristic
	err_code = sd_ble_gatts_characteristic_add(p_amb->service_handle, &char_md,
									&attr_char, &p_amb->lum_handles);

	if(err_code != NRF_SUCCESS)
		return err_code;

	//Set atributes struct
	ble_char_uuid.type = p_amb->uuid_type;
	ble_char_uuid.uuid = AMBIENT_UUID_LUM_CONFIG_CHAR;

	attr_char.p_uuid    = &ble_char_uuid;
	attr_char.p_attr_md = &attr_md_read_write;
	attr_char.init_len  = sizeof(uint8_t);
	attr_char.init_offs = 0;
	attr_char.max_len   = sizeof(uint8_t);
	attr_char.p_value   = &(p_amb->lum_configuration);

	char_md.char_props.write  = 1;
	char_md.char_props.write_wo_resp = 1;

	//Add temp configuration characteristic
	err_code = sd_ble_gatts_characteristic_add(p_amb->service_handle, &char_md,
									&attr_char, &p_amb->lum_configuration_handles);

	if(err_code != NRF_SUCCESS)
		return err_code;
	#endif

	//A map for handles, maybe a bit rudimentary...	
	type_to_handle[0].type = BLE_AMBIENT_TEMP;
	#if TEMP_ENABLED
	type_to_handle[0].handle = &(p_amb->temp_handles);
	type_to_handle[0].config_handle = &(p_amb->temp_configuration_handles);
	type_to_handle[0].value = (p_amb->temp_value);
	#endif
	
	type_to_handle[1].type = BLE_AMBIENT_PR;
	#if PR_ENABLED
	type_to_handle[1].handle = &(p_amb->pr_handles);
	type_to_handle[1].config_handle = &(p_amb->pr_configuration_handles);
	type_to_handle[1].value = (p_amb->pr_value);
	#endif

	type_to_handle[2].type = BLE_AMBIENT_HUM;
	#if HUM_ENABLED
	type_to_handle[2].handle = &(p_amb->hum_handles);
	type_to_handle[2].config_handle = &(p_amb->hum_configuration_handles);
	type_to_handle[2].value = (p_amb->hum_value);
	#endif	
	
	type_to_handle[3].type = BLE_AMBIENT_LUM;
	#if LUM_ENABLED
	type_to_handle[3].handle = &(p_amb->lum_handles);
	type_to_handle[3].config_handle = &(p_amb->lum_configuration_handles);
	type_to_handle[3].value = (p_amb->lum_value);
	#endif

	type_to_handle[4].type = BLE_AMBIENT_HUMSOLO;
	#if HUMSOLO_ENABLED
	type_to_handle[4].handle = &(p_amb->humsolo_handles);
	type_to_handle[4].config_handle = &(p_amb->humsolo_configuration_handles);
	type_to_handle[4].value = (p_amb->humsolo_value);
	#endif	

	return err_code;											
}