/****************************************************************************** ** ** 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_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_rfc_close ** ** Description RFCOMM connection closed. ** ** ** Returns void ** *******************************************************************************/ void bta_hf_client_rfc_close(tBTA_HF_CLIENT_DATA *p_data) { UNUSED(p_data); /* reinitialize stuff */ bta_hf_client_cb.scb.peer_features = 0; bta_hf_client_cb.scb.chld_features = 0; bta_hf_client_cb.scb.role = BTA_HF_CLIENT_ACP; bta_hf_client_cb.scb.svc_conn = FALSE; bta_hf_client_cb.scb.send_at_reply = FALSE; bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD; bta_hf_client_at_reset(); bta_sys_conn_close(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); /* call close cback */ (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CLOSE_EVT, NULL); /* if not deregistering reopen server */ if (bta_hf_client_cb.scb.deregister == FALSE) { /* Clear peer bd_addr so instance can be reused */ bdcpy(bta_hf_client_cb.scb.peer_addr, bd_addr_null); /* start server as it might got closed on open*/ bta_hf_client_start_server(); bta_hf_client_cb.scb.conn_handle = 0; /* Make sure SCO is shutdown */ bta_hf_client_sco_shutdown(NULL); bta_sys_sco_unuse(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); } /* else close port and deallocate scb */ else { bta_hf_client_close_server(); bta_hf_client_scb_disable(); } }
/******************************************************************************* ** ** Function bta_hf_client_rfc_fail ** ** Description RFCOMM connection failed. ** ** ** Returns void ** *******************************************************************************/ void bta_hf_client_rfc_fail(tBTA_HF_CLIENT_DATA *p_data) { UNUSED(p_data); /* reinitialize stuff */ bta_hf_client_cb.scb.conn_handle = 0; bta_hf_client_cb.scb.peer_features = 0; bta_hf_client_cb.scb.chld_features = 0; bta_hf_client_cb.scb.role = BTA_HF_CLIENT_ACP; bta_hf_client_cb.scb.svc_conn = FALSE; bta_hf_client_cb.scb.send_at_reply = FALSE; bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD; bta_hf_client_at_reset(); /* reopen server */ bta_hf_client_start_server(); /* call open cback w. failure */ bta_hf_client_cback_open(NULL, BTA_HF_CLIENT_FAIL_RFCOMM); }
void bta_hf_client_at_init(void) { memset(&bta_hf_client_cb.scb.at_cb, 0, sizeof(tBTA_HF_CLIENT_AT_CB)); bta_hf_client_at_reset(); }