server_common.c 8.8 KB

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