Prepare WinRT subscriptions afresh and test BlueZ session replacement
This commit is contained in:
1 parent
68444ef192
commit
752a3a7d95
2 files changed
+48
-15
No files matched your search
+22
-12
@@ -743,7 +743,7 @@ struct WinState : std::enable_shared_from_this<WinState> {
|
||||
l->value_changed = s.watch_value(id, l->tx, BLE_WIRE_DATA);
|
||||
l->invite_changed = s.watch_value(id, l->invite, BLE_WIRE_INVITE);
|
||||
l->ack_changed = s.watch_value(id, l->ack, BLE_WIRE_ACK);
|
||||
s.subscribe_channel(id, BLE_WIRE_DATA);
|
||||
s.subscribe_channel(id, BLE_WIRE_DATA, true);
|
||||
});
|
||||
}
|
||||
GattCharacteristic::ValueChanged_revoker watch_value(ble_link_id id, GattCharacteristic const& characteristic, enum ble_wire_channel channel) {
|
||||
@@ -752,7 +752,12 @@ struct WinState : std::enable_shared_from_this<WinState> {
|
||||
DEBUG_DEBUG(CAT, "BLE WinRT register ValueChanged link=%llu channel=%d", (unsigned long long)id, channel);
|
||||
return characteristic.ValueChanged(auto_revoke, [weak, id, channel](auto const&, GattValueChangedEventArgs const& args) {
|
||||
if (auto s = weak.lock()) s->post("GattCharacteristic.ValueChanged", id, [id, channel, args](WinState& s) {
|
||||
if (!s.link(id)) return;
|
||||
auto* l = s.link(id); if (!l) return;
|
||||
if (!l->opened) {
|
||||
DEBUG_DEBUG(CAT, "BLE WinRT notification ignored during CCC preparation link=%llu channel=%d",
|
||||
(unsigned long long)id, channel);
|
||||
return;
|
||||
}
|
||||
s.step("ValueChanged.CharacteristicValue/DataReader", id);
|
||||
auto data = bytes(args.CharacteristicValue());
|
||||
DEBUG_TRACE(CAT, "BLE WinRT RX value link=%llu channel=%d bytes=%zu", (unsigned long long)id, channel, data.size());
|
||||
@@ -760,24 +765,29 @@ struct WinState : std::enable_shared_from_this<WinState> {
|
||||
});
|
||||
});
|
||||
}
|
||||
void subscribe_channel(ble_link_id id, enum ble_wire_channel channel) {
|
||||
// Сбросить весь набор CCC до включения: ACL и удалённые CCC могут пережить прежнюю сессию.
|
||||
void subscribe_channel(ble_link_id id, enum ble_wire_channel channel, bool reset) {
|
||||
auto* l = link(id);
|
||||
auto characteristic = channel == BLE_WIRE_ACK ? l->ack : channel == BLE_WIRE_DATA ? l->tx : l->invite;
|
||||
auto mode = channel == BLE_WIRE_INVITE ? GattClientCharacteristicConfigurationDescriptorValue::Indicate :
|
||||
GattClientCharacteristicConfigurationDescriptorValue::Notify;
|
||||
auto mode = reset ? GattClientCharacteristicConfigurationDescriptorValue::None :
|
||||
channel == BLE_WIRE_INVITE ? GattClientCharacteristicConfigurationDescriptorValue::Indicate :
|
||||
GattClientCharacteristicConfigurationDescriptorValue::Notify;
|
||||
step("GattCharacteristic.WriteCCCDWithResultAsync", id);
|
||||
DEBUG_DEBUG(CAT, "BLE WinRT subscribe request link=%llu channel=%d mode=%d", (unsigned long long)id, channel, (int)mode);
|
||||
DEBUG_DEBUG(CAT, "BLE WinRT CCC request link=%llu reset=%d channel=%d mode=%d", (unsigned long long)id, reset, channel, (int)mode);
|
||||
await("subscribe channel", characteristic.WriteClientCharacteristicConfigurationDescriptorWithResultAsync(mode), id,
|
||||
[id, channel](WinState& s, GattWriteResult const& result) {
|
||||
[id, channel, reset](WinState& s, GattWriteResult const& result) {
|
||||
auto status = result.Status(); auto protocol = result.ProtocolError();
|
||||
DEBUG_DEBUG(CAT, "BLE WinRT subscribe link=%llu channel=%d status=%d", (unsigned long long)id, channel, (int)status);
|
||||
DEBUG_DEBUG(CAT, "BLE WinRT CCC complete link=%llu reset=%d channel=%d status=%d",
|
||||
(unsigned long long)id, reset, channel, (int)status);
|
||||
if (status != GattCommunicationStatus::Success) {
|
||||
DEBUG_WARN(CAT, "BLE WinRT subscription failed link=%llu channel=%d status=%d ATT_error=%d",
|
||||
(unsigned long long)id, channel, (int)status, protocol ? int(protocol.Value()) : -1);
|
||||
DEBUG_WARN(CAT, "BLE WinRT CCC failed link=%llu reset=%d channel=%d status=%d ATT_error=%d",
|
||||
(unsigned long long)id, reset, channel, (int)status, protocol ? int(protocol.Value()) : -1);
|
||||
s.error(id, "GATT subscription failed"); return;
|
||||
}
|
||||
if (channel == BLE_WIRE_DATA) { s.subscribe_channel(id, BLE_WIRE_INVITE); return; }
|
||||
if (channel == BLE_WIRE_INVITE) { s.subscribe_channel(id, BLE_WIRE_ACK); return; }
|
||||
if (channel == BLE_WIRE_DATA) { s.subscribe_channel(id, BLE_WIRE_INVITE, reset); return; }
|
||||
if (channel == BLE_WIRE_INVITE) { s.subscribe_channel(id, BLE_WIRE_ACK, reset); return; }
|
||||
if (reset) { s.subscribe_channel(id, BLE_WIRE_DATA, false); return; }
|
||||
DEBUG_INFO(CAT, "BLE WinRT subscriptions ready link=%llu DATA=notify INVITE=indicate ACK=notify", (unsigned long long)id);
|
||||
auto* l = s.link(id); l->opened = true; ble_backend_opened(s.owner, id, l->session.MaxPduSize());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ static struct UASYNC* ua;
|
||||
static sd_bus* bus;
|
||||
static struct ble_transport* transport;
|
||||
static char application[256];
|
||||
static int ready, broadcasts, ready_links, advertisement_count;
|
||||
static int ready, broadcasts, ready_links, advertisement_count, closed_links;
|
||||
static ble_link_id links[4];
|
||||
static unsigned commands, requests, ack_requests, ack_values;
|
||||
static int ack_fds[2] = {-1, -1};
|
||||
@@ -127,6 +127,7 @@ static void status(void* arg, enum ble_state state, const char* reason) {
|
||||
static void connection(void* arg, ble_link_id id, uint64_t node, enum ble_state state, const char* reason) {
|
||||
(void)arg; (void)reason;
|
||||
if (state == BLE_READY) { CHECK(node < 4); links[node] = id; ready_links++; }
|
||||
if (state == BLE_CLOSED) closed_links++;
|
||||
}
|
||||
static void broadcast(void* arg, const struct ble_endpoint* ep, const uint8_t* data, size_t len, int rssi) {
|
||||
(void)arg; CHECK(strstr(ep->id, "dev_A")); CHECK(len == 3 && !memcmp(data, "abc", 3)); CHECK(rssi == -42); broadcasts++;
|
||||
@@ -241,6 +242,28 @@ int main(void) {
|
||||
CHECK(send(invite2, "\1", 1, MSG_NOSIGNAL) == 1); poll_all();
|
||||
}
|
||||
CHECK(ack_values >= 2);
|
||||
/* Повторный AcquireNotify до HUP старого fd: новая сессия A, действующая сессия B не затронута. */
|
||||
ble_link_id old_a = links[1], old_b = links[2];
|
||||
int closed_before = closed_links;
|
||||
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(invite1); close(fd1); fd1 = new_fd1;
|
||||
invite1 = acquire(ADAPTER "/dev_A", 1);
|
||||
CHECK(ready_links == 2);
|
||||
ack_fds[0] = acquire(ADAPTER "/dev_A", 2);
|
||||
hello(ADAPTER "/dev_A", fd1, 1);
|
||||
CHECK(ready_links == 3 && links[1] != old_a && links[2] == old_b);
|
||||
CHECK(!ble_tx_put(transport, old_b, frame(0xf1))); poll_all();
|
||||
for (int offset = 0; offset < 31; offset += 11) {
|
||||
CHECK(recv(fd2, data, sizeof(data), MSG_DONTWAIT) == (offset == 22 ? 18 : 20));
|
||||
CHECK(data[8] == offset && data[9] == 0xf1);
|
||||
}
|
||||
write_value(ADAPTER "/dev_B", data, 2, 2);
|
||||
write_value(ADAPTER "/dev_A", incoming, sizeof(incoming), 0);
|
||||
e = ble_rx_get(transport, links[1]); CHECK(e && e->len == 3 && !memcmp(e->dgram, incoming + 9, 3));
|
||||
queue_dgram_free(e); queue_entry_free(e);
|
||||
close(ack_fds[0]); close(ack_fds[1]); ack_fds[0] = ack_fds[1] = -1;
|
||||
close(invite1); close(invite2);
|
||||
close(fd1); poll_all(); close(fd2); poll_all();
|
||||
@@ -248,10 +271,10 @@ int main(void) {
|
||||
struct ble_endpoint ep = {REMOTE};
|
||||
CHECK(ble_connect(transport, &ep, 3)); poll_all();
|
||||
/* Кеш UUID доступен сразу, но до ServicesResolved нельзя объявлять GATT готовым с прежним MTU23. */
|
||||
CHECK(ready_links == 2 && commands == 0);
|
||||
CHECK(ready_links == 3 && commands == 0);
|
||||
remote_resolved = 1;
|
||||
CHECK(sd_bus_emit_properties_changed(bus, REMOTE, "org.bluez.Device1", "ServicesResolved", NULL) >= 0);
|
||||
poll_all(); CHECK(ready_links == 3 && commands == 1);
|
||||
poll_all(); CHECK(ready_links == 4 && commands == 1);
|
||||
CHECK(!ble_tx_put(transport, links[3], frame(0xe5)));
|
||||
CHECK(!ble_channel_tx_put(transport, links[3], BLE_CHANNEL_INVITE, frame(0xe6)));
|
||||
poll_all(); CHECK(commands == 2 && requests == 1 && ack_requests >= 1); /* MTU517 и ACK Write Command. */
|
||||
|
||||
Reference in new issue
Block a user