18843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta/******************************************************************************
28843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
38843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *  Copyright (C) 2016 The Android Open Source Project
48843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *  Copyright (C) 2002-2012 Broadcom Corporation
58843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
68843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *  Licensed under the Apache License, Version 2.0 (the "License");
78843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *  you may not use this file except in compliance with the License.
88843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *  You may obtain a copy of the License at:
98843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
108843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *  http://www.apache.org/licenses/LICENSE-2.0
118843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
128843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *  Unless required by applicable law or agreed to in writing, software
138843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *  distributed under the License is distributed on an "AS IS" BASIS,
148843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
158843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *  See the License for the specific language governing permissions and
168843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *  limitations under the License.
178843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
188843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta ******************************************************************************/
198843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
208843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta/******************************************************************************
218843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
228843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *  this file contains the connection interface functions
238843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
248843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta ******************************************************************************/
258843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
268843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta#include <stdio.h>
278843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta#include <stdlib.h>
288843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta#include <string.h>
298843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
308843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta#include "bt_types.h"
318843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
328843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta#include "l2c_api.h"
338843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta#include "l2cdefs.h"
348843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
358843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta#include "btm_api.h"
368843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta#include "btm_int.h"
378843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta#include "btu.h"
388843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
398843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta#include "hiddefs.h"
408843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
418843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta#include "bt_utils.h"
428843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta#include "hidd_api.h"
438843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta#include "hidd_int.h"
448843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
458843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta#include "osi/include/osi.h"
468843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
478843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptastatic void hidd_l2cif_connect_ind(BD_ADDR bd_addr, uint16_t cid, uint16_t psm,
488843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                   uint8_t id);
498843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptastatic void hidd_l2cif_connect_cfm(uint16_t cid, uint16_t result);
508843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptastatic void hidd_l2cif_config_ind(uint16_t cid, tL2CAP_CFG_INFO* p_cfg);
518843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptastatic void hidd_l2cif_config_cfm(uint16_t cid, tL2CAP_CFG_INFO* p_cfg);
528843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptastatic void hidd_l2cif_disconnect_ind(uint16_t cid, bool ack_needed);
538843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptastatic void hidd_l2cif_disconnect_cfm(uint16_t cid, uint16_t result);
548843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptastatic void hidd_l2cif_data_ind(uint16_t cid, BT_HDR* p_msg);
558843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptastatic void hidd_l2cif_cong_ind(uint16_t cid, bool congested);
568843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
578843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptastatic const tL2CAP_APPL_INFO dev_reg_info = {hidd_l2cif_connect_ind,
588843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                              hidd_l2cif_connect_cfm,
598843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                              NULL,
608843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                              hidd_l2cif_config_ind,
618843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                              hidd_l2cif_config_cfm,
628843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                              hidd_l2cif_disconnect_ind,
638843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                              hidd_l2cif_disconnect_cfm,
648843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                              NULL,
658843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                              hidd_l2cif_data_ind,
668843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                              hidd_l2cif_cong_ind,
678843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                              NULL};
688843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
698843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta/*******************************************************************************
708843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
718843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Function         hidd_check_config_done
728843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
738843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Description      Checks if connection is configured and callback can be fired
748843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
758843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Returns          void
768843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
778843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta ******************************************************************************/
788843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptastatic void hidd_check_config_done() {
798843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  tHID_CONN* p_hcon;
808843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
818843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_hcon = &hd_cb.device.conn;
828843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
838843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (((p_hcon->conn_flags & HID_CONN_FLAGS_ALL_CONFIGURED) ==
848843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta       HID_CONN_FLAGS_ALL_CONFIGURED) &&
858843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      (p_hcon->conn_state == HID_CONN_STATE_CONFIG)) {
868843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->conn_state = HID_CONN_STATE_CONNECTED;
878843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
888843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    hd_cb.device.state = HIDD_DEV_CONNECTED;
898843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
908843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_OPEN, 0, NULL);
918843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
928843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    // send outstanding data on intr
938843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    if (hd_cb.pending_data) {
948843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      L2CA_DataWrite(p_hcon->intr_cid, hd_cb.pending_data);
958843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      hd_cb.pending_data = NULL;
968843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    }
978843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
988843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta}
998843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
1008843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta/*******************************************************************************
1018843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
1028843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Function         hidh_sec_check_complete_term
1038843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
1048843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Description      HID security check complete callback function.
1058843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
1068843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Returns          Send L2CA_ConnectRsp OK if secutiry check succeed; otherwise
1078843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *                  send security block L2C connection response.
1088843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
1098843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta ******************************************************************************/
1108843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptastatic void hidd_sec_check_complete(UNUSED_ATTR BD_ADDR bd_addr,
1118843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                    UNUSED_ATTR tBT_TRANSPORT transport,
1128843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                    void* p_ref_data, uint8_t res) {
1138843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  tHID_DEV_DEV_CTB* p_dev = (tHID_DEV_DEV_CTB*)p_ref_data;
1148843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
1158843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (res == BTM_SUCCESS && p_dev->conn.conn_state == HID_CONN_STATE_SECURITY) {
1168843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_dev->conn.disc_reason = HID_SUCCESS;
1178843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_dev->conn.conn_state = HID_CONN_STATE_CONNECTING_INTR;
1188843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
1198843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    L2CA_ConnectRsp(p_dev->addr, p_dev->conn.ctrl_id, p_dev->conn.ctrl_cid,
1208843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                    L2CAP_CONN_OK, L2CAP_CONN_OK);
1218843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    L2CA_ConfigReq(p_dev->conn.ctrl_cid, &hd_cb.l2cap_cfg);
1228843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  } else if (res != BTM_SUCCESS) {
1238843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: connection rejected by security", __func__);
1248843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
1258843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_dev->conn.disc_reason = HID_ERR_AUTH_FAILED;
1268843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_dev->conn.conn_state = HID_CONN_STATE_UNUSED;
1278843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    L2CA_ConnectRsp(p_dev->addr, p_dev->conn.ctrl_id, p_dev->conn.ctrl_cid,
1288843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                    L2CAP_CONN_SECURITY_BLOCK, L2CAP_CONN_OK);
1298843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return;
1308843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
1318843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta}
1328843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
1338843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta/*******************************************************************************
1348843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
1358843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Function         hidd_sec_check_complete_orig
1368843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
1378843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Description      HID security check complete callback function (device
1388843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta*originated)
1398843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
1408843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Returns          void
1418843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
1428843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta ******************************************************************************/
1438843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptavoid hidd_sec_check_complete_orig(UNUSED_ATTR BD_ADDR bd_addr,
1448843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                  UNUSED_ATTR tBT_TRANSPORT transport,
1458843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                  void* p_ref_data, uint8_t res) {
1468843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  tHID_DEV_DEV_CTB* p_dev = (tHID_DEV_DEV_CTB*)p_ref_data;
1478843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
1488843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (p_dev->conn.conn_state != HID_CONN_STATE_SECURITY) {
1498843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: invalid state (%02x)", __func__,
1508843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                       p_dev->conn.conn_state);
1518843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return;
1528843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
1538843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
1548843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (res == BTM_SUCCESS) {
1558843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_EVENT("%s: security ok", __func__);
1568843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_dev->conn.disc_reason = HID_SUCCESS;
1578843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
1588843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_dev->conn.conn_state = HID_CONN_STATE_CONFIG;
1598843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    L2CA_ConfigReq(p_dev->conn.ctrl_cid, &hd_cb.l2cap_cfg);
1608843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  } else {
1618843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: security check failed (%02x)", __func__, res);
1628843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_dev->conn.disc_reason = HID_ERR_AUTH_FAILED;
1638843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    hidd_conn_disconnect();
1648843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
1658843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta}
1668843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
1678843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta/*******************************************************************************
1688843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
1698843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Function         hidd_l2cif_connect_ind
1708843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
1718843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Description      Handles incoming L2CAP connection (we act as server)
1728843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
1738843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Returns          void
1748843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
1758843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta ******************************************************************************/
1768843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptastatic void hidd_l2cif_connect_ind(BD_ADDR bd_addr, uint16_t cid, uint16_t psm,
1778843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                   uint8_t id) {
1788843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  tHID_CONN* p_hcon;
1798843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  tHID_DEV_DEV_CTB* p_dev;
1808843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  bool accept = TRUE;  // accept by default
1818843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
1828843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  HIDD_TRACE_EVENT("%s: psm=%04x cid=%04x id=%02x", __func__, psm, cid, id);
1838843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
1848843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_dev = &hd_cb.device;
1858843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
1868843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (!hd_cb.allow_incoming) {
1878843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: incoming connections not allowed, rejecting",
1888843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                       __func__);
1898843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_NO_RESOURCES, 0);
1908843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return;
1918843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
1928843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
1938843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (p_dev->in_use && memcmp(bd_addr, p_dev->addr, sizeof(BD_ADDR))) {
1948843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING(
1958843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        "%s: incoming connections from different device, rejecting", __func__);
1968843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_NO_RESOURCES, 0);
1978843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return;
1988843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  } else if (!p_dev->in_use) {
1998843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_dev->in_use = TRUE;
2008843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    memcpy(p_dev->addr, bd_addr, sizeof(BD_ADDR));
2018843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_dev->state = HIDD_DEV_NO_CONN;
2028843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
2038843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
2048843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_hcon = &hd_cb.device.conn;
2058843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
2068843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  switch (psm) {
2078843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    case HID_PSM_INTERRUPT:
2088843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      if (p_hcon->ctrl_cid == 0) {
2098843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        accept = FALSE;
2108843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        HIDD_TRACE_WARNING("%s: incoming INTR without CTRL, rejecting",
2118843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                           __func__);
2128843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      }
2138843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
2148843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      if (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) {
2158843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        accept = FALSE;
2168843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        HIDD_TRACE_WARNING("%s: incoming INTR in invalid state (%d), rejecting",
2178843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                           __func__, p_hcon->conn_state);
2188843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      }
2198843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
2208843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      break;
2218843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
2228843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    case HID_PSM_CONTROL:
2238843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      if (p_hcon->conn_state != HID_CONN_STATE_UNUSED) {
2248843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        accept = FALSE;
2258843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        HIDD_TRACE_WARNING("%s: incoming CTRL in invalid state (%d), rejecting",
2268843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                           __func__, p_hcon->conn_state);
2278843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      }
2288843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
2298843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      break;
2308843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
2318843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    default:
2328843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      accept = FALSE;
2338843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      HIDD_TRACE_ERROR("%s: received invalid PSM, rejecting", __func__);
2348843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      break;
2358843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
2368843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
2378843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (!accept) {
2388843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_NO_RESOURCES, 0);
2398843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return;
2408843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
2418843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
2428843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  // for CTRL we need to go through security and we reply in callback from there
2438843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (psm == HID_PSM_CONTROL) {
2448843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->conn_flags = 0;
2458843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->ctrl_cid = cid;
2468843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->ctrl_id = id;
2478843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;
2488843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
2498843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->conn_state = HID_CONN_STATE_SECURITY;
2508843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    if (btm_sec_mx_access_request(p_dev->addr, HID_PSM_CONTROL, FALSE,
2518843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                  BTM_SEC_PROTO_HID, HIDD_NOSEC_CHN,
2528843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                  &hidd_sec_check_complete,
2538843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                  p_dev) == BTM_CMD_STARTED) {
2548843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_PENDING, L2CAP_CONN_OK);
2558843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    }
2568843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
2578843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return;
2588843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
2598843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
2608843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  // for INTR we go directly to config state
2618843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_hcon->conn_state = HID_CONN_STATE_CONFIG;
2628843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_hcon->intr_cid = cid;
2638843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
2648843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_OK, L2CAP_CONN_OK);
2658843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  L2CA_ConfigReq(cid, &hd_cb.l2cap_intr_cfg);
2668843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta}
2678843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
2688843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta/*******************************************************************************
2698843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
2708843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Function         hidd_l2cif_connect_cfm
2718843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
2728843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Description      Handles L2CAP connection response (we act as client)
2738843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
2748843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Returns          void
2758843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
2768843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta ******************************************************************************/
2778843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptastatic void hidd_l2cif_connect_cfm(uint16_t cid, uint16_t result) {
2788843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  tHID_DEV_DEV_CTB* p_dev = &hd_cb.device;
2798843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  tHID_CONN* p_hcon = &hd_cb.device.conn;
2808843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
2818843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  HIDD_TRACE_EVENT("%s: cid=%04x result=%d", __func__, cid, result);
2828843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
2838843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
2848843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: unknown cid", __func__);
2858843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return;
2868843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
2878843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
2888843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (!(p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) ||
2898843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      ((cid == p_hcon->ctrl_cid) &&
2908843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta       (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_CTRL)) ||
2918843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      ((cid == p_hcon->intr_cid) &&
2928843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta       (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR))) {
2938843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: unexpected", __func__);
2948843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return;
2958843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
2968843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
2978843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (result != L2CAP_CONN_OK) {
2988843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: connection failed, now disconnect", __func__);
2998843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
3008843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    if (cid == p_hcon->ctrl_cid)
3018843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      p_hcon->ctrl_cid = 0;
3028843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    else
3038843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      p_hcon->intr_cid = 0;
3048843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
3058843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    hidd_conn_disconnect();
3068843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
3078843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE,
3088843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                   HID_L2CAP_CONN_FAIL | (uint32_t)result, NULL);
3098843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return;
3108843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
3118843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
3128843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  /* CTRL connect conf */
3138843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (cid == p_hcon->ctrl_cid) {
3148843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->conn_state = HID_CONN_STATE_SECURITY;
3158843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->disc_reason =
3168843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        HID_L2CAP_CONN_FAIL; /* in case disconnected before sec completed */
3178843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
3188843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    btm_sec_mx_access_request(p_dev->addr, HID_PSM_CONTROL, TRUE,
3198843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                              BTM_SEC_PROTO_HID, HIDD_SEC_CHN,
3208843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                              &hidd_sec_check_complete_orig, p_dev);
3218843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  } else {
3228843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->conn_state = HID_CONN_STATE_CONFIG;
3238843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    L2CA_ConfigReq(cid, &hd_cb.l2cap_intr_cfg);
3248843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
3258843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
3268843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  return;
3278843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta}
3288843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
3298843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta/*******************************************************************************
3308843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
3318843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Function         hidd_l2cif_config_ind
3328843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
3338843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Description      Handles incoming L2CAP configuration request
3348843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
3358843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Returns          void
3368843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
3378843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta ******************************************************************************/
3388843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptastatic void hidd_l2cif_config_ind(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) {
3398843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  tHID_CONN* p_hcon;
3408843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
3418843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid);
3428843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
3438843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_hcon = &hd_cb.device.conn;
3448843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
3458843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
3468843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: unknown cid", __func__);
3478843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return;
3488843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
3498843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
3508843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if ((!p_cfg->mtu_present) || (p_cfg->mtu > HID_DEV_MTU_SIZE))
3518843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->rem_mtu_size = HID_DEV_MTU_SIZE;
3528843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  else
3538843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->rem_mtu_size = p_cfg->mtu;
3548843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
3558843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  // accept without changes
3568843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_cfg->flush_to_present = FALSE;
3578843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_cfg->mtu_present = FALSE;
3588843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_cfg->result = L2CAP_CFG_OK;
3598843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
3608843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (cid == p_hcon->intr_cid && hd_cb.use_in_qos && !p_cfg->qos_present) {
3618843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_cfg->qos_present = TRUE;
3628843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    memcpy(&p_cfg->qos, &hd_cb.in_qos, sizeof(FLOW_SPEC));
3638843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
3648843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
3658843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  L2CA_ConfigRsp(cid, p_cfg);
3668843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
3678843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  // update flags
3688843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (cid == p_hcon->ctrl_cid) {
3698843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_CTRL_CFG_DONE;
3708843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
3718843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) &&
3728843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        (p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE)) {
3738843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;
3748843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      if ((p_hcon->intr_cid =
3758843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta               L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) {
3768843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        hidd_conn_disconnect();
377367373ba8bcfb1d9db41b1904de372483991fc10Ivan Podogov        p_hcon->conn_state = HID_CONN_STATE_UNUSED;
3788843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
3798843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        HIDD_TRACE_WARNING("%s: could not start L2CAP connection for INTR",
3808843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                           __func__);
3818843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE,
3828843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                       HID_ERR_L2CAP_FAILED, NULL);
3838843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        return;
3848843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      } else {
3858843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        p_hcon->conn_state = HID_CONN_STATE_CONNECTING_INTR;
3868843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      }
3878843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    }
3888843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  } else {
3898843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_INTR_CFG_DONE;
3908843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
3918843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
3928843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  hidd_check_config_done();
3938843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta}
3948843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
3958843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta/*******************************************************************************
3968843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
3978843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Function         hidd_l2cif_config_cfm
3988843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
3998843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Description      Handles incoming L2CAP configuration response
4008843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
4018843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Returns          void
4028843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
4038843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta ******************************************************************************/
4048843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptastatic void hidd_l2cif_config_cfm(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) {
4058843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  tHID_CONN* p_hcon;
4068843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  uint32_t reason;
4078843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4088843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  HIDD_TRACE_EVENT("%s: cid=%04x pcfg->result=%d", __func__, cid,
4098843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                   p_cfg->result);
4108843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4118843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_hcon = &hd_cb.device.conn;
4128843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4138843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
4148843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: unknown cid", __func__);
4158843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return;
4168843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
4178843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4188843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (p_hcon->intr_cid == cid &&
4198843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      p_cfg->result == L2CAP_CFG_UNACCEPTABLE_PARAMS && p_cfg->qos_present) {
4208843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    tL2CAP_CFG_INFO new_qos;
4218843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4228843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    // QoS parameters not accepted for intr, try again with host proposal
4238843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4248843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    memcpy(&new_qos, &hd_cb.l2cap_intr_cfg, sizeof(new_qos));
4258843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    memcpy(&new_qos.qos, &p_cfg->qos, sizeof(FLOW_SPEC));
4268843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    new_qos.qos_present = TRUE;
4278843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4288843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: config failed, retry", __func__);
4298843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4308843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    L2CA_ConfigReq(cid, &new_qos);
4318843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return;
4328843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  } else if (p_hcon->intr_cid == cid &&
4338843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta             p_cfg->result == L2CAP_CFG_UNKNOWN_OPTIONS) {
4348843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    // QoS not understood by remote device, try configuring without QoS
4358843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4368843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: config failed, retry without QoS", __func__);
4378843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4388843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    L2CA_ConfigReq(cid, &hd_cb.l2cap_cfg);
4398843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return;
4408843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  } else if (p_cfg->result != L2CAP_CFG_OK) {
4418843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: config failed, disconnecting", __func__);
4428843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4438843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    hidd_conn_disconnect();
4448843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    reason = HID_L2CAP_CFG_FAIL | (uint32_t)p_cfg->result;
4458843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4468843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, reason, NULL);
4478843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return;
4488843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
4498843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4508843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  // update flags
4518843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (cid == p_hcon->ctrl_cid) {
4528843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->conn_flags |= HID_CONN_FLAGS_MY_CTRL_CFG_DONE;
4538843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4548843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) &&
4558843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        (p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE)) {
4568843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;
4578843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      if ((p_hcon->intr_cid =
4588843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta               L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) {
4598843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        hidd_conn_disconnect();
460367373ba8bcfb1d9db41b1904de372483991fc10Ivan Podogov        p_hcon->conn_state = HID_CONN_STATE_UNUSED;
4618843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4628843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        HIDD_TRACE_WARNING("%s: could not start L2CAP connection for INTR",
4638843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                           __func__);
4648843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE,
4658843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                       HID_ERR_L2CAP_FAILED, NULL);
4668843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        return;
4678843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      } else {
4688843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        p_hcon->conn_state = HID_CONN_STATE_CONNECTING_INTR;
4698843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      }
4708843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    }
4718843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  } else {
4728843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->conn_flags |= HID_CONN_FLAGS_MY_INTR_CFG_DONE;
4738843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
4748843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4758843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  hidd_check_config_done();
4768843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta}
4778843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4788843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta/*******************************************************************************
4798843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
4808843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Function         hidd_l2cif_disconnect_ind
4818843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
4828843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Description      Handler incoming L2CAP disconnection request
4838843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
4848843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Returns          void
4858843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
4868843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta ******************************************************************************/
4878843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptastatic void hidd_l2cif_disconnect_ind(uint16_t cid, bool ack_needed) {
4888843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  tHID_CONN* p_hcon;
4898843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4908843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  HIDD_TRACE_EVENT("%s: cid=%04x ack_needed=%d", __func__, cid, ack_needed);
4918843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4928843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_hcon = &hd_cb.device.conn;
4938843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
4948843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (p_hcon->conn_state == HID_CONN_STATE_UNUSED ||
4958843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
4968843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: unknown cid", __func__);
4978843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return;
4988843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
4998843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5008843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (ack_needed) L2CA_DisconnectRsp(cid);
5018843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5028843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING;
5038843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5048843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (cid == p_hcon->ctrl_cid)
5058843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->ctrl_cid = 0;
5068843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  else
5078843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->intr_cid = 0;
5088843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5098843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) {
5108843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_EVENT("%s: INTR and CTRL disconnected", __func__);
5118843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5128843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    // clean any outstanding data on intr
5138843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    if (hd_cb.pending_data) {
5148843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      osi_free(hd_cb.pending_data);
5158843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      hd_cb.pending_data = NULL;
5168843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    }
5178843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5188843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    hd_cb.device.state = HIDD_DEV_NO_CONN;
5198843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->conn_state = HID_CONN_STATE_UNUSED;
5208843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5218843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, p_hcon->disc_reason,
5228843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                   NULL);
5238843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
5248843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta}
5258843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5268843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta/*******************************************************************************
5278843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
5288843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Function         hidd_l2cif_disconnect_cfm
5298843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
5308843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Description      Handles L2CAP disconection response
5318843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
5328843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Returns          void
5338843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
5348843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta ******************************************************************************/
5358843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptastatic void hidd_l2cif_disconnect_cfm(uint16_t cid, uint16_t result) {
5368843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  tHID_CONN* p_hcon;
5378843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5388843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  HIDD_TRACE_EVENT("%s: cid=%04x result=%d", __func__, cid, result);
5398843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5408843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_hcon = &hd_cb.device.conn;
5418843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5428843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (p_hcon->conn_state == HID_CONN_STATE_UNUSED ||
5438843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
5448843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: unknown cid", __func__);
5458843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return;
5468843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
5478843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5488843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (cid == p_hcon->ctrl_cid) {
5498843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->ctrl_cid = 0;
5508843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  } else {
5518843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->intr_cid = 0;
5528843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5538843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    // now disconnect CTRL
5548843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    L2CA_DisconnectReq(p_hcon->ctrl_cid);
5558843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
5568843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5578843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) {
5588843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_EVENT("%s: INTR and CTRL disconnected", __func__);
5598843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5608843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    hd_cb.device.state = HIDD_DEV_NO_CONN;
5618843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->conn_state = HID_CONN_STATE_UNUSED;
5628843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5638843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    if (hd_cb.pending_vc_unplug) {
5648843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_VC_UNPLUG,
5658843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                     p_hcon->disc_reason, NULL);
5668843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      hd_cb.pending_vc_unplug = FALSE;
5678843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    } else {
5688843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE,
5698843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                     p_hcon->disc_reason, NULL);
5708843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    }
5718843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
5728843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta}
5738843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5748843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta/*******************************************************************************
5758843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
5768843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Function         hidd_l2cif_cong_ind
5778843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
5788843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Description      Handles L2CAP congestion status event
5798843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
5808843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Returns          void
5818843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
5828843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta ******************************************************************************/
5838843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptastatic void hidd_l2cif_cong_ind(uint16_t cid, bool congested) {
5848843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  tHID_CONN* p_hcon;
5858843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5868843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  HIDD_TRACE_EVENT("%s: cid=%04x congested=%d", __func__, cid, congested);
5878843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5888843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_hcon = &hd_cb.device.conn;
5898843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5908843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (p_hcon->conn_state == HID_CONN_STATE_UNUSED ||
5918843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
5928843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: unknown cid", __func__);
5938843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return;
5948843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
5958843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
5968843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (congested) {
5978843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->conn_flags |= HID_CONN_FLAGS_CONGESTED;
5988843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  } else {
5998843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->conn_flags &= ~HID_CONN_FLAGS_CONGESTED;
6008843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
6018843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta}
6028843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
6038843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta/*******************************************************************************
6048843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
6058843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Function         hidd_l2cif_data_ind
6068843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
6078843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Description      Handler incoming data on L2CAP channel
6088843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
6098843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Returns          void
6108843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
6118843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta ******************************************************************************/
6128843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptastatic void hidd_l2cif_data_ind(uint16_t cid, BT_HDR* p_msg) {
6138843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  tHID_CONN* p_hcon;
6148843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  uint8_t* p_data = (uint8_t*)(p_msg + 1) + p_msg->offset;
6158843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  uint8_t msg_type, param;
6168843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  bool err = FALSE;
6178843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
6188843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid);
6198843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
6208843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_hcon = &hd_cb.device.conn;
6218843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
6228843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (p_hcon->conn_state == HID_CONN_STATE_UNUSED ||
6238843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
6248843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: unknown cid", __func__);
6258843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    osi_free(p_msg);
6268843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return;
6278843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
6288843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
6298843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  msg_type = HID_GET_TRANS_FROM_HDR(*p_data);
6308843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  param = HID_GET_PARAM_FROM_HDR(*p_data);
6318843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
6328843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (msg_type == HID_TRANS_DATA && cid == p_hcon->intr_cid) {
6338843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    // skip HID header
6348843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_msg->offset++;
6358843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_msg->len--;
6368843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
6378843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_INTR_DATA, 0, p_msg);
6388843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return;
6398843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
6408843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
6418843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  switch (msg_type) {
6428843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    case HID_TRANS_GET_REPORT:
6438843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      // at this stage we don't know if Report Id shall be included in request
6448843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      // so we pass complete packet in callback and let other code analyze this
6458843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_GET_REPORT,
6468843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                     !!(param & HID_PAR_GET_REP_BUFSIZE_FOLLOWS), p_msg);
6478843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      break;
6488843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
6498843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    case HID_TRANS_SET_REPORT:
6508843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      // as above
6518843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_SET_REPORT, 0, p_msg);
6528843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      break;
6538843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
6548843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    case HID_TRANS_GET_IDLE:
6558843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_DATA,
6568843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                          HID_PAR_REP_TYPE_OTHER, hd_cb.device.idle_time, 0,
6578843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                          NULL);
6588843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      osi_free(p_msg);
6598843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      break;
6608843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
6618843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    case HID_TRANS_SET_IDLE:
6628843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      if (p_msg->len != 2) {
6638843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        HIDD_TRACE_ERROR("%s: invalid len (%d) set idle request received",
6648843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                         __func__, p_msg->len);
6658843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        err = TRUE;
6668843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      } else {
6678843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        hd_cb.device.idle_time = p_data[1];
6688843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        HIDD_TRACE_DEBUG("%s: idle_time = %d", __func__,
6698843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                         hd_cb.device.idle_time);
6708843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        if (hd_cb.device.idle_time) {
6718843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta          HIDD_TRACE_WARNING(
6728843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta              "%s: idle_time of %d ms not supported by HID Device", __func__,
6738843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta              (hd_cb.device.idle_time * 4));
6748843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta          err = TRUE;
6758843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        }
6768843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      }
6778843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      if (!err) {
6788843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        hidd_conn_send_data(0, HID_TRANS_HANDSHAKE,
6798843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                            HID_PAR_HANDSHAKE_RSP_SUCCESS, 0, 0, NULL);
6808843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      } else {
6818843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        hidd_conn_send_data(0, HID_TRANS_HANDSHAKE,
6828843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                            HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM, 0, 0,
6838843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                            NULL);
6848843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      }
6858843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      osi_free(p_msg);
6868843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      break;
6878843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
6888843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    case HID_TRANS_GET_PROTOCOL:
6898843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_DATA,
6908843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                          HID_PAR_REP_TYPE_OTHER, !hd_cb.device.boot_mode, 0,
6918843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                          NULL);
6928843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      osi_free(p_msg);
6938843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      break;
6948843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
6958843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    case HID_TRANS_SET_PROTOCOL:
6968843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      hd_cb.device.boot_mode = !(param & HID_PAR_PROTOCOL_MASK);
6978843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_SET_PROTOCOL,
6988843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                     param & HID_PAR_PROTOCOL_MASK, NULL);
6998843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, HID_PAR_HANDSHAKE_RSP_SUCCESS,
7008843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                          0, 0, NULL);
7018843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      osi_free(p_msg);
7028843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      break;
7038843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
7048843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    case HID_TRANS_CONTROL:
7058843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      switch (param) {
7068843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        case HID_PAR_CONTROL_SUSPEND:
7078843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta          hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_SUSPEND, 0, NULL);
7088843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta          break;
7098843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
7108843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        case HID_PAR_CONTROL_EXIT_SUSPEND:
7118843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta          hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_EXIT_SUSPEND, 0,
7128843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                         NULL);
7138843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta          break;
7148843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
7158843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        case HID_PAR_CONTROL_VIRTUAL_CABLE_UNPLUG:
7168843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta          hidd_conn_disconnect();
7178843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
7188843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta          // set flag so we can notify properly when disconnected
7198843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta          hd_cb.pending_vc_unplug = TRUE;
7208843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta          break;
7218843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      }
7228843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
7238843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      osi_free(p_msg);
7248843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      break;
7258843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
7268843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    case HID_TRANS_DATA:
7278843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    default:
7288843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      HIDD_TRACE_WARNING("%s: got unsupported msg (%d)", __func__, msg_type);
7298843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      hidd_conn_send_data(0, HID_TRANS_HANDSHAKE,
7308843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                          HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ, 0, 0,
7318843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                          NULL);
7328843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      osi_free(p_msg);
7338843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      break;
7348843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
7358843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta}
7368843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
7378843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta/*******************************************************************************
7388843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
7398843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Function         hidd_conn_reg
7408843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
7418843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Description      Registers L2CAP channels
7428843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
7438843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Returns          void
7448843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
7458843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta ******************************************************************************/
7468843cc830b522cfe6f1e361297fc28fd331a1378Hemant GuptatHID_STATUS hidd_conn_reg(void) {
7478843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  HIDD_TRACE_API("%s", __func__);
7488843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
7498843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  memset(&hd_cb.l2cap_cfg, 0, sizeof(tL2CAP_CFG_INFO));
7508843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
7518843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  hd_cb.l2cap_cfg.mtu_present = TRUE;
7528843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  hd_cb.l2cap_cfg.mtu = HID_DEV_MTU_SIZE;
7538843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  hd_cb.l2cap_cfg.flush_to_present = TRUE;
7548843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  hd_cb.l2cap_cfg.flush_to = HID_DEV_FLUSH_TO;
7558843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
7568843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  memset(&hd_cb.l2cap_intr_cfg, 0, sizeof(tL2CAP_CFG_INFO));
7578843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  hd_cb.l2cap_intr_cfg.mtu_present = TRUE;
7588843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  hd_cb.l2cap_intr_cfg.mtu = HID_DEV_MTU_SIZE;
7598843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  hd_cb.l2cap_intr_cfg.flush_to_present = TRUE;
7608843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  hd_cb.l2cap_intr_cfg.flush_to = HID_DEV_FLUSH_TO;
7618843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
7628843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (!L2CA_Register(HID_PSM_CONTROL, (tL2CAP_APPL_INFO*)&dev_reg_info)) {
7638843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_ERROR("HID Control (device) registration failed");
7648843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return (HID_ERR_L2CAP_FAILED);
7658843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
7668843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
7678843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (!L2CA_Register(HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO*)&dev_reg_info)) {
7688843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    L2CA_Deregister(HID_PSM_CONTROL);
7698843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_ERROR("HID Interrupt (device) registration failed");
7708843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return (HID_ERR_L2CAP_FAILED);
7718843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
7728843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
7738843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  return (HID_SUCCESS);
7748843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta}
7758843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
7768843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta/*******************************************************************************
7778843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
7788843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Function         hidd_conn_dereg
7798843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
7808843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Description      Deregisters L2CAP channels
7818843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
7828843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Returns          void
7838843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
7848843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta ******************************************************************************/
7858843cc830b522cfe6f1e361297fc28fd331a1378Hemant Guptavoid hidd_conn_dereg(void) {
7868843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  HIDD_TRACE_API("%s", __func__);
7878843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
7888843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  L2CA_Deregister(HID_PSM_CONTROL);
7898843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  L2CA_Deregister(HID_PSM_INTERRUPT);
7908843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta}
7918843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
7928843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta/*******************************************************************************
7938843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
7948843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Function         hidd_conn_initiate
7958843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
7968843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Description      Initiates HID connection to plugged device
7978843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
7988843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Returns          HID_SUCCESS
7998843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
8008843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta ******************************************************************************/
8018843cc830b522cfe6f1e361297fc28fd331a1378Hemant GuptatHID_STATUS hidd_conn_initiate(void) {
8028843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  tHID_DEV_DEV_CTB* p_dev = &hd_cb.device;
8038843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
8048843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  HIDD_TRACE_API("%s", __func__);
8058843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
8068843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (!p_dev->in_use) {
8078843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: no virtual cable established", __func__);
8088843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return (HID_ERR_NOT_REGISTERED);
8098843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
8108843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
8118843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (p_dev->conn.conn_state != HID_CONN_STATE_UNUSED) {
8128843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: connection already in progress", __func__);
8138843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return (HID_ERR_CONN_IN_PROCESS);
8148843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
8158843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
8168843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_dev->conn.ctrl_cid = 0;
8178843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_dev->conn.intr_cid = 0;
8188843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_dev->conn.disc_reason = HID_L2CAP_CONN_FAIL;
8198843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
8208843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_dev->conn.conn_flags = HID_CONN_FLAGS_IS_ORIG;
8218843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
8228843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  BTM_SetOutService(p_dev->addr, BTM_SEC_SERVICE_HIDD_SEC_CTRL, HIDD_SEC_CHN);
8238843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
8248843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  /* Check if L2CAP started the connection process */
8258843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if ((p_dev->conn.ctrl_cid = L2CA_ConnectReq(HID_PSM_CONTROL, p_dev->addr)) ==
8268843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      0) {
8278843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: could not start L2CAP connection", __func__);
8288843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_ERR_L2CAP_FAILED,
8298843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                   NULL);
8308843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  } else {
8318843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_dev->conn.conn_state = HID_CONN_STATE_CONNECTING_CTRL;
8328843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
8338843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
8348843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  return (HID_SUCCESS);
8358843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta}
8368843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
8378843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta/*******************************************************************************
8388843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
8398843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Function         hidd_conn_disconnect
8408843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
8418843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Description      Disconnects existing HID connection
8428843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
8438843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Returns          HID_SUCCESS
8448843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
8458843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta ******************************************************************************/
8468843cc830b522cfe6f1e361297fc28fd331a1378Hemant GuptatHID_STATUS hidd_conn_disconnect(void) {
8478843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  tHID_CONN* p_hcon;
8488843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
8498843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  HIDD_TRACE_API("%s", __func__);
8508843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
8518843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  // clean any outstanding data on intr
8528843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (hd_cb.pending_data) {
8538843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    osi_free(hd_cb.pending_data);
8548843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    hd_cb.pending_data = NULL;
8558843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
8568843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
8578843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_hcon = &hd_cb.device.conn;
8588843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
8598843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if ((p_hcon->ctrl_cid != 0) || (p_hcon->intr_cid != 0)) {
8608843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING;
8618843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
8628843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    /* Set l2cap idle timeout to 0 (so ACL link is disconnected
8638843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta     * immediately after last channel is closed) */
8648843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    L2CA_SetIdleTimeoutByBdAddr(hd_cb.device.addr, 0, BT_TRANSPORT_BR_EDR);
8658843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
8668843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    if (p_hcon->intr_cid) {
8678843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      L2CA_DisconnectReq(p_hcon->intr_cid);
8688843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    } else if (p_hcon->ctrl_cid) {
8698843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      L2CA_DisconnectReq(p_hcon->ctrl_cid);
8708843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    }
8718843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  } else {
8728843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_WARNING("%s: already disconnected", __func__);
8738843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_hcon->conn_state = HID_CONN_STATE_UNUSED;
8748843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
8758843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
8768843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  return (HID_SUCCESS);
8778843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta}
8788843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
8798843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta/*******************************************************************************
8808843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
8818843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Function         hidd_conn_send_data
8828843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
8838843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Description      Sends data to host
8848843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
8858843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta * Returns          tHID_STATUS
8868843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta *
8878843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta ******************************************************************************/
8888843cc830b522cfe6f1e361297fc28fd331a1378Hemant GuptatHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type,
8898843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                uint8_t param, uint8_t data, uint16_t len,
8908843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                                uint8_t* p_data) {
8918843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  tHID_CONN* p_hcon;
8928843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  BT_HDR* p_buf;
8938843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  uint8_t* p_out;
8948843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  uint16_t cid;
8958843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  uint16_t buf_size;
8968843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
8978843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  HIDD_TRACE_VERBOSE("%s: channel(%d), msg_type(%d), len(%d)", __func__,
8988843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta                     channel, msg_type, len);
8998843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
9008843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_hcon = &hd_cb.device.conn;
9018843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
9028843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (p_hcon->conn_flags & HID_CONN_FLAGS_CONGESTED) {
9038843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return HID_ERR_CONGESTED;
9048843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
9058843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
9068843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  switch (msg_type) {
9078843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    case HID_TRANS_HANDSHAKE:
9088843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    case HID_TRANS_CONTROL:
9098843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      cid = p_hcon->ctrl_cid;
9108843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      buf_size = HID_CONTROL_BUF_SIZE;
9118843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      break;
9128843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    case HID_TRANS_DATA:
9138843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      if (channel == HID_CHANNEL_CTRL) {
9148843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        cid = p_hcon->ctrl_cid;
9158843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        buf_size = HID_CONTROL_BUF_SIZE;
9168843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      } else {
9178843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        cid = p_hcon->intr_cid;
9188843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        buf_size = HID_INTERRUPT_BUF_SIZE;
9198843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      }
9208843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      break;
9218843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    default:
9228843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      return (HID_ERR_INVALID_PARAM);
9238843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
9248843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
9258843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_buf = (BT_HDR*)osi_malloc(buf_size);
9268843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (p_buf == NULL) return (HID_ERR_NO_RESOURCES);
9278843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
9288843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_buf->offset = L2CAP_MIN_OFFSET;
9298843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
9308843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_out = (uint8_t*)(p_buf + 1) + p_buf->offset;
9318843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
9328843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  *p_out = HID_BUILD_HDR(msg_type, param);
9338843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_out++;
9348843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
9358843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  p_buf->len = 1;  // start with header only
9368843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
9378843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  // add report id prefix only if non-zero (which is reserved)
9388843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (msg_type == HID_TRANS_DATA && (data || param == HID_PAR_REP_TYPE_OTHER)) {
9398843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    *p_out = data;  // report_id
9408843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_out++;
9418843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_buf->len++;
9428843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
9438843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
9448843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (len > 0 && p_data != NULL) {
9458843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    memcpy(p_out, p_data, len);
9468843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    p_buf->len += len;
9478843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
9488843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
9498843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  // check if connected
9508843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (hd_cb.device.state != HIDD_DEV_CONNECTED) {
9518843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    // for DATA on intr we hold transfer and try to reconnect
9528843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    if (msg_type == HID_TRANS_DATA && cid == p_hcon->intr_cid) {
9538843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      // drop previous data, we do not queue it for now
9548843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      if (hd_cb.pending_data) {
9558843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        osi_free(hd_cb.pending_data);
9568843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      }
9578843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
9588843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      hd_cb.pending_data = p_buf;
9598843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
9608843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      if (hd_cb.device.conn.conn_state == HID_CONN_STATE_UNUSED) {
9618843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta        hidd_conn_initiate();
9628843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      }
9638843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
9648843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta      return HID_SUCCESS;
9658843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    }
9668843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
9678843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    return HID_ERR_NO_CONNECTION;
9688843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
9698843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
9708843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta#ifdef REPORT_TRANSFER_TIMESTAMP
9718843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (report_transfer) {
9728843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta    HIDD_TRACE_ERROR("%s: report sent", __func__);
9738843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  }
9748843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta#endif
9758843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  HIDD_TRACE_VERBOSE("%s: report sent", __func__);
9768843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
9778843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  if (!L2CA_DataWrite(cid, p_buf)) return (HID_ERR_CONGESTED);
9788843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta
9798843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta  return (HID_SUCCESS);
9808843cc830b522cfe6f1e361297fc28fd331a1378Hemant Gupta}
981