static void external_report_reference_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { struct hog_device *hogdev = user_data; uint16_t uuid16; bt_uuid_t uuid; if (status != 0) { error("Read External Report Reference descriptor failed: %s", att_ecode2str(status)); return; } if (plen != 3) { error("Malformed ATT read response"); return; } uuid16 = get_le16(&pdu[1]); DBG("External report reference read, external report characteristic " "UUID: 0x%04x", uuid16); bt_uuid16_create(&uuid, uuid16); gatt_discover_char(hogdev->attrib, 0x00, 0xff, &uuid, external_service_char_cb, hogdev); }
static DBusMessage *discover_char(DBusConnection *conn, DBusMessage *msg, void *data) { struct gatt_service *gatt = data; struct query *query; struct query_data *qchr; INFO("discovering characteristics on %s",gatt->path); query = g_new0(struct query, 1); qchr = g_new0(struct query_data, 1); qchr->gatt = gatt; query->msg = dbus_message_ref(msg); gatt->query = query; query_list_append(gatt, qchr); if (gatt->attrib == 0) { INFO("trying to connect..."); query->attioid = btd_device_add_attio_callback(gatt->dev, send_discover, cancel_discover, qchr); } else { INFO("using existing connection"); gatt_discover_char(gatt->attrib, gatt->prim->range.start, gatt->prim->range.end, NULL, char_discovered_cb, qchr); } return 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"); 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 gboolean characteristics(gpointer user_data) { GAttrib *attrib = user_data; gatt_discover_char(attrib, opt_start, opt_end, opt_uuid, char_discovered_cb, NULL); return FALSE; }
static void attio_connected_cb(GAttrib *attrib, gpointer user_data) { struct deviceinfo *d = user_data; d->attrib = g_attrib_ref(attrib); gatt_discover_char(d->attrib, d->svc_range->start, d->svc_range->end, NULL, configure_deviceinfo_cb, d); }
static void discover_immediate_handle(struct monitor *monitor) { struct att_range *immediate = monitor->immediate; bt_uuid_t uuid; bt_uuid16_create(&uuid, ALERT_LEVEL_CHR_UUID); gatt_discover_char(monitor->attrib, immediate->start, immediate->end, &uuid, immediate_handle_cb, monitor); }
static void send_discover(GAttrib *attrib, gpointer user_data) { struct query_data *qchr = user_data; struct gatt_service *gatt = qchr->gatt; struct gatt_primary *prim = gatt->prim; gatt->attrib = g_attrib_ref(attrib); gatt_discover_char(gatt->attrib, prim->range.start, prim->range.end, NULL, char_discovered_cb, qchr); }
static void discover_char(struct bt_scpp *scpp, GAttrib *attrib, uint16_t start, uint16_t end, bt_uuid_t *uuid, gatt_cb_t func, gpointer user_data) { unsigned int id; id = gatt_discover_char(attrib, start, end, uuid, func, user_data); queue_push_head(scpp->gatt_op, UINT_TO_PTR(id)); }
static void attio_connected_cb(GAttrib *attrib, gpointer user_data) { struct heartrate *hr = user_data; DBG(""); hr->attrib = g_attrib_ref(attrib); gatt_discover_char(hr->attrib, hr->svc_range->start, hr->svc_range->end, NULL, discover_char_cb, hr); }
static void attio_connected_cb(GAttrib *attrib, gpointer user_data) { struct scan *scan = user_data; bt_uuid_t iwin_uuid, refresh_uuid; scan->attrib = g_attrib_ref(attrib); if (scan->iwhandle) { write_scan_params(scan->attrib, scan->iwhandle); return; } bt_uuid16_create(&iwin_uuid, SCAN_INTERVAL_WIN_UUID); bt_uuid16_create(&refresh_uuid, SCAN_REFRESH_UUID); gatt_discover_char(scan->attrib, scan->range.start, scan->range.end, &iwin_uuid, iwin_discovered_cb, scan); gatt_discover_char(scan->attrib, scan->range.start, scan->range.end, &refresh_uuid, refresh_discovered_cb, scan); }
static void attio_connected_cb(GAttrib *attrib, gpointer user_data) { struct csc *csc = user_data; DBG(""); csc->attrib = g_attrib_ref(attrib); gatt_discover_char(csc->attrib, csc->svc_range->start, csc->svc_range->end, NULL, discover_char_cb, csc); }
static void cmd_char(int argcp, char **argvp) { int start = 0x0001; int end = 0xffff; if (conn_state != STATE_CONNECTED) { failed("Disconnected\n"); return; } if (argcp > 1) { start = strtohandle(argvp[1]); if (start < 0) { error("Invalid start handle: %s\n", argvp[1]); return; } } if (argcp > 2) { end = strtohandle(argvp[2]); if (end < 0) { error("Invalid end handle: %s\n", argvp[2]); return; } } if (argcp > 3) { bt_uuid_t uuid; if (bt_string_to_uuid(&uuid, argvp[3]) < 0) { error("Invalid UUID\n"); 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_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 int discover_characteristics(gpointer data, uint16_t start, uint16_t end) { GAttrib *attrib = data; if (get_state() != STATE_CONNECTED) { printf("device is already disconnected\n"); return -1; } gatt_discover_char(attrib, start, end, NULL, discover_char_cb, NULL); g_main_loop_run(event_loop); return 0; }
static void attio_connected_cb(GAttrib *attrib, gpointer user_data) { struct heartrate *hr = user_data; DBG(""); hr->attrib = g_attrib_ref(attrib); hr->attionotid = g_attrib_register(hr->attrib, ATT_OP_HANDLE_NOTIFY, notify_handler, hr, NULL); gatt_discover_char(hr->attrib, hr->svc_range->start, hr->svc_range->end, NULL, discover_char_cb, hr); }
static void discover_char(struct bt_bas *bas, GAttrib *attrib, uint16_t start, uint16_t end, bt_uuid_t *uuid, gatt_cb_t func, gpointer user_data) { struct gatt_request *req; unsigned int id; req = create_request(bas, user_data); id = gatt_discover_char(attrib, start, end, uuid, func, req); set_and_store_gatt_req(bas, req, id); }
static void discover_char(struct bt_scpp *scpp, GAttrib *attrib, uint16_t start, uint16_t end, bt_uuid_t *uuid, gatt_cb_t func, gpointer user_data) { unsigned int id; id = gatt_discover_char(attrib, start, end, uuid, func, user_data); if (queue_push_head(scpp->gatt_op, UINT_TO_PTR(id))) return; error("scpp: Could not discover characteristic"); g_attrib_cancel(attrib, id); }
bool bt_hog_attach(struct bt_hog *hog, void *gatt) { struct gatt_primary *primary = hog->primary; GSList *l; if (hog->attrib) return false; hog->attrib = g_attrib_ref(gatt); if (!primary) { gatt_discover_primary(hog->attrib, NULL, primary_cb, hog); return true; } if (hog->scpp) bt_scpp_attach(hog->scpp, gatt); if (hog->dis) bt_dis_attach(hog->dis, gatt); if (hog->bas) bt_bas_attach(hog->bas, gatt); for (l = hog->instances; l; l = l->next) { struct bt_hog *instance = l->data; bt_hog_attach(instance, gatt); } if (hog->reports == NULL) { gatt_discover_char(hog->attrib, primary->range.start, primary->range.end, NULL, char_discovered_cb, hog); return true; } for (l = hog->reports; l; l = l->next) { struct report *r = l->data; r->notifyid = g_attrib_register(hog->attrib, ATT_OP_HANDLE_NOTIFY, r->decl->value_handle, report_value_cb, r, NULL); } return true; }
static void read_tx_power(struct monitor *monitor) { struct att_range *txpower = monitor->txpower; bt_uuid_t uuid; if (monitor->txpowerhandle != 0) { gatt_read_char(monitor->attrib, monitor->txpowerhandle, 0, tx_power_read_cb, monitor); return; } bt_uuid16_create(&uuid, POWER_LEVEL_CHR_UUID); gatt_discover_char(monitor->attrib, txpower->start, txpower->end, &uuid, tx_power_handle_cb, monitor); }
static void find_included_cb(uint8_t status, GSList *services, void *user_data) { struct bt_hog *hog = user_data; struct gatt_included *include; GSList *l; DBG(""); if (hog->primary) return; if (status) { const char *str = att_ecode2str(status); DBG("Find included failed: %s", str); return; } if (!services) { DBG("No included service found"); return; } for (l = services; l; l = l->next) { include = l->data; if (strcmp(include->uuid, HOG_UUID) == 0) break; } if (!l) { for (l = services; l; l = l->next) { include = l->data; gatt_find_included(hog->attrib, include->range.start, include->range.end, find_included_cb, hog); } return; } hog->primary = g_new0(struct gatt_primary, 1); memcpy(hog->primary->uuid, include->uuid, sizeof(include->uuid)); memcpy(&hog->primary->range, &include->range, sizeof(include->range)); gatt_discover_char(hog->attrib, hog->primary->range.start, hog->primary->range.end, NULL, char_discovered_cb, hog); }
static void hog_attach_hog(struct bt_hog *hog, struct gatt_primary *primary) { struct bt_hog *instance; if (!hog->primary) { hog->primary = g_memdup(primary, sizeof(*primary)); gatt_discover_char(hog->attrib, primary->range.start, primary->range.end, NULL, char_discovered_cb, hog); return; } instance = bt_hog_new(hog->name, hog->vendor, hog->product, hog->version, primary); if (!instance) return; bt_hog_attach(instance, hog->attrib); hog->instances = g_slist_append(hog->instances, instance); }
static void discover_char(struct bt_scpp *scpp, GAttrib *attrib, uint16_t start, uint16_t end, bt_uuid_t *uuid, gatt_cb_t func, gpointer user_data) { struct gatt_request *req; unsigned int id; req = create_request(scpp, user_data); if (!req) return; id = gatt_discover_char(attrib, start, end, uuid, func, req); if (set_and_store_gatt_req(scpp, req, id)) return; error("scpp: Could not discover characteristic"); g_attrib_cancel(attrib, id); free(req); }
static int write_alert_level(struct monitor *monitor) { struct att_range *linkloss = monitor->linkloss; bt_uuid_t uuid; if (monitor->linklosshandle) { uint8_t value = str2level(monitor->linklosslevel); gatt_write_char(monitor->attrib, monitor->linklosshandle, &value, 1, linkloss_written, monitor); return 0; } bt_uuid16_create(&uuid, ALERT_LEVEL_CHR_UUID); /* FIXME: use cache (requires service changed support) ? */ gatt_discover_char(monitor->attrib, linkloss->start, linkloss->end, &uuid, char_discovered_cb, monitor); return 0; }
// Discover Services static void discover_services_cb(GSList *ranges, guint8 status, gpointer user_data) { GSList *l; if (status) { error("Discover primary services by UUID failed: %s\n", att_ecode2str(status)); return; } if (ranges == NULL) { error("No service UUID found\n"); return; } for (l = ranges; l; l = l->next) { struct att_range *range = l->data; rl_printf("Starting handle: 0x%04x Ending handle: 0x%04x\n", range->start, range->end); } gatt_discover_char(attrib, 0x1, 0xffff, NULL, discover_char_cb, NULL); }