1 /**
2 ****************************************************************************************
3 *
4 * @file rtus.c
5 *
6 * @brief Reference Time Update Service implementation.
7 *
8 ****************************************************************************************
9 * @attention
10 #####Copyright (c) 2019 GOODIX
11 All rights reserved.
12
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions are met:
15 * Redistributions of source code must retain the above copyright
16 notice, this list of conditions and the following disclaimer.
17 * Redistributions in binary form must reproduce the above copyright
18 notice, this list of conditions and the following disclaimer in the
19 documentation and/or other materials provided with the distribution.
20 * Neither the name of GOODIX nor the names of its contributors may be used
21 to endorse or promote products derived from this software without
22 specific prior written permission.
23
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
28 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 POSSIBILITY OF SUCH DAMAGE.
35 *****************************************************************************************
36 */
37
38 /*
39 * INCLUDE FILES
40 ****************************************************************************************
41 */
42 #include "rtus.h"
43 #include "ble_prf_types.h"
44 #include "ble_prf_utils.h"
45 #include "utility.h"
46
47 /*
48 * ENUMERATIONS
49 ****************************************************************************************
50 */
51 /**@brief Reference Time Update Service Attributes Indexes. */
52 enum {
53 // Reference Time Update Service
54 RTUS_IDX_SVC,
55
56 // Time Update Control Point
57 RTUS_IDX_CTRL_PT_CHAR,
58 RTUS_IDX_CTRL_PT_VAL,
59
60 // Time Update State
61 RTUS_IDX_UPDATE_STATE_CHAR,
62 RTUS_IDX_UPDATE_STATE_VAL,
63
64 RTUS_IDX_NB
65 };
66
67 /*
68 * STRUCTURES
69 *****************************************************************************************
70 */
71 /**@brief Reference Time Update Service environment variable. */
72 struct rtus_env_t {
73 rtus_init_t rtus_init; /**< Reference Time Update Service initialization variables. */
74 uint16_t start_hdl; /**< Reference Time Update Service start handle. */
75 rtus_update_state_t update_state; /**< State of time update. */
76 };
77 /*
78 * LOCAL FUNCTION DECLARATION
79 *****************************************************************************************
80 */
81 static sdk_err_t rtus_init(void);
82 static void rtus_read_att_cb(uint8_t conidx, const gatts_read_req_cb_t *p_param);
83 static void rtus_write_att_cb(uint8_t conidx, const gatts_write_req_cb_t *p_param);
84
85 /*
86 * LOCAL VARIABLE DEFINITIONS
87 *****************************************************************************************
88 */
89 static struct rtus_env_t s_rtus_env;
90
91 /**@brief Full RTUS Database Description - Used to add attributes into the database. */
92 static const attm_desc_t rtus_attr_tab[RTUS_IDX_NB] = {
93 // RTUS Service Declaration
94 [RTUS_IDX_SVC] = {BLE_ATT_DECL_PRIMARY_SERVICE, READ_PERM_UNSEC, 0, 0},
95
96 // Time Update Control Point Characteristic Declaration
97 [RTUS_IDX_CTRL_PT_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
98 // Time Update Control Point Characteristic Declaration value
99 [RTUS_IDX_CTRL_PT_VAL] = {
100 BLE_ATT_CHAR_TIME_UPDATE_CNTL_POINT,
101 WRITE_CMD_PERM(AUTH),
102 ATT_VAL_LOC_USER,
103 RTUS_CTRL_PT_VAL_LEN
104 },
105
106 // Time Update State Characteristic Declaration
107 [RTUS_IDX_UPDATE_STATE_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
108 // Time Update State Characteristic Declaration value
109 [RTUS_IDX_UPDATE_STATE_VAL] = {
110 BLE_ATT_CHAR_TIME_UPDATE_STATE,
111 READ_PERM(AUTH),
112 ATT_VAL_LOC_USER,
113 RTUS_UPDATE_STATE_VAL_LEN
114 },
115 };
116
117 /**@brief RTUS Task interface required by profile manager. */
118 static ble_prf_manager_cbs_t rtus_tack_cbs = {
119 (prf_init_func_t) rtus_init,
120 NULL,
121 NULL
122 };
123
124 /**@brief RTUS Task Callbacks. */
125 static gatts_prf_cbs_t rtus_cb_func = {
126 rtus_read_att_cb,
127 rtus_write_att_cb,
128 NULL,
129 NULL
130 };
131
132 /**@brief RTUS Information. */
133 static const prf_server_info_t rtus_prf_info = {
134 .max_connection_nb = RTUS_CONNECTION_MAX,
135 .manager_cbs = &rtus_tack_cbs,
136 .gatts_prf_cbs = &rtus_cb_func
137 };
138
139 /*
140 * LOCAL FUNCTION DEFINITIONS
141 *****************************************************************************************
142 */
143 /**
144 *****************************************************************************************
145 * @brief Initialize Reference Time Update service and create db in att
146 *
147 * @return Error code to know if profile initialization succeed or not.
148 *****************************************************************************************
149 */
rtus_init(void)150 static sdk_err_t rtus_init(void)
151 {
152 // The start hanlde must be set with PRF_INVALID_HANDLE to be allocated automatically by BLE Stack.
153 uint16_t start_hdl = PRF_INVALID_HANDLE;
154 const uint8_t rtus_svc_uuid[] = BLE_ATT_16_TO_16_ARRAY(BLE_ATT_SVC_REF_TIME_UPDATE);
155 sdk_err_t error_code;
156 gatts_create_db_t gatts_db;
157
158 error_code = memset_s(&gatts_db, sizeof(gatts_db), 0, sizeof(gatts_db));
159 if (error_code < 0) {
160 return error_code;
161 }
162
163 gatts_db.shdl = &start_hdl;
164 gatts_db.uuid = rtus_svc_uuid;
165 gatts_db.attr_tab_cfg = (uint8_t *)&(s_rtus_env.rtus_init.char_mask);
166 gatts_db.max_nb_attr = RTUS_IDX_NB;
167 gatts_db.srvc_perm = 0;
168 gatts_db.attr_tab_type = SERVICE_TABLE_TYPE_16;
169 gatts_db.attr_tab.attr_tab_16 = rtus_attr_tab;
170
171 error_code = ble_gatts_srvc_db_create(&gatts_db);
172 if (SDK_SUCCESS == error_code) {
173 s_rtus_env.start_hdl = *gatts_db.shdl;
174 }
175
176 return error_code;
177 }
178
179 /**
180 *****************************************************************************************
181 * @brief Handles reception of the attribute info request message.
182 *
183 * @param[in] conn_idx: Connection index
184 * @param[in] p_param: The parameters of the read request.
185 *****************************************************************************************
186 */
rtus_read_att_cb(uint8_t conn_idx,const gatts_read_req_cb_t * p_param)187 static void rtus_read_att_cb(uint8_t conn_idx, const gatts_read_req_cb_t *p_param)
188 {
189 gatts_read_cfm_t cfm;
190 uint8_t handle = p_param->handle;
191 uint8_t tab_index = prf_find_idx_by_handle(handle,
192 s_rtus_env.start_hdl,
193 RTUS_IDX_NB,
194 (uint8_t *)&s_rtus_env.rtus_init.char_mask);
195 cfm.handle = handle;
196 cfm.status = BLE_SUCCESS;
197
198 switch (tab_index) {
199 case RTUS_IDX_UPDATE_STATE_VAL:
200 cfm.length = RTUS_UPDATE_STATE_VAL_LEN;
201 cfm.value = (uint8_t *)&s_rtus_env.update_state;
202 break;
203
204 default:
205 cfm.length = 0;
206 cfm.status = BLE_ATT_ERR_INVALID_HANDLE;
207 break;
208 }
209
210 ble_gatts_read_cfm(conn_idx, &cfm);
211 }
212 /**
213 *****************************************************************************************
214 * @brief Handles reception of the write request.
215 *
216 * @param[in]: conn_idx: Connection index
217 * @param[in]: p_param: The parameters of the write request.
218 *****************************************************************************************
219 */
rtus_write_att_cb(uint8_t conn_idx,const gatts_write_req_cb_t * p_param)220 static void rtus_write_att_cb(uint8_t conn_idx, const gatts_write_req_cb_t *p_param)
221 {
222 uint16_t handle = p_param->handle;
223 uint16_t tab_index = 0;
224 rtus_ctrl_pt_t ctrl_pt;
225 rtus_evt_t event;
226 gatts_write_cfm_t cfm;
227
228 tab_index = prf_find_idx_by_handle(handle,
229 s_rtus_env.start_hdl,
230 RTUS_IDX_NB,
231 (uint8_t *)&s_rtus_env.rtus_init.char_mask);
232 cfm.handle = handle;
233 cfm.status = BLE_SUCCESS;
234 event.evt_type = RTUS_EVT_INVALID;
235 event.conn_idx = conn_idx;
236
237 switch (tab_index) {
238 case RTUS_IDX_CTRL_PT_VAL:
239 ctrl_pt = (rtus_ctrl_pt_t)p_param->value[0];
240
241 if (RTUS_CTRL_PT_GET_UPDATE == ctrl_pt) {
242 event.evt_type = RTUS_EVT_GET_UPDATE;
243 } else if (RTUS_CTRL_PT_CANCEL_UPDATE == ctrl_pt) {
244 event.evt_type = RTUS_EVT_CANCEL_UPDATE;
245 } else {
246 break;
247 }
248
249 default:
250 cfm.status = BLE_ATT_ERR_INVALID_HANDLE;
251 break;
252 }
253
254 ble_gatts_write_cfm(conn_idx, &cfm);
255
256 if (BLE_ATT_ERR_INVALID_HANDLE != cfm.status && RTUS_EVT_INVALID != event.evt_type
257 && s_rtus_env.rtus_init.evt_handler) {
258 s_rtus_env.rtus_init.evt_handler(&event);
259 }
260 }
261
262 /*
263 * GLOBAL FUNCTION DEFINITIONS
264 *****************************************************************************************
265 */
rtus_current_state_set(rtus_cur_state_t cur_state)266 void rtus_current_state_set(rtus_cur_state_t cur_state)
267 {
268 s_rtus_env.update_state.cur_state = cur_state;
269 }
270
rtus_update_result_set(rtus_update_result_t update_result)271 void rtus_update_result_set(rtus_update_result_t update_result)
272 {
273 s_rtus_env.update_state.update_result = update_result;
274 }
275
rtus_service_init(rtus_init_t * p_rtus_init)276 sdk_err_t rtus_service_init(rtus_init_t *p_rtus_init)
277 {
278 sdk_err_t ret;
279 if (p_rtus_init == NULL) {
280 return SDK_ERR_POINTER_NULL;
281 }
282
283 ret = memcpy_s(&s_rtus_env.rtus_init, sizeof(rtus_init_t), p_rtus_init, sizeof(rtus_init_t));
284 if (ret < 0) {
285 return ret;
286 }
287
288 return ble_server_prf_add(&rtus_prf_info);
289 }
290
291