Error 13313 on `ble_hids_boot_kb_inp_rep_send` if called within a few seconds of connecting - otherwise works fine

Hello, I've posted a few questions about this project but I keep running into issues - relatively new to this workflow, I guess. It's a modified ble_hids_keyboard example for PCA10056/S140 using custom NRF52840 hardware. The modifications largely involve having any of several active-low buttons, each on a separate GPIO, start a timer which then starts polling all keys at a fixed interval and, after 3 cycles of inactivity, stops polling. Additionally, and also probably relevant to the problem, is one of the keys being designated as a 'function key' which while disconnected/advertising, will restart advertising or, on button-held, delete bonds. It is de-initialized and re-initialized as a normal key with the rest of the keys on connection.

The problem occurs when I press a key after clicking 'Connect' on the host device (Win10 PC in this instance). The error occurs on Line 1451, or adjusted 20 in the block below. However if I wait a couple seconds, after all the peer_manager_handler messages complete, it works without issue. Using RTT Viewer to see these debug messages, by the way.

void switch_polling_handler(void * p_context){
  ret_code_t err_code;
  uint8_t data[] = {0, 0, 0, 0, 0, 0, 0, 0};
  uint64_t current_input = (uint64_t)(NRF_P0->IN) | ((uint64_t)(NRF_P1->IN) << 32);

  if((current_input != last_input) || enc_accum[0] || enc_accum[1]){

    last_input = (uint64_t)(NRF_P0->IN) | ((uint64_t)(NRF_P1->IN) << 32);
    input_to_data(last_input, data);

    if(!m_in_boot_mode){
      err_code = ble_hids_inp_rep_send(&m_hids, INPUT_REPORT_KEYS_INDEX,  INPUT_REPORT_KEYS_MAX_LEN,  data,  m_conn_handle);
      /*for(uint8_t i = 0; i < sizeof(data); i++){
        NRF_LOG_RAW_INFO("%x ", data[i]);
      }
      NRF_LOG_RAW_INFO("\n");*/      
    } else{
       err_code = ble_hids_boot_kb_inp_rep_send(&m_hids, INPUT_REPORT_KEYS_MAX_LEN, data, m_conn_handle);
    }
    APP_ERROR_CHECK(err_code);
  }

  if(poll_counter++ > 2){
    //NRF_LOG_RAW_INFO("  :Poll Stop\n");
    polling = false;
    app_timer_stop(c_switch_polling_timer_id);
  }
}

I try to prevent the keys from doing anything until connected with the following code snippet, but apparently it's still not quite ready to send HID reports, so I suppose my question is... how can I enable the keys such that I know I'm all ready to send HID reports without issue?

static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
    ret_code_t err_code;

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            ble_status = connected;
            stop_blinking_led();
            NRF_LOG_INFO("Connected");
            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
            APP_ERROR_CHECK(err_code);

            // ADDED THIS
            ble_gap_conn_params_t p_conn_params;
            p_conn_params.min_conn_interval = p_ble_evt->evt.gap_evt.params.connected.conn_params.min_conn_interval;
            p_conn_params.max_conn_interval = p_ble_evt->evt.gap_evt.params.connected.conn_params.max_conn_interval;
            p_conn_params.slave_latency     = SLAVE_LATENCY;
            p_conn_params.conn_sup_timeout  = p_ble_evt->evt.gap_evt.params.connected.conn_params.conn_sup_timeout;

            err_code = sd_ble_gap_conn_param_update(m_conn_handle, &p_conn_params);
            APP_ERROR_CHECK(err_code);

            pin_as_function_button(pin_as_func, false);
            for(uint8_t i = 0; i < sizeof(input_pins); i++){
              if(i != KEY_AS_FUNC){   // don't do the normal task/event until connected for this button
                nrf_drv_gpiote_in_event_enable(input_pins[i], true);
              }
            }
            nrf_drv_saadc_sample();     // updates battery level

            break;
            
            ...
            // all key GPIOTE are disabled in the DISCONNECTED state, and the function key returned to 'function' status

When I search Error 13313 on the forums I do find the names of some events that apparently trigger when such a state has been reached, but I had trouble finding them / implementing them in my code. Any help is appreciated, and I can of course post more code snippets, or if helpful, the entire project. Thanks!

Parents Reply Children
  • Hi Kenneth,

    Thanks for the info, that worked great to avoid Error 13313 on normal keys. I've moved the pin_as_function and for loop into pm_evt_handler under that case/event.

    However, I still get Error 13313 when hitting the aforementioned 'function key' too soon. Additionally, hitting any other key too soon results in Error 8 - Invalid State, as seen in the RTT below

    00> <info> peer_manager_handler: Connection secured: role: Peripheral, conn_handle: 0, procedure: Bonding
    00> 
    00> <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Bonding data, action: Update
    00> 
    00> <info> app: New Bond, add the peer to the whitelist if possible
    00> 
    00> <info> app:   m_whitelist_peer_cnt 2, MAX_PEERS_WLIST 8
    00> 
    00> <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update
    00> 
    00> <info> peer_manager_handler: Peer data updated in flash: peer_id<info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Central address resolution, action: Update
    00> 
    00> <error> app: ERROR 8 [NRF_ERROR_INVALID_STATE] at B:\Users\[me]\Documents\NRF52_SDK17.0\nRF5_SDK_17.0.0_9d13099\examples\my_custom_projects\nrf52840_keypad_0\main.c:1454
    00> 
    00> PC at: 0x00031AEF
    00> 
    00> <error> app: End of error report

    Line 1454 is the same place the original error occurred - the APP_ERROR_CHECK after ble_hids_inp_rep_send(). I've attached main.c in case this issue runs deeper than I presume.

    5344.main.zip

  • Invalid state is what you typically get if you try to send a keypress before the link is established, so either ignore or buffer until link is established and encrypted.

    The same applies to any system attribute missing error, either ignore or buffer until link is established and encrypted and try again then.

    Kenneth

  • Kenneth,

    I can add Errors 4 and 13313 as exceptions to the error check, but I have to admit it feels like a bit of a band-aid solution. Even waiting until after PM_EVT_CONN_SEC_SUCCEEDED to send data results in these errors, I have to wonder if there's some register, flag, etc that I could check to confirm the link is 100% established and I'm cleared to send data?

    Otherwise, I'm fine going ahead with this solution - I noticed the hid_keyboard example doesn't actually check the err_code from ble_hids_inp_rep_send(), or at least not that I could see, so my code certainly doesn't need to either.

    Thanks!

Related