static void cmd_unregister_notify(struct client *cli, char *cmd_str) { char *argv[2]; int argc = 0; unsigned int id; char *endptr = NULL; 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) { unregister_notify_usage(); return; } id = strtol(argv[0], &endptr, 10); if (!endptr || *endptr != '\0' || !id) { printf("Invalid notify id: %s\n", argv[0]); return; } if (!bt_gatt_client_unregister_notify(cli->gatt, id)) { printf("Failed to unregister notify handler with id: %u\n", id); return; } printf("Unregistered notify handler with id: %u\n", id); }
static void cmd_read_long_value(struct client *cli, char *cmd_str) { char *argv[3]; int argc = 0; uint16_t handle; uint16_t offset; char *endptr = NULL; if (!bt_gatt_client_is_ready(cli->gatt)) { printf("GATT client not initialized\n"); return; } if (!parse_args(cmd_str, 2, argv, &argc) || argc != 2) { read_long_value_usage(); return; } handle = strtol(argv[0], &endptr, 16); if (!endptr || *endptr != '\0' || !handle) { printf("Invalid value handle: %s\n", argv[0]); return; } endptr = NULL; offset = strtol(argv[1], &endptr, 16); if (!endptr || *endptr != '\0' || !handle) { printf("Invalid offset: %s\n", argv[1]); return; } if (!bt_gatt_client_read_long_value(cli->gatt, handle, offset, read_cb, NULL, NULL)) printf("Failed to initiate read long value procedure\n"); }
static void cmd_register_notify(struct client *cli, char *cmd_str) { char *argv[2]; int argc = 0; uint16_t value_handle; char *endptr = NULL; 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) { register_notify_usage(); return; } value_handle = strtol(argv[0], &endptr, 16); if (!endptr || *endptr != '\0' || !value_handle) { printf("Invalid value handle: %s\n", argv[0]); return; } if (!bt_gatt_client_register_notify(cli->gatt, value_handle, register_notify_cb, notify_cb, NULL, NULL)) printf("Failed to register notify handler\n"); printf("\n"); }
static void cmd_set_security(struct client *cli, char *cmd_str) { char *argv[2]; int argc = 0; char *endptr = NULL; int level; if (!bt_gatt_client_is_ready(cli->gatt)) { printf("GATT client not initialized\n"); return; } if (!parse_args(cmd_str, 1, argv, &argc)) { printf("Too many arguments\n"); set_security_usage(); return; } if (argc < 1) { set_security_usage(); return; } level = strtol(argv[0], &endptr, 0); if (!endptr || *endptr != '\0' || level < 1 || level > 3) { printf("Invalid level: %s\n", argv[0]); return; } if (!bt_gatt_client_set_security(cli->gatt, level)) printf("Could not set sec level\n"); else printf("Setting security level %d success\n", level); }
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; } execute = !!strtol(argv[1], &endptr, 0); if (!endptr || *endptr != '\0') { printf("Invalid execute: %s\n", argv[1]); return; } if (execute) { if (!bt_gatt_client_write_execute(cli->gatt, session_id, write_cb, NULL, NULL)) printf("Failed to proceed write execute\n"); } else { bt_gatt_client_cancel(cli->gatt, session_id); } cli->reliable_session_id = 0; }
static void cmd_services(struct client *cli, char *cmd_str) { char *argv[3]; int argc = 0; if (!bt_gatt_client_is_ready(cli->gatt)) { printf("GATT client not initialized\n"); return; } if (!parse_args(cmd_str, 2, argv, &argc)) { services_usage(); return; } if (!argc) { print_services(cli); return; } if (argc != 2) { services_usage(); return; } if (!strcmp(argv[0], "-u") || !strcmp(argv[0], "--uuid")) { bt_uuid_t tmp, uuid; if (bt_string_to_uuid(&tmp, argv[1]) < 0) { printf("Invalid UUID: %s\n", argv[1]); return; } bt_uuid_to_uuid128(&tmp, &uuid); print_services_by_uuid(cli, &uuid); } else if (!strcmp(argv[0], "-a") || !strcmp(argv[0], "--handle")) { uint16_t handle; char *endptr = NULL; handle = strtol(argv[1], &endptr, 16); if (!endptr || *endptr != '\0') { printf("Invalid start handle: %s\n", argv[1]); return; } print_services_by_handle(cli, handle); } else services_usage(); }
static void cmd_get_security(struct client *cli, char *cmd_str) { int level; if (!bt_gatt_client_is_ready(cli->gatt)) { printf("GATT client not initialized\n"); return; } level = bt_gatt_client_get_security(cli->gatt); if (level < 0) printf("Could not set sec level\n"); else printf("Security level: %u\n", level); }
static void cmd_read_multiple(struct client *cli, char *cmd_str) { int argc = 0; uint16_t *value; char *argv[512]; int i; char *endptr = NULL; if (!bt_gatt_client_is_ready(cli->gatt)) { printf("GATT client not initialized\n"); return; } if (!parse_args(cmd_str, sizeof(argv), argv, &argc) || argc < 2) { read_multiple_usage(); return; } value = malloc(sizeof(uint16_t) * argc); if (!value) { printf("Failed to construct value\n"); return; } for (i = 0; i < argc; i++) { value[i] = strtol(argv[i], &endptr, 0); if (endptr == argv[i] || *endptr != '\0' || !value[i]) { printf("Invalid value byte: %s\n", argv[i]); free(value); return; } } if (!bt_gatt_client_read_multiple(cli->gatt, value, argc, read_multiple_cb, NULL, NULL)) printf("Failed to initiate read multiple procedure\n"); free(value); }
static void service_added(struct gatt_db_attribute *attr, void *user_data) { struct gas *gas = user_data; bt_uuid_t uuid, gap_uuid; if (!bt_gatt_client_is_ready(gas->client)) return; gatt_db_attribute_get_service_uuid(attr, &uuid); bt_uuid16_create(&gap_uuid, GAP_UUID16); if (bt_uuid_cmp(&uuid, &gap_uuid)) return; if (gas->attr) { error("More than one GAP service added to device"); return; } DBG("GAP service added"); gas->attr = attr; handle_gap_service(gas); }
static void cmd_write_long_value(struct client *cli, char *cmd_str) { int opt, i; char *argvbuf[516]; char **argv = argvbuf; int argc = 1; uint16_t handle; uint16_t offset; char *endptr = NULL; int length; uint8_t *value = NULL; bool reliable_writes = false; 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; } optind = 0; argv[0] = "write-long-value"; while ((opt = getopt_long(argc, argv, "+r", write_long_value_options, NULL)) != -1) { switch (opt) { case 'r': reliable_writes = true; break; default: write_long_value_usage(); return; } } argc -= optind; argv += optind; if (argc < 2) { write_long_value_usage(); return; } handle = strtol(argv[0], &endptr, 16); if (!endptr || *endptr != '\0' || !handle) { printf("Invalid handle: %s\n", argv[0]); return; } endptr = NULL; offset = strtol(argv[1], &endptr, 10); if (!endptr || *endptr != '\0' || errno == ERANGE) { printf("Invalid offset: %s\n", argv[1]); return; } length = argc - 1; if (length > 0) { if (length > UINT16_MAX) { printf("Write value too long\n"); return; } value = malloc(length); if (!value) { printf("Failed to construct write 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, 16); if (endptr == argv[i] || *endptr != '\0' || errno == ERANGE) { printf("Invalid value byte: %s\n", argv[i]); free(value); return; } } } if (!bt_gatt_client_write_long_value(cli->gatt, reliable_writes, handle, offset, value, length, write_long_cb, NULL, NULL)) printf("Failed to initiate long write procedure\n"); free(value); }
static void cmd_write_value(struct client *cli, char *cmd_str) { int opt, i; char *argvbuf[516]; char **argv = argvbuf; int argc = 1; uint16_t handle; char *endptr = NULL; int length; uint8_t *value = NULL; bool without_response = false; 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; } optind = 0; argv[0] = "write-value"; while ((opt = getopt_long(argc, argv, "+w", write_value_options, NULL)) != -1) { switch (opt) { case 'w': without_response = true; break; default: write_value_usage(); return; } } argc -= optind; argv += optind; if (argc < 1) { write_value_usage(); return; } handle = strtol(argv[0], &endptr, 16); if (!endptr || *endptr != '\0' || !handle) { printf("Invalid handle: %s\n", argv[0]); return; } length = argc - 1; if (length > 0) { if (length > UINT16_MAX) { printf("Write value too long\n"); return; } value = malloc(length); if (!value) { printf("Failed to construct write value\n"); return; } for (i = 1; i < argc; i++) { if (strlen(argv[i]) != 2) { printf("Invalid value byte: %s\n", argv[i]); goto done; } value[i-1] = strtol(argv[i], &endptr, 16); if (endptr == argv[i] || *endptr != '\0' || errno == ERANGE) { printf("Invalid value byte: %s\n", argv[i]); goto done; } } } if (without_response) { if (!bt_gatt_client_write_without_response(cli->gatt, handle, false, value, length)) { printf("Failed to initiate write without response " "procedure\n"); goto done; } printf("Write command sent\n"); goto done; } if (!bt_gatt_client_write_value(cli->gatt, handle, value, length, write_cb, NULL, NULL)) printf("Failed to initiate write procedure\n"); done: free(value); }
static void cmd_write_prepare(struct client *cli, char *cmd_str) { int opt, i, val; 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++) { val = strtol(argv[i], &endptr, 0); if (endptr == argv[i] || *endptr != '\0' || errno == ERANGE || val < 0 || val > 255) { printf("Invalid value byte: %s\n", argv[i]); free(value); return; } value[i-2] = val; } 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); }