@@ -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 <y/n>\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"},
{ }