/******************************************************************************* ** ** Function avrc_bld_app_setting_text_rsp ** ** Description This function builds the Get Application Settings Attribute Text ** or Get Application Settings Value Text response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_app_setting_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start, *p_len, *p_count; UINT16 len, len_left; UINT8 xx; tAVRC_STS sts = AVRC_STS_NO_ERROR; UINT8 num_added = 0; if (!p_rsp->p_attrs) { AVRC_TRACE_ERROR0("avrc_bld_app_setting_text_rsp NULL parameter"); return AVRC_STS_BAD_PARAM; } /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_len = p_start + 2; /* pdu + rsvd */ len_left = GKI_get_buf_size(p_pkt) - BT_HDR_SIZE - p_pkt->offset - p_pkt->len; BE_STREAM_TO_UINT16(len, p_data); p_count = p_data; if (len == 0) { *p_count = 0; p_data++; } else { p_data = p_start + p_pkt->len; } for (xx=0; xx<p_rsp->num_attr; xx++) { if (len_left < (p_rsp->p_attrs[xx].str_len + 4)) { AVRC_TRACE_ERROR3("avrc_bld_app_setting_text_rsp out of room (str_len:%d, left:%d)", xx, p_rsp->p_attrs[xx].str_len, len_left); p_rsp->num_attr = num_added; sts = AVRC_STS_INTERNAL_ERR; break; } if ( !p_rsp->p_attrs[xx].str_len || !p_rsp->p_attrs[xx].p_str ) { AVRC_TRACE_ERROR1("avrc_bld_app_setting_text_rsp NULL attr text[%d]", xx); continue; } UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id); UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].charset_id); UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].str_len); ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].p_str, p_rsp->p_attrs[xx].str_len); (*p_count)++; num_added++; } len = p_data - p_count; UINT16_TO_BE_STREAM(p_len, len); p_pkt->len = (p_data - p_start); return sts; }
/******************************************************************************* ** ** Function bta_av_dup_audio_buf ** ** Description dup the audio data to the q_info.a2d of other audio channels ** ** Returns void ** *******************************************************************************/ void bta_av_dup_audio_buf(tBTA_AV_SCB *p_scb, BT_HDR *p_buf) { tBTA_AV_SCB *p_scbi; BUFFER_Q *pq; int i; UINT16 size, copy_size; BT_HDR *p_new; if(!p_buf) return; if(bta_av_cb.audio_open_cnt >= 2) { size = GKI_get_buf_size(p_buf); copy_size = BT_HDR_SIZE + p_buf->len + p_buf->offset; /* more than one audio channel is connected */ for(i=0; i<BTA_AV_NUM_STRS; i++) { p_scbi = bta_av_cb.p_scb[i]; if( (p_scb->hdi != i) && /* not the original channel */ (bta_av_cb.conn_audio & BTA_AV_HNDL_TO_MSK(i)) && /* connected audio */ p_scbi && p_scbi->co_started ) /* scb is used and started */ { /* enqueue the data only when the stream is started */ p_new = (BT_HDR *)GKI_getbuf(size); if(p_new) { memcpy(p_new, p_buf, copy_size); pq = &p_scbi->q_info.a2d; GKI_enqueue(pq, p_new); if(pq->count > p_bta_av_cfg->audio_mqs) { bta_av_co_audio_drop(p_scbi->hndl); GKI_freebuf(GKI_dequeue(pq)); } } } } } }
/******************************************************************************* ** ** Function gki_chk_buf_damage ** ** Description Called internally by OSS to check for buffer corruption. ** ** Returns TRUE if there is a problem, else FALSE ** *******************************************************************************/ BOOLEAN gki_chk_buf_damage(void *p_buf) { #if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE) UINT32 *magic; magic = (UINT32 *)((UINT8 *) p_buf + GKI_get_buf_size(p_buf)); if ((UINT32)magic & 1) return (TRUE); if (*magic == MAGIC_NO) return (FALSE); return (TRUE); #else return (FALSE); #endif }
static void btu_exec_tap_fd_read(void *p_param) { struct pollfd ufd; int fd = (int)p_param; if (fd == -1 || fd != btpan_cb.tap_fd) return; // Don't occupy BTU context too long, avoid GKI buffer overruns and // give other profiles a chance to run by limiting the amount of memory // PAN can use from the shared pool buffer. for(int i = 0; i < PAN_POOL_MAX && btif_is_enabled() && btpan_cb.flow; i++) { BT_HDR *buffer = (BT_HDR *)GKI_getpoolbuf(PAN_POOL_ID); if (!buffer) { BTIF_TRACE_WARNING("%s unable to allocate buffer for packet.", __func__); break; } buffer->offset = PAN_MINIMUM_OFFSET; buffer->len = GKI_get_buf_size(buffer) - sizeof(BT_HDR) - buffer->offset; UINT8 *packet = (UINT8 *)buffer + sizeof(BT_HDR) + buffer->offset; // If we don't have an undelivered packet left over, pull one from the TAP driver. // We save it in the congest_packet right away in case we can't deliver it in this // attempt. if (!btpan_cb.congest_packet_size) { ssize_t ret = read(fd, btpan_cb.congest_packet, sizeof(btpan_cb.congest_packet)); switch (ret) { case -1: BTIF_TRACE_ERROR("%s unable to read from driver: %s", __func__, strerror(errno)); GKI_freebuf(buffer); return; case 0: BTIF_TRACE_WARNING("%s end of file reached.", __func__); GKI_freebuf(buffer); return; default: btpan_cb.congest_packet_size = ret; break; } } memcpy(packet, btpan_cb.congest_packet, MIN(btpan_cb.congest_packet_size, buffer->len)); buffer->len = MIN(btpan_cb.congest_packet_size, buffer->len); if (buffer->len > sizeof(tETH_HDR) && should_forward((tETH_HDR *)packet)) { // Extract the ethernet header from the buffer since the PAN_WriteBuf inside // forward_bnep can't handle two pointers that point inside the same GKI buffer. tETH_HDR hdr; memcpy(&hdr, packet, sizeof(tETH_HDR)); // Skip the ethernet header. buffer->len -= sizeof(tETH_HDR); buffer->offset += sizeof(tETH_HDR); if (forward_bnep(&hdr, buffer) != FORWARD_CONGEST) btpan_cb.congest_packet_size = 0; } else { BTIF_TRACE_WARNING("%s dropping packet of length %d", __func__, buffer->len); btpan_cb.congest_packet_size = 0; GKI_freebuf(buffer); } // Bail out of the loop if reading from the TAP fd would block. ufd.fd = fd; ufd.events = POLLIN; ufd.revents = 0; if(poll(&ufd, 1, 0) <= 0 || IS_EXCEPTION(ufd.revents)) { btsock_thread_add_fd(pan_pth, fd, 0, SOCK_THREAD_FD_RD, 0); return; } } }
/******************************************************************************* ** ** Function llcp_sdp_send_sdres ** ** Description Send Service Discovery Response ** ** ** Returns LLCP_STATUS ** *******************************************************************************/ static tLLCP_STATUS llcp_sdp_send_sdres (UINT8 tid, UINT8 sap) { tLLCP_STATUS status; UINT16 available_bytes; LLCP_TRACE_DEBUG2 ("llcp_sdp_send_sdres (): tid=0x%x, SAP=0x%x", tid, sap); /* if there is no pending SNL */ if (!llcp_cb.sdp_cb.p_snl) { llcp_cb.sdp_cb.p_snl = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID); if (llcp_cb.sdp_cb.p_snl) { llcp_cb.sdp_cb.p_snl->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE + LLCP_PDU_HEADER_SIZE; llcp_cb.sdp_cb.p_snl->len = 0; } } if (llcp_cb.sdp_cb.p_snl) { available_bytes = GKI_get_buf_size (llcp_cb.sdp_cb.p_snl) - BT_HDR_SIZE - llcp_cb.sdp_cb.p_snl->offset - llcp_cb.sdp_cb.p_snl->len; /* if SDRES parameter can be added in SNL */ if ( (available_bytes >= 2 + LLCP_SDRES_LEN) &&(llcp_cb.sdp_cb.p_snl->len + 2 + LLCP_SDRES_LEN <= llcp_cb.lcb.effective_miu) ) { llcp_sdp_add_sdres (tid, sap); status = LLCP_STATUS_SUCCESS; } else { /* send pending SNL PDU to LM */ llcp_sdp_check_send_snl (); llcp_cb.sdp_cb.p_snl = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID); if (llcp_cb.sdp_cb.p_snl) { llcp_cb.sdp_cb.p_snl->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE + LLCP_PDU_HEADER_SIZE; llcp_cb.sdp_cb.p_snl->len = 0; llcp_sdp_add_sdres (tid, sap); status = LLCP_STATUS_SUCCESS; } else { status = LLCP_STATUS_FAIL; } } } else { status = LLCP_STATUS_FAIL; } /* if LM is waiting for PDUs from upper layer */ if ( (status == LLCP_STATUS_SUCCESS) &&(llcp_cb.lcb.symm_state == LLCP_LINK_SYMM_LOCAL_XMIT_NEXT) ) { llcp_link_check_send_data (); } return status; }