From 2cd3f966b244ed16760e19c908c595f53fbfa5f2 Mon Sep 17 00:00:00 2001 From: evgeny Date: Fri, 30 Oct 2026 21:43:26 +0100 Subject: [PATCH] Document fresh CCC preparation and finalize reconnect regression --- doc/ble_transport.txt | 10 ++++++++++ lib/ble/tests/test_ble_bluez.c | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/doc/ble_transport.txt b/doc/ble_transport.txt index 373be5c4..b54ac2bb 100644 --- a/doc/ble_transport.txt +++ b/doc/ble_transport.txt @@ -99,6 +99,13 @@ HELLO/ACCEPT идут только по DATA, сборка DATA и INVITE нез frame_id увеличивается modulo 65536 отдельно для каждого направления и канала. Планировщик чередует фрагменты DATA/INVITE; готовый ACK имеет высший приоритет, затем HELLO/ACCEPT. До HELLO обязательны подписки DATA/INVITE/ACK с обеих сторон. +При новом подключении Android/WinRT сначала последовательно записывают CCC=0 +для всех трёх каналов, затем включают DATA=Notify, INVITE=Indicate, ACK=Notify. +Только завершение всех шести операций разрешает HELLO; уведомления во время +подготовки не передаются протоколу. ACL и значения CCC могут пережить процесс: +повторное включение без сброса не гарантирует создания новых серверных fd. +Android-сервер принимает CCC=0 идемпотентно, завершает прежнюю сессию без +cancelConnection и не создаёт сессию до следующего включения подписок. Размер значения <= min(ATT_MTU-3,512), минимальный ATT MTU=23. Полезный DATA-фрагмент:11байт при MTU23,235 при247,503 при517; HELLO/ACCEPT занимают19. Нулевой offset начинает новый кадр и заменяет незавершённую предыдущую сборку. @@ -151,6 +158,9 @@ instance может иметь другой random address). Нехватка р отдельный SOCK_SEQPACKET socketpair для каждого клиента и канала. DATA/ACK fd принимают notifications: успешная запись завершает локальный send без ожидания ATT ACK. INVITE fd передаёт indications; байт1 в обратную сторону подтверждает ATT completion. +HUP любого обязательного fd завершает сессию. Новый AcquireNotify занятого +канала заменяет прежнюю сессию, даже если HUP старого fd ещё не обработан. +Подписки других клиентов при этом сохраняются. EAGAIN сохраняет фрагмент и ждёт writable; синхронных callbacks send нет. Value/Confirm без адреса клиента для серверной передачи не используются. Выходящий клиент: DATA/ACK WriteValue(type=command), INVITE WriteValue(type=request), diff --git a/lib/ble/tests/test_ble_bluez.c b/lib/ble/tests/test_ble_bluez.c index 6f03d7b8..7585090b 100644 --- a/lib/ble/tests/test_ble_bluez.c +++ b/lib/ble/tests/test_ble_bluez.c @@ -245,10 +245,11 @@ int main(void) { /* Повторный AcquireNotify до HUP старого fd: новая сессия A, действующая сессия B не затронута. */ ble_link_id old_a = links[1], old_b = links[2]; int closed_before = closed_links; + int old_ack = ack_fds[0]; ack_fds[0] = -1; /* poll_all не должен читать EOF закрываемой подписки. */ int new_fd1 = acquire(ADAPTER "/dev_A", 0); CHECK(closed_links == closed_before + 1 && ready_links == 2); CHECK(recv(invite1, data, sizeof(data), MSG_DONTWAIT) == 0); - close(ack_fds[0]); ack_fds[0] = -1; + close(old_ack); close(invite1); close(fd1); fd1 = new_fd1; invite1 = acquire(ADAPTER "/dev_A", 1); CHECK(ready_links == 2);