• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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