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