/******************************************************************************* ** ** Function l2c_ucd_delete_sec_pending_q ** ** Description discard all of UCD packets in security pending queue ** ** Returns None ** *******************************************************************************/ void l2c_ucd_delete_sec_pending_q(tL2C_LCB *p_lcb) { /* clean up any security pending UCD */ while (p_lcb->ucd_out_sec_pending_q.p_first) { osi_free(fixed_queue_try_dequeue(p_lcb->ucd_out_sec_pending_q)); } fixed_queue_free(p_lcb->ucd_out_sec_pending_q, NULL); p_lcb->ucd_out_sec_pending_q = NULL; while (! fixed_queue_is_empty(p_lcb->ucd_in_sec_pending_q)) { osi_free(fixed_queue_try_dequeue(p_lcb->ucd_in_sec_pending_q)); } fixed_queue_free(p_lcb->ucd_in_sec_pending_q); p_lcb->ucd_in_sec_pending_q = NULL; }
/******************************************************************************* ** ** 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 (!fixed_queue_is_empty(p_ccb->rsp_q)) { while ((p_msg = (BT_HDR *)fixed_queue_try_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 avdt_ccb_clear_cmds ** ** Description This function is called when the signaling channel is ** closed to clean up any pending commands. For each pending ** command in the command queue, it frees the command and ** calls the application callback function indicating failure. ** Certain CCB variables are also initialized. ** ** ** Returns void. ** *******************************************************************************/ void avdt_ccb_clear_cmds(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) { int i; tAVDT_SCB *p_scb = &avdt_cb.scb[0]; UINT8 err_code = AVDT_ERR_CONNECT; UNUSED(p_data); /* clear the ccb */ avdt_ccb_clear_ccb(p_ccb); /* clear out command queue; this is a little tricky here; we need ** to handle the case where there is a command on deck in p_curr_cmd, ** plus we need to clear out the queue */ do { /* we know p_curr_cmd = NULL after this */ avdt_ccb_cmd_fail(p_ccb, (tAVDT_CCB_EVT *) &err_code); /* set up next message */ p_ccb->p_curr_cmd = (BT_HDR *) fixed_queue_try_dequeue(p_ccb->cmd_q); } while (p_ccb->p_curr_cmd != NULL); /* send a CC_CLOSE_EVT any active scbs associated with this ccb */ for (i = 0; i < AVDT_NUM_SEPS; i++, p_scb++) { if ((p_scb->allocated) && (p_scb->p_ccb == p_ccb)) { avdt_scb_event(p_scb, AVDT_SCB_CC_CLOSE_EVT, NULL); } } }
/******************************************************************************* ** ** Function avdt_ccb_clear_ccb ** ** Description This function clears out certain buffers, queues, and ** other data elements of a ccb. ** ** ** Returns void. ** *******************************************************************************/ static void avdt_ccb_clear_ccb(tAVDT_CCB *p_ccb) { BT_HDR *p_buf; /* clear certain ccb variables */ p_ccb->cong = FALSE; p_ccb->ret_count = 0; /* free message being fragmented */ if (p_ccb->p_curr_msg != NULL) { osi_free(p_ccb->p_curr_msg); p_ccb->p_curr_msg = NULL; } /* free message being reassembled */ if (p_ccb->p_rx_msg != NULL) { osi_free(p_ccb->p_rx_msg); p_ccb->p_rx_msg = NULL; } /* clear out response queue */ while ((p_buf = (BT_HDR *) fixed_queue_try_dequeue(p_ccb->rsp_q)) != NULL) { osi_free(p_buf); } }
/******************************************************************************* ** ** Function l2c_ucd_send_pending_out_sec_q ** ** Description dequeue UCD packet from security pending queue and ** enqueue it into CCB ** ** Return None ** *******************************************************************************/ void l2c_ucd_send_pending_out_sec_q(tL2C_CCB *p_ccb) { BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_out_sec_pending_q); if (p_buf != NULL) { l2c_enqueue_peer_data (p_ccb, (BT_HDR *)p_buf); l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL); } }
static void *run_thread(void *start_arg) { assert(start_arg != NULL); struct start_arg *start = start_arg; thread_t *thread = start->thread; assert(thread != NULL); if (prctl(PR_SET_NAME, (unsigned long)thread->name) == -1) { ALOGE("%s unable to set thread name: %s", __func__, strerror(errno)); start->error = errno; semaphore_post(start->start_sem); return NULL; } thread->tid = gettid(); semaphore_post(start->start_sem); reactor_object_t work_queue_object; work_queue_object.context = thread->work_queue; work_queue_object.fd = fixed_queue_get_dequeue_fd(thread->work_queue); work_queue_object.interest = REACTOR_INTEREST_READ; work_queue_object.read_ready = work_queue_read_cb; reactor_register(thread->reactor, &work_queue_object); reactor_start(thread->reactor); // Make sure we dispatch all queued work items before exiting the thread. // This allows a caller to safely tear down by enqueuing a teardown // work item and then joining the thread. size_t count = 0; work_item_t *item = fixed_queue_try_dequeue(thread->work_queue); while (item && count <= WORK_QUEUE_CAPACITY) { item->func(item->context); free(item); item = fixed_queue_try_dequeue(thread->work_queue); ++count; } if (count > WORK_QUEUE_CAPACITY) ALOGD("%s growing event queue on shutdown.", __func__); return NULL; }
/******************************************************************************* ** ** Function l2c_ucd_discard_pending_out_sec_q ** ** Description dequeue UCD packet from security pending queue and ** discard it. ** ** Return None ** *******************************************************************************/ void l2c_ucd_discard_pending_out_sec_q(tL2C_CCB *p_ccb) { BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_out_sec_pending_q); /* we may need to report to application */ if (p_buf) { osi_free (p_buf); } }
static void *run_thread(void *start_arg) { assert(start_arg != NULL); struct start_arg *start = start_arg; thread_t *thread = start->thread; assert(thread != NULL); if (prctl(PR_SET_NAME, (unsigned long)thread->name) == -1) { LOG_ERROR("%s unable to set thread name: %s", __func__, strerror(errno)); start->error = errno; semaphore_post(start->start_sem); return NULL; } thread->tid = gettid(); semaphore_post(start->start_sem); int fd = fixed_queue_get_dequeue_fd(thread->work_queue); void *context = thread->work_queue; reactor_object_t *work_queue_object = reactor_register(thread->reactor, fd, context, work_queue_read_cb, NULL); reactor_start(thread->reactor); reactor_unregister(work_queue_object); // Make sure we dispatch all queued work items before exiting the thread. // This allows a caller to safely tear down by enqueuing a teardown // work item and then joining the thread. size_t count = 0; work_item_t *item = fixed_queue_try_dequeue(thread->work_queue); while (item && count <= fixed_queue_capacity(thread->work_queue)) { item->func(item->context); osi_free(item); item = fixed_queue_try_dequeue(thread->work_queue); ++count; } if (count > fixed_queue_capacity(thread->work_queue)) LOG_DEBUG("%s growing event queue on shutdown.", __func__); return NULL; }
/******************************************************************************* ** ** Function l2c_ucd_check_pending_in_sec_q ** ** Description check incoming security ** ** Return TRUE if any UCD packet for security ** *******************************************************************************/ BOOLEAN l2c_ucd_check_pending_in_sec_q(tL2C_CCB *p_ccb) { BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q); if (p_buf != NULL) { UINT16 psm; UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset; STREAM_TO_UINT16(psm, p) p_ccb->chnl_state = CST_TERM_W4_SEC_COMP; btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, psm, p_ccb->p_lcb->handle, CONNLESS_TERM, &l2c_link_sec_comp, p_ccb); return (TRUE); } return (FALSE); }
/******************************************************************************* ** ** Function avdt_ccb_snd_cmd ** ** Description This function is called the send the next command, ** if any, in the command queue. ** ** ** Returns void. ** *******************************************************************************/ void avdt_ccb_snd_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) { BT_HDR *p_msg; UNUSED(p_data); /* do we have commands to send? send next command; make sure we're clear; ** not congested, not sending fragment, not waiting for response */ if ((!p_ccb->cong) && (p_ccb->p_curr_msg == NULL) && (p_ccb->p_curr_cmd == NULL)) { if ((p_msg = (BT_HDR *) fixed_queue_try_dequeue(p_ccb->cmd_q)) != NULL) { /* make a copy of buffer in p_curr_cmd */ if ((p_ccb->p_curr_cmd = (BT_HDR *) osi_malloc(AVDT_CMD_BUF_SIZE)) != NULL) { memcpy(p_ccb->p_curr_cmd, p_msg, (sizeof(BT_HDR) + p_msg->offset + p_msg->len)); avdt_msg_send(p_ccb, p_msg); } } } }
/******************************************************************************* ** ** Function port_rfc_send_tx_data ** ** Description This function is when forward data can be sent to the peer ** *******************************************************************************/ UINT32 port_rfc_send_tx_data (tPORT *p_port) { UINT32 events = 0; BT_HDR *p_buf; /* if there is data to be sent */ if (p_port->tx.queue_size > 0) { /* while the rfcomm peer is not flow controlling us, and peer is ready */ while (!p_port->tx.peer_fc && p_port->rfc.p_mcb && p_port->rfc.p_mcb->peer_ready) { /* get data from tx queue and send it */ osi_mutex_global_lock(); if ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_port->tx.queue)) != NULL) { p_port->tx.queue_size -= p_buf->len; osi_mutex_global_unlock(); RFCOMM_TRACE_DEBUG ("Sending RFCOMM_DataReq tx.queue_size=%d", p_port->tx.queue_size); RFCOMM_DataReq (p_port->rfc.p_mcb, p_port->dlci, p_buf); events |= PORT_EV_TXCHAR; if (p_port->tx.queue_size == 0) { events |= PORT_EV_TXEMPTY; break; } } /* queue is empty-- all data sent */ else { osi_mutex_global_unlock(); events |= PORT_EV_TXEMPTY; break; } } /* If we flow controlled user based on the queue size enable data again */ events |= port_flow_control_user (p_port); } return (events & p_port->ev_mask); }
/******************************************************************************* ** ** Function rfc_check_send_cmd ** ** Description This function is called to send an RFCOMM command message ** or to handle the RFCOMM command message queue. ** ** Returns void ** *******************************************************************************/ void rfc_check_send_cmd(tRFC_MCB *p_mcb, BT_HDR *p_buf) { BT_HDR *p; /* if passed a buffer queue it */ if (p_buf != NULL) { if (p_mcb->cmd_q == NULL) { RFCOMM_TRACE_ERROR("%s: empty queue: p_mcb = %p p_mcb->lcid = %u cached p_mcb = %p", __func__, p_mcb, p_mcb->lcid, rfc_find_lcid_mcb(p_mcb->lcid)); } fixed_queue_enqueue(p_mcb->cmd_q, p_buf); } /* handle queue if L2CAP not congested */ while (p_mcb->l2cap_congested == FALSE) { if ((p = (BT_HDR *)fixed_queue_try_dequeue(p_mcb->cmd_q)) == NULL) { break; } L2CA_DataWrite (p_mcb->lcid, p); } }
static void btc_a2dp_sink_data_ready(UNUSED_ATTR void *context) { tBT_SBC_HDR *p_msg; if (fixed_queue_is_empty(btc_aa_snk_cb.RxSbcQ)) { APPL_TRACE_DEBUG(" QUE EMPTY "); } else { if (btc_aa_snk_cb.rx_flush == TRUE) { btc_a2dp_sink_flush_q(btc_aa_snk_cb.RxSbcQ); return; } while ((p_msg = (tBT_SBC_HDR *)fixed_queue_try_peek_first(btc_aa_snk_cb.RxSbcQ)) != NULL ) { btc_a2dp_sink_handle_inc_media(p_msg); p_msg = (tBT_SBC_HDR *)fixed_queue_try_dequeue(btc_aa_snk_cb.RxSbcQ); if ( p_msg == NULL ) { APPL_TRACE_ERROR("Insufficient data in que "); break; } osi_free(p_msg); } APPL_TRACE_DEBUG(" Process Frames - "); } }
return (FALSE); } /******************************************************************************* ** ** Function l2c_ucd_send_pending_in_sec_q ** ** Description dequeue UCD packet from security pending queue and ** send it to application ** ** Return None ** *******************************************************************************/ void l2c_ucd_send_pending_in_sec_q(tL2C_CCB *p_ccb) { BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q) if (p_buf != NULL) { p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb(p_ccb->p_lcb->remote_bd_addr, (BT_HDR *)p_buf); } } /******************************************************************************* ** ** Function l2c_ucd_discard_pending_in_sec_q ** ** Description dequeue UCD packet from security pending queue and ** discard it. ** ** Return None **
/******************************************************************************* ** ** Function port_release_port ** ** Description Release port infor control block. ** ** Returns Pointer to the PORT or NULL if not found ** *******************************************************************************/ void port_release_port (tPORT *p_port) { BT_HDR *p_buf; UINT32 mask; tPORT_CALLBACK *p_port_cb; tPORT_STATE user_port_pars; osi_mutex_global_lock(); RFCOMM_TRACE_DEBUG("port_release_port, p_port:%p", p_port); while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_port->rx.queue)) != NULL) { osi_free (p_buf); } p_port->rx.queue_size = 0; while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_port->tx.queue)) != NULL) { osi_free (p_buf); } p_port->tx.queue_size = 0; osi_mutex_global_unlock(); p_port->state = PORT_STATE_CLOSED; if (p_port->rfc.state == RFC_STATE_CLOSED) { RFCOMM_TRACE_DEBUG ("rfc_port_closed DONE"); if (p_port->rfc.p_mcb) { p_port->rfc.p_mcb->port_inx[p_port->dlci] = 0; /* If there are no more ports opened on this MCB release it */ rfc_check_mcb_active (p_port->rfc.p_mcb); } rfc_port_timer_stop (p_port); fixed_queue_free(p_port->tx.queue, NULL); p_port->tx.queue = NULL; fixed_queue_free(p_port->rx.queue, NULL); p_port->rx.queue = NULL; RFCOMM_TRACE_DEBUG ("port_release_port:p_port->keep_port_handle:%d", p_port->keep_port_handle); if ( p_port->keep_port_handle ) { RFCOMM_TRACE_DEBUG ("port_release_port:Initialize handle:%d", p_port->inx); /* save event mask and callback */ mask = p_port->ev_mask; p_port_cb = p_port->p_callback; user_port_pars = p_port->user_port_pars; port_set_defaults(p_port); /* restore */ p_port->ev_mask = mask; p_port->p_callback = p_port_cb; p_port->user_port_pars = user_port_pars; p_port->mtu = p_port->keep_mtu; p_port->state = PORT_STATE_OPENING; p_port->rfc.p_mcb = NULL; if (p_port->is_server) { p_port->dlci &= 0xfe; } p_port->local_ctrl.modem_signal = p_port->default_signal_state; memcpy (p_port->bd_addr, BT_BD_ANY, BD_ADDR_LEN); } else { RFCOMM_TRACE_DEBUG ("port_release_port:Clean-up handle:%d", p_port->inx); memset (p_port, 0, sizeof (tPORT)); } } }
/******************************************************************************* ** ** Function btc_a2dp_sink_flush_q ** ** Description ** ** Returns void ** *******************************************************************************/ static void btc_a2dp_sink_flush_q(fixed_queue_t *p_q) { while (! fixed_queue_is_empty(p_q)) { osi_free(fixed_queue_try_dequeue(p_q)); } }