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