This needs to be in emulator as HFP plugin should answer AT+COPS requests
even when oFono is not registered on network.
---
src/emulator.c | 72 ++++++++++++++++++++++++++++++++++++++++++++
src/network.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 155 insertions(+), 7 deletions(-)
diff --git a/src/emulator.c b/src/emulator.c
index 864e50b..eb4f49e 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -49,6 +49,8 @@ struct ofono_emulator {
int events_mode;
gboolean events_ind;
GSList *indicators;
+ char op_name[17];
+ int net_mode;
};
struct indicator {
@@ -387,6 +389,59 @@ fail:
}
}
+static void cops_cb(GAtServer *server, GAtServerRequestType type,
+ GAtResult *result, gpointer user_data)
+{
+ struct ofono_emulator *em = user_data;
+ char buf[32];
+
+ if (em->type == OFONO_EMULATOR_TYPE_HFP && em->slc == FALSE) {
+ g_at_server_send_final(em->server, G_AT_SERVER_RESULT_ERROR);
+ return;
+ }
+
+ switch (type) {
+ case G_AT_SERVER_REQUEST_TYPE_QUERY:
+ sprintf(buf, "+COPS: %d,0,\"%s\"", em->net_mode,
em->op_name);
+ g_at_server_send_info(em->server, buf, TRUE);
+ g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
+ break;
+
+ case G_AT_SERVER_REQUEST_TYPE_SET:
+ {
+ GAtResultIter iter;
+ int val;
+
+ g_at_result_iter_init(&iter, result);
+ g_at_result_iter_next(&iter, "");
+
+ if (!g_at_result_iter_next_number(&iter, &val))
+ goto fail;
+
+ if (val != 3)
+ goto fail;
+
+ if (!g_at_result_iter_next_number(&iter, &val))
+ goto fail;
+
+ if (val != 0)
+ goto fail;
+
+ /* check there is no more parameter */
+ if (g_at_result_iter_skip_next(&iter))
+ goto fail;
+
+ g_at_server_send_final(server, G_AT_SERVER_RESULT_OK);
+ break;
+ }
+
+ default:
+fail:
+ g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
+ break;
+ }
+}
+
static void emulator_add_indicator(struct ofono_emulator *em, const char* name,
int min, int max, int dflt)
{
@@ -465,6 +520,7 @@ void ofono_emulator_register(struct ofono_emulator *em, int fd)
g_at_server_register(em->server, "+BRSF", brsf_cb, em, NULL);
g_at_server_register(em->server, "+CIND", cind_cb, em, NULL);
g_at_server_register(em->server, "+CMER", cmer_cb, em, NULL);
+ g_at_server_register(em->server, "+COPS", cops_cb, em, NULL);
}
__ofono_atom_register(em->atom, emulator_unregister);
@@ -508,6 +564,7 @@ struct ofono_emulator *ofono_emulator_create(struct ofono_modem
*modem,
/* TODO: Check real local features */
em->l_features = 32;
em->events_mode = 3; /* default mode is forwarding events */
+ em->op_name[0] = '\0';
em->atom = __ofono_modem_add_atom_offline(modem, atom_t,
emulator_remove, em);
@@ -703,3 +760,18 @@ void ofono_emulator_set_indicator(struct ofono_emulator *em,
return;
}
}
+
+void ofono_emulator_set_network_name(struct ofono_emulator *em,
+ const char *name)
+{
+ if (name == NULL)
+ return;
+
+ strncpy(em->op_name, name, 16);
+ em->op_name[16] = '\0';
+}
+
+void ofono_emulator_set_network_mode(struct ofono_emulator *em, int mode)
+{
+ em->net_mode = mode;
+}
diff --git a/src/network.c b/src/network.c
index 2d0a9f8..d529431 100644
--- a/src/network.c
+++ b/src/network.c
@@ -145,11 +145,19 @@ static char **network_operator_technologies(struct
network_operator_data *opd)
return techs;
}
+static void notify_emulator_mode(struct ofono_atom *atom, void *data)
+{
+ struct ofono_emulator *em = __ofono_atom_get_data(atom);
+
+ ofono_emulator_set_network_mode(em, GPOINTER_TO_INT(data));
+}
+
static void set_registration_mode(struct ofono_netreg *netreg, int mode)
{
DBusConnection *conn;
const char *strmode;
const char *path;
+ struct ofono_modem *modem;
if (netreg->mode == mode)
return;
@@ -170,6 +178,10 @@ static void set_registration_mode(struct ofono_netreg *netreg, int
mode)
ofono_dbus_signal_property_changed(conn, path,
OFONO_NETWORK_REGISTRATION_INTERFACE,
"Mode", DBUS_TYPE_STRING, &strmode);
+
+ modem = __ofono_atom_get_modem(netreg->atom);
+ __ofono_modem_foreach_atom(modem, OFONO_ATOM_TYPE_EMULATOR_HFP,
+ notify_emulator_mode, GINT_TO_POINTER(mode));
}
static void registration_status_callback(const struct ofono_error *error,
@@ -400,13 +412,20 @@ static char *get_operator_display_name(struct ofono_netreg *netreg)
return name;
}
+static void notify_emulator_operator_name(struct ofono_atom *atom, void *data)
+{
+ struct ofono_emulator *em = __ofono_atom_get_data(atom);
+
+ ofono_emulator_set_network_name(em, data);
+}
+
static void set_network_operator_name(struct network_operator_data *opd,
const char *name)
{
DBusConnection *conn = ofono_dbus_get_connection();
struct ofono_netreg *netreg = opd->netreg;
const char *path;
- const char *operator;
+ char *operator;
if (name[0] == '\0')
return;
@@ -426,6 +445,7 @@ static void set_network_operator_name(struct network_operator_data
*opd,
if (opd == netreg->current_operator) {
const char *path = __ofono_atom_get_path(netreg->atom);
+ struct ofono_modem *modem;
operator = get_operator_display_name(netreg);
@@ -433,6 +453,11 @@ static void set_network_operator_name(struct network_operator_data
*opd,
OFONO_NETWORK_REGISTRATION_INTERFACE,
"Name", DBUS_TYPE_STRING,
&operator);
+
+ modem = __ofono_atom_get_modem(netreg->atom);
+ __ofono_modem_foreach_atom(modem, OFONO_ATOM_TYPE_EMULATOR_HFP,
+ notify_emulator_operator_name,
+ operator);
}
/* Don't emit when only operator name is reported */
@@ -481,13 +506,19 @@ static void set_network_operator_eons_info(struct
network_operator_data *opd,
if (opd == netreg->current_operator) {
const char *npath = __ofono_atom_get_path(netreg->atom);
- const char *operator =
- get_operator_display_name(netreg);
+ char *operator = get_operator_display_name(netreg);
+ struct ofono_modem *modem;
ofono_dbus_signal_property_changed(conn, npath,
OFONO_NETWORK_REGISTRATION_INTERFACE,
"Name", DBUS_TYPE_STRING,
&operator);
+
+ modem = __ofono_atom_get_modem(netreg->atom);
+ __ofono_modem_foreach_atom(modem,
+ OFONO_ATOM_TYPE_EMULATOR_HFP,
+ notify_emulator_operator_name,
+ operator);
}
}
@@ -1178,7 +1209,8 @@ static void current_operator_callback(const struct ofono_error
*error,
struct ofono_netreg *netreg = data;
const char *path = __ofono_atom_get_path(netreg->atom);
GSList *op = NULL;
- const char *operator;
+ char *operator;
+ struct ofono_modem *modem;
DBG("%p, %p", netreg, netreg->current_operator);
@@ -1254,6 +1286,11 @@ emit:
"Name", DBUS_TYPE_STRING,
&operator);
+ modem = __ofono_atom_get_modem(netreg->atom);
+ __ofono_modem_foreach_atom(modem, OFONO_ATOM_TYPE_EMULATOR_HFP,
+ notify_emulator_operator_name,
+ operator);
+
if (netreg->current_operator) {
if (netreg->current_operator->mcc[0] != '\0') {
const char *mcc = netreg->current_operator->mcc;
@@ -1540,7 +1577,8 @@ static void sim_spdi_read_cb(int ok, int length, int record,
if (netreg->status == NETWORK_REGISTRATION_STATUS_ROAMING) {
DBusConnection *conn = ofono_dbus_get_connection();
const char *path = __ofono_atom_get_path(netreg->atom);
- const char *operator;
+ char *operator;
+ struct ofono_modem *modem;
if (!sim_spdi_lookup(netreg->spdi,
current->mcc, current->mnc))
@@ -1552,6 +1590,11 @@ static void sim_spdi_read_cb(int ok, int length, int record,
OFONO_NETWORK_REGISTRATION_INTERFACE,
"Name", DBUS_TYPE_STRING,
&operator);
+
+ modem = __ofono_atom_get_modem(netreg->atom);
+ __ofono_modem_foreach_atom(modem, OFONO_ATOM_TYPE_EMULATOR_HFP,
+ notify_emulator_operator_name,
+ operator);
}
}
@@ -1609,7 +1652,8 @@ static void sim_spn_read_cb(int ok, int length, int record,
if (netreg->current_operator) {
DBusConnection *conn = ofono_dbus_get_connection();
const char *path = __ofono_atom_get_path(netreg->atom);
- const char *operator;
+ char *operator;
+ struct ofono_modem *modem;
operator = get_operator_display_name(netreg);
@@ -1617,6 +1661,11 @@ static void sim_spn_read_cb(int ok, int length, int record,
OFONO_NETWORK_REGISTRATION_INTERFACE,
"Name", DBUS_TYPE_STRING,
&operator);
+
+ modem = __ofono_atom_get_modem(netreg->atom);
+ __ofono_modem_foreach_atom(modem, OFONO_ATOM_TYPE_EMULATOR_HFP,
+ notify_emulator_operator_name,
+ operator);
}
}
@@ -1704,9 +1753,16 @@ static void netreg_unregister(struct ofono_atom *atom)
__ofono_modem_foreach_atom(modem, OFONO_ATOM_TYPE_EMULATOR_HFP,
notify_emulator_status,
GINT_TO_POINTER(0));
+
__ofono_modem_foreach_atom(modem, OFONO_ATOM_TYPE_EMULATOR_HFP,
notify_emulator_strength, GINT_TO_POINTER(0));
+ __ofono_modem_foreach_atom(modem, OFONO_ATOM_TYPE_EMULATOR_HFP,
+ notify_emulator_mode, GINT_TO_POINTER(0));
+
+ __ofono_modem_foreach_atom(modem, OFONO_ATOM_TYPE_EMULATOR_HFP,
+ notify_emulator_operator_name, "");
+
__ofono_modem_remove_atom_watch(modem, netreg->hfp_watch);
__ofono_watchlist_free(netreg->status_watches);
@@ -1875,7 +1931,8 @@ static void sim_spn_spdi_changed(int id, void *userdata)
if (netreg->current_operator) {
DBusConnection *conn = ofono_dbus_get_connection();
const char *path = __ofono_atom_get_path(netreg->atom);
- const char *operator;
+ char *operator;
+ struct ofono_modem *modem;
operator = get_operator_display_name(netreg);
@@ -1883,6 +1940,11 @@ static void sim_spn_spdi_changed(int id, void *userdata)
OFONO_NETWORK_REGISTRATION_INTERFACE,
"Name", DBUS_TYPE_STRING,
&operator);
+
+ modem = __ofono_atom_get_modem(netreg->atom);
+ __ofono_modem_foreach_atom(modem, OFONO_ATOM_TYPE_EMULATOR_HFP,
+ notify_emulator_operator_name,
+ operator);
}
ofono_sim_read(netreg->sim_context, SIM_EFSPN_FILEID,
@@ -1901,9 +1963,23 @@ static void emulator_hfp_watch(struct ofono_atom *atom,
__ofono_modem_foreach_atom(modem, OFONO_ATOM_TYPE_EMULATOR_HFP,
notify_emulator_status,
GINT_TO_POINTER(netreg->status));
+
__ofono_modem_foreach_atom(modem, OFONO_ATOM_TYPE_EMULATOR_HFP,
notify_emulator_strength,
GINT_TO_POINTER(netreg->signal_strength));
+
+ __ofono_modem_foreach_atom(modem, OFONO_ATOM_TYPE_EMULATOR_HFP,
+ notify_emulator_mode,
+ GINT_TO_POINTER(netreg->mode));
+
+ if (netreg->current_operator) {
+ char *operator = get_operator_display_name(netreg);
+
+ __ofono_modem_foreach_atom(modem,
+ OFONO_ATOM_TYPE_EMULATOR_HFP,
+ notify_emulator_operator_name,
+ operator);
+ }
}
}
--
1.7.1