• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  *****************************************************************************************
3  *
4  * @file dis.h
5  *
6  * @brief Device Information 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 "dis.h"
43 #include "ble_prf_types.h"
44 #include "ble_prf_utils.h"
45 #include "utility.h"
46 #define INDEX_0 0
47 #define INDEX_1 1
48 #define INDEX_2 2
49 #define INDEX_3 3
50 #define INDEX_4 4
51 #define INDEX_5 5
52 #define INDEX_6 6
53 /*
54  * ENUMERATIONS
55  *****************************************************************************************
56  */
57 /**@brief Device Information Service Attributes database index list. */
58 enum dis_attr_idx_t {
59     DIS_IDX_SVC,
60 
61     DIS_IDX_SYSTEM_ID_CHAR,
62     DIS_IDX_SYSTEM_ID_VAL,
63 
64     DIS_IDX_MODEL_NB_STR_CHAR,
65     DIS_IDX_MODEL_NB_STR_VAL,
66 
67     DIS_IDX_SERIAL_NB_STR_CHAR,
68     DIS_IDX_SERIAL_NB_STR_VAL,
69 
70     DIS_IDX_HARD_REV_STR_CHAR,
71     DIS_IDX_HARD_REV_STR_VAL,
72 
73     DIS_IDX_FIRM_REV_STR_CHAR,
74     DIS_IDX_FIRM_REV_STR_VAL,
75 
76     DIS_IDX_SW_REV_STR_CHAR,
77     DIS_IDX_SW_REV_STR_VAL,
78 
79     DIS_IDX_MANUFACTURER_NAME_CHAR,
80     DIS_IDX_MANUFACTURER_NAME_VAL,
81 
82     DIS_IDX_IEEE_CHAR,
83     DIS_IDX_IEEE_VAL,
84 
85     DIS_IDX_PNP_ID_CHAR,
86     DIS_IDX_PNP_ID_VAL,
87 
88     DIS_IDX_NB,
89 };
90 
91 /*
92  * STRUCTURES
93  *****************************************************************************************
94  */
95 /**@brief Device Information Service environment variable. */
96 struct dis_env_t {
97     dis_init_t dis_init;       /**< Device Information Service initialization variables. */
98     uint16_t   start_hdl;      /**< Device Information Service start handle. */
99 };
100 
101 /*
102  * LOCAL FUNCTION DECLARATION
103  *****************************************************************************************
104  */
105 static sdk_err_t   dis_init(void);
106 static void        dis_read_att_cb(uint8_t conn_idx, const gatts_read_req_cb_t *p_param);
107 
108 /*
109  * LOCAL VARIABLE DEFINITIONS
110  *****************************************************************************************
111  */
112 static struct dis_env_t s_dis_env;
113 
114 /**@brief Full DIS Database Description which is used to add attributes into the ATT database. */
115 static const attm_desc_t dis_attr_tab[DIS_IDX_NB] = {
116     // Device Information Service Declaration
117     [DIS_IDX_SVC] = {BLE_ATT_DECL_PRIMARY_SERVICE, READ_PERM_UNSEC, 0, 0},
118 
119     // System ID Characteristic Declaration
120     [DIS_IDX_SYSTEM_ID_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
121     // System ID Characteristic Value
122     [DIS_IDX_SYSTEM_ID_VAL]  = {BLE_ATT_CHAR_SYS_ID, READ_PERM_UNSEC, ATT_VAL_LOC_USER, DIS_SYS_ID_LEN},
123 
124     // Model Number String Characteristic Declaration
125     [DIS_IDX_MODEL_NB_STR_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
126     // Model Number String Characteristic Value
127     [DIS_IDX_MODEL_NB_STR_VAL]  = {BLE_ATT_CHAR_MODEL_NB, READ_PERM_UNSEC, ATT_VAL_LOC_USER, DIS_VAL_MAX_LEN},
128 
129     // Serial Number String Characteristic Declaration
130     [DIS_IDX_SERIAL_NB_STR_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
131     // Serial Number String Characteristic Value
132     [DIS_IDX_SERIAL_NB_STR_VAL]  = {BLE_ATT_CHAR_SERIAL_NB, READ_PERM_UNSEC, ATT_VAL_LOC_USER, DIS_VAL_MAX_LEN},
133 
134     // Firmware Revision String Characteristic Declaration
135     [DIS_IDX_FIRM_REV_STR_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
136     // Firmware Revision String Characteristic Value
137     [DIS_IDX_FIRM_REV_STR_VAL]  = {BLE_ATT_CHAR_FW_REV, READ_PERM_UNSEC, ATT_VAL_LOC_USER, DIS_VAL_MAX_LEN},
138 
139     // Hardware Revision String Characteristic Declaration
140     [DIS_IDX_HARD_REV_STR_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
141     // Hardware Revision String Characteristic Value
142     [DIS_IDX_HARD_REV_STR_VAL]  = {BLE_ATT_CHAR_HW_REV, READ_PERM_UNSEC, ATT_VAL_LOC_USER, DIS_VAL_MAX_LEN},
143 
144     // Software Revision String Characteristic Declaration
145     [DIS_IDX_SW_REV_STR_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
146     // Software Revision String Characteristic Value
147     [DIS_IDX_SW_REV_STR_VAL]  = {BLE_ATT_CHAR_SW_REV, READ_PERM_UNSEC, ATT_VAL_LOC_USER, DIS_VAL_MAX_LEN},
148 
149     // Manufacturer Name Characteristic Declaration
150     [DIS_IDX_MANUFACTURER_NAME_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
151     // Manufacturer Name Characteristic Value
152     [DIS_IDX_MANUFACTURER_NAME_VAL]  = {BLE_ATT_CHAR_MANUF_NAME, READ_PERM_UNSEC, ATT_VAL_LOC_USER, DIS_VAL_MAX_LEN},
153 
154     // IEEE 11073-20601 Regulatory Certification Data List Characteristic Declaration
155     [DIS_IDX_IEEE_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
156     // IEEE 11073-20601 Regulatory Certification Data List Characteristic Value
157     [DIS_IDX_IEEE_VAL]  = {BLE_ATT_CHAR_IEEE_CERTIF, READ_PERM_UNSEC, ATT_VAL_LOC_USER, DIS_SYS_ID_LEN},
158 
159     // PnP ID Characteristic Declaration
160     [DIS_IDX_PNP_ID_CHAR] = {BLE_ATT_DECL_CHARACTERISTIC, READ_PERM_UNSEC, 0, 0},
161     // PnP ID Characteristic Value
162     [DIS_IDX_PNP_ID_VAL]  = {BLE_ATT_CHAR_PNP_ID, READ_PERM_UNSEC, ATT_VAL_LOC_USER, DIS_PNP_ID_LEN},
163 };
164 
165 /**@brief Device Information Service interface required by profile manager. */
166 static ble_prf_manager_cbs_t dis_mgr_cbs = {
167     (prf_init_func_t)dis_init,
168     NULL,
169     NULL
170 };
171 
172 /**@brief Device Information GATT Server Callbacks. */
173 static gatts_prf_cbs_t dis_gatts_cbs = {
174     dis_read_att_cb,
175     NULL,
176     NULL,
177     NULL
178 };
179 
180 /**@brief Device Information Service Information. */
181 static const prf_server_info_t dis_prf_info = {
182     .max_connection_nb = DIS_CONNECTION_MAX,
183     .manager_cbs       = &dis_mgr_cbs,
184     .gatts_prf_cbs     = &dis_gatts_cbs
185 };
186 
187 /*
188  * LOCAL FUNCTION DEFINITIONS
189  *****************************************************************************************
190  */
191 /**
192  *****************************************************************************************
193  * @brief Initialize device information service and create DB in ATT.
194  *
195  * @return Error code to know if service initialization succeed or not.
196  *****************************************************************************************
197  */
dis_init(void)198 static sdk_err_t dis_init(void)
199 {
200     // The start hanlde must be set with PRF_INVALID_HANDLE to be allocated automatically by BLE Stack.
201     uint16_t          start_hdl      = PRF_INVALID_HANDLE;
202     const uint8_t     dis_svc_uuid[] = BLE_ATT_16_TO_16_ARRAY(BLE_ATT_SVC_DEVICE_INFO);
203     sdk_err_t         error_code     = SDK_SUCCESS;
204     gatts_create_db_t gatts_db;
205 
206     error_code = memset_s(&gatts_db, sizeof(gatts_db), 0, sizeof(gatts_db));
207     if (error_code < 0) {
208         return error_code;
209     }
210 
211     gatts_db.shdl                 = &start_hdl;
212     gatts_db.uuid                 = dis_svc_uuid;
213     gatts_db.attr_tab_cfg         = (uint8_t *)&s_dis_env.dis_init.char_mask;
214     gatts_db.max_nb_attr          = DIS_IDX_NB;
215     gatts_db.srvc_perm            = 0;
216     gatts_db.attr_tab_type        = SERVICE_TABLE_TYPE_16;
217     gatts_db.attr_tab.attr_tab_16 = dis_attr_tab;
218 
219     error_code = ble_gatts_srvc_db_create(&gatts_db);
220     if (SDK_SUCCESS == error_code) {
221         s_dis_env.start_hdl = *gatts_db.shdl;
222     }
223 
224     return error_code;
225 }
226 
227 /**
228  *****************************************************************************************
229  * @brief Handles reception of the attribute info request message.
230  *
231  * @param[in] conn_idx: Connection index
232  * @param[in] p_param:  Pointer to the parameters of the read request.
233  *****************************************************************************************
234  */
dis_read_att_cb(uint8_t conn_idx,const gatts_read_req_cb_t * p_param)235 static void dis_read_att_cb(uint8_t conn_idx, const gatts_read_req_cb_t *p_param)
236 {
237     gatts_read_cfm_t cfm;
238     uint16_t         handle    = p_param->handle;
239     uint8_t          tab_index = prf_find_idx_by_handle(handle,
240                                  s_dis_env.start_hdl,
241                                  DIS_IDX_NB,
242                                  (uint8_t *)&s_dis_env.dis_init.char_mask);
243     cfm.handle = handle;
244     cfm.status = BLE_SUCCESS;
245 
246     uint8_t buf[DIS_PNP_ID_LEN];
247 
248     switch (tab_index) {
249         case DIS_IDX_SYSTEM_ID_VAL:
250             cfm.length = DIS_SYS_ID_LEN;
251             cfm.value  = (uint8_t *)s_dis_env.dis_init.p_sys_id;
252             break;
253 
254         case DIS_IDX_MODEL_NB_STR_VAL:
255             cfm.length = s_dis_env.dis_init.model_num_str.length;
256             cfm.value  = (uint8_t *)s_dis_env.dis_init.model_num_str.p_str;
257             break;
258 
259         case DIS_IDX_SERIAL_NB_STR_VAL:
260             cfm.length = s_dis_env.dis_init.serial_num_str.length;
261             cfm.value  = (uint8_t *)s_dis_env.dis_init.serial_num_str.p_str;
262             break;
263 
264         case DIS_IDX_FIRM_REV_STR_VAL:
265             cfm.length = s_dis_env.dis_init.fw_rev_str.length;
266             cfm.value  = (uint8_t *)s_dis_env.dis_init.fw_rev_str.p_str;
267             break;
268 
269         case DIS_IDX_HARD_REV_STR_VAL:
270             cfm.length = s_dis_env.dis_init.hw_rev_str.length;
271             cfm.value  = (uint8_t *)s_dis_env.dis_init.hw_rev_str.p_str;
272             break;
273 
274         case DIS_IDX_SW_REV_STR_VAL:
275             cfm.length = s_dis_env.dis_init.sw_rev_str.length;
276             cfm.value  = (uint8_t *)s_dis_env.dis_init.sw_rev_str.p_str;
277             break;
278 
279         case DIS_IDX_MANUFACTURER_NAME_VAL:
280             cfm.length = s_dis_env.dis_init.manufact_name_str.length;
281             cfm.value  = (uint8_t *)s_dis_env.dis_init.manufact_name_str.p_str;
282             break;
283 
284         case DIS_IDX_IEEE_VAL:
285             cfm.length = s_dis_env.dis_init.reg_cert_data_list.list_len;
286             cfm.value  = (uint8_t *)s_dis_env.dis_init.reg_cert_data_list.p_list;
287             break;
288 
289         case DIS_IDX_PNP_ID_VAL: {
290             buf[INDEX_0] = s_dis_env.dis_init.p_pnp_id->vendor_id_source;
291             buf[INDEX_1] = LO_U16(s_dis_env.dis_init.p_pnp_id->vendor_id);
292             buf[INDEX_2] = HI_U16(s_dis_env.dis_init.p_pnp_id->vendor_id);
293             buf[INDEX_3] = LO_U16(s_dis_env.dis_init.p_pnp_id->product_id);
294             buf[INDEX_4] = HI_U16(s_dis_env.dis_init.p_pnp_id->product_id);
295             buf[INDEX_5] = LO_U16(s_dis_env.dis_init.p_pnp_id->product_version);
296             buf[INDEX_6] = HI_U16(s_dis_env.dis_init.p_pnp_id->product_version);
297             cfm.length = DIS_PNP_ID_LEN;
298             cfm.value  = buf;
299         }
300             break;
301 
302         default:
303             cfm.length = 0;
304             cfm.status = BLE_ATT_ERR_INVALID_HANDLE;
305             break;
306     }
307 
308     ble_gatts_read_cfm(conn_idx, &cfm);
309 }
310 
311 /*
312  * GLOBAL FUNCTION DEFINITIONS
313  *****************************************************************************************
314  */
dis_service_init(dis_init_t * p_dis_init)315 sdk_err_t dis_service_init(dis_init_t *p_dis_init)
316 {
317     sdk_err_t ret;
318     if (p_dis_init == NULL) {
319         return SDK_ERR_POINTER_NULL;
320     }
321     ret = memcpy_s(&s_dis_env.dis_init, sizeof(dis_init_t), p_dis_init, sizeof(dis_init_t));
322     if (ret < 0) {
323         return ret;
324     }
325 
326     return ble_server_prf_add(&dis_prf_info);
327 }
328 
329