Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Standalone L2CAP Example, Since Apple Core Bluetooth doesn't support OTS

Hi

We want to open L2CAP channel to stream data between nRF52840 and iOS, We cant use OTS example since there is no OTS support  from Apple core bluetooth framework.

So we thought to open a raw L2CAP channel on PSM (either hard-coded or from GATT Characteristic) and stream data over that channel.

I looked around many threads and pages to get some path to finish the task. Found one Similar thread and did the below steps

    Modified  OTS Server example to open L2CAP Channel after peer connected, But L2CAP Connection is rejected instantly (due to lack of clarity at example).

   Any help on this is highly appreciated since i could not much information on this topic.

   

Parents
  • Hi,

    What are you using for testing? An iPhone? Did you develop your own app which is reading the L2CAP stream, or are you using some sort of testing app?

    If you can send a sniffer log that would be great. Then we can see what is going on.

    What is the reason you want to use a raw L2CAP channel? With connection event length extension and long MTU, you should be able to get almost same throughput using GATT.

Reply
  • Hi,

    What are you using for testing? An iPhone? Did you develop your own app which is reading the L2CAP stream, or are you using some sort of testing app?

    If you can send a sniffer log that would be great. Then we can see what is going on.

    What is the reason you want to use a raw L2CAP channel? With connection event length extension and long MTU, you should be able to get almost same throughput using GATT.

Children
  • Hello Stian,

    Test scenario iPAD and nRF52840DK

    1. iPAD has custom developed application which reads the psm over gatt characteristic and tries to connect on using that psm.

    2. nRF52840 should setup L2CAP channel as soon as it receives connected event and update the PSM on gatt characteristic.

    Is there any design conflict in our procedure.

    I am initializing the stack with below snippet but app is crashing, i cannot see the error code, since uart is not available.

     To enable L2CAP do i need to create any instance or enable any macro.

    static void ble_stack_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        // Configure the BLE stack using the default settings.
        // Fetch the start address of the application RAM.
        uint32_t ram_start = 0;
        err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(err_code);
    
        
        // Overwrite some of the default configurations for the BLE stack.
        ble_cfg_t ble_cfg;
    
        // Configure the number of custom UUIDS.
        memset(&ble_cfg, 0x00, sizeof(ble_cfg));
        ble_cfg.common_cfg.vs_uuid_cfg.vs_uuid_count = 0;
    
    
        // Set l2cap channel configuration
        ble_cfg.conn_cfg.conn_cfg_tag                        = APP_BLE_CONN_CFG_TAG;
        ble_cfg.conn_cfg.params.l2cap_conn_cfg.rx_mps        = BLE_L2CAP_MPS_MIN;
        ble_cfg.conn_cfg.params.l2cap_conn_cfg.rx_queue_size = 1;
        ble_cfg.conn_cfg.params.l2cap_conn_cfg.tx_mps        = BLE_L2CAP_MPS_MIN;
        ble_cfg.conn_cfg.params.l2cap_conn_cfg.tx_queue_size = 1;
        ble_cfg.conn_cfg.params.l2cap_conn_cfg.ch_count      = BLE_L2CAP_CH_COUNT_MAX;
    
        err_code = sd_ble_cfg_set(BLE_CONN_CFG_L2CAP, &ble_cfg, ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Register a handler for BLE events.
        NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
    }
    

  • So after the connection the nRF52840 needs to setup the L2CAP channel. The procedure is described here:

    https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.s140.api.v6.1.1/group___b_l_e___l2_c_a_p___c_h___s_e_t_u_p___m_s_c.html?cp=3_4_3_1_2_5_3_3

    You can also look at the ble_central OTS example, in the main file in the ots_c_evt_handler you see how the channel is initialized using the sd_ble_l2cap_ch_setup function. It's documented here:

    https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.s140.api.v6.1.1/group___b_l_e___l2_c_a_p___f_u_n_c_t_i_o_n_s.html?cp=3_4_3_1_2_5_2_3#ga69199818fd81b20baf5c7db0656962c9

                ble_l2cap_ch_setup_params_t params;

                params.rx_params.rx_mps = L2CAP_RX_MPS;
                params.rx_params.rx_mtu = L2CAP_RX_MTU;
                params.rx_params.sdu_buf.p_data = NULL;
                params.le_psm = BLE_OTS_PSM;    // Used when requesting setup of an L2CAP channel, ignored otherwise.
                params.status = 0;              // Used when requesting setup of an L2CAP channel, ignored otherwise.

                uint16_t cid  = BLE_L2CAP_CID_INVALID;

                err_code = sd_ble_l2cap_ch_setup(m_ots_c.conn_handle, &cid, &params);
                APP_ERROR_CHECK(err_code);

    You have to make sure that you are responding to the events in the ble_evt_handler according to the flow chart.

    You must also have a way to debug the code. Why can't you use UART? It's integrated into the nRF52840 DK, you just need the UART terminal, like Putty. You should also use the debugging functionality in the IDE you are using, stepping through the code, catching the error codes.

  • Hi Stian,

    It was RAM  SIZE Issue,Now built the L2CAP Feature over ble_app_template (took reference from OTS), i used UART for printing debug messages, Able to  Receive the L2CAP packets from  TAB, assigned methods to all the events of L2CAP. 

    Last time, Issues due to lack of understanding about events and rules of L2CAP.

    1. Currently its speed is 8kbps, rx_mtu is 1000bytes, rx_mtu is 100 bytes.  To use the max possible speed what all parameters needs to be configured.

    2. Documentation says there is no upper limit for MTU i.e. 64KB since type is uint16_t, what about MPU

    3. Are there any other parameters  like connection length, connection size to be configured ?

    Some references and points on increasing the channel speed is highly appreciated.

    Thanks a lot for your   reply

  • The most important parameters are connection interval, GAP event length, and GAP data length.

    The GAP data length tells you how many bytes you can transmit per BLE packet, or the Link Layer PDU. It defaults to 27 bytes. A BLE packet contains lots of overhead data, like access address, LL header, L2CAP header etc. So you should increase this to more than 27 bytes. The maximum supported by the BLE spec is 251 bytes.

    The data length update is performed by using this function: https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.s140.api.v6.1.1/group___b_l_e___g_a_p___f_u_n_c_t_i_o_n_s.html?cp=3_4_3_1_2_1_2_14#gac4a6ef5c106107eb2a1707bb26f3245c

    It needs to be responded to by the peer. The flow chart is here: https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.s140.api.v6.1.1/group___b_l_e___g_a_p___d_a_t_a___l_e_n_g_t_h___u_p_d_a_t_e___p_r_o_c_e_d_u_r_e___m_s_c.html?cp=3_4_3_1_2_1_3_6

    You can also send several packets per connection interval. So the GAP event length is how much time is set aside for transmitting packets within one connection interval. In theory it can be as long as the connection interval.

    This is usually set in the sdk_config.h file and is called NRF_SDH_BLE_GAP_EVENT_LENGTH. Which is then passed to the softdevice when you call the nrf_sdh_ble_default_cfg_set() function.

    The softdevice will continue to transmit packets as long as there is time left within the connection interval.

    The, you have the connection interval. You can set a long connection interval, and send many packets per connection interval, which will probably give you the highest throughput. The drawback is that when you get a packet loss, which happens from time to time, depending on the connection quality, you will have to wait until the next connection interval to re-transmit the packets.

    You can  have a look at the throughput example in the SDK to see how these parameters are tweaked to get the highest throughput:  https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v15.3.0/ble_sdk_app_att_mtu.html?cp=5_1_4_2_1_0

Related