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