• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright 2005-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /******************************************************************************
20  *
21  *  This file contains the HID host action functions.
22  *
23  ******************************************************************************/
24 
25 #define LOG_TAG "bluetooth"
26 
27 // BTA_HH_INCLUDED
28 #include <cstdint>
29 #include <string>
30 
31 #include "bt_target.h"  // Must be first to define build configuration
32 #include "bta/hh/bta_hh_int.h"
33 #include "bta/include/bta_hh_api.h"
34 #include "bta/include/bta_hh_co.h"
35 #include "bta/sys/bta_sys.h"
36 #include "btif/include/btif_storage.h"
37 #include "main/shim/dumpsys.h"
38 #include "osi/include/allocator.h"
39 #include "osi/include/log.h"
40 #include "osi/include/osi.h"  // UNUSED_ATTR
41 #include "stack/include/acl_api.h"
42 #include "stack/include/bt_hdr.h"
43 #include "stack/include/hiddefs.h"
44 #include "stack/include/hidh_api.h"
45 #include "types/bluetooth/uuid.h"
46 #include "types/raw_address.h"
47 
48 /*****************************************************************************
49  *  Constants
50  ****************************************************************************/
51 
52 namespace {
53 
54 constexpr char kBtmLogTag[] = "HIDH";
55 
56 }
57 
58 /*****************************************************************************
59  *  Local Function prototypes
60  ****************************************************************************/
61 static void bta_hh_cback(uint8_t dev_handle, const RawAddress& addr,
62                          uint8_t event, uint32_t data, BT_HDR* pdata);
63 static tBTA_HH_STATUS bta_hh_get_trans_status(uint32_t result);
64 
65 static const char* bta_hh_get_w4_event(uint16_t event);
66 static const char* bta_hh_hid_event_name(uint16_t event);
67 
68 /*****************************************************************************
69  *  Action Functions
70  ****************************************************************************/
71 /*******************************************************************************
72  *
73  * Function         bta_hh_api_enable
74  *
75  * Description      Perform necessary operations to enable HID host.
76  *
77  *
78  * Returns          void
79  *
80  ******************************************************************************/
bta_hh_api_enable(tBTA_HH_CBACK * p_cback,bool enable_hid,bool enable_hogp)81 void bta_hh_api_enable(tBTA_HH_CBACK* p_cback, bool enable_hid, bool enable_hogp) {
82   tBTA_HH_STATUS status = BTA_HH_OK;
83   uint8_t xx;
84 
85   /* initialize BTE HID */
86   HID_HostInit();
87 
88   memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB));
89 
90   /* store parameters */
91   bta_hh_cb.p_cback = p_cback;
92   /* initialize device CB */
93   for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++) {
94     bta_hh_cb.kdev[xx].state = BTA_HH_IDLE_ST;
95     bta_hh_cb.kdev[xx].hid_handle = BTA_HH_INVALID_HANDLE;
96     bta_hh_cb.kdev[xx].index = xx;
97   }
98 
99   /* initialize control block map */
100   for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++) {
101     bta_hh_cb.cb_index[xx] = BTA_HH_IDX_INVALID;
102   }
103 
104   if (enable_hid) {
105     /* Register with L2CAP */
106     if (HID_HostRegister(bta_hh_cback) != HID_SUCCESS) {
107       status = BTA_HH_ERR;
108     }
109   }
110 
111   if (status == BTA_HH_OK && enable_hogp) {
112     bta_hh_le_enable();
113   } else {
114     /* signal BTA call back event */
115     tBTA_HH bta_hh;
116     bta_hh.status = status;
117     if (status != BTA_HH_OK) {
118       LOG_ERROR("Failed to register, status: %d", status);
119     }
120     if (bta_hh_cb.p_cback) {
121       (*bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, &bta_hh);
122     }
123   }
124 }
125 /*******************************************************************************
126  *
127  * Function         bta_hh_api_disable
128  *
129  * Description      Perform necessary operations to disable HID host.
130  *
131  *
132  * Returns          void
133  *
134  ******************************************************************************/
bta_hh_api_disable(void)135 void bta_hh_api_disable(void) {
136   uint8_t xx;
137 
138   /* service is not enabled */
139   if (bta_hh_cb.p_cback == NULL) return;
140 
141   /* no live connection, signal DISC_CMPL_EVT directly */
142   if (!bta_hh_cb.cnt_num) {
143     bta_hh_disc_cmpl();
144   } else /* otherwise, disconnect all live connections */
145   {
146     bta_hh_cb.w4_disable = true;
147 
148     for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++) {
149       /* send API_CLOSE event to every connected device */
150       if (bta_hh_cb.kdev[xx].state == BTA_HH_CONN_ST) {
151         /* disconnect all connected devices */
152         bta_hh_sm_execute(&bta_hh_cb.kdev[xx], BTA_HH_API_CLOSE_EVT, NULL);
153       }
154     }
155   }
156 
157   return;
158 }
159 
160 /*******************************************************************************
161  *
162  * Function         bta_hh_disc_cmpl
163  *
164  * Description      All connections have been closed, disable service.
165  *
166  *
167  * Returns          void
168  *
169  ******************************************************************************/
bta_hh_disc_cmpl(void)170 void bta_hh_disc_cmpl(void) {
171   LOG_DEBUG("Disconnect complete");
172   tBTA_HH_STATUS status = BTA_HH_OK;
173 
174   /* Deregister with lower layer */
175   if (HID_HostDeregister() != HID_SUCCESS) status = BTA_HH_ERR;
176 
177   if (bta_hh_cb.gatt_if != BTA_GATTS_INVALID_IF) {
178     LOG_DEBUG("Deregister HOGP host before cleanup");
179     bta_hh_le_deregister();
180   } else {
181     bta_hh_cleanup_disable(status);
182   }
183 }
184 
185 /*******************************************************************************
186  *
187  * Function         bta_hh_sdp_cback
188  *
189  * Description      SDP callback function.
190  *
191  * Returns          void
192  *
193  ******************************************************************************/
bta_hh_sdp_cback(uint16_t result,uint16_t attr_mask,tHID_DEV_SDP_INFO * sdp_rec)194 static void bta_hh_sdp_cback(uint16_t result, uint16_t attr_mask,
195                              tHID_DEV_SDP_INFO* sdp_rec) {
196   tBTA_HH_DEV_CB* p_cb = bta_hh_cb.p_cur;
197   uint8_t hdl = 0;
198   tBTA_HH_STATUS status = BTA_HH_ERR_SDP;
199 
200   /* make sure sdp succeeded and hh has not been disabled */
201   if ((result == SDP_SUCCESS) && (p_cb != NULL)) {
202     /* security is required for the connection, add attr_mask bit*/
203     attr_mask |= HID_SEC_REQUIRED;
204 
205     APPL_TRACE_EVENT("%s: p_cb: %d result 0x%02x, attr_mask 0x%02x, handle %x",
206                      __func__, p_cb, result, attr_mask, p_cb->hid_handle);
207 
208     /* check to see type of device is supported , and should not been added
209      * before */
210     if (bta_hh_tod_spt(p_cb, sdp_rec->sub_class)) {
211       /* if not added before */
212       if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE) {
213         /*  add device/update attr_mask information */
214         if (HID_HostAddDev(p_cb->addr, attr_mask, &hdl) == HID_SUCCESS) {
215           status = BTA_HH_OK;
216           /* update cb_index[] map */
217           bta_hh_cb.cb_index[hdl] = p_cb->index;
218         } else {
219           p_cb->app_id = 0;
220         }
221       } else {
222         hdl = p_cb->hid_handle;
223       }
224       /* else : incoming connection after SDP should update the SDP information
225        * as well */
226 
227       if (p_cb->app_id != 0) {
228         /* update cb information with attr_mask, dscp_info etc. */
229         bta_hh_add_device_to_list(p_cb, hdl, attr_mask, &sdp_rec->dscp_info,
230                                   sdp_rec->sub_class, sdp_rec->ssr_max_latency,
231                                   sdp_rec->ssr_min_tout, p_cb->app_id);
232 
233         p_cb->dscp_info.ctry_code = sdp_rec->ctry_code;
234 
235         status = BTA_HH_OK;
236       }
237 
238     } else /* type of device is not supported */
239       status = BTA_HH_ERR_TOD_UNSPT;
240   }
241 
242   /* free disc_db when SDP is completed */
243   osi_free_and_reset((void**)&bta_hh_cb.p_disc_db);
244 
245   /* send SDP_CMPL_EVT into state machine */
246   tBTA_HH_DATA bta_hh_data;
247   bta_hh_data.status = status;
248   bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, &bta_hh_data);
249 
250   return;
251 }
252 /*******************************************************************************
253  *
254  * Function         bta_hh_di_sdp_cback
255  *
256  * Description      SDP DI callback function.
257  *
258  * Returns          void
259  *
260  ******************************************************************************/
bta_hh_di_sdp_cback(tSDP_RESULT result)261 static void bta_hh_di_sdp_cback(tSDP_RESULT result) {
262   tBTA_HH_DEV_CB* p_cb = bta_hh_cb.p_cur;
263   tBTA_HH_STATUS status = BTA_HH_ERR_SDP;
264   tSDP_DI_GET_RECORD di_rec;
265   tHID_STATUS ret;
266   APPL_TRACE_EVENT("%s: p_cb: %d result 0x%02x", __func__, p_cb, result);
267 
268   /* if DI record does not exist on remote device, vendor_id in
269    * tBTA_HH_DEV_DSCP_INFO will be set to 0xffff and we will allow the
270    * connection to go through. Spec mandates that DI record be set, but many
271    * HID devices do not set this. So for IOP purposes, we allow the connection
272    * to go through and update the DI record to invalid DI entry.
273    */
274   if (((result == SDP_SUCCESS) || (result == SDP_NO_RECS_MATCH)) &&
275       (p_cb != NULL)) {
276     if (result == SDP_SUCCESS &&
277         SDP_GetNumDiRecords(bta_hh_cb.p_disc_db) != 0) {
278       /* always update information with primary DI record */
279       if (SDP_GetDiRecord(1, &di_rec, bta_hh_cb.p_disc_db) == SDP_SUCCESS) {
280         bta_hh_update_di_info(p_cb, di_rec.rec.vendor, di_rec.rec.product,
281                               di_rec.rec.version, 0, 0);
282       }
283 
284     } else /* no DI recrod available */
285     {
286       bta_hh_update_di_info(p_cb, BTA_HH_VENDOR_ID_INVALID, 0, 0, 0, 0);
287     }
288 
289     ret = HID_HostGetSDPRecord(p_cb->addr, bta_hh_cb.p_disc_db,
290                                p_bta_hh_cfg->sdp_db_size, bta_hh_sdp_cback);
291     if (ret == HID_SUCCESS) {
292       status = BTA_HH_OK;
293     } else {
294       APPL_TRACE_DEBUG("%s:  HID_HostGetSDPRecord failed: Status 0x%2x",
295                        __func__, ret);
296     }
297   }
298 
299   if (status != BTA_HH_OK) {
300     osi_free_and_reset((void**)&bta_hh_cb.p_disc_db);
301     /* send SDP_CMPL_EVT into state machine */
302     tBTA_HH_DATA bta_hh_data;
303     bta_hh_data.status = status;
304     bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, &bta_hh_data);
305   }
306   return;
307 }
308 
309 /*******************************************************************************
310  *
311  * Function         bta_hh_start_sdp
312  *
313  * Description      Start SDP service search, and obtain necessary SDP records.
314  *                  Only one SDP service search request is allowed at the same
315  *                  time. For every BTA_HhOpen API call, do SDP first unless SDP
316  *                  has been done previously.
317  *
318  * Returns          void
319  *
320  ******************************************************************************/
bta_hh_start_sdp(tBTA_HH_DEV_CB * p_cb,const tBTA_HH_DATA * p_data)321 static void bta_hh_start_sdp(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
322   if (!bta_hh_cb.p_disc_db) {
323     bta_hh_cb.p_disc_db =
324         (tSDP_DISCOVERY_DB*)osi_malloc(p_bta_hh_cfg->sdp_db_size);
325 
326     /* Do DI discovery first */
327     if (SDP_DiDiscover(p_data->api_conn.bd_addr, bta_hh_cb.p_disc_db,
328                        p_bta_hh_cfg->sdp_db_size,
329                        bta_hh_di_sdp_cback) == SDP_SUCCESS) {
330       /* SDP search started successfully
331        * Connection will be triggered at the end of successful SDP search
332        */
333     } else {
334       LOG_ERROR("SDP_DiDiscover failed");
335 
336       osi_free_and_reset((void**)&bta_hh_cb.p_disc_db);
337 
338       tBTA_HH_DATA bta_hh_data;
339       bta_hh_data.status = BTA_HH_ERR_SDP;
340       bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, &bta_hh_data);
341     }
342   } else if (bta_hh_cb.p_disc_db) {
343     /* Incoming/outgoing collision case. DUT initiated HID connection at the
344      * same time as the remote connected HID control channel.
345      * When flow reaches here due to remote initiated connection, DUT may be
346      * doing SDP. In such case, just do nothing and the ongoing SDP completion
347      * or failure will handle this case.
348      */
349     LOG_WARN("Ignoring as SDP already in progress");
350   }
351 }
352 
353 /*******************************************************************************
354  *
355  * Function         bta_hh_sdp_cmpl
356  *
357  * Description      When SDP completes, initiate a connection or report an error
358  *                  depending on the SDP result.
359  *
360  *
361  * Returns          void
362  *
363  ******************************************************************************/
bta_hh_sdp_cmpl(tBTA_HH_DEV_CB * p_cb,const tBTA_HH_DATA * p_data)364 void bta_hh_sdp_cmpl(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
365   CHECK(p_data != nullptr);
366 
367   tBTA_HH_CONN conn_dat;
368   tBTA_HH_STATUS status = p_data->status;
369 
370   APPL_TRACE_DEBUG("%s:  status 0x%2X", __func__, p_data->status);
371 
372   /* initialize call back data */
373   memset((void*)&conn_dat, 0, sizeof(tBTA_HH_CONN));
374   conn_dat.handle = p_cb->hid_handle;
375   conn_dat.bda = p_cb->addr;
376 
377   /* if SDP compl success */
378   if (status == BTA_HH_OK) {
379     /* not incoming connection doing SDP, initiate a HID connection */
380     if (!p_cb->incoming_conn) {
381       tHID_STATUS ret;
382 
383       /* open HID connection */
384       ret = HID_HostOpenDev(p_cb->hid_handle);
385       APPL_TRACE_DEBUG("%s: HID_HostOpenDev returned=%d", __func__, ret);
386       if (ret == HID_SUCCESS || ret == HID_ERR_ALREADY_CONN) {
387         status = BTA_HH_OK;
388       } else if (ret == HID_ERR_CONN_IN_PROCESS) {
389         /* Connection already in progress, return from here, SDP
390          * will be performed after connection is completed.
391          */
392         APPL_TRACE_DEBUG("%s: connection already in progress", __func__);
393         return;
394       } else {
395         APPL_TRACE_DEBUG("%s: HID_HostOpenDev failed: Status 0x%2X", __func__,
396                          ret);
397         /* open fail, remove device from management device list */
398         HID_HostRemoveDev(p_cb->hid_handle);
399         status = BTA_HH_ERR;
400       }
401     } else /* incoming connection SDP finish */
402     {
403       bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, NULL);
404     }
405   }
406 
407   if (status != BTA_HH_OK) {
408     /* Check if this was incoming connection request  from an unknown device
409      * and connection failed due to missing HID Device SDP UUID
410      * In above condition, disconnect the link as well as remove the
411      * device from list of HID devices
412      */
413     if ((status == BTA_HH_ERR_SDP) && (p_cb->incoming_conn) &&
414         (p_cb->app_id == 0)) {
415       APPL_TRACE_ERROR("%s: SDP failed for  incoming conn hndl: %d", __func__,
416                        p_cb->incoming_hid_handle);
417       HID_HostRemoveDev(p_cb->incoming_hid_handle);
418     }
419     conn_dat.status = status;
420     (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH*)&conn_dat);
421 
422     /* move state machine W4_CONN ->IDLE */
423     bta_hh_sm_execute(p_cb, BTA_HH_API_CLOSE_EVT, NULL);
424 
425     /* if this is an outgoing connection to an unknown device, clean up cb */
426     if (p_cb->app_id == 0 && !p_cb->incoming_conn) {
427       /* clean up device control block */
428       bta_hh_clean_up_kdev(p_cb);
429     }
430     bta_hh_trace_dev_db();
431   }
432   p_cb->incoming_conn = false;
433   p_cb->incoming_hid_handle = BTA_HH_INVALID_HANDLE;
434   return;
435 }
436 
437 /*******************************************************************************
438  *
439  * Function         bta_hh_bredr_conn
440  *
441  * Description      Initiate BR/EDR HID connection. This may be triggered by
442  *                  the local application or as a result of remote initiated
443  *                  HID connection.
444  *
445  * Returns          void
446  *
447  ******************************************************************************/
bta_hh_bredr_conn(tBTA_HH_DEV_CB * p_cb,const tBTA_HH_DATA * p_data)448 static void bta_hh_bredr_conn(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
449   bta_hh_cb.p_cur = p_cb;
450 
451   /* If previously virtually cabled device */
452   if (p_cb->app_id) {
453     tBTA_HH_DATA bta_hh_data;
454     bta_hh_data.status = BTA_HH_OK;
455 
456     APPL_TRACE_DEBUG("%s: skip SDP for known devices", __func__);
457 
458     if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE) {
459       uint8_t hdl;
460       if (HID_HostAddDev(p_cb->addr, p_cb->attr_mask, &hdl) == HID_SUCCESS) {
461         /* update device CB with newly register device handle */
462         bta_hh_add_device_to_list(p_cb, hdl, p_cb->attr_mask, NULL,
463                                   p_cb->sub_class,
464                                   p_cb->dscp_info.ssr_max_latency,
465                                   p_cb->dscp_info.ssr_min_tout, p_cb->app_id);
466         /* update cb_index[] map */
467         bta_hh_cb.cb_index[hdl] = p_cb->index;
468       } else {
469         bta_hh_data.status = BTA_HH_ERR_NO_RES;
470       }
471     }
472 
473     bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, &bta_hh_data);
474   }
475   else { /* First time connection, start SDP */
476     bta_hh_start_sdp(p_cb, p_data);
477   }
478 }
479 
480 /*******************************************************************************
481  *
482  * Function         bta_hh_connect
483  *
484  * Description      Start HID host connection.
485  *
486  * Returns          void
487  *
488  ******************************************************************************/
bta_hh_connect(tBTA_HH_DEV_CB * p_cb,const tBTA_HH_DATA * p_data)489 void bta_hh_connect(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
490   bool hid_available = false;
491   bool hogp_available = false;
492   bluetooth::Uuid remote_uuids[BT_MAX_NUM_UUIDS] = {};
493   bt_property_t remote_properties = {BT_PROPERTY_UUIDS, sizeof(remote_uuids),
494                                      &remote_uuids};
495   const RawAddress& bd_addr = p_data->api_conn.bd_addr;
496 
497   // Find the device type
498   tBT_DEVICE_TYPE dev_type;
499   tBLE_ADDR_TYPE addr_type;
500   BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
501 
502   // Find which transports are already connected
503   bool bredr = BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_BR_EDR);
504   bool le_acl = BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_LE);
505 
506   // Find which services known to be available
507   if (btif_storage_get_remote_device_property(&bd_addr,
508                                               &remote_properties) == BT_STATUS_SUCCESS) {
509     int count = remote_properties.len / sizeof(remote_uuids[0]);
510     for (int i = 0; i < count; i++) {
511       if (remote_uuids[i].Is16Bit()) {
512         if (remote_uuids[i].As16Bit() == UUID_SERVCLASS_HUMAN_INTERFACE) {
513           hid_available = true;
514         } else if (remote_uuids[i].As16Bit() == UUID_SERVCLASS_LE_HID) {
515           hogp_available = true;
516         }
517       }
518 
519       if (hid_available && hogp_available) {
520         break;
521       }
522     }
523   }
524 
525   /* Decide whether to connect HID or HOGP */
526   if (bredr && hid_available) {
527     p_cb->is_le_device = false;
528   } else if (le_acl && hogp_available) {
529     p_cb->is_le_device = true;
530   } else if (hid_available) {
531     p_cb->is_le_device = false;
532   } else if (hogp_available) {
533     p_cb->is_le_device = true;
534   } else if (bredr) {
535     p_cb->is_le_device = false;
536   } else if (le_acl || dev_type == BT_DEVICE_TYPE_BLE) {
537     p_cb->is_le_device = true;
538   } else {
539     p_cb->is_le_device = false;
540   }
541 
542   LOG_DEBUG("bd_addr:%s, bredr:%d, hid_available:%d, le_acl:%d, hogp_available:%d, "
543             "dev_type:%d, is_le_device:%d", ADDRESS_TO_LOGGABLE_CSTR(bd_addr), bredr,
544             hid_available, le_acl, hogp_available, dev_type, p_cb->is_le_device);
545 
546   p_cb->mode = p_data->api_conn.mode;
547   bta_hh_cb.p_cur = p_cb;
548 
549   // Initiate HID host connection
550   if (p_cb->is_le_device) {
551     bta_hh_le_open_conn(p_cb, bd_addr);
552   } else {
553     bta_hh_bredr_conn(p_cb, p_data);
554   }
555 }
556 
557 /*******************************************************************************
558  *
559  * Function         bta_hh_api_disc_act
560  *
561  * Description      HID Host initiate a disconnection.
562  *
563  *
564  * Returns          void
565  *
566  ******************************************************************************/
567 void btif_hh_remove_device(RawAddress bd_addr);
bta_hh_api_disc_act(tBTA_HH_DEV_CB * p_cb,const tBTA_HH_DATA * p_data)568 void bta_hh_api_disc_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
569   CHECK(p_cb != nullptr);
570 
571   if (p_cb->is_le_device) {
572     LOG_DEBUG("Host initiating close to le device:%s",
573               ADDRESS_TO_LOGGABLE_CSTR(p_cb->addr));
574 
575     bta_hh_le_api_disc_act(p_cb);
576 
577   } else {
578     const uint8_t hid_handle =
579         (p_data != nullptr) ? static_cast<uint8_t>(p_data->hdr.layer_specific)
580                             : p_cb->hid_handle;
581     tHID_STATUS status = HID_HostCloseDev(hid_handle);
582     if (status != HID_SUCCESS) {
583       LOG_WARN("Failed closing classic device:%s status:%s",
584                ADDRESS_TO_LOGGABLE_CSTR(p_cb->addr), hid_status_text(status).c_str());
585     } else {
586       LOG_DEBUG("Host initiated close to classic device:%s",
587                 ADDRESS_TO_LOGGABLE_CSTR(p_cb->addr));
588     }
589     tBTA_HH bta_hh = {
590         .dev_status = {.status =
591                            (status == HID_SUCCESS) ? BTA_HH_OK : BTA_HH_ERR,
592                        .handle = hid_handle},
593     };
594     (*bta_hh_cb.p_cback)(BTA_HH_CLOSE_EVT, &bta_hh);
595   }
596 }
597 
598 /*******************************************************************************
599  *
600  * Function         bta_hh_open_cmpl_act
601  *
602  * Description      HID host connection completed
603  *
604  *
605  * Returns          void
606  *
607  ******************************************************************************/
bta_hh_open_cmpl_act(tBTA_HH_DEV_CB * p_cb,const tBTA_HH_DATA * p_data)608 void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
609   tBTA_HH_CONN conn;
610   uint8_t dev_handle =
611       p_data ? (uint8_t)p_data->hid_cback.hdr.layer_specific : p_cb->hid_handle;
612 
613   memset((void*)&conn, 0, sizeof(tBTA_HH_CONN));
614   conn.handle = dev_handle;
615   conn.bda = p_cb->addr;
616 
617   /* increase connection number */
618   bta_hh_cb.cnt_num++;
619 
620   conn.status = p_cb->status;
621   conn.le_hid = p_cb->is_le_device;
622   conn.scps_supported = p_cb->scps_supported;
623   conn.sub_class = p_cb->sub_class;
624   conn.attr_mask = p_cb->attr_mask;
625   conn.app_id = p_cb->app_id;
626 
627   BTM_LogHistory(kBtmLogTag, p_cb->addr, "Opened",
628                  base::StringPrintf(
629                      "%s initiator:%s", (p_cb->is_le_device) ? "le" : "classic",
630                      (p_cb->incoming_conn) ? "remote" : "local"));
631 
632   if (!p_cb->is_le_device)
633   {
634     /* inform role manager */
635     bta_sys_conn_open(BTA_ID_HH, p_cb->app_id, p_cb->addr);
636 
637     /* set protocol mode when not default report mode */
638     if (p_cb->mode != BTA_HH_PROTO_RPT_MODE) {
639       tHID_STATUS status =
640           HID_HostWriteDev(dev_handle, HID_TRANS_SET_PROTOCOL,
641                            HID_PAR_PROTOCOL_BOOT_MODE, 0, 0, NULL);
642 
643       if (status == HID_SUCCESS) {
644         p_cb->w4_evt = BTA_HH_SET_PROTO_EVT;
645       } else {
646         /* HID connection is up, while SET_PROTO fail */
647         conn.status = BTA_HH_ERR_PROTO;
648       }
649     }
650   }
651   p_cb->incoming_conn = false;
652   p_cb->incoming_hid_handle = BTA_HH_INVALID_HANDLE;
653 
654   (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH*)&conn);
655 }
656 /*******************************************************************************
657  *
658  * Function         bta_hh_open_act
659  *
660  * Description      HID host receive HID_OPEN_EVT .
661  *
662  *
663  * Returns          void
664  *
665  ******************************************************************************/
bta_hh_open_act(tBTA_HH_DEV_CB * p_cb,const tBTA_HH_DATA * p_data)666 void bta_hh_open_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
667   tBTA_HH_API_CONN conn_data;
668 
669   uint8_t dev_handle =
670       p_data ? (uint8_t)p_data->hid_cback.hdr.layer_specific : p_cb->hid_handle;
671 
672   APPL_TRACE_EVENT("%s:  Device[%d] connected", __func__, dev_handle);
673 
674   /* SDP has been done */
675   if (p_cb->app_id != 0) {
676     bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, p_data);
677   } else
678   /*  app_id == 0 indicates an incoming conenction request arrives without SDP
679    *  performed, do it first
680    */
681   {
682     p_cb->incoming_conn = true;
683     /* store the handle here in case sdp fails - need to disconnect */
684     p_cb->incoming_hid_handle = dev_handle;
685 
686     memset(&conn_data, 0, sizeof(tBTA_HH_API_CONN));
687     conn_data.bd_addr = p_cb->addr;
688     bta_hh_cb.p_cur = p_cb;
689     bta_hh_bredr_conn(p_cb, (tBTA_HH_DATA*)&conn_data);
690   }
691 
692   return;
693 }
694 
695 /*******************************************************************************
696  *
697  * Function         bta_hh_data_act
698  *
699  * Description      HID Host process a data report
700  *
701  *
702  * Returns          void
703  *
704  ******************************************************************************/
bta_hh_data_act(tBTA_HH_DEV_CB * p_cb,const tBTA_HH_DATA * p_data)705 void bta_hh_data_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
706   BT_HDR* pdata = p_data->hid_cback.p_data;
707   uint8_t* p_rpt = (uint8_t*)(pdata + 1) + pdata->offset;
708 
709   bta_hh_co_data((uint8_t)p_data->hid_cback.hdr.layer_specific, p_rpt,
710                  pdata->len, p_cb->mode, p_cb->sub_class,
711                  p_cb->dscp_info.ctry_code, p_cb->addr, p_cb->app_id);
712 
713   osi_free_and_reset((void**)&pdata);
714 }
715 
716 /*******************************************************************************
717  *
718  * Function         bta_hh_handsk_act
719  *
720  * Description      HID Host process a handshake acknowledgement.
721  *
722  *
723  * Returns          void
724  *
725  ******************************************************************************/
bta_hh_handsk_act(tBTA_HH_DEV_CB * p_cb,const tBTA_HH_DATA * p_data)726 void bta_hh_handsk_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
727   APPL_TRACE_DEBUG("HANDSHAKE received for: event = %s data= %d",
728                    bta_hh_get_w4_event(p_cb->w4_evt), p_data->hid_cback.data);
729 
730   tBTA_HH bta_hh;
731   memset(&bta_hh, 0, sizeof(tBTA_HH));
732 
733   switch (p_cb->w4_evt) {
734     /* GET_ transsaction, handshake indicate unsupported request */
735     case BTA_HH_GET_PROTO_EVT:
736       bta_hh.hs_data.rsp_data.proto_mode = BTA_HH_PROTO_UNKNOWN;
737       FALLTHROUGH_INTENDED; /* FALLTHROUGH */
738     case BTA_HH_GET_RPT_EVT:
739     case BTA_HH_GET_IDLE_EVT:
740       bta_hh.hs_data.handle = p_cb->hid_handle;
741       /* if handshake gives an OK code for these transaction, fill in UNSUPT */
742       bta_hh.hs_data.status = bta_hh_get_trans_status(p_data->hid_cback.data);
743       if (bta_hh.hs_data.status == BTA_HH_OK)
744         bta_hh.hs_data.status = BTA_HH_HS_TRANS_NOT_SPT;
745       (*bta_hh_cb.p_cback)(p_cb->w4_evt, &bta_hh);
746       p_cb->w4_evt = 0;
747       break;
748 
749     /* acknoledgement from HID device for SET_ transaction */
750     case BTA_HH_SET_RPT_EVT:
751     case BTA_HH_SET_PROTO_EVT:
752     case BTA_HH_SET_IDLE_EVT:
753       bta_hh.dev_status.handle = p_cb->hid_handle;
754       bta_hh.dev_status.status =
755           bta_hh_get_trans_status(p_data->hid_cback.data);
756       (*bta_hh_cb.p_cback)(p_cb->w4_evt, &bta_hh);
757       p_cb->w4_evt = 0;
758       break;
759 
760     /* SET_PROTOCOL when open connection */
761     case BTA_HH_OPEN_EVT:
762       bta_hh.conn.status =
763           p_data->hid_cback.data ? BTA_HH_ERR_PROTO : BTA_HH_OK;
764       bta_hh.conn.handle = p_cb->hid_handle;
765       bta_hh.conn.bda = p_cb->addr;
766       (*bta_hh_cb.p_cback)(p_cb->w4_evt, &bta_hh);
767       bta_hh_trace_dev_db();
768       p_cb->w4_evt = 0;
769       break;
770 
771     default:
772       /* unknow transaction handshake response */
773       APPL_TRACE_DEBUG("unknown transaction type");
774       break;
775   }
776 
777   /* transaction achknoledgement received, inform PM for mode change */
778   bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
779   return;
780 }
781 /*******************************************************************************
782  *
783  * Function         bta_hh_ctrl_dat_act
784  *
785  * Description      HID Host process a data report from control channel.
786  *
787  *
788  * Returns          void
789  *
790  ******************************************************************************/
bta_hh_ctrl_dat_act(tBTA_HH_DEV_CB * p_cb,const tBTA_HH_DATA * p_data)791 void bta_hh_ctrl_dat_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
792   BT_HDR* pdata = p_data->hid_cback.p_data;
793   uint8_t* data = (uint8_t*)(pdata + 1) + pdata->offset;
794   tBTA_HH_HSDATA hs_data;
795 
796   APPL_TRACE_DEBUG("Ctrl DATA received w4: event[%s]",
797                    bta_hh_get_w4_event(p_cb->w4_evt));
798   if (pdata->len == 0) {
799     p_cb->w4_evt = 0;
800     osi_free_and_reset((void**)&pdata);
801     return;
802   }
803   hs_data.status = BTA_HH_OK;
804   hs_data.handle = p_cb->hid_handle;
805 
806   switch (p_cb->w4_evt) {
807     case BTA_HH_GET_IDLE_EVT:
808       hs_data.rsp_data.idle_rate = *data;
809       break;
810     case BTA_HH_GET_RPT_EVT:
811       hs_data.rsp_data.p_rpt_data = pdata;
812       break;
813     case BTA_HH_GET_PROTO_EVT:
814       /* match up BTE/BTA report/boot mode def*/
815       hs_data.rsp_data.proto_mode = ((*data) == HID_PAR_PROTOCOL_REPORT)
816                                         ? BTA_HH_PROTO_RPT_MODE
817                                         : BTA_HH_PROTO_BOOT_MODE;
818       APPL_TRACE_DEBUG("GET_PROTOCOL Mode = [%s]",
819                        (hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE)
820                            ? "Report"
821                            : "Boot");
822       break;
823     /* should not expect control DATA for SET_ transaction */
824     case BTA_HH_SET_PROTO_EVT:
825       FALLTHROUGH_INTENDED; /* FALLTHROUGH */
826     case BTA_HH_SET_RPT_EVT:
827       FALLTHROUGH_INTENDED; /* FALLTHROUGH */
828     case BTA_HH_SET_IDLE_EVT:
829       FALLTHROUGH_INTENDED; /* FALLTHROUGH */
830     default:
831       APPL_TRACE_DEBUG("invalid  transaction type for DATA payload: 4_evt[%s]",
832                        bta_hh_get_w4_event(p_cb->w4_evt));
833       break;
834   }
835 
836   /* inform PM for mode change */
837   bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
838   bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
839 
840   (*bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH*)&hs_data);
841 
842   p_cb->w4_evt = 0;
843   osi_free_and_reset((void**)&pdata);
844 }
845 
846 /*******************************************************************************
847  *
848  * Function         bta_hh_open_failure
849  *
850  * Description      report HID open failure when at wait for connection state
851  *                  and receive device close event.
852  *
853  *
854  * Returns          void
855  *
856  ******************************************************************************/
bta_hh_open_failure(tBTA_HH_DEV_CB * p_cb,const tBTA_HH_DATA * p_data)857 void bta_hh_open_failure(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
858   tBTA_HH_CONN conn_dat;
859   uint32_t reason = p_data->hid_cback.data; /* Reason for closing (32-bit) */
860 
861   memset(&conn_dat, 0, sizeof(tBTA_HH_CONN));
862   conn_dat.handle = p_cb->hid_handle;
863   conn_dat.status =
864       (reason == HID_ERR_AUTH_FAILED) ? BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
865   conn_dat.bda = p_cb->addr;
866   HID_HostCloseDev(p_cb->hid_handle);
867 
868   /* Report OPEN fail event */
869   (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH*)&conn_dat);
870 
871   bta_hh_trace_dev_db();
872   /* clean up control block, but retain SDP info and device handle */
873   p_cb->vp = false;
874   p_cb->w4_evt = 0;
875 
876   /* if no connection is active and HH disable is signaled, disable service */
877   if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable) {
878     bta_hh_disc_cmpl();
879   }
880 
881   /* Error in opening hid connection, reset flags */
882   p_cb->incoming_conn = false;
883   p_cb->incoming_hid_handle = BTA_HH_INVALID_HANDLE;
884 }
885 
886 /*******************************************************************************
887  *
888  * Function         bta_hh_close_act
889  *
890  * Description      HID Host process a close event
891  *
892  *
893  * Returns          void
894  *
895  ******************************************************************************/
bta_hh_close_act(tBTA_HH_DEV_CB * p_cb,const tBTA_HH_DATA * p_data)896 void bta_hh_close_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
897   tBTA_HH_CONN conn_dat;
898   tBTA_HH_CBDATA disc_dat = {BTA_HH_OK, 0};
899 
900   uint32_t reason = p_data->hid_cback.data; /* Reason for closing (32-bit) */
901   const bool l2cap_conn_fail = reason & HID_L2CAP_CONN_FAIL;
902   const bool l2cap_req_fail = reason & HID_L2CAP_REQ_FAIL;
903   const bool l2cap_cfg_fail = reason & HID_L2CAP_CFG_FAIL;
904   const tHID_STATUS hid_status = static_cast<tHID_STATUS>(reason & 0xff);
905 
906   /* if HID_HDEV_EVT_VC_UNPLUG was received, report BTA_HH_VC_UNPLUG_EVT */
907   uint16_t event = p_cb->vp ? BTA_HH_VC_UNPLUG_EVT : BTA_HH_CLOSE_EVT;
908 
909   disc_dat.handle = p_cb->hid_handle;
910   disc_dat.status = to_bta_hh_status(p_data->hid_cback.data);
911 
912   std::string overlay_fail =
913       base::StringPrintf("%s %s %s", (l2cap_conn_fail) ? "l2cap_conn_fail" : "",
914                          (l2cap_req_fail) ? "l2cap_req_fail" : "",
915                          (l2cap_cfg_fail) ? "l2cap_cfg_fail" : "");
916   BTM_LogHistory(kBtmLogTag, p_cb->addr, "Closed",
917                  base::StringPrintf("%s reason %s %s",
918                                     (p_cb->is_le_device) ? "le" : "classic",
919                                     hid_status_text(hid_status).c_str(),
920                                     overlay_fail.c_str()));
921 
922   /* Check reason for closing */
923   if ((reason & (HID_L2CAP_CONN_FAIL |
924                  HID_L2CAP_REQ_FAIL)) || /* Failure to initialize connection
925                                             (page timeout or l2cap error) */
926       (reason ==
927        HID_ERR_AUTH_FAILED) || /* Authenication error (while initiating) */
928       (reason == HID_ERR_L2CAP_FAILED)) /* Failure creating l2cap connection */
929   {
930     /* Failure in opening connection */
931     conn_dat.handle = p_cb->hid_handle;
932     conn_dat.status =
933         (reason == HID_ERR_AUTH_FAILED) ? BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
934     conn_dat.bda = p_cb->addr;
935     HID_HostCloseDev(p_cb->hid_handle);
936 
937     /* Report OPEN fail event */
938     (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH*)&conn_dat);
939 
940     bta_hh_trace_dev_db();
941     return;
942   }
943   /* otherwise report CLOSE/VC_UNPLUG event */
944   else {
945     /* inform role manager */
946     bta_sys_conn_close(BTA_ID_HH, p_cb->app_id, p_cb->addr);
947     /* update total conn number */
948     bta_hh_cb.cnt_num--;
949 
950     if (disc_dat.status) disc_dat.status = BTA_HH_ERR;
951 
952     (*bta_hh_cb.p_cback)(event, (tBTA_HH*)&disc_dat);
953 
954     /* if virtually unplug, remove device */
955     if (p_cb->vp) {
956       HID_HostRemoveDev(p_cb->hid_handle);
957       bta_hh_clean_up_kdev(p_cb);
958     }
959 
960     bta_hh_trace_dev_db();
961   }
962 
963   /* clean up control block, but retain SDP info and device handle */
964   p_cb->vp = false;
965   p_cb->w4_evt = 0;
966 
967   /* if no connection is active and HH disable is signaled, disable service */
968   if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable) {
969     bta_hh_disc_cmpl();
970   }
971 
972   return;
973 }
974 
975 /*******************************************************************************
976  *
977  * Function         bta_hh_get_dscp_act
978  *
979  * Description      Get device report descriptor
980  *
981  *
982  * Returns          void
983  *
984  ******************************************************************************/
bta_hh_get_dscp_act(tBTA_HH_DEV_CB * p_cb,UNUSED_ATTR const tBTA_HH_DATA * p_data)985 void bta_hh_get_dscp_act(tBTA_HH_DEV_CB* p_cb,
986                          UNUSED_ATTR const tBTA_HH_DATA* p_data) {
987   if (p_cb->is_le_device) {
988     if (p_cb->hid_srvc.state >= BTA_HH_SERVICE_DISCOVERED) {
989       p_cb->dscp_info.hid_handle = p_cb->hid_handle;
990     }
991     bta_hh_le_get_dscp_act(p_cb);
992   } else {
993     p_cb->dscp_info.hid_handle = p_cb->hid_handle;
994     (*bta_hh_cb.p_cback)(BTA_HH_GET_DSCP_EVT, (tBTA_HH*)&p_cb->dscp_info);
995   }
996 }
997 
998 /*******************************************************************************
999  *
1000  * Function         bta_hh_maint_dev_act
1001  *
1002  * Description      HID Host maintain device list.
1003  *
1004  *
1005  * Returns          void
1006  *
1007  ******************************************************************************/
bta_hh_maint_dev_act(tBTA_HH_DEV_CB * p_cb,const tBTA_HH_DATA * p_data)1008 void bta_hh_maint_dev_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
1009   const tBTA_HH_MAINT_DEV* p_dev_info = &p_data->api_maintdev;
1010   tBTA_HH_DEV_INFO dev_info;
1011   uint8_t dev_handle;
1012 
1013   dev_info.status = BTA_HH_ERR;
1014   dev_info.handle = BTA_HH_INVALID_HANDLE;
1015 
1016   switch (p_dev_info->sub_event) {
1017     case BTA_HH_ADD_DEV_EVT: /* add a device */
1018       dev_info.bda = p_dev_info->bda;
1019       /* initialize callback data */
1020       if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE) {
1021         if (BTM_UseLeLink(p_data->api_conn.bd_addr)) {
1022           p_cb->is_le_device = true;
1023           dev_info.handle = bta_hh_le_add_device(p_cb, p_dev_info);
1024           if (dev_info.handle != BTA_HH_INVALID_HANDLE)
1025             dev_info.status = BTA_HH_OK;
1026         } else
1027 
1028             if (HID_HostAddDev(p_dev_info->bda, p_dev_info->attr_mask,
1029                                &dev_handle) == HID_SUCCESS) {
1030           dev_info.handle = dev_handle;
1031           dev_info.status = BTA_HH_OK;
1032 
1033           /* update DI information */
1034           bta_hh_update_di_info(
1035               p_cb, p_dev_info->dscp_info.vendor_id,
1036               p_dev_info->dscp_info.product_id, p_dev_info->dscp_info.version,
1037               p_dev_info->dscp_info.flag, p_dev_info->dscp_info.ctry_code);
1038 
1039           /* add to BTA device list */
1040           bta_hh_add_device_to_list(
1041               p_cb, dev_handle, p_dev_info->attr_mask,
1042               &p_dev_info->dscp_info.descriptor, p_dev_info->sub_class,
1043               p_dev_info->dscp_info.ssr_max_latency,
1044               p_dev_info->dscp_info.ssr_min_tout, p_dev_info->app_id);
1045           /* update cb_index[] map */
1046           bta_hh_cb.cb_index[dev_handle] = p_cb->index;
1047         }
1048       } else /* device already been added */
1049       {
1050         dev_info.handle = p_cb->hid_handle;
1051         dev_info.status = BTA_HH_OK;
1052       }
1053       bta_hh_trace_dev_db();
1054 
1055       break;
1056     case BTA_HH_RMV_DEV_EVT: /* remove device */
1057       dev_info.handle = (uint8_t)p_dev_info->hdr.layer_specific;
1058       dev_info.bda = p_cb->addr;
1059 
1060       if (p_cb->is_le_device) {
1061         bta_hh_le_remove_dev_bg_conn(p_cb);
1062         bta_hh_sm_execute(p_cb, BTA_HH_API_CLOSE_EVT, NULL);
1063         bta_hh_clean_up_kdev(p_cb);
1064       } else
1065       {
1066         if (HID_HostRemoveDev(dev_info.handle) == HID_SUCCESS) {
1067           dev_info.status = BTA_HH_OK;
1068 
1069           /* remove from known device list in BTA */
1070           bta_hh_clean_up_kdev(p_cb);
1071         }
1072       }
1073       break;
1074 
1075     default:
1076       APPL_TRACE_DEBUG("invalid command");
1077       break;
1078   }
1079 
1080   (*bta_hh_cb.p_cback)(p_dev_info->sub_event, (tBTA_HH*)&dev_info);
1081 }
1082 /*******************************************************************************
1083  *
1084  * Function         bta_hh_write_dev_act
1085  *
1086  * Description      Write device action. can be SET/GET/DATA transaction.
1087  *
1088  * Returns          void
1089  *
1090  ******************************************************************************/
convert_api_sndcmd_param(const tBTA_HH_CMD_DATA & api_sndcmd)1091 static uint8_t convert_api_sndcmd_param(const tBTA_HH_CMD_DATA& api_sndcmd) {
1092   uint8_t api_sndcmd_param = api_sndcmd.param;
1093   if (api_sndcmd.t_type == HID_TRANS_SET_PROTOCOL) {
1094     api_sndcmd_param = (api_sndcmd.param == BTA_HH_PROTO_RPT_MODE)
1095                            ? HID_PAR_PROTOCOL_REPORT
1096                            : HID_PAR_PROTOCOL_BOOT_MODE;
1097   }
1098   return api_sndcmd_param;
1099 }
1100 
bta_hh_write_dev_act(tBTA_HH_DEV_CB * p_cb,const tBTA_HH_DATA * p_data)1101 void bta_hh_write_dev_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) {
1102   uint16_t event =
1103       (p_data->api_sndcmd.t_type - HID_TRANS_GET_REPORT) + BTA_HH_GET_RPT_EVT;
1104 
1105   if (p_cb->is_le_device)
1106     bta_hh_le_write_dev_act(p_cb, p_data);
1107   else {
1108     /* match up BTE/BTA report/boot mode def */
1109     const uint8_t api_sndcmd_param =
1110         convert_api_sndcmd_param(p_data->api_sndcmd);
1111 
1112     tHID_STATUS status = HID_HostWriteDev(p_cb->hid_handle,
1113                                           p_data->api_sndcmd.t_type,
1114                                           api_sndcmd_param,
1115                                           p_data->api_sndcmd.data,
1116                                           p_data->api_sndcmd.rpt_id,
1117                                           p_data->api_sndcmd.p_data);
1118     if (status != HID_SUCCESS) {
1119       LOG_ERROR("HID_HostWriteDev Error, status: %d", status);
1120 
1121       if (p_data->api_sndcmd.t_type != HID_TRANS_CONTROL &&
1122           p_data->api_sndcmd.t_type != HID_TRANS_DATA) {
1123         BT_HDR cbhdr = {
1124           .event = BTA_HH_GET_RPT_EVT,
1125           .len = 0,
1126           .offset = 0,
1127           .layer_specific = 0,
1128         };
1129         tBTA_HH cbdata = {
1130           .hs_data = {
1131             .status = BTA_HH_ERR,
1132             .handle = p_cb->hid_handle,
1133             .rsp_data = {
1134               .p_rpt_data = &cbhdr,
1135             },
1136           },
1137         };
1138         (*bta_hh_cb.p_cback)(event, &cbdata);
1139       } else if (api_sndcmd_param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG) {
1140         tBTA_HH cbdata = {
1141           .dev_status = {
1142             .status = BTA_HH_ERR,
1143             .handle = p_cb->hid_handle,
1144           },
1145         };
1146         (*bta_hh_cb.p_cback)(BTA_HH_VC_UNPLUG_EVT, &cbdata);
1147       } else {
1148         LOG_ERROR("skipped executing callback in hid host error handling. "
1149                   "command type: %d, param: %d", p_data->api_sndcmd.t_type,
1150                   p_data->api_sndcmd.param);
1151       }
1152     } else {
1153       switch (p_data->api_sndcmd.t_type) {
1154         case HID_TRANS_SET_PROTOCOL:
1155           FALLTHROUGH_INTENDED; /* FALLTHROUGH */
1156         case HID_TRANS_GET_REPORT:
1157           FALLTHROUGH_INTENDED; /* FALLTHROUGH */
1158         case HID_TRANS_SET_REPORT:
1159           FALLTHROUGH_INTENDED; /* FALLTHROUGH */
1160         case HID_TRANS_GET_PROTOCOL:
1161           FALLTHROUGH_INTENDED; /* FALLTHROUGH */
1162         case HID_TRANS_GET_IDLE:
1163           FALLTHROUGH_INTENDED;  /* FALLTHROUGH */
1164         case HID_TRANS_SET_IDLE: /* set w4_handsk event name for callback
1165                                     function use */
1166           p_cb->w4_evt = event;
1167           break;
1168         case HID_TRANS_DATA: /* output report */
1169           FALLTHROUGH_INTENDED; /* FALLTHROUGH */
1170         case HID_TRANS_CONTROL:
1171           /* no handshake event will be generated */
1172           /* if VC_UNPLUG is issued, set flag */
1173           if (api_sndcmd_param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG)
1174             p_cb->vp = true;
1175 
1176           break;
1177         /* currently not expected */
1178         case HID_TRANS_DATAC:
1179         default:
1180           APPL_TRACE_DEBUG("%s: cmd type = %d", __func__,
1181                            p_data->api_sndcmd.t_type);
1182           break;
1183       }
1184 
1185       /* if not control type transaction, notify PM for energy control */
1186       if (p_data->api_sndcmd.t_type != HID_TRANS_CONTROL) {
1187         /* inform PM for mode change */
1188         bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
1189         bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
1190       } else if (api_sndcmd_param == BTA_HH_CTRL_SUSPEND) {
1191         bta_sys_sco_close(BTA_ID_HH, p_cb->app_id, p_cb->addr);
1192       } else if (api_sndcmd_param == BTA_HH_CTRL_EXIT_SUSPEND) {
1193         bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
1194       }
1195     }
1196   }
1197   return;
1198 }
1199 
1200 /*****************************************************************************
1201  *  Static Function
1202  ****************************************************************************/
1203 /*******************************************************************************
1204  *
1205  * Function         bta_hh_cback
1206  *
1207  * Description      BTA HH callback function.
1208  *
1209  *
1210  * Returns          void
1211  *
1212  ******************************************************************************/
bta_hh_cback(uint8_t dev_handle,const RawAddress & addr,uint8_t event,uint32_t data,BT_HDR * pdata)1213 static void bta_hh_cback(uint8_t dev_handle, const RawAddress& addr,
1214                          uint8_t event, uint32_t data, BT_HDR* pdata) {
1215   uint16_t sm_event = BTA_HH_INVALID_EVT;
1216   uint8_t xx = 0;
1217 
1218   APPL_TRACE_DEBUG("%s::HID_event [%s]", __func__,
1219                    bta_hh_hid_event_name(event));
1220 
1221   switch (event) {
1222     case HID_HDEV_EVT_OPEN:
1223       sm_event = BTA_HH_INT_OPEN_EVT;
1224       break;
1225     case HID_HDEV_EVT_CLOSE:
1226       sm_event = BTA_HH_INT_CLOSE_EVT;
1227       break;
1228     case HID_HDEV_EVT_INTR_DATA:
1229       sm_event = BTA_HH_INT_DATA_EVT;
1230       break;
1231     case HID_HDEV_EVT_HANDSHAKE:
1232       sm_event = BTA_HH_INT_HANDSK_EVT;
1233       break;
1234     case HID_HDEV_EVT_CTRL_DATA:
1235       sm_event = BTA_HH_INT_CTRL_DATA;
1236       break;
1237     case HID_HDEV_EVT_RETRYING:
1238       break;
1239     case HID_HDEV_EVT_INTR_DATC:
1240     case HID_HDEV_EVT_CTRL_DATC:
1241       /* Unhandled events: Free buffer for DATAC */
1242       osi_free_and_reset((void**)&pdata);
1243       break;
1244     case HID_HDEV_EVT_VC_UNPLUG:
1245       for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++) {
1246         if (bta_hh_cb.kdev[xx].hid_handle == dev_handle) {
1247           bta_hh_cb.kdev[xx].vp = true;
1248           break;
1249         }
1250       }
1251       break;
1252   }
1253 
1254   if (sm_event != BTA_HH_INVALID_EVT) {
1255     tBTA_HH_CBACK_DATA* p_buf = (tBTA_HH_CBACK_DATA*)osi_malloc(
1256         sizeof(tBTA_HH_CBACK_DATA) + sizeof(BT_HDR));
1257     p_buf->hdr.event = sm_event;
1258     p_buf->hdr.layer_specific = (uint16_t)dev_handle;
1259     p_buf->data = data;
1260     p_buf->addr = addr;
1261     p_buf->p_data = pdata;
1262 
1263     bta_sys_sendmsg(p_buf);
1264   }
1265 }
1266 
1267 /*******************************************************************************
1268  *
1269  * Function         bta_hh_get_trans_status
1270  *
1271  * Description      translate a handshake result code into BTA HH
1272  *                  status code
1273  *
1274  ******************************************************************************/
bta_hh_get_trans_status(uint32_t result)1275 static tBTA_HH_STATUS bta_hh_get_trans_status(uint32_t result) {
1276   switch (result) {
1277     case HID_PAR_HANDSHAKE_RSP_SUCCESS: /*   (0) */
1278       return BTA_HH_OK;
1279     case HID_PAR_HANDSHAKE_RSP_NOT_READY:           /*   (1) */
1280     case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID:  /*   (2) */
1281     case HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ: /*   (3) */
1282     case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM:   /*   (4) */
1283       return (tBTA_HH_STATUS)result;
1284     case HID_PAR_HANDSHAKE_RSP_ERR_UNKNOWN: /*   (14) */
1285     case HID_PAR_HANDSHAKE_RSP_ERR_FATAL:   /*   (15) */
1286     default:
1287       return BTA_HH_HS_ERROR;
1288       break;
1289   }
1290 }
1291 /*****************************************************************************
1292  *  Debug Functions
1293  ****************************************************************************/
1294 
bta_hh_get_w4_event(uint16_t event)1295 static const char* bta_hh_get_w4_event(uint16_t event) {
1296   switch (event) {
1297     case BTA_HH_GET_RPT_EVT:
1298       return "BTA_HH_GET_RPT_EVT";
1299     case BTA_HH_SET_RPT_EVT:
1300       return "BTA_HH_SET_RPT_EVT";
1301     case BTA_HH_GET_PROTO_EVT:
1302       return "BTA_HH_GET_PROTO_EVT";
1303     case BTA_HH_SET_PROTO_EVT:
1304       return "BTA_HH_SET_PROTO_EVT";
1305     case BTA_HH_GET_IDLE_EVT:
1306       return "BTA_HH_GET_IDLE_EVT";
1307     case BTA_HH_SET_IDLE_EVT:
1308       return "BTA_HH_SET_IDLE_EVT";
1309     case BTA_HH_OPEN_EVT:
1310       return "BTA_HH_OPEN_EVT";
1311     default:
1312       return "Unknown event";
1313   }
1314 }
1315 
bta_hh_hid_event_name(uint16_t event)1316 static const char* bta_hh_hid_event_name(uint16_t event) {
1317   switch (event) {
1318     case HID_HDEV_EVT_OPEN:
1319       return "HID_HDEV_EVT_OPEN";
1320     case HID_HDEV_EVT_CLOSE:
1321       return "HID_HDEV_EVT_CLOSE";
1322     case HID_HDEV_EVT_RETRYING:
1323       return "HID_HDEV_EVT_RETRYING";
1324     case HID_HDEV_EVT_INTR_DATA:
1325       return "HID_HDEV_EVT_INTR_DATA";
1326     case HID_HDEV_EVT_INTR_DATC:
1327       return "HID_HDEV_EVT_INTR_DATC";
1328     case HID_HDEV_EVT_CTRL_DATA:
1329       return "HID_HDEV_EVT_CTRL_DATA";
1330     case HID_HDEV_EVT_CTRL_DATC:
1331       return "HID_HDEV_EVT_CTRL_DATC";
1332     case HID_HDEV_EVT_HANDSHAKE:
1333       return "HID_HDEV_EVT_HANDSHAKE";
1334     case HID_HDEV_EVT_VC_UNPLUG:
1335       return "HID_HDEV_EVT_VC_UNPLUG";
1336     default:
1337       return "Unknown HID event";
1338   }
1339 }
1340