1 // Copyright 2019 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20 
21 #include <protocomm.h>
22 
23 /**
24  * @brief   Property description data structure, which is to be populated
25  *          and passed to the `esp_local_ctrl_add_property()` function
26  *
27  * Once a property is added, its structure is available for read-only access
28  * inside `get_prop_values()` and `set_prop_values()` handlers.
29  */
30 typedef struct esp_local_ctrl_prop {
31     /**
32      * Unique name of property
33      */
34     char *name;
35 
36     /**
37      * Type of property. This may be set to application defined enums
38      */
39     uint32_t type;
40 
41     /**
42      * Size of the property value, which:
43      * - if zero, the property can have values of variable size
44      * - if non-zero, the property can have values of fixed size only,
45      *   therefore, checks are performed internally by esp_local_ctrl
46      *   when setting the value of such a property
47      */
48     size_t size;
49 
50     /**
51      * Flags set for this property. This could be a bit field.
52      * A flag may indicate property behavior, e.g. read-only / constant
53      */
54     uint32_t flags;
55 
56     /**
57      * Pointer to some context data relevant for this property. This will
58      * be available for use inside the `get_prop_values` and `set_prop_values`
59      * handlers as a part of this property structure. When set, this is valid
60      * throughout the lifetime of a property, till either the property is
61      * removed or the esp_local_ctrl service is stopped.
62      */
63     void *ctx;
64 
65     /**
66      * Function used by esp_local_ctrl to internally free the property
67      * context when `esp_local_ctrl_remove_property()` or
68      * `esp_local_ctrl_stop()` is called.
69      */
70     void (*ctx_free_fn)(void *ctx);
71 } esp_local_ctrl_prop_t;
72 
73 /**
74  * @brief   Property value data structure. This gets passed to the
75  *          `get_prop_values()` and `set_prop_values()` handlers for
76  *          the purpose of retrieving or setting the present value
77  *          of a property.
78  */
79 typedef struct esp_local_ctrl_prop_val {
80     /**
81      * Pointer to memory holding property value
82      */
83     void *data;
84 
85     /**
86      * Size of property value
87      */
88     size_t size;
89 
90     /**
91      * This may be set by the application in `get_prop_values()` handler
92      * to tell `esp_local_ctrl` to call this function on the data pointer
93      * above, for freeing its resources after sending the `get_prop_values`
94      * response.
95      */
96     void (*free_fn)(void *data);
97 } esp_local_ctrl_prop_val_t;
98 
99 /**
100  * @brief   Handlers for receiving and responding to local
101  *          control commands for getting and setting properties.
102  */
103 typedef struct esp_local_ctrl_handlers {
104     /**
105      * @brief Handler function to be implemented for retrieving current
106      *        values of properties
107      *
108      * @note  If any of the properties have fixed sizes, the size field of
109      * corresponding element in `prop_values` need to be set
110      *
111      * @param[in]  props_count  Total elements in the props array
112      * @param[in]  props        Array of properties, the current values for which
113      *                          have been requested by the client
114      * @param[out] prop_values  Array of empty property values, the elements of
115      *                          which need to be populated with the current values
116      *                          of those properties specified by props argument
117      * @param[in]  usr_ctx      This provides value of the `usr_ctx` field of
118      *                          `esp_local_ctrl_handlers_t` structure
119      *
120      * @return Returning different error codes will convey the corresponding
121      *         protocol level errors to the client :
122      *         - ESP_OK : Success
123      *         - ESP_ERR_INVALID_ARG   : InvalidArgument
124      *         - ESP_ERR_INVALID_STATE : InvalidProto
125      *         - All other error codes : InternalError
126      */
127     esp_err_t (*get_prop_values)(size_t props_count,
128                                  const esp_local_ctrl_prop_t props[],
129                                  esp_local_ctrl_prop_val_t prop_values[],
130                                  void *usr_ctx);
131 
132     /**
133      * @brief Handler function to be implemented for changing values of properties
134      *
135      * @note  If any of the properties have variable sizes, the size field
136      * of the corresponding element in `prop_values` must be checked
137      * explicitly before making any assumptions on the size.
138      *
139      * @param[in]  props_count  Total elements in the props array
140      * @param[in]  props        Array of properties, the values for which the
141      *                          client requests to change
142      * @param[in]  prop_values  Array of property values, the elements of which
143      *                          need to be used for updating those properties
144      *                          specified by props argument
145      * @param[in]  usr_ctx      This provides value of the `usr_ctx` field of
146      *                          `esp_local_ctrl_handlers_t` structure
147      *
148      * @return Returning different error codes will convey the corresponding
149      *         protocol level errors to the client :
150      *         - ESP_OK : Success
151      *         - ESP_ERR_INVALID_ARG   : InvalidArgument
152      *         - ESP_ERR_INVALID_STATE : InvalidProto
153      *         - All other error codes : InternalError
154      */
155     esp_err_t (*set_prop_values)(size_t props_count,
156                                  const esp_local_ctrl_prop_t props[],
157                                  const esp_local_ctrl_prop_val_t prop_values[],
158                                  void *usr_ctx);
159 
160     /**
161      * Context pointer to be passed to above handler functions upon invocation.
162      * This is different from the property level context, as this is valid
163      * throughout the lifetime of the `esp_local_ctrl` service, and freed only
164      * when the service is stopped.
165      */
166     void *usr_ctx;
167 
168     /**
169      * Pointer to function which will be internally invoked on `usr_ctx` for
170      * freeing the context resources when `esp_local_ctrl_stop()` is called.
171      */
172     void (*usr_ctx_free_fn)(void *usr_ctx);
173 } esp_local_ctrl_handlers_t;
174 
175 /**
176  * @brief   Transport mode (BLE / HTTPD) over which the service will be provided
177  *
178  * This is forward declaration of a private structure, implemented internally
179  * by `esp_local_ctrl`.
180  */
181 typedef struct esp_local_ctrl_transport esp_local_ctrl_transport_t;
182 
183 /**
184  * @brief   Function for obtaining BLE transport mode
185  */
186 const esp_local_ctrl_transport_t *esp_local_ctrl_get_transport_ble(void);
187 
188 /**
189  * @brief   Function for obtaining HTTPD transport mode
190  */
191 const esp_local_ctrl_transport_t *esp_local_ctrl_get_transport_httpd(void);
192 
193 #define ESP_LOCAL_CTRL_TRANSPORT_BLE   esp_local_ctrl_get_transport_ble()
194 #define ESP_LOCAL_CTRL_TRANSPORT_HTTPD esp_local_ctrl_get_transport_httpd()
195 
196 /**
197  * @brief   Configuration for transport mode BLE
198  *
199  * This is a forward declaration for `protocomm_ble_config_t`.
200  * To use this, application must set CONFIG_BT_BLUEDROID_ENABLED
201  * and include `protocomm_ble.h`.
202  */
203 typedef struct protocomm_ble_config esp_local_ctrl_transport_config_ble_t;
204 
205 /**
206  * @brief   Configuration for transport mode HTTPD
207  *
208  * This is a forward declaration for `httpd_ssl_config_t`.
209  * To use this, application must set CONFIG_ESP_HTTPS_SERVER_ENABLE
210  * and include `esp_https_server.h`
211  */
212 typedef struct httpd_ssl_config esp_local_ctrl_transport_config_httpd_t;
213 
214 /**
215  * @brief   Transport mode (BLE / HTTPD) configuration
216  */
217 typedef union {
218     /**
219      * This is same as `protocomm_ble_config_t`. See `protocomm_ble.h` for
220      * available configuration parameters.
221      */
222     esp_local_ctrl_transport_config_ble_t *ble;
223 
224     /**
225      * This is same as `httpd_ssl_config_t`. See `esp_https_server.h` for
226      * available configuration parameters.
227      */
228     esp_local_ctrl_transport_config_httpd_t *httpd;
229 } esp_local_ctrl_transport_config_t;
230 
231 /**
232  * @brief   Security types for esp_local_control
233  */
234 typedef enum esp_local_ctrl_proto_sec {
235     PROTOCOM_SEC0 = 0,
236     PROTOCOM_SEC1,
237     PROTOCOM_SEC_CUSTOM,
238 } esp_local_ctrl_proto_sec_t;
239 
240 /**
241  * Protocom security configs
242  */
243 typedef struct esp_local_ctrl_proto_sec_cfg {
244      /**
245      * This sets protocom security version, sec0/sec1 or custom
246      * If custom, user must provide handle via `proto_sec_custom_handle` below
247      */
248     esp_local_ctrl_proto_sec_t version;
249 
250     /**
251      * Custom security handle if security is set custom via `proto_sec` above
252      * This handle must follow `protocomm_security_t` signature
253      */
254     void *custom_handle;
255 
256     /**
257      * Proof of possession to be used for local control. Could be NULL.
258      */
259     void *pop;
260 } esp_local_ctrl_proto_sec_cfg_t;
261 
262 /**
263  * @brief   Configuration structure to pass to `esp_local_ctrl_start()`
264  */
265 typedef struct esp_local_ctrl_config {
266     /**
267      * Transport layer over which service will be provided
268      */
269     const esp_local_ctrl_transport_t *transport;
270 
271     /**
272      * Transport layer over which service will be provided
273      */
274     esp_local_ctrl_transport_config_t transport_config;
275 
276     /**
277      * Security version and POP
278      */
279     esp_local_ctrl_proto_sec_cfg_t proto_sec;
280 
281     /**
282      * Register handlers for responding to get/set requests on properties
283      */
284     esp_local_ctrl_handlers_t handlers;
285 
286     /**
287      * This limits the number of properties that are available at a time
288      */
289     size_t max_properties;
290 } esp_local_ctrl_config_t;
291 
292 /**
293  * @brief   Start local control service
294  *
295  * @param[in] config    Pointer to configuration structure
296  *
297  * @return
298  *  - ESP_OK      : Success
299  *  - ESP_FAIL    : Failure
300  */
301 esp_err_t esp_local_ctrl_start(const esp_local_ctrl_config_t *config);
302 
303 /**
304  * @brief   Stop local control service
305  */
306 esp_err_t esp_local_ctrl_stop(void);
307 
308 /**
309  * @brief   Add a new property
310  *
311  * This adds a new property and allocates internal resources for it.
312  * The total number of properties that could be added is limited by
313  * configuration option `max_properties`
314  *
315  * @param[in] prop    Property description structure
316  *
317  * @return
318  *  - ESP_OK      : Success
319  *  - ESP_FAIL    : Failure
320  */
321 esp_err_t esp_local_ctrl_add_property(const esp_local_ctrl_prop_t *prop);
322 
323 /**
324  * @brief   Remove a property
325  *
326  * This finds a property by name, and releases the internal resources
327  * which are associated with it.
328  *
329  * @param[in] name    Name of the property to remove
330  *
331  * @return
332  *  - ESP_OK      : Success
333  *  - ESP_ERR_NOT_FOUND : Failure
334  */
335 esp_err_t esp_local_ctrl_remove_property(const char *name);
336 
337 /**
338  * @brief   Get property description structure by name
339  *
340  * This API may be used to get a property's context structure
341  * `esp_local_ctrl_prop_t` when its name is known
342  *
343  * @param[in] name    Name of the property to find
344  *
345  * @return
346  *  - Pointer to property
347  *  - NULL if not found
348  */
349 const esp_local_ctrl_prop_t *esp_local_ctrl_get_property(const char *name);
350 
351 /**
352  * @brief   Register protocomm handler for a custom endpoint
353  *
354  * This API can be called by the application to register a protocomm handler
355  * for an endpoint after the local control service has started.
356  *
357  * @note In case of BLE transport the names and uuids of all custom
358  * endpoints must be provided beforehand as a part of the `protocomm_ble_config_t`
359  * structure set in `esp_local_ctrl_config_t`, and passed to `esp_local_ctrl_start()`.
360  *
361  * @param[in] ep_name   Name of the endpoint
362  * @param[in] handler   Endpoint handler function
363  * @param[in] user_ctx  User data
364  *
365  * @return
366  *  - ESP_OK      : Success
367  *  - ESP_FAIL    : Failure
368  */
369 esp_err_t esp_local_ctrl_set_handler(const char *ep_name,
370                                      protocomm_req_handler_t handler,
371                                      void *user_ctx);
372 
373 #ifdef __cplusplus
374 }
375 #endif
376