zephyr/tests/bluetooth
Rubin Gerritsen bfc0cdc905 Bluetooth: Conditionally print out HCI error codes as strings
When developing Bluetooth applications, you typically run into
some errors. If you are an experienced Bluetooth developer,
you would typically have an HCI error lookup table in your memory.
Others might not.

This commit utilizes defines CONFIG_BT_DEBUG_HCI_ERR_TO_STR
and utilizes bt_hci_err_to_str() to print out HCI error strings
when enabled to improve the user experience.

Several alternatives where considered. This approach was chosen
as it had the best balance between readability, code size, and
implementation complexity.

The alternatives are listed below as a reference.

1. Macro defined format specifier:

```c
  #define HCI_ERR_FMT "%s"
  #define BT_HCI_ERR_TO_STR(err) (err)
  #define HCI_ERR_FMT "%d"
  #define BT_HCI_ERR_TO_STR(err) bt_hci_err_to_str((err))

LOG_INF("The event contained " HCI_ERR_FMT " as status",
	BT_HCI_ERR_TO_STR(err));
```
Advantage: Space efficient: Code size does not increase
Disadvantage: Code becomes hard to read

2. Format specifier to always include both integer and string:

```c
static inline const char bt_hci_err_to_str(err)
{
	return "";
}

LOG_INF("The event contained %s(0x%02x) as status",
	bt_hci_err_to_str(err), err);
```

Advantage: Simple to use, implement, and read,
Disadvantage: Increases code size when CONFIG_BT_DEBUG_HCI_ERR_TO_STR
is disabled. The compiler seems unable to optimize away the unused
format specifier. Note: The size increase is only present when
logging is enabled.

3. Always print as string, allocate a stack variable when printing:

```c
const char *bt_hci_err_to_str(char *dst, size_t dst_size, uint8_t err)
{
  snprintf(dst, dst_size, 0x%02x, err);
  return dst;
}

LOG_INF("The event contained %s as status", BT_HCI_ERR_TO_STR(err));
```

Advantage: Very easy to read.
Disadvantage: Printing error codes becomes slow as it involves calling
snprint.

4. Implement a custom printf specifier, for example E.

   This requires a global CONFIG_ERR_AS_STR as I assume we cannot have
   one specifier for each type of error code.
   Also, I assume we cannot start adding specifiers for each subsystem.

```c
  #define BT_HCI_ERR_TO_STR(err) (err)
  #define BT_HCI_ERR_TO_STR(err) bt_hci_err_to_str((err))

LOG_INF("The event contained %E as status", BT_HCI_ERR_TO_STR(err));
```

Advantage: Both efficient code and readable code.
Disadvantage: This requires a global CONFIG_ERR_AS_STR as I assume
we cannot have one specifier for each type of error code.
Also, I assume we cannot start adding specifiers for each subsystem.
That is, this approach is hard to implement correctly in a scalable
way.

Signed-off-by: Rubin Gerritsen <rubin.gerritsen@nordicsemi.no>
2024-07-30 18:25:56 +01:00
..
addr
adv
at
audio tests: Bluetooth: Audio: Move role specific mocks files 2024-07-30 18:25:47 +01:00
bluetooth
bt_crypto
bt_crypto_ccm
common/testlib
controller
ctrl_isoal
ctrl_sw_privacy
ctrl_sw_privacy_unit
ctrl_user_ext
df everywhere: replace double words 2024-06-25 06:05:35 -04:00
gatt Bluetooth: Mark bt_<type>_err_to_str() APIs experimental 2024-07-11 13:11:59 -04:00
hci Bluetooth: Conditionally print out HCI error codes as strings 2024-07-30 18:25:56 +01:00
hci_codecs_info tests: bluetooth: fix missing net_buf_ref(rsp) 2024-06-24 14:26:22 +02:00
hci_prop_evt
hci_uart_async everywhere: reindent `.overlay` files with tabs 2024-06-26 15:59:44 +02:00
host everywhere: replace double words 2024-06-22 05:40:22 -04:00
host_long_adv_recv Bluetooth: Host: Discard advertising data if not explicit scanning 2024-07-27 15:12:39 +03:00
init
l2cap
ll_settings
mesh bluetooth: remove CONFIG_BT_DEBUG_LOG 2024-06-18 14:33:58 -04:00
mesh_shell
qualification test: bluetooth: Correct profile names MBT and DFU 2024-07-11 16:15:10 +02:00
shell Bluetooth: shell: Enable sysbuild for nRF5340 2024-07-27 20:51:10 +03:00
smp Bluetooth: Mark bt_<type>_err_to_str() APIs experimental 2024-07-11 13:11:59 -04:00
tester tests: bluetooth: tester: Fix zero length array in middle of struct 2024-07-27 20:51:30 +03:00
uuid