<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Peripheral is connected to two Centrals, each with two Gatt Services, occurred mtu exchange fail.</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/114653/peripheral-is-connected-to-two-centrals-each-with-two-gatt-services-occurred-mtu-exchange-fail</link><description>Hello, 
 I am using three nrf52840 DKs to test sending gatt notify data. They are one peripheral and two central. 
 When they each have only one Gatt Customer Service, peripheral can connect to both centrals at the same time and successfully send gatt</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Tue, 01 Oct 2024 06:56:56 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/114653/peripheral-is-connected-to-two-centrals-each-with-two-gatt-services-occurred-mtu-exchange-fail" /><item><title>RE: Peripheral is connected to two Centrals, each with two Gatt Services, occurred mtu exchange fail.</title><link>https://devzone.nordicsemi.com/thread/504466?ContentTypeID=1</link><pubDate>Tue, 01 Oct 2024 06:56:56 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:7d6a376e-b2c7-42be-9773-99d522624d79</guid><dc:creator>LandyWang</dc:creator><description>&lt;p&gt;Thank you for your assistance.&lt;/p&gt;
&lt;p&gt;I tried increasing buffer and stack size, it helped.&lt;/p&gt;
&lt;p&gt;Now I can successfully connect to two centrals with two Gatt Services.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Peripheral is connected to two Centrals, each with two Gatt Services, occurred mtu exchange fail.</title><link>https://devzone.nordicsemi.com/thread/504301?ContentTypeID=1</link><pubDate>Mon, 30 Sep 2024 08:59:29 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:85558f67-3363-482a-b4f0-8484544af831</guid><dc:creator>Einar Thorsrud</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;Which sample in which SDK version have you based your peiheral application on? Can you share a full diff?&lt;/p&gt;
&lt;p&gt;The errors you get essentially tell us that there are no buffers available, and at the same time you get a timeout on the central side. Can you try to incrase some buffer and stack sizses and see if htat helps? For instance, try something like this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
CONFIG_BT_CONN_TX_MAX=10&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Does that improve things?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Peripheral is connected to two Centrals, each with two Gatt Services, occurred mtu exchange fail.</title><link>https://devzone.nordicsemi.com/thread/503856?ContentTypeID=1</link><pubDate>Thu, 26 Sep 2024 01:32:34 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:709d23b1-4838-4b44-8a1e-ccfe9cc7d565</guid><dc:creator>LandyWang</dc:creator><description>&lt;p&gt;As shown in the code snippet above, after the peripheral side connected to the central, I performed bt_gatt_exchange_mtu and bt_gatt_discover and then started transmitting data directly without doing any other processing on the connection. Both connections are handled this way.&lt;/p&gt;
&lt;p&gt;Here is a more detailed snippet of my code. Other than that, I don&amp;#39;t do anything else in the peripheral.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;BT_GATT_SERVICE_DEFINE(test_svc,
	BT_GATT_PRIMARY_SERVICE(&amp;amp;test_uuid),
	BT_GATT_CHARACTERISTIC(&amp;amp;test_chrc_uuid.uuid, 
		BT_GATT_CHRC_WRITE_WITHOUT_RESP |BT_GATT_CHRC_NOTIFY,
		BT_GATT_PERM_WRITE,
		NULL, write_test, NULL),
	BT_GATT_CCC(vnd_ccc_cfg_changed, BT_GATT_PERM_WRITE), //2
);
BT_GATT_SERVICE_DEFINE(test_svc_2,
	BT_GATT_PRIMARY_SERVICE(&amp;amp;test_uuid_2),
	BT_GATT_CHARACTERISTIC(&amp;amp;test_chrc_uuid_2.uuid, 
		BT_GATT_CHRC_WRITE_WITHOUT_RESP |BT_GATT_CHRC_NOTIFY,
		BT_GATT_PERM_WRITE,
		NULL, write_test, NULL),
	BT_GATT_CCC(vnd_ccc_cfg_changed, BT_GATT_PERM_WRITE), //2
);

static void vnd_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
{
	ARG_UNUSED(attr);

	bool notif_enabled = (value == BT_GATT_CCC_NOTIFY);

	LOG_INF(&amp;quot;notifications %s&amp;quot;, notif_enabled ? &amp;quot;enabled&amp;quot; : &amp;quot;disabled&amp;quot;);
}

static void exchange_func(struct bt_conn *conn, uint8_t err, struct bt_gatt_exchange_params *params)
{
	if (!err) {
		LOG_INF(&amp;quot;MTU exchange done\n&amp;quot;);
	} else {
		LOG_INF(&amp;quot;MTU exchange failed (err %&amp;quot; PRIu8 &amp;quot;)\n&amp;quot;, err);
	}
}

static uint8_t notify_func(struct bt_conn *conn,
		struct bt_gatt_subscribe_params *params,
		const void *data, uint16_t length)
{
	uint8_t value[200];
	memcpy(value,data,length);
	if (!data) {
		LOG_INF(&amp;quot;[UNSUBSCRIBED]\n&amp;quot;);
		connected_flag = 0;
		return BT_GATT_ITER_STOP;
	}
	LOG_INF(&amp;quot;[NOTIFICATION] data %x %x length %u\n&amp;quot;, value[0],value[1], length);
	connected_flag = 1;
	return BT_GATT_ITER_CONTINUE;
}

static uint8_t discover_func(struct bt_conn *conn, const struct bt_gatt_attr *attr,
			     struct bt_gatt_discover_params *params)
{
    int err;
    if (!attr) {
		LOG_INF(&amp;quot;Discover complete&amp;quot;);
		(void)memset(params, 0, sizeof(*params));
		return BT_GATT_ITER_STOP;
	}
    LOG_INF(&amp;quot;[ATTRIBUTE] handle %u&amp;quot;, attr-&amp;gt;handle);
    if (!bt_uuid_cmp(discover_params.uuid, &amp;amp;test_uuid.uuid)) {
		memcpy(&amp;amp;uuid, &amp;amp;test_chrc_uuid.uuid, sizeof(uuid));
		discover_params.uuid = &amp;amp;uuid.uuid;
		discover_params.start_handle = attr-&amp;gt;handle + 1;
		discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;

		err = bt_gatt_discover(conn, &amp;amp;discover_params);
		LOG_INF(&amp;quot;Discover Service&amp;quot;);
		if (err) {
			LOG_INF(&amp;quot;Discover failed (err %d)\n&amp;quot;, err);
		}
	} else if (!bt_uuid_cmp(discover_params.uuid,&amp;amp;test_chrc_uuid.uuid)) {
		memcpy(&amp;amp;uuid, BT_UUID_GATT_CCC, sizeof(uuid));
		discover_params.uuid = &amp;amp;uuid.uuid;
		discover_params.start_handle = attr-&amp;gt;handle + 2;
		discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
		subscribe_params.value_handle = bt_gatt_attr_value_handle(attr);
		err = bt_gatt_discover(conn, &amp;amp;discover_params);
		LOG_INF(&amp;quot;Discover Character&amp;quot;);
		if (err) {
			LOG_INF(&amp;quot;Discover failed (err %d)\n&amp;quot;, err);
		}
	} else if (bt_uuid_cmp(discover_params.uuid, &amp;amp;test_chrc_uuid.uuid)){
		subscribe_params.notify = notify_func;
		subscribe_params.value = BT_GATT_CCC_NOTIFY;
		subscribe_params.ccc_handle = attr-&amp;gt;handle;
		err = bt_gatt_subscribe(conn, &amp;amp;subscribe_params);
		if (err &amp;amp;&amp;amp; err != -EALREADY) {
			LOG_INF(&amp;quot;Subscribe failed (err %d)\n&amp;quot;, err);
		} else {
			LOG_INF(&amp;quot;[SUBSCRIBED]\n&amp;quot;);
		}
	}
	return BT_GATT_ITER_STOP;
}

static uint8_t discover_func_2(struct bt_conn *conn, const struct bt_gatt_attr *attr,
			     struct bt_gatt_discover_params *params)
{
    int err;
    if (!attr) {
		LOG_INF(&amp;quot;Discover complete&amp;quot;);
		(void)memset(params, 0, sizeof(*params));
		return BT_GATT_ITER_STOP;
	}
    LOG_INF(&amp;quot;[ATTRIBUTE] handle %u&amp;quot;, attr-&amp;gt;handle);
    if (!bt_uuid_cmp(discover_params_2.uuid, &amp;amp;test_uuid_2.uuid)) {
		memcpy(&amp;amp;uuid_2, &amp;amp;test_chrc_uuid_2.uuid, sizeof(uuid_2));
		discover_params_2.uuid = &amp;amp;uuid_2.uuid;
		discover_params_2.start_handle = attr-&amp;gt;handle + 1;
		discover_params_2.type = BT_GATT_DISCOVER_CHARACTERISTIC;

		err = bt_gatt_discover(conn, &amp;amp;discover_params_2);
		LOG_INF(&amp;quot;Discover Service&amp;quot;);
		if (err) {
			LOG_INF(&amp;quot;Discover failed (err %d)\n&amp;quot;, err);
		}
	} else if (!bt_uuid_cmp(discover_params_2.uuid,&amp;amp;test_chrc_uuid_2.uuid)) {
		memcpy(&amp;amp;uuid_2, BT_UUID_GATT_CCC, sizeof(uuid_2));
		discover_params_2.uuid = &amp;amp;uuid_2.uuid;
		discover_params_2.start_handle = attr-&amp;gt;handle + 2;
		discover_params_2.type = BT_GATT_DISCOVER_DESCRIPTOR;
		subscribe_params_2.value_handle = bt_gatt_attr_value_handle(attr);

		err = bt_gatt_discover(conn, &amp;amp;discover_params_2);
		LOG_INF(&amp;quot;Discover Character&amp;quot;);
		if (err) {
			LOG_INF(&amp;quot;Discover failed (err %d)\n&amp;quot;, err);
		}
	} else if (bt_uuid_cmp(discover_params_2.uuid, &amp;amp;test_chrc_uuid_2.uuid)){
		subscribe_params_2.notify = notify_func;
		subscribe_params_2.value = BT_GATT_CCC_NOTIFY;
		subscribe_params_2.ccc_handle = attr-&amp;gt;handle;
		err = bt_gatt_subscribe(conn, &amp;amp;subscribe_params_2);
		if (err &amp;amp;&amp;amp; err != -EALREADY) {
			LOG_INF(&amp;quot;Subscribe failed (err %d)\n&amp;quot;, err);
		} else {
			LOG_INF(&amp;quot;[SUBSCRIBED]\n&amp;quot;);
			connected_flag = 1;
		}
	}
	return BT_GATT_ITER_STOP;
}

void connected(struct bt_conn *conn, uint8_t err)
{
	connected_count++;
	if(connected_count == 1){
		app_conn1 = conn;
	}else if(connected_count == 2){
		app_conn2 = conn;
	}
	char addr[BT_ADDR_LE_STR_LEN];
	static struct bt_gatt_exchange_params exchange_params;

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	if (err != 0) {
		LOG_INF(&amp;quot;Failed to connect to %s (%u)&amp;quot;, addr, err);
		return;
	}
	connected_flag = 1;
	exchange_params.func = exchange_func;
	err = bt_gatt_exchange_mtu(conn, &amp;amp;exchange_params);
	if (err) {
		LOG_INF(&amp;quot;MTU exchange failed (err %d)&amp;quot;, err);
	}
	memcpy(&amp;amp;uuid, &amp;amp;test_uuid.uuid, sizeof(uuid));
	discover_params.uuid = &amp;amp;uuid.uuid;
    discover_params.func = discover_func;
	discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
	discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
	discover_params.type = BT_GATT_DISCOVER_PRIMARY;
    err = bt_gatt_discover(conn,&amp;amp;discover_params);
	if (err) {
		LOG_ERR(&amp;quot;Discover failed(err %d)\n&amp;quot;, err);
		return;
	}
#if CONFIG_TWO_GATT_SERVICE
	memcpy(&amp;amp;uuid_2, &amp;amp;test_uuid_2.uuid, sizeof(uuid_2));
	discover_params_2.uuid = &amp;amp;uuid_2.uuid;
    discover_params_2.func = discover_func_2;
	discover_params_2.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
	discover_params_2.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
	discover_params_2.type = BT_GATT_DISCOVER_PRIMARY;
    err = bt_gatt_discover(conn,&amp;amp;discover_params_2);
	if (err) {
		LOG_ERR(&amp;quot;Discover failed(err %d)\n&amp;quot;, err);
		return;
	}
#endif
}
void disconnected(struct bt_conn *conn, uint8_t reason)
{
	LOG_INF(&amp;quot;disconnected reason:%d&amp;quot;,reason);
	le_app_advertising();
	connected_flag = 0;
	connected_count--;
}
static struct bt_conn_cb conn_callbacks = {
	.connected = connected,
	.disconnected = disconnected,
};

/* Start advertising for app */
void le_app_advertising(void)
{
    int ret;
    ret = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad),
			      sd, ARRAY_SIZE(sd));
	if (ret) {
		LOG_ERR(&amp;quot;Advertising failed to start (err %d)&amp;quot;, ret);
	}
}

void app_initial(void){
    bt_conn_cb_register(&amp;amp;conn_callbacks);
    le_app_advertising();
}

static void send_data(void){
	int ret;
	if(connected_count == 1){
		ret = bt_gatt_notify(app_conn1, &amp;amp;test_svc.attrs[1], &amp;amp;info, 240);
		ret = bt_gatt_notify(app_conn1, &amp;amp;test_svc_2.attrs[1], &amp;amp;info, 240);
	}else if(connected_count == 2){
		ret = bt_gatt_notify(app_conn1, &amp;amp;test_svc.attrs[1], &amp;amp;info, 240);
		ret = bt_gatt_notify(app_conn1, &amp;amp;test_svc_2.attrs[1], &amp;amp;info, 240);
		ret = bt_gatt_notify(app_conn2, &amp;amp;test_svc.attrs[1], &amp;amp;info, 240);
		ret = bt_gatt_notify(app_conn2, &amp;amp;test_svc_2.attrs[1], &amp;amp;info, 240);
	}
}

static void my_check_handler(struct k_work *work);
K_WORK_DEFINE(my_check, my_check_handler);
struct k_timer my_timer;
static void my_timer_handler(struct k_timer *dummy)
{
	k_work_submit(&amp;amp;my_check);
}
K_TIMER_DEFINE(my_timer,my_timer_handler,NULL);

static void my_check_handler(struct k_work *work){
	if(connected_flag){
		send_data();
	}
}

int main(void)
{
	const struct device *hs_dev;
	int ret;

	ret = bt_enable(NULL);
	if (ret) {
	    LOG_ERR(&amp;quot;bt enable error %d&amp;quot;,ret);
	}
    if (IS_ENABLED(CONFIG_SETTINGS)) {
		settings_load();
	}
    app_initial();
	connected_flag = 0;

	k_timer_start(&amp;amp;my_timer, K_MSEC(2000), K_MSEC(7.5)); //wang20240903 temp pass(den&amp;#39;t send ble data)

	return 0;
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In addition to bt_gatt_exchange_mtu and bt_gatt_discover, does peripheral need to do other processing on the connections when connecting?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Peripheral is connected to two Centrals, each with two Gatt Services, occurred mtu exchange fail.</title><link>https://devzone.nordicsemi.com/thread/503730?ContentTypeID=1</link><pubDate>Wed, 25 Sep 2024 10:57:24 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:10e3b9a7-2eb9-465f-a1fd-34178ff28a5d</guid><dc:creator>Einar Thorsrud</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;-12 is -ENOMEM and that can be returned from GATT APIs in several situations. But generally you can solve it by waiting a bit and trying again (&amp;quot;ATT request queue is full and blocking would cause deadlock.&amp;quot;).&lt;/p&gt;
&lt;p&gt;That said, I wonder if you&amp;nbsp;can share more of your code so that I understand what you are doing? In these code snippets I do not see that you have any handling of the two connections (or how you handle it) . That will requiere quite a bit as the examples are based on a single connection. (Multi peripheral role is not common so there is unfortunately no example of it that I can point to).&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Peripheral is connected to two Centrals, each with two Gatt Services, occurred mtu exchange fail.</title><link>https://devzone.nordicsemi.com/thread/502858?ContentTypeID=1</link><pubDate>Wed, 18 Sep 2024 06:25:48 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c9fd8c63-4c89-4417-a1d9-5094a40b680d</guid><dc:creator>LandyWang</dc:creator><description>&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;Here are the logs of each of the three devices when the peripheral is connected to the first central and transmits data stably, and the second central is powered on and connected.&lt;/p&gt;
&lt;p&gt;The peripheral:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;[00:00:55.102,142] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 2 return:0
[00:00:55.109,039] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 1 return:0
[00:00:55.109,130] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 2 return:0
[00:00:55.116,058] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 1 return:0
[00:00:55.116,149] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 2 return:0
[00:00:55.123,107] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 1 return:0
[00:00:55.123,199] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 2 return:0
[00:00:55.130,096] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 1 return:0
[00:00:55.130,218] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 2 return:0
[00:00:55.137,115] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 1 return:0
[00:00:55.137,207] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 2 return:0
[00:00:55.144,226] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 1 return:0
[00:00:55.144,317] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 2 return:0
[00:00:55.151,123] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 1 return:0
[00:00:55.151,184] &amp;lt;wrn&amp;gt; bt_att: Unable to allocate ATT TX meta
[00:00:55.151,184] &amp;lt;wrn&amp;gt; bt_gatt: No buffer available to send notification
[00:00:55.151,214] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 2 return:-12
[00:00:55.157,348] &amp;lt;inf&amp;gt; main: connected
[00:00:55.157,440] &amp;lt;inf&amp;gt; main: Connected to DD:09:1C:C5:87:68 (random)
[00:00:55.158,416] &amp;lt;wrn&amp;gt; bt_att: Unable to allocate ATT TX meta
[00:00:55.158,447] &amp;lt;wrn&amp;gt; bt_gatt: No buffer available to send notification
[00:00:55.158,447] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 1 return:-12
[00:00:55.158,477] &amp;lt;wrn&amp;gt; bt_att: Unable to allocate ATT TX meta
[00:00:55.158,508] &amp;lt;wrn&amp;gt; bt_gatt: No buffer available to send notification
[00:00:55.158,538] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 2 return:-12
[00:00:55.158,538] &amp;lt;wrn&amp;gt; bt_att: No ATT channel for MTU 243
[00:00:55.158,569] &amp;lt;wrn&amp;gt; bt_gatt: No buffer available to send notification
[00:00:55.158,599] &amp;lt;inf&amp;gt; main: Connection 2 Gatt Notify Service 1 return:-12
[00:00:55.158,630] &amp;lt;wrn&amp;gt; bt_att: No ATT channel for MTU 243
[00:00:55.158,630] &amp;lt;wrn&amp;gt; bt_gatt: No buffer available to send notification
[00:00:55.158,630] &amp;lt;inf&amp;gt; main: Connection 2 Gatt Notify Service 2 return:-12
[00:00:55.165,100] &amp;lt;wrn&amp;gt; bt_att: Unable to allocate ATT TX meta
[00:00:55.165,100] &amp;lt;wrn&amp;gt; bt_gatt: No buffer available to send notification
[00:00:55.165,130] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 1 return:-12
[00:00:55.165,161] &amp;lt;wrn&amp;gt; bt_att: Unable to allocate ATT TX meta
[00:00:55.165,191] &amp;lt;wrn&amp;gt; bt_gatt: No buffer available to send notification
[00:00:55.165,191] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 2 return:-12
[00:00:55.165,222] &amp;lt;wrn&amp;gt; bt_att: No ATT channel for MTU 243
[00:00:55.165,252] &amp;lt;wrn&amp;gt; bt_gatt: No buffer available to send notification
[00:00:55.165,252] &amp;lt;inf&amp;gt; main: Connection 2 Gatt Notify Service 1 return:-12
[00:00:55.165,283] &amp;lt;wrn&amp;gt; bt_att: No ATT channel for MTU 243
[00:00:55.165,283] &amp;lt;wrn&amp;gt; bt_gatt: No buffer available to send notification
[00:00:55.165,313] &amp;lt;inf&amp;gt; main: Connection 2 Gatt Notify Service 2 return:-12
[00:00:55.172,119] &amp;lt;wrn&amp;gt; bt_att: Unable to allocate ATT TX meta
[00:00:55.172,149] &amp;lt;wrn&amp;gt; bt_gatt: No buffer available to send notification
[00:00:55.172,149] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 1 return:-12
[00:00:55.172,180] &amp;lt;wrn&amp;gt; bt_att: Unable to allocate ATT TX meta
[00:00:55.172,210] &amp;lt;wrn&amp;gt; bt_gatt: No buffer available to send notification
[00:00:55.172,210] &amp;lt;inf&amp;gt; main: Connection 1 Gatt Notify Service 2 return:-12
[00:00:55.172,241] &amp;lt;wrn&amp;gt; bt_att: No ATT channel for MTU 243
[00:00:55.172,271] &amp;lt;wrn&amp;gt; bt_gatt: No buffer available to send notification
[00:00:55.172,271] &amp;lt;inf&amp;gt; main: Connection 2 Gatt Notify Service 1 return:-12
[00:00:55.172,302] &amp;lt;wrn&amp;gt; bt_att: No ATT channel for MTU 243
[00:00:55.172,302] &amp;lt;wrn&amp;gt; bt_gatt: No buffer available to send notification
[00:00:55.172,332] &amp;lt;inf&amp;gt; main: Connection 2 Gatt Notify Service 2 return:-12&lt;/pre&gt;&lt;/p&gt;
[quote userid="121867" url="~/f/nordic-q-a/114653/peripheral-is-connected-to-two-centrals-each-with-two-gatt-services-occurred-mtu-exchange-fail/502453"]At this time, peripheral does not output any special message.[/quote]
&lt;p&gt;Sorry I said it wrong here.&amp;nbsp;When the second central connection was made, the peripheral had an &amp;quot;Unable to allocate ATT TX meta&amp;quot; error and could no longer successfully send any data.&lt;/p&gt;
&lt;p&gt;The central 1(The first connected device):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;[00:01:31.220,916] &amp;lt;inf&amp;gt; central_test: connected
[00:01:31.221,008] &amp;lt;inf&amp;gt; central_test: Connected to C3:1B:EF:44:AA:E6 (random)
[00:01:35.222,564] &amp;lt;inf&amp;gt; central_test: MTU exchange done

[00:01:40.222,656] &amp;lt;inf&amp;gt; central_test: [ATTRIBUTE] Service 1 handle 16
[00:01:40.222,839] &amp;lt;inf&amp;gt; central_test: Discover Service
[0
[00:00:09.227,386] &amp;lt;inf&amp;gt; central_test: Discover Service
[00:00:11.227,233] &amp;lt;inf&amp;gt; central_test: [ATTRIBUTE] Service 2 handle 20
[00:00:11.227,325] &amp;lt;inf&amp;gt; central_test: Discover Service
[00:00:12.229,949] &amp;lt;inf&amp;gt; central_test: [ATTRIBUTE] Service 1 handle 17
[00:00:12.230,041] &amp;lt;inf&amp;gt; central_test: Discover Character
[00:00:15.228,424] &amp;lt;inf&amp;gt; central_test: [ATTRIBUTE] Service 2 handle 21
[00:00:15.228,515] &amp;lt;inf&amp;gt; central_test: Discover Character
[00:00:16.229,827] &amp;lt;inf&amp;gt; central_test: [ATTRIBUTE] Service 1 handle 19
[00:00:16.229,919] &amp;lt;inf&amp;gt; central_test: [SUBSCRIBED]

[00:00:17.228,057] &amp;lt;inf&amp;gt; central_test: [NOTIFICATION] Service 1 data ff ff length 240

[00:00:17.229,766] &amp;lt;inf&amp;gt; central_test: [ATTRIBUTE] Service 2 handle 23
[00:00:17.229,888] &amp;lt;inf&amp;gt; central_test: [SUBSCRIBED]

[00:00:18.228,057] &amp;lt;inf&amp;gt; central_test: [NOTIFICATION] Service 1 data ff ff length 240

[00:00:18.229,309] &amp;lt;inf&amp;gt; central_test: [NOTIFICATION] Service 2 data ff ff length 240

[00:00:19.228,057] &amp;lt;inf&amp;gt; central_test: [NOTIFICATION] Service 1 data ff ff length 240

[00:00:19.229,309] &amp;lt;inf&amp;gt; central_test: [NOTIFICATION] Service 2 data ff ff length 240

[00:00:19.235,382] &amp;lt;inf&amp;gt; central_test: [NOTIFICATION] Service 1 data ff ff length 240

[00:00:19.236,816] &amp;lt;inf&amp;gt; central_test: [NOTIFICATION] Service 2 data ff ff length 240

[00:00:19.242,889] &amp;lt;inf&amp;gt; central_test: [NOTIFICATION] Service 1 data ff ff length 240

[00:00:19.244,323] &amp;lt;inf&amp;gt; central_test: [NOTIFICATION] Service 2 data ff ff length 240&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;It stopped outputting logs when the second central is connected to the peripheral.&lt;/p&gt;
&lt;p&gt;Now I think it stopped outputting logs because it didn&amp;#39;t receive data rather than &amp;quot;crashes&amp;quot;.&lt;/p&gt;
&lt;p&gt;The central 2(&lt;span&gt;The&amp;nbsp;second connected device&lt;/span&gt;):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;[00:00:30.148,956] &amp;lt;err&amp;gt; bt_att: ATT Timeout for device C3:1B:EF:44:AA:E6 (random)
[00:00:30.149,017] &amp;lt;inf&amp;gt; central_test: MTU exchange failed (err 14)

[00:00:30.149,017] &amp;lt;inf&amp;gt; central_test: Discover complete
[00:00:30.149,047] &amp;lt;inf&amp;gt; central_test: Discover complete&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;It&amp;nbsp;seems that an exchange error occurred while connecting.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The peripheral and central do the same thing when connected. The following is the code.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;void connected(struct bt_conn *conn, uint8_t err)
{
	LOG_INF(&amp;quot;connected&amp;quot;);
	connected_count++;
	if(connected_count == 1){
		app_conn1 = conn;
	}else if(connected_count == 2){
		app_conn2 = conn;
	}
	char addr[BT_ADDR_LE_STR_LEN];
	static struct bt_gatt_exchange_params exchange_params;

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	if (err != 0) {
		LOG_INF(&amp;quot;Failed to connect to %s (%u)&amp;quot;, addr, err);
        bt_conn_unref(conn_connecting);
		conn_connecting = NULL;
        start_scan();
		return;
	}
	LOG_INF(&amp;quot;Connected to %s&amp;quot;, addr);

	exchange_params.func = exchange_func;
	err = bt_gatt_exchange_mtu(conn, &amp;amp;exchange_params);
	if (err) {
		LOG_INF(&amp;quot;MTU exchange failed (err %d)&amp;quot;, err);
	}
 
	if(conn == conn_connecting){
		memcpy(&amp;amp;uuid, &amp;amp;test_uuid.uuid, sizeof(uuid));
		discover_params.uuid = &amp;amp;uuid.uuid;
    	discover_params.func = discover_func;
		discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
		discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
		discover_params.type = BT_GATT_DISCOVER_PRIMARY;
    	err = bt_gatt_discover(conn,&amp;amp;discover_params);
		if (err) {
			LOG_ERR(&amp;quot;Discover failed(err %d)\n&amp;quot;, err);
			return;
		}
#if CONFIG_TWO_GATT_SERVICE
		memcpy(&amp;amp;uuid_2, &amp;amp;test_uuid_2.uuid, sizeof(uuid_2));
		discover_params_2.uuid = &amp;amp;uuid_2.uuid;
    	discover_params_2.func = discover_func_2;
		discover_params_2.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
		discover_params_2.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
		discover_params_2.type = BT_GATT_DISCOVER_PRIMARY;
    	err = bt_gatt_discover(conn,&amp;amp;discover_params_2);
		if (err) {
			LOG_ERR(&amp;quot;Discover failed(err %d)\n&amp;quot;, err);
			return;
		}
#endif
	}
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;static uint8_t notify_func(struct bt_conn *conn,
		struct bt_gatt_subscribe_params *params,
		const void *data, uint16_t length)
{
	uint8_t value[200];
	memcpy(value,data,length);
	if (!data) {
		LOG_INF(&amp;quot;[UNSUBSCRIBED]\n&amp;quot;);
		connected_flag = 0;
		return BT_GATT_ITER_STOP;
	}
	LOG_INF(&amp;quot;[NOTIFICATION] data %x %x length %u\n&amp;quot;, value[0],value[1], length);
	connected_flag = 1;
	return BT_GATT_ITER_CONTINUE;
}

static uint8_t discover_func(struct bt_conn *conn, const struct bt_gatt_attr *attr,
			     struct bt_gatt_discover_params *params)
{
    int err;
    if (!attr) {
		LOG_INF(&amp;quot;Discover complete&amp;quot;);
		(void)memset(params, 0, sizeof(*params));
		return BT_GATT_ITER_STOP;
	}
    LOG_INF(&amp;quot;[ATTRIBUTE] handle %u&amp;quot;, attr-&amp;gt;handle);
    if (!bt_uuid_cmp(discover_params.uuid, &amp;amp;test_uuid.uuid)) {
		memcpy(&amp;amp;uuid, &amp;amp;test_chrc_uuid.uuid, sizeof(uuid));
		discover_params.uuid = &amp;amp;uuid.uuid;
		discover_params.start_handle = attr-&amp;gt;handle + 1;
		discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;

		err = bt_gatt_discover(conn, &amp;amp;discover_params);
		LOG_INF(&amp;quot;Discover Service&amp;quot;);
		if (err) {
			LOG_INF(&amp;quot;Discover failed (err %d)\n&amp;quot;, err);
		}
	} else if (!bt_uuid_cmp(discover_params.uuid,&amp;amp;test_chrc_uuid.uuid)) {
		memcpy(&amp;amp;uuid, BT_UUID_GATT_CCC, sizeof(uuid));
		discover_params.uuid = &amp;amp;uuid.uuid;
		discover_params.start_handle = attr-&amp;gt;handle + 2;
		discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
		subscribe_params.value_handle = bt_gatt_attr_value_handle(attr);
		err = bt_gatt_discover(conn, &amp;amp;discover_params);
		LOG_INF(&amp;quot;Discover Character&amp;quot;);
		if (err) {
			LOG_INF(&amp;quot;Discover failed (err %d)\n&amp;quot;, err);
		}
	} else if (bt_uuid_cmp(discover_params.uuid, &amp;amp;test_chrc_uuid.uuid)){
		subscribe_params.notify = notify_func;
		subscribe_params.value = BT_GATT_CCC_NOTIFY;
		subscribe_params.ccc_handle = attr-&amp;gt;handle;
		err = bt_gatt_subscribe(conn, &amp;amp;subscribe_params);
		if (err &amp;amp;&amp;amp; err != -EALREADY) {
			LOG_INF(&amp;quot;Subscribe failed (err %d)\n&amp;quot;, err);
		} else {
			LOG_INF(&amp;quot;[SUBSCRIBED]\n&amp;quot;);
		}
	}
	return BT_GATT_ITER_STOP;
}

#if CONFIG_TWO_GATT_SERVICE
static uint8_t discover_func_2(struct bt_conn *conn, const struct bt_gatt_attr *attr,
			     struct bt_gatt_discover_params *params)
{
    int err;
    if (!attr) {
		LOG_INF(&amp;quot;Discover complete&amp;quot;);
		(void)memset(params, 0, sizeof(*params));
		return BT_GATT_ITER_STOP;
	}
    LOG_INF(&amp;quot;[ATTRIBUTE] handle %u&amp;quot;, attr-&amp;gt;handle);
    if (!bt_uuid_cmp(discover_params_2.uuid, &amp;amp;test_uuid_2.uuid)) {
		memcpy(&amp;amp;uuid_2, &amp;amp;test_chrc_uuid_2.uuid, sizeof(uuid_2));
		discover_params_2.uuid = &amp;amp;uuid_2.uuid;
		discover_params_2.start_handle = attr-&amp;gt;handle + 1;
		discover_params_2.type = BT_GATT_DISCOVER_CHARACTERISTIC;

		err = bt_gatt_discover(conn, &amp;amp;discover_params_2);
		LOG_INF(&amp;quot;Discover Service&amp;quot;);
		if (err) {
			LOG_INF(&amp;quot;Discover failed (err %d)\n&amp;quot;, err);
		}
	} else if (!bt_uuid_cmp(discover_params_2.uuid,&amp;amp;test_chrc_uuid_2.uuid)) {
		memcpy(&amp;amp;uuid_2, BT_UUID_GATT_CCC, sizeof(uuid_2));
		discover_params_2.uuid = &amp;amp;uuid_2.uuid;
		discover_params_2.start_handle = attr-&amp;gt;handle + 2;
		discover_params_2.type = BT_GATT_DISCOVER_DESCRIPTOR;
		subscribe_params_2.value_handle = bt_gatt_attr_value_handle(attr);

		err = bt_gatt_discover(conn, &amp;amp;discover_params_2);
		LOG_INF(&amp;quot;Discover Character&amp;quot;);
		if (err) {
			LOG_INF(&amp;quot;Discover failed (err %d)\n&amp;quot;, err);
		}
	} else if (bt_uuid_cmp(discover_params_2.uuid, &amp;amp;test_chrc_uuid_2.uuid)){
		subscribe_params_2.notify = notify_func;
		subscribe_params_2.value = BT_GATT_CCC_NOTIFY;
		subscribe_params_2.ccc_handle = attr-&amp;gt;handle;
		err = bt_gatt_subscribe(conn, &amp;amp;subscribe_params_2);
		if (err &amp;amp;&amp;amp; err != -EALREADY) {
			LOG_INF(&amp;quot;Subscribe failed (err %d)\n&amp;quot;, err);
		} else {
			LOG_INF(&amp;quot;[SUBSCRIBED]\n&amp;quot;);
			connected_flag = 1;
		}
	}
	return BT_GATT_ITER_STOP;
}
#endif&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Is it because two services are registered at the same time and connected to two central devices at the same time, causing the connection to be unstable?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Peripheral is connected to two Centrals, each with two Gatt Services, occurred mtu exchange fail.</title><link>https://devzone.nordicsemi.com/thread/502453?ContentTypeID=1</link><pubDate>Fri, 13 Sep 2024 09:29:39 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b93dd63d-416d-4512-ac99-1a36721c5cbb</guid><dc:creator>LandyWang</dc:creator><description>&lt;p&gt;The code I shown is from the peripheral side.&lt;/p&gt;
&lt;p&gt;I added CONFIG_BT_MAX_CONN=2 and CONFIG_BT_MAX_PAIRED=2 to the peripheral application so that it can connect to two centrals at the same time.&lt;/p&gt;
&lt;p&gt;After the peripheral is connected to the central, it will continuously transmit data to the central, and the central will also output the received data to the log.&lt;/p&gt;
&lt;p&gt;When the second central device connected, the first central device stopped outputting logs and didn&amp;#39;t seem to be doing anything, so I thought it &amp;quot;crashes&amp;quot;.&lt;/p&gt;
&lt;p&gt;At this time, peripheral does not output any special message.&lt;/p&gt;
&lt;p&gt;I will share the detailed logs and code next week.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Peripheral is connected to two Centrals, each with two Gatt Services, occurred mtu exchange fail.</title><link>https://devzone.nordicsemi.com/thread/502446?ContentTypeID=1</link><pubDate>Fri, 13 Sep 2024 08:52:11 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:2f8b71ec-46d6-499d-bd88-29ae79da7c40</guid><dc:creator>Einar Thorsrud</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;I don&amp;#39;t know anything more than you have written, so the reason for my initial question was to ask if you handle multiple connections properly in your peripheral application (as most smaples are only designed for a single connection).&lt;/p&gt;
&lt;p&gt;The code snippet you have shown here is that from the central or peripheral side? (I ask as a GATT client can be present on both)? And do you have logs from both sentrals and the peripheral you can share that may shed some light on this? For instance, what happens on the first central when it &amp;quot;crashes&amp;quot;? And what happens on the peripheral side?&amp;nbsp;Knowing more about the implemetnation would be usefull as well.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Peripheral is connected to two Centrals, each with two Gatt Services, occurred mtu exchange fail.</title><link>https://devzone.nordicsemi.com/thread/502223?ContentTypeID=1</link><pubDate>Thu, 12 Sep 2024 05:58:39 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:d25cd155-c853-4dc4-8715-445e60d21b22</guid><dc:creator>LandyWang</dc:creator><description>&lt;p&gt;Thank you for your reply.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t quite understand what you mean. Do you mean that some steps were not completed when I connected?&lt;/p&gt;
&lt;p&gt;These are what I do when connected:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;void connected(struct bt_conn *conn, uint8_t err)
{
	LOG_INF(&amp;quot;connected&amp;quot;);
	char addr[BT_ADDR_LE_STR_LEN];
	static struct bt_gatt_exchange_params exchange_params;

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	if (err != 0) {
		LOG_INF(&amp;quot;Failed to connect to %s (%u)&amp;quot;, addr, err);
		return;
	}

	LOG_INF(&amp;quot;Connected to %s&amp;quot;, addr);

	exchange_params.func = exchange_func;
	err = bt_gatt_exchange_mtu(conn, &amp;amp;exchange_params);
	if (err) {
		LOG_INF(&amp;quot;MTU exchange failed (err %d)&amp;quot;, err);
	}
	memcpy(&amp;amp;uuid, &amp;amp;test_uuid.uuid, sizeof(uuid));
	discover_params.uuid = &amp;amp;uuid.uuid;
    discover_params.func = discover_func;
	discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
	discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
	discover_params.type = BT_GATT_DISCOVER_PRIMARY;
    err = bt_gatt_discover(conn,&amp;amp;discover_params);
	if (err) {
		LOG_ERR(&amp;quot;Discover failed(err %d)\n&amp;quot;, err);
		return;
	}
#if CONFIG_TWO_GATT_SERVICE
	memcpy(&amp;amp;uuid_2, &amp;amp;test_uuid_2.uuid, sizeof(uuid_2));
	discover_params_2.uuid = &amp;amp;uuid_2.uuid;
    discover_params_2.func = discover_func_2;
	discover_params_2.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
	discover_params_2.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
	discover_params_2.type = BT_GATT_DISCOVER_PRIMARY;
    err = bt_gatt_discover(conn,&amp;amp;discover_params_2);
	if (err) {
		LOG_ERR(&amp;quot;Discover failed(err %d)\n&amp;quot;, err);
		return;
	}
#endif
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;If I set CONFIG_TWO_GATT_SERVICE to n, peripheral can successfully connect to two centrals.&lt;/p&gt;
&lt;p&gt;But if I set CONFIG_TWO_GATT_SERVICE to y, the error I mentioned above will occur when peripheral connects to the second central.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Peripheral is connected to two Centrals, each with two Gatt Services, occurred mtu exchange fail.</title><link>https://devzone.nordicsemi.com/thread/502116?ContentTypeID=1</link><pubDate>Wed, 11 Sep 2024 12:23:47 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:eade58c0-ec49-4cd4-b648-9308b55a5ec4</guid><dc:creator>Einar Thorsrud</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;Multiple connections in the peripheral role is possible and supported, but then your application needs to properly support it.&amp;nbsp;So you need to keep track of the connections, and make all connection related API calls with the correct connection object (bt_conn struct) which is typically the first argument, etc. As you see something happen on one link when you do something on the other link, that indocate to me that perhaps you do not have a clean handling of the connections in your application?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>