1 /******************************************************************************
2  *
3  *  Copyright (C) 2016 The Android Open Source Project
4  *  Copyright (C) 2005-2012 Broadcom Corporation
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at:
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  ******************************************************************************/
19 /******************************************************************************
20  *
21  *  This file contains the HID device action functions.
22  *
23  ******************************************************************************/
24 #include "common/bt_target.h"
25 
26 #if defined(BTA_HD_INCLUDED) && (BTA_HD_INCLUDED == TRUE)
27 
28 #include "bta/bta_sys.h"
29 #include "bta_hd_int.h"
30 #include "osi/allocator.h"
31 #include "osi/osi.h"
32 #include "stack/btm_api.h"
33 #include <string.h>
34 
35 static void bta_hd_cback(BD_ADDR bd_addr, uint8_t event, uint32_t data, BT_HDR *pdata);
36 
check_descriptor(uint8_t * data,uint16_t length,bool * has_report_id)37 static bool check_descriptor(uint8_t *data, uint16_t length, bool *has_report_id)
38 {
39     uint8_t *ptr = data;
40     *has_report_id = FALSE;
41     while (ptr < data + length) {
42         uint8_t item = *ptr++;
43         switch (item) {
44         case 0xfe: // long item indicator
45             if (ptr < data + length) {
46                 ptr += ((*ptr) + 2);
47             } else {
48                 return false;
49             }
50             break;
51         case 0x85: // Report ID
52             *has_report_id = TRUE;
53         default:
54             ptr += (item & 0x03);
55             break;
56         }
57     }
58     return (ptr == data + length);
59 }
60 
61 /*******************************************************************************
62  *
63  * Function         bta_hd_api_enable
64  *
65  * Description      Enables HID device
66  *
67  * Returns          void
68  *
69  ******************************************************************************/
bta_hd_api_enable(tBTA_HD_DATA * p_data)70 void bta_hd_api_enable(tBTA_HD_DATA *p_data)
71 {
72     tBTA_HD_STATUS status = BTA_HD_ERROR;
73     tHID_STATUS ret;
74 
75     APPL_TRACE_API("%s", __func__);
76 
77     HID_DevInit();
78 
79     memset(&bta_hd_cb, 0, sizeof(tBTA_HD_CB));
80 
81     HID_DevSetSecurityLevel(BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
82     /* store parameters */
83     bta_hd_cb.p_cback = p_data->api_enable.p_cback;
84 
85     ret = HID_DevRegister(bta_hd_cback);
86     if (ret == HID_SUCCESS) {
87         status = BTA_HD_OK;
88     } else {
89         APPL_TRACE_ERROR("%s: Failed to register HID device (%d)", __func__, ret);
90     }
91 
92     /* signal BTA call back event */
93     (*bta_hd_cb.p_cback)(BTA_HD_ENABLE_EVT, (tBTA_HD *)&status);
94 }
95 
96 /*******************************************************************************
97  *
98  * Function         bta_hd_api_disable
99  *
100  * Description      Disables HID device
101  *
102  * Returns          void
103  *
104  ******************************************************************************/
bta_hd_api_disable(void)105 void bta_hd_api_disable(void)
106 {
107     tBTA_HD_STATUS status = BTA_HD_ERROR;
108     tHID_STATUS ret;
109 
110     APPL_TRACE_API("%s", __func__);
111 
112     /* service is not enabled */
113     if (bta_hd_cb.p_cback == NULL)
114         return;
115 
116     /* Remove service record */
117     if (bta_hd_cb.sdp_handle != 0) {
118         SDP_DeleteRecord(bta_hd_cb.sdp_handle);
119         bta_sys_remove_uuid(UUID_SERVCLASS_HUMAN_INTERFACE);
120     }
121 
122     /* Deregister with lower layer */
123     ret = HID_DevDeregister();
124     if (ret == HID_SUCCESS) {
125         status = BTA_HD_OK;
126     } else {
127         APPL_TRACE_ERROR("%s: Failed to deregister HID device (%d)", __func__, ret);
128     }
129 
130     (*bta_hd_cb.p_cback)(BTA_HD_DISABLE_EVT, (tBTA_HD *)&status);
131 
132     memset(&bta_hd_cb, 0, sizeof(tBTA_HD_CB));
133 }
134 
135 /*******************************************************************************
136  *
137  * Function         bta_hd_register_act
138  *
139  * Description      Registers SDP record
140  *
141  * Returns          void
142  *
143  ******************************************************************************/
bta_hd_register_act(tBTA_HD_DATA * p_data)144 void bta_hd_register_act(tBTA_HD_DATA *p_data)
145 {
146     tBTA_HD ret;
147     tBTA_HD_REGISTER_APP *p_app_data = (tBTA_HD_REGISTER_APP *)p_data;
148     bool use_report_id = FALSE;
149 
150     APPL_TRACE_API("%s", __func__);
151 
152     ret.reg_status.in_use = FALSE;
153 
154     /* Check if len doesn't exceed BTA_HD_APP_DESCRIPTOR_LEN and descriptor
155      * itself is well-formed. Also check if descriptor has Report Id item so we
156      * know if report will have prefix or not. */
157     if (p_app_data->d_len > BTA_HD_APP_DESCRIPTOR_LEN ||
158         !check_descriptor(p_app_data->d_data, p_app_data->d_len, &use_report_id)) {
159         APPL_TRACE_ERROR("%s: Descriptor is too long or malformed", __func__);
160         ret.reg_status.status = BTA_HD_ERROR;
161         (*bta_hd_cb.p_cback)(BTA_HD_REGISTER_APP_EVT, &ret);
162         return;
163     }
164 
165     ret.reg_status.status = BTA_HD_OK;
166 
167     /* Remove old record if for some reason it's already registered */
168     if (bta_hd_cb.sdp_handle != 0) {
169         SDP_DeleteRecord(bta_hd_cb.sdp_handle);
170     }
171 
172     bta_hd_cb.use_report_id = use_report_id;
173     bta_hd_cb.sdp_handle = SDP_CreateRecord();
174     HID_DevAddRecord(bta_hd_cb.sdp_handle, p_app_data->name, p_app_data->description, p_app_data->provider,
175                      p_app_data->subclass, p_app_data->d_len, p_app_data->d_data);
176     bta_sys_add_uuid(UUID_SERVCLASS_HUMAN_INTERFACE);
177 
178     HID_DevSetIncomingQos(p_app_data->in_qos.service_type, p_app_data->in_qos.token_rate,
179                           p_app_data->in_qos.token_bucket_size, p_app_data->in_qos.peak_bandwidth,
180                           p_app_data->in_qos.access_latency, p_app_data->in_qos.delay_variation);
181 
182     HID_DevSetOutgoingQos(p_app_data->out_qos.service_type, p_app_data->out_qos.token_rate,
183                           p_app_data->out_qos.token_bucket_size, p_app_data->out_qos.peak_bandwidth,
184                           p_app_data->out_qos.access_latency, p_app_data->out_qos.delay_variation);
185 
186     // application is registered so we can accept incoming connections
187     HID_DevSetIncomingPolicy(TRUE);
188 
189     if (HID_DevGetDevice(&ret.reg_status.bda) == HID_SUCCESS) {
190         ret.reg_status.in_use = TRUE;
191     }
192 
193     (*bta_hd_cb.p_cback)(BTA_HD_REGISTER_APP_EVT, &ret);
194 }
195 
196 /*******************************************************************************
197  *
198  * Function         bta_hd_unregister_act
199  *
200  * Description      Unregisters SDP record
201  *
202  * Returns          void
203  *
204  ******************************************************************************/
bta_hd_unregister_act(UNUSED_ATTR tBTA_HD_DATA * p_data)205 void bta_hd_unregister_act(UNUSED_ATTR tBTA_HD_DATA *p_data)
206 {
207     tBTA_HD_STATUS status = BTA_HD_OK;
208 
209     APPL_TRACE_API("%s", __func__);
210 
211     // application is no longer registered so we do not want incoming connections
212     HID_DevSetIncomingPolicy(FALSE);
213 
214     if (bta_hd_cb.sdp_handle != 0) {
215         SDP_DeleteRecord(bta_hd_cb.sdp_handle);
216     }
217 
218     bta_hd_cb.sdp_handle = 0;
219     bta_sys_remove_uuid(UUID_SERVCLASS_HUMAN_INTERFACE);
220 
221     (*bta_hd_cb.p_cback)(BTA_HD_UNREGISTER_APP_EVT, (tBTA_HD *)&status);
222 }
223 
224 /*******************************************************************************
225  *
226  * Function         bta_hd_unregister2_act
227  *
228  * Description
229  *
230  * Returns          void
231  *
232  ******************************************************************************/
bta_hd_unregister2_act(tBTA_HD_DATA * p_data)233 void bta_hd_unregister2_act(tBTA_HD_DATA *p_data)
234 {
235     APPL_TRACE_API("%s", __func__);
236 
237     // close first
238     bta_hd_close_act(p_data);
239 
240     // then unregister
241     bta_hd_unregister_act(p_data);
242 
243     if (bta_hd_cb.disable_w4_close) {
244         bta_hd_api_disable();
245     }
246 }
247 
248 /*******************************************************************************
249  *
250  * Function         bta_hd_connect_act
251  *
252  * Description      Connect to device (must be virtually plugged)
253  *
254  * Returns          void
255  *
256  ******************************************************************************/
bta_hd_connect_act(tBTA_HD_DATA * p_data)257 extern void bta_hd_connect_act(tBTA_HD_DATA *p_data)
258 {
259     tHID_STATUS ret;
260     tBTA_HD_DEVICE_CTRL *p_ctrl = (tBTA_HD_DEVICE_CTRL *)p_data;
261     tBTA_HD cback_data;
262 
263     APPL_TRACE_API("%s", __func__);
264     do {
265         ret = HID_DevPlugDevice(p_ctrl->addr);
266         if (ret != HID_SUCCESS) {
267             APPL_TRACE_WARNING("%s: HID_DevPlugDevice returned %d", __func__, ret);
268             return;
269         }
270 
271         ret = HID_DevConnect();
272         if (ret != HID_SUCCESS) {
273             APPL_TRACE_WARNING("%s: HID_DevConnect returned %d", __func__, ret);
274             return;
275         }
276     } while (0);
277 
278     bdcpy(cback_data.conn.bda, p_ctrl->addr);
279     cback_data.conn.status = (ret == HID_SUCCESS ? BTA_HD_OK : BTA_HD_ERROR);
280     cback_data.conn.conn_status = BTA_HD_CONN_STATE_CONNECTING;
281     bta_hd_cb.p_cback(BTA_HD_OPEN_EVT, &cback_data);
282 }
283 
284 /*******************************************************************************
285  *
286  * Function         bta_hd_disconnect_act
287  *
288  * Description      Disconnect from device
289  *
290  * Returns          void
291  *
292  ******************************************************************************/
bta_hd_disconnect_act(UNUSED_ATTR tBTA_HD_DATA * p_data)293 extern void bta_hd_disconnect_act(UNUSED_ATTR tBTA_HD_DATA *p_data)
294 {
295     tHID_STATUS ret;
296     tBTA_HD cback_data;
297 
298     APPL_TRACE_API("%s", __func__);
299 
300     ret = HID_DevDisconnect();
301 
302     if (ret != HID_SUCCESS) {
303         APPL_TRACE_WARNING("%s: HID_DevDisconnect returned %d", __func__, ret);
304         return;
305     }
306 
307     if (HID_DevGetDevice(&cback_data.conn.bda) == HID_SUCCESS) {
308         cback_data.conn.status = BTA_HD_OK;
309         cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTING;
310         bta_hd_cb.p_cback(BTA_HD_CLOSE_EVT, &cback_data);
311     }
312 }
313 
314 /*******************************************************************************
315  *
316  * Function         bta_hd_add_device_act
317  *
318  * Description
319  *
320  * Returns          void
321  *
322  ******************************************************************************/
bta_hd_add_device_act(tBTA_HD_DATA * p_data)323 extern void bta_hd_add_device_act(tBTA_HD_DATA *p_data)
324 {
325     tBTA_HD_DEVICE_CTRL *p_ctrl = (tBTA_HD_DEVICE_CTRL *)p_data;
326 
327     APPL_TRACE_API("%s", __func__);
328 
329     HID_DevPlugDevice(p_ctrl->addr);
330 }
331 
332 /*******************************************************************************
333  *
334  * Function         bta_hd_remove_device_act
335  *
336  * Description
337  *
338  * Returns          void
339  *
340  ******************************************************************************/
bta_hd_remove_device_act(tBTA_HD_DATA * p_data)341 extern void bta_hd_remove_device_act(tBTA_HD_DATA *p_data)
342 {
343     tBTA_HD_DEVICE_CTRL *p_ctrl = (tBTA_HD_DEVICE_CTRL *)p_data;
344 
345     APPL_TRACE_API("%s", __func__);
346 
347     HID_DevUnplugDevice(p_ctrl->addr);
348 }
349 
350 /*******************************************************************************
351  *
352  * Function         bta_hd_send_report_act
353  *
354  * Description      Sends report
355  *
356  * Returns          void
357  *
358  ******************************************************************************/
bta_hd_send_report_act(tBTA_HD_DATA * p_data)359 extern void bta_hd_send_report_act(tBTA_HD_DATA *p_data)
360 {
361     tBTA_HD_SEND_REPORT *p_report = (tBTA_HD_SEND_REPORT *)p_data;
362     uint8_t channel;
363     uint8_t report_id;
364     tBTA_HD cback_data;
365     tHID_STATUS ret;
366 
367     APPL_TRACE_VERBOSE("%s", __func__);
368 
369     channel = p_report->use_intr ? HID_CHANNEL_INTR : HID_CHANNEL_CTRL;
370     report_id = (bta_hd_cb.use_report_id || bta_hd_cb.boot_mode) ? p_report->id : 0x00;
371 
372     ret = HID_DevSendReport(channel, p_report->type, report_id, p_report->len, p_report->data);
373 
374     /* trigger PM */
375     bta_sys_busy(BTA_ID_HD, 1, bta_hd_cb.bd_addr);
376     bta_sys_idle(BTA_ID_HD, 1, bta_hd_cb.bd_addr);
377 
378     cback_data.send_report.status = (ret == HID_SUCCESS ? BTA_HD_OK : BTA_HD_ERROR);
379     cback_data.send_report.reason = ret;
380     cback_data.send_report.report_id = report_id;
381     cback_data.send_report.report_type = p_report->type;
382     bta_hd_cb.p_cback(BTA_HD_SEND_REPORT_EVT, &cback_data);
383 }
384 
385 /*******************************************************************************
386  *
387  * Function         bta_hd_report_error_act
388  *
389  * Description
390  *
391  * Returns          void
392  *
393  ******************************************************************************/
bta_hd_report_error_act(tBTA_HD_DATA * p_data)394 extern void bta_hd_report_error_act(tBTA_HD_DATA *p_data)
395 {
396     tBTA_HD_REPORT_ERR *p_report = (tBTA_HD_REPORT_ERR *)p_data;
397     tHID_STATUS ret;
398     tBTA_HD cback_data;
399 
400     APPL_TRACE_API("%s: error = %d", __func__, p_report->error);
401 
402     ret = HID_DevReportError(p_report->error);
403 
404     if (ret != HID_SUCCESS) {
405         APPL_TRACE_WARNING("%s: HID_DevReportError returned %d", __func__, ret);
406     }
407 
408     cback_data.report_err.status = (ret == HID_SUCCESS ? BTA_HD_OK : BTA_HD_ERROR);
409     cback_data.report_err.reason = ret;
410     bta_hd_cb.p_cback(BTA_HD_REPORT_ERR_EVT, &cback_data);
411 }
412 
413 /*******************************************************************************
414  *
415  * Function         bta_hd_vc_unplug_act
416  *
417  * Description      Sends Virtual Cable Unplug
418  *
419  * Returns          void
420  *
421  ******************************************************************************/
bta_hd_vc_unplug_act(UNUSED_ATTR tBTA_HD_DATA * p_data)422 extern void bta_hd_vc_unplug_act(UNUSED_ATTR tBTA_HD_DATA *p_data)
423 {
424     tHID_STATUS ret;
425     tBTA_HD cback_data = {0};
426     BD_ADDR plugged_addr = {0};
427 
428     APPL_TRACE_API("%s", __func__);
429 
430     bta_hd_cb.vc_unplug = TRUE;
431     ret = HID_DevVirtualCableUnplug();
432 
433     if (ret == HID_ERR_NO_CONNECTION) {
434         /* This is a local VUP without connection, set the vc_unplug to FALSE */
435         bta_hd_cb.vc_unplug = FALSE;
436         APPL_TRACE_WARNING("%s: HID_DevVirtualCableUnplug returned %d", __func__, ret);
437         if (HID_DevGetDevice(&plugged_addr) == HID_SUCCESS) {
438             HID_DevUnplugDevice(plugged_addr);
439         }
440         APPL_TRACE_DEBUG("%s local VUP, remove bda: %02x:%02x:%02x:%02x:%02x:%02x", __func__, plugged_addr[0],
441                          plugged_addr[1], plugged_addr[2], plugged_addr[3], plugged_addr[4], plugged_addr[5]);
442         cback_data.conn.status = BTA_HD_OK;
443         cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTED;
444         bta_hd_cb.p_cback(BTA_HD_VC_UNPLUG_EVT, &cback_data);
445         return;
446     } else if (ret != HID_SUCCESS) {
447         APPL_TRACE_WARNING("%s: HID_DevVirtualCableUnplug returned %d", __func__, ret);
448     }
449 
450     /* trigger PM */
451     bta_sys_busy(BTA_ID_HD, 1, bta_hd_cb.bd_addr);
452     bta_sys_idle(BTA_ID_HD, 1, bta_hd_cb.bd_addr);
453 }
454 
455 /*******************************************************************************
456  *
457  * Function         bta_hd_open_act
458  *
459  * Description
460  *
461  * Returns          void
462  *
463  ******************************************************************************/
bta_hd_open_act(tBTA_HD_DATA * p_data)464 extern void bta_hd_open_act(tBTA_HD_DATA *p_data)
465 {
466     tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
467     tBTA_HD cback_data;
468 
469     APPL_TRACE_API("%s", __func__);
470 
471     HID_DevPlugDevice(p_cback->addr);
472     bta_sys_conn_open(BTA_ID_HD, 1, p_cback->addr);
473 
474     bdcpy(cback_data.conn.bda, p_cback->addr);
475     bdcpy(bta_hd_cb.bd_addr, p_cback->addr);
476     cback_data.conn.status = BTA_HD_OK;
477     cback_data.conn.conn_status = BTA_HD_CONN_STATE_CONNECTED;
478     bta_hd_cb.p_cback(BTA_HD_OPEN_EVT, &cback_data);
479 }
480 
481 /*******************************************************************************
482  *
483  * Function         bta_hd_close_act
484  *
485  * Description
486  *
487  * Returns          void
488  *
489  ******************************************************************************/
bta_hd_close_act(tBTA_HD_DATA * p_data)490 extern void bta_hd_close_act(tBTA_HD_DATA *p_data)
491 {
492     tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
493     tBTA_HD cback_data;
494     tBTA_HD_EVT cback_event = BTA_HD_CLOSE_EVT;
495 
496     APPL_TRACE_API("%s", __func__);
497 
498     bta_sys_conn_close(BTA_ID_HD, 1, p_cback->addr);
499 
500     if (bta_hd_cb.vc_unplug) {
501         bta_hd_cb.vc_unplug = FALSE;
502         HID_DevUnplugDevice(p_cback->addr);
503         cback_event = BTA_HD_VC_UNPLUG_EVT;
504     }
505 
506     bdcpy(cback_data.conn.bda, p_cback->addr);
507     memset(bta_hd_cb.bd_addr, 0, sizeof(BD_ADDR));
508     cback_data.conn.status = BTA_HD_OK;
509     cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTED;
510     bta_hd_cb.p_cback(cback_event, &cback_data);
511 }
512 
513 /*******************************************************************************
514  *
515  * Function         bta_hd_intr_data_act
516  *
517  * Description      Handles incoming DATA request on intr
518  *
519  * Returns          void
520  *
521  ******************************************************************************/
bta_hd_intr_data_act(tBTA_HD_DATA * p_data)522 extern void bta_hd_intr_data_act(tBTA_HD_DATA *p_data)
523 {
524     tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
525     BT_HDR *p_msg = p_cback->p_data;
526     uint16_t len = p_msg->len;
527     uint8_t *p_buf = (uint8_t *)(p_msg + 1) + p_msg->offset;
528     tBTA_HD_INTR_DATA ret;
529 
530     APPL_TRACE_API("%s", __func__);
531 
532     if (bta_hd_cb.use_report_id || bta_hd_cb.boot_mode) {
533         ret.report_id = *p_buf;
534         len--;
535         p_buf++;
536     } else {
537         ret.report_id = 0;
538     }
539 
540     ret.len = len;
541     ret.p_data = p_buf;
542     (*bta_hd_cb.p_cback)(BTA_HD_INTR_DATA_EVT, (tBTA_HD *)&ret);
543     if (p_msg) {
544         osi_free(p_msg);
545     }
546 }
547 
548 /*******************************************************************************
549  *
550  * Function         bta_hd_get_report_act
551  *
552  * Description      Handles incoming GET_REPORT request
553  *
554  * Returns          void
555  *
556  ******************************************************************************/
bta_hd_get_report_act(tBTA_HD_DATA * p_data)557 extern void bta_hd_get_report_act(tBTA_HD_DATA *p_data)
558 {
559     tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
560     bool rep_size_follows = p_cback->data;
561     BT_HDR *p_msg = p_cback->p_data;
562     uint8_t *p_buf = (uint8_t *)(p_msg + 1) + p_msg->offset;
563     tBTA_HD_GET_REPORT ret = {0, 0, 0};
564     uint16_t remaining_len = p_msg->len;
565 
566     APPL_TRACE_API("%s", __func__);
567     if (remaining_len < 1) {
568         APPL_TRACE_ERROR("%s invalid data, remaining_len:%d", __func__, remaining_len);
569         return;
570     }
571 
572     ret.report_type = *p_buf & HID_PAR_REP_TYPE_MASK;
573     p_buf++;
574     remaining_len--;
575 
576     if (bta_hd_cb.use_report_id) {
577         if (remaining_len < 1) {
578             APPL_TRACE_ERROR("%s invalid data, remaining_len:%d", __func__, remaining_len);
579             return;
580         }
581         ret.report_id = *p_buf;
582         p_buf++;
583         remaining_len--;
584     }
585 
586     if (rep_size_follows) {
587         if (remaining_len < 2) {
588             APPL_TRACE_ERROR("%s invalid data, remaining_len:%d", __func__, remaining_len);
589             return;
590         }
591         ret.buffer_size = *p_buf | (*(p_buf + 1) << 8);
592     }
593 
594     (*bta_hd_cb.p_cback)(BTA_HD_GET_REPORT_EVT, (tBTA_HD *)&ret);
595     if (p_msg) {
596         osi_free(p_msg);
597     }
598 }
599 
600 /*******************************************************************************
601  *
602  * Function         bta_hd_set_report_act
603  *
604  * Description      Handles incoming SET_REPORT request
605  *
606  * Returns          void
607  *
608  ******************************************************************************/
bta_hd_set_report_act(tBTA_HD_DATA * p_data)609 extern void bta_hd_set_report_act(tBTA_HD_DATA *p_data)
610 {
611     tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
612     BT_HDR *p_msg = p_cback->p_data;
613     uint16_t len = p_msg->len;
614     uint8_t *p_buf = (uint8_t *)(p_msg + 1) + p_msg->offset;
615     tBTA_HD_SET_REPORT ret = {0, 0, 0, NULL};
616 
617     APPL_TRACE_API("%s", __func__);
618 
619     ret.report_type = *p_buf & HID_PAR_REP_TYPE_MASK;
620     p_buf++;
621     len--;
622 
623     if (bta_hd_cb.use_report_id || bta_hd_cb.boot_mode) {
624         ret.report_id = *p_buf;
625         len--;
626         p_buf++;
627     } else {
628         ret.report_id = 0;
629     }
630 
631     ret.len = len;
632     ret.p_data = p_buf;
633     (*bta_hd_cb.p_cback)(BTA_HD_SET_REPORT_EVT, (tBTA_HD *)&ret);
634     if (p_msg) {
635         osi_free(p_msg);
636     }
637 }
638 
639 /*******************************************************************************
640  *
641  * Function         bta_hd_set_protocol_act
642  *
643  * Description
644  *
645  * Returns          void
646  *
647  ******************************************************************************/
bta_hd_set_protocol_act(tBTA_HD_DATA * p_data)648 extern void bta_hd_set_protocol_act(tBTA_HD_DATA *p_data)
649 {
650     tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
651     tBTA_HD cback_data;
652 
653     APPL_TRACE_API("%s", __func__);
654 
655     bta_hd_cb.boot_mode = (p_cback->data == HID_PAR_PROTOCOL_BOOT_MODE);
656     cback_data.set_protocol = p_cback->data;
657 
658     (*bta_hd_cb.p_cback)(BTA_HD_SET_PROTOCOL_EVT, &cback_data);
659 }
660 
661 /*******************************************************************************
662  *
663  * Function         bta_hd_vc_unplug_done_act
664  *
665  * Description
666  *
667  * Returns          void
668  *
669  ******************************************************************************/
bta_hd_vc_unplug_done_act(tBTA_HD_DATA * p_data)670 extern void bta_hd_vc_unplug_done_act(tBTA_HD_DATA *p_data)
671 {
672     tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
673     tBTA_HD cback_data;
674 
675     APPL_TRACE_API("%s", __func__);
676 
677     bta_sys_conn_close(BTA_ID_HD, 1, p_cback->addr);
678 
679     HID_DevUnplugDevice(p_cback->addr);
680 
681     bdcpy(cback_data.conn.bda, p_cback->addr);
682     bdcpy(bta_hd_cb.bd_addr, p_cback->addr);
683     cback_data.conn.status = BTA_HD_OK;
684     cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTED;
685     (*bta_hd_cb.p_cback)(BTA_HD_VC_UNPLUG_EVT, &cback_data);
686 }
687 
688 /*******************************************************************************
689  *
690  * Function         bta_hd_suspend_act
691  *
692  * Description
693  *
694  * Returns          void
695  *
696  ******************************************************************************/
bta_hd_suspend_act(tBTA_HD_DATA * p_data)697 extern void bta_hd_suspend_act(tBTA_HD_DATA *p_data)
698 {
699     tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
700 
701     APPL_TRACE_API("%s", __func__);
702 
703     bta_sys_idle(BTA_ID_HD, 1, p_cback->addr);
704 }
705 
706 /*******************************************************************************
707  *
708  * Function         bta_hd_exit_suspend_act
709  *
710  * Description
711  *
712  * Returns          void
713  *
714  ******************************************************************************/
bta_hd_exit_suspend_act(tBTA_HD_DATA * p_data)715 extern void bta_hd_exit_suspend_act(tBTA_HD_DATA *p_data)
716 {
717     tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
718 
719     APPL_TRACE_API("%s", __func__);
720 
721     bta_sys_busy(BTA_ID_HD, 1, p_cback->addr);
722     bta_sys_idle(BTA_ID_HD, 1, p_cback->addr);
723 }
724 
725 /*******************************************************************************
726  *
727  * Function         bta_hd_open_failure
728  *
729  * Description
730  *
731  * Returns          void
732  *
733  ******************************************************************************/
bta_hd_open_failure(tBTA_HD_DATA * p_data)734 extern void bta_hd_open_failure(tBTA_HD_DATA *p_data)
735 {
736     tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
737     tBTA_HD cback_data = {0};
738 
739     bdcpy(cback_data.conn.bda, p_cback->addr);
740     cback_data.conn.status = BTA_HD_ERROR;
741     cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTED;
742     bta_hd_cb.p_cback(BTA_HD_OPEN_EVT, &cback_data);
743 }
744 
745 /*******************************************************************************
746  *
747  * Function         bta_hd_cback
748  *
749  * Description      BTA HD callback function
750  *
751  * Returns          void
752  *
753  ******************************************************************************/
bta_hd_cback(BD_ADDR bd_addr,uint8_t event,uint32_t data,BT_HDR * pdata)754 static void bta_hd_cback(BD_ADDR bd_addr, uint8_t event, uint32_t data, BT_HDR *pdata)
755 {
756     tBTA_HD_CBACK_DATA *p_buf = NULL;
757     uint16_t sm_event = BTA_HD_INVALID_EVT;
758 
759     APPL_TRACE_API("%s: event=%d", __func__, event);
760 
761     switch (event) {
762     case HID_DHOST_EVT_OPEN:
763         sm_event = BTA_HD_INT_OPEN_EVT;
764         break;
765 
766     case HID_DHOST_EVT_CLOSE:
767         sm_event = BTA_HD_INT_CLOSE_EVT;
768         break;
769 
770     case HID_DHOST_EVT_GET_REPORT:
771         sm_event = BTA_HD_INT_GET_REPORT_EVT;
772         break;
773 
774     case HID_DHOST_EVT_SET_REPORT:
775         sm_event = BTA_HD_INT_SET_REPORT_EVT;
776         break;
777 
778     case HID_DHOST_EVT_SET_PROTOCOL:
779         sm_event = BTA_HD_INT_SET_PROTOCOL_EVT;
780         break;
781 
782     case HID_DHOST_EVT_INTR_DATA:
783         sm_event = BTA_HD_INT_INTR_DATA_EVT;
784         break;
785 
786     case HID_DHOST_EVT_VC_UNPLUG:
787         sm_event = BTA_HD_INT_VC_UNPLUG_EVT;
788         break;
789 
790     case HID_DHOST_EVT_SUSPEND:
791         sm_event = BTA_HD_INT_SUSPEND_EVT;
792         break;
793 
794     case HID_DHOST_EVT_EXIT_SUSPEND:
795         sm_event = BTA_HD_INT_EXIT_SUSPEND_EVT;
796         break;
797     }
798 
799     if (sm_event != BTA_HD_INVALID_EVT &&
800         (p_buf = (tBTA_HD_CBACK_DATA *)osi_malloc(sizeof(tBTA_HD_CBACK_DATA) + sizeof(BT_HDR))) != NULL) {
801         p_buf->hdr.event = sm_event;
802         bdcpy(p_buf->addr, bd_addr);
803         p_buf->data = data;
804         p_buf->p_data = pdata;
805 
806         bta_sys_sendmsg(p_buf);
807     }
808 }
809 #endif /* BTA_HD_INCLUDED */
810