/****************************************************************************** ** ** MAIN PARSING FUNCTION ** ** *******************************************************************************/ void bta_hf_client_at_parse(char *buf, unsigned int len) { APPL_TRACE_DEBUG("%s offset: %u len: %u", __FUNCTION__, bta_hf_client_cb.scb.at_cb.offset, len); if (len + bta_hf_client_cb.scb.at_cb.offset > BTA_HF_CLIENT_AT_PARSER_MAX_LEN) { unsigned int tmp = bta_hf_client_cb.scb.at_cb.offset; unsigned int space_left = BTA_HF_CLIENT_AT_PARSER_MAX_LEN - bta_hf_client_cb.scb.at_cb.offset; char *tmp_buff = osi_malloc(BTA_HF_CLIENT_AT_PARSER_MAX_LEN); if (tmp_buff == NULL) { APPL_TRACE_ERROR("No mem %s", __FUNCTION__); return; } APPL_TRACE_DEBUG("%s overrun, trying to recover", __FUNCTION__); /* fill up parser buffer */ memcpy(bta_hf_client_cb.scb.at_cb.buf + bta_hf_client_cb.scb.at_cb.offset, buf, space_left); len -= space_left; buf += space_left; bta_hf_client_cb.scb.at_cb.offset += space_left; /* find end of last complete command before proceeding */ while (bta_hf_client_check_at_complete() == FALSE) { if (bta_hf_client_cb.scb.at_cb.offset == 0) { APPL_TRACE_ERROR("HFPClient: AT parser buffer overrun, disconnecting"); bta_hf_client_at_reset(); bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL); osi_free(tmp_buff); return; } bta_hf_client_cb.scb.at_cb.offset--; } /* cut buffer to complete AT event and keep cut data */ tmp += space_left - bta_hf_client_cb.scb.at_cb.offset; memcpy(tmp_buff, bta_hf_client_cb.scb.at_cb.buf + bta_hf_client_cb.scb.at_cb.offset, tmp); bta_hf_client_cb.scb.at_cb.buf[bta_hf_client_cb.scb.at_cb.offset] = '\0'; /* parse */ bta_hf_client_at_parse_start(); bta_hf_client_at_clear_buf(); /* recover cut data */ memcpy(bta_hf_client_cb.scb.at_cb.buf, tmp_buff, tmp); bta_hf_client_cb.scb.at_cb.offset += tmp; osi_free(tmp_buff); } memcpy(bta_hf_client_cb.scb.at_cb.buf + bta_hf_client_cb.scb.at_cb.offset, buf, len); bta_hf_client_cb.scb.at_cb.offset += len; /* If last event is complete, parsing can be started */ if (bta_hf_client_check_at_complete() == TRUE) { bta_hf_client_at_parse_start(); bta_hf_client_at_clear_buf(); } }
static void bta_hf_client_at_resp_timer_cback (TIMER_LIST_ENT *p_tle) { if (p_tle) { bta_hf_client_cb.scb.at_cb.resp_timer_on = FALSE; APPL_TRACE_ERROR("HFPClient: AT response timeout, disconnecting"); bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL); } }
/******************************************************************************* ** ** Function bta_hf_client_do_disc ** ** Description Do service discovery. ** ** ** Returns void ** *******************************************************************************/ void bta_hf_client_do_disc(void) { tSDP_UUID uuid_list[2]; UINT16 num_uuid = 1; UINT16 attr_list[4]; UINT8 num_attr; BOOLEAN db_inited = FALSE; /* initiator; get proto list and features */ if (bta_hf_client_cb.scb.role == BTA_HF_CLIENT_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_AG_HANDSFREE; } /* acceptor; get features */ else { 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_AG_HANDSFREE; } /* allocate buffer for sdp database */ bta_hf_client_cb.scb.p_disc_db = (tSDP_DISCOVERY_DB *) osi_malloc(BT_DEFAULT_BUFFER_SIZE); if (bta_hf_client_cb.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(bta_hf_client_cb.scb.p_disc_db, BT_DEFAULT_BUFFER_SIZE, num_uuid, uuid_list, num_attr, attr_list); } if (db_inited) { /*Service discovery not initiated */ db_inited = SDP_ServiceSearchAttributeRequest(bta_hf_client_cb.scb.peer_addr, bta_hf_client_cb.scb.p_disc_db, bta_hf_client_sdp_cback); } if (!db_inited) { /*free discover db */ bta_hf_client_free_db(NULL); /* sent failed event */ bta_hf_client_sm_execute(BTA_HF_CLIENT_DISC_FAIL_EVT, NULL); } }
static void bta_hf_client_at_parse_start(void) { char *buf = bta_hf_client_cb.scb.at_cb.buf; APPL_TRACE_DEBUG("%s", __FUNCTION__); #ifdef BTA_HF_CLIENT_AT_DUMP bta_hf_client_dump_at(); #endif while(*buf != '\0') { int i; char *tmp = NULL; for(i = 0; i < bta_hf_client_psraser_cb_count; i++) { tmp = bta_hf_client_parser_cb[i](buf); if (tmp == NULL) { APPL_TRACE_ERROR("HFPCient: AT event/reply parsing failed, skipping"); tmp = bta_hf_client_skip_unknown(buf); break; } /* matched or unknown skipped, if unknown failed tmp is NULL so this is also handled */ if (tmp != buf) { buf = tmp; break; } } /* could not skip unknown (received garbage?)... disconnect */ if (tmp == NULL) { APPL_TRACE_ERROR("HFPCient: could not skip unknown AT event, disconnecting"); bta_hf_client_at_reset(); bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL); return; } buf = tmp; } }
/******************************************************************************* ** ** Function bta_hf_client_disc_int_res ** ** Description This function handles a discovery result when initiator. ** ** ** Returns void ** *******************************************************************************/ void bta_hf_client_disc_int_res(tBTA_HF_CLIENT_DATA *p_data) { UINT16 event = BTA_HF_CLIENT_DISC_FAIL_EVT; APPL_TRACE_DEBUG ("bta_hf_client_disc_int_res: Status: %d", p_data->disc_result.status); /* if found service */ if (p_data->disc_result.status == SDP_SUCCESS || p_data->disc_result.status == SDP_DB_FULL) { /* get attributes */ if (bta_hf_client_sdp_find_attr()) { event = BTA_HF_CLIENT_DISC_OK_EVT; } } /* free discovery db */ bta_hf_client_free_db(p_data); /* send ourselves sdp ok/fail event */ bta_hf_client_sm_execute(event, p_data); }