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