1 /**
2 ****************************************************************************************
3 *
4 * @file ndcs.c
5 *
6 * @brief Next DST Change 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 "ndcs.h"
43 #include "ble_prf_types.h"
44 #include "ble_prf_utils.h"
45 #include "utility.h"
46
47 #define INDEX_7 7
48 /*
49 * ENUMERATIONS
50 ****************************************************************************************
51 */
52 /**@brief Next DST Change Service Attributes Indexes. */
53 enum {
54 // Next DST Change Service
55 NDCS_IDX_SVC,
56
57 // Time with DST
58 NDCS_IDX_TIME_DST_CHAR,
59 NDCS_IDX_TIME_DST_VAL,
60
61 NDCS_IDX_NB
62 };
63
64 /*
65 * STRUCTURES
66 *****************************************************************************************
67 */
68 /**@brief Next DST Change Service environment variable. */
69 struct ndcs_env_t {
70 uint16_t char_mask; /**< Mask of supported characteristics. */
71 uint16_t start_hdl; /**< Next DST Change Service start handle. */
72 ndcs_time_dst_t time_with_dst; /**< Time with DST value. */
73 };
74 /*
75 * LOCAL FUNCTION DECLARATION
76 *****************************************************************************************
77 */
78 static sdk_err_t ndcs_init(void);
79 static void ndcs_read_att_cb(uint8_t conidx, const gatts_read_req_cb_t *p_param);
80 static void ndcs_time_with_dst_read_handler(gatts_read_cfm_t *p_cfm, uint8_t *p_encode_buffer);
81
82 /*
83 * LOCAL VARIABLE DEFINITIONS
84 *****************************************************************************************
85 */
86 static struct ndcs_env_t s_ndcs_env;
87
88 /**@brief Full NDCS Database Description - Used to add attributes into the database. */
89 static const attm_desc_t ndcs_attr_tab[NDCS_IDX_NB] = {
90 // NDCS Service Declaration
91 [NDCS_IDX_SVC] = {BLE_ATT_DECL_PRIMARY_SERVICE, READ_PERM_UNSEC, 0, 0},
92
93 // Time with DST Characteristic Declaration
94 [NDCS_IDX_TIME_DST_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
95 // Time with DST Characteristic Declaration value
96 [NDCS_IDX_TIME_DST_VAL] = {
97 BLE_ATT_CHAR_TIME_WITH_DST,
98 READ_PERM(AUTH),
99 ATT_VAL_LOC_USER,
100 NDCS_TIME_WITH_DST_VAL_LEN
101 },
102 };
103
104 /**@brief NDCS Task interface required by profile manager. */
105 static ble_prf_manager_cbs_t ndcs_tack_cbs = {
106 (prf_init_func_t) ndcs_init,
107 NULL,
108 NULL
109 };
110
111 /**@brief NDCS Task Callbacks. */
112 static gatts_prf_cbs_t ndcs_cb_func = {
113 ndcs_read_att_cb,
114 NULL,
115 NULL,
116 NULL
117 };
118
119 /**@brief NDCS Information. */
120 static const prf_server_info_t ndcs_prf_info = {
121 .max_connection_nb = NDCS_CONNECTION_MAX,
122 .manager_cbs = &ndcs_tack_cbs,
123 .gatts_prf_cbs = &ndcs_cb_func
124 };
125
126 /*
127 * LOCAL FUNCTION DEFINITIONS
128 *****************************************************************************************
129 */
130 /**
131 *****************************************************************************************
132 * @brief Initialize Next DST Change service and create db in att
133 *
134 * @return Error code to know if profile initialization succeed or not.
135 *****************************************************************************************
136 */
ndcs_init(void)137 static sdk_err_t ndcs_init(void)
138 {
139 // The start hanlde must be set with PRF_INVALID_HANDLE to be allocated automatically by BLE Stack.
140 uint16_t start_hdl = PRF_INVALID_HANDLE;
141 const uint8_t ndcs_svc_uuid[] = BLE_ATT_16_TO_16_ARRAY(BLE_ATT_SVC_NEXT_DST_CHANGE);
142 sdk_err_t error_code;
143 gatts_create_db_t gatts_db;
144
145 error_code = memset_s(&gatts_db, sizeof(gatts_db), 0, sizeof(gatts_db));
146 if (error_code < 0) {
147 return error_code;
148 }
149
150 gatts_db.shdl = &start_hdl;
151 gatts_db.uuid = ndcs_svc_uuid;
152 gatts_db.attr_tab_cfg = (uint8_t *)&(s_ndcs_env.char_mask);
153 gatts_db.max_nb_attr = NDCS_IDX_NB;
154 gatts_db.srvc_perm = 0;
155 gatts_db.attr_tab_type = SERVICE_TABLE_TYPE_16;
156 gatts_db.attr_tab.attr_tab_16 = ndcs_attr_tab;
157
158 error_code = ble_gatts_srvc_db_create(&gatts_db);
159 if (SDK_SUCCESS == error_code) {
160 s_ndcs_env.start_hdl = *gatts_db.shdl;
161 }
162
163 return error_code;
164 }
165
166 /**
167 *****************************************************************************************
168 * @brief Handles reception of the attribute info request message.
169 *
170 * @param[in] conn_idx: Connection index
171 * @param[in] p_param: The parameters of the read request.
172 *****************************************************************************************
173 */
ndcs_read_att_cb(uint8_t conn_idx,const gatts_read_req_cb_t * p_param)174 static void ndcs_read_att_cb(uint8_t conn_idx, const gatts_read_req_cb_t *p_param)
175 {
176 gatts_read_cfm_t cfm;
177 uint8_t handle = p_param->handle;
178 uint8_t tab_index = prf_find_idx_by_handle(handle,
179 s_ndcs_env.start_hdl,
180 NDCS_IDX_NB,
181 (uint8_t *)&s_ndcs_env.char_mask);
182 cfm.handle = handle;
183 cfm.status = BLE_SUCCESS;
184
185 switch (tab_index) {
186 case NDCS_IDX_TIME_DST_VAL: {
187 uint8_t encoded_buffer[NDCS_TIME_WITH_DST_VAL_LEN];
188 ndcs_time_with_dst_read_handler(&cfm, encoded_buffer);
189 break;
190 }
191
192 default:
193 cfm.length = 0;
194 cfm.status = BLE_ATT_ERR_INVALID_HANDLE;
195 break;
196 }
197
198 ble_gatts_read_cfm(conn_idx, &cfm);
199 }
200
201 /**
202 *****************************************************************************************
203 * @brief Handle Time with DSP Time read event.
204 *
205 * @param[out] p_cfm: Pointer to GATT read attribute result description.
206 * @param[out] p_encode_buffer: Pointer to encoded data will be written.
207 *****************************************************************************************
208 */
ndcs_time_with_dst_read_handler(gatts_read_cfm_t * p_cfm,uint8_t * p_encode_buffer)209 static void ndcs_time_with_dst_read_handler(gatts_read_cfm_t *p_cfm, uint8_t *p_encode_buffer)
210 {
211 prf_pack_date_time(p_encode_buffer, &s_ndcs_env.time_with_dst.date_time);
212
213 p_encode_buffer[INDEX_7] = s_ndcs_env.time_with_dst.dst_offset;
214
215 p_cfm->length = NDCS_TIME_WITH_DST_VAL_LEN;
216 p_cfm->value = p_encode_buffer;
217 }
218
219 /*
220 * GLOBAL FUNCTION DEFINITIONS
221 *****************************************************************************************
222 */
ndcs_day_time_update(prf_date_time_t * p_day_time)223 void ndcs_day_time_update(prf_date_time_t *p_day_time)
224 {
225 uint8_t ret;
226
227 ret = memcpy_s(&s_ndcs_env.time_with_dst.date_time, sizeof(prf_date_time_t),
228 p_day_time, sizeof(prf_date_time_t));
229 if (ret < 0) {
230 return ret;
231 }
232 }
233
ndcs_dst_offset_update(ndcs_dst_offset_t dst_offset)234 void ndcs_dst_offset_update(ndcs_dst_offset_t dst_offset)
235 {
236 s_ndcs_env.time_with_dst.dst_offset = dst_offset;
237 }
238
ndcs_service_init(uint8_t char_mask)239 sdk_err_t ndcs_service_init(uint8_t char_mask)
240 {
241 s_ndcs_env.char_mask = char_mask;
242
243 return ble_server_prf_add(&ndcs_prf_info);
244 }
245