Blame mesh/mesh-mgmt.c

Packit Service 8264ee
/*
Packit Service 8264ee
 *
Packit Service 8264ee
 *  BlueZ - Bluetooth protocol stack for Linux
Packit Service 8264ee
 *
Packit Service 8264ee
 *  Copyright (C) 2019  SILVAIR sp. z o.o. All rights reserved.
Packit Service 8264ee
 *
Packit Service 8264ee
 *
Packit Service 8264ee
 *  This library is free software; you can redistribute it and/or
Packit Service 8264ee
 *  modify it under the terms of the GNU Lesser General Public
Packit Service 8264ee
 *  License as published by the Free Software Foundation; either
Packit Service 8264ee
 *  version 2.1 of the License, or (at your option) any later version.
Packit Service 8264ee
 *
Packit Service 8264ee
 *  This library is distributed in the hope that it will be useful,
Packit Service 8264ee
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 8264ee
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 8264ee
 *  Lesser General Public License for more details.
Packit Service 8264ee
 *
Packit Service 8264ee
 */
Packit Service 8264ee
Packit Service 8264ee
#ifdef HAVE_CONFIG_H
Packit Service 8264ee
#include <config.h>
Packit Service 8264ee
#endif
Packit Service 8264ee
Packit Service 8264ee
#include "lib/bluetooth.h"
Packit Service 8264ee
#include "lib/mgmt.h"
Packit Service 8264ee
#include "src/shared/mgmt.h"
Packit Service 8264ee
Packit Service 8264ee
#include "ell/queue.h"
Packit Service 8264ee
#include "ell/log.h"
Packit Service 8264ee
#include "ell/util.h"
Packit Service 8264ee
Packit Service 8264ee
#include "mesh/mesh-mgmt.h"
Packit Service 8264ee
Packit Service 8264ee
struct read_info_reg {
Packit Service 8264ee
	mesh_mgmt_read_info_func_t cb;
Packit Service 8264ee
	void *user_data;
Packit Service 8264ee
};
Packit Service 8264ee
Packit Service 8264ee
struct read_info_req {
Packit Service 8264ee
	int index;
Packit Service 8264ee
	struct mesh_io *io;
Packit Service 8264ee
};
Packit Service 8264ee
Packit Service 8264ee
static struct mgmt *mgmt_mesh;
Packit Service 8264ee
static struct l_queue *controllers;
Packit Service 8264ee
static struct l_queue *read_info_regs;
Packit Service 8264ee
Packit Service 8264ee
static bool simple_match(const void *a, const void *b)
Packit Service 8264ee
{
Packit Service 8264ee
	return a == b;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void process_read_info_req(void *data, void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct read_info_reg *reg = data;
Packit Service 8264ee
	int index = L_PTR_TO_UINT(user_data);
Packit Service 8264ee
Packit Service 8264ee
	reg->cb(index, reg->user_data);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void read_info_cb(uint8_t status, uint16_t length,
Packit Service 8264ee
					const void *param, void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	int index = L_PTR_TO_UINT(user_data);
Packit Service 8264ee
	const struct mgmt_rp_read_info *rp = param;
Packit Service 8264ee
	uint32_t current_settings, supported_settings;
Packit Service 8264ee
Packit Service 8264ee
	l_debug("hci %u status 0x%02x", index, status);
Packit Service 8264ee
Packit Service 8264ee
	if (status != MGMT_STATUS_SUCCESS) {
Packit Service 8264ee
		l_error("Failed to read info for hci index %u: %s (0x%02x)",
Packit Service 8264ee
				index, mgmt_errstr(status), status);
Packit Service 8264ee
		return;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	if (length < sizeof(*rp)) {
Packit Service 8264ee
		l_error("Read info response too short");
Packit Service 8264ee
		return;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	current_settings = btohl(rp->current_settings);
Packit Service 8264ee
	supported_settings = btohl(rp->supported_settings);
Packit Service 8264ee
Packit Service 8264ee
	l_debug("settings: supp %8.8x curr %8.8x",
Packit Service 8264ee
					supported_settings, current_settings);
Packit Service 8264ee
Packit Service 8264ee
	if (current_settings & MGMT_SETTING_POWERED) {
Packit Service 8264ee
		l_info("Controller hci %u is in use", index);
Packit Service 8264ee
		return;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	if (!(supported_settings & MGMT_SETTING_LE)) {
Packit Service 8264ee
		l_info("Controller hci %u does not support LE", index);
Packit Service 8264ee
		return;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	l_queue_foreach(read_info_regs, process_read_info_req,
Packit Service 8264ee
							L_UINT_TO_PTR(index));
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void index_added(uint16_t index, uint16_t length, const void *param,
Packit Service 8264ee
							void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	if (l_queue_find(controllers, simple_match, L_UINT_TO_PTR(index)))
Packit Service 8264ee
		return;
Packit Service 8264ee
Packit Service 8264ee
	l_queue_push_tail(controllers, L_UINT_TO_PTR(index));
Packit Service 8264ee
Packit Service 8264ee
	if (mgmt_send(mgmt_mesh, MGMT_OP_READ_INFO, index, 0, NULL,
Packit Service 8264ee
			read_info_cb, L_UINT_TO_PTR(index), NULL) != 0)
Packit Service 8264ee
		return;
Packit Service 8264ee
Packit Service 8264ee
	l_queue_remove(controllers, L_UINT_TO_PTR(index));
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void index_removed(uint16_t index, uint16_t length, const void *param,
Packit Service 8264ee
							void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	l_warn("Hci dev %4.4x removed", index);
Packit Service 8264ee
	l_queue_remove(controllers, L_UINT_TO_PTR(index));
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void read_index_list_cb(uint8_t status, uint16_t length,
Packit Service 8264ee
					const void *param, void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	const struct mgmt_rp_read_index_list *rp = param;
Packit Service 8264ee
	uint16_t num;
Packit Service 8264ee
	int i;
Packit Service 8264ee
Packit Service 8264ee
	if (status != MGMT_STATUS_SUCCESS) {
Packit Service 8264ee
		l_error("Failed to read index list: %s (0x%02x)",
Packit Service 8264ee
						mgmt_errstr(status), status);
Packit Service 8264ee
		return;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	if (length < sizeof(*rp)) {
Packit Service 8264ee
		l_error("Read index list response sixe too short");
Packit Service 8264ee
		return;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	num = btohs(rp->num_controllers);
Packit Service 8264ee
Packit Service 8264ee
	l_debug("Number of controllers: %u", num);
Packit Service 8264ee
Packit Service 8264ee
	if (num * sizeof(uint16_t) + sizeof(*rp) != length) {
Packit Service 8264ee
		l_error("Incorrect packet size for index list response");
Packit Service 8264ee
		return;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	for (i = 0; i < num; i++) {
Packit Service 8264ee
		uint16_t index;
Packit Service 8264ee
Packit Service 8264ee
		index = btohs(rp->index[i]);
Packit Service 8264ee
		index_added(index, 0, NULL, user_data);
Packit Service 8264ee
	}
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool mesh_mgmt_init(void)
Packit Service 8264ee
{
Packit Service 8264ee
	if (!controllers)
Packit Service 8264ee
		controllers = l_queue_new();
Packit Service 8264ee
Packit Service 8264ee
	if (!read_info_regs)
Packit Service 8264ee
		read_info_regs = l_queue_new();
Packit Service 8264ee
Packit Service 8264ee
	if (!mgmt_mesh) {
Packit Service 8264ee
		mgmt_mesh = mgmt_new_default();
Packit Service 8264ee
Packit Service 8264ee
		if (!mgmt_mesh) {
Packit Service 8264ee
			l_error("Failed to initialize mesh management");
Packit Service 8264ee
			return false;
Packit Service 8264ee
		}
Packit Service 8264ee
Packit Service 8264ee
		mgmt_register(mgmt_mesh, MGMT_EV_INDEX_ADDED,
Packit Service 8264ee
				MGMT_INDEX_NONE, index_added, NULL, NULL);
Packit Service 8264ee
		mgmt_register(mgmt_mesh, MGMT_EV_INDEX_REMOVED,
Packit Service 8264ee
				MGMT_INDEX_NONE, index_removed, NULL, NULL);
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	return true;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
bool mesh_mgmt_list(mesh_mgmt_read_info_func_t cb, void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct read_info_reg *reg;
Packit Service 8264ee
Packit Service 8264ee
	if (!mesh_mgmt_init())
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	reg = l_new(struct read_info_reg, 1);
Packit Service 8264ee
	reg->cb = cb;
Packit Service 8264ee
	reg->user_data = user_data;
Packit Service 8264ee
Packit Service 8264ee
	l_queue_push_tail(read_info_regs, reg);
Packit Service 8264ee
Packit Service 8264ee
	/* Use MGMT to find a candidate controller */
Packit Service 8264ee
	l_debug("send read index_list");
Packit Service 8264ee
	if (mgmt_send(mgmt_mesh, MGMT_OP_READ_INDEX_LIST,
Packit Service 8264ee
					MGMT_INDEX_NONE, 0, NULL,
Packit Service 8264ee
					read_index_list_cb, NULL, NULL) <= 0)
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	return true;
Packit Service 8264ee
}