Send AT+COPS=3,0 at the end of the SLC creation to set the format of the operator selection to long alphanumeric, then query the currently selected operator name from the AG. Register +COPS handler to call the update_operator callback on event. --- src/shared/hfp.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++-- src/shared/hfp.h | 1 + 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/src/shared/hfp.c b/src/shared/hfp.c index d01915ab1..f94df90f1 100644 --- a/src/shared/hfp.c +++ b/src/shared/hfp.c @@ -1710,7 +1710,30 @@ static void ciev_cb(struct hfp_context *context, void *user_data) set_indicator_value(index, val, hfp->ag_ind, hfp); } -static void slc_cmer_resp(enum hfp_result result, enum hfp_error cme_err, +static void cops_cb(struct hfp_context *context, void *user_data) +{ + struct hfp_hf *hfp = user_data; + unsigned int mode, val; + char name[255]; + + DBG(hfp, ""); + + if (!hfp_context_get_number(context, &mode)) + return; + + if (!hfp_context_get_number(context, &val)) + return; + + if (!hfp_context_get_string(context, name, sizeof(name))) { + DBG(hfp, "hf: Could not get string"); + return; + } + + if (hfp->callbacks && hfp->callbacks->update_operator) + hfp->callbacks->update_operator(name, hfp->callbacks_data); +} + +static void cops_resp(enum hfp_result result, enum hfp_error cme_err, void *user_data) { struct hfp_hf *hfp = user_data; @@ -1718,7 +1741,7 @@ static void slc_cmer_resp(enum hfp_result result, enum hfp_error cme_err, DBG(hfp, ""); if (result != HFP_RESULT_OK) { - DBG(hfp, "hf: CMER error: %d", result); + DBG(hfp, "hf: COPS? error: %d", result); goto failed; } @@ -1726,8 +1749,65 @@ static void slc_cmer_resp(enum hfp_result result, enum hfp_error cme_err, hfp->callbacks->session_ready(HFP_RESULT_OK, 0, hfp->callbacks_data); + return; + +failed: + if (hfp->callbacks->session_ready) + hfp->callbacks->session_ready(result, cme_err, + hfp->callbacks_data); +} + +static void cops_conf_resp(enum hfp_result result, enum hfp_error cme_err, + void *user_data) +{ + struct hfp_hf *hfp = user_data; + + DBG(hfp, ""); + + if (result != HFP_RESULT_OK) { + DBG(hfp, "hf: COPS= error: %d", result); + goto failed; + } + + /* SLC creation done, continue with default setup */ + if (!hfp_hf_send_command(hfp, cops_resp, hfp, + "AT+COPS?")) { + DBG(hfp, "hf: Could not send AT+COPS?"); + result = HFP_RESULT_ERROR; + goto failed; + } + + return; + +failed: + if (hfp->callbacks->session_ready) + hfp->callbacks->session_ready(result, cme_err, + hfp->callbacks_data); +} + +static void slc_cmer_resp(enum hfp_result result, enum hfp_error cme_err, + void *user_data) +{ + struct hfp_hf *hfp = user_data; + + DBG(hfp, ""); + + if (result != HFP_RESULT_OK) { + DBG(hfp, "hf: CMER error: %d", result); + goto failed; + } + + /* SLC creation done, continue with default setup */ + if (!hfp_hf_send_command(hfp, cops_conf_resp, hfp, + "AT+COPS=3,0")) { + DBG(hfp, "hf: Could not send AT+COPS=3,0"); + result = HFP_RESULT_ERROR; + goto failed; + } + /* Register unsolicited results handlers */ hfp_hf_register(hfp, ciev_cb, "+CIEV", hfp, NULL); + hfp_hf_register(hfp, cops_cb, "+COPS", hfp, NULL); return; diff --git a/src/shared/hfp.h b/src/shared/hfp.h index e6f7bbbb6..27f6d2d7c 100644 --- a/src/shared/hfp.h +++ b/src/shared/hfp.h @@ -190,6 +190,7 @@ struct hfp_hf_callbacks { void *user_data); void (*update_indicator)(enum hfp_indicator indicator, uint32_t val, void *user_data); + void (*update_operator)(const char *operator_name, void *user_data); }; struct hfp_hf *hfp_hf_new(int fd); -- 2.43.0