1 /*
2 * Copyright (C) 2018-2020 Alibaba Group Holding Limited
3 */
4
5 #include <api/mesh.h>
6 #include <mesh/access.h>
7 #include "misc/dlist.h"
8 //nclude "access.h"
9 #include "genie_service.h"
10
11 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_VENDOR_MODEL)
12 #include "common/log.h"
13
14 /**
15 * vendor model publish context, alloc maximum message buffer size
16 * */
17 struct bt_mesh_model_pub genie_model_pub = {
18 //max = 8 seg package
19 .msg = NET_BUF_SIMPLE(GENIE_MODEL_MTU), // allocate maximum payload size
20 };
21
genie_model_handle_mesg(genie_transport_model_param_t * p_msg)22 int genie_model_handle_mesg(genie_transport_model_param_t *p_msg)
23 {
24 uint8_t *p_data = NULL;
25
26 if (!p_msg)
27 {
28 BT_ERR("p_msg is null");
29 return -1;
30 }
31
32 if (p_msg->len < 2)
33 {
34 return genie_down_msg(GENIE_DOWN_MESG_VENDOR_TYPE, CONFIG_MESH_VENDOR_COMPANY_ID, p_msg);
35 }
36
37 if (!p_msg->data || p_msg->len == 0)
38 {
39 BT_ERR("invalid model mesg");
40 return -1;
41 }
42
43 p_data = p_msg->data;
44 BT_INFO("opcode:0x%x, tid:%d, len:%d", p_msg->opid, p_msg->tid, p_msg->len);
45
46 if (p_data && p_msg->len)
47 {
48 BT_INFO("payload: %s", bt_hex(p_data, p_msg->len));
49 }
50
51 #ifdef MESH_MODEL_VENDOR_TIMER
52 if (genie_time_handle_model_mesg(p_msg) != 0)
53 {
54 return 0; //This is genie time message
55 }
56 #endif
57
58 genie_down_msg(GENIE_DOWN_MESG_VENDOR_TYPE, CONFIG_MESH_VENDOR_COMPANY_ID, p_msg);
59
60 return 0;
61 }
62
63 /** @def genie_model_analyze
64 *
65 * @brief analyze the received message and notify genie SDK
66 *
67 * @param pointer to the received message (vendor model, context and the message buffer) and opid
68 *
69 * @return if success return 0; if fails return error no.
70 */
genie_model_analyze(struct bt_mesh_model * p_model,struct bt_mesh_msg_ctx * p_ctx,struct net_buf_simple * p_buf,u8_t opid)71 static s16_t genie_model_analyze(struct bt_mesh_model *p_model,
72 struct bt_mesh_msg_ctx *p_ctx,
73 struct net_buf_simple *p_buf,
74 u8_t opid)
75 {
76 genie_transport_model_param_t msg;
77 sig_model_element_state_t *p_elem = NULL;
78
79 if (!p_model || !p_buf || !p_model->user_data)
80 return MESH_ANALYZE_ARGS_ERROR;
81
82 if (p_buf->len < 3)
83 {
84 BT_ERR("invalid buf len(%d)", p_buf->len);
85 return MESH_ANALYZE_SIZE_ERROR;
86 }
87
88 p_elem = p_model->user_data;
89
90 memset(&msg, 0, sizeof(genie_transport_model_param_t));
91
92 msg.opid = opid;
93 msg.tid = net_buf_simple_pull_u8(p_buf);
94
95 if (genie_transport_check_tid(p_ctx->addr, msg.tid, p_elem->element_id) != MESH_SUCCESS)
96 {
97 BT_ERR("MESH_TID_REPEAT src_addr(0x%04x) tid(0x%02x)", p_ctx->addr, msg.tid);
98 return MESH_TID_REPEAT;
99 }
100 genie_transport_src_addr_set(p_ctx->addr);
101
102 msg.len = p_buf->len;
103 BT_INFO("opcode:0x%x, tid:%d, len:%d", msg.opid, msg.tid, msg.len);
104 if (msg.len)
105 {
106 msg.data = (u8_t *)p_buf->data;
107 net_buf_simple_pull(p_buf, msg.len);
108 BT_DBG("payload:%s", bt_hex(msg.data, msg.len));
109 }
110 else
111 {
112 msg.data = NULL;
113 }
114
115 msg.p_model = p_model;
116 genie_event(GENIE_EVT_VENDOR_MODEL_MSG, (void *)&msg);
117
118 return 0;
119 }
120
121 /** @def genie_model_get
122 *
123 * @brief handle VENDOR_OP_ATTR_GET_STATUS message
124 *
125 * @param pointer to the received message (vendor model, context and the message buffer)
126 *
127 * @return N/A
128 */
genie_model_get(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)129 static void genie_model_get(struct bt_mesh_model *model,
130 struct bt_mesh_msg_ctx *ctx,
131 struct net_buf_simple *buf)
132 {
133 genie_model_analyze(model, ctx, buf, VENDOR_OP_ATTR_GET_STATUS);
134 }
135
136 /** @def genie_model_set_ack
137 *
138 * @brief handle VENDOR_OP_ATTR_SET_ACK message
139 *
140 * @param pointer to the received message (vendor model, context and the message buffer)
141 *
142 * @return N/A
143 */
genie_model_set_ack(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)144 static void genie_model_set_ack(struct bt_mesh_model *model,
145 struct bt_mesh_msg_ctx *ctx,
146 struct net_buf_simple *buf)
147 {
148 genie_model_analyze(model, ctx, buf, VENDOR_OP_ATTR_SET_ACK);
149 }
150
151 /** @def genie_model_set_unack
152 *
153 * @brief handle VENDOR_OP_ATTR_SET_UNACK message
154 *
155 * @param pointer to the received message (vendor model, context and the message buffer)
156 *
157 * @return N/A
158 */
genie_model_set_unack(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)159 static void genie_model_set_unack(struct bt_mesh_model *model,
160 struct bt_mesh_msg_ctx *ctx,
161 struct net_buf_simple *buf)
162 {
163 genie_model_analyze(model, ctx, buf, VENDOR_OP_ATTR_SET_UNACK);
164 }
165
166 /** @def genie_model_confirm
167 *
168 * @brief handle VENDOR_OP_ATTR_CONFIME message
169 *
170 * @param pointer to the received message (vendor model, context and the message buffer)
171 *
172 * @return N/A
173 */
genie_model_confirm(struct bt_mesh_model * p_model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)174 static void genie_model_confirm(struct bt_mesh_model *p_model,
175 struct bt_mesh_msg_ctx *ctx,
176 struct net_buf_simple *buf)
177 {
178 u8_t tid = 0x0;
179 genie_transport_model_param_t msg;
180
181 if (!p_model || !p_model->user_data)
182 {
183 GENIE_LOG_ERR("param err");
184 return;
185 }
186
187 if (buf->len != 1)
188 {
189 BT_ERR("invalid buf len(%d)", buf->len);
190 return;
191 }
192
193 tid = net_buf_simple_pull_u8(buf);
194 genie_transport_ack(tid);
195
196 memset(&msg, 0, sizeof(genie_transport_model_param_t));
197 msg.opid = VENDOR_OP_ATTR_CONFIME;
198 msg.tid = tid;
199 msg.len = 0;
200 msg.data = NULL;
201
202 msg.p_model = p_model;
203 genie_event(GENIE_EVT_VENDOR_MODEL_MSG, (void *)&msg);
204 }
205
genie_model_get_indicate(struct bt_mesh_model * p_model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)206 static void genie_model_get_indicate(struct bt_mesh_model *p_model,
207 struct bt_mesh_msg_ctx *ctx,
208 struct net_buf_simple *buf)
209 {
210 u8_t tid = 0x0;
211 genie_transport_model_param_t msg;
212 struct net_buf_simple *p_msg = NET_BUF_SIMPLE(3 + 1 + 4); //opcode + tid + TransMIC
213
214 if (!p_model || !p_model->user_data)
215 {
216 GENIE_LOG_ERR("param err");
217 return;
218 }
219
220 tid = net_buf_simple_pull_u8(buf);
221 genie_transport_ack(tid);
222
223 bt_mesh_model_msg_init(p_msg, BT_MESH_MODEL_OP_3(VENDOR_OP_ATTR_CONFIME, CONFIG_MESH_VENDOR_COMPANY_ID));
224 net_buf_simple_add_u8(p_msg, tid);
225 ctx->send_ttl = GENIE_TRANSPORT_DEFAULT_TTL;
226 if (bt_mesh_model_send(p_model, ctx, p_msg, NULL, NULL))
227 {
228 BT_ERR("send comfirm fail");
229 }
230
231 memset(&msg, 0, sizeof(genie_transport_model_param_t));
232 msg.opid = VENDOR_OP_ATTR_INDICATE;
233 msg.tid = tid;
234 msg.len = 0;
235 msg.data = NULL;
236 genie_transport_src_addr_set(ctx->addr);
237 msg.p_model = p_model;
238
239 genie_event(GENIE_EVT_VENDOR_MODEL_MSG, (void *)&msg);
240 }
241
242 /** @def genie_model_confirm_tg
243 *
244 * @brief handle VENDOR_OP_ATTR_CONFIME_TG message
245 *
246 * @param pointer to the received message (vendor model, context and the message buffer)
247 *
248 * @return N/A
249 */
genie_model_confirm_tg(struct bt_mesh_model * p_model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)250 static void genie_model_confirm_tg(struct bt_mesh_model *p_model,
251 struct bt_mesh_msg_ctx *ctx,
252 struct net_buf_simple *buf)
253 {
254 u8_t tid = 0x0;
255 genie_transport_model_param_t msg;
256
257 if (!p_model || !p_model->user_data)
258 {
259 GENIE_LOG_ERR("param err");
260 return;
261 }
262
263 tid = net_buf_simple_pull_u8(buf);
264 genie_transport_ack(tid);
265
266 memset(&msg, 0, sizeof(genie_transport_model_param_t));
267 msg.opid = VENDOR_OP_ATTR_CONFIME_TG;
268 msg.tid = tid;
269 msg.len = buf->len;
270
271 if (msg.len)
272 {
273 msg.data = (u8_t *)buf->data;
274 net_buf_simple_pull(buf, msg.len);
275 BT_DBG("payload:%s", bt_hex(msg.data, msg.len));
276 }
277 else
278 {
279 msg.data = NULL;
280 }
281
282 msg.p_model = p_model;
283 genie_event(GENIE_EVT_VENDOR_MODEL_MSG, (void *)&msg);
284 }
285
286 /** @def genie_model_transparent
287 *
288 * @brief handle VENDOR_OP_ATTR_TRANS_MSG message
289 *
290 * @param pointer to the received message (vendor model, context and the message buffer)
291 *
292 * @return N/A
293 */
genie_model_transparent(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)294 static void genie_model_transparent(struct bt_mesh_model *model,
295 struct bt_mesh_msg_ctx *ctx,
296 struct net_buf_simple *buf)
297 {
298 genie_model_analyze(model, ctx, buf, VENDOR_OP_ATTR_TRANS_MSG);
299 }
300
301 /** @def genie_model_transparent_ack
302 *
303 * @brief handle VENDOR_OP_ATTR_TRANS_ACK message
304 *
305 * @param pointer to the received message (vendor model, context and the message buffer)
306 *
307 * @return N/A
308 */
genie_model_transparent_ack(struct bt_mesh_model * p_model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)309 static void genie_model_transparent_ack(struct bt_mesh_model *p_model,
310 struct bt_mesh_msg_ctx *ctx,
311 struct net_buf_simple *buf)
312 {
313 u8_t tid = 0x0;
314 genie_transport_model_param_t msg;
315
316 if (!p_model || !p_model->user_data)
317 {
318 GENIE_LOG_ERR("param err");
319 return;
320 }
321
322 if (buf->len != 1)
323 {
324 BT_ERR("invalid buf len(%d)", buf->len);
325 return;
326 }
327
328 tid = net_buf_simple_pull_u8(buf);
329 genie_transport_ack(tid);
330
331 memset(&msg, 0, sizeof(genie_transport_model_param_t));
332 msg.opid = VENDOR_OP_ATTR_TRANS_ACK;
333 msg.tid = tid;
334 msg.len = 0;
335 msg.data = NULL;
336
337 msg.p_model = p_model;
338 genie_event(GENIE_EVT_VENDOR_MODEL_MSG, (void *)&msg);
339 }
340
341 /** @def ggenie_model_alibaba_op
342 *
343 * @brief vendor model operations struct
344 *
345 */
346 const struct bt_mesh_model_op genie_model_op[VENDOR_MODEL_OPC_NUM] = {
347 {BT_MESH_MODEL_OP_3(VENDOR_OP_ATTR_GET_STATUS, CONFIG_MESH_VENDOR_COMPANY_ID), 2, genie_model_get},
348 {BT_MESH_MODEL_OP_3(VENDOR_OP_ATTR_SET_ACK, CONFIG_MESH_VENDOR_COMPANY_ID), 2, genie_model_set_ack},
349 {BT_MESH_MODEL_OP_3(VENDOR_OP_ATTR_SET_UNACK, CONFIG_MESH_VENDOR_COMPANY_ID), 2, genie_model_set_unack},
350 {BT_MESH_MODEL_OP_3(VENDOR_OP_ATTR_INDICATE, CONFIG_MESH_VENDOR_COMPANY_ID), 1, genie_model_get_indicate},
351 {BT_MESH_MODEL_OP_3(VENDOR_OP_ATTR_CONFIME, CONFIG_MESH_VENDOR_COMPANY_ID), 1, genie_model_confirm},
352 {BT_MESH_MODEL_OP_3(VENDOR_OP_ATTR_CONFIME_TG, CONFIG_MESH_VENDOR_COMPANY_ID), 1, genie_model_confirm_tg},
353 {BT_MESH_MODEL_OP_3(VENDOR_OP_ATTR_TRANS_MSG, CONFIG_MESH_VENDOR_COMPANY_ID), 1, genie_model_transparent},
354 {BT_MESH_MODEL_OP_3(VENDOR_OP_ATTR_TRANS_ACK, CONFIG_MESH_VENDOR_COMPANY_ID), 1, genie_model_transparent_ack},
355 BT_MESH_MODEL_OP_END,
356 };
357