Skip to content

Commit f3a8e2e

Browse files
samples: bluetooth: hids_keyboard: update button fetaures to match NCS
Update button features to match NCS sample. Work in progress. Signed-off-by: Eivind Jølsgard <[email protected]>
1 parent 149162a commit f3a8e2e

File tree

2 files changed

+112
-30
lines changed

2 files changed

+112
-30
lines changed

samples/bluetooth/ble_hids_keyboard/README.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@ Overview
4040
The sample uses the buttons on a development kit to simulate keys on a keyboard.
4141
One button simulates the letter keys by generating letter keystrokes for a predefined string.
4242
A second button simulates the Shift button and shows how to modify the letter keystrokes.
43-
An LED displays the Caps Lock state, which can be modified by another connected keyboard. (TODO Match this behaviour from NCS sample)
43+
An LED displays the Caps Lock state, which can be modified by another connected keyboard.
4444

45-
This sample exposes the HID GATT Service. It uses a report map for a generic keyboard.
45+
This sample exposes the HID GATT Service.
46+
It uses a report map for a generic keyboard.
4647

4748
User interface
4849
**************

samples/bluetooth/ble_hids_keyboard/src/main.c

Lines changed: 109 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,40 +5,56 @@
55
*/
66

77
#include <stdint.h>
8+
#include <nrf_error.h>
89
#include <nrf_sdh.h>
910
#include <nrf_sdh_ble.h>
1011
#include <nrf_soc.h>
11-
#include <event_scheduler.h>
1212
#include <ble_adv.h>
1313
#include <ble_gap.h>
1414
#include <ble_types.h>
15-
#include <nrf_error.h>
1615
#include <bluetooth/services/common.h>
1716
#include <bluetooth/services/ble_dis.h>
1817
#include <bluetooth/services/ble_hids.h>
18+
#include <event_scheduler.h>
1919
#include <zephyr/toolchain.h>
2020
#include <zephyr/sys/printk.h>
2121
#include <zephyr/logging/log.h>
2222
#include <zephyr/logging/log_ctrl.h>
2323
#include <bm_buttons.h>
24-
24+
#include <hal/nrf_gpio.h>
2525
#include <board-config.h>
2626

2727
LOG_MODULE_REGISTER(app, CONFIG_BLE_HIDS_KEYBOARD_SAMPLE_LOG_LEVEL);
2828

2929
#define BASE_USB_HID_SPEC_VERSION 0x0101
3030

31-
#define INPUT_REPORT_KEYS_INDEX 0 /**< Index of Input Report. */
32-
#define INPUT_REPORT_KEYS_MAX_LEN 8 /**< Maximum length of the Input Report characteristic. */
33-
#define INPUT_REP_REF_ID 0 /**< Id of reference to Keyboard Input Report. */
34-
35-
#define OUTPUT_REPORT_INDEX 0 /**< Index of Output Report. */
36-
#define OUTPUT_REPORT_MAX_LEN 1 /**< Maximum length of the Output Report characteristic. */
37-
#define OUTPUT_REP_REF_ID 0 /**< Id of reference to Keyboard Output Report. */
38-
39-
#define FEATURE_REPORT_INDEX 0 /**< Index of Feature Report. */
40-
#define FEATURE_REPORT_MAX_LEN 2 /**< Maximum length of the Feature Report characteristic. */
41-
#define FEATURE_REP_REF_ID 0 /**< Id of reference to Keyboard Feature Report. */
31+
/* Control key codes - required 8 of them */
32+
#define INPUT_REPORT_KEYS_CTRL_CODE_MIN 224
33+
/* Control key codes - required 8 of them */
34+
#define INPUT_REPORT_KEYS_CTRL_CODE_MAX 231
35+
/* Index of Input Report. */
36+
#define INPUT_REPORT_KEYS_INDEX 0
37+
/* Maximum length of the Input Report characteristic. */
38+
#define INPUT_REPORT_KEYS_MAX_LEN 8
39+
/* Id of reference to Keyboard Input Report. */
40+
#define INPUT_REP_REF_ID 0
41+
42+
/* Index of Output Report. */
43+
#define OUTPUT_REPORT_INDEX 0
44+
/* Maximum length of the Output Report characteristic. */
45+
#define OUTPUT_REPORT_MAX_LEN 1
46+
/* Id of reference to Keyboard Output Report. */
47+
#define OUTPUT_REP_REF_ID 0
48+
/* Index of Feature Report. */
49+
#define FEATURE_REPORT_INDEX 0
50+
/* Maximum length of the Feature Report characteristic. */
51+
#define FEATURE_REPORT_MAX_LEN 2
52+
/* Id of reference to Keyboard Feature Report. */
53+
#define FEATURE_REP_REF_ID 0
54+
/* CAPS LOCK bit in Output Report (based on 'LED Page (0x08)' of the
55+
* Universal Serial Bus HID Usage Tables).
56+
*/
57+
#define OUTPUT_REPORT_BIT_MASK_CAPS_LOCK 0x02
4258

4359
#define BTN_PRESSED 1
4460

@@ -50,6 +66,8 @@ BLE_ADV_DEF(ble_adv);
5066
/* BLE Connection handle */
5167
static uint16_t conn_handle = BLE_CONN_HANDLE_INVALID;
5268

69+
static uint8_t keys_report[INPUT_REPORT_KEYS_MAX_LEN];
70+
5371
static void on_ble_evt(const ble_evt_t *evt, void *ctx)
5472
{
5573
uint32_t nrf_err;
@@ -260,44 +278,105 @@ static uint32_t hids_init(void)
260278
return ble_hids_init(&ble_hids, &hids_config);
261279
}
262280

263-
static int register_key(struct ble_hids *hids, const char key, bool pressed)
281+
static uint8_t button_ctrl_code_get(uint8_t key)
264282
{
265-
uint32_t nrf_err;
266-
uint8_t report[INPUT_REPORT_KEYS_MAX_LEN] = {};
283+
if (INPUT_REPORT_KEYS_CTRL_CODE_MIN <= key && key <= INPUT_REPORT_KEYS_CTRL_CODE_MAX) {
284+
return (uint8_t)(1U << (key - INPUT_REPORT_KEYS_CTRL_CODE_MIN));
285+
}
286+
return 0;
287+
}
288+
289+
290+
static int key_set(struct ble_hids *hids, uint8_t *report, size_t report_size, uint8_t key)
291+
{
292+
uint8_t ctrl_mask = button_ctrl_code_get(key);
293+
294+
if (ctrl_mask) {
295+
report[0] |= ctrl_mask;
296+
return 0;
297+
}
298+
for (size_t i = 0; i < (report_size - 2); ++i) {
299+
if (report[i + 2] == 0) {
300+
report[i + 2] = key;
301+
return 0;
302+
}
303+
}
304+
/* All slots busy */
305+
return -EBUSY;
306+
}
307+
308+
309+
static int key_clear(struct ble_hids *hids, uint8_t *report, size_t report_size, uint8_t key)
310+
{
311+
uint8_t ctrl_mask = button_ctrl_code_get(key);
267312

268-
#define DATA_OFFSET 2
313+
if (ctrl_mask) {
314+
report[0] &= ~ctrl_mask;
315+
return 0;
316+
}
317+
for (size_t i = 0; i < (report_size - 2); ++i) {
318+
if (report[i + 2] == key) {
319+
report[i + 2] = 0;
320+
return 0;
321+
}
322+
}
323+
324+
/* Key not found */
325+
return -EINVAL;
326+
}
327+
328+
static int on_key_press(struct ble_hids *hids, const char key, bool pressed)
329+
{
330+
uint32_t nrf_err;
269331

270332
if (pressed) {
271-
memcpy(report + DATA_OFFSET, &key, sizeof(key));
333+
key_set(hids, keys_report, sizeof(keys_report), key);
334+
} else {
335+
key_clear(hids, keys_report, sizeof(keys_report), key);
272336
}
273337

274-
nrf_err = ble_hids_inp_rep_send(hids, conn_handle, INPUT_REPORT_KEYS_INDEX, &report,
275-
sizeof(report));
276-
if (nrf_err) {
277-
printk("Failed to send input report, nrf_error %#x", nrf_err);
338+
nrf_err = ble_hids_inp_rep_send(hids, conn_handle, INPUT_REPORT_KEYS_INDEX, keys_report,
339+
sizeof(keys_report));
340+
if (nrf_err != NRF_SUCCESS) {
341+
LOG_ERR("Failed to send input report, nrf_error %#x", nrf_err);
278342
}
279343

280344
return 0;
281345
}
282346

283347
static void button_handler(uint8_t pin, uint8_t action)
284348
{
349+
static const char hello_world_str[] = {
350+
0x0b, /* Key h */
351+
0x08, /* Key e */
352+
0x0f, /* Key l */
353+
0x0f, /* Key l */
354+
0x12, /* Key o */
355+
0x28, /* Key Return */
356+
};
357+
static const char *chr = hello_world_str;
358+
285359
if (conn_handle == BLE_CONN_HANDLE_INVALID) {
286360
return;
287361
}
288362

289363
switch (pin) {
290364
case BOARD_PIN_BTN_0:
291-
register_key(&ble_hids, 0x04, action == BTN_PRESSED); /* Key a */
365+
if (action == BTN_PRESSED) {
366+
on_key_press(&ble_hids, *chr, true);
367+
} else {
368+
on_key_press(&ble_hids, *chr, false);
369+
if (++chr == (hello_world_str + sizeof(hello_world_str))) {
370+
chr = hello_world_str;
371+
}
372+
}
292373
break;
293374
case BOARD_PIN_BTN_1:
294-
register_key(&ble_hids, 0x05, action == BTN_PRESSED); /* Key b */
375+
on_key_press(&ble_hids, 0xE1, action == BTN_PRESSED); /* Shift */
295376
break;
296377
case BOARD_PIN_BTN_2:
297-
register_key(&ble_hids, 0x06, action == BTN_PRESSED); /* Key c */
298-
break;
299378
case BOARD_PIN_BTN_3:
300-
register_key(&ble_hids, 0x07, action == BTN_PRESSED); /* Key d */
379+
/* Reserved for pairing */
301380
break;
302381
}
303382
}
@@ -343,6 +422,8 @@ int main(void)
343422
},
344423
};
345424

425+
nrf_gpio_cfg_output(BOARD_PIN_LED_0);
426+
346427
err = bm_buttons_init(configs, ARRAY_SIZE(configs), BM_BUTTONS_DETECTION_DELAY_MIN_US);
347428
if (err) {
348429
printk("Failed to initialize buttons, err %d\n", err);

0 commit comments

Comments
 (0)