/******************************************************************************* ** ** Function bta_ma_parse_envelope ** ** Description Parses a <bmessage-envelope> from the stream into a ** generic tBTA_MA_BMSG_ENVELOPE structure. This will parse text ** until we see "END:BENV" at the start of a line. ** ** Parameters p_envelope - pointer to generic envelope structure. ** p_stream - Input stream. ** ** Returns BTA_MA_STATUS_OK if successful. BTA_MA_STATUS_FAIL if not. ** *******************************************************************************/ tBTA_MA_STATUS bta_ma_parse_envelope(tBTA_MA_BMSG_ENVELOPE * p_envelope, tBTA_MA_STREAM * p_stream) { char sz[BTA_MA_MAX_SIZE]; tBTA_MA_STATUS status = BTA_MA_STATUS_FAIL; tBTA_MA_BMSG_VCARD * p_vcard = NULL; tBTA_MA_BMSG_ENVELOPE * p_new_envelope = NULL; tBTA_MA_BMSG_BODY * p_body = NULL; while ( bta_ma_get_tag(p_stream, sz, BTA_MA_MAX_SIZE) ) { if ( strcmp(sz, "BEGIN") == 0 ) { bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); if ( strcmp(sz, "VCARD") == 0 ) { p_vcard = BTA_MaBmsgAddRecipToEnv(p_envelope); bta_ma_parse_vcard(p_vcard, p_stream); } else if ( strcmp(sz, "BENV") == 0 ) { p_new_envelope = BTA_MaBmsgAddEnvToEnv(p_envelope); bta_ma_parse_envelope(p_new_envelope, p_stream); } else if ( strcmp(sz, "BBODY") == 0 ) { p_body = BTA_MaBmsgAddBodyToEnv(p_envelope); bta_ma_parse_body(p_body, p_stream); } else { APPL_TRACE_ERROR1("bta_ma_parse_envelope - Invalid BEGIN: '%s'", sz); } } else if ( strcmp(sz, "END") == 0 ) { bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE); status = BTA_MA_STATUS_OK; break; } else { APPL_TRACE_ERROR1("bta_ma_parse_envelope - Invalid tag: '%s'", sz); } } return( status ); }
int socket_server_open(char *socket_name) { int sock = -1; struct sockaddr_un server_address; int status; char errorstring[80]; sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock < 0) { strerror_r(errno, errorstring, sizeof(errorstring)); APPL_TRACE_ERROR1("socket_server_open: socket failed(%s) \n", errorstring); return -1; } memset((char *) &server_address, 0 , sizeof(server_address)); server_address.sun_family = AF_UNIX; server_address.sun_path[0] = 0; strncat(server_address.sun_path, (char*)socket_name, sizeof(server_address.sun_path)-1-strlen(server_address.sun_path)); /* Remove old socket (if previous server closed without removing it) */ if (unlink(server_address.sun_path) == 0) { APPL_TRACE_WARNING1("socket_server_open: removed old file:%s \n", socket_name); } if (bind(sock, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) { strerror_r(errno, errorstring, sizeof(errorstring)); APPL_TRACE_ERROR1("socket_server_open: bind failed(%s) \n", errorstring); close(sock); return -1; } /* Set up queue for incoming connections. */ status = listen(sock, LISTEN_BACKLOG); if (status < 0) { strerror_r(errno, errorstring, sizeof(errorstring)); APPL_TRACE_ERROR1("socket_server_open: listen failed(%s) \n", errorstring); close(sock); return -1; } return sock; }
int btsock_thread_wakeup(int h) { if(h < 0 || h >= MAX_THREAD) { APPL_TRACE_ERROR1("invalid bt thread handle:%d", h); return FALSE; } if(ts[h].cmd_fdw == -1) { APPL_TRACE_ERROR1("thread handle:%d, cmd socket is not created", h); return FALSE; } sock_cmd_t cmd = {CMD_WAKEUP, 0, 0, 0, 0}; return send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd); }
static char *bta_hf_client_parse_binp(char *buffer) { /* HFP only supports phone number as BINP data */ /* phone number is 32 chars plus one for \0*/ char numstr[33]; int res; int offset = 0; AT_CHECK_EVENT(buffer, "+BINP:"); res = sscanf(buffer, "\"%32[^\"]\"\r\n%n", numstr, &offset); if(res < 1) { return NULL; } /* Abort in case offset not set because of format error */ if (offset == 0) { APPL_TRACE_ERROR1("bta_hf_client_parse_binp: Format Error %s", buffer); return NULL; } buffer += offset; /* some phones might sent type as well, just skip it */ AT_SKIP_REST(buffer); AT_CHECK_RN(buffer); bta_hf_client_handle_binp(numstr); return buffer; }
static char *bta_hf_client_parse_cops(char *buffer) { UINT8 mode; /* spec forces 16 chars max, plus \0 here */ char opstr[17]; int res; int offset = 0; AT_CHECK_EVENT(buffer, "+COPS:"); /* TODO: Not sure if operator string actually can contain escaped " char inside */ res = sscanf(buffer, "%hhi,0,\"%16[^\"]\"%n", &mode, opstr, &offset); if(res < 2) { return NULL; } /* Abort in case offset not set because of format error */ if (offset == 0) { APPL_TRACE_ERROR1("bta_hf_client_parse_cops: Format Error %s", buffer); return NULL; } buffer += offset; AT_SKIP_REST(buffer); AT_CHECK_RN(buffer); bta_hf_client_handle_cops(opstr, mode); return buffer; }
/* in HFP context there is no difference between ccwa and clip */ static char *bta_hf_client_parse_ccwa(char *buffer) { /* ac to spec 32 chars max, plus \0 here */ char number[33]; UINT32 type = 0; int res ; int offset = 0; AT_CHECK_EVENT(buffer, "+CCWA:"); /* there might be something more after %lu but HFP doesn't care */ res = sscanf(buffer, "\"%32[^\"]\",%lu%n", number, &type, &offset); if(res < 2) { return NULL; } if (offset == 0) { APPL_TRACE_ERROR1("bta_hf_client_parse_ccwa : Format Error %s", buffer); return NULL; } buffer += offset; AT_SKIP_REST(buffer); AT_CHECK_RN(buffer); bta_hf_client_handle_ccwa(number, type); return buffer; }
static char *bta_hf_client_parse_ciev(char *buffer) { UINT32 index, value; int res; int offset = 0; AT_CHECK_EVENT(buffer, "+CIEV:"); res = sscanf(buffer, "%lu,%lu%n", &index, &value, &offset); if(res < 2) { return NULL; } if (offset == 0) { APPL_TRACE_ERROR1("bta_hf_client_parse_ciev : Format Error %s", buffer); return NULL; } buffer += offset; AT_CHECK_RN(buffer); bta_hf_client_handle_ciev(index, value); return buffer; }
static int process_cmd_sock(int h) { sock_cmd_t cmd = {-1, 0, 0, 0, 0}; int fd = ts[h].cmd_fdr; if(recv(fd, &cmd, sizeof(cmd), MSG_WAITALL) != sizeof(cmd)) { APPL_TRACE_ERROR1("recv cmd errno:%d", errno); return FALSE; } APPL_TRACE_DEBUG1("cmd.id:%d", cmd.id); switch(cmd.id) { case CMD_ADD_FD: add_poll(h, cmd.fd, cmd.type, cmd.flags, cmd.user_id); break; case CMD_WAKEUP: break; case CMD_USER_PRIVATE: asrt(ts[h].cmd_callback); if(ts[h].cmd_callback) ts[h].cmd_callback(fd, cmd.type, cmd.flags, cmd.user_id); break; case CMD_EXIT: return FALSE; default: APPL_TRACE_DEBUG1("unknown cmd: %d", cmd.id); break; } return TRUE; }
static char *bta_hf_client_parse_cnum(char *buffer) { char numstr[33]; /* spec forces 32 chars, plus one for \0*/ UINT16 type; UINT16 service = 0; /* 0 in case this optional parameter is not being sent */ int res; int offset = 0; AT_CHECK_EVENT(buffer, "+CNUM:"); res = sscanf(buffer, ",\"%32[^\"]\",%hu,,%hu%n", numstr, &type, &service, &offset); if(res < 0) { return NULL; } if (res == 0) { res = sscanf(buffer, ",\"\",%hu,,%hu%n", &type, &service, &offset); if (res < 0) { return NULL; } /* numstr is not matched in second attempt, correct this */ res++; numstr[0] = '\0'; } if (res < 3) { return NULL; } /* Abort in case offset not set because of format error */ if (offset == 0) { APPL_TRACE_ERROR1("bta_hf_client_parse_cnum: Format Error %s", buffer); return NULL; } buffer += offset; AT_CHECK_RN(buffer); /* service is optional */ if(res == 2) { bta_hf_client_handle_cnum(numstr, type, service); return buffer; } if (service != 4 && service != 5) { return NULL; } bta_hf_client_handle_cnum(numstr, type, service); return buffer; }
/******************************************************************************* ** ** Function bta_av_co_audio_peer_supports_codec ** ** Description Check if a connection supports the codec config ** ** Returns TRUE if the connection supports this codec, FALSE otherwise ** *******************************************************************************/ static BOOLEAN bta_av_co_audio_peer_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_snk_index) { int index; UINT8 codec_type; FUNC_TRACE(); /* Configure the codec type to look for */ codec_type = bta_av_co_cb.codec_cfg.id; for (index = 0; index < p_peer->num_sup_snks; index++) { if (p_peer->snks[index].codec_type == codec_type) { switch (bta_av_co_cb.codec_cfg.id) { case BTIF_AV_CODEC_SBC: if (p_snk_index) *p_snk_index = index; return bta_av_co_audio_codec_match(p_peer->snks[index].codec_caps); break; default: APPL_TRACE_ERROR1("bta_av_co_audio_peer_supports_codec: unsupported codec id %d", bta_av_co_cb.codec_cfg.id); return FALSE; break; } } } return FALSE; }
/******************************************************************************* ** ** Function bta_av_co_audio_codec_build_config ** ** Description Build the codec configuration ** ** Returns TRUE if the codec was built successfully, FALSE otherwise ** *******************************************************************************/ static BOOLEAN bta_av_co_audio_codec_build_config(const UINT8 *p_codec_caps, UINT8 *p_codec_cfg) { FUNC_TRACE(); memset(p_codec_cfg, 0, AVDT_CODEC_SIZE); switch (bta_av_co_cb.codec_cfg.id) { case BTIF_AV_CODEC_SBC: /* only copy the relevant portions for this codec to avoid issues when comparing codec configs covering larger codec sets than SBC (7 bytes) */ memcpy(p_codec_cfg, bta_av_co_cb.codec_cfg.info, BTA_AV_CO_SBC_MAX_BITPOOL_OFF+1); /* Update the bit pool boundaries with the codec capabilities */ p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF] = p_codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF]; p_codec_cfg[BTA_AV_CO_SBC_MAX_BITPOOL_OFF] = p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]; APPL_TRACE_EVENT2("bta_av_co_audio_codec_build_config : bitpool min %d, max %d", p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF], p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]); break; default: APPL_TRACE_ERROR1("bta_av_co_audio_codec_build_config: unsupported codec id %d", bta_av_co_cb.codec_cfg.id); return FALSE; break; } return TRUE; }
static char *bta_hf_client_parse_cind_list(char *buffer) { int offset = 0; char name[129]; UINT32 min, max; UINT32 index = 0; int res; while ((res = sscanf(buffer, "(\"%128[^\"]\",(%lu%*[-,]%lu))%n", name, &min, &max, &offset)) > 2) { bta_hf_client_handle_cind_list_item(name, min, max, index); if (offset == 0) { APPL_TRACE_ERROR1("bta_hf_client_parse_cind_list : Format Error %s", buffer); return NULL; } buffer += offset; index++; if (*buffer != ',') { break; } buffer++; } if (res > 2) { AT_CHECK_RN(buffer); return buffer; } return NULL; }
int btsock_thread_post_cmd(int h, int type, const unsigned char* data, int size, uint32_t user_id) { if(h < 0 || h >= MAX_THREAD) { APPL_TRACE_ERROR1("invalid bt thread handle:%d", h); return FALSE; } if(ts[h].cmd_fdw == -1) { APPL_TRACE_ERROR0("cmd socket is not created. socket thread may not initialized"); return FALSE; } sock_cmd_t cmd = {CMD_USER_PRIVATE, 0, type, size, user_id}; APPL_TRACE_DEBUG3("post cmd type:%d, size:%d, h:%d, ", type, size, h); sock_cmd_t* cmd_send = &cmd; int size_send = sizeof(cmd); if(data && size) { size_send = sizeof(cmd) + size; cmd_send = (sock_cmd_t*)alloca(size_send); if(cmd_send) { *cmd_send = cmd; memcpy(cmd_send + 1, data, size); } else { APPL_TRACE_ERROR3("alloca failed at h:%d, cmd type:%d, size:%d", h, type, size_send); return FALSE; } } return send(ts[h].cmd_fdw, cmd_send, size_send, 0) == size_send; }
static inline void add_poll(int h, int fd, int type, int flags, uint32_t user_id) { asrt(fd != -1); int i; int empty = -1; poll_slot_t* ps = ts[h].ps; for(i = 0; i < MAX_POLL; i++) { if(ps[i].pfd.fd == fd) { asrt(ts[h].poll_count < MAX_POLL); set_poll(&ps[i], fd, type, flags | ps[i].flags, user_id); return; } else if(empty < 0 && ps[i].pfd.fd == -1) empty = i; } if(empty >= 0) { asrt(ts[h].poll_count < MAX_POLL); set_poll(&ps[empty], fd, type, flags, user_id); ++ts[h].poll_count; return; } APPL_TRACE_ERROR1("exceeded max poll slot:%d!", MAX_POLL); }
int btsock_thread_add_fd(int h, int fd, int type, int flags, uint32_t user_id) { if(h < 0 || h >= MAX_THREAD) { APPL_TRACE_ERROR1("invalid bt thread handle:%d", h); return FALSE; } if(ts[h].cmd_fdw == -1) { APPL_TRACE_ERROR0("cmd socket is not created. socket thread may not initialized"); return FALSE; } if(flags & SOCK_THREAD_ADD_FD_SYNC) { //must executed in socket poll thread if(ts[h].thread_id == pthread_self()) { //cleanup one-time flags flags &= ~SOCK_THREAD_ADD_FD_SYNC; add_poll(h, fd, type, flags, user_id); return TRUE; } APPL_TRACE_DEBUG0("THREAD_ADD_FD_SYNC is not called in poll thread, fallback to async"); } sock_cmd_t cmd = {CMD_ADD_FD, fd, type, flags, user_id}; APPL_TRACE_DEBUG2("adding fd:%d, flags:0x%x", fd, flags); return send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd); }
static void free_thread_slot(int h) { if(0 <= h && h < MAX_THREAD) { close_cmd_fd(h); ts[h].used = 0; } else APPL_TRACE_ERROR1("invalid thread handle:%d", h); }
static inline void set_socket_blocking(int s, int blocking) { int opts; opts = fcntl(s, F_GETFL); if (opts<0) APPL_TRACE_ERROR1("set blocking (%s)", strerror(errno)); if(blocking) opts &= ~O_NONBLOCK; else opts |= O_NONBLOCK; fcntl(s, F_SETFL, opts); }
/******************************************************************************* ** ** Function bta_gattc_hdl_event ** ** Description GATT client main event handling function. ** ** ** Returns void ** *******************************************************************************/ BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg) { tBTA_GATTC_CB *p_cb = &bta_gattc_cb; tBTA_GATTC_CLCB *p_clcb = NULL; #if BTA_GATT_DEBUG == TRUE APPL_TRACE_DEBUG1("bta_gattc_hdl_event: Event [%s]", gattc_evt_code(p_msg->event)); #endif switch (p_msg->event) { case BTA_GATTC_API_REG_EVT: bta_gattc_register(p_cb, (tBTA_GATTC_DATA *) p_msg); break; case BTA_GATTC_INT_START_IF_EVT: bta_gattc_start_if(p_cb, (tBTA_GATTC_DATA *) p_msg); break; case BTA_GATTC_API_DEREG_EVT: bta_gattc_deregister(p_cb, (tBTA_GATTC_DATA *) p_msg); break; case BTA_GATTC_INT_DEREG_EVT: bta_gattc_int_deregister(p_cb, (tBTA_GATTC_DATA *) p_msg); break; case BTA_GATTC_API_OPEN_EVT: bta_gattc_process_api_open(p_cb, (tBTA_GATTC_DATA *) p_msg); break; case BTA_GATTC_API_CANCEL_OPEN_EVT: bta_gattc_process_api_open_cancel(p_cb, (tBTA_GATTC_DATA *) p_msg); break; case BTA_GATTC_API_REFRESH_EVT: bta_gattc_process_api_refresh(p_cb, (tBTA_GATTC_DATA *) p_msg); break; default: if ((p_clcb = bta_gattc_find_clcb_by_conn_id(p_msg->layer_specific)) != NULL) { bta_gattc_sm_execute(p_clcb, p_msg->event, (tBTA_GATTC_DATA *) p_msg); } else { APPL_TRACE_ERROR1("Unknown conn ID: %d", p_msg->layer_specific); } break; } return(TRUE); }
void * bta_ma_bmsg_alloc(size_t cb) { void * p_buf; /* For MMS, the size can be greater than UINT16. This was causing overflow error. Changed this to UINT32 */ if ((p_buf = GKI_getbuf((UINT32) cb)) == NULL ) { APPL_TRACE_ERROR1("Unable to allocate buffer for size=%d", (UINT16) cb); } return(p_buf); }
/* create dummy socket pair used to wake up select loop */ static inline void init_cmd_fd(int h) { asrt(ts[h].cmd_fdr == -1 && ts[h].cmd_fdw == -1); if(socketpair(AF_UNIX, SOCK_STREAM, 0, &ts[h].cmd_fdr) < 0) { APPL_TRACE_ERROR1("socketpair failed: %s", strerror(errno)); return; } APPL_TRACE_DEBUG3("h:%d, cmd_fdr:%d, cmd_fdw:%d", h, ts[h].cmd_fdr, ts[h].cmd_fdw); //add the cmd fd for read & write add_poll(h, ts[h].cmd_fdr, 0, SOCK_THREAD_FD_RD, 0); }
/******************************************************************************* ** ** Function bta_av_alloc_scb ** ** Description allocate stream control block, ** register the service to stack ** create SDP record ** ** Returns void ** *******************************************************************************/ static tBTA_AV_SCB * bta_av_alloc_scb(tBTA_AV_CHNL chnl) { tBTA_AV_SCB *p_ret = NULL; int xx; tBTA_AV_STATUS sts = BTA_AV_SUCCESS; if(chnl == BTA_AV_CHNL_VIDEO) { if(p_bta_av_cfg->p_act_tbl == NULL || p_bta_av_cfg->p_reg == NULL) { APPL_TRACE_ERROR0("Video streaming not supported"); sts = BTA_AV_FAIL; } else { /* allow only one Video channel */ if(bta_av_cb.reg_video) { APPL_TRACE_ERROR0("Already registered"); sts = BTA_AV_FAIL; } } } else if(chnl != BTA_AV_CHNL_AUDIO) { APPL_TRACE_ERROR1("bad channel: %d", chnl); sts = BTA_AV_FAIL; } if(sts == BTA_AV_SUCCESS) { for(xx=0; xx<BTA_AV_NUM_STRS; xx++) { if(bta_av_cb.p_scb[xx] == NULL) { /* found an empty spot */ p_ret = (tBTA_AV_SCB *)GKI_getbuf(sizeof(tBTA_AV_SCB)); if(p_ret) { memset(p_ret, 0, sizeof(tBTA_AV_SCB)); p_ret->rc_handle = BTA_AV_RC_HANDLE_NONE; p_ret->chnl = chnl; p_ret->hndl = (tBTA_AV_HNDL)((xx + 1) | chnl); p_ret->hdi = xx; bta_av_cb.p_scb[xx] = p_ret; } break; } } } return p_ret; }
static inline pthread_t create_thread(void *(*start_routine)(void *), void * arg) { pthread_attr_t thread_attr; pthread_attr_init(&thread_attr); pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE); pthread_t thread_id = -1; if( pthread_create(&thread_id, &thread_attr, start_routine, arg)!=0 ) { APPL_TRACE_ERROR1("pthread_create : %s", strerror(errno)); return -1; } return thread_id; }
/******************************************************************************* ** ** Function bta_av_co_get_peer ** ** Description find the peer entry for a given handle ** ** Returns the control block ** *******************************************************************************/ static tBTA_AV_CO_PEER *bta_av_co_get_peer(tBTA_AV_HNDL hndl) { UINT8 index; FUNC_TRACE(); index = BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl); /* Sanity check */ if (index >= BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers)) { APPL_TRACE_ERROR1("bta_av_co_get_peer peer index out of bounds:%d", index); return NULL; } return &bta_av_co_cb.peers[index]; }
/******************************************************************************* ** ** Function bta_av_co_audio_src_data_path ** ** Description This function is called to manage data transfer from ** the audio codec to AVDTP. ** ** Returns Pointer to the GKI buffer to send, NULL if no buffer to send ** *******************************************************************************/ BTA_API void * bta_av_co_audio_src_data_path(tBTA_AV_CODEC codec_type, UINT32 *p_len, UINT32 *p_timestamp) { BT_HDR *p_buf; FUNC_TRACE(); p_buf = btif_media_aa_readbuf(); if (p_buf != NULL) { switch (codec_type) { case BTA_AV_CODEC_SBC: /* In media packet SBC, the following information is available: * p_buf->layer_specific : number of SBC frames in the packet * p_buf->word[0] : timestamp */ /* Retrieve the timestamp information from the media packet */ *p_timestamp = *((UINT32 *) (p_buf + 1)); /* Set up packet header */ bta_av_sbc_bld_hdr(p_buf, p_buf->layer_specific); break; default: APPL_TRACE_ERROR1("bta_av_co_audio_src_data_path Unsupported codec type (%d)", codec_type); break; } #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE) { UINT8 *p; if (bta_av_co_cp_is_active()) { p_buf->len++; p_buf->offset--; p = (UINT8 *)(p_buf + 1) + p_buf->offset; *p = bta_av_co_cp_get_flag(); } } #endif } return p_buf; }
/******************************************************************************* ** ** Function bta_av_co_audio_media_supports_config ** ** Description Check if the media source supports a given configuration ** ** Returns TRUE if the media source supports this config, FALSE otherwise ** *******************************************************************************/ static BOOLEAN bta_av_co_audio_media_supports_config(UINT8 codec_type, const UINT8 *p_codec_cfg) { FUNC_TRACE(); switch (codec_type) { case BTA_AV_CODEC_SBC: if (bta_av_sbc_cfg_in_cap((UINT8 *)p_codec_cfg, (tA2D_SBC_CIE *)&bta_av_co_sbc_caps)) { return FALSE; } break; default: APPL_TRACE_ERROR1("bta_av_co_audio_media_supports_config unsupported codec type %d", codec_type); return FALSE; break; } return TRUE; }
static int create_server_sdp_record(rfc_slot_t* rs) { int scn = rs->scn; if(rs->scn > 0) { if(BTM_TryAllocateSCN(rs->scn) == FALSE) { APPL_TRACE_ERROR1("rfc channel:%d already in use", scn); return FALSE; } } else if((rs->scn = BTM_AllocateSCN()) == 0) { APPL_TRACE_ERROR0("run out of rfc channels"); return FALSE; } if((rs->sdp_handle = add_rfc_sdp_rec(rs->service_name, rs->service_uuid, rs->scn)) <= 0) { return FALSE; } return TRUE; }
int btsock_thread_exit(int h) { if(h < 0 || h >= MAX_THREAD) { APPL_TRACE_ERROR1("invalid bt thread handle:%d", h); return FALSE; } if(ts[h].cmd_fdw == -1) { APPL_TRACE_ERROR0("cmd socket is not created"); return FALSE; } sock_cmd_t cmd = {CMD_EXIT, 0, 0, 0, 0}; if(send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd)) { pthread_join(ts[h].thread_id, 0); lock_slot(&thread_slot_lock); free_thread_slot(h); unlock_slot(&thread_slot_lock); return TRUE; } return FALSE; }
/******************************************************************************* ** ** Function bta_av_co_audio_codec_cfg_matches_caps ** ** Description Check if a codec config matches a codec capabilities ** ** Returns TRUE if it codec config is supported, FALSE otherwise ** *******************************************************************************/ static BOOLEAN bta_av_co_audio_codec_cfg_matches_caps(UINT8 codec_id, const UINT8 *p_codec_caps, const UINT8 *p_codec_cfg) { FUNC_TRACE(); switch(codec_id) { case BTIF_AV_CODEC_SBC: APPL_TRACE_EVENT4("bta_av_co_audio_codec_cfg_matches_caps : min %d/%d max %d/%d", p_codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF], p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF], p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF], p_codec_cfg[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]); /* Must match all items exactly except bitpool boundaries which can be adjusted */ if (!((p_codec_caps[BTA_AV_CO_SBC_FREQ_CHAN_OFF] & p_codec_cfg[BTA_AV_CO_SBC_FREQ_CHAN_OFF]) && (p_codec_caps[BTA_AV_CO_SBC_BLOCK_BAND_OFF] & p_codec_cfg[BTA_AV_CO_SBC_BLOCK_BAND_OFF]))) { APPL_TRACE_EVENT4("FALSE %x %x %x %x", p_codec_caps[BTA_AV_CO_SBC_FREQ_CHAN_OFF], p_codec_cfg[BTA_AV_CO_SBC_FREQ_CHAN_OFF], p_codec_caps[BTA_AV_CO_SBC_BLOCK_BAND_OFF], p_codec_cfg[BTA_AV_CO_SBC_BLOCK_BAND_OFF]); return FALSE; } break; default: APPL_TRACE_ERROR1("bta_av_co_audio_codec_cfg_matches_caps: unsupported codec id %d", codec_id); return FALSE; break; } APPL_TRACE_EVENT0("TRUE"); return TRUE; }
static rfc_slot_t* alloc_rfc_slot(const bt_bdaddr_t *addr, const char* name, const uint8_t* uuid, int channel, int flags, BOOLEAN server) { int security = 0; if(flags & BTSOCK_FLAG_ENCRYPT) security |= server ? BTM_SEC_IN_ENCRYPT : BTM_SEC_OUT_ENCRYPT; if(flags & BTSOCK_FLAG_AUTH) security |= server ? BTM_SEC_IN_AUTHENTICATE : BTM_SEC_OUT_AUTHENTICATE; rfc_slot_t* rs = find_free_slot(); if(rs) { int fds[2] = {-1, -1}; if(socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) { APPL_TRACE_ERROR1("socketpair failed, errno:%d", errno); return NULL; } rs->fd = fds[0]; rs->app_fd = fds[1]; rs->security = security; rs->scn = channel; if(uuid) memcpy(rs->service_uuid, uuid, sizeof(rs->service_uuid)); else memset(rs->service_uuid, 0, sizeof(rs->service_uuid)); if(name && *name) strncpy(rs->service_name, name, sizeof(rs->service_name) -1); if(addr) rs->addr = *addr; ++rfc_slot_id; if(rfc_slot_id == 0) rfc_slot_id = 1; //skip 0 when wrapped rs->id = rfc_slot_id; rs->f.server = server; } return rs; }
static void jv_dm_cback(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data) { uint32_t id = (uint32_t)user_data; APPL_TRACE_DEBUG2("jv_dm_cback: event:%d, slot id:%d", event, id); switch(event) { case BTA_JV_CREATE_RECORD_EVT: { lock_slot(&slot_lock); rfc_slot_t* rs = find_rfc_slot_by_id(id); if(rs && create_server_sdp_record(rs)) { //now start the rfcomm server after sdp & channel # assigned BTA_JvRfcommStartServer(rs->security, rs->role, rs->scn, MAX_RFC_SESSION, rfcomm_cback, (void*)rs->id); } else if(rs) { APPL_TRACE_ERROR1("jv_dm_cback: cannot start server, slot found:%p", rs); cleanup_rfc_slot(rs); } unlock_slot(&slot_lock); break; } case BTA_JV_DISCOVERY_COMP_EVT: { rfc_slot_t* rs = NULL; lock_slot(&slot_lock); if(p_data->disc_comp.status == BTA_JV_SUCCESS && p_data->disc_comp.scn) { APPL_TRACE_DEBUG3("BTA_JV_DISCOVERY_COMP_EVT, slot id:%d, status:%d, scn:%d", id, p_data->disc_comp.status, p_data->disc_comp.scn); rs = find_rfc_slot_by_id(id); if(rs && rs->f.doing_sdp_request) { if(BTA_JvRfcommConnect(rs->security, rs->role, p_data->disc_comp.scn, rs->addr.address, rfcomm_cback, (void*)rs->id) == BTA_JV_SUCCESS) { rs->scn = p_data->disc_comp.scn; rs->f.doing_sdp_request = FALSE; if(!send_app_scn(rs)) cleanup_rfc_slot(rs); } else cleanup_rfc_slot(rs); } else if(rs) { APPL_TRACE_ERROR3("DISCOVERY_COMP_EVT no pending sdp request, slot id:%d, \ flag sdp pending:%d, flag sdp doing:%d", id, rs->f.pending_sdp_request, rs->f.doing_sdp_request); } } else { APPL_TRACE_ERROR3("DISCOVERY_COMP_EVT slot id:%d, failed to find channle, \ status:%d, scn:%d", id, p_data->disc_comp.status, p_data->disc_comp.scn); rs = find_rfc_slot_by_id(id); if(rs) cleanup_rfc_slot(rs); } rs = find_rfc_slot_by_pending_sdp(); if(rs) { APPL_TRACE_DEBUG0("BTA_JV_DISCOVERY_COMP_EVT, start another pending scn sdp request"); tSDP_UUID sdp_uuid; sdp_uuid.len = 16; memcpy(sdp_uuid.uu.uuid128, rs->service_uuid, sizeof(sdp_uuid.uu.uuid128)); BTA_JvStartDiscovery((UINT8*)rs->addr.address, 1, &sdp_uuid, (void*)rs->id); rs->f.pending_sdp_request = FALSE; rs->f.doing_sdp_request = TRUE; } unlock_slot(&slot_lock); break; }