/******************************************************************************* ** ** Function bta_gattc_clcb_dealloc ** ** Description Deallocte a clcb ** ** Returns pointer to the clcb ** *******************************************************************************/ void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb) { tBTA_GATTC_SERV *p_srcb = NULL; if (p_clcb) { p_srcb = p_clcb->p_srcb; if (p_srcb->num_clcb) p_srcb->num_clcb --; if (p_clcb->p_rcb->num_clcb) p_clcb->p_rcb->num_clcb --; /* if the srcb is no longer needed, reset the state */ if ( p_srcb->num_clcb == 0) { p_srcb->connected = FALSE; p_srcb->state = BTA_GATTC_SERV_IDLE; p_srcb->mtu = 0; } utl_freebuf((void **)&p_clcb->p_q_cmd); memset(p_clcb, 0, sizeof(tBTA_GATTC_CLCB)); } else { APPL_TRACE_ERROR("bta_gattc_clcb_dealloc p_clcb=NULL"); } }
/******************************************************************************* ** ** Function bta_hh_di_sdp_cback ** ** Description SDP DI callback function. ** ** Returns void ** *******************************************************************************/ static void bta_hh_di_sdp_cback(UINT16 result) { tBTA_HH_DEV_CB *p_cb = bta_hh_cb.p_cur; tBTA_HH_STATUS status = BTA_HH_ERR_SDP; tSDP_DI_GET_RECORD di_rec; tHID_STATUS ret; #if BTA_HH_DEBUG APPL_TRACE_EVENT("bta_hh_di_sdp_cback: p_cb: %d result 0x%02x", p_cb, result); #endif /* if DI record does not exist on remote device, vendor_id in tBTA_HH_DEV_DSCP_INFO will be * set to 0xffff and we will allow the connection to go through. Spec mandates that DI * record be set, but many HID devices do not set this. So for IOP purposes, we allow the * connection to go through and update the DI record to invalid DI entry.*/ if (((result == SDP_SUCCESS) || (result == SDP_NO_RECS_MATCH)) && (p_cb != NULL)) { if(result == SDP_SUCCESS && SDP_GetNumDiRecords(bta_hh_cb.p_disc_db) != 0) { /* always update information with primary DI record */ if (SDP_GetDiRecord(1, &di_rec, bta_hh_cb.p_disc_db) == SDP_SUCCESS) { bta_hh_update_di_info(p_cb, di_rec.rec.vendor, di_rec.rec.product, di_rec.rec.version, 0); } } else /* no DI recrod available */ { bta_hh_update_di_info(p_cb, BTA_HH_VENDOR_ID_INVALID, 0, 0, 0); } if ((ret = HID_HostGetSDPRecord(p_cb->addr, bta_hh_cb.p_disc_db, p_bta_hh_cfg->sdp_db_size, bta_hh_sdp_cback)) == HID_SUCCESS) { status = BTA_HH_OK; } else { #if BTA_HH_DEBUG APPL_TRACE_DEBUG ("bta_hh_di_sdp_cback: HID_HostGetSDPRecord failed: Status 0x%2x", ret); #endif } } if (status != BTA_HH_OK) { 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 bta_gattc_srcb_alloc ** ** Description allocate server cache control block ** ** Returns pointer to the server cache. ** *******************************************************************************/ tBTA_GATTC_SERV * bta_gattc_srcb_alloc(BD_ADDR bda) { tBTA_GATTC_SERV *p_tcb = &bta_gattc_cb.known_server[0], *p_recycle = NULL; BOOLEAN found = FALSE; UINT8 i; for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_tcb ++) { if (!p_tcb->in_use) { found = TRUE; break; } else if (!p_tcb->connected) { p_recycle = p_tcb; } } /* if not found, try to recycle one known device */ if (!found && !p_recycle) p_tcb = NULL; else if (!found && p_recycle) p_tcb = p_recycle; if (p_tcb != NULL) { while (!GKI_queue_is_empty(&p_tcb->cache_buffer)) GKI_freebuf (GKI_dequeue (&p_tcb->cache_buffer)); utl_freebuf((void **)&p_tcb->p_srvc_list); memset(p_tcb, 0 , sizeof(tBTA_GATTC_SERV)); p_tcb->in_use = TRUE; bdcpy(p_tcb->server_bda, bda); } return p_tcb; }
/******************************************************************************* ** ** 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 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; }