1 /******************************************************************************
2 *
3 * Copyright (C) 2016 The Android Open Source Project
4 * Copyright (C) 2009-2012 Broadcom Corporation
5 * Copyright (C) 2019 Blake Felt
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at:
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ******************************************************************************/
20 /************************************************************************************
21 *
22 * Filename: btc_hd.c
23 *
24 * Description: HID Device Profile Bluetooth Interface
25 *
26 *
27 ***********************************************************************************/
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include "bta/bta_api.h"
34 #include "bta/bta_hd_api.h"
35 #include "bta/bta_hh_api.h"
36 #include "bta/utl.h"
37 #include "btc/btc_storage.h"
38 #include "btc/btc_util.h"
39 #include "btc/btc_manage.h"
40 #include "btc_hd.h"
41
42 #include "osi/allocator.h"
43
44 #include "esp_hidd_api.h"
45
46 #if HID_DEV_INCLUDED == TRUE
47 #include "bta_dm_int.h"
48
49 /* HD request events */
50 typedef enum { BTC_HD_DUMMY_REQ_EVT = 0 } btc_hd_req_evt_t;
51
52 /*******************************************************************************
53 * Static variables
54 ******************************************************************************/
55 btc_hd_cb_t btc_hd_cb = {0};
56
57 // static tBTA_HD_APP_INFO app_info;
58 // static tBTA_HD_QOS_INFO in_qos;
59 // static tBTA_HD_QOS_INFO out_qos;
60
61 /******************************************************************************
62 * Constants & Macros
63 *****************************************************************************/
64 #define BTC_HD_APP_NAME_LEN 50
65 #define BTC_HD_APP_DESCRIPTION_LEN 50
66 #define BTC_HD_APP_PROVIDER_LEN 50
67 #define BTC_HD_APP_DESCRIPTOR_LEN 2048
68 #define COD_HID_KEYBOARD 0x0540
69 #define COD_HID_POINTING 0x0580
70 #define COD_HID_COMBO 0x05C0
71 #define COD_HID_MAJOR 0x0500
72
73 #define is_hidd_init() (btc_hd_cb.status > BTC_HD_DISABLED)
74 #define is_hidd_app_register() (btc_hd_cb.app_registered)
75
76 typedef void (bt_hid_copy_cb_t)(btc_msg_t *msg, void *p_dest, void *p_src);
77
btc_hd_cb_to_app(esp_hidd_cb_event_t event,esp_hidd_cb_param_t * param)78 static inline void btc_hd_cb_to_app(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param)
79 {
80 esp_hd_cb_t btc_hd_cb = (esp_hd_cb_t)btc_profile_cb_get(BTC_PID_HD);
81 if (btc_hd_cb) {
82 btc_hd_cb(event, param);
83 }
84 }
85
free_app_info_param(void)86 static void free_app_info_param(void)
87 {
88 utl_freebuf((void **)&btc_hd_cb.app_info.descriptor.dsc_list);
89 utl_freebuf((void **)&btc_hd_cb.app_info.p_provider);
90 utl_freebuf((void **)&btc_hd_cb.app_info.p_description);
91 utl_freebuf((void **)&btc_hd_cb.app_info.p_name);
92 }
93
bte_hd_arg_deep_copy(btc_msg_t * msg,void * p_dst,void * p_src)94 static void bte_hd_arg_deep_copy(btc_msg_t *msg, void *p_dst, void *p_src)
95 {
96 tBTA_HD *p_dst_data = (tBTA_HD *)p_dst;
97 tBTA_HD *p_src_data = (tBTA_HD *)p_src;
98 switch (msg->act)
99 {
100 case BTA_HD_SET_REPORT_EVT: {
101 uint8_t *src_data = p_src_data->set_report.p_data;
102 if (src_data) {
103 p_dst_data->set_report.p_data = osi_malloc(p_src_data->set_report.len);
104 if (p_dst_data->set_report.p_data == NULL) {
105 BTC_TRACE_ERROR("%s malloc set_report data failed!", __func__);
106 break;
107 }
108 memcpy(p_dst_data->set_report.p_data, src_data, p_src_data->set_report.len);
109 }
110 break;
111 }
112 case BTA_HD_INTR_DATA_EVT: {
113 uint8_t *src_data = p_src_data->intr_data.p_data;
114 if (src_data) {
115 p_dst_data->intr_data.p_data = osi_malloc(p_src_data->intr_data.len);
116 if (p_dst_data->intr_data.p_data == NULL) {
117 BTC_TRACE_ERROR("%s malloc intr_data data failed!", __func__);
118 break;
119 }
120 memcpy(p_dst_data->intr_data.p_data, src_data, p_src_data->intr_data.len);
121 }
122 break;
123 }
124 default:
125 break;
126 }
127 }
128
129 /*******************************************************************************
130 *
131 * Function btc_hd_remove_device
132 *
133 * Description Removes plugged device
134 *
135 * Returns void
136 *
137 ******************************************************************************/
btc_hd_remove_device(bt_bdaddr_t bd_addr)138 void btc_hd_remove_device(bt_bdaddr_t bd_addr)
139 {
140 BTA_HdRemoveDevice((uint8_t *)&bd_addr);
141 // btc_storage_remove_hidd(&bd_addr);
142 }
143
144 /*******************************************************************************
145 *
146 * Function bte_hd_evt
147 *
148 * Description Switches context from BTE to BTC for all BT-HD events
149 *
150 * Returns void
151 *
152 ******************************************************************************/
bte_hd_evt(tBTA_HD_EVT event,tBTA_HD * p_data)153 static void bte_hd_evt(tBTA_HD_EVT event, tBTA_HD *p_data)
154 {
155 bt_status_t status;
156 int param_len = 0;
157
158 BTC_TRACE_API("%s event=%d", __func__, event);
159
160 switch (event) {
161 case BTA_HD_ENABLE_EVT:
162 case BTA_HD_DISABLE_EVT:
163 case BTA_HD_UNREGISTER_APP_EVT:
164 param_len = sizeof(tBTA_HD_STATUS);
165 break;
166 case BTA_HD_REGISTER_APP_EVT:
167 param_len = sizeof(tBTA_HD_REG_STATUS);
168 break;
169 case BTA_HD_OPEN_EVT:
170 case BTA_HD_CLOSE_EVT:
171 case BTA_HD_VC_UNPLUG_EVT:
172 param_len = sizeof(tBTA_HD_CONN);
173 break;
174 case BTA_HD_GET_REPORT_EVT:
175 param_len += sizeof(tBTA_HD_GET_REPORT);
176 break;
177 case BTA_HD_SET_REPORT_EVT:
178 param_len = sizeof(tBTA_HD_SET_REPORT);
179 break;
180 case BTA_HD_SET_PROTOCOL_EVT:
181 param_len += sizeof(p_data->set_protocol);
182 break;
183 case BTA_HD_INTR_DATA_EVT:
184 param_len = sizeof(tBTA_HD_INTR_DATA);
185 break;
186 case BTA_HD_SEND_REPORT_EVT:
187 param_len = sizeof(tBTA_HD_API_SEND_REPORT);
188 break;
189 case BTA_HD_REPORT_ERR_EVT:
190 param_len = sizeof(tBTA_HD_API_REPORT_ERR);
191 break;
192 }
193
194 btc_msg_t msg;
195 msg.sig = BTC_SIG_API_CB;
196 msg.pid = BTC_PID_HD;
197 msg.act = event;
198
199 status = btc_transfer_context(&msg, p_data, param_len, bte_hd_arg_deep_copy, btc_hd_cb_arg_deep_free);
200 if (status != BT_STATUS_SUCCESS) {
201 BTC_TRACE_ERROR("context transfer failed");
202 }
203 }
204
205 /*******************************************************************************
206 *
207 * Function btc_hd_init
208 *
209 * Description Initializes BT-HD interface
210 *
211 * Returns void
212 *
213 ******************************************************************************/
btc_hd_init(void)214 static void btc_hd_init(void)
215 {
216 BTC_TRACE_API("%s", __func__);
217 esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
218 do {
219 if (is_hidd_init()) {
220 BTC_TRACE_ERROR("%s HD has been initiated, shall uninit first!", __func__);
221 ret = ESP_HIDD_NEED_DEINIT;
222 break;
223 }
224 memset(&btc_hd_cb, 0, sizeof(btc_hd_cb));
225 /* enable HD */
226 BTA_HdEnable(bte_hd_evt);
227 } while (0);
228
229 if (ret != ESP_HIDD_SUCCESS) {
230 esp_hidd_cb_param_t param;
231 param.init.status = ret;
232 btc_hd_cb_to_app(ESP_HIDD_INIT_EVT, ¶m);
233 }
234 }
235
236 /*******************************************************************************
237 *
238 * Function btc_hd_deinit
239 *
240 * Description de-initializes the hd interface
241 *
242 * Returns void
243 *
244 ******************************************************************************/
245 static void btc_hd_unregister_app(bool need_deinit);
btc_hd_deinit(void)246 static void btc_hd_deinit(void)
247 {
248 BTC_TRACE_API("%s", __func__);
249 esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
250 do {
251 if (!is_hidd_init()) {
252 BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
253 ret = ESP_HIDD_NEED_INIT;
254 break;
255 }
256
257 if (btc_hd_cb.status == BTC_HD_DISABLING) {
258 BTC_TRACE_ERROR("%s is disabling, try later!", __func__);
259 ret = ESP_HIDD_BUSY;
260 break;
261 }
262
263 btc_hd_cb.service_dereg_active = FALSE;
264 // unregister app will also release the connection
265 // and disable after receiving unregister event from lower layer
266 if (is_hidd_app_register()) {
267 btc_hd_unregister_app(true);
268 } else {
269 btc_hd_cb.status = BTC_HD_DISABLING;
270 BTC_TRACE_WARNING("%s disabling hid device service now", __func__);
271 BTA_HdDisable();
272 }
273 } while (0);
274
275 if (ret != ESP_HIDD_SUCCESS) {
276 esp_hidd_cb_param_t param;
277 param.deinit.status = ret;
278 btc_hd_cb_to_app(ESP_HIDD_DEINIT_EVT, ¶m);
279 }
280 }
281
282 /*******************************************************************************
283 *
284 * Function btc_hd_register_app
285 *
286 * Description Registers HID Device application
287 *
288 * Returns void
289 *
290 ******************************************************************************/
btc_hd_register_app(esp_hidd_app_param_t * p_app_param,esp_hidd_qos_param_t * p_in_qos,esp_hidd_qos_param_t * p_out_qos)291 static void btc_hd_register_app(esp_hidd_app_param_t *p_app_param, esp_hidd_qos_param_t *p_in_qos,
292 esp_hidd_qos_param_t *p_out_qos)
293 {
294 BTC_TRACE_API("%s", __func__);
295 esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
296 do {
297 if (!is_hidd_init()) {
298 BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
299 ret = ESP_HIDD_NEED_INIT;
300 break;
301 } else if (btc_hd_cb.status == BTC_HD_DISABLING) {
302 BTC_TRACE_ERROR("%s: deinit is in progress!", __func__);
303 ret = ESP_HIDD_BUSY;
304 break;
305 }
306
307 if (is_hidd_app_register()) {
308 BTC_TRACE_ERROR("%s: application already registered, shall deregister first!", __func__);
309 ret = ESP_HIDD_NEED_DEREG;
310 break;
311 }
312
313 if ((btc_hd_cb.app_info.p_name = (char *)osi_malloc(BTC_HD_APP_NAME_LEN)) == NULL ||
314 (btc_hd_cb.app_info.p_description = (char *)osi_malloc(BTC_HD_APP_DESCRIPTION_LEN)) == NULL ||
315 (btc_hd_cb.app_info.p_provider = (char *)osi_malloc(BTC_HD_APP_PROVIDER_LEN)) == NULL ||
316 (btc_hd_cb.app_info.descriptor.dsc_list = (uint8_t *)osi_malloc(p_app_param->desc_list_len)) == NULL) {
317 BTC_TRACE_ERROR(
318 "%s malloc app_info failed! p_name:%p, p_description:%p, p_provider:%p, descriptor.dsc_list:%p",
319 __func__, btc_hd_cb.app_info.p_name, btc_hd_cb.app_info.p_description, btc_hd_cb.app_info.p_provider,
320 btc_hd_cb.app_info.descriptor.dsc_list);
321 ret = ESP_HIDD_NO_RES;
322 break;
323 }
324 memcpy(btc_hd_cb.app_info.p_name, p_app_param->name, BTC_HD_APP_NAME_LEN);
325 memcpy(btc_hd_cb.app_info.p_description, p_app_param->description, BTC_HD_APP_DESCRIPTION_LEN);
326 memcpy(btc_hd_cb.app_info.p_provider, p_app_param->provider, BTC_HD_APP_PROVIDER_LEN);
327 memcpy(btc_hd_cb.app_info.descriptor.dsc_list, p_app_param->desc_list, p_app_param->desc_list_len);
328 btc_hd_cb.app_info.subclass = p_app_param->subclass;
329 btc_hd_cb.app_info.descriptor.dl_len = p_app_param->desc_list_len;
330
331 btc_hd_cb.in_qos.service_type = p_in_qos->service_type;
332 btc_hd_cb.in_qos.token_rate = p_in_qos->token_rate;
333 btc_hd_cb.in_qos.token_bucket_size = p_in_qos->token_bucket_size;
334 btc_hd_cb.in_qos.peak_bandwidth = p_in_qos->peak_bandwidth;
335 btc_hd_cb.in_qos.access_latency = p_in_qos->access_latency;
336 btc_hd_cb.in_qos.delay_variation = p_in_qos->delay_variation;
337 btc_hd_cb.out_qos.service_type = p_out_qos->service_type;
338 btc_hd_cb.out_qos.token_rate = p_out_qos->token_rate;
339 btc_hd_cb.out_qos.token_bucket_size = p_out_qos->token_bucket_size;
340 btc_hd_cb.out_qos.peak_bandwidth = p_out_qos->peak_bandwidth;
341 btc_hd_cb.out_qos.access_latency = p_out_qos->access_latency;
342 btc_hd_cb.out_qos.delay_variation = p_out_qos->delay_variation;
343
344 BTA_HdRegisterApp(&btc_hd_cb.app_info, &btc_hd_cb.in_qos, &btc_hd_cb.out_qos);
345 } while(0);
346
347 if (ret != ESP_HIDD_SUCCESS) {
348 esp_hidd_cb_param_t param;
349 param.register_app.status = ret;
350 param.register_app.in_use = false;
351 memset(param.register_app.bd_addr, 0, BD_ADDR_LEN);
352 btc_hd_cb_to_app(ESP_HIDD_REGISTER_APP_EVT, ¶m);
353 }
354 free_app_info_param();
355 }
356
357 /*******************************************************************************
358 *
359 * Function btc_hd_unregister_app
360 *
361 * Description Unregisters HID Device application
362 *
363 * Returns void
364 *
365 ******************************************************************************/
btc_hd_unregister_app(bool need_deinit)366 static void btc_hd_unregister_app(bool need_deinit)
367 {
368 BTC_TRACE_API("%s", __func__);
369 esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
370 do {
371 if (!is_hidd_init()) {
372 BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
373 ret = ESP_HIDD_NEED_INIT;
374 break;
375 } else if (btc_hd_cb.status == BTC_HD_DISABLING) {
376 BTC_TRACE_ERROR("%s: deinit is in progress!", __func__);
377 ret = ESP_HIDD_BUSY;
378 break;
379 }
380
381 if (!is_hidd_app_register()) {
382 BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__);
383 ret = ESP_HIDD_NEED_REG;
384 break;
385 }
386
387 if (btc_hd_cb.service_dereg_active) {
388 BTC_TRACE_ERROR("%s: BT-HD deregistering in progress", __func__);
389 ret = ESP_HIDD_BUSY;
390 break;
391 }
392 btc_hd_cb.service_dereg_active = TRUE;
393
394 if (need_deinit) {
395 btc_hd_cb.status = BTC_HD_DISABLING;
396 }
397
398 BTA_HdUnregisterApp();
399 } while(0);
400
401 if (ret != ESP_HIDD_SUCCESS) {
402 esp_hidd_cb_param_t param = {0};
403 param.unregister_app.status = ret;
404 btc_hd_cb_to_app(ESP_HIDD_UNREGISTER_APP_EVT, ¶m);
405 }
406 }
407
408 /*******************************************************************************
409 *
410 * Function btc_hd_connect
411 *
412 * Description Connects to host
413 *
414 * Returns void
415 *
416 ******************************************************************************/
btc_hd_connect(BD_ADDR bd_addr)417 static void btc_hd_connect(BD_ADDR bd_addr)
418 {
419 BTC_TRACE_API("%s", __func__);
420 esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
421
422 do {
423 switch (btc_hd_cb.status) {
424 case BTC_HD_DISABLED:
425 BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
426 ret = ESP_HIDD_NEED_INIT;
427 break;
428 case BTC_HD_DISABLING:
429 BTC_TRACE_ERROR("%s: deinit is in progress!", __func__);
430 ret = ESP_HIDD_BUSY;
431 break;
432 case BTC_HD_CONNECTING:
433 case BTC_HD_DISCONNECTING:
434 BTC_TRACE_ERROR("%s: busy now, status:%d, try later!", __func__, btc_hd_cb.status);
435 ret = ESP_HIDD_BUSY;
436 break;
437 case BTC_HD_CONNECTED:
438 BTC_TRACE_ERROR("%s: already connect to the other HID host!", __func__);
439 ret = ESP_HIDD_NO_RES;
440 break;
441 default:
442 break;
443 }
444
445 if (ret != ESP_HIDD_SUCCESS) {
446 break;
447 }
448
449 if (!is_hidd_app_register()) {
450 BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__);
451 ret = ESP_HIDD_NEED_REG;
452 break;
453 }
454
455 BTA_HdConnect(bd_addr);
456 btc_hd_cb.status = BTC_HD_CONNECTING;
457 } while (0);
458
459 if (ret != ESP_HIDD_SUCCESS) {
460 esp_hidd_cb_param_t param = {0};
461 param.open.status = ret;
462 param.open.conn_status = ESP_HIDD_CONN_STATE_DISCONNECTED;
463 memcpy(param.open.bd_addr, bd_addr, BD_ADDR_LEN);
464 btc_hd_cb_to_app(ESP_HIDD_OPEN_EVT, ¶m);
465 }
466 }
467
468 /*******************************************************************************
469 *
470 * Function btc_hd_disconnect
471 *
472 * Description Disconnects from host
473 *
474 * Returns void
475 *
476 ******************************************************************************/
btc_hd_disconnect(void)477 static void btc_hd_disconnect(void)
478 {
479 BTC_TRACE_API("%s", __func__);
480 esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
481
482 do {
483 switch (btc_hd_cb.status) {
484 case BTC_HD_DISABLED:
485 BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
486 ret = ESP_HIDD_NEED_INIT;
487 break;
488 case BTC_HD_DISABLING:
489 BTC_TRACE_ERROR("%s: deinit is in progress!", __func__);
490 ret = ESP_HIDD_BUSY;
491 break;
492 case BTC_HD_CONNECTING:
493 case BTC_HD_DISCONNECTING:
494 BTC_TRACE_ERROR("%s: busy now, status:%d, try later!", __func__, btc_hd_cb.status);
495 ret = ESP_HIDD_BUSY;
496 break;
497 case BTC_HD_ENABLED:
498 case BTC_HD_DISCONNECTED:
499 BTC_TRACE_ERROR("%s: no connection!", __func__);
500 ret = ESP_HIDD_NO_CONNECTION;
501 break;
502 default:
503 break;
504 }
505
506 if (ret != ESP_HIDD_SUCCESS) {
507 break;
508 }
509
510 if (!is_hidd_app_register()) {
511 BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__);
512 ret = ESP_HIDD_NEED_REG;
513 break;
514 }
515
516 BTA_HdDisconnect();
517 btc_hd_cb.status = BTC_HD_DISCONNECTING;
518 } while (0);
519
520 if (ret != ESP_HIDD_SUCCESS) {
521 esp_hidd_cb_param_t param = {0};
522 param.close.status = ret;
523 param.close.conn_status = ESP_HIDD_CONN_STATE_DISCONNECTED;
524 btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, ¶m);
525 }
526 }
527
528 /*******************************************************************************
529 *
530 * Function btc_hd_send_report
531 *
532 * Description Sends Reports to hid host
533 *
534 * Returns void
535 *
536 ******************************************************************************/
btc_hd_send_report(esp_hidd_report_type_t type,uint8_t id,uint16_t len,uint8_t * p_data)537 static void btc_hd_send_report(esp_hidd_report_type_t type, uint8_t id, uint16_t len, uint8_t *p_data)
538 {
539 BTC_TRACE_API("%s: type=%d id=%d len=%d", __func__, type, id, len);
540 tBTA_HD_REPORT report = {0};
541 esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
542
543 do {
544 switch (btc_hd_cb.status) {
545 case BTC_HD_DISABLED:
546 BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
547 ret = ESP_HIDD_NEED_INIT;
548 break;
549 case BTC_HD_DISABLING:
550 BTC_TRACE_ERROR("%s: deinit is in progress!", __func__);
551 ret = ESP_HIDD_BUSY;
552 break;
553 case BTC_HD_CONNECTING:
554 case BTC_HD_DISCONNECTING:
555 BTC_TRACE_ERROR("%s: busy now, status:%d, try later!", __func__, btc_hd_cb.status);
556 ret = ESP_HIDD_BUSY;
557 break;
558 case BTC_HD_ENABLED:
559 case BTC_HD_DISCONNECTED:
560 if (type == ESP_HIDD_REPORT_TYPE_INTRDATA) {
561 BTC_TRACE_WARNING("%s: no connection, try to reconnect!", __func__);
562 btc_hd_cb.status = BTC_HD_CONNECTING;
563 } else {
564 BTC_TRACE_ERROR("%s: no connection!", __func__);
565 ret = ESP_HIDD_NO_CONNECTION;
566 }
567 break;
568 default:
569 break;
570 }
571
572 if (ret != ESP_HIDD_SUCCESS) {
573 break;
574 }
575
576 if (!is_hidd_app_register()) {
577 BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__);
578 ret = ESP_HIDD_NEED_REG;
579 break;
580 }
581
582 if (type == ESP_HIDD_REPORT_TYPE_INTRDATA) {
583 report.type = ESP_HIDD_REPORT_TYPE_INPUT;
584 report.use_intr = TRUE;
585 } else {
586 report.type = (type & 0x03);
587 report.use_intr = FALSE;
588 }
589
590 report.id = id;
591 report.len = len;
592 report.p_data = p_data;
593
594 BTA_HdSendReport(&report);
595 } while (0);
596
597 if (ret != ESP_HIDD_SUCCESS) {
598 esp_hidd_cb_param_t param = {0};
599 param.send_report.status = ret;
600 param.send_report.reason = 0;
601 param.send_report.report_type = report.type;
602 param.send_report.report_id = report.id;
603 btc_hd_cb_to_app(ESP_HIDD_SEND_REPORT_EVT, ¶m);
604 }
605 }
606
607 /*******************************************************************************
608 *
609 * Function btc_hd_report_error
610 *
611 * Description Sends HANDSHAKE with error info for invalid SET_REPORT
612 *
613 * Returns void
614 *
615 ******************************************************************************/
btc_hd_report_error(uint8_t error)616 static void btc_hd_report_error(uint8_t error)
617 {
618 BTC_TRACE_API("%s", __func__);
619 esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
620 do {
621 if (!is_hidd_init()) {
622 BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
623 ret = ESP_HIDD_NEED_INIT;
624 break;
625 }
626
627 if (!is_hidd_app_register()) {
628 BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__);
629 ret = ESP_HIDD_NEED_REG;
630 break;
631 }
632
633 if (btc_hd_cb.status != BTC_HD_CONNECTED) {
634 BTC_TRACE_ERROR("%s: no connection!", __func__);
635 ret = ESP_HIDD_NO_CONNECTION;
636 break;
637 }
638
639 BTA_HdReportError(error);
640 } while (0);
641
642 if (ret != ESP_HIDD_SUCCESS) {
643 esp_hidd_cb_param_t param = {0};
644 param.report_err.status = ret;
645 param.report_err.reason = 0;
646 btc_hd_cb_to_app(ESP_HIDD_REPORT_ERR_EVT, ¶m);
647 }
648 }
649
650 /*******************************************************************************
651 *
652 * Function btc_hd_virtual_cable_unplug
653 *
654 * Description Sends Virtual Cable Unplug to host
655 *
656 * Returns void
657 *
658 ******************************************************************************/
btc_hd_virtual_cable_unplug(void)659 static void btc_hd_virtual_cable_unplug(void)
660 {
661 BTC_TRACE_API("%s", __func__);
662 esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
663
664 do {
665 switch (btc_hd_cb.status) {
666 case BTC_HD_DISABLED:
667 BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
668 ret = ESP_HIDD_NEED_INIT;
669 break;
670 case BTC_HD_DISABLING:
671 BTC_TRACE_ERROR("%s: deinit is in progress!", __func__);
672 ret = ESP_HIDD_BUSY;
673 break;
674 case BTC_HD_CONNECTING:
675 case BTC_HD_DISCONNECTING:
676 BTC_TRACE_ERROR("%s: busy now, status:%d, try later!", __func__, btc_hd_cb.status);
677 ret = ESP_HIDD_BUSY;
678 break;
679 default:
680 break;
681 }
682
683 if (ret != ESP_HIDD_SUCCESS) {
684 break;
685 }
686
687 if (!is_hidd_app_register()) {
688 BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__);
689 ret = ESP_HIDD_NEED_REG;
690 break;
691 }
692
693 BTA_HdVirtualCableUnplug();
694
695 if (btc_hd_cb.status == BTC_HD_CONNECTED) {
696 btc_hd_cb.status = BTC_HD_DISCONNECTING;
697 }
698 } while (0);
699
700 if (ret != ESP_HIDD_SUCCESS) {
701 esp_hidd_cb_param_t param = {0};
702 param.vc_unplug.status = ret;
703 param.vc_unplug.conn_status = ESP_HIDD_CONN_STATE_DISCONNECTED;
704 btc_hd_cb_to_app(ESP_HIDD_VC_UNPLUG_EVT, ¶m);
705 }
706 }
707
btc_hd_call_arg_deep_free(btc_msg_t * msg)708 static void btc_hd_call_arg_deep_free(btc_msg_t *msg)
709 {
710 btc_hidd_args_t *arg = (btc_hidd_args_t *)msg->arg;
711
712 switch (msg->act) {
713 case BTC_HD_SEND_REPORT_EVT:
714 utl_freebuf((void **)&arg->send_report.data);
715 break;
716 default:
717 break;
718 }
719 }
720
btc_hd_call_handler(btc_msg_t * msg)721 void btc_hd_call_handler(btc_msg_t *msg)
722 {
723 btc_hidd_args_t *arg = (btc_hidd_args_t *)(msg->arg);
724 switch (msg->act) {
725 case BTC_HD_INIT_EVT:
726 btc_hd_init();
727 break;
728 case BTC_HD_DEINIT_EVT:
729 btc_hd_deinit();
730 break;
731 case BTC_HD_REGISTER_APP_EVT:
732 btc_hd_register_app(arg->register_app.app_param, arg->register_app.in_qos, arg->register_app.out_qos);
733 break;
734 case BTC_HD_UNREGISTER_APP_EVT:
735 btc_hd_unregister_app(false);
736 break;
737 case BTC_HD_CONNECT_EVT:
738 btc_hd_connect(arg->connect.bd_addr);
739 break;
740 case BTC_HD_DISCONNECT_EVT:
741 btc_hd_disconnect();
742 break;
743 case BTC_HD_SEND_REPORT_EVT:
744 btc_hd_send_report(arg->send_report.type, arg->send_report.id, arg->send_report.len, arg->send_report.data);
745 break;
746 case BTC_HD_REPORT_ERROR_EVT:
747 btc_hd_report_error(arg->error);
748 break;
749 case BTC_HD_UNPLUG_EVT:
750 btc_hd_virtual_cable_unplug();
751 break;
752 default:
753 BTC_TRACE_WARNING("unknown hidd action %i", msg->act);
754 break;
755 }
756 btc_hd_call_arg_deep_free(msg);
757 }
758
btc_hd_cb_arg_deep_free(btc_msg_t * msg)759 void btc_hd_cb_arg_deep_free(btc_msg_t *msg)
760 {
761 tBTA_HD *arg = (tBTA_HD *)msg->arg;
762
763 switch (msg->act) {
764 case BTA_HD_SET_REPORT_EVT:
765 utl_freebuf((void **)&arg->set_report.p_data);
766 break;
767 case BTA_HD_INTR_DATA_EVT:
768 utl_freebuf((void **)&arg->intr_data.p_data);
769 break;
770 default:
771 break;
772 }
773 }
774
btc_hd_cb_handler(btc_msg_t * msg)775 void btc_hd_cb_handler(btc_msg_t *msg)
776 {
777 uint16_t event = msg->act;
778 tBTA_HD *p_data = (tBTA_HD *)msg->arg;
779 esp_hidd_cb_param_t param = {0};
780 BTC_TRACE_API("%s: event=%s", __func__, dump_hd_event(event));
781
782 switch (event) {
783 case BTA_HD_ENABLE_EVT:
784 BTC_TRACE_DEBUG("%s: status=%d", __func__, p_data->status);
785 if (p_data->status == BTA_HD_OK) {
786 btc_storage_load_hidd();
787 btc_hd_cb.status = BTC_HD_ENABLED;
788 } else {
789 btc_hd_cb.status = BTC_HD_DISABLED;
790 BTC_TRACE_WARNING("Failed to enable BT-HD, status=%d", p_data->status);
791 }
792 param.init.status = p_data->status;
793 btc_hd_cb_to_app(ESP_HIDD_INIT_EVT, ¶m);
794 break;
795 case BTA_HD_DISABLE_EVT:
796 BTC_TRACE_DEBUG("%s: status=%d", __func__, p_data->status);
797 if (p_data->status == BTA_HD_OK){
798 btc_hd_cb.status = BTC_HD_DISABLED;
799 if (btc_hd_cb.service_dereg_active) {
800 btc_hd_cb.service_dereg_active = FALSE;
801 }
802 free_app_info_param();
803 memset(&btc_hd_cb, 0, sizeof(btc_hd_cb));
804 } else {
805 BTC_TRACE_WARNING("Failed to disable BT-HD, status=%d", p_data->status);
806 }
807 param.deinit.status = p_data->status;
808 btc_hd_cb_to_app(ESP_HIDD_DEINIT_EVT, ¶m);
809 break;
810 case BTA_HD_REGISTER_APP_EVT:
811 if (p_data->reg_status.status == BTA_HD_OK) {
812 btc_hd_cb.app_registered = TRUE;
813 }
814 param.register_app.status = p_data->reg_status.status;
815 param.register_app.in_use = p_data->reg_status.in_use;
816 if (!p_data->reg_status.in_use) {
817 memset(param.register_app.bd_addr, 0, BD_ADDR_LEN);
818 } else {
819 memcpy(param.register_app.bd_addr, p_data->reg_status.bda, BD_ADDR_LEN);
820 }
821 btc_hd_cb_to_app(ESP_HIDD_REGISTER_APP_EVT, ¶m);
822 break;
823 case BTA_HD_UNREGISTER_APP_EVT:
824 btc_hd_cb.app_registered = FALSE;
825 param.unregister_app.status = p_data->status;
826 btc_hd_cb_to_app(ESP_HIDD_UNREGISTER_APP_EVT, ¶m);
827 if (btc_hd_cb.status == BTC_HD_DISABLING) {
828 BTC_TRACE_WARNING("disabling hid device service now");
829 BTA_HdDisable();
830 }
831 break;
832 case BTA_HD_OPEN_EVT: {
833 bt_bdaddr_t *addr = (bt_bdaddr_t *)&p_data->conn.bda;
834 BTC_TRACE_EVENT("BTA_HD_OPEN_EVT, address (%02x:%02x:%02x:%02x:%02x:%02x)", addr->address[0], addr->address[1],
835 addr->address[2], addr->address[3], addr->address[4], addr->address[5]);
836 if (p_data->conn.status == BTA_HD_OK && p_data->conn.conn_status == BTA_HD_CONN_STATE_CONNECTED) {
837 // /* Check if the connection is from hid host and not hid device */
838 // if (check_cod_hid(addr)) {
839 // /* Incoming connection from hid device, reject it */
840 // BTC_TRACE_WARNING("remote device is not hid host, disconnecting");
841 // btc_hd_cb.forced_disc = TRUE;
842 // BTA_HdDisconnect();
843 // break;
844 // }
845 // btc_storage_set_hidd((bt_bdaddr_t *)&p_data->conn.bda);
846 btc_hd_cb.status = BTC_HD_CONNECTED;
847 } else if (p_data->conn.conn_status == BTA_HD_CONN_STATE_DISCONNECTED) {
848 btc_hd_cb.status = BTC_HD_DISCONNECTED;
849 }
850 param.open.status = p_data->conn.status;
851 param.open.conn_status = p_data->conn.conn_status;
852 memcpy(param.open.bd_addr, p_data->conn.bda, BD_ADDR_LEN);
853 btc_hd_cb_to_app(ESP_HIDD_OPEN_EVT, ¶m);
854 break;
855 }
856 case BTA_HD_CLOSE_EVT:
857 if (p_data->conn.conn_status == BTA_HD_CONN_STATE_DISCONNECTED) {
858 btc_hd_cb.status = BTC_HD_DISCONNECTED;
859 if (btc_hd_cb.forced_disc) {
860 bt_bdaddr_t *addr = (bt_bdaddr_t *)&p_data->conn.bda;
861 BTC_TRACE_WARNING("remote device was forcefully disconnected");
862 btc_hd_remove_device(*addr);
863 btc_hd_cb.forced_disc = FALSE;
864 break;
865 }
866 }
867
868 param.close.status = p_data->conn.status;
869 param.close.conn_status = p_data->conn.conn_status;
870 btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, ¶m);
871 break;
872 case BTA_HD_GET_REPORT_EVT:
873 param.get_report.report_type = p_data->get_report.report_type;
874 param.get_report.report_id = p_data->get_report.report_id;
875 param.get_report.buffer_size = p_data->get_report.buffer_size;
876 btc_hd_cb_to_app(ESP_HIDD_GET_REPORT_EVT, ¶m);
877 break;
878 case BTA_HD_SET_REPORT_EVT:
879 param.set_report.report_type = p_data->set_report.report_type;
880 param.set_report.report_id = p_data->set_report.report_id;
881 param.set_report.len = p_data->set_report.len;
882 param.set_report.data = p_data->set_report.p_data;
883 btc_hd_cb_to_app(ESP_HIDD_SET_REPORT_EVT, ¶m);
884 break;
885 case BTA_HD_SET_PROTOCOL_EVT:
886 switch (p_data->set_protocol) {
887 case HID_PAR_PROTOCOL_BOOT_MODE:
888 param.set_protocol.protocol_mode = ESP_HIDD_BOOT_MODE;
889 break;
890 case HID_PAR_PROTOCOL_REPORT:
891 param.set_protocol.protocol_mode = ESP_HIDD_REPORT_MODE;
892 break;
893 default:
894 param.set_protocol.protocol_mode = ESP_HIDD_UNSUPPORTED_MODE;
895 break;
896 }
897 btc_hd_cb_to_app(ESP_HIDD_SET_PROTOCOL_EVT, ¶m);
898 break;
899 case BTA_HD_INTR_DATA_EVT:
900 param.intr_data.report_id = p_data->intr_data.report_id;
901 param.intr_data.len = p_data->intr_data.len;
902 param.intr_data.data = p_data->intr_data.p_data;
903 btc_hd_cb_to_app(ESP_HIDD_INTR_DATA_EVT, ¶m);
904 break;
905 case BTA_HD_VC_UNPLUG_EVT: {
906 bt_bdaddr_t *bd_addr = (bt_bdaddr_t *)&p_data->conn.bda;
907 if (bta_dm_check_if_only_hd_connected(p_data->conn.bda)) {
908 BTC_TRACE_DEBUG("%s: Removing bonding as only HID profile connected", __func__);
909 BTA_DmRemoveDevice((uint8_t *)&p_data->conn.bda, BT_TRANSPORT_BR_EDR);
910 } else {
911 BTC_TRACE_DEBUG("%s: Only removing HID data as some other profiles connected", __func__);
912 btc_hd_remove_device(*bd_addr);
913 }
914
915 if (btc_hd_cb.status == BTC_HD_DISCONNECTING || btc_hd_cb.status == BTC_HD_CONNECTING ||
916 btc_hd_cb.status == BTC_HD_CONNECTED) {
917 btc_hd_cb.status = BTC_HD_DISCONNECTED;
918 param.close.status = p_data->conn.status;
919 param.close.conn_status = p_data->conn.conn_status;
920 btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, ¶m);
921 }
922
923 param.vc_unplug.status = p_data->conn.status;
924 param.vc_unplug.conn_status = p_data->conn.conn_status;
925 btc_hd_cb_to_app(ESP_HIDD_VC_UNPLUG_EVT, ¶m);
926 break;
927 }
928 case BTA_HD_SEND_REPORT_EVT:
929 param.send_report.status = p_data->send_report.status;
930 param.send_report.reason = p_data->send_report.reason;
931 param.send_report.report_type = p_data->send_report.report_type;
932 param.send_report.report_id = p_data->send_report.report_id;
933 btc_hd_cb_to_app(ESP_HIDD_SEND_REPORT_EVT, ¶m);
934 break;
935 case BTA_HD_REPORT_ERR_EVT:
936 param.report_err.status = p_data->report_err.status;
937 param.report_err.reason = p_data->report_err.reason;
938 btc_hd_cb_to_app(ESP_HIDD_REPORT_ERR_EVT, ¶m);
939 break;
940 default:
941 BTC_TRACE_WARNING("%s: unknown event (%d)", __func__, event);
942 break;
943 }
944 btc_hd_cb_arg_deep_free(msg);
945 }
946
btc_hd_arg_deep_copy(btc_msg_t * msg,void * p_dest,void * p_src)947 void btc_hd_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
948 {
949 btc_hidd_args_t *dst = (btc_hidd_args_t *)p_dest;
950 btc_hidd_args_t *src = (btc_hidd_args_t *)p_src;
951
952 switch (msg->act) {
953 case BTC_HD_SEND_REPORT_EVT:
954 dst->send_report.data = (uint8_t *)osi_malloc(src->send_report.len);
955 if (dst->send_report.data) {
956 memcpy(dst->send_report.data, src->send_report.data, src->send_report.len);
957 } else {
958 BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act);
959 }
960 break;
961 default:
962 break;
963 }
964 }
965
966 #endif // HID_DEV_INCLUDED==TRUE
967