Example #1
0
GAttrib *g_attrib_new(GIOChannel *io)
{
	struct _GAttrib *attrib;
	uint16_t omtu;

	g_io_channel_set_encoding(io, NULL, NULL);
	g_io_channel_set_buffered(io, FALSE);

	attrib = g_try_new0(struct _GAttrib, 1);
	if (attrib == NULL)
		return NULL;

	attrib->io = g_io_channel_ref(io);
	attrib->queue = g_queue_new();

	attrib->read_watch = g_io_add_watch(attrib->io,
			G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
			received_data, attrib);

	if (bt_io_get(attrib->io, BT_IO_L2CAP, NULL,
			BT_IO_OPT_OMTU, &omtu,
			BT_IO_OPT_INVALID)) {
		if (omtu == 0 || omtu > ATT_MAX_MTU)
			omtu = ATT_MAX_MTU;
	} else
		omtu = ATT_DEFAULT_LE_MTU;

	attrib->buf = g_malloc0(omtu);
	attrib->buflen = omtu;

	return g_attrib_ref(attrib);
}
Example #2
0
guint gatt_discover_char(GAttrib *attrib, uint16_t start, uint16_t end,
						bt_uuid_t *uuid, gatt_cb_t func,
						gpointer user_data)
{
	size_t buflen;
	uint8_t *buf = g_attrib_get_buffer(attrib, &buflen);
	struct discover_char *dc;
	bt_uuid_t type_uuid;
	guint16 plen;

	bt_uuid16_create(&type_uuid, GATT_CHARAC_UUID);

	plen = enc_read_by_type_req(start, end, &type_uuid, buf, buflen);
	if (plen == 0)
		return 0;

	dc = g_try_new0(struct discover_char, 1);
	if (dc == NULL)
		return 0;

	dc->attrib = g_attrib_ref(attrib);
	dc->cb = func;
	dc->user_data = user_data;
	dc->end = end;
	dc->uuid = g_memdup(uuid, sizeof(bt_uuid_t));

	return g_attrib_send(attrib, 0, buf, plen, char_discovered_cb,
								dc, NULL);
}
Example #3
0
bool bt_scpp_attach(struct bt_scpp *scan, void *attrib)
{
	bt_uuid_t iwin_uuid, refresh_uuid;

	if (!scan || scan->attrib || !scan->primary)
		return false;

	scan->attrib = g_attrib_ref(attrib);

	if (scan->iwhandle)
		write_scan_params(scan->attrib, scan->iwhandle, scan->interval,
								scan->window);
	else {
		bt_uuid16_create(&iwin_uuid, SCAN_INTERVAL_WIN_UUID);
		discover_char(scan, scan->attrib, scan->primary->range.start,
					scan->primary->range.end, &iwin_uuid,
					iwin_discovered_cb, scan);
	}

	if (scan->refresh_handle)
		scan->refresh_cb_id = g_attrib_register(scan->attrib,
				ATT_OP_HANDLE_NOTIFY, scan->refresh_handle,
				refresh_value_cb, scan, NULL);
	else {
		bt_uuid16_create(&refresh_uuid, SCAN_REFRESH_UUID);
		discover_char(scan, scan->attrib, scan->primary->range.start,
					scan->primary->range.end, &refresh_uuid,
					refresh_discovered_cb, scan);
	}

	return true;
}
Example #4
0
guint gatt_read_char(GAttrib *attrib, uint16_t handle, GAttribResultFunc func,
							gpointer user_data)
{
	uint8_t *buf;
	size_t buflen;
	guint16 plen;
	guint id;
	struct read_long_data *long_read;

	long_read = g_try_new0(struct read_long_data, 1);

	if (long_read == NULL)
		return 0;

	long_read->attrib = g_attrib_ref(attrib);
	long_read->func = func;
	long_read->user_data = user_data;
	long_read->handle = handle;

	buf = g_attrib_get_buffer(attrib, &buflen);
	plen = enc_read_req(handle, buf, buflen);
	id = g_attrib_send(attrib, 0, buf, plen, read_char_helper,
						long_read, read_long_destroy);
	if (id == 0) {
		g_attrib_unref(long_read->attrib);
		g_free(long_read);
	} else {
		__sync_fetch_and_add(&long_read->ref, 1);
		long_read->id = id;
	}

	return id;
}
Example #5
0
static gboolean disconnect_timeout(gpointer data)
{
  struct _GAttrib *attrib = data;
  struct command *c;

  g_attrib_ref(attrib);

  c = g_queue_pop_head(attrib->requests);
  if (c == NULL)
    goto done;

  if (c->func)
    c->func(ATT_ECODE_TIMEOUT, NULL, 0, c->user_data);

  command_destroy(c);

  while ((c = g_queue_pop_head(attrib->requests))) {
    if (c->func)
      c->func(ATT_ECODE_ABORTED, NULL, 0, c->user_data);
    command_destroy(c);
  }

done:
  attrib->stale = true;

  g_attrib_unref(attrib);

  return FALSE;
}
Example #6
0
guint gatt_discover_primary(GAttrib *attrib, bt_uuid_t *uuid, gatt_cb_t func,
							gpointer user_data)
{
	struct discover_primary *dp;
	size_t buflen;
	uint8_t *buf = g_attrib_get_buffer(attrib, &buflen);
	GAttribResultFunc cb;
	guint16 plen;

	plen = encode_discover_primary(0x0001, 0xffff, uuid, buf, buflen);
	if (plen == 0)
		return 0;

	dp = g_try_new0(struct discover_primary, 1);
	if (dp == NULL)
		return 0;

	dp->attrib = g_attrib_ref(attrib);
	dp->cb = func;
	dp->user_data = user_data;

	if (uuid) {
		dp->uuid = *uuid;
		cb = primary_by_uuid_cb;
	} else
		cb = primary_all_cb;

	return g_attrib_send(attrib, 0, buf, plen, cb, dp, NULL);
}
static void test_refcount(struct context *cxt, gconstpointer unused)
{
	GAttrib *extra_ref;
	int destroy_canary = 0;

	g_attrib_set_destroy_function(cxt->att, destroy_canary_increment,
							       &destroy_canary);

	extra_ref = g_attrib_ref(cxt->att);

	g_assert(extra_ref == cxt->att);

	g_assert(destroy_canary == 0);

	g_attrib_unref(extra_ref);

	g_assert(destroy_canary == 0);

	g_attrib_unref(cxt->att);

	g_assert(destroy_canary == 1);

	/* Avoid a double-free from the teardown function */
	cxt->att = NULL;
}
Example #8
0
guint gatt_discover_desc(GAttrib *attrib, uint16_t start, uint16_t end,
						bt_uuid_t *uuid, gatt_cb_t func,
						gpointer user_data)
{
	size_t buflen;
	uint8_t *buf = g_attrib_get_buffer(attrib, &buflen);
	struct discover_desc *dd;
	guint16 plen;

	plen = enc_find_info_req(start, end, buf, buflen);
	if (plen == 0)
		return 0;

	dd = g_try_new0(struct discover_desc, 1);
	if (dd == NULL)
		return 0;

	dd->attrib = g_attrib_ref(attrib);
	dd->cb = func;
	dd->user_data = user_data;
	dd->start = start;
	dd->end = end;
	dd->uuid = g_memdup(uuid, sizeof(bt_uuid_t));

	dd->id = g_attrib_send(attrib, 0, buf, plen, desc_discovered_cb,
				discover_desc_ref(dd), discover_desc_unref);

	return dd->id;
}
Example #9
0
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);
}
Example #10
0
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);
}
Example #11
0
static void wake_up_sender(struct _GAttrib *attrib)
{
  if (attrib->write_watch > 0)
    return;

  attrib = g_attrib_ref(attrib);
  attrib->write_watch = g_io_add_watch_full(attrib->io,
        G_PRIORITY_DEFAULT, G_IO_OUT,
        can_write_data, attrib, destroy_sender);
}
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);
}
Example #13
0
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 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);
}
Example #15
0
unsigned int gatt_find_included(GAttrib *attrib, uint16_t start, uint16_t end,
					gatt_cb_t func, gpointer user_data)
{
	struct included_discovery *isd;

	isd = g_new0(struct included_discovery, 1);
	isd->attrib = g_attrib_ref(attrib);
	isd->end_handle = end;
	isd->cb = func;
	isd->user_data = user_data;

	return find_included(isd, start);
}
Example #16
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);
}
Example #17
0
File: hog.c Project: aguedes/bluez
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;
}
Example #18
0
GAttrib *g_attrib_new(GIOChannel *io, guint16 mtu, bool ext_signed)
{
	gint fd;
	GAttrib *attr;

	if (!io)
		return NULL;

	fd = g_io_channel_unix_get_fd(io);
	attr = new0(GAttrib, 1);
	if (!attr)
		return NULL;

	g_io_channel_ref(io);
	attr->io = io;

	attr->att = bt_att_new(fd, ext_signed);
	if (!attr->att)
		goto fail;

	bt_att_set_close_on_unref(attr->att, true);
	g_io_channel_set_close_on_unref(io, FALSE);

	if (!bt_att_set_mtu(attr->att, mtu))
		goto fail;

	attr->buf = malloc0(mtu);
	attr->buflen = mtu;
	if (!attr->buf)
		goto fail;

	attr->callbacks = queue_new();
	if (!attr->callbacks)
		goto fail;

	attr->track_ids = queue_new();
	if (!attr->track_ids)
		goto fail;

	return g_attrib_ref(attr);

fail:
	free(attr->buf);
	bt_att_unref(attr->att);
	g_io_channel_unref(io);
	free(attr);
	return NULL;
}
Example #19
0
bool bt_dis_attach(struct bt_dis *dis, void *attrib)
{
	struct gatt_primary *primary = dis->primary;

	if (dis->attrib || !primary)
		return false;

	dis->attrib = g_attrib_ref(attrib);

	if (!dis->handle)
		discover_char(dis, dis->attrib, primary->range.start,
						primary->range.end, NULL,
						configure_deviceinfo_cb, dis);

	return true;
}
Example #20
0
bool bt_bas_attach(struct bt_bas *bas, void *attrib)
{
	if (!bas || bas->attrib || !bas->primary)
		return false;

	bas->attrib = g_attrib_ref(attrib);

	if (bas->handle > 0)
		return true;

	discover_char(bas, bas->attrib, bas->primary->range.start,
					bas->primary->range.end, NULL,
					bas_discovered_cb, bas);

	return true;
}
Example #21
0
static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
{
	struct monitor *monitor = user_data;

	monitor->attrib = g_attrib_ref(attrib);

	if (monitor->enabled.linkloss)
		write_alert_level(monitor);

	if (monitor->enabled.pathloss)
		read_tx_power(monitor);

	if (monitor->immediatehandle == 0) {
		if(monitor->enabled.pathloss || monitor->enabled.findme)
			discover_immediate_handle(monitor);
	} else if (monitor->fallbacklevel)
		write_immediate_alert(monitor);
}
Example #22
0
static void attio_connected(GAttrib *attrib, gpointer user_data)
{
	struct gatt_service *gatt = user_data;

	gatt->attrib = g_attrib_ref(attrib);

	g_attrib_register(gatt->attrib, ATT_OP_HANDLE_NOTIFY,
					events_handler, gatt, NULL);
	g_attrib_register(gatt->attrib, ATT_OP_HANDLE_IND,
					events_handler, gatt, NULL);

	/*
	 * TODO : we do not support offline writing
	 */
	/*g_slist_foreach(gatt->offline_chars, offline_char_write, attrib);*/

	INFO("%s connected", gatt->path);
}
Example #23
0
GAttrib *g_attrib_new(GIOChannel *io)
{
	struct _GAttrib *attrib;
	uint16_t imtu;
	uint16_t att_mtu;
	uint16_t cid;
	GError *gerr = NULL;

	g_io_channel_set_encoding(io, NULL, NULL);
	g_io_channel_set_buffered(io, FALSE);

	bt_io_get(io, BT_IO_L2CAP, &gerr,
			BT_IO_OPT_IMTU, &imtu,
			BT_IO_OPT_CID, &cid,
			BT_IO_OPT_INVALID);

	if (gerr) {
		error("%s", gerr->message);
		g_error_free(gerr);
		return NULL;
	}

	attrib = g_try_new0(struct _GAttrib, 1);
	if (attrib == NULL)
		return NULL;

	att_mtu = (cid == ATT_CID) ? ATT_DEFAULT_LE_MTU : imtu;

	attrib->buf = g_malloc0(att_mtu);
	attrib->buflen = att_mtu;

	attrib->io = g_io_channel_ref(io);
	attrib->requests = g_queue_new();
	attrib->responses = g_queue_new();

	attrib->read_watch = g_io_add_watch(attrib->io,
			G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
			received_data, attrib);

	return g_attrib_ref(attrib);
}
Example #24
0
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);
}
Example #25
0
guint gatt_read_char_single(GAttrib *attrib, uint16_t handle, uint16_t offset,
                GAttribResultFunc func, gpointer user_data)
{
    uint8_t *buf;
    size_t buflen;
    guint16 plen;
    guint id;
    struct read_data *read;

    read = g_try_new0(struct read_data, 1);

    if (read == NULL)
        return 0;

    read->attrib = g_attrib_ref(attrib);
    read->func = func;
    read->user_data = user_data;
    read->handle = handle;
    read->offset = offset;

    buf = g_attrib_get_buffer(attrib, &buflen);
    if (!offset)
        plen = enc_read_req(handle, buf, buflen);
    else
        plen = enc_read_blob_req(handle, offset, buf, buflen);

    id = g_attrib_send(attrib, 0, buf, plen, read_char_helper,
                       read, read_destroy);
    if (id == 0) {
        g_attrib_unref(read->attrib);
        g_free(read);
    } else {
        __sync_fetch_and_add(&read->ref, 1);
        read->id = id;
    }

    return id;
}