1 /******************************************************************************
2  *
3  *  Copyright 2002-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 connection interface functions
22  *
23  ******************************************************************************/
24 
25 #include <base/functional/callback.h>
26 #include <base/strings/stringprintf.h>
27 #include <bluetooth/log.h>
28 #include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
29 #include <string.h>
30 
31 #include "bta/include/bta_sec_api.h"
32 #include "hiddefs.h"
33 #include "hidh_api.h"
34 #include "hidh_int.h"
35 #include "internal_include/bt_target.h"
36 #include "l2c_api.h"
37 #include "l2cdefs.h"
38 #include "osi/include/allocator.h"
39 #include "osi/include/osi.h"
40 #include "stack/include/acl_api.h"
41 #include "stack/include/bt_hdr.h"
42 #include "stack/include/bt_psm_types.h"
43 #include "stack/include/btm_log_history.h"
44 #include "stack/include/stack_metrics_logging.h"
45 #include "types/raw_address.h"
46 
47 using namespace bluetooth;
48 
49 namespace {
50 constexpr char kBtmLogTag[] = "HIDH";
51 constexpr uint8_t kHID_HOST_MAX_DEVICES = HID_HOST_MAX_DEVICES;
52 }
53 
54 static uint8_t find_conn_by_cid(uint16_t cid);
55 static void hidh_conn_retry(uint8_t dhandle);
56 
57 /******************************************************************************/
58 /*            L O C A L    F U N C T I O N     P R O T O T Y P E S            */
59 /******************************************************************************/
60 static void hidh_l2cif_connect_ind(const RawAddress& bd_addr,
61                                    uint16_t l2cap_cid, uint16_t psm,
62                                    uint8_t l2cap_id);
63 static void hidh_l2cif_connect_cfm(uint16_t l2cap_cid, uint16_t result);
64 static void hidh_l2cif_config_ind(uint16_t l2cap_cid, tL2CAP_CFG_INFO* p_cfg);
65 static void hidh_l2cif_config_cfm(uint16_t l2cap_cid, uint16_t result,
66                                   tL2CAP_CFG_INFO* p_cfg);
67 static void hidh_l2cif_disconnect_ind(uint16_t l2cap_cid, bool ack_needed);
68 static void hidh_l2cif_data_ind(uint16_t l2cap_cid, BT_HDR* p_msg);
69 static void hidh_l2cif_disconnect(uint16_t l2cap_cid);
70 static void hidh_l2cif_cong_ind(uint16_t l2cap_cid, bool congested);
71 static void hidh_on_l2cap_error(uint16_t l2cap_cid, uint16_t result);
72 
73 static const tL2CAP_APPL_INFO hst_reg_info = {
74     .pL2CA_ConnectInd_Cb = hidh_l2cif_connect_ind,
75     .pL2CA_ConnectCfm_Cb = hidh_l2cif_connect_cfm,
76     .pL2CA_ConfigInd_Cb = hidh_l2cif_config_ind,
77     .pL2CA_ConfigCfm_Cb = hidh_l2cif_config_cfm,
78     .pL2CA_DisconnectInd_Cb = hidh_l2cif_disconnect_ind,
79     .pL2CA_DataInd_Cb = hidh_l2cif_data_ind,
80     .pL2CA_CongestionStatus_Cb = hidh_l2cif_cong_ind,
81     .pL2CA_TxComplete_Cb = nullptr,
82     .pL2CA_Error_Cb = hidh_on_l2cap_error,
83     .pL2CA_CreditBasedConnectInd_Cb = nullptr,
84     .pL2CA_CreditBasedConnectCfm_Cb = nullptr,
85     .pL2CA_CreditBasedReconfigCompleted_Cb = nullptr,
86     .pL2CA_CreditBasedCollisionInd_Cb = nullptr,
87 };
88 static void hidh_try_repage(uint8_t dhandle);
89 
90 /*******************************************************************************
91  *
92  * Function         hidh_l2cif_reg
93  *
94  * Description      This function initializes the SDP unit.
95  *
96  * Returns          void
97  *
98  ******************************************************************************/
hidh_conn_reg(void)99 tHID_STATUS hidh_conn_reg(void) {
100   int xx;
101 
102   /* Initialize the L2CAP configuration. We only care about MTU and flush */
103   memset(&hh_cb.l2cap_cfg, 0, sizeof(tL2CAP_CFG_INFO));
104 
105   hh_cb.l2cap_cfg.mtu_present = true;
106   hh_cb.l2cap_cfg.mtu = HID_HOST_MTU;
107 
108   /* Now, register with L2CAP */
109   if (!L2CA_RegisterWithSecurity(
110           HID_PSM_CONTROL, hst_reg_info, false /* enable_snoop */, nullptr,
111           HID_HOST_MTU, 0, BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)) {
112     log::error("HID-Host Control Registration failed");
113     log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
114                             HIDH_ERR_L2CAP_FAILED_AT_REGISTER_CONTROL,
115                         1);
116     return (HID_ERR_L2CAP_FAILED);
117   }
118   if (!L2CA_RegisterWithSecurity(
119           HID_PSM_INTERRUPT, hst_reg_info, false /* enable_snoop */, nullptr,
120           HID_HOST_MTU, 0, BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)) {
121     L2CA_Deregister(HID_PSM_CONTROL);
122     log::error("HID-Host Interrupt Registration failed");
123     log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
124                             HIDH_ERR_L2CAP_FAILED_AT_REGISTER_INTERRUPT,
125                         1);
126     return (HID_ERR_L2CAP_FAILED);
127   }
128 
129   for (xx = 0; xx < kHID_HOST_MAX_DEVICES; xx++) {
130     hh_cb.devices[xx].in_use = false;
131     hh_cb.devices[xx].conn.conn_state = HID_CONN_STATE_UNUSED;
132   }
133 
134   return (HID_SUCCESS);
135 }
136 
137 /*******************************************************************************
138  *
139  * Function         hidh_conn_disconnect
140  *
141  * Description      This function disconnects a connection.
142  *
143  * Returns          true if disconnect started, false if already disconnected
144  *
145  ******************************************************************************/
hidh_conn_disconnect(uint8_t dhandle)146 tHID_STATUS hidh_conn_disconnect(uint8_t dhandle) {
147   tHID_CONN* p_hcon = &hh_cb.devices[dhandle].conn;
148 
149   if ((p_hcon->ctrl_cid != 0) || (p_hcon->intr_cid != 0)) {
150     p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING;
151 
152     /* Set l2cap idle timeout to 0 (so ACL link is disconnected
153      * immediately after last channel is closed) */
154     if (!L2CA_SetIdleTimeoutByBdAddr(hh_cb.devices[dhandle].addr, 0,
155                                      BT_TRANSPORT_BR_EDR)) {
156       log::warn("Unable to set L2CAP idle timeout peer:{}",
157                 hh_cb.devices[dhandle].addr);
158     }
159     /* Disconnect both interrupt and control channels */
160     if (p_hcon->intr_cid)
161       hidh_l2cif_disconnect(p_hcon->intr_cid);
162     else if (p_hcon->ctrl_cid)
163       hidh_l2cif_disconnect(p_hcon->ctrl_cid);
164 
165     BTM_LogHistory(kBtmLogTag, hh_cb.devices[dhandle].addr, "Disconnecting",
166                    "local initiated");
167   } else {
168     p_hcon->conn_state = HID_CONN_STATE_UNUSED;
169   }
170   return HID_SUCCESS;
171 }
172 
173 /*******************************************************************************
174  *
175  * Function         hidh_l2cif_connect_ind
176  *
177  * Description      This function handles an inbound connection indication
178  *                  from L2CAP. This is the case where we are acting as a
179  *                  server.
180  *
181  * Returns          void
182  *
183  ******************************************************************************/
hidh_l2cif_connect_ind(const RawAddress & bd_addr,uint16_t l2cap_cid,uint16_t psm,uint8_t l2cap_id)184 static void hidh_l2cif_connect_ind(const RawAddress& bd_addr,
185                                    uint16_t l2cap_cid, uint16_t psm,
186                                    uint8_t l2cap_id) {
187   bool bAccept = true;
188   uint8_t i = kHID_HOST_MAX_DEVICES;
189 
190   log::verbose("HID-Host Rcvd L2CAP conn ind, PSM: 0x{:04x}  CID 0x{:x}", psm,
191                l2cap_cid);
192 
193   /* always add incoming connection device into HID database by default */
194   if (HID_HostAddDev(bd_addr, HID_SEC_REQUIRED, &i) != HID_SUCCESS) {
195     if (!L2CA_DisconnectReq(l2cap_cid)) {
196       log::warn("Unable to send L2CAP disconnect request peer:{} cid:{}",
197                 bd_addr, l2cap_cid);
198     }
199     return;
200   }
201 
202   tHID_CONN* p_hcon = &hh_cb.devices[i].conn;
203 
204   BTM_LogHistory(
205       kBtmLogTag, hh_cb.devices[i].addr, "Connect request",
206       base::StringPrintf("%s state:%s",
207                          (psm == HID_PSM_CONTROL) ? "control" : "interrupt",
208                          hid_conn::state_text(p_hcon->conn_state).c_str()));
209 
210   /* Check we are in the correct state for this */
211   if (psm == HID_PSM_INTERRUPT) {
212     if (p_hcon->ctrl_cid == 0) {
213       log::warn("HID-Host Rcvd INTR L2CAP conn ind, but no CTL channel");
214       bAccept = false;
215     }
216     if (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) {
217       log::warn("HID-Host Rcvd INTR L2CAP conn ind, wrong state: {}",
218                 p_hcon->conn_state);
219       bAccept = false;
220     }
221   } else /* CTRL channel */
222   {
223 #if (HID_HOST_ACPT_NEW_CONN == TRUE)
224     p_hcon->ctrl_cid = p_hcon->intr_cid = 0;
225     p_hcon->conn_state = HID_CONN_STATE_UNUSED;
226 #else
227     if (p_hcon->conn_state != HID_CONN_STATE_UNUSED) {
228       log::warn("HID-Host - Rcvd CTL L2CAP conn ind, wrong state: {}",
229                 p_hcon->conn_state);
230       bAccept = false;
231     }
232 #endif
233   }
234 
235   if (!bAccept) {
236     if (!L2CA_DisconnectReq(l2cap_cid)) {
237       log::warn("Unable to send L2CAP disconnect request peer:{} cid:{}",
238                 bd_addr, l2cap_cid);
239     }
240     return;
241   }
242 
243   if (psm == HID_PSM_CONTROL) {
244     p_hcon->conn_flags = 0;
245     p_hcon->ctrl_cid = l2cap_cid;
246     p_hcon->disc_reason = HID_SUCCESS; /* Authentication passed. Reset
247                                               disc_reason (from
248                                               HID_ERR_AUTH_FAILED) */
249     p_hcon->conn_state = HID_CONN_STATE_CONNECTING_INTR;
250     BTM_LogHistory(kBtmLogTag, hh_cb.devices[i].addr, "Connecting",
251                    "waiting for interrupt channel");
252     return;
253   }
254 
255   /* Transition to the next appropriate state, configuration */
256   p_hcon->conn_state = HID_CONN_STATE_CONFIG;
257   p_hcon->intr_cid = l2cap_cid;
258 
259   log::verbose(
260       "HID-Host Rcvd L2CAP conn ind, sent config req, PSM: 0x{:04x}  CID "
261       "0x{:x}",
262       psm, l2cap_cid);
263 }
264 
hidh_process_repage_timer_timeout(void * data)265 static void hidh_process_repage_timer_timeout(void* data) {
266   uint8_t dhandle = PTR_TO_UINT(data);
267   hidh_try_repage(dhandle);
268 }
269 
270 /*******************************************************************************
271  *
272  * Function         hidh_try_repage
273  *
274  * Description      This function processes timeout (to page device).
275  *
276  * Returns          void
277  *
278  ******************************************************************************/
hidh_try_repage(uint8_t dhandle)279 static void hidh_try_repage(uint8_t dhandle) {
280   tHID_HOST_DEV_CTB* device;
281 
282   hidh_conn_initiate(dhandle);
283 
284   device = &hh_cb.devices[dhandle];
285   device->conn_tries++;
286 
287   hh_cb.callback(dhandle, device->addr, HID_HDEV_EVT_RETRYING,
288                  device->conn_tries, NULL);
289 }
290 
hidh_on_l2cap_error(uint16_t l2cap_cid,uint16_t result)291 static void hidh_on_l2cap_error(uint16_t l2cap_cid, uint16_t result) {
292   auto dhandle = find_conn_by_cid(l2cap_cid);
293   if (dhandle == kHID_HOST_MAX_DEVICES) {
294     log::warn("Received error for unknown device cid:0x{:04x} reason:{}",
295               l2cap_cid, hci_reason_code_text(to_hci_reason_code(result)));
296     return;
297   }
298 
299   hidh_conn_disconnect(dhandle);
300 
301   if (result != L2CAP_CFG_FAILED_NO_REASON) {
302 #if (HID_HOST_MAX_CONN_RETRY > 0)
303     if ((hh_cb.devices[dhandle].conn_tries <= HID_HOST_MAX_CONN_RETRY) &&
304         (result == HCI_ERR_CONNECTION_TOUT || result == HCI_ERR_UNSPECIFIED ||
305          result == HCI_ERR_PAGE_TIMEOUT)) {
306       hidh_conn_retry(dhandle);
307     } else
308 #endif
309     {
310       uint32_t reason = HID_L2CAP_CONN_FAIL | (uint32_t)result;
311       hh_cb.callback(dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE,
312                      reason, NULL);
313     }
314   } else {
315     uint32_t reason = HID_L2CAP_CFG_FAIL | (uint32_t)result;
316     hh_cb.callback(dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE,
317                    reason, NULL);
318   }
319 }
320 
321 /*******************************************************************************
322  *
323  * Function         hidh_l2cif_connect_cfm
324  *
325  * Description      This function handles the connect confirm events
326  *                  from L2CAP. This is the case when we are acting as a
327  *                  client and have sent a connect request.
328  *
329  * Returns          void
330  *
331  ******************************************************************************/
hidh_l2cif_connect_cfm(uint16_t l2cap_cid,uint16_t result)332 static void hidh_l2cif_connect_cfm(uint16_t l2cap_cid, uint16_t result) {
333   uint8_t dhandle;
334   tHID_CONN* p_hcon = NULL;
335 
336   /* Find CCB based on CID, and verify we are in a state to accept this message
337    */
338   dhandle = find_conn_by_cid(l2cap_cid);
339   if (dhandle < kHID_HOST_MAX_DEVICES) {
340     p_hcon = &hh_cb.devices[dhandle].conn;
341   }
342 
343   if ((p_hcon == NULL) || (!(p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG)) ||
344       ((l2cap_cid == p_hcon->ctrl_cid) &&
345        (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_CTRL)) ||
346       ((l2cap_cid == p_hcon->intr_cid) &&
347        (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) &&
348        (p_hcon->conn_state != HID_CONN_STATE_DISCONNECTING))) {
349     log::warn("HID-Host Rcvd unexpected conn cnf, CID 0x{:x}", l2cap_cid);
350     return;
351   }
352 
353   if (result != L2CAP_CONN_OK) {
354     // TODO: We need to provide the real HCI status if we want to retry.
355     log::error("invoked with non OK status");
356     return;
357   }
358   /* receive Control Channel connect confirmation */
359   if (l2cap_cid == p_hcon->ctrl_cid) {
360     /* check security requirement */
361     p_hcon->disc_reason = HID_SUCCESS; /* Authentication passed. Reset
362                                               disc_reason (from
363                                               HID_ERR_AUTH_FAILED) */
364 
365     /* Transition to the next appropriate state, configuration */
366     p_hcon->conn_state = HID_CONN_STATE_CONFIG;
367   } else {
368     p_hcon->conn_state = HID_CONN_STATE_CONFIG;
369   }
370   BTM_LogHistory(
371       kBtmLogTag, hh_cb.devices[dhandle].addr, "Configuring",
372       base::StringPrintf("control:0x%04x interrupt:0x%04x state:%s",
373                          p_hcon->ctrl_cid, p_hcon->intr_cid,
374                          hid_conn::state_text(p_hcon->conn_state).c_str()));
375   return;
376 }
377 
378 /*******************************************************************************
379  *
380  * Function         hidh_l2cif_config_ind
381  *
382  * Description      This function processes the L2CAP configuration indication
383  *                  event.
384  *
385  * Returns          void
386  *
387  ******************************************************************************/
hidh_l2cif_config_ind(uint16_t l2cap_cid,tL2CAP_CFG_INFO * p_cfg)388 static void hidh_l2cif_config_ind(uint16_t l2cap_cid, tL2CAP_CFG_INFO* p_cfg) {
389   uint8_t dhandle;
390   tHID_CONN* p_hcon = NULL;
391 
392   /* Find CCB based on CID */
393   dhandle = find_conn_by_cid(l2cap_cid);
394   if (dhandle < kHID_HOST_MAX_DEVICES) {
395     p_hcon = &hh_cb.devices[dhandle].conn;
396   }
397 
398   if (p_hcon == NULL) {
399     log::warn("HID-Host Rcvd L2CAP cfg ind, unknown CID: 0x{:x}", l2cap_cid);
400     return;
401   }
402 
403   log::verbose("HID-Host Rcvd cfg ind, sent cfg cfm, CID: 0x{:x}", l2cap_cid);
404 
405   /* Remember the remote MTU size */
406   if ((!p_cfg->mtu_present) || (p_cfg->mtu > HID_HOST_MTU))
407     p_hcon->rem_mtu_size = HID_HOST_MTU;
408   else
409     p_hcon->rem_mtu_size = p_cfg->mtu;
410 }
411 
412 /*******************************************************************************
413  *
414  * Function         hidh_l2cif_config_cfm
415  *
416  * Description      This function processes the L2CAP configuration confirmation
417  *                  event.
418  *
419  * Returns          void
420  *
421  ******************************************************************************/
hidh_l2cif_config_cfm(uint16_t l2cap_cid,uint16_t initiator,tL2CAP_CFG_INFO * p_cfg)422 static void hidh_l2cif_config_cfm(uint16_t l2cap_cid, uint16_t initiator,
423                                   tL2CAP_CFG_INFO* p_cfg) {
424   hidh_l2cif_config_ind(l2cap_cid, p_cfg);
425 
426   uint8_t dhandle;
427   tHID_CONN* p_hcon = NULL;
428   uint32_t reason;
429 
430   log::verbose("HID-Host Rcvd cfg cfm, CID: 0x{:x}", l2cap_cid);
431 
432   /* Find CCB based on CID */
433   dhandle = find_conn_by_cid(l2cap_cid);
434   if (dhandle < kHID_HOST_MAX_DEVICES) p_hcon = &hh_cb.devices[dhandle].conn;
435 
436   if (p_hcon == NULL) {
437     log::warn("HID-Host Rcvd L2CAP cfg ind, unknown CID: 0x{:x}", l2cap_cid);
438     return;
439   }
440 
441   if (l2cap_cid == p_hcon->ctrl_cid) {
442     if (p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) {
443       /* Connect interrupt channel */
444       p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* Reset initial reason for
445                                                     CLOSE_EVT: Connection
446                                                     Attempt was made but failed
447                                                     */
448       p_hcon->intr_cid = L2CA_ConnectReqWithSecurity(
449           HID_PSM_INTERRUPT, hh_cb.devices[dhandle].addr,
450           BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
451       if (p_hcon->intr_cid == 0) {
452         log::warn("HID-Host INTR Originate failed");
453         reason = HID_L2CAP_REQ_FAIL;
454         p_hcon->conn_state = HID_CONN_STATE_UNUSED;
455         BTM_LogHistory(kBtmLogTag, hh_cb.devices[dhandle].addr, "Failed");
456         hidh_conn_disconnect(dhandle);
457         hh_cb.callback(dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE,
458                        reason, NULL);
459         return;
460       } else {
461         /* Transition to the next appropriate state, waiting for connection
462          * confirm on interrupt channel. */
463         p_hcon->conn_state = HID_CONN_STATE_CONNECTING_INTR;
464         BTM_LogHistory(kBtmLogTag, hh_cb.devices[dhandle].addr, "Connecting",
465                        "interrupt channel");
466       }
467     }
468   }
469 
470   /* If all configuration is complete, change state and tell management we are
471    * up */
472   if (p_hcon->conn_state == HID_CONN_STATE_CONFIG) {
473     p_hcon->conn_state = HID_CONN_STATE_CONNECTED;
474     /* Reset disconnect reason to success, as connection successful */
475     p_hcon->disc_reason = HID_SUCCESS;
476 
477     hh_cb.devices[dhandle].state = HID_DEV_CONNECTED;
478     hh_cb.callback(dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_OPEN, 0,
479                    NULL);
480     BTM_LogHistory(
481         kBtmLogTag, hh_cb.devices[dhandle].addr, "Connected",
482         base::StringPrintf("control:0x%04x interrupt:0x%04x state:%s",
483                            p_hcon->ctrl_cid, p_hcon->intr_cid,
484                            hid_conn::state_text(p_hcon->conn_state).c_str()));
485   }
486 }
487 
488 /*******************************************************************************
489  *
490  * Function         hidh_l2cif_disconnect_ind
491  *
492  * Description      This function handles a disconnect event from L2CAP. If
493  *                  requested to, we ack the disconnect before dropping the CCB
494  *
495  * Returns          void
496  *
497  ******************************************************************************/
hidh_l2cif_disconnect_ind(uint16_t l2cap_cid,bool ack_needed)498 static void hidh_l2cif_disconnect_ind(uint16_t l2cap_cid, bool ack_needed) {
499   uint8_t dhandle;
500   tHID_CONN* p_hcon = NULL;
501   tHCI_REASON disc_res = HCI_SUCCESS;
502   uint16_t hid_close_evt_reason;
503 
504   /* Find CCB based on CID */
505   dhandle = find_conn_by_cid(l2cap_cid);
506   if (dhandle < kHID_HOST_MAX_DEVICES) p_hcon = &hh_cb.devices[dhandle].conn;
507 
508   if (p_hcon == NULL) {
509     log::warn("HID-Host Rcvd L2CAP disc, unknown CID: 0x{:x}", l2cap_cid);
510     return;
511   }
512 
513   log::verbose("HID-Host Rcvd L2CAP disc, CID: 0x{:x}", l2cap_cid);
514 
515   p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING;
516   BTM_LogHistory(
517       kBtmLogTag, hh_cb.devices[dhandle].addr, "Disconnecting",
518       base::StringPrintf("%s channel", (l2cap_cid == p_hcon->ctrl_cid)
519                                            ? "control"
520                                            : "interrupt"));
521 
522   if (l2cap_cid == p_hcon->ctrl_cid)
523     p_hcon->ctrl_cid = 0;
524   else
525     p_hcon->intr_cid = 0;
526 
527   if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) {
528     hh_cb.devices[dhandle].state = HID_DEV_NO_CONN;
529     p_hcon->conn_state = HID_CONN_STATE_UNUSED;
530 
531     if (!ack_needed) disc_res = btm_get_acl_disc_reason_code();
532 
533 #if (HID_HOST_MAX_CONN_RETRY > 0)
534     if ((disc_res == HCI_ERR_CONNECTION_TOUT ||
535          disc_res == HCI_ERR_UNSPECIFIED) &&
536         (!(hh_cb.devices[dhandle].attr_mask & HID_RECONN_INIT)) &&
537         (hh_cb.devices[dhandle].attr_mask & HID_NORMALLY_CONNECTABLE)) {
538       hh_cb.devices[dhandle].conn_tries = 0;
539       uint64_t interval_ms = HID_HOST_REPAGE_WIN * 1000;
540       alarm_set_on_mloop(hh_cb.devices[dhandle].conn.process_repage_timer,
541                          interval_ms, hidh_process_repage_timer_timeout,
542                          UINT_TO_PTR(dhandle));
543       hh_cb.callback(dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE,
544                      disc_res, NULL);
545     } else
546 #endif
547     {
548       /* Set reason code for HID_HDEV_EVT_CLOSE */
549       hid_close_evt_reason = p_hcon->disc_reason;
550 
551       /* If we got baseband sent HCI_DISCONNECT_COMPLETE_EVT due to security
552        * failure, then set reason to HID_ERR_AUTH_FAILED */
553       if ((disc_res == HCI_ERR_AUTH_FAILURE) ||
554           (disc_res == HCI_ERR_KEY_MISSING) ||
555           (disc_res == HCI_ERR_HOST_REJECT_SECURITY) ||
556           (disc_res == HCI_ERR_PAIRING_NOT_ALLOWED) ||
557           (disc_res == HCI_ERR_UNIT_KEY_USED) ||
558           (disc_res == HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED) ||
559           (disc_res == HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE) ||
560           (disc_res == HCI_ERR_REPEATED_ATTEMPTS)) {
561         log_counter_metrics(
562             android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_AUTH_FAILED,
563             1);
564         hid_close_evt_reason = HID_ERR_AUTH_FAILED;
565       }
566 
567       hh_cb.callback(dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE,
568                      hid_close_evt_reason, NULL);
569     }
570   }
571 }
572 
hidh_l2cif_disconnect(uint16_t l2cap_cid)573 static void hidh_l2cif_disconnect(uint16_t l2cap_cid) {
574   if (!L2CA_DisconnectReq(l2cap_cid)) {
575     log::warn("Unable to send L2CAP disconnect request cid:{}", l2cap_cid);
576   }
577 
578   /* Find CCB based on CID */
579   const uint8_t dhandle = find_conn_by_cid(l2cap_cid);
580   if (dhandle == kHID_HOST_MAX_DEVICES) {
581     log::warn("HID-Host Rcvd L2CAP disc cfm, unknown CID: 0x{:x}", l2cap_cid);
582     return;
583   }
584 
585   tHID_CONN* p_hcon = &hh_cb.devices[dhandle].conn;
586   if (l2cap_cid == p_hcon->ctrl_cid) {
587     p_hcon->ctrl_cid = 0;
588   } else {
589     p_hcon->intr_cid = 0;
590     if (p_hcon->ctrl_cid) {
591       log::verbose("HID-Host Initiating L2CAP Ctrl disconnection");
592       if (!L2CA_DisconnectReq(p_hcon->ctrl_cid)) {
593         log::warn("Unable to send L2CAP disconnect request cid:{}",
594                   p_hcon->ctrl_cid);
595       }
596       p_hcon->ctrl_cid = 0;
597     }
598   }
599 
600   if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) {
601     hh_cb.devices[dhandle].state = HID_DEV_NO_CONN;
602     p_hcon->conn_state = HID_CONN_STATE_UNUSED;
603     BTM_LogHistory(kBtmLogTag, hh_cb.devices[dhandle].addr, "Disconnected");
604     hh_cb.callback(dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE,
605                    p_hcon->disc_reason, NULL);
606   }
607 }
608 
609 /*******************************************************************************
610  *
611  * Function         hidh_l2cif_cong_ind
612  *
613  * Description      This function handles a congestion status event from L2CAP.
614  *
615  * Returns          void
616  *
617  ******************************************************************************/
hidh_l2cif_cong_ind(uint16_t l2cap_cid,bool congested)618 static void hidh_l2cif_cong_ind(uint16_t l2cap_cid, bool congested) {
619   uint8_t dhandle;
620   tHID_CONN* p_hcon = NULL;
621 
622   /* Find CCB based on CID */
623   dhandle = find_conn_by_cid(l2cap_cid);
624   if (dhandle < kHID_HOST_MAX_DEVICES) p_hcon = &hh_cb.devices[dhandle].conn;
625 
626   if (p_hcon == NULL) {
627     log::warn("HID-Host Rcvd L2CAP congestion status, unknown CID: 0x{:x}",
628               l2cap_cid);
629     return;
630   }
631 
632   log::verbose("HID-Host Rcvd L2CAP congestion status, CID: 0x{:x}  Cong: {}",
633                l2cap_cid, congested);
634 
635   if (congested)
636     p_hcon->conn_flags |= HID_CONN_FLAGS_CONGESTED;
637   else {
638     p_hcon->conn_flags &= ~HID_CONN_FLAGS_CONGESTED;
639   }
640 }
641 
642 /*******************************************************************************
643  *
644  * Function         hidh_l2cif_data_ind
645  *
646  * Description      This function is called when data is received from L2CAP.
647  *                  if we are the originator of the connection, we are the SDP
648  *                  client, and the received message is queued up for the
649  *                  client.
650  *
651  *                  If we are the destination of the connection, we are the SDP
652  *                  server, so the message is passed to the server processing
653  *                  function.
654  *
655  * Returns          void
656  *
657  ******************************************************************************/
hidh_l2cif_data_ind(uint16_t l2cap_cid,BT_HDR * p_msg)658 static void hidh_l2cif_data_ind(uint16_t l2cap_cid, BT_HDR* p_msg) {
659   uint8_t* p_data = (uint8_t*)(p_msg + 1) + p_msg->offset;
660   uint8_t ttype, param, rep_type, evt;
661   uint8_t dhandle;
662   tHID_CONN* p_hcon = NULL;
663 
664   log::verbose("HID-Host hidh_l2cif_data_ind [l2cap_cid=0x{:04x}]", l2cap_cid);
665 
666   /* Find CCB based on CID */
667   dhandle = find_conn_by_cid(l2cap_cid);
668   if (dhandle < kHID_HOST_MAX_DEVICES) p_hcon = &hh_cb.devices[dhandle].conn;
669 
670   if (p_hcon == NULL) {
671     log::warn("HID-Host Rcvd L2CAP data, unknown CID: 0x{:x}", l2cap_cid);
672     osi_free(p_msg);
673     return;
674   }
675 
676   if (p_msg->len < 1) {
677     log::warn("Rcvd L2CAP data, invalid length {}, should be >= 1", p_msg->len);
678     osi_free(p_msg);
679     return;
680   }
681 
682   ttype = HID_GET_TRANS_FROM_HDR(*p_data);
683   param = HID_GET_PARAM_FROM_HDR(*p_data);
684   rep_type = param & HID_PAR_REP_TYPE_MASK;
685   p_data++;
686 
687   /* Get rid of the data type */
688   p_msg->len--;
689   p_msg->offset++;
690 
691   switch (ttype) {
692     case HID_TRANS_HANDSHAKE:
693       hh_cb.callback(dhandle, hh_cb.devices[dhandle].addr,
694                      HID_HDEV_EVT_HANDSHAKE, param, NULL);
695       osi_free(p_msg);
696       break;
697 
698     case HID_TRANS_CONTROL:
699       switch (param) {
700         case HID_PAR_CONTROL_VIRTUAL_CABLE_UNPLUG:
701           hidh_conn_disconnect(dhandle);
702           /* Device is unplugging from us. Tell USB */
703           hh_cb.callback(dhandle, hh_cb.devices[dhandle].addr,
704                          HID_HDEV_EVT_VC_UNPLUG, 0, NULL);
705           break;
706 
707         default:
708           break;
709       }
710       osi_free(p_msg);
711       break;
712 
713     case HID_TRANS_DATA:
714       evt = (hh_cb.devices[dhandle].conn.intr_cid == l2cap_cid)
715                 ? HID_HDEV_EVT_INTR_DATA
716                 : HID_HDEV_EVT_CTRL_DATA;
717       hh_cb.callback(dhandle, hh_cb.devices[dhandle].addr, evt, rep_type,
718                      p_msg);
719       break;
720 
721     case HID_TRANS_DATAC:
722       evt = (hh_cb.devices[dhandle].conn.intr_cid == l2cap_cid)
723                 ? HID_HDEV_EVT_INTR_DATC
724                 : HID_HDEV_EVT_CTRL_DATC;
725       hh_cb.callback(dhandle, hh_cb.devices[dhandle].addr, evt, rep_type,
726                      p_msg);
727       break;
728 
729     default:
730       osi_free(p_msg);
731       break;
732   }
733 }
734 
735 /*******************************************************************************
736  *
737  * Function         hidh_conn_snd_data
738  *
739  * Description      This function is sends out data.
740  *
741  * Returns          tHID_STATUS
742  *
743  ******************************************************************************/
hidh_conn_snd_data(uint8_t dhandle,uint8_t trans_type,uint8_t param,uint16_t data,uint8_t report_id,BT_HDR * buf)744 tHID_STATUS hidh_conn_snd_data(uint8_t dhandle, uint8_t trans_type,
745                                uint8_t param, uint16_t data, uint8_t report_id,
746                                BT_HDR* buf) {
747   tHID_CONN* p_hcon = &hh_cb.devices[dhandle].conn;
748   BT_HDR* p_buf;
749   uint8_t* p_out;
750   uint16_t bytes_copied;
751   bool seg_req = false;
752   uint16_t data_size;
753   uint16_t cid;
754   uint16_t buf_size;
755   uint8_t use_data = 0;
756   bool blank_datc = false;
757 
758   if (!BTM_IsAclConnectionUp(hh_cb.devices[dhandle].addr,
759                              BT_TRANSPORT_BR_EDR)) {
760     osi_free(buf);
761     log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
762                             HIDH_ERR_NO_CONNECTION_AT_SEND_DATA,
763                         1);
764     return HID_ERR_NO_CONNECTION;
765   }
766 
767   if (p_hcon->conn_flags & HID_CONN_FLAGS_CONGESTED) {
768     osi_free(buf);
769     log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
770                             HIDH_ERR_CONGESTED_AT_FLAG_CHECK,
771                         1);
772     return HID_ERR_CONGESTED;
773   }
774 
775   switch (trans_type) {
776     case HID_TRANS_CONTROL:
777     case HID_TRANS_GET_REPORT:
778     case HID_TRANS_SET_REPORT:
779     case HID_TRANS_GET_PROTOCOL:
780     case HID_TRANS_SET_PROTOCOL:
781     case HID_TRANS_GET_IDLE:
782     case HID_TRANS_SET_IDLE:
783       cid = p_hcon->ctrl_cid;
784       buf_size = HID_CONTROL_BUF_SIZE;
785       break;
786     case HID_TRANS_DATA:
787       cid = p_hcon->intr_cid;
788       buf_size = HID_INTERRUPT_BUF_SIZE;
789       break;
790     default:
791       log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
792                               HIDH_ERR_INVALID_PARAM_AT_SEND_DATA,
793                           1);
794       return (HID_ERR_INVALID_PARAM);
795   }
796 
797   if (trans_type == HID_TRANS_SET_IDLE)
798     use_data = 1;
799   else if ((trans_type == HID_TRANS_GET_REPORT) && (param & 0x08))
800     use_data = 2;
801 
802   do {
803     if (buf == NULL || blank_datc) {
804       p_buf = (BT_HDR*)osi_malloc(buf_size);
805 
806       p_buf->offset = L2CAP_MIN_OFFSET;
807       seg_req = false;
808       data_size = 0;
809       bytes_copied = 0;
810       blank_datc = false;
811     } else if ((buf->len > (p_hcon->rem_mtu_size - 1))) {
812       p_buf = (BT_HDR*)osi_malloc(buf_size);
813 
814       p_buf->offset = L2CAP_MIN_OFFSET;
815       seg_req = true;
816       data_size = buf->len;
817       bytes_copied = p_hcon->rem_mtu_size - 1;
818     } else {
819       p_buf = buf;
820       p_buf->offset -= 1;
821       seg_req = false;
822       data_size = buf->len;
823       bytes_copied = buf->len;
824     }
825 
826     p_out = (uint8_t*)(p_buf + 1) + p_buf->offset;
827     *p_out++ = HID_BUILD_HDR(trans_type, param);
828 
829     /* If report ID required for this device */
830     if ((trans_type == HID_TRANS_GET_REPORT) && (report_id != 0)) {
831       *p_out = report_id;
832       data_size = bytes_copied = 1;
833     }
834 
835     if (seg_req) {
836       memcpy(p_out, (((uint8_t*)(buf + 1)) + buf->offset), bytes_copied);
837       buf->offset += bytes_copied;
838       buf->len -= bytes_copied;
839     } else if (use_data == 1) {
840       *(p_out + bytes_copied) = data & 0xff;
841     } else if (use_data == 2) {
842       *(p_out + bytes_copied) = data & 0xff;
843       *(p_out + bytes_copied + 1) = (data >> 8) & 0xff;
844     }
845 
846     p_buf->len = bytes_copied + 1 + use_data;
847     data_size -= bytes_copied;
848 
849     /* Send the buffer through L2CAP */
850     if ((p_hcon->conn_flags & HID_CONN_FLAGS_CONGESTED) ||
851         (!L2CA_DataWrite(cid, p_buf))) {
852       log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
853                               HIDH_ERR_CONGESTED_AT_SEND_DATA,
854                           1);
855       return (HID_ERR_CONGESTED);
856     }
857 
858     if (data_size)
859       trans_type = HID_TRANS_DATAC;
860     else if (bytes_copied == (p_hcon->rem_mtu_size - 1)) {
861       trans_type = HID_TRANS_DATAC;
862       blank_datc = true;
863     }
864 
865   } while ((data_size != 0) || blank_datc);
866 
867   return (HID_SUCCESS);
868 }
869 /*******************************************************************************
870  *
871  * Function         hidh_conn_initiate
872  *
873  * Description      This function is called by the management to create a
874  *                  connection.
875  *
876  * Returns          void
877  *
878  ******************************************************************************/
hidh_conn_initiate(uint8_t dhandle)879 tHID_STATUS hidh_conn_initiate(uint8_t dhandle) {
880   tHID_HOST_DEV_CTB* p_dev = &hh_cb.devices[dhandle];
881 
882   if (p_dev->conn.conn_state != HID_CONN_STATE_UNUSED) {
883     log_counter_metrics(
884         android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_CONN_IN_PROCESS,
885         1);
886     return (HID_ERR_CONN_IN_PROCESS);
887   }
888 
889   p_dev->conn.ctrl_cid = 0;
890   p_dev->conn.intr_cid = 0;
891   p_dev->conn.disc_reason =
892       HID_L2CAP_CONN_FAIL; /* Reset initial reason for CLOSE_EVT: Connection
893                               Attempt was made but failed */
894 
895   /* We are the originator of this connection */
896   p_dev->conn.conn_flags = HID_CONN_FLAGS_IS_ORIG;
897 
898   /* Check if L2CAP started the connection process */
899   p_dev->conn.ctrl_cid = L2CA_ConnectReqWithSecurity(
900       HID_PSM_CONTROL, p_dev->addr, BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
901   if (p_dev->conn.ctrl_cid == 0) {
902     log::warn("HID-Host Originate failed");
903     hh_cb.callback(dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE,
904                    HID_ERR_L2CAP_FAILED, NULL);
905     log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
906                             HIDH_ERR_L2CAP_FAILED_AT_INITIATE,
907                         1);
908   } else {
909     /* Transition to the next appropriate state, waiting for connection confirm
910      * on control channel. */
911     p_dev->conn.conn_state = HID_CONN_STATE_CONNECTING_CTRL;
912     BTM_LogHistory(kBtmLogTag, hh_cb.devices[dhandle].addr, "Connecting",
913                    "control channel");
914   }
915 
916   return (HID_SUCCESS);
917 }
918 
919 /*******************************************************************************
920  *
921  * Function         find_conn_by_cid
922  *
923  * Description      This function finds a connection control block based on CID.
924  *
925  * Returns          index of control block, or kHID_HOST_MAX_DEVICES if not
926  *                  found.
927  *
928  ******************************************************************************/
find_conn_by_cid(uint16_t cid)929 static uint8_t find_conn_by_cid(uint16_t cid) {
930   uint8_t xx;
931 
932   for (xx = 0; xx < kHID_HOST_MAX_DEVICES; xx++) {
933     if ((hh_cb.devices[xx].in_use) &&
934         (hh_cb.devices[xx].conn.conn_state != HID_CONN_STATE_UNUSED) &&
935         ((hh_cb.devices[xx].conn.ctrl_cid == cid) ||
936          (hh_cb.devices[xx].conn.intr_cid == cid)))
937       break;
938   }
939 
940   return (xx);
941 }
942 
hidh_conn_dereg(void)943 void hidh_conn_dereg(void) {
944   L2CA_Deregister(HID_PSM_CONTROL);
945   L2CA_Deregister(HID_PSM_INTERRUPT);
946 }
947 
948 /*******************************************************************************
949  *
950  * Function         hidh_conn_retry
951  *
952  * Description      This function is called to retry a failed connection.
953  *
954  * Returns          void
955  *
956  ******************************************************************************/
hidh_conn_retry(uint8_t dhandle)957 static void hidh_conn_retry(uint8_t dhandle) {
958   tHID_HOST_DEV_CTB* p_dev = &hh_cb.devices[dhandle];
959 
960   p_dev->conn.conn_state = HID_CONN_STATE_UNUSED;
961 #if (HID_HOST_REPAGE_WIN > 0)
962   uint64_t interval_ms = HID_HOST_REPAGE_WIN * 1000;
963   alarm_set_on_mloop(p_dev->conn.process_repage_timer, interval_ms,
964                      hidh_process_repage_timer_timeout, UINT_TO_PTR(dhandle));
965 #else
966   hidh_try_repage(dhandle);
967 #endif
968 }
969