From 4bc0c28a046ec6ae606b0f8372b1650de16ec382 Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Fri, 9 Feb 2024 13:13:59 -0800 Subject: [PATCH] chore: Add new Valve patches for bluez --- .../bluez/0001-valve-bluetooth-config.patch | 4 +- .../bluez/0002-valve-bluetooth-phy.patch | 45 +++- ...ent-security-level-change-for-PTS-GA.patch | 104 ++++++++ ...d-command-to-prevent-security-level-.patch | 224 ++++++++++++++++++ ...d-function-to-search-service-based-o.patch | 110 +++++++++ ...d-function-to-search-characteristics.patch | 117 +++++++++ ...d-function-to-search-all-primary-ser.patch | 71 ++++++ spec_files/bluez/AVRCP_TG_MDI_BV-04-C.patch | 10 +- spec_files/bluez/bluez.spec | 5 + 9 files changed, 673 insertions(+), 17 deletions(-) create mode 100644 spec_files/bluez/0006-shared-gatt-Prevent-security-level-change-for-PTS-GA.patch create mode 100644 spec_files/bluez/0007-btgatt-client-Add-command-to-prevent-security-level-.patch create mode 100644 spec_files/bluez/0008-btgatt-client-Add-function-to-search-service-based-o.patch create mode 100644 spec_files/bluez/0009-btgatt-client-Add-function-to-search-characteristics.patch create mode 100644 spec_files/bluez/0010-btgatt-client-Add-function-to-search-all-primary-ser.patch diff --git a/spec_files/bluez/0001-valve-bluetooth-config.patch b/spec_files/bluez/0001-valve-bluetooth-config.patch index b9e73f7b..ba22408c 100644 --- a/spec_files/bluez/0001-valve-bluetooth-config.patch +++ b/spec_files/bluez/0001-valve-bluetooth-config.patch @@ -1,5 +1,5 @@ diff --git a/src/main.conf b/src/main.conf -index 085c81a..ca2abcd 100644 +index 2796f155e..f7b032b9f 100644 --- a/src/main.conf +++ b/src/main.conf @@ -60,7 +60,7 @@ @@ -11,7 +11,7 @@ index 085c81a..ca2abcd 100644 # Permanently enables the Fast Connectable setting for adapters that # support it. When enabled other devices can connect faster to us, -@@ -193,8 +193,8 @@ +@@ -182,8 +182,8 @@ # LE scanning parameters used for passive scanning supporting wake from suspend # scenarios diff --git a/spec_files/bluez/0002-valve-bluetooth-phy.patch b/spec_files/bluez/0002-valve-bluetooth-phy.patch index 36154e23..d9552a9f 100644 --- a/spec_files/bluez/0002-valve-bluetooth-phy.patch +++ b/spec_files/bluez/0002-valve-bluetooth-phy.patch @@ -1,5 +1,27 @@ +From d1ef0be0d84b909a88dccf28af52d5a1c0e49992 Mon Sep 17 00:00:00 2001 +From: Vicki Pfau +Date: Fri, 8 Sep 2023 16:53:02 -0700 +Subject: [PATCH 2/2] Experimental patch to enable alternate Bluetooth + connection modes + +This should improve Bluetooth connectivity, especially with multiple controllers and while docked. + +Testing: +sudo btmgmt +[mgmt]# phy +Verify that LE2MRX, LE2MTX, LECODEDRX, LECODEDTX are in the selected phys list. +Verify that multiple controllers can connect and work well. + +Co-Authored-By: Rachel Blackman +--- + src/adapter.c | 46 ++++++++++++++++++++++++++++ + src/btd.h | 2 ++ + src/main.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++ + src/main.conf | 5 +++ + 4 files changed, 138 insertions(+) + diff --git a/src/adapter.c b/src/adapter.c -index 8a7c53a..b941559 100644 +index 5ebfc4752..bc1e1d418 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -86,6 +86,18 @@ @@ -58,7 +80,7 @@ index 8a7c53a..b941559 100644 static bool pairable_timeout_handler(gpointer user_data) { struct btd_adapter *adapter = user_data; -@@ -10389,6 +10431,10 @@ static void read_info_complete(uint8_t status, uint16_t length, +@@ -10387,6 +10429,10 @@ static void read_info_complete(uint8_t status, uint16_t length, if (btd_adapter_get_powered(adapter)) adapter_start(adapter); @@ -70,7 +92,7 @@ index 8a7c53a..b941559 100644 failed: diff --git a/src/btd.h b/src/btd.h -index b7e7ebd..2b84f7a 100644 +index b7e7ebd61..2b84f7a51 100644 --- a/src/btd.h +++ b/src/btd.h @@ -151,6 +151,8 @@ struct btd_opts { @@ -83,10 +105,10 @@ index b7e7ebd..2b84f7a 100644 extern struct btd_opts btd_opts; diff --git a/src/main.c b/src/main.c -index cddf139..1f3301b 100644 +index 2134fcf75..700c83c78 100644 --- a/src/main.c +++ b/src/main.c -@@ -128,6 +128,7 @@ static const char *le_options[] = { +@@ -127,6 +127,7 @@ static const char *le_options[] = { "AdvMonAllowlistScanDuration", "AdvMonNoFilterScanDuration", "EnableAdvMonInterleaveScan", @@ -94,7 +116,7 @@ index cddf139..1f3301b 100644 NULL }; -@@ -182,10 +183,32 @@ static const struct group_table { +@@ -180,10 +181,32 @@ static const struct group_table { { } }; @@ -127,7 +149,7 @@ index cddf139..1f3301b 100644 static int8_t check_sirk_alpha_numeric(char *str) { int8_t val = 0; -@@ -226,6 +249,54 @@ static size_t hex2bin(const char *hexstr, uint8_t *buf, size_t buflen) +@@ -224,6 +247,54 @@ static size_t hex2bin(const char *hexstr, uint8_t *buf, size_t buflen) return len; } @@ -182,7 +204,7 @@ index cddf139..1f3301b 100644 GKeyFile *btd_get_main_conf(void) { return main_conf; -@@ -678,6 +749,20 @@ static void parse_le_config(GKeyFile *config) +@@ -674,6 +745,20 @@ static void parse_le_config(GKeyFile *config) return; parse_mode_config(config, "LE", params, ARRAY_SIZE(params)); @@ -204,10 +226,10 @@ index cddf139..1f3301b 100644 static bool match_experimental(const void *data, const void *match_data) diff --git a/src/main.conf b/src/main.conf -index ca2abcd..cd535e1 100644 +index cb9b241df..c086a17d0 100644 --- a/src/main.conf +++ b/src/main.conf -@@ -231,6 +231,11 @@ ScanWindowSuspend=224 +@@ -231,6 +231,11 @@ MultiProfile = multiple # Defaults to 1 #EnableAdvMonInterleaveScan= @@ -219,3 +241,6 @@ index ca2abcd..cd535e1 100644 [GATT] # GATT attribute cache. # Possible values: +-- +2.41.0 + diff --git a/spec_files/bluez/0006-shared-gatt-Prevent-security-level-change-for-PTS-GA.patch b/spec_files/bluez/0006-shared-gatt-Prevent-security-level-change-for-PTS-GA.patch new file mode 100644 index 00000000..f6bf33e6 --- /dev/null +++ b/spec_files/bluez/0006-shared-gatt-Prevent-security-level-change-for-PTS-GA.patch @@ -0,0 +1,104 @@ +From 805b1f5bf596d747f28f53191b7a28507efb7797 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Danis?= +Date: Thu, 25 Jan 2024 20:08:01 +0100 +Subject: [PATCH BlueZ 1/5] shared/gatt: Prevent security level change for PTS + GATT tests +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: 8bit + +Some PTS GATT tests like GATT/CL/GAR/BI-04-C request to be able to get the +security error and do not try to change the security level. + +This commit adds the ability to prevent to change the security level for +an operation. +--- + src/shared/att.c | 26 ++++++++++++++++++++++++++ + src/shared/att.h | 1 + + src/shared/gatt-client.c | 19 +++++++++++++++++++ + src/shared/gatt-client.h | 3 +++ + 4 files changed, 49 insertions(+) + +diff --git a/src/shared/att.c b/src/shared/att.c +index 85feead77..64544f89b 100644 +--- a/src/shared/att.c ++++ b/src/shared/att.c +@@ -2034,3 +2034,29 @@ bool bt_att_has_crypto(struct bt_att *att) + + return att->crypto ? true : false; + } ++ ++bool bt_att_set_retry(struct bt_att *att, unsigned int id, bool retry) ++{ ++ struct att_send_op *op; ++ ++ if (!id) ++ return false; ++ ++ op = queue_find(att->req_queue, match_op_id, UINT_TO_PTR(id)); ++ if (op) ++ goto done; ++ ++ op = queue_find(att->ind_queue, match_op_id, UINT_TO_PTR(id)); ++ if (op) ++ goto done; ++ ++ op = queue_find(att->write_queue, match_op_id, UINT_TO_PTR(id)); ++ ++done: ++ if (!op) ++ return false; ++ ++ op->retry = !retry; ++ ++ return true; ++} +diff --git a/src/shared/att.h b/src/shared/att.h +index 4aa3de87b..6fd78636e 100644 +--- a/src/shared/att.h ++++ b/src/shared/att.h +@@ -110,3 +110,4 @@ bool bt_att_set_local_key(struct bt_att *att, uint8_t sign_key[16], + bool bt_att_set_remote_key(struct bt_att *att, uint8_t sign_key[16], + bt_att_counter_func_t func, void *user_data); + bool bt_att_has_crypto(struct bt_att *att); ++bool bt_att_set_retry(struct bt_att *att, unsigned int id, bool retry); +diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c +index efc013a20..2c16e78be 100644 +--- a/src/shared/gatt-client.c ++++ b/src/shared/gatt-client.c +@@ -3817,3 +3817,22 @@ bool bt_gatt_client_idle_unregister(struct bt_gatt_client *client, + + return false; + } ++ ++bool bt_gatt_client_set_retry(struct bt_gatt_client *client, ++ unsigned int id, ++ bool retry) ++{ ++ struct request *req; ++ ++ if (!client || !id) ++ return false; ++ ++ req = queue_find(client->pending_requests, match_req_id, ++ UINT_TO_PTR(id)); ++ if (!req) ++ return false; ++ ++ bt_att_set_retry(client->att, req->att_id, retry); ++ ++ return true; ++} +diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h +index bccd04a62..63cf99500 100644 +--- a/src/shared/gatt-client.h ++++ b/src/shared/gatt-client.h +@@ -134,3 +134,6 @@ unsigned int bt_gatt_client_idle_register(struct bt_gatt_client *client, + bt_gatt_client_destroy_func_t destroy); + bool bt_gatt_client_idle_unregister(struct bt_gatt_client *client, + unsigned int id); ++bool bt_gatt_client_set_retry(struct bt_gatt_client *client, ++ unsigned int id, ++ bool retry); +-- +2.34.1 + diff --git a/spec_files/bluez/0007-btgatt-client-Add-command-to-prevent-security-level-.patch b/spec_files/bluez/0007-btgatt-client-Add-command-to-prevent-security-level-.patch new file mode 100644 index 00000000..9f0fb9c2 --- /dev/null +++ b/spec_files/bluez/0007-btgatt-client-Add-command-to-prevent-security-level-.patch @@ -0,0 +1,224 @@ +From c92872e79bdf835060e7a6d2cab2103841f428ac Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Danis?= +Date: Thu, 25 Jan 2024 20:08:02 +0100 +Subject: [PATCH BlueZ 2/5] btgatt-client: Add command to prevent security + level change +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: 8bit + +Some PTS GATT tests like GATT/CL/GAR/BI-04-C request to be able to get the +security error and do not try to change the security level. + +This commit adds the ability to prevent to change the security level. +--- + tools/btgatt-client.c | 84 ++++++++++++++++++++++++++++++++++++------- + 1 file changed, 72 insertions(+), 12 deletions(-) + +diff --git a/tools/btgatt-client.c b/tools/btgatt-client.c +index 58a03bd48..3bcb7e1cf 100644 +--- a/tools/btgatt-client.c ++++ b/tools/btgatt-client.c +@@ -57,6 +57,7 @@ struct client { + struct bt_gatt_client *gatt; + + unsigned int reliable_session_id; ++ bool sec_retry; + }; + + static void print_prompt(void) +@@ -172,6 +173,7 @@ static struct client *client_create(int fd, uint16_t mtu) + fprintf(stderr, "Failed to allocate memory for client\n"); + return NULL; + } ++ cli->sec_retry = true; + + cli->att = bt_att_new(fd, false); + if (!cli->att) { +@@ -488,6 +490,7 @@ static void cmd_read_multiple(struct client *cli, char *cmd_str) + char *argv[512]; + int i; + char *endptr = NULL; ++ unsigned int id; + + if (!bt_gatt_client_is_ready(cli->gatt)) { + printf("GATT client not initialized\n"); +@@ -514,9 +517,12 @@ static void cmd_read_multiple(struct client *cli, char *cmd_str) + } + } + +- if (!bt_gatt_client_read_multiple(cli->gatt, value, argc, +- read_multiple_cb, NULL, NULL)) ++ id = bt_gatt_client_read_multiple(cli->gatt, value, argc, ++ read_multiple_cb, NULL, NULL); ++ if (!id) + printf("Failed to initiate read multiple procedure\n"); ++ else if (!cli->sec_retry) ++ bt_gatt_client_set_retry(cli->gatt, id, false); + + free(value); + } +@@ -558,6 +564,7 @@ static void cmd_read_value(struct client *cli, char *cmd_str) + int argc = 0; + uint16_t handle; + char *endptr = NULL; ++ unsigned int id; + + if (!bt_gatt_client_is_ready(cli->gatt)) { + printf("GATT client not initialized\n"); +@@ -575,9 +582,12 @@ static void cmd_read_value(struct client *cli, char *cmd_str) + return; + } + +- if (!bt_gatt_client_read_value(cli->gatt, handle, read_cb, +- NULL, NULL)) ++ id = bt_gatt_client_read_value(cli->gatt, handle, read_cb, ++ NULL, NULL); ++ if (!id) + printf("Failed to initiate read value procedure\n"); ++ else if (!cli->sec_retry) ++ bt_gatt_client_set_retry(cli->gatt, id, false); + } + + static void read_long_value_usage(void) +@@ -592,6 +602,7 @@ static void cmd_read_long_value(struct client *cli, char *cmd_str) + uint16_t handle; + uint16_t offset; + char *endptr = NULL; ++ unsigned int id; + + if (!bt_gatt_client_is_ready(cli->gatt)) { + printf("GATT client not initialized\n"); +@@ -616,9 +627,12 @@ static void cmd_read_long_value(struct client *cli, char *cmd_str) + return; + } + +- if (!bt_gatt_client_read_long_value(cli->gatt, handle, offset, read_cb, +- NULL, NULL)) ++ id = bt_gatt_client_read_long_value(cli->gatt, handle, offset, read_cb, ++ NULL, NULL); ++ if (!id) + printf("Failed to initiate read long value procedure\n"); ++ else if (!cli->sec_retry) ++ bt_gatt_client_set_retry(cli->gatt, id, false); + } + + static void write_value_usage(void) +@@ -659,6 +673,7 @@ static void cmd_write_value(struct client *cli, char *cmd_str) + uint8_t *value = NULL; + bool without_response = false; + bool signed_write = false; ++ unsigned int id; + + if (!bt_gatt_client_is_ready(cli->gatt)) { + printf("GATT client not initialized\n"); +@@ -740,10 +755,13 @@ static void cmd_write_value(struct client *cli, char *cmd_str) + goto done; + } + +- if (!bt_gatt_client_write_value(cli->gatt, handle, value, length, ++ id = bt_gatt_client_write_value(cli->gatt, handle, value, length, + write_cb, +- NULL, NULL)) ++ NULL, NULL); ++ if (!id) + printf("Failed to initiate write procedure\n"); ++ else if (!cli->sec_retry) ++ bt_gatt_client_set_retry(cli->gatt, id, false); + + done: + free(value); +@@ -789,6 +807,7 @@ static void cmd_write_long_value(struct client *cli, char *cmd_str) + int length; + uint8_t *value = NULL; + bool reliable_writes = false; ++ unsigned int id; + + if (!bt_gatt_client_is_ready(cli->gatt)) { + printf("GATT client not initialized\n"); +@@ -863,11 +882,14 @@ static void cmd_write_long_value(struct client *cli, char *cmd_str) + } + } + +- if (!bt_gatt_client_write_long_value(cli->gatt, reliable_writes, handle, ++ id = bt_gatt_client_write_long_value(cli->gatt, reliable_writes, handle, + offset, value, length, + write_long_cb, +- NULL, NULL)) ++ NULL, NULL); ++ if (!id) + printf("Failed to initiate long write procedure\n"); ++ else if (!cli->sec_retry) ++ bt_gatt_client_set_retry(cli->gatt, id, false); + + free(value); + } +@@ -999,12 +1021,18 @@ done: + value, length, + write_long_cb, NULL, + NULL); +- if (!cli->reliable_session_id) ++ if (!cli->reliable_session_id) { + printf("Failed to proceed prepare write\n"); +- else ++ } else { ++ if (!cli->sec_retry) ++ bt_gatt_client_set_retry(cli->gatt, ++ cli->reliable_session_id, ++ false); ++ + printf("Prepare write success.\n" + "Session id: %d to be used on next write\n", + cli->reliable_session_id); ++ } + + free(value); + } +@@ -1236,6 +1264,36 @@ static void cmd_get_security(struct client *cli, char *cmd_str) + printf("Security level: %u\n", level); + } + ++static void set_security_retry_usage(void) ++{ ++ printf("Usage: set-security-retry \n" ++ "e.g.:\n" ++ "\tset-security-retry n\n"); ++} ++ ++static void cmd_set_security_retry(struct client *cli, char *cmd_str) ++{ ++ char *argv[2]; ++ int argc = 0; ++ ++ if (!bt_gatt_client_is_ready(cli->gatt)) { ++ printf("GATT client not initialized\n"); ++ return; ++ } ++ ++ if (!parse_args(cmd_str, 1, argv, &argc) || argc != 1) { ++ set_security_retry_usage(); ++ return; ++ } ++ ++ if (argv[0][0] == 'y') ++ cli->sec_retry = true; ++ else if (argv[0][0] == 'n') ++ cli->sec_retry = false; ++ else ++ printf("Invalid argument: %s\n", argv[0]); ++} ++ + static bool convert_sign_key(char *optarg, uint8_t key[16]) + { + int i; +@@ -1327,6 +1385,8 @@ static struct { + "\tSet security level on le connection"}, + { "get-security", cmd_get_security, + "\tGet security level on le connection"}, ++ { "set-security-retry", cmd_set_security_retry, ++ "\tSet retry on security error by elevating security"}, + { "set-sign-key", cmd_set_sign_key, + "\tSet signing key for signed write command"}, + { } +-- +2.34.1 + diff --git a/spec_files/bluez/0008-btgatt-client-Add-function-to-search-service-based-o.patch b/spec_files/bluez/0008-btgatt-client-Add-function-to-search-service-based-o.patch new file mode 100644 index 00000000..fa6cace4 --- /dev/null +++ b/spec_files/bluez/0008-btgatt-client-Add-function-to-search-service-based-o.patch @@ -0,0 +1,110 @@ +From fd39b61b38336cba2ef6fb3d0e2884f88e4ef0a8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Danis?= +Date: Thu, 25 Jan 2024 20:08:03 +0100 +Subject: [PATCH BlueZ 3/5] btgatt-client: Add function to search service based + on UUID +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: 8bit + +This is requested to pass PTS GATT/CL/GAD/BV-02-C test. +--- + tools/btgatt-client.c | 69 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 69 insertions(+) + +diff --git a/tools/btgatt-client.c b/tools/btgatt-client.c +index 3bcb7e1cf..99a123697 100644 +--- a/tools/btgatt-client.c ++++ b/tools/btgatt-client.c +@@ -33,6 +33,7 @@ + #include "src/shared/queue.h" + #include "src/shared/gatt-db.h" + #include "src/shared/gatt-client.h" ++#include "src/shared/gatt-helpers.h" + + #define ATT_CID 4 + +@@ -1353,6 +1354,72 @@ static void cmd_set_sign_key(struct client *cli, char *cmd_str) + set_sign_key_usage(); + } + ++static void search_service_usage(void) ++{ ++ printf("Usage: search-service \n" ++ "e.g.:\n" ++ "\tsearch-service 1800\n"); ++} ++ ++static void search_service_cb(bool success, uint8_t att_ecode, ++ struct bt_gatt_result *result, ++ void *user_data) ++{ ++ struct bt_gatt_iter iter; ++ uint16_t start_handle, end_handle; ++ uint128_t u128; ++ bt_uuid_t uuid; ++ char uuid_str[MAX_LEN_UUID_STR]; ++ ++ if (!success) { ++ PRLOG("\nService discovery failed: %s (0x%02x)\n", ++ ecode_to_string(att_ecode), att_ecode); ++ return; ++ } ++ ++ if (!result || !bt_gatt_iter_init(&iter, result)) ++ return; ++ ++ printf("\n"); ++ while (bt_gatt_iter_next_service(&iter, &start_handle, &end_handle, ++ u128.data)) { ++ bt_uuid128_create(&uuid, u128); ++ bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str)); ++ printf("Found start handle: 0x%04x, end handle: 0x%04x, " ++ "UUID: %s\n", ++ start_handle, end_handle, uuid_str); ++ } ++ PRLOG("\n"); ++} ++ ++static void cmd_search_service(struct client *cli, char *cmd_str) ++{ ++ char *argv[2]; ++ int argc = 0; ++ bt_uuid_t uuid; ++ ++ if (!bt_gatt_client_is_ready(cli->gatt)) { ++ printf("GATT client not initialized\n"); ++ return; ++ } ++ ++ if (!parse_args(cmd_str, 1, argv, &argc) || argc != 1) { ++ search_service_usage(); ++ return; ++ } ++ ++ if (bt_string_to_uuid(&uuid, argv[0]) < 0) { ++ printf("Invalid UUID: %s\n", argv[0]); ++ return; ++ } ++ ++ bt_gatt_discover_primary_services(bt_gatt_client_get_att(cli->gatt), ++ &uuid, 0x0001, 0xFFFF, ++ search_service_cb, ++ NULL, ++ NULL); ++} ++ + static void cmd_help(struct client *cli, char *cmd_str); + + typedef void (*command_func_t)(struct client *cli, char *cmd_str); +@@ -1389,6 +1456,8 @@ static struct { + "\tSet retry on security error by elevating security"}, + { "set-sign-key", cmd_set_sign_key, + "\tSet signing key for signed write command"}, ++ { "search-service", cmd_search_service, ++ "\tSearch service"}, + { } + }; + +-- +2.34.1 + diff --git a/spec_files/bluez/0009-btgatt-client-Add-function-to-search-characteristics.patch b/spec_files/bluez/0009-btgatt-client-Add-function-to-search-characteristics.patch new file mode 100644 index 00000000..3585853f --- /dev/null +++ b/spec_files/bluez/0009-btgatt-client-Add-function-to-search-characteristics.patch @@ -0,0 +1,117 @@ +From b36be985e700374f815c21fa7a787c4740edc1f4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Danis?= +Date: Thu, 25 Jan 2024 20:08:04 +0100 +Subject: [PATCH BlueZ 4/5] btgatt-client: Add function to search + characteristics +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: 8bit + +This is requested to pass PTS GATT/CL/GAD/BV-05-C test. +This search characteristics based on UUID, start and end handles. +--- + tools/btgatt-client.c | 82 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 82 insertions(+) + +diff --git a/tools/btgatt-client.c b/tools/btgatt-client.c +index 99a123697..04fd3ce0f 100644 +--- a/tools/btgatt-client.c ++++ b/tools/btgatt-client.c +@@ -1420,6 +1420,86 @@ static void cmd_search_service(struct client *cli, char *cmd_str) + NULL); + } + ++static void search_characteristics_usage(void) ++{ ++ printf("Usage: search-characteristics " ++ "\n" ++ "e.g.:\n" ++ "\tsearch-characteristics 0x0001 0xFFFF 1800\n"); ++} ++ ++static void search_characteristics_cb(bool success, uint8_t att_ecode, ++ struct bt_gatt_result *result, ++ void *user_data) ++{ ++ struct bt_gatt_iter iter; ++ uint16_t handle, length; ++ const uint8_t *value; ++ int i; ++ ++ if (!success) { ++ PRLOG("\nCharacteristics discovery failed: %s (0x%02x)\n", ++ ecode_to_string(att_ecode), att_ecode); ++ return; ++ } ++ ++ if (!result || !bt_gatt_iter_init(&iter, result)) ++ return; ++ ++ printf("\n"); ++ while (bt_gatt_iter_next_read_by_type(&iter, &handle, &length, ++ &value)) { ++ printf("Found handle: 0x%04x value: ", handle); ++ for (i = 0; i < length; i++) ++ printf("%02x ", value[i]); ++ printf("\n"); ++ } ++ PRLOG("\n"); ++} ++ ++static void cmd_search_characteristics(struct client *cli, char *cmd_str) ++{ ++ char *argv[4]; ++ int argc = 0; ++ uint16_t start_handle, end_handle; ++ char *endptr = NULL; ++ bt_uuid_t uuid; ++ ++ if (!bt_gatt_client_is_ready(cli->gatt)) { ++ printf("GATT client not initialized\n"); ++ return; ++ } ++ ++ if (!parse_args(cmd_str, 3, argv, &argc) || argc != 3) { ++ search_characteristics_usage(); ++ return; ++ } ++ ++ start_handle = strtol(argv[0], &endptr, 0); ++ if (!endptr || *endptr != '\0') { ++ printf("Invalid start handle: %s\n", argv[0]); ++ return; ++ } ++ ++ end_handle = strtol(argv[1], &endptr, 0); ++ if (!endptr || *endptr != '\0') { ++ printf("Invalid end handle: %s\n", argv[1]); ++ return; ++ } ++ ++ if (bt_string_to_uuid(&uuid, argv[2]) < 0) { ++ printf("Invalid UUID: %s\n", argv[2]); ++ return; ++ } ++ ++ bt_gatt_read_by_type(bt_gatt_client_get_att(cli->gatt), start_handle, ++ end_handle, ++ &uuid, ++ search_characteristics_cb, ++ NULL, ++ NULL); ++} ++ + static void cmd_help(struct client *cli, char *cmd_str); + + typedef void (*command_func_t)(struct client *cli, char *cmd_str); +@@ -1458,6 +1538,8 @@ static struct { + "\tSet signing key for signed write command"}, + { "search-service", cmd_search_service, + "\tSearch service"}, ++ { "search-characteristics", cmd_search_characteristics, ++ "\tSearch characteristics"}, + { } + }; + +-- +2.34.1 + diff --git a/spec_files/bluez/0010-btgatt-client-Add-function-to-search-all-primary-ser.patch b/spec_files/bluez/0010-btgatt-client-Add-function-to-search-all-primary-ser.patch new file mode 100644 index 00000000..1521de3c --- /dev/null +++ b/spec_files/bluez/0010-btgatt-client-Add-function-to-search-all-primary-ser.patch @@ -0,0 +1,71 @@ +From 52aa25f70651df9e9357fdab47bddd25e096d150 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Danis?= +Date: Thu, 25 Jan 2024 20:08:05 +0100 +Subject: [PATCH BlueZ 5/5] btgatt-client: Add function to search all primary + services +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: 8bit + +This is requested to pass PTS GATT/CL/GAD/BV-01-C test. +--- + tools/btgatt-client.c | 30 +++++++++++++++++++++++------- + 1 file changed, 23 insertions(+), 7 deletions(-) + +diff --git a/tools/btgatt-client.c b/tools/btgatt-client.c +index 04fd3ce0f..b47914da3 100644 +--- a/tools/btgatt-client.c ++++ b/tools/btgatt-client.c +@@ -1354,13 +1354,6 @@ static void cmd_set_sign_key(struct client *cli, char *cmd_str) + set_sign_key_usage(); + } + +-static void search_service_usage(void) +-{ +- printf("Usage: search-service \n" +- "e.g.:\n" +- "\tsearch-service 1800\n"); +-} +- + static void search_service_cb(bool success, uint8_t att_ecode, + struct bt_gatt_result *result, + void *user_data) +@@ -1392,6 +1385,27 @@ static void search_service_cb(bool success, uint8_t att_ecode, + PRLOG("\n"); + } + ++static void cmd_search_all_primary_services(struct client *cli, char *cmd_str) ++{ ++ if (!bt_gatt_client_is_ready(cli->gatt)) { ++ printf("GATT client not initialized\n"); ++ return; ++ } ++ ++ bt_gatt_discover_all_primary_services(bt_gatt_client_get_att(cli->gatt), ++ NULL, ++ search_service_cb, ++ NULL, ++ NULL); ++} ++ ++static void search_service_usage(void) ++{ ++ printf("Usage: search-service \n" ++ "e.g.:\n" ++ "\tsearch-service 1800\n"); ++} ++ + static void cmd_search_service(struct client *cli, char *cmd_str) + { + char *argv[2]; +@@ -1536,6 +1550,8 @@ static struct { + "\tSet retry on security error by elevating security"}, + { "set-sign-key", cmd_set_sign_key, + "\tSet signing key for signed write command"}, ++ { "search-all-primary-services", cmd_search_all_primary_services, ++ "\tSearch all primary services"}, + { "search-service", cmd_search_service, + "\tSearch service"}, + { "search-characteristics", cmd_search_characteristics, +-- +2.34.1 + diff --git a/spec_files/bluez/AVRCP_TG_MDI_BV-04-C.patch b/spec_files/bluez/AVRCP_TG_MDI_BV-04-C.patch index 8ce18411..38478f05 100644 --- a/spec_files/bluez/AVRCP_TG_MDI_BV-04-C.patch +++ b/spec_files/bluez/AVRCP_TG_MDI_BV-04-C.patch @@ -1,8 +1,7 @@ -diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c -index dda9a30..d0ae0a4 100644 ---- a/profiles/audio/avrcp.c -+++ b/profiles/audio/avrcp.c -@@ -1210,6 +1210,10 @@ static GList *player_list_metadata(struct avrcp_player *player) +diff -ru bluez-5.66.orig/profiles/audio/avrcp.c bluez-5.66/profiles/audio/avrcp.c +--- bluez-5.66.orig/profiles/audio/avrcp.c 2022-03-16 08:06:20.000000000 -0700 ++++ bluez-5.66/profiles/audio/avrcp.c 2023-07-30 08:03:17.414213611 -0700 +@@ -1210,6 +1210,10 @@ GUINT_TO_POINTER(str_to_metadata(key))); } @@ -13,3 +12,4 @@ index dda9a30..d0ae0a4 100644 return attrs; } +Only in bluez-5.66/profiles/audio: avrcp.c.orig diff --git a/spec_files/bluez/bluez.spec b/spec_files/bluez/bluez.spec index bf751061..dc4f0257 100644 --- a/spec_files/bluez/bluez.spec +++ b/spec_files/bluez/bluez.spec @@ -21,6 +21,11 @@ Patch2: power-state-adapter-property.patch Patch3: AVRCP_TG_MDI_BV-04-C.patch Patch4: 0001-valve-bluetooth-config.patch Patch5: 0002-valve-bluetooth-phy.patch +Patch6: 0006-shared-gatt-Prevent-security-level-change-for-PTS-GA.patch +Patch7: 0007-btgatt-client-Add-command-to-prevent-security-level-.patch +Patch8: 0008-btgatt-client-Add-function-to-search-service-based-o.patch +Patch9: 0009-btgatt-client-Add-function-to-search-characteristics.patch +Patch10: 0010-btgatt-client-Add-function-to-search-all-primary-ser.patch BuildRequires: dbus-devel >= 1.6 BuildRequires: glib2-devel