RE: [PATCH v3 7/7] tools/btgatt-client: Add prepare and execute write

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Lukasz,

> -----Original Message-----
> From: linux-bluetooth-owner@xxxxxxxxxxxxxxx [mailto:linux-bluetooth-
> owner@xxxxxxxxxxxxxxx] On Behalf Of Lukasz Rymanowski
> Sent: Friday, March 06, 2015 10:19 PM
> To: linux-bluetooth@xxxxxxxxxxxxxxx
> Cc: Lukasz Rymanowski
> Subject: [PATCH v3 7/7] tools/btgatt-client: Add prepare and execute write
> 
> ---
>  tools/btgatt-client.c | 204
> ++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 204 insertions(+)
> 
> diff --git a/tools/btgatt-client.c b/tools/btgatt-client.c index
> e2e0d15..6a0eae8 100644
> --- a/tools/btgatt-client.c
> +++ b/tools/btgatt-client.c
> @@ -67,6 +67,8 @@ struct client {
>  	struct bt_att *att;
>  	struct gatt_db *db;
>  	struct bt_gatt_client *gatt;
> +
> +	unsigned int reliable_session_id;
>  };
> 
>  static void print_prompt(void)
> @@ -884,6 +886,204 @@ static void cmd_write_long_value(struct client *cli,
> char *cmd_str)
>  	free(value);
>  }
> 
> +static void write_prepare_usage(void)
> +{
> +	printf("Usage: write-prepare [options] <value_handle> <offset> "
> +				"<value>\n"
> +				"Options:\n"
> +				"\t-s, --session-id\tSession id\n"
> +				"e.g.:\n"
> +				"\twrite-prepare -s 1 0x0001 00 01 00\n"); }
> +
> +static struct option write_prepare_options[] = {
> +	{ "session-id",		1, 0, 's' },
> +	{ }
> +};
> +
> +static void cmd_write_prepare(struct client *cli, char *cmd_str) {
> +	int opt, i;
> +	char *argvbuf[516];
> +	char **argv = argvbuf;
> +	int argc = 0;
> +	unsigned int id = 0;
> +	uint16_t handle;
> +	uint16_t offset;
> +	char *endptr = NULL;
> +	unsigned int length;
> +	uint8_t *value = NULL;
> +
> +	if (!bt_gatt_client_is_ready(cli->gatt)) {
> +		printf("GATT client not initialized\n");
> +		return;
> +	}
> +
> +	if (!parse_args(cmd_str, 514, argv + 1, &argc)) {
> +		printf("Too many arguments\n");
> +		write_value_usage();
> +		return;
> +	}
> +
> +	/* Add command name for getopt_long */
> +	argc++;
> +	argv[0] = "write-prepare";
> +
> +	optind = 0;
> +	while ((opt = getopt_long(argc, argv , "s:", write_prepare_options,
> +								NULL)) !=
-1) {
> +		switch (opt) {
> +		case 's':
> +			if (!optarg) {
> +				write_prepare_usage();
> +				return;
> +			}
> +
> +			id = atoi(optarg);
> +
> +			break;
> +		default:
> +			write_prepare_usage();
> +			return;
> +		}
> +	}
> +
> +	argc -= optind;
> +	argv += optind;
> +
> +	if (argc < 3) {
> +		write_prepare_usage();
> +		return;
> +	}
> +
> +	if (cli->reliable_session_id != id) {
> +		printf("Session id != Ongoing session id (%u!=%u)\n", id,
> +						cli->reliable_session_id);
> +		return;
> +	}
> +
> +	handle = strtol(argv[0], &endptr, 0);
> +	if (!endptr || *endptr != '\0' || !handle) {
> +		printf("Invalid handle: %s\n", argv[0]);
> +		return;
> +	}
> +
> +	endptr = NULL;
> +	offset = strtol(argv[1], &endptr, 0);
> +	if (!endptr || *endptr != '\0' || errno == ERANGE) {
> +		printf("Invalid offset: %s\n", argv[1]);
> +		return;
> +	}
> +
> +	/*
> +	 * First two arguments are handle and offset. What remains is the
> value
> +	 * length
> +	 */
> +	length = argc - 2;
> +
> +	if (length == 0)
> +		goto done;
> +
> +	if (length > UINT16_MAX) {
> +		printf("Write value too long\n");
> +		return;
> +	}
> +
> +	value = malloc(length);
> +	if (!value) {
> +		printf("Failed to allocate memory for value\n");
> +		return;
> +	}
> +
> +	for (i = 2; i < argc; i++) {
> +		if (strlen(argv[i]) != 2) {
> +			printf("Invalid value byte: %s\n", argv[i]);
> +			free(value);
> +			return;
> +		}
> +
> +		value[i-2] = strtol(argv[i], &endptr, 0);
> +		if (endptr == argv[i] || *endptr != '\0' || errno == ERANGE)
{
> +			printf("Invalid value byte: %s\n", argv[i]);
> +			free(value);
> +			return;
> +		}
> +	}
> +
> +done:
> +	cli->reliable_session_id =
> +			bt_gatt_client_prepare_write(cli->gatt, id,
> +							handle, offset,
> +							value, length,
> +							write_long_cb, NULL,
> +							NULL);
> +	if (!cli->reliable_session_id)
> +		printf("Failed to proceed prepare write\n");
> +	else
> +		printf("Prepare write success.\n"
> +				"Session id: %d to be used on next write\n",
> +						cli->reliable_session_id);
> +
> +	free(value);
> +}
> +
> +static void write_execute_usage(void)
> +{
> +	printf("Usage: write-execute <session_id> <execute>\n"
> +				"e.g.:\n"
> +				"\twrite-execute 1 0\n");
> +}
> +
> +static void cmd_write_execute(struct client *cli, char *cmd_str) {
> +	char *argvbuf[516];
> +	char **argv = argvbuf;
> +	int argc = 0;
> +	char *endptr = NULL;
> +	unsigned int session_id;
> +	bool execute;
> +
> +	if (!bt_gatt_client_is_ready(cli->gatt)) {
> +		printf("GATT client not initialized\n");
> +		return;
> +	}
> +
> +	if (!parse_args(cmd_str, 514, argv, &argc)) {
> +		printf("Too many arguments\n");
> +		write_value_usage();
> +		return;
> +	}
> +
> +	if (argc < 2) {
> +		write_execute_usage();
> +		return;
> +	}
> +
> +	session_id = strtol(argv[0], &endptr, 0);
> +	if (!endptr || *endptr != '\0') {
> +		printf("Invalid session id: %s\n", argv[0]);
> +		return;
> +	}
> +
> +	if (session_id != cli->reliable_session_id) {
> +		printf("Invalid session id: %u != %u\n", session_id,
> +						cli->reliable_session_id);
> +		return;
> +	}
> +

I applied this patch set internally and tested the prepare write and execute
functionality using PTS tool.
Listed below are few fixes which I am able to figure out.

I think '!!' here is not required, unless there is some specific reason.

> +	execute = !!strtol(argv[1], &endptr, 0);
> +	if (!endptr || *endptr != '\0') {
> +		printf("Invalid execute: %s\n", argv[1]);
> +		return;
> +	}
> +

The function defined in src/shared/gatt-client.h.

unsigned int bt_gatt_client_write_execute(struct bt_gatt_client *client,
                                        bool execute,
                                        unsigned int id,
                                        bt_gatt_client_callback_t callback,
                                        void *user_data,
                                        bt_gatt_client_destroy_func_t
destroy);

Function parameters are not matching.
Other than these, it is passing all reliable write Test Cases.

> +	if (!bt_gatt_client_write_execute(cli->gatt, session_id, execute,
> +							write_cb, NULL,
> NULL))
> +		printf("Failed to proceed write execute\n");
> +
> +	cli->reliable_session_id = 0;
> +}
> +
>  static void register_notify_usage(void)  {
>  	printf("Usage: register-notify <chrc value handle>\n"); @@ -1130,6
> +1330,10 @@ static struct {
>  			"\tWrite a characteristic or descriptor value" },
>  	{ "write-long-value", cmd_write_long_value,
>  			"Write long characteristic or descriptor value" },
> +	{ "write-prepare", cmd_write_prepare,
> +			"\tWrite prepare characteristic or descriptor value"
},
> +	{ "write-execute", cmd_write_execute,
> +			"\tExecute already prepared write" },
>  	{ "register-notify", cmd_register_notify,
>  			"\tSubscribe to not/ind from a characteristic" },
>  	{ "unregister-notify", cmd_unregister_notify,
> --
> 1.8.4
> 

Regards,
Gowtham Anandha Babu

> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth"
in
> the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo
> info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux