This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Negative power value bugs in ble_dtm.c

ble_dtm.c has some bugs related to signed integer representation which prevent negative power (less than 0 dBm) from being requested in the vendor specific message.

  1. First, this bug is not yet patched: devzone.nordicsemi.com/.../44704

  2. In dtm_vendor_specific_pkt() the freq value (now called vendor_option) is passed to dtm_set_txpower() without proper sign extension.

  3. In dtm_set_txpower() the value is converted to int8_t without proper sign extension, taking into account the value is only six bits so the int8_t sign bit will always be 0.

  4. Any attempt to set negative power will therefore fail the "if (new_power8 > 4)" test in dtm_set_txpower().

  5. If these checks are bypassed, m_tx_power is set to an invalid value because of the lack of proper sign extension.

EDIT: Here's an example.

Suppose we are commanding a power of -4 dBm.

In examples/dtm/direct_test_mode/main.c:87,

typedef uint32_t dtm_freq_t;
dtm_freq_t     freq         = (command >> 8) & 0x3F;

Now freq is -4 & 0x3F, or 0x0000003c

in dtm_cmd(), line 537, freq is supplied as the second arg to dtm_vendor_specific_pkt(), which is defined on ble_dtm.c:327:

static uint32_t dtm_vendor_specific_pkt(uint32_t vendor_cmd,
                                        dtm_freq_t vendor_option)

so now vendor_option is 0x0000003c

This is passed directly to dtm_set_txpower(), which is defined in ble_dtm.c:577:

bool dtm_set_txpower(uint32_t new_tx_power)

so new_tx_power is 0x0000003c

on ble_dtm.c:580, new_power8 is defined:

int8_t new_power8 = (int8_t)(new_tx_power & 0xFF);

so new_power8 is now 0x3c. This is a positive value. The sign bit is clear.

0x3c is 60 decimal.

on ble_dtm.c:588, new_power8 is compared to 4. 60 is greater than 4, so false is returned. This false value causes dtm_vendor_specific_pkt() to return DTM_ERROR_ILLEGAL_CONFIGURATION, but this return value is ignored at main.c:169 and vendor specific commands do not set m_event on error, so it doesn't appear on the UART. But the tx_power being set will be the old one.

Related