Exemplo n.º 1
0
static void exec_write_cb(uint8_t opcode, const void *pdu,
					uint16_t length, void *user_data)
{
	struct bt_gatt_server *server = user_data;
	uint8_t flags;
	uint8_t ecode;
	bool write;
	uint16_t ehandle = 0;

	if (length != 1) {
		ecode = BT_ATT_ERROR_INVALID_PDU;
		goto error;
	}

	flags = ((uint8_t *) pdu)[0];

	util_debug(server->debug_callback, server->debug_data,
				"Exec Write Req - flags: 0x%02x", flags);

	if (flags == 0x00)
		write = false;
	else if (flags == 0x01)
		write = true;
	else {
		ecode = BT_ATT_ERROR_INVALID_PDU;
		goto error;
	}

	if (!write) {
		queue_remove_all(server->prep_queue, NULL, NULL,
						prep_write_data_destroy);
		bt_att_send(server->att, BT_ATT_OP_EXEC_WRITE_RSP, NULL, 0,
							NULL, NULL, NULL);
		return;
	}

	/* If there is more than one prep request, we are in reliable session */
	if (queue_length(server->prep_queue) > 1) {
		struct prep_write_data *prep_data;

		prep_data = queue_find(server->prep_queue,
					find_no_reliable_characteristic, NULL);
		if (prep_data) {
			ecode = BT_ATT_ERROR_REQUEST_NOT_SUPPORTED;
			ehandle = prep_data->handle;
			goto error;
		}
	}

	exec_next_prep_write(server, 0, 0);

	return;

error:
	queue_remove_all(server->prep_queue, NULL, NULL,
						prep_write_data_destroy);
	bt_att_send_error_rsp(server->att, opcode, ehandle, ecode);
}
Exemplo n.º 2
0
bool bt_att_unregister_all(struct bt_att *att)
{
	if (!att)
		return false;

	queue_remove_all(att->notify_list, NULL, NULL, destroy_att_notify);
	queue_remove_all(att->disconn_list, NULL, NULL, destroy_att_disconn);

	return true;
}
Exemplo n.º 3
0
bool mgmt_cancel_all(struct mgmt *mgmt)
{
	if (!mgmt)
		return false;

	queue_remove_all(mgmt->pending_list, NULL, NULL, destroy_request);
	queue_remove_all(mgmt->reply_queue, NULL, NULL, destroy_request);
	queue_remove_all(mgmt->request_queue, NULL, NULL, destroy_request);

	return true;
}
Exemplo n.º 4
0
bool mgmt_cancel_index(struct mgmt *mgmt, uint16_t index)
{
	if (!mgmt)
		return false;

	queue_remove_all(mgmt->request_queue, match_request_index,
					UINT_TO_PTR(index), destroy_request);
	queue_remove_all(mgmt->reply_queue, match_request_index,
					UINT_TO_PTR(index), destroy_request);
	queue_remove_all(mgmt->pending_list, match_request_index,
					UINT_TO_PTR(index), destroy_request);

	return true;
}
bool bt_hci_flush(struct bt_hci *hci)
{
	if (!hci)
		return false;

	if (hci->writer_active) {
		io_set_write_handler(hci->io, NULL, NULL, NULL);
		hci->writer_active = false;
	}

	queue_remove_all(hci->cmd_queue, NULL, NULL, cmd_free);
	queue_remove_all(hci->rsp_queue, NULL, NULL, cmd_free);

	return true;
}
Exemplo n.º 6
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);
}
Exemplo n.º 7
0
bool bt_att_cancel_all(struct bt_att *att)
{
	if (!att)
		return false;

	queue_remove_all(att->req_queue, NULL, NULL, destroy_att_send_op);
	queue_remove_all(att->ind_queue, NULL, NULL, destroy_att_send_op);
	queue_remove_all(att->write_queue, NULL, NULL, destroy_att_send_op);

	if (att->pending_req)
		destroy_att_send_op(att->pending_req);

	if (att->pending_ind)
		destroy_att_send_op(att->pending_ind);

	return true;
}
Exemplo n.º 8
0
void queue_destroy(struct queue *queue, queue_destroy_func_t destroy)
{
	if (!queue)
		return;

	queue_remove_all(queue, NULL, NULL, destroy);

	queue_unref(queue);
}
Exemplo n.º 9
0
static void unregister_characteristic(void *data)
{
	struct characteristic *chrc = data;
	struct bt_gatt_client *gatt = chrc->service->client->gatt;

	DBG("Removing GATT characteristic: %s", chrc->path);

	if (chrc->read_id)
		bt_gatt_client_cancel(gatt, chrc->read_id);

	if (chrc->write_id)
		bt_gatt_client_cancel(gatt, chrc->write_id);

	queue_remove_all(chrc->notify_clients, NULL, NULL, remove_client);
	queue_remove_all(chrc->descs, NULL, NULL, unregister_descriptor);

	g_dbus_unregister_interface(btd_get_dbus_connection(), chrc->path,
						GATT_CHARACTERISTIC_IFACE);
}
Exemplo n.º 10
0
bool bt_att_cancel_all(struct bt_att *att)
{
	if (!att)
		return false;

	queue_remove_all(att->req_queue, NULL, NULL, destroy_att_send_op);
	queue_remove_all(att->ind_queue, NULL, NULL, destroy_att_send_op);
	queue_remove_all(att->write_queue, NULL, NULL, destroy_att_send_op);

	if (att->pending_req)
		/* Don't cancel the pending request; remove it's handlers */
		cancel_att_send_op(att->pending_req);

	if (att->pending_ind)
		/* Don't cancel the pending request; remove it's handlers */
		cancel_att_send_op(att->pending_ind);

	return true;
}
Exemplo n.º 11
0
bool gatt_db_clear(struct gatt_db *db)
{
	if (!db)
		return false;

	queue_remove_all(db->services, NULL, NULL, gatt_db_service_destroy);

	db->next_handle = 0;

	return true;
}
Exemplo n.º 12
0
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;
}
static void unregister_service(void *data)
{
	struct service *service = data;

	DBG("Removing GATT service: %s", service->path);

	if (service->idle_id)
		g_source_remove(service->idle_id);

	queue_remove_all(service->chrcs, NULL, NULL, unregister_characteristic);

	g_dbus_unregister_interface(btd_get_dbus_connection(), service->path,
							GATT_SERVICE_IFACE);
}
Exemplo n.º 14
0
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;
}
Exemplo n.º 15
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;
}
Exemplo n.º 16
0
bool gatt_db_clear_range(struct gatt_db *db, uint16_t start_handle,
							uint16_t end_handle)
{
	struct clear_range range;

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

	range.start = start_handle;
	range.end = end_handle;

	queue_remove_all(db->services, match_range, &range,
						gatt_db_service_destroy);

	return true;
}
void btd_gatt_client_disconnected(struct btd_gatt_client *client)
{
	if (!client)
		return;

	DBG("Device disconnected. Cleaning up");

	/*
	 * Remove all services. We'll recreate them when a new bt_gatt_client
	 * becomes ready.
	 */
	queue_remove_all(client->services, NULL, NULL, unregister_service);

	bt_gatt_client_unref(client->gatt);
	client->gatt = NULL;
}
void btd_gatt_client_service_removed(struct btd_gatt_client *client,
					struct gatt_db_attribute *attrib)
{
	uint16_t start_handle, end_handle;

	if (!client || !attrib || !client->ready)
		return;

	gatt_db_attribute_get_service_handles(attrib, &start_handle,
								&end_handle);

	DBG("GATT Services Removed - start: 0x%04x, end: 0x%04x", start_handle,
								end_handle);
	queue_remove_all(client->services, match_service_handle,
						UINT_TO_PTR(start_handle),
						unregister_service);
}
Exemplo n.º 19
0
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;
	}
}
Exemplo n.º 20
0
static void exec_next_prep_write(struct bt_gatt_server *server,
						uint16_t ehandle, int err)
{
	struct prep_write_data *next = NULL;
	struct gatt_db_attribute *attr;
	bool status;

	if (err)
		goto error;

	next = queue_pop_head(server->prep_queue);
	if (!next) {
		bt_att_send(server->att, BT_ATT_OP_EXEC_WRITE_RSP, NULL, 0,
							NULL, NULL, NULL);
		return;
	}

	attr = gatt_db_get_attribute(server->db, next->handle);
	if (!attr) {
		err = BT_ATT_ERROR_UNLIKELY;
		goto error;
	}

	status = gatt_db_attribute_write(attr, next->offset,
						next->value, next->length,
						BT_ATT_OP_EXEC_WRITE_REQ,
						server->att,
						exec_write_complete_cb, server);

	prep_write_data_destroy(next);

	if (status)
		return;

	err = BT_ATT_ERROR_UNLIKELY;

error:
	queue_remove_all(server->prep_queue, NULL, NULL,
						prep_write_data_destroy);

	bt_att_send_error_rsp(server->att, BT_ATT_OP_EXEC_WRITE_REQ,
								ehandle, err);
}
Exemplo n.º 21
0
static void exec_write_cb(uint8_t opcode, const void *pdu,
					uint16_t length, void *user_data)
{
	struct bt_gatt_server *server = user_data;
	uint8_t flags;
	uint8_t ecode;
	bool write;

	if (length != 1) {
		ecode = BT_ATT_ERROR_INVALID_PDU;
		goto error;
	}

	flags = ((uint8_t *) pdu)[0];

	util_debug(server->debug_callback, server->debug_data,
				"Exec Write Req - flags: 0x%02x", flags);

	if (flags == 0x00)
		write = false;
	else if (flags == 0x01)
		write = true;
	else {
		ecode = BT_ATT_ERROR_INVALID_PDU;
		goto error;
	}

	if (!write) {
		queue_remove_all(server->prep_queue, NULL, NULL,
						prep_write_data_destroy);
		bt_att_send(server->att, BT_ATT_OP_EXEC_WRITE_RSP, NULL, 0,
							NULL, NULL, NULL);
		return;
	}

	exec_next_prep_write(server, 0, 0);

	return;

error:
	bt_att_send_error_rsp(server->att, opcode, 0, ecode);
}
Exemplo n.º 22
0
static void mcap_mdl_deleted_cb(struct mcap_mdl *mdl, void *data)
{
	struct health_channel *channel = data;
	struct health_device *dev;

	if (!channel)
		return;

	dev = channel->dev;

	DBG("device %p channel %p mdl %p", dev, channel, mdl);

	/* mdl == NULL means, delete all mdls */
	if (!mdl) {
		queue_foreach(dev->channels, notify_channel, NULL);
		queue_remove_all(dev->channels, NULL, NULL,
						free_health_channel);
		return;
	}

	destroy_channel(channel);
}