| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- // SPDX-License-Identifier: LGPL-2.1-or-later
- /*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2019 SILVAIR sp. z o.o. All rights reserved.
- *
- *
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include "lib/bluetooth.h"
- #include "lib/mgmt.h"
- #include "src/shared/mgmt.h"
- #include "ell/queue.h"
- #include "ell/log.h"
- #include "ell/util.h"
- #include "mesh/mesh-mgmt.h"
- struct read_info_reg {
- mesh_mgmt_read_info_func_t cb;
- void *user_data;
- };
- struct read_info_req {
- int index;
- struct mesh_io *io;
- };
- static struct mgmt *mgmt_mesh;
- static struct l_queue *read_info_regs;
- static void process_read_info_req(void *data, void *user_data)
- {
- struct read_info_reg *reg = data;
- int index = L_PTR_TO_UINT(user_data);
- reg->cb(index, reg->user_data);
- }
- static void read_info_cb(uint8_t status, uint16_t length,
- const void *param, void *user_data)
- {
- int index = L_PTR_TO_UINT(user_data);
- const struct mgmt_rp_read_info *rp = param;
- uint32_t current_settings, supported_settings;
- l_debug("hci %u status 0x%02x", index, status);
- if (status != MGMT_STATUS_SUCCESS) {
- l_error("Failed to read info for hci index %u: %s (0x%02x)",
- index, mgmt_errstr(status), status);
- return;
- }
- if (length < sizeof(*rp)) {
- l_error("Read info response too short");
- return;
- }
- current_settings = btohl(rp->current_settings);
- supported_settings = btohl(rp->supported_settings);
- l_debug("settings: supp %8.8x curr %8.8x",
- supported_settings, current_settings);
- if (current_settings & MGMT_SETTING_POWERED) {
- l_info("Controller hci %u is in use", index);
- return;
- }
- if (!(supported_settings & MGMT_SETTING_LE)) {
- l_info("Controller hci %u does not support LE", index);
- return;
- }
- l_queue_foreach(read_info_regs, process_read_info_req,
- L_UINT_TO_PTR(index));
- }
- static void index_added(uint16_t index, uint16_t length, const void *param,
- void *user_data)
- {
- mgmt_send(mgmt_mesh, MGMT_OP_READ_INFO, index, 0, NULL,
- read_info_cb, L_UINT_TO_PTR(index), NULL);
- }
- static void index_removed(uint16_t index, uint16_t length, const void *param,
- void *user_data)
- {
- l_warn("Hci dev %4.4x removed", index);
- }
- static void read_index_list_cb(uint8_t status, uint16_t length,
- const void *param, void *user_data)
- {
- const struct mgmt_rp_read_index_list *rp = param;
- uint16_t num;
- int i;
- if (status != MGMT_STATUS_SUCCESS) {
- l_error("Failed to read index list: %s (0x%02x)",
- mgmt_errstr(status), status);
- return;
- }
- if (length < sizeof(*rp)) {
- l_error("Read index list response sixe too short");
- return;
- }
- num = btohs(rp->num_controllers);
- l_debug("Number of controllers: %u", num);
- if (num * sizeof(uint16_t) + sizeof(*rp) != length) {
- l_error("Incorrect packet size for index list response");
- return;
- }
- for (i = 0; i < num; i++) {
- uint16_t index;
- index = btohs(rp->index[i]);
- index_added(index, 0, NULL, user_data);
- }
- }
- static bool mesh_mgmt_init(void)
- {
- if (!read_info_regs)
- read_info_regs = l_queue_new();
- if (!mgmt_mesh) {
- mgmt_mesh = mgmt_new_default();
- if (!mgmt_mesh) {
- l_error("Failed to initialize mesh management");
- return false;
- }
- mgmt_register(mgmt_mesh, MGMT_EV_INDEX_ADDED,
- MGMT_INDEX_NONE, index_added, NULL, NULL);
- mgmt_register(mgmt_mesh, MGMT_EV_INDEX_REMOVED,
- MGMT_INDEX_NONE, index_removed, NULL, NULL);
- }
- return true;
- }
- bool mesh_mgmt_list(mesh_mgmt_read_info_func_t cb, void *user_data)
- {
- struct read_info_reg *reg;
- if (!mesh_mgmt_init())
- return false;
- reg = l_new(struct read_info_reg, 1);
- reg->cb = cb;
- reg->user_data = user_data;
- l_queue_push_tail(read_info_regs, reg);
- /* Use MGMT to find a candidate controller */
- l_debug("send read index_list");
- if (mgmt_send(mgmt_mesh, MGMT_OP_READ_INDEX_LIST,
- MGMT_INDEX_NONE, 0, NULL,
- read_index_list_cb, NULL, NULL) <= 0)
- return false;
- return true;
- }
|