/******************************************************************************* ** ** Function nfc_hal_dm_set_config ** ** Description Send NCI config items to NFCC ** ** Returns tHAL_NFC_STATUS ** *******************************************************************************/ tHAL_NFC_STATUS nfc_hal_dm_set_config (UINT8 tlv_size, UINT8 *p_param_tlvs, tNFC_HAL_NCI_CBACK *p_cback) { UINT8 *p_buff, *p; UINT8 num_param = 0, param_len, rem_len, *p_tlv; UINT16 cmd_len = NCI_MSG_HDR_SIZE + tlv_size + 1; tHAL_NFC_STATUS status = HAL_NFC_STATUS_FAILED; if ((tlv_size == 0)||(p_param_tlvs == NULL)) { return status; } if ((p_buff = (UINT8 *) GKI_getbuf ((UINT16)(NCI_MSG_HDR_SIZE + tlv_size))) != NULL) { p = p_buff; NCI_MSG_BLD_HDR0 (p, NCI_MT_CMD, NCI_GID_CORE); NCI_MSG_BLD_HDR1 (p, NCI_MSG_CORE_SET_CONFIG); UINT8_TO_STREAM (p, (UINT8) (tlv_size + 1)); rem_len = tlv_size; p_tlv = p_param_tlvs; while (rem_len > 1) { num_param++; /* number of params */ p_tlv ++; /* param type */ param_len = *p_tlv++; /* param length */ rem_len -= 2; /* param type and length */ if (rem_len >= param_len) { rem_len -= param_len; p_tlv += param_len; /* next param_type */ if (rem_len == 0) { status = HAL_NFC_STATUS_OK; break; } } else { /* error found */ break; } } if (status == HAL_NFC_STATUS_OK) { UINT8_TO_STREAM (p, num_param); ARRAY_TO_STREAM (p, p_param_tlvs, tlv_size); nfc_hal_dm_send_nci_cmd (p_buff, cmd_len, p_cback); } else { HAL_TRACE_ERROR0 ("nfc_hal_dm_set_config ():Bad TLV"); } GKI_freebuf (p_buff); } return status; }
/******************************************************************************* ** ** Function gatt_process_read_rsp ** ** Description This function is called to handle the read BLOB response ** ** ** Returns void ** *******************************************************************************/ void gatt_process_read_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, UINT16 len, UINT8 *p_data) { UINT16 offset = p_clcb->counter; UINT8 * p= p_data; if (p_clcb->operation == GATTC_OPTYPE_READ) { if (p_clcb->op_subtype != GATT_READ_BY_HANDLE) { p_clcb->counter = len; gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p); } else { /* allocate GKI buffer holding up long attribute value */ if (!p_clcb->p_attr_buf) p_clcb->p_attr_buf = (UINT8 *)GKI_getbuf(GATT_MAX_ATTR_LEN); /* copy attrobute value into cb buffer */ if (p_clcb->p_attr_buf && offset < GATT_MAX_ATTR_LEN) { if ((len + offset) > GATT_MAX_ATTR_LEN) len = GATT_MAX_ATTR_LEN - offset; p_clcb->counter += len; memcpy(p_clcb->p_attr_buf + offset, p, len); /* send next request if needed */ if (len == (p_tcb->payload_size - 1) && /* full packet for read or read blob rsp */ len + offset < GATT_MAX_ATTR_LEN) { GATT_TRACE_DEBUG3("full pkt issue read blob for remianing bytes old offset=%d len=%d new offset=%d", offset, len, p_clcb->counter); gatt_act_read(p_clcb, p_clcb->counter); } else /* end of request, send callback */ { gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf); } } else /* exception, should not happen */ { GATT_TRACE_ERROR2("attr offset = %d p_attr_buf = %d ", offset, p_clcb->p_attr_buf); gatt_end_operation(p_clcb, GATT_NO_RESOURCES, (void *)p_clcb->p_attr_buf); } } } else { if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->op_subtype == GATT_DISC_INC_SRVC && p_clcb->read_uuid128.wait_for_read_rsp ) { p_clcb->s_handle = p_clcb->read_uuid128.next_disc_start_hdl; p_clcb->read_uuid128.wait_for_read_rsp = FALSE; if (len == LEN_UUID_128) { memcpy(p_clcb->read_uuid128.result.value.incl_service.service_type.uu.uuid128, p, len); p_clcb->read_uuid128.result.value.incl_service.service_type.len = LEN_UUID_128; if ( p_clcb->p_reg->app_cb.p_disc_res_cb) (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &p_clcb->read_uuid128.result); gatt_act_discovery(p_clcb) ; } else { gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p); } } } }
/******************************************************************************* ** ** Function mca_ccb_hdl_req ** ** Description This function is called when a MCAP request is received from ** the peer. It calls the application callback function to ** report the event. ** ** Returns void. ** *******************************************************************************/ void mca_ccb_hdl_req(tMCA_CCB *p_ccb, tMCA_CCB_EVT *p_data) { BT_HDR *p_pkt = &p_data->hdr; BT_HDR *p_buf; UINT8 *p, *p_start; tMCA_DCB *p_dcb; tMCA_CTRL evt_data; tMCA_CCB_MSG *p_rx_msg = NULL; UINT8 reject_code = MCA_RSP_NO_RESOURCE; BOOLEAN send_rsp = FALSE; BOOLEAN check_req = FALSE; UINT8 reject_opcode; MCA_TRACE_DEBUG ("mca_ccb_hdl_req status:%d", p_ccb->status); p_rx_msg = (tMCA_CCB_MSG *)p_pkt; p = (UINT8 *)(p_pkt + 1) + p_pkt->offset; evt_data.hdr.op_code = *p++; BE_STREAM_TO_UINT16 (evt_data.hdr.mdl_id, p); reject_opcode = evt_data.hdr.op_code+1; MCA_TRACE_DEBUG ("received mdl id: %d ", evt_data.hdr.mdl_id); if (p_ccb->status == MCA_CCB_STAT_PENDING) { MCA_TRACE_DEBUG ("received req inpending state"); /* allow abort in pending state */ if ((p_ccb->status == MCA_CCB_STAT_PENDING) && (evt_data.hdr.op_code == MCA_OP_MDL_ABORT_REQ)) { reject_code = MCA_RSP_SUCCESS; send_rsp = TRUE; /* clear the pending status */ p_ccb->status = MCA_CCB_STAT_NORM; if (p_ccb->p_tx_req && ((p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx))!= NULL)) { mca_dcb_dealloc (p_dcb, NULL); mca_free_buf ((void **)&p_ccb->p_tx_req); } } else reject_code = MCA_RSP_BAD_OP; } else if (p_ccb->p_rx_msg) { MCA_TRACE_DEBUG ("still handling prev req"); /* still holding previous message, reject this new one ?? */ } else if (p_ccb->p_tx_req) { MCA_TRACE_DEBUG ("still waiting for a response ctrl_vpsm:0x%x", p_ccb->ctrl_vpsm); /* sent a request; waiting for response */ if (p_ccb->ctrl_vpsm == 0) { MCA_TRACE_DEBUG ("local is ACP. accept the cmd from INT"); /* local is acceptor, need to handle the request */ check_req = TRUE; reject_code = MCA_RSP_SUCCESS; /* drop the previous request */ if ((p_ccb->p_tx_req->op_code == MCA_OP_MDL_CREATE_REQ) && ((p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx)) != NULL)) { mca_dcb_dealloc(p_dcb, NULL); } mca_free_buf ((void **)&p_ccb->p_tx_req); mca_stop_timer(p_ccb); } else { /* local is initiator, ignore the req */ GKI_freebuf (p_pkt); return; } } else if (p_pkt->layer_specific != MCA_RSP_SUCCESS) { reject_code = (UINT8)p_pkt->layer_specific; if (((evt_data.hdr.op_code >= MCA_NUM_STANDARD_OPCODE) && (evt_data.hdr.op_code < MCA_FIRST_SYNC_OP)) || (evt_data.hdr.op_code > MCA_LAST_SYNC_OP)) { /* invalid op code */ reject_opcode = MCA_OP_ERROR_RSP; evt_data.hdr.mdl_id = 0; } } else { check_req = TRUE; reject_code = MCA_RSP_SUCCESS; } if (check_req) { if (reject_code == MCA_RSP_SUCCESS) { reject_code = MCA_RSP_BAD_MDL; if (MCA_IS_VALID_MDL_ID(evt_data.hdr.mdl_id) || ((evt_data.hdr.mdl_id == MCA_ALL_MDL_ID) && (evt_data.hdr.op_code == MCA_OP_MDL_DELETE_REQ))) { reject_code = MCA_RSP_SUCCESS; /* mdl_id is valid according to the spec */ switch (evt_data.hdr.op_code) { case MCA_OP_MDL_CREATE_REQ: evt_data.create_ind.dep_id = *p++; evt_data.create_ind.cfg = *p++; p_rx_msg->mdep_id = evt_data.create_ind.dep_id; if (!mca_is_valid_dep_id(p_ccb->p_rcb, p_rx_msg->mdep_id)) { MCA_TRACE_ERROR ("not a valid local mdep id"); reject_code = MCA_RSP_BAD_MDEP; } else if (mca_ccb_uses_mdl_id(p_ccb, evt_data.hdr.mdl_id)) { MCA_TRACE_DEBUG ("the mdl_id is currently used in the CL(create)"); mca_dcb_close_by_mdl_id(p_ccb, evt_data.hdr.mdl_id); } else { /* check if this dep still have MDL available */ if (mca_dep_free_mdl(p_ccb, evt_data.create_ind.dep_id) == 0) { MCA_TRACE_ERROR ("the mdep is currently using max_mdl"); reject_code = MCA_RSP_MDEP_BUSY; } } break; case MCA_OP_MDL_RECONNECT_REQ: if (mca_ccb_uses_mdl_id(p_ccb, evt_data.hdr.mdl_id)) { MCA_TRACE_ERROR ("the mdl_id is currently used in the CL(reconn)"); reject_code = MCA_RSP_MDL_BUSY; } break; case MCA_OP_MDL_ABORT_REQ: reject_code = MCA_RSP_BAD_OP; break; case MCA_OP_MDL_DELETE_REQ: /* delete the associated mdl */ mca_dcb_close_by_mdl_id(p_ccb, evt_data.hdr.mdl_id); send_rsp = TRUE; break; } } } } if (((reject_code != MCA_RSP_SUCCESS) && (evt_data.hdr.op_code != MCA_OP_SYNC_INFO_IND)) || send_rsp) { p_buf = (BT_HDR *)GKI_getbuf (MCA_CTRL_MTU); if (p_buf) { p_buf->offset = L2CAP_MIN_OFFSET; p = p_start = (UINT8*)(p_buf + 1) + L2CAP_MIN_OFFSET; *p++ = reject_opcode; *p++ = reject_code; UINT16_TO_BE_STREAM (p, evt_data.hdr.mdl_id); /* if (((*p_start) == MCA_OP_MDL_CREATE_RSP) && (reject_code == MCA_RSP_SUCCESS)) { *p++ = evt_data.create_ind.cfg; } */ p_buf->len = p - p_start; L2CA_DataWrite (p_ccb->lcid, p_buf); } } if (reject_code == MCA_RSP_SUCCESS) { /* use the received GKI buffer to store information to double check response API */ p_rx_msg->op_code = evt_data.hdr.op_code; p_rx_msg->mdl_id = evt_data.hdr.mdl_id; p_ccb->p_rx_msg = p_rx_msg; if (send_rsp) { GKI_freebuf (p_pkt); p_ccb->p_rx_msg = NULL; } mca_ccb_report_event(p_ccb, evt_data.hdr.op_code, &evt_data); } else GKI_freebuf (p_pkt); }
void *GKI_getpoolbuf (UINT8 pool_id) #endif { FREE_QUEUE_T *Q; BUFFER_HDR_T *p_hdr; tGKI_COM_CB *p_cb = &gki_cb.com; if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) return (NULL); #if GKI_BUFFER_DEBUG LOGD("GKI_getpoolbuf() requesting from %d func:%s(line=%d)", pool_id, _function_, _line_); #endif /* Make sure the buffers aren't disturbed til finished with allocation */ GKI_disable(); Q = &p_cb->freeq[pool_id]; if(Q->cur_cnt < Q->total) { #ifdef GKI_USE_DEFERED_ALLOC_BUF_POOLS if(Q->p_first == 0 && gki_alloc_free_queue(pool_id) != TRUE) return NULL; #endif if(Q->p_first == 0) { /* gki_alloc_free_queue() failed to alloc memory */ GKI_TRACE_ERROR_0("GKI_getpoolbuf() fail alloc free queue"); return NULL; } p_hdr = Q->p_first; Q->p_first = p_hdr->p_next; if (!Q->p_first) Q->p_last = NULL; if(++Q->cur_cnt > Q->max_cnt) Q->max_cnt = Q->cur_cnt; GKI_enable(); p_hdr->task_id = GKI_get_taskid(); p_hdr->status = BUF_STATUS_UNLINKED; p_hdr->p_next = NULL; p_hdr->Type = 0; #if GKI_BUFFER_DEBUG LOGD("GKI_getpoolbuf() allocated, %x, %x (%d of %d used) %d", (UINT8*)p_hdr + BUFFER_HDR_SIZE, p_hdr, Q->cur_cnt, Q->total, p_cb->freeq[pool_id].total); strncpy(p_hdr->_function, _function_, _GKI_MAX_FUNCTION_NAME_LEN); p_hdr->_function[_GKI_MAX_FUNCTION_NAME_LEN] = '\0'; p_hdr->_line = _line_; #endif return ((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE)); } /* If here, no buffers in the specified pool */ GKI_enable(); #if GKI_BUFFER_DEBUG /* try for free buffers in public pools */ return (GKI_getbuf_debug(p_cb->freeq[pool_id].size, _function_, _line_)); #else /* try for free buffers in public pools */ return (GKI_getbuf(p_cb->freeq[pool_id].size)); #endif }
/******************************************************************************* ** ** Function gatt_process_read_by_type_rsp ** ** Description This function is called to handle the read by type response. ** read by type can be used for discovery, or read by type or ** read characteristic value. ** ** Returns void ** *******************************************************************************/ void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, UINT16 len, UINT8 *p_data) { tGATT_DISC_RES result; tGATT_DISC_VALUE record_value; UINT8 *p = p_data, value_len, handle_len = 2; UINT16 handle = 0; /* discovery procedure and no callback function registered */ if (((!p_clcb->p_reg) || (!p_clcb->p_reg->app_cb.p_disc_res_cb)) && (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)) return; STREAM_TO_UINT8(value_len, p); if ((value_len > (p_tcb->payload_size - 2)) || (value_len > (len-1)) ) { /* this is an error case that server's response containing a value length which is larger than MTU-2 or value_len > message total length -1 */ GATT_TRACE_ERROR4("gatt_process_read_by_type_rsp: Discard response op_code=%d vale_len=%d > (MTU-2=%d or msg_len-1=%d)", op_code, value_len, (p_tcb->payload_size - 2), (len-1)); gatt_end_operation(p_clcb, GATT_ERROR, NULL); return; } if (op_code == GATT_RSP_READ_BY_GRP_TYPE) handle_len = 4; value_len -= handle_len; /* substract the handle pairs bytes */ len -= 1; while (len >= (handle_len + value_len)) { STREAM_TO_UINT16(handle, p); if (!GATT_HANDLE_IS_VALID(handle)) { gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL); return; } memset(&result, 0, sizeof(tGATT_DISC_RES)); memset(&record_value, 0, sizeof(tGATT_DISC_VALUE)); result.handle = handle; result.type.len = 2; result.type.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype]; /* discover all services */ if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->op_subtype == GATT_DISC_SRVC_ALL && op_code == GATT_RSP_READ_BY_GRP_TYPE) { STREAM_TO_UINT16(handle, p); if (!GATT_HANDLE_IS_VALID(handle)) { gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL); return; } else { record_value.group_value.e_handle = handle; if (!gatt_parse_uuid_from_cmd(&record_value.group_value.service_type, value_len, &p)) { GATT_TRACE_ERROR0("discover all service response parsing failure"); break; } } } /* discover included service */ else if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->op_subtype == GATT_DISC_INC_SRVC) { STREAM_TO_UINT16(record_value.incl_service.s_handle, p); STREAM_TO_UINT16(record_value.incl_service.e_handle, p); if (!GATT_HANDLE_IS_VALID(record_value.incl_service.s_handle) || !GATT_HANDLE_IS_VALID(record_value.incl_service.e_handle)) { gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL); return; } if(value_len == 6) { STREAM_TO_UINT16(record_value.incl_service.service_type.uu.uuid16, p); record_value.incl_service.service_type.len = LEN_UUID_16; } else if (value_len == 4) { p_clcb->s_handle = record_value.incl_service.s_handle; p_clcb->read_uuid128.wait_for_read_rsp = TRUE; p_clcb->read_uuid128.next_disc_start_hdl = handle + 1; memcpy(&p_clcb->read_uuid128.result, &result, sizeof(result)); memcpy(&p_clcb->read_uuid128.result.value, &record_value, sizeof (result.value)); p_clcb->op_subtype |= 0x90; gatt_act_read(p_clcb, 0); return; } else { GATT_TRACE_ERROR1("gatt_process_read_by_type_rsp INCL_SRVC failed with invalid data value_len=%d", value_len); gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p); return; } } /* read by type */ else if (p_clcb->operation == GATTC_OPTYPE_READ && p_clcb->op_subtype == GATT_READ_BY_TYPE) { p_clcb->counter = len - 2; p_clcb->s_handle = handle; if ( p_clcb->counter == (p_clcb->p_tcb->payload_size -4)) { p_clcb->op_subtype = GATT_READ_BY_HANDLE; if (!p_clcb->p_attr_buf) p_clcb->p_attr_buf = (UINT8 *)GKI_getbuf(GATT_MAX_ATTR_LEN); if (p_clcb->p_attr_buf && p_clcb->counter <= GATT_MAX_ATTR_LEN) { memcpy(p_clcb->p_attr_buf, p, p_clcb->counter); gatt_act_read(p_clcb, p_clcb->counter); } else gatt_end_operation(p_clcb, GATT_INTERNAL_ERROR, (void *)p); } else { gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p); } return; } else /* discover characterisitic or read characteristic value */ { STREAM_TO_UINT8 (record_value.dclr_value.char_prop, p); STREAM_TO_UINT16(record_value.dclr_value.val_handle, p); if (!GATT_HANDLE_IS_VALID(record_value.dclr_value.val_handle)) { gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL); return; } gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid, (UINT16)(value_len - 3), &p); /* UUID not matching */ if (!gatt_uuid_compare(record_value.dclr_value.char_uuid, p_clcb->uuid)) { len -= (value_len + 2); continue; /* skip the result, and look for next one */ } else if (p_clcb->operation == GATTC_OPTYPE_READ) /* UUID match for read characteristic value */ { /* only read the first matching UUID characteristic value, and discard the rest results */ p_clcb->s_handle = record_value.dclr_value.val_handle; p_clcb->op_subtype |= 0x80; gatt_act_read(p_clcb, 0); return; } } len -= (value_len + handle_len); /* result is (handle, 16bits UUID) pairs */ memcpy (&result.value, &record_value, sizeof (result.value)); /* send callback if is discover procedure */ if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->p_reg->app_cb.p_disc_res_cb) (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result); } p_clcb->s_handle = (handle == 0) ? 0 : (handle + 1); if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY) { /* initiate another request */ gatt_act_discovery(p_clcb) ; } else /* read characteristic value */ { gatt_act_read(p_clcb, 0); } }
/******************************************************************************* ** ** Function bta_ag_mgmt_cback ** ** Description RFCOMM management callback ** ** ** Returns void ** *******************************************************************************/ static void bta_ag_mgmt_cback(UINT32 code, UINT16 port_handle, UINT16 handle) { tBTA_AG_RFC *p_buf; tBTA_AG_SCB *p_scb; UINT16 event; UINT8 i; BOOLEAN found_handle = FALSE; APPL_TRACE_DEBUG("ag_mgmt_cback : code = %d, port_handle = %d, handle = %d", code, port_handle, handle); if ((p_scb = bta_ag_scb_by_idx(handle)) != NULL) { /* ignore close event for port handles other than connected handle */ if ((code != PORT_SUCCESS) && (port_handle != p_scb->conn_handle)) { APPL_TRACE_DEBUG("ag_mgmt_cback ignoring handle:%d", port_handle); return; } if (code == PORT_SUCCESS) { if (p_scb->conn_handle) /* Outgoing connection */ { if (port_handle == p_scb->conn_handle) found_handle = TRUE; } else /* Incoming connection */ { for (i = 0; i < BTA_AG_NUM_IDX; i++) { if (port_handle == p_scb->serv_handle[i]) found_handle = TRUE; } } if (!found_handle) { APPL_TRACE_ERROR ("bta_ag_mgmt_cback: PORT_SUCCESS, ignoring handle = %d", port_handle); return; } event = BTA_AG_RFC_OPEN_EVT; } /* distinguish server close events */ else if (port_handle == p_scb->conn_handle) { event = BTA_AG_RFC_CLOSE_EVT; } else { event = BTA_AG_RFC_SRV_CLOSE_EVT; } if ((p_buf = (tBTA_AG_RFC *) GKI_getbuf(sizeof(tBTA_AG_RFC))) != NULL) { p_buf->hdr.event = event; p_buf->hdr.layer_specific = handle; p_buf->port_handle = port_handle; bta_sys_sendmsg(p_buf); } } }
/******************************************************************************* ** ** Function nfa_p2p_update_active_listen ** ** Description Remove active listen mode temporarily or restore it ** ** ** Returns None ** *******************************************************************************/ static void nfa_p2p_update_active_listen (void) { tNFA_DM_DISC_TECH_PROTO_MASK p2p_listen_mask = 0; BT_HDR *p_msg; P2P_TRACE_DEBUG1 ("nfa_p2p_update_active_listen (): listen_tech_mask_to_restore:0x%x", nfa_p2p_cb.listen_tech_mask_to_restore); /* if active listen mode was removed temporarily */ if (nfa_p2p_cb.listen_tech_mask_to_restore) { /* restore listen technologies */ nfa_p2p_cb.listen_tech_mask = nfa_p2p_cb.listen_tech_mask_to_restore; nfa_p2p_cb.listen_tech_mask_to_restore = 0; nfa_sys_stop_timer (&nfa_p2p_cb.active_listen_restore_timer); } else { /* start timer in case of no passive activation */ nfa_p2p_cb.active_listen_restore_timer.p_cback = (TIMER_CBACK *)nfa_p2p_update_active_listen_timeout_cback; nfa_sys_start_timer (&nfa_p2p_cb.active_listen_restore_timer, 0, NFA_P2P_RESTORE_ACTIVE_LISTEN_TIMEOUT); /* save listen techonologies */ nfa_p2p_cb.listen_tech_mask_to_restore = nfa_p2p_cb.listen_tech_mask; /* remove active listen mode */ nfa_p2p_cb.listen_tech_mask &= ~( NFA_TECHNOLOGY_MASK_A_ACTIVE|NFA_TECHNOLOGY_MASK_F_ACTIVE); } if (nfa_p2p_cb.dm_disc_handle != NFA_HANDLE_INVALID) { nfa_dm_delete_rf_discover (nfa_p2p_cb.dm_disc_handle); nfa_p2p_cb.dm_disc_handle = NFA_HANDLE_INVALID; } /* collect listen technologies with NFC-DEP protocol */ if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_A) p2p_listen_mask |= NFA_DM_DISC_MASK_LA_NFC_DEP; if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_F) p2p_listen_mask |= NFA_DM_DISC_MASK_LF_NFC_DEP; if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_A_ACTIVE) p2p_listen_mask |= NFA_DM_DISC_MASK_LAA_NFC_DEP; if (nfa_p2p_cb.listen_tech_mask & NFA_TECHNOLOGY_MASK_F_ACTIVE) p2p_listen_mask |= NFA_DM_DISC_MASK_LFA_NFC_DEP; #if(NFC_NXP_NOT_OPEN_INCLUDED == TRUE) /*For P2P mode(Default DTA mode) open Raw channel to bypass LLCP layer. For LLCP DTA mode activate LLCP * Bypassing LLCP is handled in nfa_dm_poll_disc_cback*/ if ((appl_dta_mode_flag == 1) && (nfa_dm_cb.eDtaMode == NFA_DTA_DEFAULT_MODE)) { /* Configure listen technologies and protocols and register callback to NFA DM discovery */ P2P_TRACE_DEBUG0 ("DTA mode1:Registering nfa_dm_poll_disc_cback to avoid LLCP in P2P "); nfa_p2p_cb.dm_disc_handle = nfa_dm_add_rf_discover (p2p_listen_mask, NFA_DM_DISC_HOST_ID_DH, nfa_dm_poll_disc_cback_dta_wrapper); } else #endif { /* Configure listen technologies and protocols and register callback to NFA DM discovery */ nfa_p2p_cb.dm_disc_handle = nfa_dm_add_rf_discover (p2p_listen_mask, NFA_DM_DISC_HOST_ID_DH, nfa_p2p_discovery_cback); } /* restart RF discovery to update RF technologies */ if ((p_msg = (BT_HDR *) GKI_getbuf (sizeof(BT_HDR))) != NULL) { p_msg->event = NFA_P2P_INT_RESTART_RF_DISC_EVT; nfa_sys_sendmsg (p_msg); } }
/******************************************************************************* ** ** Function AVDT_SendReport ** ** Description ** ** ** ** Returns ** *******************************************************************************/ UINT16 AVDT_SendReport(UINT8 handle, AVDT_REPORT_TYPE type, tAVDT_REPORT_DATA *p_data) { tAVDT_SCB *p_scb; UINT16 result = AVDT_BAD_PARAMS; BT_HDR *p_pkt; tAVDT_TC_TBL *p_tbl; UINT8 *p, *plen, *pm1, *p_end; #if AVDT_MULTIPLEXING == TRUE UINT8 *p_al = NULL, u; #endif UINT32 ssrc; UINT16 len; /* map handle to scb && verify parameters */ if (((p_scb = avdt_scb_by_hdl(handle)) != NULL) && (p_scb->p_ccb != NULL) && (((type == AVDT_RTCP_PT_SR) && (p_scb->cs.tsep == AVDT_TSEP_SRC)) || ((type == AVDT_RTCP_PT_RR) && (p_scb->cs.tsep == AVDT_TSEP_SNK)) || (type == AVDT_RTCP_PT_SDES)) ) { result = AVDT_NO_RESOURCES; /* build SR - assume fit in one packet */ p_tbl = avdt_ad_tc_tbl_by_type(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb); if ((p_tbl->state == AVDT_AD_ST_OPEN) && (p_pkt = (BT_HDR *)GKI_getbuf(p_tbl->peer_mtu)) != NULL) { p_pkt->offset = L2CAP_MIN_OFFSET; p = (UINT8 *)(p_pkt + 1) + p_pkt->offset; #if AVDT_MULTIPLEXING == TRUE if (p_scb->curr_cfg.psc_mask & AVDT_PSC_MUX) { /* Adaptation Layer header later */ p_al = p; p += 2; } #endif pm1 = p; *p++ = AVDT_MEDIA_OCTET1 | 1; *p++ = type; /* save the location for length */ plen = p; p += 2; ssrc = avdt_scb_gen_ssrc(p_scb); UINT32_TO_BE_STREAM(p, ssrc); switch (type) { case AVDT_RTCP_PT_SR: /* Sender Report */ *pm1 = AVDT_MEDIA_OCTET1; UINT32_TO_BE_STREAM(p, p_data->sr.ntp_sec); UINT32_TO_BE_STREAM(p, p_data->sr.ntp_frac); UINT32_TO_BE_STREAM(p, p_data->sr.rtp_time); UINT32_TO_BE_STREAM(p, p_data->sr.pkt_count); UINT32_TO_BE_STREAM(p, p_data->sr.octet_count); break; case AVDT_RTCP_PT_RR: /* Receiver Report */ *p++ = p_data->rr.frag_lost; AVDT_TRACE_API("packet_lost: %d\n", p_data->rr.packet_lost); p_data->rr.packet_lost &= 0xFFFFFF; AVDT_TRACE_API("packet_lost: %d\n", p_data->rr.packet_lost); UINT24_TO_BE_STREAM(p, p_data->rr.packet_lost); UINT32_TO_BE_STREAM(p, p_data->rr.seq_num_rcvd); UINT32_TO_BE_STREAM(p, p_data->rr.jitter); UINT32_TO_BE_STREAM(p, p_data->rr.lsr); UINT32_TO_BE_STREAM(p, p_data->rr.dlsr); break; case AVDT_RTCP_PT_SDES: /* Source Description */ *p++ = AVDT_RTCP_SDES_CNAME; len = strlen((char *)p_data->cname); if (len > AVDT_MAX_CNAME_SIZE) { len = AVDT_MAX_CNAME_SIZE; } *p++ = (UINT8)len; BCM_STRNCPY_S((char *)p, len + 1, (char *)p_data->cname, len + 1); p += len; break; } p_end = p; len = p - pm1 - 1; UINT16_TO_BE_STREAM(plen, len); #if AVDT_MULTIPLEXING == TRUE if (p_scb->curr_cfg.psc_mask & AVDT_PSC_MUX) { /* Adaptation Layer header */ p = p_al; len++; UINT16_TO_BE_STREAM(p_al, len ); /* TSID, no-fragment bit and coding of length(9-bit length field) */ u = *p; *p = (p_scb->curr_cfg.mux_tsid_report << 3) | AVDT_ALH_LCODE_9BITM0; if (u) { *p |= AVDT_ALH_LCODE_9BITM1; } } #endif /* set the actual payload length */ p_pkt->len = p_end - p; /* send the packet */ if (L2CAP_DW_FAILED != avdt_ad_write_req(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb, p_pkt)) { result = AVDT_SUCCESS; } } } return result; }
/******************************************************************************* ** ** Function bta_ag_do_disc ** ** Description Do service discovery. ** ** ** Returns void ** *******************************************************************************/ void bta_ag_do_disc(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK service) { tSDP_UUID uuid_list[2]; UINT16 num_uuid = 1; UINT16 attr_list[4]; UINT8 num_attr; BOOLEAN db_inited = FALSE; /* HFP initiator; get proto list and features */ if (service & BTA_HFP_SERVICE_MASK && p_scb->role == BTA_AG_INT) { attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST; attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST; attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST; attr_list[3] = ATTR_ID_SUPPORTED_FEATURES; num_attr = 4; uuid_list[0].uu.uuid16 = UUID_SERVCLASS_HF_HANDSFREE; } /* HFP acceptor; get features */ else if (service & BTA_HFP_SERVICE_MASK && p_scb->role == BTA_AG_ACP) { attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST; attr_list[1] = ATTR_ID_BT_PROFILE_DESC_LIST; attr_list[2] = ATTR_ID_SUPPORTED_FEATURES; num_attr = 3; uuid_list[0].uu.uuid16 = UUID_SERVCLASS_HF_HANDSFREE; } /* HSP initiator; get proto list */ else if (service & BTA_HSP_SERVICE_MASK && p_scb->role == BTA_AG_INT) { attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST; attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST; attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST; attr_list[3] = ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL; num_attr = 4; uuid_list[0].uu.uuid16 = UUID_SERVCLASS_HEADSET; /* Legacy from HSP v1.0 */ if (p_scb->hsp_version >= HSP_VERSION_1_2) { uuid_list[1].uu.uuid16 = UUID_SERVCLASS_HEADSET_HS; num_uuid = 2; } } /* HSP acceptor; no discovery */ else { return; } /* allocate buffer for sdp database */ p_scb->p_disc_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(BTA_AG_DISC_BUF_SIZE); if(p_scb->p_disc_db) { /* set up service discovery database; attr happens to be attr_list len */ uuid_list[0].len = LEN_UUID_16; uuid_list[1].len = LEN_UUID_16; db_inited = SDP_InitDiscoveryDb(p_scb->p_disc_db, BTA_AG_DISC_BUF_SIZE, num_uuid, uuid_list, num_attr, attr_list); } if(db_inited) { /*Service discovery not initiated */ db_inited = SDP_ServiceSearchAttributeRequest(p_scb->peer_addr, p_scb->p_disc_db, bta_ag_sdp_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]); } if(!db_inited) { /*free discover db */ bta_ag_free_db(p_scb, NULL); /* sent failed event */ bta_ag_sm_execute(p_scb, BTA_AG_DISC_FAIL_EVT, NULL); } }
/******************************************************************************* ** ** Function dis_c_cmpl_cback ** ** Description Client operation complete callback. ** ** Returns void ** *******************************************************************************/ void dis_c_cmpl_cback (tSRVC_CLCB *p_clcb, tGATTC_OPTYPE op, tGATT_STATUS status, tGATT_CL_COMPLETE *p_data) { UINT16 read_type = dis_attr_uuid[dis_cb.dis_read_uuid_idx]; UINT8 *pp = NULL, *p_str; UINT16 conn_id = p_clcb->conn_id; GATT_TRACE_EVENT ("dis_c_cmpl_cback() - op_code: 0x%02x status: 0x%02x \ read_type: 0x%04x", op, status, read_type); if (op != GATTC_OPTYPE_READ) return; if (p_data != NULL && status == GATT_SUCCESS) { pp = p_data->att_value.value; switch (read_type) { case GATT_UUID_SYSTEM_ID: GATT_TRACE_EVENT ("DIS_ATTR_SYS_ID_BIT"); if (p_data->att_value.len == DIS_SYSTEM_ID_SIZE) { p_clcb->dis_value.attr_mask |= DIS_ATTR_SYS_ID_BIT; /* save system ID*/ STREAM_TO_UINT64 (p_clcb->dis_value.system_id, pp); } break; case GATT_UUID_PNP_ID: if (p_data->att_value.len == DIS_PNP_ID_SIZE) { p_clcb->dis_value.attr_mask |= DIS_ATTR_PNP_ID_BIT; STREAM_TO_UINT8 (p_clcb->dis_value.pnp_id.vendor_id_src, pp); STREAM_TO_UINT16 (p_clcb->dis_value.pnp_id.vendor_id, pp); STREAM_TO_UINT16 (p_clcb->dis_value.pnp_id.product_id, pp); STREAM_TO_UINT16 (p_clcb->dis_value.pnp_id.product_version, pp); } break; case GATT_UUID_MODEL_NUMBER_STR: case GATT_UUID_SERIAL_NUMBER_STR: case GATT_UUID_FW_VERSION_STR: case GATT_UUID_HW_VERSION_STR: case GATT_UUID_SW_VERSION_STR: case GATT_UUID_MANU_NAME: case GATT_UUID_IEEE_DATA: p_str = p_clcb->dis_value.data_string[read_type - GATT_UUID_MODEL_NUMBER_STR]; if (p_str != NULL) GKI_freebuf(p_str); if ((p_str = (UINT8 *)GKI_getbuf((UINT16)(p_data->att_value.len + 1))) != NULL) { p_clcb->dis_value.attr_mask |= dis_uuid_to_attr(read_type); memcpy(p_str, p_data->att_value.value, p_data->att_value.len); p_str[p_data->att_value.len] = 0; p_clcb->dis_value.data_string[read_type - GATT_UUID_MODEL_NUMBER_STR] = p_str; } break; default: break; break; }/* end switch */ }/* end if */ dis_cb.dis_read_uuid_idx ++; dis_gatt_c_read_dis_req(conn_id); }