/******************************************************************************* ** ** Function AVDT_WriteDataReq ** ** Description Send a media packet to the peer device. The stream must ** be started before this function is called. Also, this ** function can only be called if the stream is a SRC. ** ** When AVDTP has sent the media packet and is ready for the ** next packet, an AVDT_WRITE_CFM_EVT is sent to the ** application via the control callback. The application must ** wait for the AVDT_WRITE_CFM_EVT before it makes the next ** call to AVDT_WriteDataReq(). If the applications calls ** AVDT_WriteDataReq() before it receives the event the packet ** will not be sent. The application may make its first call ** to AVDT_WriteDataReq() after it receives an ** AVDT_START_CFM_EVT or AVDT_START_IND_EVT. ** ** Returns AVDT_SUCCESS if successful, otherwise error. ** *******************************************************************************/ extern UINT16 AVDT_WriteDataReq(UINT8 handle, UINT8 *p_data, UINT32 data_len, UINT32 time_stamp, UINT8 m_pt, UINT8 marker) { tAVDT_SCB *p_scb; tAVDT_SCB_EVT evt; UINT16 result = AVDT_SUCCESS; do { /* check length of media frame */ if (data_len > AVDT_MAX_MEDIA_SIZE) { result = AVDT_BAD_PARAMS; break; } /* map handle to scb */ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL) { result = AVDT_BAD_HANDLE; break; } AVDT_TRACE_WARNING("mux_tsid_media:%d\n", p_scb->curr_cfg.mux_tsid_media); if (p_scb->p_pkt != NULL || p_scb->p_ccb == NULL || !GKI_queue_is_empty(&p_scb->frag_q) || p_scb->frag_off != 0 || p_scb->curr_cfg.mux_tsid_media == 0) { result = AVDT_ERR_BAD_STATE; AVDT_TRACE_WARNING("p_scb->p_pkt=%p, p_scb->p_ccb=%p, IsQueueEmpty=%x, p_scb->frag_off=%x\n", p_scb->p_pkt, p_scb->p_ccb, GKI_queue_is_empty(&p_scb->frag_q), p_scb->frag_off); break; } evt.apiwrite.p_buf = 0; /* it will indicate using of fragments queue frag_q */ /* create queue of media fragments */ GKI_init_q (&evt.apiwrite.frag_q); /* compose fragments from media payload and put fragments into gueue */ avdt_scb_queue_frags(p_scb, &p_data, &data_len, &evt.apiwrite.frag_q); if (GKI_queue_is_empty(&evt.apiwrite.frag_q)) { AVDT_TRACE_WARNING("AVDT_WriteDataReq out of GKI buffers"); result = AVDT_ERR_RESOURCE; break; } evt.apiwrite.data_len = data_len; evt.apiwrite.p_data = p_data; /* process the fragments queue */ evt.apiwrite.time_stamp = time_stamp; evt.apiwrite.m_pt = m_pt | (marker << 7); avdt_scb_event(p_scb, AVDT_SCB_API_WRITE_REQ_EVT, &evt); } while (0); #if (BT_USE_TRACES == TRUE) if (result != AVDT_SUCCESS) { AVDT_TRACE_WARNING("*** AVDT_WriteDataReq failed result=%d\n", result); } #endif return result; }
/******************************************************************************* ** ** Function avdt_ccb_snd_msg ** ** Description ** ** ** Returns void. ** *******************************************************************************/ void avdt_ccb_snd_msg(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) { BT_HDR *p_msg; UNUSED(p_data); /* if not congested */ if (!p_ccb->cong) { /* are we sending a fragmented message? continue sending fragment */ if (p_ccb->p_curr_msg != NULL) { avdt_msg_send(p_ccb, NULL); } /* do we have responses to send? send them */ else if (!GKI_queue_is_empty(&p_ccb->rsp_q)) { while ((p_msg = (BT_HDR *) GKI_dequeue(&p_ccb->rsp_q)) != NULL) { if (avdt_msg_send(p_ccb, p_msg) == TRUE) { /* break out if congested */ break; } } } /* do we have commands to send? send next command */ avdt_ccb_snd_cmd(p_ccb, NULL); } }
/******************************************************************************* ** ** Function gatt_sec_check_complete ** ** Description security check complete and proceed to data sending action. ** ** Returns void. ** *******************************************************************************/ void gatt_sec_check_complete(BOOLEAN sec_check_ok, tGATT_CLCB *p_clcb, UINT8 sec_act) { if (p_clcb && p_clcb->p_tcb && GKI_queue_is_empty(&p_clcb->p_tcb->pending_enc_clcb)) { gatt_set_sec_act(p_clcb->p_tcb, GATT_SEC_NONE); } #if (GATTC_INCLUDED == TRUE) if (!sec_check_ok) { gatt_end_operation(p_clcb, GATT_AUTH_FAIL, NULL); } else if (p_clcb->operation == GATTC_OPTYPE_WRITE) { gatt_act_write(p_clcb, sec_act); } else if (p_clcb->operation == GATTC_OPTYPE_READ) { gatt_act_read(p_clcb, p_clcb->counter); } #endif ///GATTC_INCLUDED == TRUE }
/******************************************************************************* ** ** Function btm_send_pending_direct_conn ** ** Description This function send the pending direct connection request in queue ** ** Returns TRUE if started, FALSE otherwise ** *******************************************************************************/ BOOLEAN btm_send_pending_direct_conn(void) { tBTM_BLE_CONN_REQ *p_req; BOOLEAN rt = FALSE; if (!GKI_queue_is_empty(&btm_cb.ble_ctr_cb.conn_pending_q)) { p_req = (tBTM_BLE_CONN_REQ*)GKI_dequeue (&btm_cb.ble_ctr_cb.conn_pending_q); rt = l2cble_init_direct_conn((tL2C_LCB *)(p_req->p_param)); GKI_freebuf((void *)p_req); } return rt; }
/******************************************************************************* ** ** 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; }
static inline void free_gki_que(BUFFER_Q* q) { while(!GKI_queue_is_empty(q)) GKI_freebuf(GKI_dequeue(q)); }
/******************************************************************************* ** ** Function rfc_port_sm_opened ** ** Description This function handles events for the port in the OPENED ** state ** ** Returns void ** *******************************************************************************/ void rfc_port_sm_opened (tPORT *p_port, UINT16 event, void *p_data) { switch (event) { case RFC_EVENT_OPEN: RFCOMM_TRACE_ERROR ("Port error state %d event %d", p_port->rfc.state, event); return; case RFC_EVENT_CLOSE: rfc_port_timer_start (p_port, RFC_DISC_TIMEOUT); rfc_send_disc (p_port->rfc.p_mcb, p_port->dlci); p_port->rfc.expected_rsp = 0; p_port->rfc.state = RFC_STATE_DISC_WAIT_UA; return; case RFC_EVENT_CLEAR: rfc_port_closed (p_port); return; case RFC_EVENT_DATA: /* Send credits in the frame. Pass them in the layer specific member of the hdr. */ /* There might be an initial case when we reduced rx_max and credit_rx is still */ /* bigger. Make sure that we do not send 255 */ if ((p_port->rfc.p_mcb->flow == PORT_FC_CREDIT) && (((BT_HDR *)p_data)->len < p_port->peer_mtu) && (!p_port->rx.user_fc) && (p_port->credit_rx_max > p_port->credit_rx)) { ((BT_HDR *)p_data)->layer_specific = (UINT8) (p_port->credit_rx_max - p_port->credit_rx); p_port->credit_rx = p_port->credit_rx_max; } else { ((BT_HDR *)p_data)->layer_specific = 0; } rfc_send_buf_uih (p_port->rfc.p_mcb, p_port->dlci, (BT_HDR *)p_data); rfc_dec_credit (p_port); return; case RFC_EVENT_UA: return; case RFC_EVENT_SABME: rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci); return; case RFC_EVENT_DM: PORT_DlcReleaseInd (p_port->rfc.p_mcb, p_port->dlci); rfc_port_closed (p_port); return; case RFC_EVENT_DISC: p_port->rfc.state = RFC_STATE_CLOSED; rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci); if(!GKI_queue_is_empty(&p_port->rx.queue)) { /* give a chance to upper stack to close port properly */ RFCOMM_TRACE_DEBUG("port queue is not empty"); rfc_port_timer_start (p_port, RFC_DISC_TIMEOUT); } else PORT_DlcReleaseInd (p_port->rfc.p_mcb, p_port->dlci); return; case RFC_EVENT_UIH: rfc_port_uplink_data (p_port, (BT_HDR *)p_data); return; case RFC_EVENT_TIMEOUT: Port_TimeOutCloseMux( p_port->rfc.p_mcb ) ; RFCOMM_TRACE_ERROR ("Port error state %d event %d", p_port->rfc.state, event); return; } RFCOMM_TRACE_WARNING ("Port state opened Event ignored %d", event); }