1 /*
2  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * SPDX-FileContributor: Blake Felt
7  */
8 
9 #ifndef __ESP_HIDD_API_H__
10 #define __ESP_HIDD_API_H__
11 
12 #include "esp_bt_defs.h"
13 #include "esp_err.h"
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 /// subclass of hid device
20 #define ESP_HID_CLASS_UNKNOWN      (0x00<<2)           /*!< unknown HID device subclass */
21 #define ESP_HID_CLASS_JOS          (0x01<<2)           /*!< joystick */
22 #define ESP_HID_CLASS_GPD          (0x02<<2)           /*!< game pad */
23 #define ESP_HID_CLASS_RMC          (0x03<<2)           /*!< remote control */
24 #define ESP_HID_CLASS_SED          (0x04<<2)           /*!< sensing device */
25 #define ESP_HID_CLASS_DGT          (0x05<<2)           /*!< digitizer tablet */
26 #define ESP_HID_CLASS_CDR          (0x06<<2)           /*!< card reader */
27 #define ESP_HID_CLASS_KBD          (0x10<<2)           /*!< keyboard */
28 #define ESP_HID_CLASS_MIC          (0x20<<2)           /*!< pointing device */
29 #define ESP_HID_CLASS_COM          (0x30<<2)           /*!< combo keyboard/pointing */
30 
31 /**
32  * @brief HIDD handshake result code
33  */
34 typedef enum {
35     ESP_HID_PAR_HANDSHAKE_RSP_SUCCESS = 0,                 /*!< successful */
36     ESP_HID_PAR_HANDSHAKE_RSP_NOT_READY = 1,               /*!< not ready, device is too busy to accept data */
37     ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID = 2,      /*!< invalid report ID */
38     ESP_HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ = 3,     /*!< device does not support the request */
39     ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM = 4,       /*!< parameter value is out of range or inappropriate */
40     ESP_HID_PAR_HANDSHAKE_RSP_ERR_UNKNOWN = 14,            /*!< device could not identify the error condition */
41     ESP_HID_PAR_HANDSHAKE_RSP_ERR_FATAL = 15,              /*!< restart is essential to resume functionality */
42 } esp_hidd_handshake_error_t;
43 
44 /**
45  * @brief HIDD report types
46  */
47 typedef enum {
48     ESP_HIDD_REPORT_TYPE_OTHER = 0,                  /*!< unknown report type */
49     ESP_HIDD_REPORT_TYPE_INPUT,                      /*!< input report */
50     ESP_HIDD_REPORT_TYPE_OUTPUT,                     /*!< output report */
51     ESP_HIDD_REPORT_TYPE_FEATURE,                    /*!< feature report */
52     ESP_HIDD_REPORT_TYPE_INTRDATA,                   /*!< special value for reports to be sent on interrupt channel, INPUT is assumed */
53 } esp_hidd_report_type_t;
54 
55 /**
56  * @brief HIDD connection state
57  */
58 typedef enum {
59     ESP_HIDD_CONN_STATE_CONNECTED,                   /*!< HID connection established */
60     ESP_HIDD_CONN_STATE_CONNECTING,                  /*!< connection to remote Bluetooth device */
61     ESP_HIDD_CONN_STATE_DISCONNECTED,                /*!< connection released */
62     ESP_HIDD_CONN_STATE_DISCONNECTING,               /*!< disconnecting to remote Bluetooth device*/
63     ESP_HIDD_CONN_STATE_UNKNOWN,                     /*!< unknown connection state */
64 } esp_hidd_connection_state_t;
65 
66 /**
67  * @brief HID device protocol modes
68  */
69 typedef enum {
70     ESP_HIDD_REPORT_MODE = 0x00,                     /*!< Report Protocol Mode */
71     ESP_HIDD_BOOT_MODE = 0x01,                       /*!< Boot Protocol Mode */
72     ESP_HIDD_UNSUPPORTED_MODE = 0xff,                /*!< unsupported */
73 } esp_hidd_protocol_mode_t;
74 
75 /**
76  * @brief HID Boot Protocol report IDs
77  */
78 typedef enum {
79     ESP_HIDD_BOOT_REPORT_ID_KEYBOARD = 1,            /*!< report ID of Boot Protocol keyboard report */
80     ESP_HIDD_BOOT_REPORT_ID_MOUSE = 2,               /*!< report ID of Boot Protocol mouse report */
81 } esp_hidd_boot_report_id_t;
82 
83 /**
84  * @brief HID Boot Protocol report size including report ID
85  */
86 enum {
87     ESP_HIDD_BOOT_REPORT_SIZE_KEYBOARD = 9,          /*!< report size of Boot Protocol keyboard report */
88     ESP_HIDD_BOOT_REPORT_SIZE_MOUSE = 4,             /*!< report size of Boot Protocol mouse report */
89 };
90 
91 /**
92  * @brief HID device characteristics for SDP server
93  */
94 typedef struct {
95     const char *name;                                /*!< service name */
96     const char *description;                         /*!< service description */
97     const char *provider;                            /*!< provider name */
98     uint8_t subclass;                                /*!< HID device subclass */
99     uint8_t *desc_list;                              /*!< HID descriptor list */
100     int desc_list_len;                               /*!< size in bytes of HID descriptor list */
101 } esp_hidd_app_param_t;
102 
103 /**
104  * @brief HIDD Quality of Service parameters negotiated over L2CAP
105  */
106 typedef struct {
107     uint8_t service_type;                            /*!< the level of service, 0 indicates no traffic */
108     uint32_t token_rate;                             /*!< token rate in bytes per second, 0 indicates "don't care" */
109     uint32_t token_bucket_size;                      /*!< limit on the burstness of the application data */
110     uint32_t peak_bandwidth;                         /*!< bytes per second, value 0 indicates "don't care" */
111     uint32_t access_latency;                         /*!< maximum acceptable delay in microseconds */
112     uint32_t delay_variation;                        /*!< the difference in microseconds between the max and min delay */
113 } esp_hidd_qos_param_t;
114 
115 /**
116  * @brief HID device callback function events
117  */
118 typedef enum {
119     ESP_HIDD_INIT_EVT = 0,       /*!< When HID device is initialized, the event comes */
120     ESP_HIDD_DEINIT_EVT,         /*!< When HID device is deinitialized, the event comes */
121     ESP_HIDD_REGISTER_APP_EVT,   /*!< When HID device application registered, the event comes */
122     ESP_HIDD_UNREGISTER_APP_EVT, /*!< When HID device application unregistered, the event comes */
123     ESP_HIDD_OPEN_EVT,           /*!< When HID device connection to host opened, the event comes */
124     ESP_HIDD_CLOSE_EVT,          /*!< When HID device connection to host closed, the event comes */
125     ESP_HIDD_SEND_REPORT_EVT,    /*!< When HID device send report to lower layer, the event comes */
126     ESP_HIDD_REPORT_ERR_EVT,     /*!< When HID device report handshanke error to lower layer, the event comes */
127     ESP_HIDD_GET_REPORT_EVT,     /*!< When HID device receives GET_REPORT request from host, the event comes */
128     ESP_HIDD_SET_REPORT_EVT,     /*!< When HID device receives SET_REPORT request from host, the event comes */
129     ESP_HIDD_SET_PROTOCOL_EVT,   /*!< When HID device receives SET_PROTOCOL request from host, the event comes */
130     ESP_HIDD_INTR_DATA_EVT,      /*!< When HID device receives DATA from host on intr, the event comes */
131     ESP_HIDD_VC_UNPLUG_EVT,      /*!< When HID device initiates Virtual Cable Unplug, the event comes */
132     ESP_HIDD_API_ERR_EVT         /*!< When HID device has API error, the event comes */
133 } esp_hidd_cb_event_t;
134 
135 typedef enum {
136     ESP_HIDD_SUCCESS,
137     ESP_HIDD_ERROR,         /*!< general ESP HD error */
138     ESP_HIDD_NO_RES,        /*!< out of system resources */
139     ESP_HIDD_BUSY,          /*!< Temporarily can not handle this request. */
140     ESP_HIDD_NO_DATA,       /*!< No data. */
141     ESP_HIDD_NEED_INIT,     /*!< HIDD module shall init first */
142     ESP_HIDD_NEED_DEINIT,   /*!< HIDD module shall deinit first */
143     ESP_HIDD_NEED_REG,      /*!< HIDD module shall register first */
144     ESP_HIDD_NEED_DEREG,    /*!< HIDD module shall deregister first */
145     ESP_HIDD_NO_CONNECTION, /*!< connection may have been closed */
146 } esp_hidd_status_t;
147 
148 /**
149  * @brief HID device callback parameters union
150  */
151 typedef union {
152     /**
153      * @brief ESP_HIDD_INIT_EVT
154      */
155     struct hidd_init_evt_param {
156         esp_hidd_status_t status; /*!< operation status */
157     } init;                       /*!< HIDD callback param of ESP_HIDD_INIT_EVT */
158 
159     /**
160      * @brief ESP_HIDD_DEINIT_EVT
161      */
162     struct hidd_deinit_evt_param {
163         esp_hidd_status_t status; /*!< operation status */
164     } deinit;                     /*!< HIDD callback param of ESP_HIDD_DEINIT_EVT */
165 
166     /**
167      * @brief ESP_HIDD_REGISTER_APP_EVT
168      */
169     struct hidd_register_app_evt_param {
170         esp_hidd_status_t status; /*!< operation status */
171         bool in_use;              /*!< indicate whether use virtual cable plug host address */
172         esp_bd_addr_t bd_addr;    /*!< host address */
173     } register_app;               /*!< HIDD callback param of ESP_HIDD_REGISTER_APP_EVT */
174 
175     /**
176      * @brief ESP_HIDD_UNREGISTER_APP_EVT
177      */
178     struct hidd_unregister_app_evt_param {
179         esp_hidd_status_t status; /*!< operation status         */
180     } unregister_app;             /*!< HIDD callback param of ESP_HIDD_UNREGISTER_APP_EVT */
181 
182     /**
183      * @brief ESP_HIDD_OPEN_EVT
184      */
185     struct hidd_open_evt_param {
186         esp_hidd_status_t status;                /*!< operation status         */
187         esp_hidd_connection_state_t conn_status; /*!< connection status */
188         esp_bd_addr_t bd_addr;                   /*!< host address */
189     } open;                                      /*!< HIDD callback param of ESP_HIDD_OPEN_EVT */
190 
191     /**
192      * @brief ESP_HIDD_CLOSE_EVT
193      */
194     struct hidd_close_evt_param {
195         esp_hidd_status_t status;                /*!< operation status         */
196         esp_hidd_connection_state_t conn_status; /*!< connection status        */
197     } close;                                     /*!< HIDD callback param of ESP_HIDD_CLOSE_EVT */
198 
199     /**
200      * @brief ESP_HIDD_SEND_REPORT_EVT
201      */
202     struct hidd_send_report_evt_param {
203         esp_hidd_status_t status;           /*!< operation status         */
204         uint8_t reason;                     /*!< lower layer failed reason(ref hiddefs.h)       */
205         esp_hidd_report_type_t report_type; /*!< report type        */
206         uint8_t report_id;                  /*!< report id         */
207     } send_report;                          /*!< HIDD callback param of ESP_HIDD_SEND_REPORT_EVT */
208 
209     /**
210      * @brief ESP_HIDD_REPORT_ERR_EVT
211      */
212     struct hidd_report_err_evt_param {
213         esp_hidd_status_t status; /*!< operation status         */
214         uint8_t reason;           /*!< lower layer failed reason(ref hiddefs.h)           */
215     } report_err;                 /*!< HIDD callback param of ESP_HIDD_REPORT_ERR_EVT */
216 
217     /**
218      * @brief ESP_HIDD_GET_REPORT_EVT
219      */
220     struct hidd_get_report_evt_param {
221         esp_hidd_report_type_t report_type; /*!< report type        */
222         uint8_t report_id;                  /*!< report id         */
223         uint16_t buffer_size;               /*!< buffer size         */
224     } get_report;                           /*!< HIDD callback param of ESP_HIDD_GET_REPORT_EVT */
225 
226     /**
227      * @brief ESP_HIDD_SET_REPORT_EVT
228      */
229     struct hidd_set_report_evt_param {
230         esp_hidd_report_type_t report_type; /*!< report type        */
231         uint8_t report_id;                  /*!< report id         */
232         uint16_t len;                       /*!< set_report data length         */
233         uint8_t *data;                      /*!< set_report data pointer         */
234     } set_report;                           /*!< HIDD callback param of ESP_HIDD_SET_REPORT_EVT */
235 
236     /**
237      * @brief ESP_HIDD_SET_PROTOCOL_EVT
238      */
239     struct hidd_set_protocol_evt_param {
240         esp_hidd_protocol_mode_t protocol_mode; /*!< protocol mode        */
241     } set_protocol;                             /*!< HIDD callback param of ESP_HIDD_SET_PROTOCOL_EVT */
242 
243     /**
244      * @brief ESP_HIDD_INTR_DATA_EVT
245      */
246     struct hidd_intr_data_evt_param {
247         uint8_t report_id; /*!< interrupt channel report id         */
248         uint16_t len;      /*!< interrupt channel report data length         */
249         uint8_t *data;     /*!< interrupt channel report data pointer         */
250     } intr_data;           /*!< HIDD callback param of ESP_HIDD_INTR_DATA_EVT */
251 
252     /**
253      * @brief ESP_HIDD_VC_UNPLUG_EVT
254      */
255     struct hidd_vc_unplug_param {
256         esp_hidd_status_t status;                /*!< operation status         */
257         esp_hidd_connection_state_t conn_status; /*!< connection status        */
258     } vc_unplug;                                 /*!< HIDD callback param of ESP_HIDD_VC_UNPLUG_EVT */
259 } esp_hidd_cb_param_t;
260 
261 /**
262  * @brief           HID device callback function type.
263  * @param           event: Event type
264  * @param           param: Point to callback parameter, currently is union type
265  */
266 typedef void (*esp_hd_cb_t)(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param);
267 
268 /**
269  * @brief           This function is called to init callbacks with HID device module.
270  *
271  * @param[in]       callback: pointer to the init callback function.
272  *
273  * @return
274  *                  - ESP_OK: success
275  *                  - other: failed
276  */
277 esp_err_t esp_bt_hid_device_register_callback(esp_hd_cb_t callback);
278 
279 /**
280  * @brief           Initializes HIDD interface. This function should be called after esp_bluedroid_init() and
281  *                  esp_bluedroid_enable() success, and should be called after esp_bt_hid_device_register_callback.
282  *                  When the operation is complete, the callback function will be called with ESP_HIDD_INIT_EVT.
283  *
284  * @return
285  *                  - ESP_OK: success
286  *                  - other: failed
287  */
288 esp_err_t esp_bt_hid_device_init(void);
289 
290 /**
291  * @brief           De-initializes HIDD interface. This function should be called after esp_bluedroid_init() and
292  *                  esp_bluedroid_enable() success, and should be called after esp_bt_hid_device_init(). When the
293  *                  operation is complete, the callback function will be called with ESP_HIDD_DEINIT_EVT.
294  *
295  * @return
296  *                  - ESP_OK: success
297  *                  - other: failed
298  */
299 esp_err_t esp_bt_hid_device_deinit(void);
300 
301 /**
302  * @brief           Registers HIDD parameters with SDP and sets l2cap Quality of Service. This function should be
303  *                  called after esp_bluedroid_init() and esp_bluedroid_enable() success, and should be called after
304  *                  esp_bt_hid_device_init(). When the operation is complete, the callback function will be called
305  *                  with ESP_HIDD_REGISTER_APP_EVT.
306  *
307  * @param[in]       app_param: HIDD parameters
308  * @param[in]       in_qos: incoming QoS parameters
309  * @param[in]       out_qos: outgoing QoS parameters
310  *
311  * @return
312  *                  - ESP_OK: success
313  *                  - other: failed
314  */
315 esp_err_t esp_bt_hid_device_register_app(esp_hidd_app_param_t *app_param, esp_hidd_qos_param_t *in_qos,
316                                          esp_hidd_qos_param_t *out_qos);
317 
318 /**
319  * @brief           Removes HIDD parameters from SDP and resets l2cap Quality of Service. This function should be
320  *                  called after esp_bluedroid_init() and esp_bluedroid_enable() success, and should be called after
321  *                  esp_bt_hid_device_init(). When the operation is complete, the callback function will be called
322  *                  with ESP_HIDD_UNREGISTER_APP_EVT.
323  *
324  * @return
325  *                  - ESP_OK: success
326  *                  - other: failed
327  */
328 esp_err_t esp_bt_hid_device_unregister_app(void);
329 
330 /**
331  * @brief           Connects to the peer HID Host with virtual cable. This function should be called after
332  *                  esp_bluedroid_init() and esp_bluedroid_enable() success, and should be called after esp_bt_hid_device_init().
333  *                  When the operation is complete, the callback function will be called with ESP_HIDD_OPEN_EVT.
334  *
335  * @param[in]       bd_addr: Remote host bluetooth device address.
336  *
337  * @return
338  *                  - ESP_OK: success
339  *                  - other: failed
340  */
341 esp_err_t esp_bt_hid_device_connect(esp_bd_addr_t bd_addr);
342 
343 /**
344  * @brief           Disconnects from the currently connected HID Host. This function should be called after
345  *                  esp_bluedroid_init() and esp_bluedroid_enable() success, and should be called after esp_bt_hid_device_init().
346  *                  When the operation is complete, the callback function will be called with ESP_HIDD_CLOSE_EVT.
347  *
348  * @note            The disconnect operation will not remove the virtually cabled device. If the connect request from the
349  *                  different HID Host, it will reject the request.
350  *
351  * @return
352  *                  - ESP_OK: success
353  *                  - other: failed
354  */
355 esp_err_t esp_bt_hid_device_disconnect(void);
356 
357 /**
358  * @brief           Sends HID report to the currently connected HID Host. This function should be called after
359  *                  esp_bluedroid_init() and esp_bluedroid_enable() success, and should be called after esp_bt_hid_device_init().
360  *                  When the operation is complete, the callback function will be called with ESP_HIDD_SEND_REPORT_EVT.
361  *
362  * @param[in]       type: type of report
363  * @param[in]       id: report id as defined by descriptor
364  * @param[in]       len: length of report
365  * @param[in]       data: report data
366  *
367  * @return
368  *                  - ESP_OK: success
369  *                  - other: failed
370  */
371 esp_err_t esp_bt_hid_device_send_report(esp_hidd_report_type_t type, uint8_t id, uint16_t len, uint8_t *data);
372 
373 /**
374  * @brief           Sends HID Handshake with error info for invalid set_report to the currently connected HID Host.
375  *                  This function should be called after esp_bluedroid_init() and esp_bluedroid_enable() success, and
376  *                  should be called after esp_bt_hid_device_init(). When the operation is complete, the callback
377  *                  function will be called with ESP_HIDD_REPORT_ERR_EVT.
378  *
379  * @param[in]       error: type of error
380  *
381  * @return
382  *                  - ESP_OK: success
383  *                  - other: failed
384  */
385 esp_err_t esp_bt_hid_device_report_error(esp_hidd_handshake_error_t error);
386 
387 /**
388  * @brief           Remove the virtually cabled device. This function should be called after esp_bluedroid_init()
389  *                  and esp_bluedroid_enable() success, and should be called after esp_bt_hid_device_init(). When the
390  *                  operation is complete, the callback function will be called with ESP_HIDD_VC_UNPLUG_EVT.
391  *
392  * @note            If the connection exists, then HID Device will send a `VIRTUAL_CABLE_UNPLUG` control command to
393  *                  the peer HID Host, and the connection will be destroyed. If the connection does not exist, then HID
394  *                  Device will only unplug on it's single side. Once the unplug operation is success, the related
395  *                  pairing and bonding information will be removed, then the HID Device can accept connection request
396  *                  from the different HID Host,
397  *
398  * @return          - ESP_OK: success
399  *                  - other: failed
400  */
401 esp_err_t esp_bt_hid_device_virtual_cable_unplug(void);
402 
403 #ifdef __cplusplus
404 }
405 #endif
406 
407 #endif
408