Beispiel #1
0
static void handle_notify(struct bt_att *att, uint8_t opcode, uint8_t *pdu,
								ssize_t pdu_len)
{
	struct notify_data data;

	bt_att_ref(att);
	att->in_notify = true;

	memset(&data, 0, sizeof(data));
	data.opcode = opcode;

	if (pdu_len > 0) {
		data.pdu = pdu;
		data.pdu_len = pdu_len;
	}

	queue_foreach(att->notify_list, notify_handler, &data);

	att->in_notify = false;

	if (att->need_notify_cleanup) {
		queue_remove_all(att->notify_list, match_notify_removed, NULL,
							destroy_att_notify);
		att->need_notify_cleanup = false;
	}

	bt_att_unref(att);
}
Beispiel #2
0
static bool disconnect_cb(struct io *io, void *user_data)
{
	struct bt_att *att = user_data;
	int err;
	socklen_t len;

	len = sizeof(err);

	if (getsockopt(att->fd, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
		util_debug(att->debug_callback, att->debug_data,
					"Failed to obtain disconnect error: %s",
					strerror(errno));
		err = 0;
	}

	util_debug(att->debug_callback, att->debug_data,
					"Physical link disconnected: %s",
					strerror(err));

	io_destroy(att->io);
	att->io = NULL;

	bt_att_cancel_all(att);

	bt_att_ref(att);

	queue_foreach(att->disconn_list, disconn_handler, INT_TO_PTR(err));

	bt_att_unregister_all(att);
	bt_att_unref(att);

	return false;
}
static void resume_callback(void)
{
    gboolean suspend = FALSE;

    DBG("Resuming ...");

    queue_foreach(devices, set_suspend, GINT_TO_POINTER(suspend));
}
static void suspend_callback(void)
{
    gboolean suspend = TRUE;

    DBG("Suspending ...");

    queue_foreach(devices, set_suspend, GINT_TO_POINTER(suspend));
}
Beispiel #5
0
void bt_dis_detach(struct bt_dis *dis)
{
	if (!dis->attrib)
		return;

	queue_foreach(dis->gatt_op, (void *) cancel_gatt_req, NULL);
	g_attrib_unref(dis->attrib);
	dis->attrib = NULL;
}
Beispiel #6
0
void btd_gatt_client_disconnected(struct btd_gatt_client *client)
{
	if (!client || !client->gatt)
		return;

	DBG("Device disconnected. Cleaning up.");

	/*
	 * TODO: Once GATT over BR/EDR is properly supported, we should pass the
	 * correct bdaddr_type based on the transport over which GATT is being
	 * done.
	 */
	queue_foreach(client->all_notify_clients, clear_notify_id, NULL);
	queue_foreach(client->services, cancel_ops, client->gatt);

	bt_gatt_client_unref(client->gatt);
	client->gatt = NULL;
}
Beispiel #7
0
static void app_search_channel(void *data, void *user_data)
{
	struct health_app *app = data;
	struct channel_search *search = user_data;

	if (search->channel)
		return;

	queue_foreach(app->devices, device_search_channel, search);
}
Beispiel #8
0
static int register_endpoints(void)
{
	struct register_state state;

	state.ep = &audio_endpoints[0];
	state.error = false;

	queue_foreach(loaded_codecs, register_endpoint, &state);

	return state.error ? AUDIO_STATUS_FAILED : AUDIO_STATUS_SUCCESS;
}
Beispiel #9
0
static struct health_channel *search_channel_by_id(uint16_t id)
{
	struct channel_search search;

	DBG("");

	search.channel_id = id;
	search.channel = NULL;
	queue_foreach(apps, app_search_channel, &search);

	return search.channel;
}
Beispiel #10
0
void gatt_db_find_information(struct gatt_db *db, uint16_t start_handle,
							uint16_t end_handle,
							struct queue *queue)
{
	struct find_information_data data;

	data.start_handle = start_handle;
	data.end_handle = end_handle;
	data.queue = queue;

	queue_foreach(db->services, find_information, &data);
}
Beispiel #11
0
static void master_command_callback(uint16_t opcode,
				const void *data, uint8_t len,
				btdev_callback callback, void *user_data)
{
	struct hciemu *hciemu = user_data;
	struct run_data run_data = { .opcode = opcode,
						.data = data, .len = len };

	btdev_command_default(callback);

	queue_foreach(hciemu->post_command_hooks, run_command_hook, &run_data);
}
Beispiel #12
0
void gatt_db_read_by_type(struct gatt_db *db, uint16_t start_handle,
						uint16_t end_handle,
						const bt_uuid_t type,
						struct queue *queue)
{
	struct read_by_type_data data;
	data.uuid = type;
	data.start_handle = start_handle;
	data.end_handle = end_handle;
	data.queue = queue;

	queue_foreach(db->services, read_by_type, &data);
}
Beispiel #13
0
static struct health_app *search_app_by_mdepid(uint8_t mdepid)
{
	struct app_search search;

	DBG("");

	search.mdepid = mdepid;
	search.app = NULL;

	queue_foreach(apps, app_search_mdep, &search);

	return search.app;
}
Beispiel #14
0
void bt_bas_detach(struct bt_bas *bas)
{
	if (!bas || !bas->attrib)
		return;

	if (bas->id > 0) {
		g_attrib_unregister(bas->attrib, bas->id);
		bas->id = 0;
	}

	queue_foreach(bas->gatt_op, (void *) cancel_gatt_req, NULL);
	g_attrib_unref(bas->attrib);
	bas->attrib = NULL;
}
Beispiel #15
0
void bt_scpp_detach(struct bt_scpp *scan)
{
	if (!scan || !scan->attrib)
		return;

	if (scan->refresh_cb_id > 0) {
		g_attrib_unregister(scan->attrib, scan->refresh_cb_id);
		scan->refresh_cb_id = 0;
	}

	queue_foreach(scan->gatt_op, (void *) cancel_gatt_req, NULL);
	g_attrib_unref(scan->attrib);
	scan->attrib = NULL;
}
bool mgmt_unregister_all(struct mgmt *mgmt)
{
	if (!mgmt)
		return false;

	if (mgmt->in_notify) {
		queue_foreach(mgmt->notify_list, mark_notify_removed,
						UINT_TO_PTR(MGMT_INDEX_NONE));
		mgmt->need_notify_cleanup = true;
	} else
		queue_remove_all(mgmt->notify_list, NULL, NULL, destroy_notify);

	return true;
}
Beispiel #17
0
void btd_gatt_client_foreach_service(struct btd_gatt_client *client,
					btd_gatt_client_service_path_t func,
					void *user_data)
{
	struct foreach_service_data data;

	if (!client)
		return;

	data.func = func;
	data.user_data = user_data;

	queue_foreach(client->services, client_service_foreach, &data);
}
bool mgmt_unregister_index(struct mgmt *mgmt, uint16_t index)
{
	if (!mgmt)
		return false;

	if (mgmt->in_notify) {
		queue_foreach(mgmt->notify_list, mark_notify_removed,
							UINT_TO_PTR(index));
		mgmt->need_notify_cleanup = true;
	} else
		queue_remove_all(mgmt->notify_list, match_notify_index,
					UINT_TO_PTR(index), destroy_notify);

	return true;
}
static gboolean characteristic_get_descriptors(
					const GDBusPropertyTable *property,
					DBusMessageIter *iter, void *data)
{
	struct characteristic *chrc = data;
	DBusMessageIter array;

	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "o", &array);

	queue_foreach(chrc->descs, append_desc_path, &array);

	dbus_message_iter_close_container(iter, &array);

	return TRUE;
}
static gboolean service_get_characteristics(const GDBusPropertyTable *property,
					DBusMessageIter *iter, void *data)
{
	struct service *service = data;
	DBusMessageIter array;

	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "o", &array);

	if (service->chrcs_ready)
		queue_foreach(service->chrcs, append_chrc_path, &array);

	dbus_message_iter_close_container(iter, &array);

	return TRUE;
}
Beispiel #21
0
bool bt_att_unregister_all(struct bt_att *att)
{
	if (!att)
		return false;

	if (!att->in_notify) {
		queue_remove_all(att->notify_list, NULL, NULL,
							destroy_att_notify);
		return true;
	}

	queue_foreach(att->notify_list, mark_notify_removed, NULL);
	att->need_notify_cleanup = true;

	return true;
}
Beispiel #22
0
static void cancel_chrc_ops(void *data, void *user_data)
{
	struct characteristic *chrc = data;
	struct bt_gatt_client *gatt = user_data;

	if (chrc->read_id) {
		bt_gatt_client_cancel(gatt, chrc->read_id);
		chrc->read_id = 0;
	}

	if (chrc->write_id) {
		bt_gatt_client_cancel(gatt, chrc->write_id);
		chrc->write_id = 0;
	}

	queue_foreach(chrc->descs, cancel_desc_ops, user_data);
}
static bool create_characteristics(struct gatt_db_attribute *attr,
						struct service *service)
{
	struct export_data data;

	data.root = service;
	data.failed = false;

	gatt_db_service_foreach_char(attr, export_char, &data);

	if (data.failed)
		return false;

	/* Obtain extended properties */
	queue_foreach(service->pending_ext_props, read_ext_props, NULL);

	return true;
}
Beispiel #24
0
static void notify_service_changed(struct gatt_db *db,
						struct gatt_db_service *service,
						bool added)
{
	struct notify_data data;

	if (queue_isempty(db->notify_list))
		return;

	data.attr = service->attributes[0];
	data.added = added;

	gatt_db_ref(db);

	queue_foreach(db->notify_list, handle_notify, &data);

	gatt_db_unref(db);
}
static void process_notify(struct mgmt *mgmt, uint16_t event, uint16_t index,
					uint16_t length, const void *param)
{
	struct event_index match = { .event = event, .index = index,
					.length = length, .param = param };

	mgmt->in_notify = true;

	queue_foreach(mgmt->notify_list, notify_handler, &match);

	mgmt->in_notify = false;

	if (mgmt->need_notify_cleanup) {
		queue_remove_all(mgmt->notify_list, match_notify_removed,
							NULL, destroy_notify);
		mgmt->need_notify_cleanup = false;
	}
}
Beispiel #26
0
static int register_service_sup_features(sdp_record_t *rec,
						struct health_app *app)
{
	sdp_list_t *sup_features = NULL;

	DBG("");

	queue_foreach(app->mdeps, register_features, &sup_features);
	if (!sup_features)
		return -1;

	if (sdp_set_supp_feat(rec, sup_features) < 0) {
		sdp_list_free(sup_features, free_hdp_list);
		return -1;
	}

	sdp_list_free(sup_features, free_hdp_list);
	return 0;
}
Beispiel #27
0
void gatt_db_foreach_service_in_range(struct gatt_db *db,
						const bt_uuid_t *uuid,
						gatt_db_attribute_cb_t func,
						void *user_data,
						uint16_t start_handle,
						uint16_t end_handle)
{
	struct foreach_data data;

	if (!db || !func || start_handle > end_handle)
		return;

	data.func = func;
	data.uuid = uuid;
	data.user_data = user_data;
	data.start = start_handle;
	data.end = end_handle;

	queue_foreach(db->services, foreach_service_in_range, &data);
}
Beispiel #28
0
unsigned int gatt_db_find_by_type(struct gatt_db *db, uint16_t start_handle,
						uint16_t end_handle,
						const bt_uuid_t *type,
						gatt_db_attribute_cb_t func,
						void *user_data)
{
	struct find_by_type_value_data data;

	memset(&data, 0, sizeof(data));

	data.uuid = *type;
	data.start_handle = start_handle;
	data.end_handle = end_handle;
	data.func = func;
	data.user_data = user_data;

	queue_foreach(db->services, find_by_type, &data);

	return data.num_of_res;
}
Beispiel #29
0
void btd_gatt_client_connected(struct btd_gatt_client *client)
{
	struct bt_gatt_client *gatt;

	gatt = btd_device_get_gatt_client(client->device);
	if (!gatt) {
		error("GATT client not initialized");
		return;
	}

	DBG("Device connected.");

	bt_gatt_client_unref(client->gatt);
	client->gatt = bt_gatt_client_ref(gatt);

	/*
	 * Services have already been created before. Re-enable notifications
	 * for any pre-registered notification sessions.
	 */
	queue_foreach(client->all_notify_clients, register_notify, client);
}
static void process_event(struct bt_hci *hci, const void *data, size_t size)
{
	const struct bt_hci_evt_hdr *hdr = data;
	const struct bt_hci_evt_cmd_complete *cc;
	const struct bt_hci_evt_cmd_status *cs;

	if (size < sizeof(struct bt_hci_evt_hdr))
		return;

	data += sizeof(struct bt_hci_evt_hdr);
	size -= sizeof(struct bt_hci_evt_hdr);

	if (hdr->plen != size)
		return;

	switch (hdr->evt) {
	case BT_HCI_EVT_CMD_COMPLETE:
		if (size < sizeof(*cc))
			return;
		cc = data;
		hci->num_cmds = cc->ncmd;
		process_response(hci, le16_to_cpu(cc->opcode),
						data + sizeof(*cc),
						size - sizeof(*cc));
		break;

	case BT_HCI_EVT_CMD_STATUS:
		if (size < sizeof(*cs))
			return;
		cs = data;
		hci->num_cmds = cs->ncmd;
		process_response(hci, le16_to_cpu(cs->opcode), &cs->status, 1);
		break;

	default:
		queue_foreach(hci->evt_list, process_notify, (void *) hdr);
		break;
	}
}