mesh-mgmt.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // SPDX-License-Identifier: LGPL-2.1-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2019 SILVAIR sp. z o.o. All rights reserved.
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #include "lib/bluetooth.h"
  14. #include "lib/mgmt.h"
  15. #include "src/shared/mgmt.h"
  16. #include "ell/queue.h"
  17. #include "ell/log.h"
  18. #include "ell/util.h"
  19. #include "mesh/mesh-mgmt.h"
  20. struct read_info_reg {
  21. mesh_mgmt_read_info_func_t cb;
  22. void *user_data;
  23. };
  24. struct read_info_req {
  25. int index;
  26. struct mesh_io *io;
  27. };
  28. static struct mgmt *mgmt_mesh;
  29. static struct l_queue *read_info_regs;
  30. static void process_read_info_req(void *data, void *user_data)
  31. {
  32. struct read_info_reg *reg = data;
  33. int index = L_PTR_TO_UINT(user_data);
  34. reg->cb(index, reg->user_data);
  35. }
  36. static void read_info_cb(uint8_t status, uint16_t length,
  37. const void *param, void *user_data)
  38. {
  39. int index = L_PTR_TO_UINT(user_data);
  40. const struct mgmt_rp_read_info *rp = param;
  41. uint32_t current_settings, supported_settings;
  42. l_debug("hci %u status 0x%02x", index, status);
  43. if (status != MGMT_STATUS_SUCCESS) {
  44. l_error("Failed to read info for hci index %u: %s (0x%02x)",
  45. index, mgmt_errstr(status), status);
  46. return;
  47. }
  48. if (length < sizeof(*rp)) {
  49. l_error("Read info response too short");
  50. return;
  51. }
  52. current_settings = btohl(rp->current_settings);
  53. supported_settings = btohl(rp->supported_settings);
  54. l_debug("settings: supp %8.8x curr %8.8x",
  55. supported_settings, current_settings);
  56. if (current_settings & MGMT_SETTING_POWERED) {
  57. l_info("Controller hci %u is in use", index);
  58. return;
  59. }
  60. if (!(supported_settings & MGMT_SETTING_LE)) {
  61. l_info("Controller hci %u does not support LE", index);
  62. return;
  63. }
  64. l_queue_foreach(read_info_regs, process_read_info_req,
  65. L_UINT_TO_PTR(index));
  66. }
  67. static void index_added(uint16_t index, uint16_t length, const void *param,
  68. void *user_data)
  69. {
  70. mgmt_send(mgmt_mesh, MGMT_OP_READ_INFO, index, 0, NULL,
  71. read_info_cb, L_UINT_TO_PTR(index), NULL);
  72. }
  73. static void index_removed(uint16_t index, uint16_t length, const void *param,
  74. void *user_data)
  75. {
  76. l_warn("Hci dev %4.4x removed", index);
  77. }
  78. static void read_index_list_cb(uint8_t status, uint16_t length,
  79. const void *param, void *user_data)
  80. {
  81. const struct mgmt_rp_read_index_list *rp = param;
  82. uint16_t num;
  83. int i;
  84. if (status != MGMT_STATUS_SUCCESS) {
  85. l_error("Failed to read index list: %s (0x%02x)",
  86. mgmt_errstr(status), status);
  87. return;
  88. }
  89. if (length < sizeof(*rp)) {
  90. l_error("Read index list response sixe too short");
  91. return;
  92. }
  93. num = btohs(rp->num_controllers);
  94. l_debug("Number of controllers: %u", num);
  95. if (num * sizeof(uint16_t) + sizeof(*rp) != length) {
  96. l_error("Incorrect packet size for index list response");
  97. return;
  98. }
  99. for (i = 0; i < num; i++) {
  100. uint16_t index;
  101. index = btohs(rp->index[i]);
  102. index_added(index, 0, NULL, user_data);
  103. }
  104. }
  105. static bool mesh_mgmt_init(void)
  106. {
  107. if (!read_info_regs)
  108. read_info_regs = l_queue_new();
  109. if (!mgmt_mesh) {
  110. mgmt_mesh = mgmt_new_default();
  111. if (!mgmt_mesh) {
  112. l_error("Failed to initialize mesh management");
  113. return false;
  114. }
  115. mgmt_register(mgmt_mesh, MGMT_EV_INDEX_ADDED,
  116. MGMT_INDEX_NONE, index_added, NULL, NULL);
  117. mgmt_register(mgmt_mesh, MGMT_EV_INDEX_REMOVED,
  118. MGMT_INDEX_NONE, index_removed, NULL, NULL);
  119. }
  120. return true;
  121. }
  122. bool mesh_mgmt_list(mesh_mgmt_read_info_func_t cb, void *user_data)
  123. {
  124. struct read_info_reg *reg;
  125. if (!mesh_mgmt_init())
  126. return false;
  127. reg = l_new(struct read_info_reg, 1);
  128. reg->cb = cb;
  129. reg->user_data = user_data;
  130. l_queue_push_tail(read_info_regs, reg);
  131. /* Use MGMT to find a candidate controller */
  132. l_debug("send read index_list");
  133. if (mgmt_send(mgmt_mesh, MGMT_OP_READ_INDEX_LIST,
  134. MGMT_INDEX_NONE, 0, NULL,
  135. read_index_list_cb, NULL, NULL) <= 0)
  136. return false;
  137. return true;
  138. }