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