Received: by 2002:a05:7412:bbc7:b0:fc:a2b0:25d7 with SMTP id kh7csp2939189rdb; Tue, 6 Feb 2024 02:16:56 -0800 (PST) X-Google-Smtp-Source: AGHT+IFrslNg43WgravRwbBtGnZ/m0StT10efNH5qrnMpq2t5TotU1ewHp0g4kDE02hwRxlhmQhE X-Received: by 2002:a17:902:6b8a:b0:1d9:6009:c23d with SMTP id p10-20020a1709026b8a00b001d96009c23dmr989068plk.54.1707214616577; Tue, 06 Feb 2024 02:16:56 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707214616; cv=pass; d=google.com; s=arc-20160816; b=ztVdDyANmz/zhHAbVS+iroR2xNY0xPUcjbeWZqQmnZfhKAzq+6P2B66ZYlRmlYcH1i wNrBx+94HCPtxUXb+hw67z6MMfQhdnDf05kzKQr7yrZW222lI+f5WPqii2ucTu8weFKI qKfRU/obw9MTomltamiMHsdpCY0QD0c8PTWmIZglz+Isz3HiA90UsHle7ba0sERsbbvi /DTtsUxm0yQcak3h0jvLP3RTERHriTrO6U5lWTO04jppxyEORszWU0A25AIpjT5amgWb Y7fWa84vQzJRc4hl/G3gLMo8Il45LRIl95QBTqRY3eG8g5YYjk6QI1xXDu4cFQSIHk/6 5gOg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:message-id:date:subject:cc:to :from; bh=4ENgHrkeEAkWsINHkj+ls0LguedvQeSprO/+77smwp4=; fh=2z8y1o5gnfBYKYB+iluQqggjZxyS4CvVEo7ri2kShjA=; b=kMj+qAJiOa+wk2q6ZdqLIbm12WMPglWlGXA/MGtS6ko5/XBV0nfyeOJQyUvwHC4KbU PZgX9Kus2tLm8dteQRzYiN0D6Xk8gpP0RQa58nnmwOr+sgDGrpdLx1jYe+nPD8REfRK7 OaOkX4/YJYklCqyOZz3zoZp4z0mckwwWdEBHMV7MUV83eYV/D9M0/jJ9dq3NeW3Wy3rP Xnw70k/S/M9FK9Bq8ecwD7BrLcTvIbhn8vJ2sBdQT3vvslp7D/yYSW9djD6zMlxqyMxo vNL2PBggb7dxIRZsyrnCELmNzBrfrKSvraWXhrXuXjLbIKQ1ZL4Mj0GNTMbxHrPhh5Bu DXuw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; arc=pass (i=1 spf=pass spfdomain=v0yd.nl); spf=pass (google.com: domain of linux-bluetooth+bounces-1623-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-bluetooth+bounces-1623-linux.lists.archive=gmail.com@vger.kernel.org" X-Forwarded-Encrypted: i=1; AJvYcCX6Kn6qH2zWFwRSGBC1PNdKXYaTnrnbdbAZdA9/R/xgj5uc/Rw5WgToaobtWUI58opGnelWxTIGLTejJVvjjOxBP0vGE2LQxsKbac5eXQ== Return-Path: Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [2604:1380:40f1:3f00::1]) by mx.google.com with ESMTPS id u8-20020a170902e5c800b001d963d963a9si1456032plf.2.2024.02.06.02.16.56 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Feb 2024 02:16:56 -0800 (PST) Received-SPF: pass (google.com: domain of linux-bluetooth+bounces-1623-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) client-ip=2604:1380:40f1:3f00::1; Authentication-Results: mx.google.com; arc=pass (i=1 spf=pass spfdomain=v0yd.nl); spf=pass (google.com: domain of linux-bluetooth+bounces-1623-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-bluetooth+bounces-1623-linux.lists.archive=gmail.com@vger.kernel.org" Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id DC82CB22FB7 for ; Tue, 6 Feb 2024 10:14:49 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 0A44412E1F4; Tue, 6 Feb 2024 10:14:34 +0000 (UTC) X-Original-To: linux-bluetooth@vger.kernel.org Received: from mout-p-101.mailbox.org (mout-p-101.mailbox.org [80.241.56.151]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ADE9212DDBA for ; Tue, 6 Feb 2024 10:14:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=80.241.56.151 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707214473; cv=none; b=ooqv6l/V6K6Hnhyqh5l/Wtho/AFtyRBwoJmQX23Yij/nAyYrQzjbtf2gjRzyl+zT1oVVeV8J0yMgTbaRizA0JtKGtMIg5y/D8qKZQKVCcwCIJC2ru9uyCol9hkWo2gm35eyWwwxhhG5JYNZt5KjAab/q2sYxLWkPsf3FZZS1+Pg= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707214473; c=relaxed/simple; bh=WfEjW8FQD5nU+ed6kuUdO9rJcnepjNMAUZHEcKdbH0c=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=k/Zg8jhRQ70ZHM286WUkMxQ7359qJFju9O5EnMrTD06GJmD1mn4FiCQ+ggWVo7JUr3qdk4Jrozk8ROo7eNKuGuVUC3JIOJvOjRy0uyic+yyXXUot6jB9xK+KL2VH65oK5hA/WzW7YX1J5aTmn+z/zPsGyLOUzVam+p9ZI10a7WM= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=v0yd.nl; spf=pass smtp.mailfrom=v0yd.nl; arc=none smtp.client-ip=80.241.56.151 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=v0yd.nl Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=v0yd.nl Received: from smtp2.mailbox.org (smtp2.mailbox.org [10.196.197.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-101.mailbox.org (Postfix) with ESMTPS id 4TTfHP1SMXz9t1h; Tue, 6 Feb 2024 11:14:25 +0100 (CET) From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= To: linux-bluetooth@vger.kernel.org, Luiz Augusto von Dentz Cc: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= Subject: [PATCH BlueZ v2] mgmt-tester: Ensure rfkilling HCI disconnects devices Date: Tue, 6 Feb 2024 11:14:15 +0100 Message-ID: <20240206101415.46505-1-verdre@v0yd.nl> Precedence: bulk X-Mailing-List: linux-bluetooth@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit The kernel was recently changed to introduce disconnecting of connected BT devices before the adapter gets rfkilled (see kernel commit "Bluetooth: Disconnect connected devices before rfkilling adapter"). Add a test to mgmt-tester to ensure that this logic works. It uses async io to write to the rfkill device and then looks if the HCI Disconnect command gets sent for the connected device. Use of async io is necessary because the rfkill write would block our thread until the disconnect and adapter shutdown is finished. To finish this disconnect though, the HCI emulator needs to respond to the "HCI Disconnect" command. Because the emulator runs in the our mgmt-tester thread too, it would be blocked by the write and couldn't reply, resulting in a timeout and test failure. --- v1: https://lore.kernel.org/linux-bluetooth/20240128210547.16141-1-verdre@v0yd.nl/ v2: added -lrt to link to real-time library for aio_* functions --- Makefile.tools | 2 +- tools/mgmt-tester.c | 153 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+), 1 deletion(-) diff --git a/Makefile.tools b/Makefile.tools index 044342e29..51ce103ea 100644 --- a/Makefile.tools +++ b/Makefile.tools @@ -124,7 +124,7 @@ tools_mgmt_tester_SOURCES = tools/mgmt-tester.c monitor/bt.h \ emulator/bthost.h emulator/bthost.c \ emulator/smp.c tools_mgmt_tester_LDADD = lib/libbluetooth-internal.la \ - src/libshared-glib.la $(GLIB_LIBS) + src/libshared-glib.la $(GLIB_LIBS) -lrt tools_mesh_tester_SOURCES = tools/mesh-tester.c monitor/bt.h \ emulator/hciemu.h emulator/hciemu.c \ diff --git a/tools/mgmt-tester.c b/tools/mgmt-tester.c index 7dfd1b0c7..60b5a305f 100644 --- a/tools/mgmt-tester.c +++ b/tools/mgmt-tester.c @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -12760,6 +12761,149 @@ static void test_hci_devcd(const void *test_data) tester_wait(test->dump_data->timeout + 1, verify_devcd, NULL); } +static const uint8_t rfkill_hci_disconnect_device[] = { + 0x2a, 0x00, /* handle */ + 0x15, /* reason: Power Off */ +}; + +static const struct generic_data rfkill_disconnect_devices = { + .setup_settings = settings_powered_connectable_bondable, + .expect_hci_command = BT_HCI_CMD_DISCONNECT, + .expect_hci_param = rfkill_hci_disconnect_device, + .expect_hci_len = sizeof(rfkill_hci_disconnect_device), +}; + +enum rfkill_type { + RFKILL_TYPE_ALL = 0, + RFKILL_TYPE_WLAN, + RFKILL_TYPE_BLUETOOTH, + RFKILL_TYPE_UWB, + RFKILL_TYPE_WIMAX, + RFKILL_TYPE_WWAN, +}; + +enum rfkill_operation { + RFKILL_OP_ADD = 0, + RFKILL_OP_DEL, + RFKILL_OP_CHANGE, + RFKILL_OP_CHANGE_ALL, +}; + +struct rfkill_event { + uint32_t idx; + uint8_t type; + uint8_t op; + uint8_t soft; + uint8_t hard; +}; +#define RFKILL_EVENT_SIZE_V1 8 + +static void trigger_rfkill(void *user_data) +{ + struct aiocb *op = user_data; + int fd; + int latest_rfkill_idx; + struct rfkill_event write_event; + + tester_print("Blocking hci device via rfkill"); + + fd = open("/dev/rfkill", O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); + if (fd < 0) { + tester_warn("Failed to open rfkill control device: %s", + strerror(errno)); + tester_test_failed(); + free(op); + return; + } + + latest_rfkill_idx = -1; + while (1) { + struct rfkill_event event = { 0 }; + ssize_t len; + + len = read(fd, &event, sizeof(event)); + if (len < RFKILL_EVENT_SIZE_V1) + break; + + if (event.type == RFKILL_TYPE_BLUETOOTH) + latest_rfkill_idx = event.idx; + } + + if (latest_rfkill_idx < 0) { + tester_warn("No rfkill device to block found"); + tester_test_failed(); + close(fd); + free(op); + return; + } + + write_event.idx = latest_rfkill_idx; + write_event.op = RFKILL_OP_CHANGE; + write_event.soft = true; + + op->aio_fildes = fd; + op->aio_buf = &write_event; + op->aio_nbytes = sizeof(write_event); + + if (aio_write(op) != 0) { + tester_warn("Failed to write to rfkill control device: %s", + strerror(errno)); + tester_test_failed(); + close(fd); + free(op); + } +} + +static void finish_aio_write(void *user_data) +{ + struct aiocb *op = user_data; + struct test_data *data = tester_get_data(); + int err; + size_t ret; + + err = aio_error(op); + ret = aio_return(op); + if (err != 0) { + tester_warn("aio_error() return error: %s", strerror(err)); + tester_test_failed(); + } else if (ret != op->aio_nbytes) { + tester_warn("aio_return() returned write failed"); + tester_test_failed(); + } + + close(op->aio_fildes); + free(op); + test_condition_complete(data); +} + +static void test_disconnect_on_rfkill(const void *test_data) +{ + struct test_data *data = tester_get_data(); + struct bthost *bthost; + const uint8_t *central_bdaddr; + uint8_t addr_type; + struct aiocb *op = new0(struct aiocb, 1); + + bthost = hciemu_client_get_host(data->hciemu); + central_bdaddr = hciemu_get_central_bdaddr(data->hciemu); + if (!central_bdaddr) { + tester_warn("No central bdaddr"); + tester_test_failed(); + return; + } + + addr_type = data->hciemu_type == HCIEMU_TYPE_BREDRLE + ? BDADDR_BREDR : BDADDR_LE_PUBLIC; + + bthost_hci_connect(bthost, central_bdaddr, addr_type); + + test_command_generic(test_data); + + tester_wait(1, trigger_rfkill, (void *)op); + tester_wait(2, finish_aio_write, (void *)op); + test_add_condition(data); +} + int main(int argc, char *argv[]) { tester_init(&argc, &argv); @@ -14925,5 +15069,14 @@ int main(int argc, char *argv[]) test_bredrle_full("HCI Devcoredump - Dump Timeout", &dump_timeout, NULL, test_hci_devcd, 3); + /* Rfkill + * Setup: Connect to device + * Run: Block hci device via rfkill + * Expect: Disconnect HCI command sent to device + */ + test_bredrle("Rfkill - disconnect devices", + &rfkill_disconnect_devices, NULL, + test_disconnect_on_rfkill); + return tester_run(); } -- 2.43.0