1 /******************************************************************************
2 *
3 * Copyright 2016 The Android Open Source Project
4 * Copyright 2002-2012 Broadcom Corporation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 ******************************************************************************/
19
20 /******************************************************************************
21 *
22 * this file contains the connection interface functions
23 *
24 ******************************************************************************/
25
26 #include <base/functional/callback.h>
27 #include <bluetooth/log.h>
28 #include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
29
30 #include <cstdint>
31
32 #include "bta/include/bta_sec_api.h"
33 #include "internal_include/bt_target.h"
34 #include "osi/include/allocator.h"
35 #include "stack/hid/hidd_int.h"
36 #include "stack/include/bt_hdr.h"
37 #include "stack/include/bt_psm_types.h"
38 #include "stack/include/l2cdefs.h"
39 #include "stack/include/stack_metrics_logging.h"
40 #include "types/raw_address.h"
41
42 using namespace bluetooth;
43
44 static void hidd_l2cif_connect_ind(const RawAddress& bd_addr, uint16_t cid,
45 uint16_t psm, uint8_t id);
46 static void hidd_l2cif_connect_cfm(uint16_t cid, uint16_t result);
47 static void hidd_l2cif_config_ind(uint16_t cid, tL2CAP_CFG_INFO* p_cfg);
48 static void hidd_l2cif_config_cfm(uint16_t cid, uint16_t result,
49 tL2CAP_CFG_INFO* p_cfg);
50 static void hidd_l2cif_disconnect_ind(uint16_t cid, bool ack_needed);
51 static void hidd_l2cif_disconnect(uint16_t cid);
52 static void hidd_l2cif_data_ind(uint16_t cid, BT_HDR* p_msg);
53 static void hidd_l2cif_cong_ind(uint16_t cid, bool congested);
54 static void hidd_on_l2cap_error(uint16_t lcid, uint16_t result);
55 static const tL2CAP_APPL_INFO dev_reg_info = {hidd_l2cif_connect_ind,
56 hidd_l2cif_connect_cfm,
57 hidd_l2cif_config_ind,
58 hidd_l2cif_config_cfm,
59 hidd_l2cif_disconnect_ind,
60 NULL,
61 hidd_l2cif_data_ind,
62 hidd_l2cif_cong_ind,
63 NULL,
64 hidd_on_l2cap_error,
65 NULL,
66 NULL,
67 NULL,
68 NULL};
69
70 /*******************************************************************************
71 *
72 * Function hidd_check_config_done
73 *
74 * Description Checks if connection is configured and callback can be fired
75 *
76 * Returns void
77 *
78 ******************************************************************************/
hidd_check_config_done()79 static void hidd_check_config_done() {
80 tHID_CONN* p_hcon = &hd_cb.device.conn;
81
82 if (p_hcon->conn_state == HID_CONN_STATE_CONFIG) {
83 p_hcon->conn_state = HID_CONN_STATE_CONNECTED;
84
85 hd_cb.device.state = HIDD_DEV_CONNECTED;
86
87 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_OPEN, 0, NULL);
88
89 // send outstanding data on intr
90 if (hd_cb.pending_data) {
91 if (L2CA_DataWrite(p_hcon->intr_cid, hd_cb.pending_data) !=
92 L2CAP_DW_SUCCESS) {
93 log::warn("Unable to write L2CAP data cid:{} len:{}", p_hcon->intr_cid,
94 hd_cb.pending_data->len);
95 }
96 hd_cb.pending_data = NULL;
97 }
98 }
99 }
100
101 /*******************************************************************************
102 *
103 * Function hidd_l2cif_connect_ind
104 *
105 * Description Handles incoming L2CAP connection (we act as server)
106 *
107 * Returns void
108 *
109 ******************************************************************************/
hidd_l2cif_connect_ind(const RawAddress & bd_addr,uint16_t cid,uint16_t psm,uint8_t id)110 static void hidd_l2cif_connect_ind(const RawAddress& bd_addr, uint16_t cid,
111 uint16_t psm, uint8_t id) {
112 tHID_DEV_DEV_CTB* p_dev;
113 bool accept = TRUE; // accept by default
114
115 log::verbose("psm={:04x} cid={:04x}", psm, cid);
116
117 p_dev = &hd_cb.device;
118
119 if (!hd_cb.allow_incoming) {
120 log::warn("incoming connections not allowed, rejecting");
121 if (!L2CA_DisconnectReq(cid)) {
122 log::warn("Unable to disconnect L2CAP peer:{} cid:{}", p_dev->addr, cid);
123 }
124
125 return;
126 }
127
128 tHID_CONN* p_hcon = &hd_cb.device.conn;
129
130 switch (psm) {
131 case HID_PSM_INTERRUPT:
132 if (p_hcon->ctrl_cid == 0) {
133 accept = FALSE;
134 log::warn("incoming INTR without CTRL, rejecting");
135 }
136
137 if (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) {
138 accept = FALSE;
139 log::warn("incoming INTR in invalid state ({}), rejecting",
140 p_hcon->conn_state);
141 }
142
143 break;
144
145 case HID_PSM_CONTROL:
146 if (p_hcon->conn_state != HID_CONN_STATE_UNUSED) {
147 accept = FALSE;
148 log::warn("incoming CTRL in invalid state ({}), rejecting",
149 p_hcon->conn_state);
150 }
151
152 break;
153
154 default:
155 accept = FALSE;
156 log::error("received invalid PSM, rejecting");
157 break;
158 }
159
160 if (!accept) {
161 if (!L2CA_DisconnectReq(cid)) {
162 log::warn("Unable to disconnect L2CAP cid:{}", cid);
163 }
164 return;
165 }
166
167 // for CTRL we need to go through security and we reply in callback from there
168 if (psm == HID_PSM_CONTROL) {
169 // We are ready to accept connection from this device, since we aren't
170 // connected to anything and are in the correct state.
171 p_dev->in_use = TRUE;
172 p_dev->addr = bd_addr;
173 p_dev->state = HIDD_DEV_NO_CONN;
174
175 p_hcon->conn_flags = 0;
176 p_hcon->ctrl_cid = cid;
177 p_hcon->disc_reason = HID_SUCCESS;
178 p_hcon->conn_state = HID_CONN_STATE_CONNECTING_INTR;
179 return;
180 }
181
182 // for INTR we go directly to config state
183 p_hcon->conn_state = HID_CONN_STATE_CONFIG;
184 p_hcon->intr_cid = cid;
185 }
186
hidd_on_l2cap_error(uint16_t lcid,uint16_t result)187 static void hidd_on_l2cap_error(uint16_t lcid, uint16_t result) {
188 log::warn("connection of config failed, now disconnect");
189
190 hidd_conn_disconnect();
191
192 // NOTE that the client doesn't care about error code
193 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE,
194 HID_L2CAP_CONN_FAIL | (uint32_t)result, NULL);
195 }
196
197 /*******************************************************************************
198 *
199 * Function hidd_l2cif_connect_cfm
200 *
201 * Description Handles L2CAP connection response (we act as client)
202 *
203 * Returns void
204 *
205 ******************************************************************************/
hidd_l2cif_connect_cfm(uint16_t cid,uint16_t result)206 static void hidd_l2cif_connect_cfm(uint16_t cid, uint16_t result) {
207 tHID_CONN* p_hcon = &hd_cb.device.conn;
208
209 log::verbose("cid={:04x} result={}", cid, result);
210
211 if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
212 log::warn("unknown cid");
213 return;
214 }
215
216 if (!(p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) ||
217 ((cid == p_hcon->ctrl_cid) &&
218 (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_CTRL)) ||
219 ((cid == p_hcon->intr_cid) &&
220 (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR))) {
221 log::warn("unexpected");
222 return;
223 }
224
225 if (result != L2CAP_CONN_OK) {
226 log::error("invoked with non OK status");
227 return;
228 }
229
230 /* CTRL connect conf */
231 if (cid == p_hcon->ctrl_cid) {
232 p_hcon->disc_reason = HID_SUCCESS;
233 p_hcon->conn_state = HID_CONN_STATE_CONFIG;
234 } else {
235 p_hcon->conn_state = HID_CONN_STATE_CONFIG;
236 }
237
238 return;
239 }
240
241 /*******************************************************************************
242 *
243 * Function hidd_l2cif_config_ind
244 *
245 * Description Handles incoming L2CAP configuration request
246 *
247 * Returns void
248 *
249 ******************************************************************************/
hidd_l2cif_config_ind(uint16_t cid,tL2CAP_CFG_INFO * p_cfg)250 static void hidd_l2cif_config_ind(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) {
251 log::verbose("cid={:04x}", cid);
252
253 tHID_CONN* p_hcon = &hd_cb.device.conn;
254
255 if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
256 log::warn("unknown cid");
257 return;
258 }
259
260 if ((!p_cfg->mtu_present) || (p_cfg->mtu > HID_DEV_MTU_SIZE))
261 p_hcon->rem_mtu_size = HID_DEV_MTU_SIZE;
262 else
263 p_hcon->rem_mtu_size = p_cfg->mtu;
264 }
265
266 /*******************************************************************************
267 *
268 * Function hidd_l2cif_config_cfm
269 *
270 * Description Handles incoming L2CAP configuration response
271 *
272 * Returns void
273 *
274 ******************************************************************************/
hidd_l2cif_config_cfm(uint16_t cid,uint16_t initiator,tL2CAP_CFG_INFO * p_cfg)275 static void hidd_l2cif_config_cfm(uint16_t cid, uint16_t initiator,
276 tL2CAP_CFG_INFO* p_cfg) {
277 hidd_l2cif_config_ind(cid, p_cfg);
278
279 log::verbose("cid={:04x}", cid);
280
281 tHID_CONN* p_hcon = &hd_cb.device.conn;
282
283 if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
284 log::warn("unknown cid");
285 return;
286 }
287
288 // update flags
289 if (cid == p_hcon->ctrl_cid) {
290 if (p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) {
291 p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;
292 if ((p_hcon->intr_cid = L2CA_ConnectReqWithSecurity(
293 HID_PSM_INTERRUPT, hd_cb.device.addr,
294 BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)) == 0) {
295 hidd_conn_disconnect();
296 p_hcon->conn_state = HID_CONN_STATE_UNUSED;
297
298 log::warn("could not start L2CAP connection for INTR");
299 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE,
300 HID_ERR_L2CAP_FAILED, NULL);
301 log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
302 HIDD_ERR_L2CAP_NOT_STARTED_INCOMING,
303 1);
304 return;
305 } else {
306 p_hcon->conn_state = HID_CONN_STATE_CONNECTING_INTR;
307 }
308 }
309 }
310
311 hidd_check_config_done();
312 }
313
314 /*******************************************************************************
315 *
316 * Function hidd_l2cif_disconnect_ind
317 *
318 * Description Handler incoming L2CAP disconnection request
319 *
320 * Returns void
321 *
322 ******************************************************************************/
hidd_l2cif_disconnect_ind(uint16_t cid,bool ack_needed)323 static void hidd_l2cif_disconnect_ind(uint16_t cid, bool ack_needed) {
324 log::verbose("cid={:04x} ack_needed={}", cid, ack_needed);
325
326 tHID_CONN* p_hcon = &hd_cb.device.conn;
327
328 if (p_hcon->conn_state == HID_CONN_STATE_UNUSED ||
329 (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
330 log::warn("unknown cid");
331 return;
332 }
333
334 p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING;
335
336 if (cid == p_hcon->ctrl_cid)
337 p_hcon->ctrl_cid = 0;
338 else
339 p_hcon->intr_cid = 0;
340
341 if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) {
342 log::verbose("INTR and CTRL disconnected");
343
344 // clean any outstanding data on intr
345 if (hd_cb.pending_data) {
346 osi_free(hd_cb.pending_data);
347 hd_cb.pending_data = NULL;
348 }
349
350 hd_cb.device.state = HIDD_DEV_NO_CONN;
351 p_hcon->conn_state = HID_CONN_STATE_UNUSED;
352
353 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, p_hcon->disc_reason,
354 NULL);
355 }
356 }
357
hidd_l2cif_disconnect(uint16_t cid)358 static void hidd_l2cif_disconnect(uint16_t cid) {
359 if (!L2CA_DisconnectReq(cid)) {
360 log::warn("Unable to disconnect L2CAP cid:{}", cid);
361 }
362
363 log::verbose("cid={:04x}", cid);
364
365 tHID_CONN* p_hcon = &hd_cb.device.conn;
366
367 if (p_hcon->conn_state == HID_CONN_STATE_UNUSED ||
368 (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
369 log::warn("unknown cid");
370 return;
371 }
372
373 if (cid == p_hcon->ctrl_cid) {
374 p_hcon->ctrl_cid = 0;
375 } else {
376 p_hcon->intr_cid = 0;
377
378 // now disconnect CTRL
379 if (!L2CA_DisconnectReq(p_hcon->ctrl_cid)) {
380 log::warn("Unable to disconnect L2CAP cid:{}", p_hcon->ctrl_cid);
381 }
382 p_hcon->ctrl_cid = 0;
383 }
384
385 if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) {
386 log::verbose("INTR and CTRL disconnected");
387
388 hd_cb.device.state = HIDD_DEV_NO_CONN;
389 p_hcon->conn_state = HID_CONN_STATE_UNUSED;
390
391 if (hd_cb.pending_vc_unplug) {
392 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_VC_UNPLUG,
393 p_hcon->disc_reason, NULL);
394 hd_cb.pending_vc_unplug = FALSE;
395 } else {
396 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE,
397 p_hcon->disc_reason, NULL);
398 }
399 }
400 }
401
402 /*******************************************************************************
403 *
404 * Function hidd_l2cif_cong_ind
405 *
406 * Description Handles L2CAP congestion status event
407 *
408 * Returns void
409 *
410 ******************************************************************************/
hidd_l2cif_cong_ind(uint16_t cid,bool congested)411 static void hidd_l2cif_cong_ind(uint16_t cid, bool congested) {
412 log::verbose("cid={:04x} congested={}", cid, congested);
413
414 tHID_CONN* p_hcon = &hd_cb.device.conn;
415
416 if (p_hcon->conn_state == HID_CONN_STATE_UNUSED ||
417 (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
418 log::warn("unknown cid");
419 return;
420 }
421
422 if (congested) {
423 p_hcon->conn_flags |= HID_CONN_FLAGS_CONGESTED;
424 } else {
425 p_hcon->conn_flags &= ~HID_CONN_FLAGS_CONGESTED;
426 }
427 }
428
429 /*******************************************************************************
430 *
431 * Function hidd_l2cif_data_ind
432 *
433 * Description Handler incoming data on L2CAP channel
434 *
435 * Returns void
436 *
437 ******************************************************************************/
hidd_l2cif_data_ind(uint16_t cid,BT_HDR * p_msg)438 static void hidd_l2cif_data_ind(uint16_t cid, BT_HDR* p_msg) {
439 uint8_t* p_data = (uint8_t*)(p_msg + 1) + p_msg->offset;
440 uint8_t msg_type, param;
441 bool err = FALSE;
442
443 log::verbose("cid={:04x}", cid);
444
445 if (p_msg->len < 1) {
446 log::error("Invalid data length, ignore");
447 osi_free(p_msg);
448 return;
449 }
450
451 tHID_CONN* p_hcon = &hd_cb.device.conn;
452
453 if (p_hcon->conn_state == HID_CONN_STATE_UNUSED ||
454 (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
455 log::warn("unknown cid");
456 osi_free(p_msg);
457 return;
458 }
459
460 msg_type = HID_GET_TRANS_FROM_HDR(*p_data);
461 param = HID_GET_PARAM_FROM_HDR(*p_data);
462
463 if (msg_type == HID_TRANS_DATA && cid == p_hcon->intr_cid) {
464 // skip HID header
465 p_msg->offset++;
466 p_msg->len--;
467
468 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_INTR_DATA, 0, p_msg);
469 return;
470 }
471
472 switch (msg_type) {
473 case HID_TRANS_GET_REPORT:
474 // at this stage we don't know if Report Id shall be included in request
475 // so we pass complete packet in callback and let other code analyze this
476 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_GET_REPORT,
477 !!(param & HID_PAR_GET_REP_BUFSIZE_FOLLOWS), p_msg);
478 break;
479
480 case HID_TRANS_SET_REPORT:
481 // as above
482 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_SET_REPORT, 0, p_msg);
483 break;
484
485 case HID_TRANS_GET_IDLE:
486 hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_DATA,
487 HID_PAR_REP_TYPE_OTHER, hd_cb.device.idle_time, 0,
488 NULL);
489 osi_free(p_msg);
490 break;
491
492 case HID_TRANS_SET_IDLE:
493 if (p_msg->len != 2) {
494 log::error("invalid len ({}) set idle request received", p_msg->len);
495 err = TRUE;
496 } else {
497 hd_cb.device.idle_time = p_data[1];
498 log::verbose("idle_time = {}", hd_cb.device.idle_time);
499 if (hd_cb.device.idle_time) {
500 log::warn("idle_time of {} ms not supported by HID Device",
501 hd_cb.device.idle_time * 4);
502 err = TRUE;
503 }
504 }
505 if (!err) {
506 hidd_conn_send_data(0, HID_TRANS_HANDSHAKE,
507 HID_PAR_HANDSHAKE_RSP_SUCCESS, 0, 0, NULL);
508 } else {
509 hidd_conn_send_data(0, HID_TRANS_HANDSHAKE,
510 HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM, 0, 0,
511 NULL);
512 }
513 osi_free(p_msg);
514 break;
515
516 case HID_TRANS_GET_PROTOCOL:
517 hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_DATA,
518 HID_PAR_REP_TYPE_OTHER, !hd_cb.device.boot_mode, 0,
519 NULL);
520 osi_free(p_msg);
521 break;
522
523 case HID_TRANS_SET_PROTOCOL:
524 hd_cb.device.boot_mode = !(param & HID_PAR_PROTOCOL_MASK);
525 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_SET_PROTOCOL,
526 param & HID_PAR_PROTOCOL_MASK, NULL);
527 hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, HID_PAR_HANDSHAKE_RSP_SUCCESS,
528 0, 0, NULL);
529 osi_free(p_msg);
530 break;
531
532 case HID_TRANS_CONTROL:
533 switch (param) {
534 case HID_PAR_CONTROL_SUSPEND:
535 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_SUSPEND, 0, NULL);
536 break;
537
538 case HID_PAR_CONTROL_EXIT_SUSPEND:
539 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_EXIT_SUSPEND, 0,
540 NULL);
541 break;
542
543 case HID_PAR_CONTROL_VIRTUAL_CABLE_UNPLUG:
544 hidd_conn_disconnect();
545
546 // set flag so we can notify properly when disconnected
547 hd_cb.pending_vc_unplug = TRUE;
548 break;
549 }
550
551 osi_free(p_msg);
552 break;
553
554 case HID_TRANS_DATA:
555 default:
556 log::warn("got unsupported msg ({})", msg_type);
557 hidd_conn_send_data(0, HID_TRANS_HANDSHAKE,
558 HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ, 0, 0,
559 NULL);
560 osi_free(p_msg);
561 break;
562 }
563 }
564
565 /*******************************************************************************
566 *
567 * Function hidd_conn_reg
568 *
569 * Description Registers L2CAP channels
570 *
571 * Returns void
572 *
573 ******************************************************************************/
hidd_conn_reg(void)574 tHID_STATUS hidd_conn_reg(void) {
575 log::verbose("");
576
577 memset(&hd_cb.l2cap_cfg, 0, sizeof(tL2CAP_CFG_INFO));
578
579 hd_cb.l2cap_cfg.mtu_present = TRUE;
580 hd_cb.l2cap_cfg.mtu = HID_DEV_MTU_SIZE;
581 memset(&hd_cb.l2cap_intr_cfg, 0, sizeof(tL2CAP_CFG_INFO));
582 hd_cb.l2cap_intr_cfg.mtu_present = TRUE;
583 hd_cb.l2cap_intr_cfg.mtu = HID_DEV_MTU_SIZE;
584
585 if (!L2CA_RegisterWithSecurity(
586 HID_PSM_CONTROL, dev_reg_info, false /* enable_snoop */, nullptr,
587 HID_DEV_MTU_SIZE, 0, BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)) {
588 log::error("HID Control (device) registration failed");
589 log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
590 HIDD_ERR_L2CAP_FAILED_CONTROL,
591 1);
592 return (HID_ERR_L2CAP_FAILED);
593 }
594
595 if (!L2CA_RegisterWithSecurity(
596 HID_PSM_INTERRUPT, dev_reg_info, false /* enable_snoop */, nullptr,
597 HID_DEV_MTU_SIZE, 0, BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)) {
598 L2CA_Deregister(HID_PSM_CONTROL);
599 log::error("HID Interrupt (device) registration failed");
600 log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
601 HIDD_ERR_L2CAP_FAILED_INTERRUPT,
602 1);
603 return (HID_ERR_L2CAP_FAILED);
604 }
605
606 return (HID_SUCCESS);
607 }
608
609 /*******************************************************************************
610 *
611 * Function hidd_conn_dereg
612 *
613 * Description Deregisters L2CAP channels
614 *
615 * Returns void
616 *
617 ******************************************************************************/
hidd_conn_dereg(void)618 void hidd_conn_dereg(void) {
619 log::verbose("");
620
621 L2CA_Deregister(HID_PSM_CONTROL);
622 L2CA_Deregister(HID_PSM_INTERRUPT);
623 }
624
625 /*******************************************************************************
626 *
627 * Function hidd_conn_initiate
628 *
629 * Description Initiates HID connection to plugged device
630 *
631 * Returns HID_SUCCESS
632 *
633 ******************************************************************************/
hidd_conn_initiate(void)634 tHID_STATUS hidd_conn_initiate(void) {
635 tHID_DEV_DEV_CTB* p_dev = &hd_cb.device;
636
637 log::verbose("");
638
639 if (!p_dev->in_use) {
640 log::warn("no virtual cable established");
641 log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
642 HIDD_ERR_NOT_REGISTERED_AT_INITIATE,
643 1);
644 return (HID_ERR_NOT_REGISTERED);
645 }
646
647 if (p_dev->conn.conn_state != HID_CONN_STATE_UNUSED) {
648 log::warn("connection already in progress");
649 log_counter_metrics(
650 android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_CONN_IN_PROCESS,
651 1);
652 return (HID_ERR_CONN_IN_PROCESS);
653 }
654
655 p_dev->conn.ctrl_cid = 0;
656 p_dev->conn.intr_cid = 0;
657 p_dev->conn.disc_reason = HID_L2CAP_CONN_FAIL;
658
659 p_dev->conn.conn_flags = HID_CONN_FLAGS_IS_ORIG;
660
661 /* Check if L2CAP started the connection process */
662 if ((p_dev->conn.ctrl_cid = L2CA_ConnectReqWithSecurity(
663 HID_PSM_CONTROL, p_dev->addr,
664 BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)) == 0) {
665 log::warn("could not start L2CAP connection");
666 hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_ERR_L2CAP_FAILED,
667 NULL);
668 log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
669 HIDD_ERR_L2CAP_FAILED_INITIATE,
670 1);
671 } else {
672 p_dev->conn.conn_state = HID_CONN_STATE_CONNECTING_CTRL;
673 }
674
675 return (HID_SUCCESS);
676 }
677
678 /*******************************************************************************
679 *
680 * Function hidd_conn_disconnect
681 *
682 * Description Disconnects existing HID connection
683 *
684 * Returns HID_SUCCESS
685 *
686 ******************************************************************************/
hidd_conn_disconnect(void)687 tHID_STATUS hidd_conn_disconnect(void) {
688 log::verbose("");
689
690 // clean any outstanding data on intr
691 if (hd_cb.pending_data) {
692 osi_free(hd_cb.pending_data);
693 hd_cb.pending_data = NULL;
694 }
695
696 tHID_CONN* p_hcon = &hd_cb.device.conn;
697
698 if ((p_hcon->ctrl_cid != 0) || (p_hcon->intr_cid != 0)) {
699 p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING;
700
701 /* Set l2cap idle timeout to 0 (so ACL link is disconnected
702 * immediately after last channel is closed) */
703 if (!L2CA_SetIdleTimeoutByBdAddr(hd_cb.device.addr, 0,
704 BT_TRANSPORT_BR_EDR)) {
705 log::warn("Unable to set L2CAP idle timeout peer:{} transport:{}",
706 hd_cb.device.addr, BT_TRANSPORT_BR_EDR);
707 }
708
709 if (p_hcon->intr_cid) {
710 hidd_l2cif_disconnect(p_hcon->intr_cid);
711 } else if (p_hcon->ctrl_cid) {
712 hidd_l2cif_disconnect(p_hcon->ctrl_cid);
713 }
714 } else {
715 log::warn("already disconnected");
716 p_hcon->conn_state = HID_CONN_STATE_UNUSED;
717 }
718
719 return (HID_SUCCESS);
720 }
721
722 /*******************************************************************************
723 *
724 * Function hidd_conn_send_data
725 *
726 * Description Sends data to host
727 *
728 * Returns tHID_STATUS
729 *
730 ******************************************************************************/
hidd_conn_send_data(uint8_t channel,uint8_t msg_type,uint8_t param,uint8_t data,uint16_t len,uint8_t * p_data)731 tHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type,
732 uint8_t param, uint8_t data, uint16_t len,
733 uint8_t* p_data) {
734 BT_HDR* p_buf;
735 uint8_t* p_out;
736 uint16_t cid;
737 uint16_t buf_size;
738
739 log::verbose("channel({}), msg_type({}), len({})", channel, msg_type, len);
740
741 tHID_CONN* p_hcon = &hd_cb.device.conn;
742
743 if (p_hcon->conn_flags & HID_CONN_FLAGS_CONGESTED) {
744 log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
745 HIDD_ERR_CONGESTED_AT_FLAG_CHECK,
746 1);
747 return HID_ERR_CONGESTED;
748 }
749
750 switch (msg_type) {
751 case HID_TRANS_HANDSHAKE:
752 case HID_TRANS_CONTROL:
753 cid = p_hcon->ctrl_cid;
754 buf_size = HID_CONTROL_BUF_SIZE;
755 break;
756 case HID_TRANS_DATA:
757 if (channel == HID_CHANNEL_CTRL) {
758 cid = p_hcon->ctrl_cid;
759 buf_size = HID_CONTROL_BUF_SIZE;
760 } else {
761 cid = p_hcon->intr_cid;
762 buf_size = HID_INTERRUPT_BUF_SIZE;
763 }
764 break;
765 default:
766 log_counter_metrics(
767 android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_INVALID_PARAM,
768 1);
769 return (HID_ERR_INVALID_PARAM);
770 }
771
772 p_buf = (BT_HDR*)osi_malloc(buf_size);
773 if (p_buf == NULL) {
774 log_counter_metrics(
775 android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_NO_RESOURCES, 1);
776 return (HID_ERR_NO_RESOURCES);
777 }
778
779 p_buf->offset = L2CAP_MIN_OFFSET;
780
781 p_out = (uint8_t*)(p_buf + 1) + p_buf->offset;
782
783 *p_out = HID_BUILD_HDR(msg_type, param);
784 p_out++;
785
786 p_buf->len = 1; // start with header only
787
788 // add report id prefix only if non-zero (which is reserved)
789 if (msg_type == HID_TRANS_DATA && (data || param == HID_PAR_REP_TYPE_OTHER)) {
790 *p_out = data; // report_id
791 p_out++;
792 p_buf->len++;
793 }
794
795 if (len > 0 && p_data != NULL) {
796 memcpy(p_out, p_data, len);
797 p_buf->len += len;
798 }
799
800 // check if connected
801 if (hd_cb.device.state != HIDD_DEV_CONNECTED) {
802 // for DATA on intr we hold transfer and try to reconnect
803 if (msg_type == HID_TRANS_DATA && cid == p_hcon->intr_cid) {
804 // drop previous data, we do not queue it for now
805 if (hd_cb.pending_data) {
806 osi_free(hd_cb.pending_data);
807 }
808
809 hd_cb.pending_data = p_buf;
810
811 if (hd_cb.device.conn.conn_state == HID_CONN_STATE_UNUSED) {
812 hidd_conn_initiate();
813 }
814
815 return HID_SUCCESS;
816 }
817 log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
818 HIDD_ERR_NO_CONNECTION_AT_SEND_DATA,
819 1);
820 return HID_ERR_NO_CONNECTION;
821 }
822
823 log::verbose("report sent");
824
825 if (!L2CA_DataWrite(cid, p_buf)) {
826 log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
827 HIDD_ERR_CONGESTED_AT_DATA_WRITE,
828 1);
829 return (HID_ERR_CONGESTED);
830 }
831
832 return (HID_SUCCESS);
833 }
834