This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

ble_advdata_encode returns SVC Handler Missing

I have a project that generally operates as a typical peripheral, but occassionally sends advertising packets of type BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED. In the process of broadcasting these non-connectable packets, I have to call ble_advdata_encode. Usually this is not a problem, but sometimes it returns error 0x01 (SVC Handler Missing). When I look at documentation of ble_advdata_encode, it says it should return either NRF_SUCCESS, NRF_ERROR_INVALID_PARAM, or NRF_ERROR_DATA_SIZE. I'm also not picking up on any pattern that this behavior follows. Can anyone enlighten me as to what might cause  ble_advdata_encode to return error 0x01 (SVC Handler Missing)?

SDK: 15.0.0_a53641a

Soft Device: 6.0.0

IDE: Keil uVision5

Parents
  • The root of the problem was in our function for broadcasting arbitrary advertising packets. It turns out that the length value in the advertising data structure in the global ble_gap_adv_data_t structure is updated with every packet to the length of that packet. If a longer packet is broadcast following a shorter packet, an error is returned. The solution was simply to update the length value for every broadcast packet. Here is what we're currently using to broadcast arbitrary advertising packets:

    static ble_gap_adv_data_t m_bcast_data =	//structure that contains a pointer to encoded advertising data and the length of that data
    {
    	.adv_data =
    	{
    			.p_data = m_enc_bcast_data,
    			.len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
    	}
    };	
    
    /**@brief Function for broadcasting advertising packets.
     *
     * @details Provide a pointer to the packet data, provide the length of the data
     *						Function returns true when packet is sent successfully, false if tranmission fails.
     *
     * */
    bool broadcast_packet( uint8_t* data, uint8_t length )
    {
    	bool						success = true;
    	ble_advdata_t               adv_data;
    	ble_gap_adv_params_t		adv_params;
    	ble_advdata_manuf_data_t    mfg_data;
    
    	//clear data structures
    	memset( &adv_data, 0, sizeof(adv_data) );
    	memset( &adv_params, 0, sizeof(adv_params) );
    	memset( &mfg_data, 0, sizeof(mfg_data) );
    	
    	//global m_bcast_data.adv_data.len needs to be reset between packets
    	//when a packet is sent, len is updated to the packet length (truncating any trailing zeros in the packet)
    	//if a longer packet is sent after a shorter packet without updating len, ble_adv_data_enc will return 0x0C -- invalid data size
    	//apparently, len is updated AFTER the size check in ble_adv_data_enc -->> manuf_specific_data_enc
    	m_bcast_data.adv_data.len = BLE_GAP_ADV_SET_DATA_SIZE_MAX;	
    	
    	//check packet length, truncate if too long
    	if( length > BROADCAST_LENGTH_MAX )
    		length = BROADCAST_LENGTH_MAX;
    
    	//configure custom data
    	mfg_data.company_identifier = BROADCAST_COMPANY_ID;
    	mfg_data.data.p_data = data;
    	mfg_data.data.size = length;
    
    	//point advertising data structure to custom data
    	adv_data.p_manuf_specific_data = &mfg_data;
    
    	//encode advertising data in m_bcast_data structure
    	if( ble_advdata_encode( &adv_data, m_bcast_data.adv_data.p_data, &m_bcast_data.adv_data.len ) != NRF_SUCCESS )
    		return !success;
    
    	//set advertising parameters
    	adv_params.primary_phy     = BLE_GAP_PHY_1MBPS;																				
    	adv_params.duration        = 12;																											//Duration, in 10ms units
    	adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;	//Broadcast packets are non-connectable, non-scannable, and undirected
    	adv_params.interval        = 0x30;                                                      //Interval, in 625us units
    
    	//stop any advertisement activity
    	sd_ble_gap_adv_stop( m_adv_handle );
    
    	//configure the packet with specified parameters
    	if( sd_ble_gap_adv_set_configure(&m_adv_handle, &m_bcast_data, &adv_params) != NRF_SUCCESS )
    		return !success;
    
    	//start broadcast
    	if( sd_ble_gap_adv_start( m_adv_handle, APP_BLE_CONN_CFG_TAG ) != NRF_SUCCESS )
    		return !success;
    
    	return success;
    }
    
    /*  We need to return to connectable advertising once the broadcast packet terminates
        Add this to ble_evt_handler:
        
        case BLE_GAP_EVT_ADV_SET_TERMINATED:
    		if( m_conn_handle == BLE_CONN_HANDLE_INVALID )
    		{
    			advertising_init();
    			advertising_start();
    		}
    		break;  */

Reply
  • The root of the problem was in our function for broadcasting arbitrary advertising packets. It turns out that the length value in the advertising data structure in the global ble_gap_adv_data_t structure is updated with every packet to the length of that packet. If a longer packet is broadcast following a shorter packet, an error is returned. The solution was simply to update the length value for every broadcast packet. Here is what we're currently using to broadcast arbitrary advertising packets:

    static ble_gap_adv_data_t m_bcast_data =	//structure that contains a pointer to encoded advertising data and the length of that data
    {
    	.adv_data =
    	{
    			.p_data = m_enc_bcast_data,
    			.len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
    	}
    };	
    
    /**@brief Function for broadcasting advertising packets.
     *
     * @details Provide a pointer to the packet data, provide the length of the data
     *						Function returns true when packet is sent successfully, false if tranmission fails.
     *
     * */
    bool broadcast_packet( uint8_t* data, uint8_t length )
    {
    	bool						success = true;
    	ble_advdata_t               adv_data;
    	ble_gap_adv_params_t		adv_params;
    	ble_advdata_manuf_data_t    mfg_data;
    
    	//clear data structures
    	memset( &adv_data, 0, sizeof(adv_data) );
    	memset( &adv_params, 0, sizeof(adv_params) );
    	memset( &mfg_data, 0, sizeof(mfg_data) );
    	
    	//global m_bcast_data.adv_data.len needs to be reset between packets
    	//when a packet is sent, len is updated to the packet length (truncating any trailing zeros in the packet)
    	//if a longer packet is sent after a shorter packet without updating len, ble_adv_data_enc will return 0x0C -- invalid data size
    	//apparently, len is updated AFTER the size check in ble_adv_data_enc -->> manuf_specific_data_enc
    	m_bcast_data.adv_data.len = BLE_GAP_ADV_SET_DATA_SIZE_MAX;	
    	
    	//check packet length, truncate if too long
    	if( length > BROADCAST_LENGTH_MAX )
    		length = BROADCAST_LENGTH_MAX;
    
    	//configure custom data
    	mfg_data.company_identifier = BROADCAST_COMPANY_ID;
    	mfg_data.data.p_data = data;
    	mfg_data.data.size = length;
    
    	//point advertising data structure to custom data
    	adv_data.p_manuf_specific_data = &mfg_data;
    
    	//encode advertising data in m_bcast_data structure
    	if( ble_advdata_encode( &adv_data, m_bcast_data.adv_data.p_data, &m_bcast_data.adv_data.len ) != NRF_SUCCESS )
    		return !success;
    
    	//set advertising parameters
    	adv_params.primary_phy     = BLE_GAP_PHY_1MBPS;																				
    	adv_params.duration        = 12;																											//Duration, in 10ms units
    	adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;	//Broadcast packets are non-connectable, non-scannable, and undirected
    	adv_params.interval        = 0x30;                                                      //Interval, in 625us units
    
    	//stop any advertisement activity
    	sd_ble_gap_adv_stop( m_adv_handle );
    
    	//configure the packet with specified parameters
    	if( sd_ble_gap_adv_set_configure(&m_adv_handle, &m_bcast_data, &adv_params) != NRF_SUCCESS )
    		return !success;
    
    	//start broadcast
    	if( sd_ble_gap_adv_start( m_adv_handle, APP_BLE_CONN_CFG_TAG ) != NRF_SUCCESS )
    		return !success;
    
    	return success;
    }
    
    /*  We need to return to connectable advertising once the broadcast packet terminates
        Add this to ble_evt_handler:
        
        case BLE_GAP_EVT_ADV_SET_TERMINATED:
    		if( m_conn_handle == BLE_CONN_HANDLE_INVALID )
    		{
    			advertising_init();
    			advertising_start();
    		}
    		break;  */

Children
No Data
Related