Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bt_gatt_notify function does not notify data larger than 20 bytes #52101

Closed
IvanVnucec opened this issue Nov 9, 2022 · 6 comments
Closed

bt_gatt_notify function does not notify data larger than 20 bytes #52101

IvanVnucec opened this issue Nov 9, 2022 · 6 comments

Comments

@IvanVnucec
Copy link

IvanVnucec commented Nov 9, 2022

Describe the bug
I have BLE peripheral device which is trying to notify 20 bytes of data over custom GATT characteristic using bt_gatt_notify function. When there are not any devices connected, bt_gatt_notify function returns -ENOTCONN (-128) error as normal. Once the device is connected, bt_gatt_notify function is returning 0 indicating that the notify was successful. Also, I can clearly see the data being notified with the nrf Connect android app.

However, when I try to send 21 bytes of data (or more), bt_gatt_notify function is returning -ENOTCONN error whether the device is connected or not.

I am using nrf52832 target platform and nRF Connect v2.0.2 SDK.

To Reproduce
Here is the code that I'm working with:

#include <zephyr/types.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/kernel.h>

#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/bluetooth/gatt.h>

static uint8_t ct[256];

static void ct_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
{
	/* TODO: Handle value */
}

static ssize_t read_ct(struct bt_conn *conn, const struct bt_gatt_attr *attr,
		       void *buf, uint16_t len, uint16_t offset)
{
	const char *value = attr->user_data;

	return bt_gatt_attr_read(conn, attr, buf, len, offset, value,
				 sizeof(ct));
}

static ssize_t write_ct(struct bt_conn *conn, const struct bt_gatt_attr *attr,
			const void *buf, uint16_t len, uint16_t offset,
			uint8_t flags)
{
	uint8_t *value = attr->user_data;

	if (offset + len > sizeof(ct)) {
		return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
	}

	memcpy(value + offset, buf, len);

	return len;
}

/* Current Time Service Declaration */
BT_GATT_SERVICE_DEFINE(cts_cvs,
	BT_GATT_PRIMARY_SERVICE(BT_UUID_DECLARE_16(0xdead)),
	BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_16(0xbeef), BT_GATT_CHRC_READ |
			       BT_GATT_CHRC_NOTIFY | BT_GATT_CHRC_WRITE,
			       BT_GATT_PERM_READ | BT_GATT_PERM_WRITE,
			       read_ct, write_ct, ct),
	BT_GATT_CCC(ct_ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
);

static const struct bt_data ad[] = {
	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
	BT_DATA_BYTES(BT_DATA_UUID16_ALL,
		      BT_UUID_16_ENCODE(0xdead)),
};

static void connected(struct bt_conn *conn, uint8_t err)
{
	if (err) {
		printk("Connection failed (err 0x%02x)\n", err);
	} else {
		printk("Connected\n");
	}
}

static void disconnected(struct bt_conn *conn, uint8_t reason)
{
	printk("Disconnected (reason 0x%02x)\n", reason);
}

BT_CONN_CB_DEFINE(conn_callbacks) = {
	.connected = connected,
	.disconnected = disconnected,
};

void cts_notify(void)
{
    static uint8_t len = 1;

    memset(ct, len, len);
    int err = bt_gatt_notify(NULL, &cts_cvs.attrs[1], &ct, len);
    printk("%d %d\n", len, err);
    len++;
}

void main(void)
{
	struct bt_gatt_attr *vnd_ind_attr;
	char str[BT_UUID_STR_LEN];
	int err;

	err = bt_enable(NULL);
	if (err) {
		printk("Bluetooth init failed (err %d)\n", err);
		return;
	}

	err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0);
	if (err) {
		printk("Advertising failed to start (err %d)\n", err);
		return;
	}

	while (1) {
		k_sleep(K_SECONDS(1));

		cts_notify();
	}
}

Expected behavior
The output on the terminal should be as follows:

1 -128
2 -128
3 -128
4 -128
5 -128
6 -128
7 -128
8 -128
9 -128
10 -128
11 -128
12 -128
13 -128
14 -128
# Here we are connected to the peripheral
Updated MTU: TX: 23 RX: 23 bytes
Connected
Connected via connection (0) at 63:BF:8E:00:34:9A (random)
Connection (0) - Initial Tx Power = 0
Connection (0) - Tx Power = 0
15 0
16 0
17 0
18 0
19 0
20 0
21 0
22 0
23 0
24 0
# and so on...

but I'm getting 21 -128, 22 -128 etc. on the console output.

Logs and console output
Current console output (with error):

1 -128
2 -128
3 -128
4 -128
5 -128
6 -128
7 -128
8 -128
9 -128
10 -128
11 -128
12 -128
13 -128
14 -128
# Here we are connected to the peripheral
Updated MTU: TX: 23 RX: 23 bytes
Connected
Connected via connection (0) at 63:BF:8E:00:34:9A (random)
Connection (0) - Initial Tx Power = 0
Connection (0) - Tx Power = 0
15 -128
16 -128
17 -128
18 0
19 0
20 0
21 -128
22 -128
23 -128
24 -128
# and so on...

Environment:

@IvanVnucec IvanVnucec added the bug The issue is a bug, or the PR is fixing a bug label Nov 9, 2022
@IvanVnucec IvanVnucec changed the title bt_gatt_notify function does not notify for data larger than 20 bytes bt_gatt_notify function does not notify data larger than 20 bytes Nov 12, 2022
@nordicjm
Copy link
Collaborator

The error might be wrong, but the failure is expected, you can't notify > 20 bytes unless you use DLE. Try with the latest version of zephyr on main branch and see if you see the same issue, if it does not return that error, then this bug can be closed. If you then try on the latest version of nRF connect SDK and see the issue, please report this to nordic on https://devzone.nordicsemi.com/ not here

@IvanVnucec
Copy link
Author

IvanVnucec commented Nov 14, 2022

The error might be wrong, but the failure is expected, you can't notify > 20 bytes unless you use DLE. Try with the latest version of zephyr on main branch and see if you see the same issue, if it does not return that error, then this bug can be closed. If you then try on the latest version of nRF connect SDK and see the issue, please report this to nordic on https://devzone.nordicsemi.com/ not here

Because I'm not using Zephyr directly but trough the nRF Connect SDK I don't know how to run zephyr on the main branch.
Secondly, I think that somewhere in the function documentation should be written that the function cannot notify > 20 bytes, and that should be reported with the proper error (if it isn't already reported on the main branch).

Can you instruct me how to use DLE feature?

@nordicjm
Copy link
Collaborator

https://docs.zephyrproject.org/latest/develop/getting_started/index.html describes how to get and use zephyr.

Secondly, I think that somewhere in the function documentation should be written that the function cannot notify > 20 bytes

It can, it can't in your example above because you haven't enabled DLE. This is printed in clear text in the output:

Updated MTU: TX: 23 RX: 23 bytes

And this is actually nothing to do with zephyr, this is part of the bluetooth standard.

Can you instruct me how to use DLE feature?

You can look at https://github.com/zephyrproject-rtos/zephyr/blob/main/samples/subsys/mgmt/mcumgr/smp_svr/overlay-bt.conf to see what Kconfig values need to be set

@IvanVnucec
Copy link
Author

You can look at https://github.com/zephyrproject-rtos/zephyr/blob/main/samples/subsys/mgmt/mcumgr/smp_svr/overlay-bt.conf to see what Kconfig values need to be set

Kconfig values in the provided link did not work for me. Also, I've set the following Kconfig values looking at the throughput example:

CONFIG_BT_BUF_ACL_RX_SIZE=502
CONFIG_BT_CONN_TX_MAX=10
CONFIG_BT_L2CAP_TX_BUF_COUNT=10
CONFIG_BT_L2CAP_TX_MTU=498
CONFIG_BT_BUF_ACL_TX_SIZE=502
CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y
CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
CONFIG_BT_USER_DATA_LEN_UPDATE=y
CONFIG_BT_AUTO_DATA_LEN_UPDATE=y
CONFIG_BT_USER_PHY_UPDATE=y
CONFIG_BT_AUTO_PHY_UPDATE=y

and called the bt_conn_le_data_len_update(ble_default_conn, BT_LE_DATA_LEN_PARAM_MAX); function in the connected callback function in order to update BLE data length. The function succeeded but I did not manage to notify data larger than 20 bytes again.

@nordicjm
Copy link
Collaborator

and called the bt_conn_le_data_len_update(ble_default_conn, BT_LE_DATA_LEN_PARAM_MAX); function in the connected callback function in order to update BLE data length. The function succeeded but I did not manage to notify data larger than 20 bytes again.

Then the remote device does not support DLE.

@IvanVnucec
Copy link
Author

IvanVnucec commented Nov 15, 2022

and called the bt_conn_le_data_len_update(ble_default_conn, BT_LE_DATA_LEN_PARAM_MAX); function in the connected callback function in order to update BLE data length. The function succeeded but I did not manage to notify data larger than 20 bytes again.

Then the remote device does not support DLE.

What do you mean by saying remote device? Is it my nRF Connect android app in this scenario?

@laurenmurphyx64 laurenmurphyx64 added the priority: low Low impact/importance bug label Nov 15, 2022
@nordicjm nordicjm removed their assignment Nov 16, 2022
@stephanosio stephanosio removed bug The issue is a bug, or the PR is fixing a bug priority: low Low impact/importance bug labels Nov 22, 2022
@zephyrproject-rtos zephyrproject-rtos locked and limited conversation to collaborators Nov 22, 2022
@stephanosio stephanosio converted this issue into discussion #52475 Nov 22, 2022

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Projects
None yet
Development

No branches or pull requests

4 participants