/******************************************************************************* ** ** Function bta_hh_start_sdp ** ** Description Start SDP service search, and obtain necessary SDP records. ** Only one SDP service search request is allowed at the same ** time. For every BTA_HhOpen API call, do SDP first unless SDP ** has been done previously. ** ** Returns void ** *******************************************************************************/ void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) { tBTA_HH_STATUS status = BTA_HH_ERR_SDP; UINT8 hdl; p_cb->sec_mask = p_data->api_conn.sec_mask; p_cb->mode = p_data->api_conn.mode; bta_hh_cb.p_cur = p_cb; #if (BTA_HH_LE_INCLUDED == TRUE) if (bta_hh_is_le_device(p_cb, p_data->api_conn.bd_addr)) { bta_hh_le_open_conn(p_cb, p_data->api_conn.bd_addr); return; } #endif /* if previously virtually cabled device, skip SDP */ if (p_cb->app_id) { status = BTA_HH_OK; #if BTA_HH_DEBUG APPL_TRACE_DEBUG("bta_hh_start_sdp:: skip SDP for known devices"); #endif if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE) { if (HID_HostAddDev (p_cb->addr, p_cb->attr_mask, &hdl) \ == HID_SUCCESS) { /* update device CB with newly register device handle */ bta_hh_add_device_to_list(p_cb, hdl, p_cb->attr_mask, NULL, p_cb->sub_class, p_cb->dscp_info.ssr_max_latency, p_cb->dscp_info.ssr_min_tout, p_cb->app_id); /* update cb_index[] map */ bta_hh_cb.cb_index[hdl] = p_cb->index; } else status = BTA_HH_ERR_NO_RES; } bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status); return; } /* GetSDPRecord. at one time only one SDP precedure can be active */ else if (!bta_hh_cb.p_disc_db) { bta_hh_cb.p_disc_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(p_bta_hh_cfg->sdp_db_size); if (bta_hh_cb.p_disc_db == NULL) { status = BTA_HH_ERR_NO_RES; } else { bta_hh_cb.p_cur = p_cb; /* do DI discovery first */ if (SDP_DiDiscover(p_data->api_conn.bd_addr, bta_hh_cb.p_disc_db, p_bta_hh_cfg->sdp_db_size, bta_hh_di_sdp_cback) != SDP_SUCCESS) { #if BTA_HH_DEBUG APPL_TRACE_DEBUG ("bta_hh_start_sdp: SDP_DiDiscover failed: \ Status 0x%2X",status); #endif status = BTA_HH_ERR_SDP; utl_freebuf((void **)&bta_hh_cb.p_disc_db); } else
/******************************************************************************* ** ** Function hidh_l2cif_connect_ind ** ** Description This function handles an inbound connection indication ** from L2CAP. This is the case where we are acting as a ** server. ** ** Returns void ** *******************************************************************************/ static void hidh_l2cif_connect_ind (BD_ADDR bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id) { tHID_CONN *p_hcon; BOOLEAN bAccept = TRUE; UINT8 i = HID_HOST_MAX_DEVICES; tHID_HOST_DEV_CTB *p_dev; HIDH_TRACE_EVENT ("HID-Host Rcvd L2CAP conn ind, PSM: 0x%04x CID 0x%x", psm, l2cap_cid); /* always add incoming connection device into HID database by default */ if (HID_HostAddDev(bd_addr, HID_SEC_REQUIRED, &i) != HID_SUCCESS) { L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_SECURITY_BLOCK, 0); return; } p_hcon = &hh_cb.devices[i].conn; p_dev = &hh_cb.devices[i]; /* Stop the retry timer if active */ #if (HID_HOST_MAX_CONN_RETRY > 0) #if (HID_HOST_REPAGE_WIN > 0) HIDH_TRACE_DEBUG ("HID-Host stopping retry timer as l2cap is connected from remote side"); p_dev->conn_tries = HID_HOST_MAX_CONN_RETRY+1; btu_stop_timer(&(p_dev->conn.timer_entry)); #endif #endif /* Check we are in the correct state for this */ if (psm == HID_PSM_INTERRUPT) { if (p_hcon->ctrl_cid == 0) { HIDH_TRACE_WARNING ("HID-Host Rcvd INTR L2CAP conn ind, but no CTL channel"); bAccept = FALSE; } if (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) { HIDH_TRACE_WARNING ("HID-Host Rcvd INTR L2CAP conn ind, wrong state: %d", p_hcon->conn_state); bAccept = FALSE; } } else /* CTRL channel */ { #if defined(HID_HOST_ACPT_NEW_CONN) && (HID_HOST_ACPT_NEW_CONN == TRUE) p_hcon->ctrl_cid = p_hcon->intr_cid = 0; p_hcon->conn_state = HID_CONN_STATE_UNUSED; #else if (p_hcon->conn_state != HID_CONN_STATE_UNUSED) { HIDH_TRACE_WARNING ("HID-Host - Rcvd CTL L2CAP conn ind, wrong state: %d", p_hcon->conn_state); bAccept = FALSE; } #endif } if (!bAccept) { L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_NO_RESOURCES, 0); return; } if (psm == HID_PSM_CONTROL) { p_hcon->conn_flags = 0; p_hcon->ctrl_cid = l2cap_cid; p_hcon->ctrl_id = l2cap_id; p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* In case disconnection occurs before security is completed, then set CLOSE_EVT reason code to 'connection failure' */ p_hcon->conn_state = HID_CONN_STATE_SECURITY; if (!interop_addr_match(INTEROP_DISABLE_AUTH_FOR_HID_POINTING, (bt_bdaddr_t*)p_dev->addr)) { if(btm_sec_mx_access_request (p_dev->addr, HID_PSM_CONTROL, FALSE, BTM_SEC_PROTO_HID, (p_dev->attr_mask & HID_SEC_REQUIRED) ? HID_SEC_CHN : HID_NOSEC_CHN, &hidh_sec_check_complete_term, p_dev) == BTM_CMD_STARTED) { L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_PENDING, L2CAP_CONN_OK); } } else { /* device is blacklisted, don't perform authentication */ L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_PENDING, L2CAP_CONN_OK); hidh_sec_check_complete_term(p_dev->addr, BT_TRANSPORT_BR_EDR, p_dev, BTM_SUCCESS); } return; } /* Transition to the next appropriate state, configuration */ p_hcon->conn_state = HID_CONN_STATE_CONFIG; p_hcon->intr_cid = l2cap_cid; /* Send response to the L2CAP layer. */ L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK); /* Send a Configuration Request. */ L2CA_ConfigReq (l2cap_cid, &hh_cb.l2cap_cfg); HIDH_TRACE_EVENT ("HID-Host Rcvd L2CAP conn ind, sent config req, PSM: 0x%04x CID 0x%x", psm, l2cap_cid); }
/******************************************************************************* ** ** Function bta_hh_sdp_cback ** ** Description SDP callback function. ** ** Returns void ** *******************************************************************************/ static void bta_hh_sdp_cback(UINT16 result, UINT16 attr_mask, tHID_DEV_SDP_INFO *sdp_rec ) { tBTA_HH_DEV_CB *p_cb = bta_hh_cb.p_cur; UINT8 hdl = 0; tBTA_HH_STATUS status = BTA_HH_ERR_SDP; /* make sure sdp succeeded and hh has not been disabled */ if ((result == SDP_SUCCESS) && (p_cb != NULL)) { /* security is required for the connection, add attr_mask bit*/ if (p_cb->sec_mask) attr_mask |= HID_SEC_REQUIRED; #if BTA_HH_DEBUG APPL_TRACE_EVENT("bta_hh_sdp_cback: p_cb: %d result 0x%02x, \ attr_mask 0x%02x, handle %x", \ p_cb, result, attr_mask,p_cb->hid_handle); #endif /* check to see type of device is supported , and should not been added before */ if (bta_hh_tod_spt(p_cb, sdp_rec->sub_class)) { /* if not added before */ if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE) { /* add device/update attr_mask information */ if(HID_HostAddDev (p_cb->addr, attr_mask, &hdl) == HID_SUCCESS) { status = BTA_HH_OK; /* update cb_index[] map */ bta_hh_cb.cb_index[hdl] = p_cb->index; } else { p_cb->app_id = 0; } } else { hdl = p_cb->hid_handle; } /* else : incoming connection after SDP should update the SDP information as well */ if (p_cb->app_id != 0) { /* update cb information with attr_mask, dscp_info etc. */ bta_hh_add_device_to_list(p_cb, hdl, attr_mask, &sdp_rec->dscp_info, sdp_rec->sub_class, sdp_rec->ssr_max_latency, sdp_rec->ssr_min_tout, p_cb->app_id); p_cb->dscp_info.ctry_code = sdp_rec->ctry_code; status = BTA_HH_OK; } } else /* type of device is not supported */ status = BTA_HH_ERR_TOD_UNSPT; } /* free disc_db when SDP is completed */ utl_freebuf((void **)&bta_hh_cb.p_disc_db); /* send SDP_CMPL_EVT into state machine */ bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status); return; }
/******************************************************************************* ** ** Function hidh_l2cif_connect_ind ** ** Description This function handles an inbound connection indication ** from L2CAP. This is the case where we are acting as a ** server. ** ** Returns void ** *******************************************************************************/ static void hidh_l2cif_connect_ind (BD_ADDR bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id) { tHID_CONN *p_hcon; BOOLEAN bAccept = TRUE; UINT8 i = HID_HOST_MAX_DEVICES; tHID_HOST_DEV_CTB *p_dev; HIDH_TRACE_EVENT2 ("HID-Host Rcvd L2CAP conn ind, PSM: 0x%04x CID 0x%x", psm, l2cap_cid); /* always add incoming connection device into HID database by default */ if (HID_HostAddDev(bd_addr, HID_SEC_REQUIRED, &i) != HID_SUCCESS) { L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_SECURITY_BLOCK, 0); return; } p_hcon = &hh_cb.devices[i].conn; p_dev = &hh_cb.devices[i]; /* Check we are in the correct state for this */ if (psm == HID_PSM_INTERRUPT) { if (p_hcon->ctrl_cid == 0) { HIDH_TRACE_WARNING0 ("HID-Host Rcvd INTR L2CAP conn ind, but no CTL channel"); bAccept = FALSE; } if (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) { HIDH_TRACE_WARNING1 ("HID-Host Rcvd INTR L2CAP conn ind, wrong state: %d", p_hcon->conn_state); bAccept = FALSE; } } else /* CTRL channel */ { #if defined(HID_HOST_ACPT_NEW_CONN) && (HID_HOST_ACPT_NEW_CONN == TRUE) p_hcon->ctrl_cid = p_hcon->intr_cid = 0; p_hcon->conn_state = HID_CONN_STATE_UNUSED; #else if (p_hcon->conn_state != HID_CONN_STATE_UNUSED) { HIDH_TRACE_WARNING1 ("HID-Host - Rcvd CTL L2CAP conn ind, wrong state: %d", p_hcon->conn_state); bAccept = FALSE; } #endif } if (!bAccept) { L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_NO_RESOURCES, 0); return; } if (psm == HID_PSM_CONTROL) { p_hcon->conn_flags = 0; p_hcon->ctrl_cid = l2cap_cid; p_hcon->ctrl_id = l2cap_id; p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* In case disconnection occurs before security is completed, then set CLOSE_EVT reason code to 'connection failure' */ p_hcon->conn_state = HID_CONN_STATE_SECURITY; if(btm_sec_mx_access_request (p_dev->addr, HID_PSM_CONTROL, FALSE, BTM_SEC_PROTO_HID, (p_dev->attr_mask & HID_SEC_REQUIRED) ? HID_SEC_CHN : HID_NOSEC_CHN, &hidh_sec_check_complete_term, p_dev) == BTM_CMD_STARTED) { L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_PENDING, L2CAP_CONN_OK); } return; } /* Transition to the next appropriate state, configuration */ p_hcon->conn_state = HID_CONN_STATE_CONFIG; p_hcon->intr_cid = l2cap_cid; /* Send response to the L2CAP layer. */ L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK); /* Send a Configuration Request. */ L2CA_ConfigReq (l2cap_cid, &hh_cb.l2cap_cfg); HIDH_TRACE_EVENT2 ("HID-Host Rcvd L2CAP conn ind, sent config req, PSM: 0x%04x CID 0x%x", psm, l2cap_cid); }