• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2017 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "syscfg/syscfg.h"
8 #define MESH_LOG_MODULE BLE_MESH_MODEL_LOG
9 
10 #include "mesh/mesh.h"
11 #include "mesh_priv.h"
12 #include "mesh/model_cli.h"
13 
14 static s32_t msg_timeout = K_SECONDS(5);
15 
16 static struct bt_mesh_gen_model_cli *gen_onoff_cli;
17 static struct bt_mesh_gen_model_cli *gen_level_cli;
18 
19 static u8_t transaction_id = 0;
20 
21 struct gen_onoff_param {
22     u8_t *state;
23 };
24 
25 struct gen_level_param {
26     s16_t *level;
27 };
28 
gen_onoff_status(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct os_mbuf * buf)29 static void gen_onoff_status(struct bt_mesh_model *model,
30                              struct bt_mesh_msg_ctx *ctx,
31                              struct os_mbuf *buf)
32 {
33     struct bt_mesh_gen_model_cli *cli = model->user_data;
34     struct gen_onoff_param *param;
35     u8_t state;
36     BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
37            ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
38            bt_hex(buf->om_data, buf->om_len));
39 
40     if (cli->op_pending != OP_GEN_ONOFF_STATUS) {
41         BT_WARN("Unexpected Generic OnOff Status message");
42         return;
43     }
44 
45     param = cli->op_param;
46     state = net_buf_simple_pull_u8(buf);
47     if (param->state) {
48         *param->state = state;
49     }
50 
51     BT_DBG("state: %d", state);
52     k_sem_give(&cli->op_sync);
53 }
54 
gen_level_status(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct os_mbuf * buf)55 static void gen_level_status(struct bt_mesh_model *model,
56                              struct bt_mesh_msg_ctx *ctx,
57                              struct os_mbuf *buf)
58 {
59     struct bt_mesh_gen_model_cli *cli = model->user_data;
60     struct gen_level_param *param;
61     s16_t level;
62     BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
63            ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
64            bt_hex(buf->om_data, buf->om_len));
65 
66     if (cli->op_pending != OP_GEN_LEVEL_STATUS) {
67         BT_WARN("Unexpected Generic LEVEL Status message");
68         return;
69     }
70 
71     param = cli->op_param;
72     level = net_buf_simple_pull_le16(buf);
73     if (param->level) {
74         *param->level = level;
75     }
76 
77     BT_DBG("level: %d", level);
78     k_sem_give(&cli->op_sync);
79 }
80 
81 const struct bt_mesh_model_op gen_onoff_cli_op[] = {
82     { OP_GEN_ONOFF_STATUS, 1, gen_onoff_status },
83     BT_MESH_MODEL_OP_END,
84 };
85 
onoff_cli_init(struct bt_mesh_model * model)86 static int onoff_cli_init(struct bt_mesh_model *model)
87 {
88     BT_DBG("");
89 
90     if (!model->user_data) {
91         BT_ERR("No Generic OnOff Client context provided");
92         return -EINVAL;
93     }
94 
95     gen_onoff_cli = model->user_data;
96     gen_onoff_cli->model = model;
97     k_sem_init(&gen_onoff_cli->op_sync, 0, 1);
98     return 0;
99 }
100 
101 const struct bt_mesh_model_cb bt_mesh_gen_onoff_cli_cb = {
102     .init = onoff_cli_init,
103 };
104 
105 const struct bt_mesh_model_op gen_level_cli_op[] = {
106     { OP_GEN_LEVEL_STATUS, 2, gen_level_status },
107     BT_MESH_MODEL_OP_END,
108 };
109 
level_cli_init(struct bt_mesh_model * model)110 static int level_cli_init(struct bt_mesh_model *model)
111 {
112     BT_DBG("");
113 
114     if (!model->user_data) {
115         BT_ERR("No Generic Level Client context provided");
116         return -EINVAL;
117     }
118 
119     gen_level_cli = model->user_data;
120     gen_level_cli->model = model;
121     k_sem_init(&gen_level_cli->op_sync, 0, 1);
122     return 0;
123 }
124 
125 const struct bt_mesh_model_cb bt_mesh_gen_level_cli_cb = {
126     .init = level_cli_init,
127 };
128 
cli_wait(struct bt_mesh_gen_model_cli * cli,void * param,u32_t op)129 static int cli_wait(struct bt_mesh_gen_model_cli *cli, void *param, u32_t op)
130 {
131     int err;
132     BT_DBG("");
133     cli->op_param = param;
134     cli->op_pending = op;
135     err = k_sem_take(&cli->op_sync, msg_timeout);
136     cli->op_pending = 0;
137     cli->op_param = NULL;
138     return err;
139 }
140 
bt_mesh_gen_onoff_get(u16_t net_idx,u16_t addr,u16_t app_idx,u8_t * state)141 int bt_mesh_gen_onoff_get(u16_t net_idx, u16_t addr, u16_t app_idx,
142                           u8_t *state)
143 {
144     struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4);
145     struct bt_mesh_msg_ctx ctx = {
146         .net_idx = net_idx,
147         .app_idx = app_idx,
148         .addr = addr,
149         .send_ttl = BT_MESH_TTL_DEFAULT,
150     };
151     struct gen_onoff_param param = {
152         .state = state,
153     };
154     int err;
155     bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_GET);
156     err = bt_mesh_model_send(gen_onoff_cli->model, &ctx, msg, NULL, NULL);
157     if (err) {
158         BT_ERR("model_send() failed (err %d)", err);
159         goto done;
160     }
161 
162     err = cli_wait(gen_onoff_cli, &param, OP_GEN_ONOFF_STATUS);
163 done:
164     os_mbuf_free_chain(msg);
165     return err;
166 }
167 
bt_mesh_gen_onoff_set(u16_t net_idx,u16_t addr,u16_t app_idx,u8_t val,u8_t * state)168 int bt_mesh_gen_onoff_set(u16_t net_idx, u16_t addr, u16_t app_idx,
169                           u8_t val, u8_t *state)
170 {
171     struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 2 + 4);
172     struct bt_mesh_msg_ctx ctx = {
173         .net_idx = net_idx,
174         .app_idx = app_idx,
175         .addr = addr,
176         .send_ttl = BT_MESH_TTL_DEFAULT,
177     };
178     struct gen_onoff_param param = {
179         .state = state,
180     };
181     int err;
182 
183     if (state) {
184         bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_SET);
185     } else {
186         bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_SET_UNACK);
187     }
188 
189     net_buf_simple_add_u8(msg, val);
190     net_buf_simple_add_u8(msg, transaction_id);
191     err = bt_mesh_model_send(gen_onoff_cli->model, &ctx, msg, NULL, NULL);
192     if (err) {
193         BT_ERR("model_send() failed (err %d)", err);
194         goto done;
195     }
196 
197     if (!state) {
198         goto done;
199     }
200 
201     err = cli_wait(gen_onoff_cli, &param, OP_GEN_ONOFF_STATUS);
202 done:
203 
204     if (err == 0) {
205         transaction_id++;
206     }
207 
208     os_mbuf_free_chain(msg);
209     return err;
210 }
211 
bt_mesh_gen_level_get(u16_t net_idx,u16_t addr,u16_t app_idx,s16_t * level)212 int bt_mesh_gen_level_get(u16_t net_idx, u16_t addr, u16_t app_idx,
213                           s16_t *level)
214 {
215     struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4);
216     struct bt_mesh_msg_ctx ctx = {
217         .net_idx = net_idx,
218         .app_idx = app_idx,
219         .addr = addr,
220         .send_ttl = BT_MESH_TTL_DEFAULT,
221     };
222     struct gen_level_param param = {
223         .level = level,
224     };
225     int err;
226     bt_mesh_model_msg_init(msg, OP_GEN_LEVEL_GET);
227     err = bt_mesh_model_send(gen_level_cli->model, &ctx, msg, NULL, NULL);
228     if (err) {
229         BT_ERR("model_send() failed (err %d)", err);
230         goto done;
231     }
232 
233     err = cli_wait(gen_level_cli, &param, OP_GEN_LEVEL_STATUS);
234 done:
235     os_mbuf_free_chain(msg);
236     return err;
237 }
238 
bt_mesh_gen_level_set(u16_t net_idx,u16_t addr,u16_t app_idx,s16_t val,s16_t * state)239 int bt_mesh_gen_level_set(u16_t net_idx, u16_t addr, u16_t app_idx,
240                           s16_t val, s16_t *state)
241 {
242     struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 3 + 4);
243     struct bt_mesh_msg_ctx ctx = {
244         .net_idx = net_idx,
245         .app_idx = app_idx,
246         .addr = addr,
247         .send_ttl = BT_MESH_TTL_DEFAULT,
248     };
249     struct gen_level_param param = {
250         .level = state,
251     };
252     int err;
253 
254     if (state) {
255         bt_mesh_model_msg_init(msg, OP_GEN_LEVEL_SET);
256     } else {
257         bt_mesh_model_msg_init(msg, OP_GEN_LEVEL_SET_UNACK);
258     }
259 
260     net_buf_simple_add_le16(msg, val);
261     net_buf_simple_add_u8(msg, transaction_id);
262     err = bt_mesh_model_send(gen_level_cli->model, &ctx, msg, NULL, NULL);
263     if (err) {
264         BT_ERR("model_send() failed (err %d)", err);
265         goto done;
266     }
267 
268     if (!state) {
269         goto done;
270     }
271 
272     err = cli_wait(gen_level_cli, &param, OP_GEN_LEVEL_STATUS);
273 done:
274 
275     if (err == 0) {
276         transaction_id++;
277     }
278 
279     os_mbuf_free_chain(msg);
280     return err;
281 }
282 
283