server_common.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <errno.h>
  7. #include "mesh.h"
  8. #include "mesh_config.h"
  9. #include "access.h"
  10. #include "mesh_common.h"
  11. #include "generic_server.h"
  12. #include "lighting_server.h"
  13. #if CONFIG_BLE_MESH_SERVER_MODEL
  14. /**
  15. * According to Mesh Model Spec:
  16. * If the Transition Time field is not present and the Generic Default Transition
  17. * Time state is supported, the Generic Default Transition Time state shall be
  18. * used. Otherwise the transition shall be instantaneous.
  19. */
  20. #define INSTANTANEOUS_TRANS_TIME 0
  21. uint8_t bt_mesh_get_default_trans_time(struct bt_mesh_model *model)
  22. {
  23. /**
  24. * 1. If a Generic Default Transition Time Server model is present on the
  25. * main element of the model, that model instance shall be used.
  26. * 2. If a Generic Default Transition Time Server model is not present on
  27. * the main element of the model, then the Generic Default Transition
  28. * Time Server model instance that is present on the element with the
  29. * largest address that is smaller than the address of the main element
  30. * of the node shall be used; if no model instance is present on any
  31. * element with an address smaller than the address of the main element,
  32. * then the Generic Default Transition Time Server is not supported.
  33. */
  34. struct bt_mesh_elem *element = bt_mesh_model_elem(model);
  35. struct bt_mesh_gen_def_trans_time_srv *state = NULL;
  36. uint16_t primary_addr = bt_mesh_primary_addr();
  37. struct bt_mesh_model *srv = NULL;
  38. for (uint16_t addr = element->addr; addr >= primary_addr; addr--) {
  39. element = bt_mesh_elem_find(addr);
  40. if (element) {
  41. srv = bt_mesh_model_find(element, BLE_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV);
  42. if (srv) {
  43. state = (struct bt_mesh_gen_def_trans_time_srv *)srv->user_data;
  44. if (state) {
  45. return state->state.trans_time;
  46. }
  47. }
  48. }
  49. }
  50. return INSTANTANEOUS_TRANS_TIME;
  51. }
  52. int bt_mesh_get_light_lc_trans_time(struct bt_mesh_model *model, uint8_t *trans_time)
  53. {
  54. struct bt_mesh_light_lc_srv *srv = NULL;
  55. uint32_t value = 0U;
  56. if (model == NULL || trans_time == NULL) {
  57. BT_ERR("%s, Invalid parameter", __func__);
  58. return -EINVAL;
  59. }
  60. if (model->id != BLE_MESH_MODEL_ID_LIGHT_LC_SRV) {
  61. BT_ERR("Invalid a Light LC Server 0x%04x", model->id);
  62. return -EINVAL;
  63. }
  64. srv = (struct bt_mesh_light_lc_srv *)model->user_data;
  65. if (srv == NULL) {
  66. BT_ERR("Invalid Light LC Server user data");
  67. return -EINVAL;
  68. }
  69. /**
  70. * 1. Set transition time to 0x54 for BQB test case MESH/SR/LLC/BV-04-C.
  71. * Light LC Property Set: 0x3C, 0x004E20 -> Light LC Time Run On
  72. * Light LC Property Set: 0x37, 0x004E20 -> Light LC Time Fade On
  73. * Light LC Property Set: 0x39, 0x004E20 -> Light LC Time Fade Standby Manual
  74. *
  75. * 2. Set transition time to 0x0 for BQB test case MESH/SR/LLC/BV-08-C.
  76. *
  77. * TODO: Based on Light LC state and choose property property value as the
  78. * transition time. Currently directly use Light LC Time Run On property value.
  79. * Unit: Millisecond, range: [0, 16777214(0xFFFFFE)]
  80. */
  81. value = srv->lc->prop_state.time_run_on & 0xFFFFFF;
  82. /**
  83. * Convert value into Default Transition Time state format.
  84. * 0b00: 0 ~ 6.2s, 100 millisecond step resolution
  85. * 0b01: 0 ~ 62s, 1 second step resolution
  86. * 0b10: 0 ~ 620s, 10 seconds step resolution
  87. * 0b11: 0 ~ 620m, 10 minutes step resolution
  88. */
  89. if (value <= 6200) {
  90. *trans_time = (0 << 6) | (value / 100);
  91. } else if (value <= 62000) {
  92. *trans_time = (1 << 6) | (value / 1000);
  93. } else if (value <= 620000) {
  94. *trans_time = (2 << 6) | (value / 10000);
  95. } else {
  96. *trans_time = (3 << 6) | (value / 600000);
  97. }
  98. return 0;
  99. }
  100. int bt_mesh_server_get_optional(struct bt_mesh_model *model,
  101. struct bt_mesh_msg_ctx *ctx,
  102. struct net_buf_simple *buf,
  103. uint8_t *trans_time, uint8_t *delay,
  104. bool *optional)
  105. {
  106. if (model == NULL || buf == NULL || trans_time == NULL ||
  107. delay == NULL || optional == NULL) {
  108. BT_ERR("%s, Invalid parameter", __func__);
  109. return -EINVAL;
  110. }
  111. if (buf->len != 0x00 && buf->len != 0x02) {
  112. BT_ERR("Invalid optional message length %d", buf->len);
  113. return -EINVAL;
  114. }
  115. /* Currently we only get optional msg info which dst is set to a unicast address */
  116. if (!BLE_MESH_ADDR_IS_UNICAST(ctx->recv_dst)) {
  117. *trans_time = 0U;
  118. *delay = 0U;
  119. *optional = false;
  120. return 0;
  121. }
  122. /* No optional fields are available */
  123. if (buf->len == 0x00) {
  124. if (model->id == BLE_MESH_MODEL_ID_LIGHT_LC_SRV) {
  125. /**
  126. * Both messages(i.e. Light LC OnOff Set/Set Unack) may optionally include
  127. * a Transition Time field indicating the transition time to the target state.
  128. * If the Transition Time is not included, the Light LC Server shall use
  129. * its appropriate transition times defined by the Light LC Property states.
  130. */
  131. if (bt_mesh_get_light_lc_trans_time(model, trans_time)) {
  132. BT_ERR("Failed to get Light LC transition time");
  133. return -EIO;
  134. }
  135. } else {
  136. *trans_time = bt_mesh_get_default_trans_time(model);
  137. }
  138. *delay = 0U;
  139. *optional = false;
  140. return 0;
  141. }
  142. /* Optional fields are available */
  143. *trans_time = net_buf_simple_pull_u8(buf);
  144. if ((*trans_time & 0x3F) == 0x3F) {
  145. BT_ERR("Invalid Transaction Number of Steps 0x3f");
  146. return -EINVAL;
  147. }
  148. *delay = net_buf_simple_pull_u8(buf);
  149. *optional = true;
  150. return 0;
  151. }
  152. void bt_mesh_server_alloc_ctx(struct k_work *work)
  153. {
  154. /**
  155. * This function is used to allocate memory for storing "struct bt_mesh_msg_ctx"
  156. * of the received messages, because some server models will callback the "struct
  157. * bt_mesh_msg_ctx" info to the application layer after a certain delay.
  158. * Here we use the allocated heap memory to store the "struct bt_mesh_msg_ctx".
  159. */
  160. __ASSERT(work, "Invalid parameter");
  161. if (!work->_reserved) {
  162. work->_reserved = bt_mesh_calloc(sizeof(struct bt_mesh_msg_ctx));
  163. __ASSERT(work->_reserved, "Out of memory");
  164. }
  165. }
  166. #if CONFIG_BLE_MESH_DEINIT
  167. void bt_mesh_server_free_ctx(struct k_work *work)
  168. {
  169. __ASSERT(work, "Invalid parameter");
  170. if (work->_reserved) {
  171. bt_mesh_free(work->_reserved);
  172. work->_reserved = NULL;
  173. }
  174. }
  175. #endif /* CONFIG_BLE_MESH_DEINIT */
  176. bool bt_mesh_is_server_recv_last_msg(struct bt_mesh_last_msg_info *last,
  177. uint8_t tid, uint16_t src, uint16_t dst, int64_t *now)
  178. {
  179. *now = k_uptime_get();
  180. /* Currently we only compare msg info which dst is set to a unicast address */
  181. if (!BLE_MESH_ADDR_IS_UNICAST(dst)) {
  182. return false;
  183. }
  184. if (last->tid == tid && last->src == src && last->dst == dst &&
  185. (*now - last->timestamp <= K_SECONDS(6))) {
  186. return true;
  187. }
  188. return false;
  189. }
  190. void bt_mesh_server_update_last_msg(struct bt_mesh_last_msg_info *last,
  191. uint8_t tid, uint16_t src, uint16_t dst, int64_t *now)
  192. {
  193. /* Currently we only update msg info which dst is set to a unicast address */
  194. if (!BLE_MESH_ADDR_IS_UNICAST(dst)) {
  195. return;
  196. }
  197. last->tid = tid;
  198. last->src = src;
  199. last->dst = dst;
  200. last->timestamp = *now;
  201. return;
  202. }
  203. struct net_buf_simple *bt_mesh_server_get_pub_msg(struct bt_mesh_model *model, uint16_t msg_len)
  204. {
  205. struct net_buf_simple *buf = NULL;
  206. if (model == NULL) {
  207. BT_ERR("%s, Invalid parameter", __func__);
  208. return NULL;
  209. }
  210. if (model->pub == NULL || model->pub->msg == NULL ||
  211. model->pub->addr == BLE_MESH_ADDR_UNASSIGNED) {
  212. BT_DBG("No publication support, model id 0x%04x", model->id);
  213. return NULL;
  214. }
  215. buf = model->pub->msg;
  216. if (buf->size < msg_len) {
  217. BT_ERR("Too small publication msg size %d, model id 0x%04x",
  218. buf->size, model->id);
  219. return NULL;
  220. }
  221. return buf;
  222. }
  223. #endif /* CONFIG_BLE_MESH_SERVER_MODEL */