How to connected severals smartphone HID Keyboard

Good Morning,

I started with example ble_app_hids_keyboard for nrf52840 with nRF5_SDK_17.1.0 and I added uart_init() function to use UARTE0 and I modified uart_event_handle() for received a message "UART_OK" when I received on the rx pin an character, this works quite. My issue I want to connect 2 smartphones with HID Keyboard. 

When I connect me to smarphone 1 the example HID keyboard is OK. But when I disconnect to smartphone "1" and I want to connect to smartphone "2" the nrf52840 is not discoveable and I can't to connect to smartphone "2". The nrf52840 indicates BSP_INDICATE_ADVERTISING_WHITELIST (LED 1 is blinking fast for period 1 sec). For our product in development  with nrf52840 I can to use only UART signals RX(pin 8) / TX (pin 6), I don't have signals buttons 1 and buttons 2 as example:

During advertising or scanning:

  • Button 1: Sleep (if not also in a connection)
  • Button 2 long push: Turn off whitelist.

During sleep:

  • Button 1: Wake up.
  • Button 2: Wake up and delete bond information.

During connection:

  • Button 1 long push: Disconnect.
  • Push and release on all buttons: Application-specific.

the only solution found is after disconnecting from the phone 1 I must during  advertising "LED 1 is blinking fast for period 1 sec" push Button 1 for sleep and during sleep push Button 2 for delete bond information ! I would like to know to make to connect 2 smartphones or other host peripheral (tablet, computer..) witthout clear bond information ?

Can we have a list of multiple hosts in nrf52840 and each host can to connect to nrf52840 ?

To make simple smartphone "1" connected HID Keyboard and I disconnect me and I connect me to the next smartphone in HID Keyboard.

Thank you help 

Alexandre

/**@brief   Function for handling app_uart events.
 *
 * @details This function will receive a single character from the app_uart module and append it to
 *          a string. 
 */
/**@snippet [Handling the data received over UART] */
void uart_event_handle(app_uart_evt_t * p_event)					//$at_06_04_22
{
	uint8_t message[UARTE_MAX_DATA_LEN] = "UART OK";
	uint8_t i;
	
    static uint8_t data_array[UARTE_MAX_DATA_LEN];
    static uint8_t index = 0;
    uint32_t       err_code;
	
    switch (p_event->evt_type)
    {
        case APP_UART_DATA_READY:
            UNUSED_VARIABLE(app_uart_get(&data_array[index]));
			for (i = 0; i < strlen((const char*)message); i++)
			{
				app_uart_put(message[i]);
			}
            break;

        case APP_UART_COMMUNICATION_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_communication);
            break;

        case APP_UART_FIFO_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_code);
            break;

        default:
            break;
    }
}
/**@snippet [Handling the data received over UART] */

/**@brief  Function for initializing the UART module.
 */
/**@snippet [UART Initialization] */
static void uart_init(void)
{
    uint32_t                     err_code;
    app_uart_comm_params_t const comm_params =
    {
        .rx_pin_no    = RX_PIN_NUMBER,
        .tx_pin_no    = TX_PIN_NUMBER,
        .rts_pin_no   = RTS_PIN_NUMBER,
        .cts_pin_no   = CTS_PIN_NUMBER,
        .flow_control = APP_UART_FLOW_CONTROL_DISABLED,
        .use_parity   = false,
#if defined (UART_PRESENT)
        .baud_rate    = NRF_UART_BAUDRATE_115200
#else
        .baud_rate    = NRF_UARTE_BAUDRATE_115200
#endif
    };

    APP_UART_FIFO_INIT(&comm_params,
                       UART_RX_BUF_SIZE,
                       UART_TX_BUF_SIZE,
                       uart_event_handle,
                       APP_IRQ_PRIORITY_LOWEST,
                       err_code);
    APP_ERROR_CHECK(err_code);
}
/**@snippet [UART Initialization] */

/**@brief Function for application main entry.
 */
int main(void)
{
    bool erase_bonds;

    // Initialize.
	uart_init();
    log_init();
    timers_init();
    buttons_leds_init(&erase_bonds);
    power_management_init();
    ble_stack_init();
    scheduler_init();
    gap_params_init();
    gatt_init();
    advertising_init();
    services_init();
    sensor_simulator_init();
    conn_params_init();
    buffer_init();
    peer_manager_init();

    // Start execution.
    NRF_LOG_INFO("HID Keyboard example started.");
    timers_start();
    advertising_start(erase_bonds);

    // Enter main loop.
    for (;;)
    {		
        idle_state_handle();
    }
}

Parents
  • Please find this devzone case that explain how a peripheral device can "switch" between central devices by manipulating the gap address. By changing the gap address the peripheral will appear as a new/different device to the central, so you can for instance switch back and forth between gap addresses to control which central you want to connect to:
    https://devzone.nordicsemi.com/f/nordic-q-a/37369/switching-keyboard-mouse-between-3-paired-devices 

    Also see (this one is likely most useful for you, since it contain an example to switch gap address):
    https://devzone.nordicsemi.com/f/nordic-q-a/57881/store-custom-application-data-using-peer-manager 

    You must call ble_advertising_restart_without_whitelist() to advertise without whitelist. OR you configure advertisment in the advertising_init(), e.g. 

    init.config.ble_adv_whitelist_enabled          = false;

    Best regards,
    Kenneth

  • Good Morning Kenneth,

    thanks for information, I 'm going to see  accurately examples . 

    On the same example HID Keyboard, my application is always power on. I have so put it comment sleep_mode() function into static void on_adv_evt(ble_adv_evt_t ble_adv_evt),  I have the same problem as this post: 

    "LED 1 blinks indicating that it is advertising, and for a few minutes it is visible in nRF Connect. But, after approximately 5 minutes the device is no longer visible. However, the LED continues to blink as though the device is still advertising."

    this is the POST: Completely disabling sleep mode - Nordic Q&A - Nordic DevZone - Nordic DevZone (nordicsemi.com)

    I looked at the following function "advertising_init" but nothing tells me how to set an infinite time with a value of 0 !

    /**@brief Function for initializing the Advertising functionality.
     */
    static void advertising_init(void)
    {
        uint32_t               err_code;
        uint8_t                adv_flags;
        ble_advertising_init_t init;
    
        memset(&init, 0, sizeof(init));
    
        adv_flags                            = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
        init.advdata.name_type               = BLE_ADVDATA_FULL_NAME;
        init.advdata.include_appearance      = true;
        init.advdata.flags                   = adv_flags;
        init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
        init.advdata.uuids_complete.p_uuids  = m_adv_uuids;
    
        init.config.ble_adv_whitelist_enabled          = true;
        init.config.ble_adv_directed_high_duty_enabled = true;
        init.config.ble_adv_directed_enabled           = false;
        init.config.ble_adv_directed_interval          = 0;
        init.config.ble_adv_directed_timeout           = 0;
        init.config.ble_adv_fast_enabled               = true;
        init.config.ble_adv_fast_interval              = APP_ADV_FAST_INTERVAL;
        init.config.ble_adv_fast_timeout               = APP_ADV_FAST_DURATION;
        init.config.ble_adv_slow_enabled               = true;
        init.config.ble_adv_slow_interval              = APP_ADV_SLOW_INTERVAL;
        init.config.ble_adv_slow_timeout               = APP_ADV_SLOW_DURATION;
    
        init.evt_handler   = on_adv_evt;
        init.error_handler = ble_advertising_error_handler;
    
        err_code = ble_advertising_init(&m_advertising, &init);
        APP_ERROR_CHECK(err_code);
    
        ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
    }
    

    For information, I use nRF SDK 17.1.0 and ble_app_hids_keyboard_pca100056_s140

    Thanks 

    Alexandre

Reply
  • Good Morning Kenneth,

    thanks for information, I 'm going to see  accurately examples . 

    On the same example HID Keyboard, my application is always power on. I have so put it comment sleep_mode() function into static void on_adv_evt(ble_adv_evt_t ble_adv_evt),  I have the same problem as this post: 

    "LED 1 blinks indicating that it is advertising, and for a few minutes it is visible in nRF Connect. But, after approximately 5 minutes the device is no longer visible. However, the LED continues to blink as though the device is still advertising."

    this is the POST: Completely disabling sleep mode - Nordic Q&A - Nordic DevZone - Nordic DevZone (nordicsemi.com)

    I looked at the following function "advertising_init" but nothing tells me how to set an infinite time with a value of 0 !

    /**@brief Function for initializing the Advertising functionality.
     */
    static void advertising_init(void)
    {
        uint32_t               err_code;
        uint8_t                adv_flags;
        ble_advertising_init_t init;
    
        memset(&init, 0, sizeof(init));
    
        adv_flags                            = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
        init.advdata.name_type               = BLE_ADVDATA_FULL_NAME;
        init.advdata.include_appearance      = true;
        init.advdata.flags                   = adv_flags;
        init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
        init.advdata.uuids_complete.p_uuids  = m_adv_uuids;
    
        init.config.ble_adv_whitelist_enabled          = true;
        init.config.ble_adv_directed_high_duty_enabled = true;
        init.config.ble_adv_directed_enabled           = false;
        init.config.ble_adv_directed_interval          = 0;
        init.config.ble_adv_directed_timeout           = 0;
        init.config.ble_adv_fast_enabled               = true;
        init.config.ble_adv_fast_interval              = APP_ADV_FAST_INTERVAL;
        init.config.ble_adv_fast_timeout               = APP_ADV_FAST_DURATION;
        init.config.ble_adv_slow_enabled               = true;
        init.config.ble_adv_slow_interval              = APP_ADV_SLOW_INTERVAL;
        init.config.ble_adv_slow_timeout               = APP_ADV_SLOW_DURATION;
    
        init.evt_handler   = on_adv_evt;
        init.error_handler = ble_advertising_error_handler;
    
        err_code = ble_advertising_init(&m_advertising, &init);
        APP_ERROR_CHECK(err_code);
    
        ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
    }
    

    For information, I use nRF SDK 17.1.0 and ble_app_hids_keyboard_pca100056_s140

    Thanks 

    Alexandre

Children
  • The ble_advertising_init() will cycle through advertising as configured by the parameters supplied. The advertisement will throw a callback in on_adv_evt() each time it change mode, and finally when all modes have elapsed it throw the BLE_ADV_EVT_IDLE event in on_adv_evt(). In this case you can either go to sleep or start advertisment again by for instance calling ble_advertising_start() or ble_advertising_restart_without_whitelist().

    Kenneth

Related