1 /**
2 *****************************************************************************************
3 *
4 * @file ias.c
5 *
6 * @brief Immediate Alert Server 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 "ias.h"
43 #include "ble_prf_types.h"
44 #include "ble_prf_utils.h"
45 #include "utility.h"
46
47 /*
48 * DEFINITIONS
49 *****************************************************************************************
50 */
51 #define INITIAL_ALERT_LEVEL IAS_ALERT_NONE
52
53 /*
54 * ENUMERATIONS
55 *****************************************************************************************
56 */
57 /**@brief IAS Attributes database index list. */
58 enum ias_attr_idx_t {
59 IAS_IDX_SVC,
60
61 IAS_IDX_ALERT_LVL_CHAR,
62 IAS_IDX_ALERT_LVL_VAL,
63
64 IAS_IDX_NB,
65 };
66
67 /**@brief Immediate Alert Service environment variable. */
68 struct ias_env_t {
69 ias_init_t ias_init; /**< Immediate Alert Service initialization variables. */
70 uint16_t start_hdl; /**< Immediate Alert Service start handle. */
71 };
72 /*
73 * LOCAL VARIABLE DEFINITIONS
74 *****************************************************************************************
75 */
76 static struct ias_env_t s_ias_env; /**< Immediate Alert Service instance. */
77 static uint8_t s_char_mask = 0x07; /**< Features added into ATT database.
78 * bit0 - Immediate Alert Service Declaration
79 * bit1 - Alert Level Characteristic Declaration
80 * bit2 - Alert Level Characteristic Value
81 */
82
83 /**@brief IAS Database Description - Used to add attributes into the database. */
84 static const attm_desc_t ias_attr_tab[IAS_IDX_NB] = {
85 // Immediate Alert Service Declaration
86 [IAS_IDX_SVC] = {BLE_ATT_DECL_PRIMARY_SERVICE, READ_PERM_UNSEC, 0, 0},
87 // Alert Level Characteristic Declaration
88 [IAS_IDX_ALERT_LVL_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
89 // Alert Level Characteristic Value
90 [IAS_IDX_ALERT_LVL_VAL] = {BLE_ATT_CHAR_ALERT_LEVEL, WRITE_CMD_PERM_UNSEC, 0, sizeof(uint8_t)},
91 };
92
93 /*
94 * LOCAL FUNCTION DECLARATIONS
95 *****************************************************************************************
96 */
97 static sdk_err_t ias_init(void);
98 static void ias_write_att_cb(uint8_t conn_idx, const gatts_write_req_cb_t *p_param);
99
100 /**@brief IAS interface required by profile manager. */
101 static ble_prf_manager_cbs_t ias_mgr_cbs = {
102 (prf_init_func_t)ias_init,
103 NULL,
104 NULL
105 };
106
107 /**@brief IAS GATT server Callbacks. */
108 static gatts_prf_cbs_t ias_gatts_cbs = {
109 NULL,
110 ias_write_att_cb,
111 NULL,
112 NULL
113 };
114
115 /**@brief IAS Information. */
116 static const prf_server_info_t ias_prf_info = {
117 /* There shall be only one connection with a device. */
118 .max_connection_nb = 1,
119 .manager_cbs = &ias_mgr_cbs,
120 .gatts_prf_cbs = &ias_gatts_cbs
121 };
122
123 /*
124 * LOCAL FUNCTION DEFINITIONS
125 *****************************************************************************************
126 */
127 /**
128 *****************************************************************************************
129 * @brief Initialize Immediate Alert Service and create DB in ATT.
130 *
131 * @return Error code to know if service initialization succeed or not.
132 *****************************************************************************************
133 */
ias_init(void)134 static sdk_err_t ias_init(void)
135 {
136 const uint8_t ias_svc_uuid[] = BLE_ATT_16_TO_16_ARRAY(BLE_ATT_SVC_IMMEDIATE_ALERT);
137 gatts_create_db_t gatts_db;
138 sdk_err_t ret;
139 uint16_t start_hdl = PRF_INVALID_HANDLE; /* The start hanlde is an in/out
140 * parameter of ble_gatts_srvc_db_create().
141 * It must be set with PRF_INVALID_HANDLE
142 * to be allocated automatically by BLE Stack. */
143
144 ret = memset_s(&gatts_db, sizeof(gatts_db), 0, sizeof(gatts_db));
145 if (ret < 0) {
146 return ret;
147 }
148
149 gatts_db.shdl = &start_hdl;
150 gatts_db.uuid = (uint8_t *)ias_svc_uuid;
151 gatts_db.attr_tab_cfg = &s_char_mask;
152 gatts_db.max_nb_attr = IAS_IDX_NB;
153 gatts_db.srvc_perm = 0;
154 gatts_db.attr_tab_type = SERVICE_TABLE_TYPE_16;
155 gatts_db.attr_tab.attr_tab_16 = ias_attr_tab;
156
157 sdk_err_t error_code = ble_gatts_srvc_db_create(&gatts_db);
158 if (SDK_SUCCESS == error_code) {
159 s_ias_env.start_hdl = *gatts_db.shdl;
160
161 uint16_t handle = prf_find_handle_by_idx(IAS_IDX_ALERT_LVL_VAL, s_ias_env.start_hdl, &s_char_mask);
162 uint8_t initial_alert_level = INITIAL_ALERT_LEVEL;
163
164 ble_gatts_value_set(handle, sizeof(uint8_t), 0, &initial_alert_level);
165 }
166
167 return error_code;
168 }
169
170 /**
171 *****************************************************************************************
172 * @brief Handles reception of the attribute info request message.
173 *
174 * @param[in] conn_idx: Connection index
175 * @param[in] p_param: The parameters of the read request.
176 *****************************************************************************************
177 */
ias_write_att_cb(uint8_t conn_idx,const gatts_write_req_cb_t * p_param)178 static void ias_write_att_cb(uint8_t conn_idx, const gatts_write_req_cb_t *p_param)
179 {
180 uint16_t handle = prf_find_handle_by_idx(IAS_IDX_ALERT_LVL_VAL, s_ias_env.start_hdl, &s_char_mask);
181 gatts_write_cfm_t cfm;
182
183 cfm.handle = p_param->handle;
184
185 if (handle != p_param->handle) {
186 cfm.status = BLE_ATT_ERR_INVALID_HANDLE;
187 } else {
188 if (p_param->length != sizeof(uint8_t)) {
189 cfm.status = SDK_ERR_INVALID_ATT_VAL_LEN;
190 } else {
191 // Send write response
192 uint8_t value = p_param->value[0];
193
194 cfm.status = (uint8_t)ble_gatts_value_set(cfm.handle, sizeof(uint8_t), 0, &value);
195 if (cfm.status != BLE_SUCCESS) {
196 return;
197 }
198 /* Alert level updated by the peer, notify app the event. */
199 if (s_ias_env.ias_init.evt_handler) {
200 ias_evt_t evt;
201
202 evt.evt_type = IAS_EVT_ALERT_LEVEL_UPDATED;
203 evt.alert_level = value;
204 s_ias_env.ias_init.evt_handler(&evt);
205 }
206 }
207 }
208
209 ble_gatts_write_cfm(conn_idx, &cfm);
210 }
211
212 /*
213 * GLOBAL FUNCTION DEFINITIONS
214 *****************************************************************************************
215 */
ias_alert_level_get(uint8_t * p_alert_level)216 sdk_err_t ias_alert_level_get(uint8_t *p_alert_level)
217 {
218 uint16_t handle = prf_find_handle_by_idx(IAS_IDX_ALERT_LVL_VAL, s_ias_env.start_hdl, (uint8_t *)&s_char_mask);
219 uint16_t length = sizeof(uint8_t);
220
221 return ble_gatts_value_get(handle, &length, p_alert_level);
222 }
223
ias_service_init(ias_init_t * p_ias_init)224 sdk_err_t ias_service_init(ias_init_t *p_ias_init)
225 {
226 if (p_ias_init == NULL) {
227 return SDK_ERR_POINTER_NULL;
228 }
229
230 s_ias_env.ias_init.evt_handler = p_ias_init->evt_handler;
231
232 return ble_server_prf_add(&ias_prf_info);
233 }
234