int bt_uuid_strcmp(const void *a, const void *b) { bt_uuid_t u1, u2; bt_string_to_uuid(&u1, a); bt_string_to_uuid(&u2, b); return bt_uuid_cmp(&u1, &u2); }
static void cmd_primary(int argcp, char **argvp) { bt_uuid_t uuid; if (conn_state != STATE_CONNECTED) { printf("Command failed: disconnected\n"); goto done; } if (argcp == 1) { gatt_discover_primary(attrib, NULL, primary_all_cb, NULL); goto done; } if (bt_string_to_uuid(&uuid, argvp[1]) < 0) { printf("Invalid UUID\n"); goto done; } gatt_discover_primary(attrib, &uuid, primary_by_uuid_cb, NULL); return; done: printf("\r%s", get_prompt()); fflush(stdout); }
static bool parse_advertising_service_data(GDBusProxy *proxy, struct bt_ad *data) { DBusMessageIter iter, entries; if (!g_dbus_proxy_get_property(proxy, "ServiceData", &iter)) return true; if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) return false; dbus_message_iter_recurse(&iter, &entries); bt_ad_clear_service_data(data); while (dbus_message_iter_get_arg_type(&entries) == DBUS_TYPE_DICT_ENTRY) { DBusMessageIter value, entry; const char *uuid_str; bt_uuid_t uuid; uint8_t *service_data; int len; dbus_message_iter_recurse(&entries, &entry); dbus_message_iter_get_basic(&entry, &uuid_str); if (bt_string_to_uuid(&uuid, uuid_str) < 0) goto fail; dbus_message_iter_next(&entry); if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_ARRAY) goto fail; dbus_message_iter_recurse(&entry, &value); if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_BYTE) goto fail; dbus_message_iter_get_fixed_array(&value, &service_data, &len); DBG("Adding ServiceData for %s", uuid_str); if (!bt_ad_add_service_data(data, &uuid, service_data, len)) goto fail; dbus_message_iter_next(&entries); } return true; fail: bt_ad_clear_service_data(data); return false; }
static void cmd_read_uuid(int argcp, char **argvp) { struct characteristic_data *char_data; int start = 0x0001; int end = 0xffff; bt_uuid_t uuid; if (conn_state != STATE_CONNECTED) { printf("Command failed: disconnected\n"); goto done; } if (argcp < 2) { printf("Missing argument: UUID\n"); goto done; } if (bt_string_to_uuid(&uuid, argvp[1]) < 0) { printf("Invalid UUID\n"); goto done; } if (argcp > 2) { start = strtohandle(argvp[2]); if (start < 0) { printf("Invalid start handle: %s\n", argvp[1]); goto done; } } if (argcp > 3) { end = strtohandle(argvp[3]); if (end < 0) { printf("Invalid end handle: %s\n", argvp[2]); goto done; } } char_data = g_new(struct characteristic_data, 1); char_data->orig_start = start; char_data->start = start; char_data->end = end; char_data->uuid = uuid; gatt_read_char_by_uuid(attrib, start, end, &char_data->uuid, char_read_by_uuid_cb, char_data); done: printf("\r%s", get_prompt()); fflush(stdout); }
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 gboolean parse_uuid(const char *key, const char *value, gpointer user_data, GError **error) { if (!value) return FALSE; opt_uuid = g_try_malloc(sizeof(bt_uuid_t)); if (opt_uuid == NULL) return FALSE; if (bt_string_to_uuid(opt_uuid, value) < 0) return FALSE; return TRUE; }
static void discover_services(void) { if (conn_state != STATE_CONNECTED) { failed("Disconnected\n"); return; } bt_uuid_t uuid; if (bt_string_to_uuid(&uuid, ANKI_STR_SERVICE_UUID) < 0) { error("Error attempting to discover service for UUID: %s\n", ANKI_STR_SERVICE_UUID); return; } gatt_discover_primary(attrib, &uuid, discover_services_cb, NULL); }
// Initialize the characteristics with Amiigo defaults void char_init() { memset(g_char, 0, sizeof(g_char)); int i; for (i = 0; i < AMIIGO_UUID_COUNT; ++i) bt_string_to_uuid(&g_char[i].uuid, g_szUUID[i]); // Set default handles g_char[AMIIGO_UUID_STATUS].value_handle = 0x0025; g_char[AMIIGO_UUID_CONFIG].value_handle = 0x0027; g_char[AMIIGO_UUID_LOGBLOCK].value_handle = 0x0029; g_char[AMIIGO_UUID_FIRMWARE].value_handle = 0x002c; g_char[AMIIGO_UUID_DEBUG].value_handle = 0x002e; g_char[AMIIGO_UUID_BUILD].value_handle = 0x0030; g_char[AMIIGO_UUID_VERSION].value_handle = 0x0032; }
static void cmd_char(int argcp, char **argvp) { int start = 0x0001; int end = 0xffff; if (conn_state != STATE_CONNECTED) { printf("Command failed: disconnected\n"); goto done; } if (argcp > 1) { start = strtohandle(argvp[1]); if (start < 0) { printf("Invalid start handle: %s\n", argvp[1]); goto done; } } if (argcp > 2) { end = strtohandle(argvp[2]); if (end < 0) { printf("Invalid end handle: %s\n", argvp[2]); goto done; } } if (argcp > 3) { bt_uuid_t uuid; if (bt_string_to_uuid(&uuid, argvp[3]) < 0) { printf("Invalid UUID\n"); goto done; } g_attrib_ref(attrib); gatt_discover_char(attrib, start, end, &uuid, char_cb, NULL); return; } g_attrib_ref(attrib); gatt_discover_char(attrib, start, end, NULL, char_cb, NULL); return; done: printf("\r%s", get_prompt()); fflush(stdout); }
static int deviceinfo_driver_accept(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); struct gatt_db *db = btd_device_get_gatt_db(device); char addr[18]; bt_uuid_t deviceinfo_uuid; ba2str(device_get_address(device), addr); DBG("deviceinfo profile accept (%s)", addr); /* Handle the device info service */ bt_string_to_uuid(&deviceinfo_uuid, DEVICE_INFORMATION_UUID); gatt_db_foreach_service(db, &deviceinfo_uuid, foreach_deviceinfo_service, device); return 0; }
static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data) { struct hog_device *hogdev = user_data; struct gatt_primary *prim = hogdev->hog_primary; bt_uuid_t report_uuid, report_map_uuid, info_uuid; bt_uuid_t proto_mode_uuid, ctrlpt_uuid; struct report *report; GSList *l; uint16_t info_handle = 0, proto_mode_handle = 0; if (status != 0) { const char *str = att_ecode2str(status); DBG("Discover all characteristics failed: %s", str); return; } bt_uuid16_create(&report_uuid, HOG_REPORT_UUID); bt_uuid16_create(&report_map_uuid, HOG_REPORT_MAP_UUID); bt_uuid16_create(&info_uuid, HOG_INFO_UUID); bt_uuid16_create(&proto_mode_uuid, HOG_PROTO_MODE_UUID); bt_uuid16_create(&ctrlpt_uuid, HOG_CONTROL_POINT_UUID); for (l = chars; l; l = g_slist_next(l)) { struct gatt_char *chr, *next; bt_uuid_t uuid; uint16_t start, end; chr = l->data; next = l->next ? l->next->data : NULL; DBG("0x%04x UUID: %s properties: %02x", chr->handle, chr->uuid, chr->properties); bt_string_to_uuid(&uuid, chr->uuid); start = chr->value_handle + 1; end = (next ? next->handle - 1 : prim->range.end); if (bt_uuid_cmp(&uuid, &report_uuid) == 0) { report = g_new0(struct report, 1); report->hogdev = hogdev; report->decl = g_memdup(chr, sizeof(*chr)); hogdev->reports = g_slist_append(hogdev->reports, report); discover_descriptor(hogdev->attrib, start, end, report); } else if (bt_uuid_cmp(&uuid, &report_map_uuid) == 0) {
static void cmd_read_uuid(int argcp, char **argvp) { struct characteristic_data *char_data; int start = 0x0001; int end = 0xffff; bt_uuid_t uuid; if (conn_state != STATE_CONNECTED) { resp_error(err_BAD_STATE); return; } if (argcp < 2 || bt_string_to_uuid(&uuid, argvp[1]) < 0) { resp_error(err_BAD_PARAM); return; } if (argcp > 2) { start = strtohandle(argvp[2]); if (start < 0) { resp_error(err_BAD_PARAM); return; } } if (argcp > 3) { end = strtohandle(argvp[3]); if (end < 0) { resp_error(err_BAD_PARAM); return; } } char_data = g_new(struct characteristic_data, 1); char_data->orig_start = start; char_data->start = start; char_data->end = end; char_data->uuid = uuid; gatt_read_char_by_uuid(attrib, start, end, &char_data->uuid, char_read_by_uuid_cb, char_data); }
static void cmd_primary(int argcp, char **argvp) { bt_uuid_t uuid; if (conn_state != STATE_CONNECTED) { resp_error(err_BAD_STATE); return; } if (argcp == 1) { gatt_discover_primary(attrib, NULL, primary_all_cb, NULL); return; } if (bt_string_to_uuid(&uuid, argvp[1]) < 0) { resp_error(err_BAD_PARAM); return; } gatt_discover_primary(attrib, &uuid, primary_by_uuid_cb, NULL); }
static void cmd_primary(int argcp, char **argvp) { bt_uuid_t uuid; if (conn_state != STATE_CONNECTED) { failed("Disconnected\n"); return; } if (argcp == 1) { gatt_discover_primary(attrib, NULL, primary_all_cb, NULL); return; } if (bt_string_to_uuid(&uuid, argvp[1]) < 0) { error("Invalid UUID\n"); return; } gatt_discover_primary(attrib, &uuid, primary_by_uuid_cb, NULL); }
static void cmd_char(int argcp, char **argvp) { int start = 0x0001; int end = 0xffff; if (conn_state != STATE_CONNECTED) { resp_error(err_BAD_STATE); return; } if (argcp > 1) { start = strtohandle(argvp[1]); if (start < 0) { resp_error(err_BAD_PARAM); return; } } if (argcp > 2) { end = strtohandle(argvp[2]); if (end < 0) { resp_error(err_BAD_PARAM); return; } } if (argcp > 3) { bt_uuid_t uuid; if (bt_string_to_uuid(&uuid, argvp[3]) < 0) { resp_error(err_BAD_PARAM); return; } gatt_discover_char(attrib, start, end, &uuid, char_cb, NULL); return; } gatt_discover_char(attrib, start, end, NULL, char_cb, NULL); }
static void cmd_read_uuid(int argcp, char **argvp) { int start = 0x0001; int end = 0xffff; bt_uuid_t uuid; if (conn_state != STATE_CONNECTED) { failed("Disconnected\n"); return; } if (argcp < 2) { error("Missing argument: UUID\n"); return; } if (bt_string_to_uuid(&uuid, argvp[1]) < 0) { error("Invalid UUID\n"); return; } if (argcp > 2) { start = strtohandle(argvp[2]); if (start < 0) { error("Invalid start handle: %s\n", argvp[1]); return; } } if (argcp > 3) { end = strtohandle(argvp[3]); if (end < 0) { error("Invalid end handle: %s\n", argvp[2]); return; } } gatt_read_char_by_uuid(attrib, start, end, &uuid, char_read_by_uuid_cb, NULL); }
static void cmd_char(int argcp, char **argvp) { int start = 0x0001; int end = 0xffff; if (conn_state != STATE_CONNECTED) { printf("Command failed: disconnected\n"); return; } if (argcp > 1) { start = strtohandle(argvp[1]); if (start < 0) { printf("Invalid start handle: %s\n", argvp[1]); return; } } if (argcp > 2) { end = strtohandle(argvp[2]); if (end < 0) { printf("Invalid end handle: %s\n", argvp[2]); return; } } if (argcp > 3) { bt_uuid_t uuid; if (bt_string_to_uuid(&uuid, argvp[3]) < 0) { printf("Invalid UUID\n"); return; } gatt_discover_char(g_connection->attrib, start, end, &uuid, char_cb, NULL); return; } gatt_discover_char(g_connection->attrib, start, end, NULL, char_cb, NULL); }
static struct network_server *find_server_by_uuid(GSList *list, const char *uuid) { bt_uuid_t srv_uuid, bnep_uuid; if (!bt_string_to_uuid(&srv_uuid, uuid)) { for (; list; list = list->next) { struct network_server *ns = list->data; bt_uuid16_create(&bnep_uuid, ns->id); /* UUID value compare */ if (!bt_uuid_cmp(&srv_uuid, &bnep_uuid)) return ns; } } else { for (; list; list = list->next) { struct network_server *ns = list->data; /* String value compare */ switch (ns->id) { case BNEP_SVC_PANU: if (!strcasecmp(uuid, "panu")) return ns; break; case BNEP_SVC_NAP: if (!strcasecmp(uuid, "nap")) return ns; break; case BNEP_SVC_GN: if (!strcasecmp(uuid, "gn")) return ns; break; } } } return NULL; }
static bool parse_advertising_solicit_uuids(GDBusProxy *proxy, struct bt_ad *data) { DBusMessageIter iter, ariter; if (!g_dbus_proxy_get_property(proxy, "SolicitUUIDs", &iter)) return true; if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) return false; dbus_message_iter_recurse(&iter, &ariter); bt_ad_clear_solicit_uuid(data); while (dbus_message_iter_get_arg_type(&ariter) == DBUS_TYPE_STRING) { const char *uuid_str; bt_uuid_t uuid; dbus_message_iter_get_basic(&ariter, &uuid_str); DBG("Adding SolicitUUID: %s", uuid_str); if (bt_string_to_uuid(&uuid, uuid_str) < 0) goto fail; if (!bt_ad_add_solicit_uuid(data, &uuid)) goto fail; dbus_message_iter_next(&ariter); } return true; fail: bt_ad_clear_solicit_uuid(data); return false; }
static void handle_characteristic(struct gatt_db_attribute *attr, void *user_data) { struct btd_device *device = user_data; uint16_t value_handle; bt_uuid_t uuid, pnpid_uuid; bt_string_to_uuid(&pnpid_uuid, PNPID_UUID); if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle, NULL, NULL, &uuid)) { error("Failed to obtain characteristic data"); return; } if (bt_uuid_cmp(&pnpid_uuid, &uuid) == 0) handle_pnpid(device, value_handle); else { char uuid_str[MAX_LEN_UUID_STR]; bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str)); DBG("Unsupported characteristic: %s", uuid_str); } }
static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data) { struct bt_hog *hog = user_data; struct gatt_primary *primary = hog->primary; bt_uuid_t report_uuid, report_map_uuid, info_uuid; bt_uuid_t proto_mode_uuid, ctrlpt_uuid; struct report *report; GSList *l; uint16_t info_handle = 0, proto_mode_handle = 0; if (status != 0) { const char *str = att_ecode2str(status); DBG("Discover all characteristics failed: %s", str); return; } bt_uuid16_create(&report_uuid, HOG_REPORT_UUID); bt_uuid16_create(&report_map_uuid, HOG_REPORT_MAP_UUID); bt_uuid16_create(&info_uuid, HOG_INFO_UUID); bt_uuid16_create(&proto_mode_uuid, HOG_PROTO_MODE_UUID); bt_uuid16_create(&ctrlpt_uuid, HOG_CONTROL_POINT_UUID); for (l = chars; l; l = g_slist_next(l)) { struct gatt_char *chr, *next; bt_uuid_t uuid; uint16_t start, end; chr = l->data; next = l->next ? l->next->data : NULL; DBG("0x%04x UUID: %s properties: %02x", chr->handle, chr->uuid, chr->properties); bt_string_to_uuid(&uuid, chr->uuid); start = chr->value_handle + 1; end = (next ? next->handle - 1 : primary->range.end); if (bt_uuid_cmp(&uuid, &report_uuid) == 0) { report = report_new(hog, chr); discover_report(hog->attrib, start, end, report); } else if (bt_uuid_cmp(&uuid, &report_map_uuid) == 0) { gatt_read_char(hog->attrib, chr->value_handle, report_map_read_cb, hog); discover_external(hog->attrib, start, end, hog); } else if (bt_uuid_cmp(&uuid, &info_uuid) == 0) info_handle = chr->value_handle; else if (bt_uuid_cmp(&uuid, &proto_mode_uuid) == 0) proto_mode_handle = chr->value_handle; else if (bt_uuid_cmp(&uuid, &ctrlpt_uuid) == 0) hog->ctrlpt_handle = chr->value_handle; } if (proto_mode_handle) { hog->proto_mode_handle = proto_mode_handle; gatt_read_char(hog->attrib, proto_mode_handle, proto_mode_read_cb, hog); } if (info_handle) gatt_read_char(hog->attrib, info_handle, info_read_cb, hog); }
int gattlib_string_to_uuid(bt_uuid_t *uuid, const char *str) { return bt_string_to_uuid(uuid, str); }