ble_app_hids_keyboard: why send_key_scan_press_release has to loop?

Hi guys. May I ask one firmware code question for ble_app_hids_keyboard_pca10056_s113 project from 17.1.0 nRF5 SDK:

static uint8_t m_caps_on_key_scan_str[] = /**< Key pattern to be sent when the output report has been written with the CAPS LOCK bit set. */
{
    0x06,       /* Key C */
    0x04,       /* Key a */
    0x13,       /* Key p */
    0x16,       /* Key s */
    0x12,       /* Key o */
    0x11,       /* Key n */
};

keys_send(sizeof(m_caps_on_key_scan_str), m_caps_on_key_scan_str);
// this calls send_key_scan_press_release()

static uint32_t send_key_scan_press_release(){
do{
ble_hids_inp_rep_send(); // Send  C a p s o n
}while (offset <= data_len);
}
}

When sending "C a p s o n", this uses a DO-WHILE LOOP. The data becomes:

1. 00 00 06 04 13 16 12 11

2. 00 00 00 04 13 16 12 11

3. 00 00 00 00 13 16 12 11

4. 00 00 00 00 00 16 12 11

5. 00 00 00 00 00 00 12 11

6. 00 00 00 00 00 00 00 11

7. 00 00 00 00 00 00 00 00

As explained in the INFO center https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.1.0/ble_sdk_app_hids_keyboard.html

May I ask why this DO-WHILE loop is needed? Can't we send these two data instead:

1. 00 00 06 04 13 16 12 11

7. 00 00 00 00 00 00 00 00

Skipping the DO-WHILE step 2 to 6? Thank you so much for your help!

  • Hi,

     

    This is the code in the sample:

    static uint32_t send_key_scan_press_release(ble_hids_t * p_hids,
                                                uint8_t    * p_key_pattern,
                                                uint16_t     pattern_len,
                                                uint16_t     pattern_offset,
                                                uint16_t   * p_actual_len)
    {
        ret_code_t err_code;
        uint16_t offset;
        uint16_t data_len;
        uint8_t  data[INPUT_REPORT_KEYS_MAX_LEN];
    
        // HID Report Descriptor enumerates an array of size 6, the pattern hence shall not be any
        // longer than this.
        STATIC_ASSERT((INPUT_REPORT_KEYS_MAX_LEN - 2) == 6);
    
        ASSERT(pattern_len <= (INPUT_REPORT_KEYS_MAX_LEN - 2));
    
        offset   = pattern_offset;
        data_len = pattern_len;
    
        do
        {
            // Reset the data buffer.
            memset(data, 0, sizeof(data));
    
            // Copy the scan code.
            memcpy(data + SCAN_CODE_POS + offset, p_key_pattern + offset, data_len - offset);
    
            if (bsp_button_is_pressed(SHIFT_BUTTON_ID))
            {
                data[MODIFIER_KEY_POS] |= SHIFT_KEY_CODE;
            }
    
            if (!m_in_boot_mode)
            {
                err_code = ble_hids_inp_rep_send(p_hids,
                                                 INPUT_REPORT_KEYS_INDEX,
                                                 INPUT_REPORT_KEYS_MAX_LEN,
                                                 data,
                                                 m_conn_handle);
            }
            else
            {
                err_code = ble_hids_boot_kb_inp_rep_send(p_hids,
                                                         INPUT_REPORT_KEYS_MAX_LEN,
                                                         data,
                                                         m_conn_handle);
            }
    
            if (err_code != NRF_SUCCESS)
            {
                break;
            }
    
            offset++;
        }
        while (offset <= data_len);
    
        *p_actual_len = offset;
    
        return err_code;
    }

     

    This will send one-and-one char, which again is the default use-case when you are using a keyboard as well.

    If you send the data in one payload, it will be like pressing all the buttons at the exact same time. It will then depend on the host implementation on which way you start to parse the data, ie: "Capson" or "nospaC".

     

    Kind regards,

    Håkon

  • Thank you Håkon.

    t will then depend on the host implementation

    Did you mean host = nRF52 firmware application implementation?

    About,

    it will be like pressing all the buttons at the exact same time.

    Did you mean that Do-While loop is related to how the user is releasing the keyboard keys?

    To check my understanding,

    1. 00 00 06 04 13 16 12 11 : Pressed C a p s o n 6 keys

    2. 00 00 00 04 13 16 12 11 : Released C

    3. 00 00 00 00 13 16 12 11 : Released a

    4. 00 00 00 00 00 16 12 11 : Released p

    5. 00 00 00 00 00 00 12 11 : Released s

    6. 00 00 00 00 00 00 00 11 : Released o

    7. 00 00 00 00 00 00 00 00 : Released n, every key

    Like this?

    Compared to this case, may I ask about this the reverse release case (User releases the key from n - o - s - p - a -C)?

    Does it look like this?

    1. 00 00 06 04 13 16 12 11 : Pressed C a p s o n 6 keys

    2. 00 00 06 04 13 16 12 00 : Released n

    3. 00 00 06 04 13 16 00 00 : Released o

    4. 00 00 06 04 13 00 00 00 : Released s

    5. 00 00 06 04 00 00 00 00 : Released p

    6. 00 00 06 00 00 00 00 00 : Released a

    7. 00 00 00 00 00 00 00 00 : Released C, every key

  • Hi,

     

    This is how the enqueue/dequeue works in this example:

     how are keyboard key release events sent in example code? 

    Now, I would strongly recommend that you do not adopt this logic into your own application, because it is more-or-less hardcoded to a specific data format, and if you change your descriptor; this will not work as intended.

     

    Kind regards,

    Håkon

  • Thank you Håkon!

    From that link, in summary of the default keyboard example is

    1. Send_keys

    2. queue a "release key" (all zeros) via function buffer_enqueue()

    3. Softdevice creates BLE_EVT_TX_COMPLETE event

    4. ends the previously enqueued release keys

    Let me check the nRFready Desktop 2 firmware nRF6928-FW for the real keyboard matrix.

    https://www.nordicsemi.com/Products/Reference-designs/nRFready-Desktop-2/Download?lang=en

  • Hi,

     

    Matthew K said:

    1. Send_keys

    2. queue a "release key" (all zeros) via function buffer_enqueue()

    3. Softdevice creates BLE_EVT_TX_COMPLETE event

    4. ends the previously enqueued release keys

    Yes, that is correct.

     

    Matthew K said:

    Let me check the nRFready Desktop 2 firmware nRF6928-FW for the real keyboard matrix.

    https://www.nordicsemi.com/Products/Reference-designs/nRFready-Desktop-2/Download?lang=en

    Just wanted to mention this as well,

    nrf_desktop is also in the application folder of ncs:

    https://github.com/nrfconnect/sdk-nrf/tree/v2.2.0/applications/nrf_desktop

     

    Kind regards,

    Håkon

Related