1 /**
2 ****************************************************************************************
3 *
4 * @file user.c
5 *
6 * @brief user defined.
7 *
8 * Copyright (C) RivieraWaves 2009-2016
9 *
10 *
11 ****************************************************************************************
12 */
13
14 /**
15 ****************************************************************************************
16 * @addtogroup USER
17 * @{
18 ****************************************************************************************
19 */
20
21 /*
22 * INCLUDE FILES
23 ****************************************************************************************
24 */
25 #include "rwip_config.h"
26 #include "app.h"
27
28 #if (BLE_APP_USER)
29 #include "attm.h"
30 #include "user.h"
31 #include "user_task.h"
32 #include "co_utils.h"
33 #include "co_endian.h"
34 #include "prf_utils.h"
35
36 #include "ke_mem.h"
37 //#include "interface.h"
38 #include "ble_arch.h"
39
40 #ifdef N32WB452_BT_API
41 #include "n32wb452_ble_api.h"
42
43 extern bt_attr_param * g_bt_init;
44 #endif
45 //#include "att.h"
46 /*
47 * HTPT PROFILE ATTRIBUTES
48 *****************************************************************************************/
49
50
51 /// Full HTS Database Description - Used to add attributes into the database
52
53 const struct attm_desc user_att_db[USER_IDX_NB] =
54 {
55 // FF00 Service Declaration
56 [USER_IDX_SVC] = {ATT_DECL_PRIMARY_SERVICE, PERM(RD, ENABLE), 0, 0},
57
58 // FF01 Characteristic Declaration
59 [USER_IDX_WRITE_NOTIFY_CHAR] = {ATT_DECL_CHARACTERISTIC, PERM(RD, ENABLE) | PERM(WRITE_REQ, ENABLE), 0, 0},
60 // Characteristic Value
61
62 #ifndef BLE_OTA_WRITE_CHAR_EN
63
64 // Characteristic Value
65 [USER_IDX_WRITE_NOTIFY_VAL] = {ATT_CHAR_WRITE_NOTIFY, PERM(WRITE_COMMAND, ENABLE)|PERM(NTF, ENABLE), PERM(RI, ENABLE), 0x300},
66 //Client Characteristic Configuration Descriptor
67 [USER_IDX_WRITE_NOTIFY_CFG] = {ATT_DESC_CLIENT_CHAR_CFG, PERM(RD, ENABLE) | PERM(WRITE_REQ, ENABLE), 0/*PERM(RI, ENABLE)*/, 0x200},
68 #endif
69 #ifdef BLE_OTA_WRITE_CHAR_EN
70 // Characteristic Value
71 [USER_IDX_WRITE_NOTIFY_VAL] = {ATT_CHAR_WRITE_NOTIFY,
72 PERM(WRITE_REQ, ENABLE) | PERM(WRITE_COMMAND, ENABLE) /*|PERM(NTF, ENABLE)*/,
73 0 /*PERM(RI, ENABLE)*/,
74 0x300},
75 // Client Characteristic Configuration Descriptor
76 [USER_IDX_WRITE_NOTIFY_CFG] = {ATT_DESC_CLIENT_CHAR_CFG,
77 PERM(RD, ENABLE) | PERM(WRITE_REQ, ENABLE),
78 0 /*PERM(RI, ENABLE)*/,
79 0x200},
80
81 // Characteristic Declaration
82 [USER_IDX_READ_NOTIFY_CHAR] = {ATT_DECL_CHARACTERISTIC, PERM(RD, ENABLE), 0, 0},
83 // Characteristic Value
84 [USER_IDX_READ_NOTIFY_VAL] = {ATT_CHAR_READ_NOTIFY,
85 /*PERM(RD, ENABLE) |*/ PERM(NTF, ENABLE),
86 (/*PERM(RI, ENABLE)|*/ PERM(NTF, ENABLE)),
87 0x200},
88 //[USER_IDX_READ_NOTIFY_VAL] = {ATT_CHAR_READ_NOTIFY, PERM(RD, ENABLE) |PERM(NTF, ENABLE), (PERM(RI, ENABLE)|PERM(NTF, ENABLE)), 0x200},
89 //Client Characteristic Configuration Descriptor
90 [USER_IDX_WRITE_NOTIFY2_CFG] = {ATT_DESC_CLIENT_CHAR_CFG, PERM(RD, ENABLE) | /* PERM(WP,ENABLE)|*/PERM(WRITE_REQ, ENABLE), 0/*PERM(RI, ENABLE)*/, 0x200},
91 #endif
92 };
93
94 #ifdef N32WB452_BT_API
get_user_character_perm(uint16_t perm)95 uint16_t get_user_character_perm(uint16_t perm)
96 {
97 uint16_t ret = 0;
98
99 // ble_log(BLE_DEBUG,"PERM(WRITE_COMMAND, ENABLE) = %0x.\r\n", PERM(WRITE_COMMAND, ENABLE));
100 // ble_log(BLE_DEBUG,"PERM(NTF, ENABLE) = %0x.\r\n", PERM(NTF, ENABLE));
101
102 if (perm & BT_RD_PERM) {
103 ret |= PERM(RD, ENABLE);
104 }
105
106 if (perm & BT_WRITE_PERM) {
107 ret |= PERM(WRITE_COMMAND, ENABLE);
108 // ble_log(BLE_DEBUG,"ret1 = %x.\r\n", ret);
109 }
110
111 if (perm & BT_WRITE_REQ_PERM) {
112 ret |= PERM(WRITE_REQ, ENABLE);
113 }
114
115 if (perm & BT_NTF_PERM) {
116 ret |= PERM(NTF, ENABLE);
117 // ble_log(BLE_DEBUG,"ret2 = %x.\r\n", ret);
118 }
119
120 return ret;
121 }
122 #endif
123
124 /*
125 * LOCAL FUNCTION DEFINITIONS
126 ****************************************************************************************
127 */
user_init(struct prf_task_env * env,uint16_t * start_hdl,uint16_t app_task,uint8_t sec_lvl,struct user_db_cfg * params)128 static uint8_t user_init(struct prf_task_env *env, uint16_t *start_hdl, uint16_t app_task,uint8_t sec_lvl, struct user_db_cfg *params)
129 {
130 #ifdef N32WB452_BT_API
131 //uint16_t perm;
132 volatile struct attm_desc user_att_db_api_define[USER_IDX_NB] = {0};
133 #endif
134
135 // Service content flag
136 uint16_t cfg_flag = (1<<USER_IDX_NB) - 1;
137 // DB Creation Status
138 uint8_t status = ATT_ERR_NO_ERROR;
139 cfg_flag = co_btohs(cfg_flag);
140
141 #ifdef N32WB452_BT_API0
142 if (g_bt_init) {
143 //设置其他默认服务
144 memcpy((void*)user_att_db_api_define, (void*)user_att_db, sizeof(user_att_db_api_define));
145
146 //配置用户定义服务和character
147 if (g_bt_init->service[0].character[0].uuid \
148 && (g_bt_init->service[0].character[0].permission & BT_WRITE_PERM)
149 && (g_bt_init->service[0].character[0].permission & BT_NTF_PERM)) {
150 user_att_db_api_define[USER_IDX_WRITE_NOTIFY_VAL].uuid = ATT_UUID_16(g_bt_init->service[0].character[0].uuid);
151 user_att_db_api_define[USER_IDX_WRITE_NOTIFY_VAL].perm = get_user_character_perm(g_bt_init->service[0].character[0].permission);
152 user_att_db_api_define[USER_IDX_WRITE_NOTIFY_VAL].ext_perm = 0;
153 user_att_db_api_define[USER_IDX_WRITE_NOTIFY_VAL].max_size = 0x300;
154 }
155
156 user_att_db_api_define[USER_IDX_WRITE_NOTIFY_VAL].uuid = ATT_UUID_16(g_bt_init->service[0].character[0].uuid);
157
158 status = attm_svc_create_db(start_hdl, (uint16_t)g_bt_init->service[0].svc_uuid, (uint8_t *)&cfg_flag,USER_IDX_NB, NULL, env->task, &user_att_db_api_define[0],(sec_lvl & (PERM_MASK_SVC_DIS | PERM_MASK_SVC_AUTH | PERM_MASK_SVC_EKS)) | PERM(SVC_MI, DISABLE));
159 } else {
160 status = attm_svc_create_db(start_hdl, (uint16_t)ATT_SVC_UKEY_SERVICE, (uint8_t *)&cfg_flag,USER_IDX_NB, NULL, env->task, &user_att_db[0],(sec_lvl & (PERM_MASK_SVC_DIS | PERM_MASK_SVC_AUTH | PERM_MASK_SVC_EKS)) | PERM(SVC_MI, DISABLE));
161 }
162 #else
163 status = attm_svc_create_db(start_hdl, (uint16_t)ATT_SVC_UKEY_SERVICE, (uint8_t *)&cfg_flag,USER_IDX_NB, NULL, env->task, &user_att_db[0],(sec_lvl & (PERM_MASK_SVC_DIS | PERM_MASK_SVC_AUTH | PERM_MASK_SVC_EKS)) | PERM(SVC_MI, DISABLE));
164 #endif
165 if (status == ATT_ERR_NO_ERROR)
166 {
167 //-------------------- allocate memory required for the profile ---------------------
168 struct user_env_tag *user_env =
169 (struct user_env_tag *) ke_malloc(sizeof(struct user_env_tag), KE_MEM_ATT_DB);
170
171 // allocate PROXR required environment variable
172 env->env = (prf_env_t *) user_env;
173
174 user_env->shdl = *start_hdl;
175 user_env->prf_env.app_task = app_task | (PERM_GET(sec_lvl, SVC_MI) ? PERM(PRF_MI, ENABLE) : PERM(PRF_MI, DISABLE));
176 user_env->prf_env.prf_task = env->task | PERM(PRF_MI, DISABLE);
177
178 // initialize environment variable
179 env->id = TASK_ID_USER;
180 env->desc.idx_max = 1;
181 env->desc.state = user_env->state;
182 env->desc.default_handler = &user_default_handler;
183
184 //Save features on the environment
185 user_env->features = params->features;
186 user_env->operation = NULL;
187 memset(user_env->ntf_ind_cfg, 0 , sizeof(user_env->ntf_ind_cfg));
188
189 // service is ready, go into an Idle state
190 ke_state_set(env->task, USER_IDLE);
191 }
192 return (status);
193 }
194
195
user_destroy(struct prf_task_env * env)196 static void user_destroy(struct prf_task_env *env)
197 {
198 struct user_env_tag *user_env = (struct user_env_tag *) env->env;
199
200 // free profile environment variables
201 if (user_env->operation != NULL)
202 {
203 ke_free(user_env->operation);
204 }
205
206
207 env->env = NULL;
208 ke_free(user_env);
209 }
210
user_create(struct prf_task_env * env,uint8_t conidx)211 static void user_create(struct prf_task_env *env, uint8_t conidx)
212 {
213 /* Clear configuration for this connection */
214 struct user_env_tag *user_env = (struct user_env_tag *) env->env;
215 //user_env->ntf_ind_cfg[conidx] = 0x03;
216 user_env->ntf_ind_cfg[USER_IDX_WRITE_NOTIFY_CFG] = USER_DATA_NTF;
217 #ifdef BLE_OTA_WRITE_CHAR_EN
218 user_env->ntf_ind_cfg[USER_IDX_WRITE_NOTIFY2_CFG] = USER_DATA_NTF;
219 #endif
220 }
221
user_cleanup(struct prf_task_env * env,uint8_t conidx,uint8_t reason)222 static void user_cleanup(struct prf_task_env *env, uint8_t conidx, uint8_t reason)
223 {
224 /* Clear configuration for this connection */
225 struct user_env_tag *user_env = (struct user_env_tag *) env->env;
226 user_env->ntf_ind_cfg[USER_IDX_WRITE_NOTIFY_CFG] = USER_DATA_NTF_IND_DISABLE;
227 #ifdef BLE_OTA_WRITE_CHAR_EN
228 user_env->ntf_ind_cfg[USER_IDX_WRITE_NOTIFY2_CFG] = USER_DATA_NTF_IND_DISABLE;
229 #endif
230
231 }
232
233
234 /*
235 * GLOBAL VARIABLE DEFINITIONS
236 ****************************************************************************************
237 */
238
239 /// HTPT Task interface required by profile manager
240 const struct prf_task_cbs user_itf =
241 {
242 (prf_init_fnct) user_init,
243 user_destroy,
244 user_create,
245 user_cleanup,
246 };
247
248
249
250
user_prf_itf_get(void)251 const struct prf_task_cbs *user_prf_itf_get(void)
252 {
253 return &user_itf;
254 }
255
256
user_att_hdl_get(struct user_env_tag * user_env,uint8_t att_idx)257 uint16_t user_att_hdl_get(struct user_env_tag *user_env, uint8_t att_idx)
258 {
259 uint16_t handle = user_env->shdl;
260
261 handle += att_idx;
262
263 return handle;
264 }
265
user_att_idx_get(struct user_env_tag * user_env,uint16_t handle)266 uint8_t user_att_idx_get(struct user_env_tag *user_env, uint16_t handle)
267 {
268 uint16_t handle_ref = user_env->shdl;
269 uint8_t att_idx = ATT_INVALID_IDX;
270
271 if (handle >handle_ref)
272 {
273 att_idx = handle - handle_ref;
274 }
275
276 return att_idx;
277 }
278
user_exe_operation(void)279 void user_exe_operation(void)
280 {
281 struct user_env_tag *user_env = PRF_ENV_GET(USER, user);
282
283 ASSERT_ERR(user_env->operation != NULL);
284
285 bool finished = true;
286
287 while (user_env->operation->cursor < BLE_CONNECTION_MAX)
288 {
289 // check if this type of event is enabled
290 if (( ( /*user_env->ntf_ind_cfg[user_env->operation->cursor] & */ user_env->operation->op) != 0) /*&& (user_env->operation->conidx != user_env->operation->cursor)*/)
291 {
292 // trigger the event
293 struct gattc_send_evt_cmd *evt = KE_MSG_ALLOC_DYN(GATTC_SEND_EVT_CMD,KE_BUILD_ID(TASK_GATTC , user_env->operation->cursor), prf_src_task_get(&user_env->prf_env, 0),gattc_send_evt_cmd, user_env->operation->length);
294 evt->operation = (user_env->operation->op != USER_DATA_NTF) ? GATTC_INDICATE : GATTC_NOTIFY;
295 evt->length = user_env->operation->length;
296 evt->handle = user_env->operation->handle;
297 memcpy(evt->value, user_env->operation->data, evt->length);
298 ke_msg_send(evt);
299
300 finished = false;
301 user_env->operation->cursor++;
302 break;
303 }
304 user_env->operation->cursor++;
305 }
306
307 // check if operation is finished
308 if (finished)
309 {
310
311 // do not send response if operation has been locally requested
312 if (user_env->operation->dest_id != prf_src_task_get(&user_env->prf_env, 0))
313 {
314
315 // send response to requester
316 struct user_upd_rsp *rsp = KE_MSG_ALLOC(((user_env->operation->op == USER_DATA_NTF) ? USER_NOTIFY_RSP : USER_INTV_RSP),user_env->operation->dest_id, prf_src_task_get(&user_env->prf_env, 0),user_upd_rsp);
317 rsp->status = GAP_ERR_NO_ERROR;
318 ke_msg_send(rsp);
319 }
320
321 // free operation
322 ke_free(user_env->operation);
323 user_env->operation = NULL;
324 // go back to idle state
325 ke_state_set(prf_src_task_get(&(user_env->prf_env), 0), USER_IDLE);
326 }
327 }
328
329
330
user_update_ntf_ind_cfg(uint8_t conidx,uint8_t cfg,uint16_t valid_val,uint8_t idx,uint16_t value)331 uint8_t user_update_ntf_ind_cfg(uint8_t conidx, uint8_t cfg, uint16_t valid_val, uint8_t idx, uint16_t value)
332 {
333 struct user_env_tag *user_env = PRF_ENV_GET(USER, user);
334 uint8_t status = GAP_ERR_NO_ERROR;
335
336 if ((value != valid_val) && (value != PRF_CLI_STOP_NTFIND))
337 {
338 status = PRF_APP_ERROR;
339 }
340
341 user_env->ntf_ind_cfg[idx] = value;
342 // else if (value == valid_val)
343 // {
344 // user_env->ntf_ind_cfg[idx]|= cfg;
345 // }
346 // else
347 // {
348 // user_env->ntf_ind_cfg[idx] &= ~cfg;
349 // }
350
351 if (status == GAP_ERR_NO_ERROR)
352 {
353 // no msg handler blank by ding.yuanwwu
354 // inform application that notification/indication configuration has changed
355 // struct user_cfg_indntf_ind *ind = KE_MSG_ALLOC(USER_CFG_INDNTF_IND, prf_dst_task_get(&user_env->prf_env, conidx), prf_src_task_get(&user_env->prf_env, conidx),user_cfg_indntf_ind);
356 // ind->conidx = conidx;
357 // ind->ntf_ind_cfg = user_env->ntf_ind_cfg[conidx];
358 // ke_msg_send(ind);
359 }
360
361 return (status);
362 }
363
364 #endif //BLE_HT_THERMOM
365
366